diff --git a/package-lock.json b/package-lock.json index 4da541e..65d1090 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "@opentelemetry/semantic-conventions": "^1.3.1", "dompurify": "^2.3.9", "express": "^4.17.2", - "hydrogen-view-sdk": "npm:@mlm/hydrogen-view-sdk@^0.0.13-scratch", + "hydrogen-view-sdk": "npm:@mlm/hydrogen-view-sdk@^0.0.14-scratch", "json5": "^2.2.1", "linkedom": "^0.14.1", "matrix-public-archive-shared": "file:./shared/", @@ -3636,9 +3636,9 @@ }, "node_modules/hydrogen-view-sdk": { "name": "@mlm/hydrogen-view-sdk", - "version": "0.0.13-scratch", - "resolved": "https://registry.npmjs.org/@mlm/hydrogen-view-sdk/-/hydrogen-view-sdk-0.0.13-scratch.tgz", - "integrity": "sha512-LAytm2lqVCvpFriizKQXjSJgOomx29ReD6w2sQhbHIfeP5DZ6wNxRybCBeBFrU1+2BiT7BTNmZp5Cwe8PGt14Q==", + "version": "0.0.14-scratch", + "resolved": "https://registry.npmjs.org/@mlm/hydrogen-view-sdk/-/hydrogen-view-sdk-0.0.14-scratch.tgz", + "integrity": "sha512-vH6OOOEZFeoyp25ub3fKtPWYOfN/BaY6qgxT+dpzi5zbbp7Il6eXNJgq1+Tbk5Uc5Z6E9hGlhwJ7sHwfSvvZ+A==", "dependencies": { "@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.8.tgz", "another-json": "^0.2.0", @@ -8070,9 +8070,9 @@ } }, "hydrogen-view-sdk": { - "version": "npm:@mlm/hydrogen-view-sdk@0.0.13-scratch", - "resolved": "https://registry.npmjs.org/@mlm/hydrogen-view-sdk/-/hydrogen-view-sdk-0.0.13-scratch.tgz", - "integrity": "sha512-LAytm2lqVCvpFriizKQXjSJgOomx29ReD6w2sQhbHIfeP5DZ6wNxRybCBeBFrU1+2BiT7BTNmZp5Cwe8PGt14Q==", + "version": "npm:@mlm/hydrogen-view-sdk@0.0.14-scratch", + "resolved": "https://registry.npmjs.org/@mlm/hydrogen-view-sdk/-/hydrogen-view-sdk-0.0.14-scratch.tgz", + "integrity": "sha512-vH6OOOEZFeoyp25ub3fKtPWYOfN/BaY6qgxT+dpzi5zbbp7Il6eXNJgq1+Tbk5Uc5Z6E9hGlhwJ7sHwfSvvZ+A==", "requires": { "@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.8.tgz", "another-json": "^0.2.0", diff --git a/package.json b/package.json index 3949e71..c0256e7 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "@opentelemetry/semantic-conventions": "^1.3.1", "dompurify": "^2.3.9", "express": "^4.17.2", - "hydrogen-view-sdk": "npm:@mlm/hydrogen-view-sdk@^0.0.13-scratch", + "hydrogen-view-sdk": "npm:@mlm/hydrogen-view-sdk@^0.0.14-scratch", "json5": "^2.2.1", "linkedom": "^0.14.1", "matrix-public-archive-shared": "file:./shared/", diff --git a/shared/4-hydrogen-vm-render-script.js b/shared/4-hydrogen-vm-render-script.js index ae188d0..95dc8cb 100644 --- a/shared/4-hydrogen-vm-render-script.js +++ b/shared/4-hydrogen-vm-render-script.js @@ -11,6 +11,7 @@ const { MediaRepository, createNavigation, createRouter, + tag, TilesCollection, FragmentIdComparer, @@ -20,15 +21,15 @@ const { encodeEventIdKey, Timeline, RoomViewModel, - ViewModel, - setupLightboxNavigation, } = require('hydrogen-view-sdk'); -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'); + +const ArchiveView = require('matrix-public-archive-shared/views/ArchiveView'); const ArchiveHistory = require('matrix-public-archive-shared/lib/archive-history'); +const ArchiveViewModel = require('matrix-public-archive-shared/viewmodels/ArchiveViewModel'); + const fromTimestamp = window.matrixPublicArchiveContext.fromTimestamp; assert(fromTimestamp); const roomData = window.matrixPublicArchiveContext.roomData; @@ -228,7 +229,8 @@ async function mountHydrogen() { const roomViewModel = new RoomViewModel({ room, - ownUserId: 'xxx', + // This is an arbitrary string (doesn't need to match anything and it shouldn't) + ownUserId: 'xxx-ownUserId', platform, urlCreator: urlRouter, navigation, @@ -243,112 +245,35 @@ async function mountHydrogen() { // FIXME: We shouldn't have to dive into the internal fields to make this work roomViewModel._timelineVM = timelineViewModel; + const fromDate = new Date(fromTimestamp); + const dateString = fromDate.toISOString().split('T')[0]; roomViewModel._composerVM = { - kind: 'none', + kind: 'disabled', + description: [ + `You're viewing an archive of events from ${dateString}. Use a `, + tag.a( + { + href: matrixPublicArchiveURLCreator.permalinkForRoomId(roomData.id), + rel: 'noopener', + target: '_blank', + }, + ['Matrix client'] + ), + ` to start chatting in this room.`, + ], }; - class CalendarViewModel extends ViewModel { - constructor(options) { - super(options); - const { activeDate, calendarDate } = options; - this._activeDate = activeDate; - this._calendarDate = calendarDate; - } - - get activeDate() { - return this._activeDate; - } - - get calendarDate() { - return this._calendarDate; - } - - archiveUrlForDate(date) { - return matrixPublicArchiveURLCreator.archiveUrlForDate(room.id, date); - } - - prevMonth() { - const prevMonthDate = new Date(this._calendarDate); - prevMonthDate.setUTCMonth(this._calendarDate.getUTCMonth() - 1); - this._calendarDate = prevMonthDate; - this.emitChange('calendarDate'); - } - - nextMonth() { - const nextMonthDate = new Date(this._calendarDate); - nextMonthDate.setUTCMonth(this._calendarDate.getUTCMonth() + 1); - console.log('nextMonthDate', nextMonthDate); - this._calendarDate = nextMonthDate; - this.emitChange('calendarDate'); - } - - onMonthInputChange(e) { - this._calendarDate = e.target.valueAsDate; - this.emitChange('calendarDate'); - } - - onYearFallbackSelectChange(e) { - const selectedDate = new Date(this._calendarDate); - selectedDate.setUTCFullYear(e.target.value); - this._calendarDate = selectedDate; - this.emitChange('calendarDate'); - } - } - - const fromDate = new Date(fromTimestamp); - class ArchiveViewModel extends ViewModel { - roomViewModel = roomViewModel; - rightPanelModel = { - navigation, - activeViewModel: { - type: 'custom', - customView: RightPanelContentView, - calendarViewModel: new CalendarViewModel({ - // The day being shown in the archive - activeDate: fromDate, - // The month displayed in the calendar - calendarDate: fromDate, - }), - }, - closePanel() { - const path = this.navigation.path.until('room'); - this.navigation.applyPath(path); - }, - }; - - get shouldShowRightPanel() { - return this._shouldShowRightPanel; - } - - constructor(options) { - super(options); - - this.#setupNavigation(); - this._updateRightPanel(); - } - - #setupNavigation() { - const rightpanel = this.navigation.observe('right-panel'); - this.track(rightpanel.subscribe(() => this._updateRightPanel())); - - setupLightboxNavigation(this, 'lightboxViewModel', (eventId) => { - return { - room, - eventEntry: eventEntriesByEventId[eventId], - }; - }); - } - - _updateRightPanel() { - this._shouldShowRightPanel = !!this.navigation.path.get('right-panel')?.value; - this.emitChange('shouldShowRightPanel'); - } - } - const archiveViewModel = new ArchiveViewModel({ + // Hydrogen options navigation: navigation, urlCreator: urlRouter, history: archiveHistory, + // Our options + roomViewModel, + room, + fromDate, + eventEntriesByEventId, + basePath: config.basePath, }); const view = new ArchiveView(archiveViewModel); diff --git a/shared/lib/url-creator.js b/shared/lib/url-creator.js index 21bd4dc..0044386 100644 --- a/shared/lib/url-creator.js +++ b/shared/lib/url-creator.js @@ -7,6 +7,10 @@ class URLCreator { this._basePath = basePath; } + permalinkForRoomId(roomId) { + return `https://matrix.to/#/${roomId}`; + } + archiveUrlForDate(roomId, date, { viaServers = [] } = {}) { let qs = new URLSearchParams(); [].concat(viaServers).forEach((viaServer) => { diff --git a/shared/viewmodels/ArchiveViewModel.js b/shared/viewmodels/ArchiveViewModel.js new file mode 100644 index 0000000..de157e8 --- /dev/null +++ b/shared/viewmodels/ArchiveViewModel.js @@ -0,0 +1,71 @@ +'use strict'; + +const { ViewModel, setupLightboxNavigation } = require('hydrogen-view-sdk'); + +const assert = require('matrix-public-archive-shared/lib/assert'); + +const CalendarViewModel = require('matrix-public-archive-shared/viewmodels/CalendarViewModel'); + +const RightPanelContentView = require('matrix-public-archive-shared/views/RightPanelContentView'); + +class ArchiveViewModel extends ViewModel { + constructor(options) { + super(options); + const { roomViewModel, room, fromDate, eventEntriesByEventId, basePath } = options; + assert(roomViewModel); + assert(room); + assert(fromDate); + assert(eventEntriesByEventId); + + this._room = room; + this._eventEntriesByEventId = eventEntriesByEventId; + + this.roomViewModel = roomViewModel; + // FIXME: Do we have to fake this? + this.rightPanelModel = { + navigation: this.navigation, + activeViewModel: { + type: 'custom', + customView: RightPanelContentView, + calendarViewModel: new CalendarViewModel({ + // The day being shown in the archive + activeDate: fromDate, + // The month displayed in the calendar + calendarDate: fromDate, + room, + basePath, + }), + }, + closePanel() { + const path = this.navigation.path.until('room'); + this.navigation.applyPath(path); + }, + }; + + this.#setupNavigation(); + this._updateRightPanel(); + } + + #setupNavigation() { + const rightpanel = this.navigation.observe('right-panel'); + this.track(rightpanel.subscribe(() => this._updateRightPanel())); + + setupLightboxNavigation(this, 'lightboxViewModel', (eventId) => { + return { + room: this._room, + eventEntry: this._eventEntriesByEventId[eventId], + }; + }); + } + + get shouldShowRightPanel() { + return this._shouldShowRightPanel; + } + + _updateRightPanel() { + this._shouldShowRightPanel = !!this.navigation.path.get('right-panel')?.value; + this.emitChange('shouldShowRightPanel'); + } +} + +module.exports = ArchiveViewModel; diff --git a/shared/viewmodels/CalendarViewModel.js b/shared/viewmodels/CalendarViewModel.js new file mode 100644 index 0000000..6cdb950 --- /dev/null +++ b/shared/viewmodels/CalendarViewModel.js @@ -0,0 +1,63 @@ +'use strict'; + +const { ViewModel } = require('hydrogen-view-sdk'); + +const assert = require('matrix-public-archive-shared/lib/assert'); +const MatrixPublicArchiveURLCreator = require('matrix-public-archive-shared/lib/url-creator'); + +class CalendarViewModel extends ViewModel { + constructor(options) { + super(options); + const { activeDate, calendarDate, room, basePath } = options; + assert(activeDate); + assert(calendarDate); + assert(room); + assert(basePath); + + this._activeDate = activeDate; + this._calendarDate = calendarDate; + this._room = room; + this._matrixPublicArchiveURLCreator = new MatrixPublicArchiveURLCreator(basePath); + } + + get activeDate() { + return this._activeDate; + } + + get calendarDate() { + return this._calendarDate; + } + + archiveUrlForDate(date) { + return this._matrixPublicArchiveURLCreator.archiveUrlForDate(this._room.id, date); + } + + prevMonth() { + const prevMonthDate = new Date(this._calendarDate); + prevMonthDate.setUTCMonth(this._calendarDate.getUTCMonth() - 1); + this._calendarDate = prevMonthDate; + this.emitChange('calendarDate'); + } + + nextMonth() { + const nextMonthDate = new Date(this._calendarDate); + nextMonthDate.setUTCMonth(this._calendarDate.getUTCMonth() + 1); + console.log('nextMonthDate', nextMonthDate); + this._calendarDate = nextMonthDate; + this.emitChange('calendarDate'); + } + + onMonthInputChange(e) { + this._calendarDate = e.target.valueAsDate; + this.emitChange('calendarDate'); + } + + onYearFallbackSelectChange(e) { + const selectedDate = new Date(this._calendarDate); + selectedDate.setUTCFullYear(e.target.value); + this._calendarDate = selectedDate; + this.emitChange('calendarDate'); + } +} + +module.exports = CalendarViewModel; diff --git a/shared/ArchiveView.js b/shared/views/ArchiveView.js similarity index 100% rename from shared/ArchiveView.js rename to shared/views/ArchiveView.js diff --git a/shared/CalendarView.js b/shared/views/CalendarView.js similarity index 100% rename from shared/CalendarView.js rename to shared/views/CalendarView.js diff --git a/shared/RightPanelContentView.js b/shared/views/RightPanelContentView.js similarity index 80% rename from shared/RightPanelContentView.js rename to shared/views/RightPanelContentView.js index b67c804..f9ee367 100644 --- a/shared/RightPanelContentView.js +++ b/shared/views/RightPanelContentView.js @@ -2,7 +2,7 @@ const { TemplateView } = require('hydrogen-view-sdk'); -const CalendarView = require('matrix-public-archive-shared/CalendarView'); +const CalendarView = require('matrix-public-archive-shared/views/CalendarView'); class RightPanelContentView extends TemplateView { render(t, vm) {