Move Hydrogen `timelineViewModel` creation to our main view model (#118)
Move Hydrogen `timelineViewModel` creation to our main view model.
Was it better to keep this Hydrogen boilerplate outside? Maybe 🤷. It's possible that all of this will go away with something like https://github.com/MadLittleMods/hydrogen-static-archives-prototype/pull/2
Should we also move the [`room` VM creation](8275f120a6/shared/hydrogen-vm-render-script.js (L88-L111)
)? Maybe but it's not as much noise as all of this tile/timeline stuff.
This commit is contained in:
parent
718f01e5a4
commit
dc7017ae4c
|
@ -14,22 +14,12 @@ const {
|
||||||
|
|
||||||
RetainedObservableValue,
|
RetainedObservableValue,
|
||||||
PowerLevels,
|
PowerLevels,
|
||||||
|
|
||||||
TilesCollection,
|
|
||||||
FragmentIdComparer,
|
|
||||||
EventEntry,
|
|
||||||
encodeKey,
|
|
||||||
encodeEventIdKey,
|
|
||||||
Timeline,
|
|
||||||
} = require('hydrogen-view-sdk');
|
} = require('hydrogen-view-sdk');
|
||||||
|
|
||||||
const ArchiveRoomView = require('matrix-public-archive-shared/views/ArchiveRoomView');
|
const ArchiveRoomView = require('matrix-public-archive-shared/views/ArchiveRoomView');
|
||||||
const ArchiveHistory = require('matrix-public-archive-shared/lib/archive-history');
|
const ArchiveHistory = require('matrix-public-archive-shared/lib/archive-history');
|
||||||
const supressBlankAnchorsReloadingThePage = require('matrix-public-archive-shared/lib/supress-blank-anchors-reloading-the-page');
|
const supressBlankAnchorsReloadingThePage = require('matrix-public-archive-shared/lib/supress-blank-anchors-reloading-the-page');
|
||||||
const ArchiveRoomViewModel = require('matrix-public-archive-shared/viewmodels/ArchiveRoomViewModel');
|
const ArchiveRoomViewModel = require('matrix-public-archive-shared/viewmodels/ArchiveRoomViewModel');
|
||||||
const {
|
|
||||||
customTileClassForEntry,
|
|
||||||
} = require('matrix-public-archive-shared/lib/custom-tile-utilities');
|
|
||||||
|
|
||||||
const fromTimestamp = window.matrixPublicArchiveContext.fromTimestamp;
|
const fromTimestamp = window.matrixPublicArchiveContext.fromTimestamp;
|
||||||
assert(fromTimestamp);
|
assert(fromTimestamp);
|
||||||
|
@ -48,12 +38,6 @@ assert(config);
|
||||||
assert(config.matrixServerUrl);
|
assert(config.matrixServerUrl);
|
||||||
assert(config.basePath);
|
assert(config.basePath);
|
||||||
|
|
||||||
let txnCount = 0;
|
|
||||||
function getFakeEventId() {
|
|
||||||
txnCount++;
|
|
||||||
return `fake-event-id-${new Date().getTime()}--${txnCount}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function addSupportClasses() {
|
function addSupportClasses() {
|
||||||
const input = document.createElement('input');
|
const input = document.createElement('input');
|
||||||
input.type = 'month';
|
input.type = 'month';
|
||||||
|
@ -63,31 +47,6 @@ function addSupportClasses() {
|
||||||
document.body.classList.toggle('fallback-input-month', !isMonthTypeSupported);
|
document.body.classList.toggle('fallback-input-month', !isMonthTypeSupported);
|
||||||
}
|
}
|
||||||
|
|
||||||
let eventIndexCounter = 0;
|
|
||||||
const fragmentIdComparer = new FragmentIdComparer([]);
|
|
||||||
function makeEventEntryFromEventJson(eventJson, memberEvent) {
|
|
||||||
assert(eventJson);
|
|
||||||
|
|
||||||
const eventIndex = eventIndexCounter;
|
|
||||||
const eventEntry = new EventEntry(
|
|
||||||
{
|
|
||||||
fragmentId: 0,
|
|
||||||
eventIndex: eventIndex, // TODO: What should this be?
|
|
||||||
roomId: roomData.id,
|
|
||||||
event: eventJson,
|
|
||||||
displayName: memberEvent && memberEvent.content && memberEvent.content.displayname,
|
|
||||||
avatarUrl: memberEvent && memberEvent.content && memberEvent.content.avatar_url,
|
|
||||||
key: encodeKey(roomData.id, 0, eventIndex),
|
|
||||||
eventIdKey: encodeEventIdKey(roomData.id, eventJson.event_id),
|
|
||||||
},
|
|
||||||
fragmentIdComparer
|
|
||||||
);
|
|
||||||
|
|
||||||
eventIndexCounter++;
|
|
||||||
|
|
||||||
return eventEntry;
|
|
||||||
}
|
|
||||||
|
|
||||||
supressBlankAnchorsReloadingThePage();
|
supressBlankAnchorsReloadingThePage();
|
||||||
|
|
||||||
// eslint-disable-next-line max-statements
|
// eslint-disable-next-line max-statements
|
||||||
|
@ -122,14 +81,6 @@ async function mountHydrogen() {
|
||||||
// page don't say `undefined`.
|
// page don't say `undefined`.
|
||||||
urlRouter.attach();
|
urlRouter.attach();
|
||||||
|
|
||||||
// We use the timeline to setup the relations between entries
|
|
||||||
const timeline = new Timeline({
|
|
||||||
roomId: roomData.id,
|
|
||||||
fragmentIdComparer: fragmentIdComparer,
|
|
||||||
clock: platform.clock,
|
|
||||||
logger: platform.logger,
|
|
||||||
});
|
|
||||||
|
|
||||||
const mediaRepository = new MediaRepository({
|
const mediaRepository = new MediaRepository({
|
||||||
homeserver: config.matrixServerUrl,
|
homeserver: config.matrixServerUrl,
|
||||||
});
|
});
|
||||||
|
@ -140,6 +91,7 @@ async function mountHydrogen() {
|
||||||
canonicalAlias: roomData.canonicalAlias,
|
canonicalAlias: roomData.canonicalAlias,
|
||||||
avatarUrl: roomData.avatarUrl,
|
avatarUrl: roomData.avatarUrl,
|
||||||
avatarColorId: roomData.id,
|
avatarColorId: roomData.id,
|
||||||
|
// Hydrogen options used by the event TilesCollection (roomVM)
|
||||||
mediaRepository: mediaRepository,
|
mediaRepository: mediaRepository,
|
||||||
// Based on https://github.com/vector-im/hydrogen-web/blob/5f9cfffa3b547991b665f57a8bf715270a1b2ef1/src/matrix/room/BaseRoom.js#L480
|
// Based on https://github.com/vector-im/hydrogen-web/blob/5f9cfffa3b547991b665f57a8bf715270a1b2ef1/src/matrix/room/BaseRoom.js#L480
|
||||||
observePowerLevels: async function () {
|
observePowerLevels: async function () {
|
||||||
|
@ -159,111 +111,20 @@ async function mountHydrogen() {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Something we can modify with new state updates as we see them
|
|
||||||
const workingStateEventMap = {
|
|
||||||
...stateEventMap,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add a summary item to the bottom of the timeline that explains if we found
|
|
||||||
// events on the day requested.
|
|
||||||
const hasEventsFromGivenDay = events[events.length - 1]?.origin_server_ts >= fromTimestamp;
|
|
||||||
let daySummaryKind;
|
|
||||||
if (events.length === 0) {
|
|
||||||
daySummaryKind = 'no-events-at-all';
|
|
||||||
} else if (hasEventsFromGivenDay) {
|
|
||||||
daySummaryKind = 'some-events-in-day';
|
|
||||||
} else if (!hasEventsFromGivenDay) {
|
|
||||||
daySummaryKind = 'no-events-in-day';
|
|
||||||
}
|
|
||||||
events.push({
|
|
||||||
event_id: getFakeEventId(),
|
|
||||||
type: 'org.matrix.archive.not_enough_events_from_day_summary',
|
|
||||||
room_id: roomData.id,
|
|
||||||
// Even though this isn't used for sort, just using the time where the event
|
|
||||||
// would logically be.
|
|
||||||
//
|
|
||||||
// -1 so we're not at 00:00:00 of the next day
|
|
||||||
origin_server_ts: toTimestamp - 1,
|
|
||||||
content: {
|
|
||||||
canonicalAlias: roomData.canonicalAlias,
|
|
||||||
daySummaryKind,
|
|
||||||
// The timestamp from the URL that was originally visited
|
|
||||||
dayTimestamp: fromTimestamp,
|
|
||||||
// The end of the range to use as a jumping off point to the next activity
|
|
||||||
rangeEndTimestamp: toTimestamp,
|
|
||||||
// This is a bit cheating but I don't know how else to pass this kind of
|
|
||||||
// info to the Tile viewmodel
|
|
||||||
basePath: config.basePath,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const eventEntries = events.map((event) => {
|
|
||||||
if (event.type === 'm.room.member') {
|
|
||||||
workingStateEventMap[event.state_key] = event;
|
|
||||||
}
|
|
||||||
|
|
||||||
const memberEvent = workingStateEventMap[event.user_id];
|
|
||||||
return makeEventEntryFromEventJson(event, memberEvent);
|
|
||||||
});
|
|
||||||
//console.log('eventEntries', eventEntries.length);
|
|
||||||
|
|
||||||
// Map of `event_id` to `EventEntry`
|
|
||||||
const eventEntriesByEventId = eventEntries.reduce((currentMap, eventEntry) => {
|
|
||||||
currentMap[eventEntry.id] = eventEntry;
|
|
||||||
return currentMap;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
// We have to use `timeline._setupEntries([])` because it sets
|
|
||||||
// `this._allEntries` in `Timeline` and we don't want to use `timeline.load()`
|
|
||||||
// to request remote things.
|
|
||||||
timeline._setupEntries([]);
|
|
||||||
// Make it safe to iterate a derived observable collection
|
|
||||||
timeline.entries.subscribe({ onAdd: () => null, onUpdate: () => null });
|
|
||||||
// We use the timeline to setup the relations between entries
|
|
||||||
timeline.addEntries(eventEntries);
|
|
||||||
|
|
||||||
//console.log('timeline.entries', timeline.entries.length, timeline.entries);
|
|
||||||
|
|
||||||
const tiles = new TilesCollection(timeline.entries, {
|
|
||||||
tileClassForEntry: customTileClassForEntry,
|
|
||||||
platform,
|
|
||||||
navigation,
|
|
||||||
urlCreator: urlRouter,
|
|
||||||
timeline,
|
|
||||||
roomVM: {
|
|
||||||
room,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
// Trigger `onSubscribeFirst` -> `tiles._populateTiles()` so it creates a tile
|
|
||||||
// for each entry to display. This way we can also call `tile.notifyVisible()`
|
|
||||||
// on each tile so that the tile creation doesn't happen later when the
|
|
||||||
// `TilesListView` is mounted and subscribes which is a bit out of our
|
|
||||||
// control.
|
|
||||||
tiles.subscribe({ onAdd: () => null, onUpdate: () => null });
|
|
||||||
|
|
||||||
// Make the lazy-load images appear
|
|
||||||
for (const tile of tiles) {
|
|
||||||
tile.notifyVisible();
|
|
||||||
}
|
|
||||||
|
|
||||||
const timelineViewModel = {
|
|
||||||
showJumpDown: false,
|
|
||||||
setVisibleTileRange: () => {},
|
|
||||||
tiles,
|
|
||||||
};
|
|
||||||
|
|
||||||
const archiveRoomViewModel = new ArchiveRoomViewModel({
|
const archiveRoomViewModel = new ArchiveRoomViewModel({
|
||||||
// Hydrogen options
|
// Hydrogen options
|
||||||
|
platform: platform,
|
||||||
navigation: navigation,
|
navigation: navigation,
|
||||||
urlCreator: urlRouter,
|
urlCreator: urlRouter,
|
||||||
history: archiveHistory,
|
history: archiveHistory,
|
||||||
// Our options
|
// Our options
|
||||||
homeserverUrl: config.matrixServerUrl,
|
homeserverUrl: config.matrixServerUrl,
|
||||||
timelineViewModel,
|
|
||||||
room,
|
room,
|
||||||
// The timestamp from the URL that was originally visited
|
// The timestamp from the URL that was originally visited
|
||||||
dayTimestamp: fromTimestamp,
|
dayTimestampFrom: fromTimestamp,
|
||||||
eventEntriesByEventId,
|
dayTimestampTo: toTimestamp,
|
||||||
|
events,
|
||||||
|
stateEventMap,
|
||||||
shouldIndex,
|
shouldIndex,
|
||||||
basePath: config.basePath,
|
basePath: config.basePath,
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,15 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const { ViewModel, setupLightboxNavigation } = require('hydrogen-view-sdk');
|
const {
|
||||||
|
ViewModel,
|
||||||
|
setupLightboxNavigation,
|
||||||
|
TilesCollection,
|
||||||
|
Timeline,
|
||||||
|
FragmentIdComparer,
|
||||||
|
EventEntry,
|
||||||
|
encodeKey,
|
||||||
|
encodeEventIdKey,
|
||||||
|
} = require('hydrogen-view-sdk');
|
||||||
|
|
||||||
const assert = require('matrix-public-archive-shared/lib/assert');
|
const assert = require('matrix-public-archive-shared/lib/assert');
|
||||||
|
|
||||||
|
@ -10,35 +19,83 @@ const CalendarViewModel = require('matrix-public-archive-shared/viewmodels/Calen
|
||||||
const DeveloperOptionsContentViewModel = require('matrix-public-archive-shared/viewmodels/DeveloperOptionsContentViewModel');
|
const DeveloperOptionsContentViewModel = require('matrix-public-archive-shared/viewmodels/DeveloperOptionsContentViewModel');
|
||||||
const RightPanelContentView = require('matrix-public-archive-shared/views/RightPanelContentView');
|
const RightPanelContentView = require('matrix-public-archive-shared/views/RightPanelContentView');
|
||||||
const AvatarViewModel = require('matrix-public-archive-shared/viewmodels/AvatarViewModel');
|
const AvatarViewModel = require('matrix-public-archive-shared/viewmodels/AvatarViewModel');
|
||||||
|
const {
|
||||||
|
customTileClassForEntry,
|
||||||
|
} = require('matrix-public-archive-shared/lib/custom-tile-utilities');
|
||||||
|
|
||||||
|
let txnCount = 0;
|
||||||
|
function getFakeEventId() {
|
||||||
|
txnCount++;
|
||||||
|
return `fake-event-id-${new Date().getTime()}--${txnCount}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
let eventIndexCounter = 0;
|
||||||
|
const fragmentIdComparer = new FragmentIdComparer([]);
|
||||||
|
function makeEventEntryFromEventJson(eventJson, memberEvent) {
|
||||||
|
assert(eventJson);
|
||||||
|
|
||||||
|
const roomId = eventJson.roomId;
|
||||||
|
const eventIndex = eventIndexCounter;
|
||||||
|
const eventEntry = new EventEntry(
|
||||||
|
{
|
||||||
|
fragmentId: 0,
|
||||||
|
eventIndex: eventIndex, // TODO: What should this be?
|
||||||
|
roomId,
|
||||||
|
event: eventJson,
|
||||||
|
displayName: memberEvent && memberEvent.content && memberEvent.content.displayname,
|
||||||
|
avatarUrl: memberEvent && memberEvent.content && memberEvent.content.avatar_url,
|
||||||
|
key: encodeKey(roomId, 0, eventIndex),
|
||||||
|
eventIdKey: encodeEventIdKey(roomId, eventJson.event_id),
|
||||||
|
},
|
||||||
|
fragmentIdComparer
|
||||||
|
);
|
||||||
|
|
||||||
|
eventIndexCounter++;
|
||||||
|
|
||||||
|
return eventEntry;
|
||||||
|
}
|
||||||
|
|
||||||
class ArchiveRoomViewModel extends ViewModel {
|
class ArchiveRoomViewModel extends ViewModel {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
super(options);
|
super(options);
|
||||||
const {
|
const {
|
||||||
homeserverUrl,
|
homeserverUrl,
|
||||||
timelineViewModel,
|
|
||||||
room,
|
room,
|
||||||
dayTimestamp,
|
dayTimestampFrom,
|
||||||
eventEntriesByEventId,
|
dayTimestampTo,
|
||||||
|
events,
|
||||||
|
stateEventMap,
|
||||||
shouldIndex,
|
shouldIndex,
|
||||||
basePath,
|
basePath,
|
||||||
} = options;
|
} = options;
|
||||||
assert(homeserverUrl);
|
assert(homeserverUrl);
|
||||||
assert(timelineViewModel);
|
|
||||||
assert(room);
|
assert(room);
|
||||||
assert(dayTimestamp);
|
assert(dayTimestampFrom);
|
||||||
|
assert(dayTimestampTo);
|
||||||
|
assert(events);
|
||||||
|
assert(stateEventMap);
|
||||||
assert(shouldIndex !== undefined);
|
assert(shouldIndex !== undefined);
|
||||||
assert(eventEntriesByEventId);
|
assert(events);
|
||||||
|
|
||||||
this._room = room;
|
this._room = room;
|
||||||
this._dayTimestamp = dayTimestamp;
|
this._dayTimestampFrom = dayTimestampFrom;
|
||||||
this._eventEntriesByEventId = eventEntriesByEventId;
|
this._dayTimestampTo = dayTimestampTo;
|
||||||
this._currentTopPositionEventEntry = null;
|
this._currentTopPositionEventEntry = null;
|
||||||
this._matrixPublicArchiveURLCreator = new MatrixPublicArchiveURLCreator(basePath);
|
this._matrixPublicArchiveURLCreator = new MatrixPublicArchiveURLCreator(basePath);
|
||||||
|
this._basePath = basePath;
|
||||||
|
|
||||||
const navigation = this.navigation;
|
const navigation = this.navigation;
|
||||||
const urlCreator = this.urlCreator;
|
const urlCreator = this.urlCreator;
|
||||||
|
|
||||||
|
// Setup events and tiles necessary to render
|
||||||
|
const eventsToDisplay = this._addJumpSummaryEvents(events);
|
||||||
|
const { eventEntriesByEventId, tiles } = this._createHydrogenTilesFromEvents({
|
||||||
|
room: this._room,
|
||||||
|
events: eventsToDisplay,
|
||||||
|
stateEventMap,
|
||||||
|
});
|
||||||
|
this._eventEntriesByEventId = eventEntriesByEventId;
|
||||||
|
|
||||||
this._roomAvatarViewModel = new AvatarViewModel({
|
this._roomAvatarViewModel = new AvatarViewModel({
|
||||||
homeserverUrlToPullMediaFrom: homeserverUrl,
|
homeserverUrlToPullMediaFrom: homeserverUrl,
|
||||||
avatarUrl: this._room.avatarUrl,
|
avatarUrl: this._room.avatarUrl,
|
||||||
|
@ -52,7 +109,7 @@ class ArchiveRoomViewModel extends ViewModel {
|
||||||
entityId: this._room.id,
|
entityId: this._room.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
const initialDate = new Date(dayTimestamp);
|
const initialDate = new Date(dayTimestampFrom);
|
||||||
this._calendarViewModel = new CalendarViewModel({
|
this._calendarViewModel = new CalendarViewModel({
|
||||||
// The day being shown in the archive
|
// The day being shown in the archive
|
||||||
activeDate: initialDate,
|
activeDate: initialDate,
|
||||||
|
@ -80,7 +137,12 @@ class ArchiveRoomViewModel extends ViewModel {
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
this._timelineViewModel = timelineViewModel;
|
this._timelineViewModel = {
|
||||||
|
showJumpDown: false,
|
||||||
|
setVisibleTileRange: () => {},
|
||||||
|
tiles,
|
||||||
|
};
|
||||||
|
|
||||||
// FIXME: Do we have to fake this?
|
// FIXME: Do we have to fake this?
|
||||||
this.rightPanelModel = {
|
this.rightPanelModel = {
|
||||||
navigation,
|
navigation,
|
||||||
|
@ -205,8 +267,8 @@ class ArchiveRoomViewModel extends ViewModel {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
get dayTimestamp() {
|
get dayTimestampFrom() {
|
||||||
return this._dayTimestamp;
|
return this._dayTimestampFrom;
|
||||||
}
|
}
|
||||||
|
|
||||||
get roomDirectoryUrl() {
|
get roomDirectoryUrl() {
|
||||||
|
@ -231,6 +293,118 @@ class ArchiveRoomViewModel extends ViewModel {
|
||||||
path = path.with(this.navigation.segment('change-dates', true));
|
path = path.with(this.navigation.segment('change-dates', true));
|
||||||
this.navigation.applyPath(path);
|
this.navigation.applyPath(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add the placeholder events which render the "Jump to previous/next activity" links
|
||||||
|
// in the timeline
|
||||||
|
_addJumpSummaryEvents(inputEventList) {
|
||||||
|
const events = [...inputEventList];
|
||||||
|
// Add a summary item to the bottom of the timeline that explains if we found
|
||||||
|
// events on the day requested.
|
||||||
|
const hasEventsFromGivenDay =
|
||||||
|
events[events.length - 1]?.origin_server_ts >= this._dayTimestampFrom;
|
||||||
|
let daySummaryKind;
|
||||||
|
if (events.length === 0) {
|
||||||
|
daySummaryKind = 'no-events-at-all';
|
||||||
|
} else if (hasEventsFromGivenDay) {
|
||||||
|
daySummaryKind = 'some-events-in-day';
|
||||||
|
} else if (!hasEventsFromGivenDay) {
|
||||||
|
daySummaryKind = 'no-events-in-day';
|
||||||
|
}
|
||||||
|
events.push({
|
||||||
|
event_id: getFakeEventId(),
|
||||||
|
type: 'org.matrix.archive.not_enough_events_from_day_summary',
|
||||||
|
room_id: this._room.id,
|
||||||
|
// Even though this isn't used for sort, just using the time where the event
|
||||||
|
// would logically be.
|
||||||
|
//
|
||||||
|
// -1 so we're not at 00:00:00 of the next day
|
||||||
|
origin_server_ts: this._dayTimestampTo - 1,
|
||||||
|
content: {
|
||||||
|
canonicalAlias: this._room.canonicalAlias,
|
||||||
|
daySummaryKind,
|
||||||
|
// The timestamp from the URL that was originally visited
|
||||||
|
dayTimestamp: this._dayTimestampFrom,
|
||||||
|
// The end of the range to use as a jumping off point to the next activity
|
||||||
|
rangeEndTimestamp: this._dayTimestampTo,
|
||||||
|
// This is a bit cheating but I don't know how else to pass this kind of
|
||||||
|
// info to the Tile viewmodel
|
||||||
|
basePath: this._basePath,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return events;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A bunch of Hydrogen boilerplate to convert the events JSON into some `tiles` we can
|
||||||
|
// use with the `TimelineView`
|
||||||
|
_createHydrogenTilesFromEvents({ room, events, stateEventMap }) {
|
||||||
|
// We use the timeline to setup the relations between entries
|
||||||
|
const timeline = new Timeline({
|
||||||
|
roomId: room.id,
|
||||||
|
fragmentIdComparer: fragmentIdComparer,
|
||||||
|
clock: this.platform.clock,
|
||||||
|
logger: this.platform.logger,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Something we can modify with new state updates as we see them
|
||||||
|
const workingStateEventMap = {
|
||||||
|
...stateEventMap,
|
||||||
|
};
|
||||||
|
|
||||||
|
const eventEntries = events.map((event) => {
|
||||||
|
if (event.type === 'm.room.member') {
|
||||||
|
workingStateEventMap[event.state_key] = event;
|
||||||
|
}
|
||||||
|
|
||||||
|
const memberEvent = workingStateEventMap[event.user_id];
|
||||||
|
return makeEventEntryFromEventJson(event, memberEvent);
|
||||||
|
});
|
||||||
|
//console.log('eventEntries', eventEntries.length);
|
||||||
|
|
||||||
|
// Map of `event_id` to `EventEntry`
|
||||||
|
const eventEntriesByEventId = eventEntries.reduce((currentMap, eventEntry) => {
|
||||||
|
currentMap[eventEntry.id] = eventEntry;
|
||||||
|
return currentMap;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
// We have to use `timeline._setupEntries([])` because it sets
|
||||||
|
// `this._allEntries` in `Timeline` and we don't want to use `timeline.load()`
|
||||||
|
// to request remote things.
|
||||||
|
timeline._setupEntries([]);
|
||||||
|
// Make it safe to iterate a derived observable collection
|
||||||
|
timeline.entries.subscribe({ onAdd: () => null, onUpdate: () => null });
|
||||||
|
// We use the timeline to setup the relations between entries
|
||||||
|
timeline.addEntries(eventEntries);
|
||||||
|
|
||||||
|
//console.log('timeline.entries', timeline.entries.length, timeline.entries);
|
||||||
|
|
||||||
|
const tiles = new TilesCollection(timeline.entries, {
|
||||||
|
tileClassForEntry: customTileClassForEntry,
|
||||||
|
platform: this.platform,
|
||||||
|
navigation: this.navigation,
|
||||||
|
urlCreator: this.urlCreator,
|
||||||
|
timeline,
|
||||||
|
roomVM: {
|
||||||
|
room,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// Trigger `onSubscribeFirst` -> `tiles._populateTiles()` so it creates a tile
|
||||||
|
// for each entry to display. This way we can also call `tile.notifyVisible()`
|
||||||
|
// on each tile so that the tile creation doesn't happen later when the
|
||||||
|
// `TilesListView` is mounted and subscribes which is a bit out of our
|
||||||
|
// control.
|
||||||
|
tiles.subscribe({ onAdd: () => null, onUpdate: () => null });
|
||||||
|
|
||||||
|
// Make the lazy-load images appear
|
||||||
|
for (const tile of tiles) {
|
||||||
|
tile.notifyVisible();
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
tiles,
|
||||||
|
eventEntriesByEventId,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = ArchiveRoomViewModel;
|
module.exports = ArchiveRoomViewModel;
|
||||||
|
|
|
@ -92,8 +92,8 @@ class DisabledComposerView extends TemplateView {
|
||||||
const activeDate = new Date(
|
const activeDate = new Date(
|
||||||
// If the date from our `archiveRoomViewModel` is available, use that
|
// If the date from our `archiveRoomViewModel` is available, use that
|
||||||
vm?.currentTopPositionEventEntry?.timestamp ||
|
vm?.currentTopPositionEventEntry?.timestamp ||
|
||||||
// Otherwise, use our initial `dayTimestamp`
|
// Otherwise, use our initial `dayTimestampFrom`
|
||||||
vm.dayTimestamp
|
vm.dayTimestampFrom
|
||||||
);
|
);
|
||||||
const dateString = activeDate.toISOString().split('T')[0];
|
const dateString = activeDate.toISOString().split('T')[0];
|
||||||
return t.span(`You're viewing an archive of events from ${dateString}. Use a `);
|
return t.span(`You're viewing an archive of events from ${dateString}. Use a `);
|
||||||
|
|
Loading…
Reference in New Issue