matrix-public-archive/shared/hydrogen-vm-render-script.js

308 lines
8.4 KiB
JavaScript
Raw Normal View History

'use strict';
const assert = require('matrix-public-archive-shared/lib/assert');
const {
2022-02-01 20:39:23 -07:00
Platform,
2022-02-01 22:45:09 -07:00
MediaRepository,
2022-02-16 18:58:32 -07:00
createNavigation,
createRouter,
2022-02-01 20:39:23 -07:00
TilesCollection,
2022-02-01 20:39:23 -07:00
FragmentIdComparer,
tileClassForEntry,
2022-02-01 20:39:23 -07:00
EventEntry,
encodeKey,
encodeEventIdKey,
Timeline,
2022-02-15 20:33:31 -07:00
// TimelineView,
// RoomView,
RoomViewModel,
2022-02-15 01:30:26 -07:00
ViewModel,
} = require('hydrogen-view-sdk');
2022-02-01 20:39:23 -07:00
2022-02-10 01:21:49 -07:00
const ArchiveView = require('matrix-public-archive-shared/ArchiveView');
const RightPanelContentView = require('matrix-public-archive-shared/RightPanelContentView');
const MatrixPublicArchiveURLCreator = require('matrix-public-archive-shared/lib/url-creator');
2022-02-10 01:21:49 -07:00
2022-02-16 22:08:18 -07:00
const fromTimestamp = window.matrixPublicArchiveContext.fromTimestamp;
assert(fromTimestamp);
const roomData = window.matrixPublicArchiveContext.roomData;
assert(roomData);
const events = window.matrixPublicArchiveContext.events;
assert(events);
const stateEventMap = window.matrixPublicArchiveContext.stateEventMap;
assert(stateEventMap);
const config = window.matrixPublicArchiveContext.config;
assert(config);
assert(config.matrixServerUrl);
2022-02-16 18:58:32 -07:00
assert(config.basePath);
const matrixPublicArchiveURLCreator = new MatrixPublicArchiveURLCreator(config.basePath);
function addSupportClasses() {
const input = document.createElement('input');
input.type = 'month';
const isMonthTypeSupported = input.type === 'month';
// Signal `<input type="month">` support to our CSS
document.body.classList.toggle('fallback-input-month', !isMonthTypeSupported);
}
let eventIndexCounter = 0;
2022-02-01 20:39:23 -07:00
const fragmentIdComparer = new FragmentIdComparer([]);
2022-02-07 18:55:11 -07:00
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
);
2022-02-01 20:39:23 -07:00
eventIndexCounter++;
2022-02-01 20:39:23 -07:00
return eventEntry;
}
2022-02-16 22:08:18 -07:00
// eslint-disable-next-line max-statements
2022-02-04 00:54:12 -07:00
async function mountHydrogen() {
const app = document.querySelector('#app');
const platformConfig = {};
2022-02-01 20:39:23 -07:00
const assetPaths = {};
const platform = new Platform({
container: app,
assetPaths,
config: platformConfig,
options: { development: true },
});
2022-02-01 20:39:23 -07:00
2022-02-16 18:58:32 -07:00
const navigation = createNavigation();
platform.setNavigation(navigation);
const urlRouter = createRouter({
navigation: navigation,
history: platform.history,
});
// We use the timeline to setup the relations between entries
const timeline = new Timeline({
roomId: roomData.id,
//storage: this._storage,
fragmentIdComparer: fragmentIdComparer,
clock: platform.clock,
logger: platform.logger,
//hsApi: this._hsApi
});
const mediaRepository = new MediaRepository({
homeserver: config.matrixServerUrl,
});
2022-02-16 22:08:18 -07:00
// const urlRouter = {
2022-02-16 18:58:32 -07:00
// urlUntilSegment: () => {
// return 'todo';
// },
2022-02-16 22:08:18 -07:00
// urlForSegments: (segments) => {
// const isLightBox = segments.find((segment) => {
// return segment.type === 'lightbox';
// console.log('segment', segment);
// });
// if (isLightBox) {
// return '#';
// }
2022-02-16 18:58:32 -07:00
// return 'todo';
// },
// };
2022-02-16 18:58:32 -07:00
// const navigation = {
2022-02-16 22:08:18 -07:00
// segment: (type, value) => {
// return new Segment(type, value);
2022-02-16 18:58:32 -07:00
// },
// };
2022-02-16 22:08:18 -07:00
const lightbox = navigation.observe('lightbox');
lightbox.subscribe((eventId) => {
this._updateLightbox(eventId);
});
const room = {
name: roomData.name,
id: roomData.id,
avatarUrl: roomData.avatarUrl,
avatarColorId: roomData.id,
mediaRepository: mediaRepository,
};
// Something we can modify with new state updates as we see them
const workingStateEventMap = {
...stateEventMap,
};
2022-02-07 18:55:11 -07:00
const eventEntries = events.map((event) => {
if (event.type === 'm.room.member') {
workingStateEventMap[event.state_key] = event;
}
const memberEvent = workingStateEventMap[event.user_id];
2022-02-07 18:55:11 -07:00
return makeEventEntryFromEventJson(event, memberEvent);
2022-02-01 20:39:23 -07:00
});
//console.log('eventEntries', eventEntries);
console.log('eventEntries', eventEntries.length);
2022-02-01 21:32:59 -07:00
// 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,
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 });
2022-02-01 21:32:59 -07:00
2022-02-01 22:45:09 -07:00
// Make the lazy-load images appear
for (const tile of tiles) {
2022-02-01 22:45:09 -07:00
tile.notifyVisible();
}
2022-02-01 20:39:23 -07:00
const timelineViewModel = {
showJumpDown: false,
setVisibleTileRange: () => {},
tiles,
2022-02-01 20:39:23 -07:00
};
// const view = new TimelineView(timelineViewModel);
// const roomViewModel = {
// kind: 'room',
// timelineViewModel,
// composerViewModel: {
// kind: 'none',
// },
// i18n: RoomViewModel.prototype.i18n,
// id: roomData.id,
// name: roomData.name,
// avatarUrl(size) {
// return getAvatarHttpUrl(roomData.avatarUrl, size, platform, mediaRepository);
// },
// };
const roomViewModel = new RoomViewModel({
room,
ownUserId: 'xxx',
platform,
2022-02-16 18:58:32 -07:00
urlCreator: urlRouter,
navigation,
});
roomViewModel._timelineVM = timelineViewModel;
roomViewModel._composerVM = {
kind: 'none',
};
2022-02-15 01:30:26 -07:00
class CalendarViewModel extends ViewModel {
constructor(options) {
super(options);
2022-02-16 22:08:18 -07:00
const { activeDate, calendarDate } = options;
this._activeDate = activeDate;
this._calendarDate = calendarDate;
}
get activeDate() {
return this._activeDate;
2022-02-15 01:30:26 -07:00
}
2022-02-16 22:08:18 -07:00
get calendarDate() {
return this._calendarDate;
2022-02-15 01:30:26 -07:00
}
archiveUrlForDate(date) {
return matrixPublicArchiveURLCreator.archiveUrlForDate(room.id, date);
2022-02-16 18:58:32 -07:00
}
2022-02-15 01:30:26 -07:00
prevMonth() {
2022-02-16 22:08:18 -07:00
const prevMonthDate = new Date(this._calendarDate);
prevMonthDate.setUTCMonth(this._calendarDate.getUTCMonth() - 1);
2022-02-16 22:08:18 -07:00
this._calendarDate = prevMonthDate;
this.emitChange('calendarDate');
2022-02-15 01:30:26 -07:00
}
nextMonth() {
2022-02-16 22:08:18 -07:00
const nextMonthDate = new Date(this._calendarDate);
nextMonthDate.setUTCMonth(this._calendarDate.getUTCMonth() + 1);
console.log('nextMonthDate', nextMonthDate);
2022-02-16 22:08:18 -07:00
this._calendarDate = nextMonthDate;
this.emitChange('calendarDate');
}
onMonthInputChange(e) {
2022-02-17 20:10:36 -07:00
this._calendarDate = e.target.valueAsDate;
this.emitChange('calendarDate');
}
onYearFallbackSelectChange(e) {
2022-02-17 20:10:36 -07:00
const selectedDate = new Date(this._calendarDate);
selectedDate.setUTCFullYear(e.target.value);
this._calendarDate = selectedDate;
this.emitChange('calendarDate');
2022-02-15 01:30:26 -07:00
}
}
2022-02-16 22:08:18 -07:00
const fromDate = new Date(fromTimestamp);
2022-02-10 01:21:49 -07:00
const archiveViewModel = {
roomViewModel,
rightPanelModel: {
activeViewModel: {
type: 'custom',
customView: RightPanelContentView,
2022-02-16 22:08:18 -07:00
calendarViewModel: new CalendarViewModel({
// The day being shown in the archive
activeDate: fromDate,
// The month displayed in the calendar
calendarDate: fromDate,
}),
2022-02-10 01:21:49 -07:00
},
},
};
const view = new ArchiveView(archiveViewModel);
2022-02-01 20:39:23 -07:00
//console.log('view.mount()', view.mount());
app.replaceChildren(view.mount());
addSupportClasses();
2022-02-01 20:39:23 -07:00
}
// N.B.: When we run this in a `vm`, it will return the last statement. It's
// important to leave this as the last statement so we can await the promise it
// returns and signal that all of the async tasks completed.
2022-02-04 00:54:12 -07:00
mountHydrogen();