Refactor to use `TimelineView` (#117)
We have to figure out our own layout but does get rid of some of the `RoomView` boilerplate. The `TimelineView` still has outside boilerplate styles to work. There shouldn't be any visible change.
This commit is contained in:
parent
b75b807865
commit
718f01e5a4
|
@ -55,6 +55,15 @@ summary {
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ArchiveRoomView_mainArea {
|
||||||
|
grid-area: middle;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
min-height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.RoomHeader_actionButton {
|
.RoomHeader_actionButton {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
@ -75,6 +84,19 @@ summary {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ArchiveRoomView_mainBody {
|
||||||
|
flex: 1 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
min-height: 0;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ArchiveRoomView_mainBody > .Timeline {
|
||||||
|
flex: 1 0;
|
||||||
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 800px) {
|
@media screen and (max-width: 800px) {
|
||||||
/* Only the middle needs to be visible mobile by default */
|
/* Only the middle needs to be visible mobile by default */
|
||||||
.ArchiveRoomView {
|
.ArchiveRoomView {
|
||||||
|
@ -95,7 +117,7 @@ summary {
|
||||||
'right' 1fr /
|
'right' 1fr /
|
||||||
1fr;
|
1fr;
|
||||||
}
|
}
|
||||||
.ArchiveRoomView.right-shown .middle {
|
.ArchiveRoomView.right-shown .ArchiveRoomView_mainArea {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
/* And show the button to open the right-panel on mobile */
|
/* And show the button to open the right-panel on mobile */
|
||||||
|
|
|
@ -11,7 +11,6 @@ const {
|
||||||
MediaRepository,
|
MediaRepository,
|
||||||
createNavigation,
|
createNavigation,
|
||||||
createRouter,
|
createRouter,
|
||||||
tag,
|
|
||||||
|
|
||||||
RetainedObservableValue,
|
RetainedObservableValue,
|
||||||
PowerLevels,
|
PowerLevels,
|
||||||
|
@ -22,11 +21,8 @@ const {
|
||||||
encodeKey,
|
encodeKey,
|
||||||
encodeEventIdKey,
|
encodeEventIdKey,
|
||||||
Timeline,
|
Timeline,
|
||||||
ViewModel,
|
|
||||||
RoomViewModel,
|
|
||||||
} = require('hydrogen-view-sdk');
|
} = require('hydrogen-view-sdk');
|
||||||
|
|
||||||
const MatrixPublicArchiveURLCreator = require('matrix-public-archive-shared/lib/url-creator');
|
|
||||||
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');
|
||||||
|
@ -52,8 +48,6 @@ assert(config);
|
||||||
assert(config.matrixServerUrl);
|
assert(config.matrixServerUrl);
|
||||||
assert(config.basePath);
|
assert(config.basePath);
|
||||||
|
|
||||||
const matrixPublicArchiveURLCreator = new MatrixPublicArchiveURLCreator(config.basePath);
|
|
||||||
|
|
||||||
let txnCount = 0;
|
let txnCount = 0;
|
||||||
function getFakeEventId() {
|
function getFakeEventId() {
|
||||||
txnCount++;
|
txnCount++;
|
||||||
|
@ -258,93 +252,22 @@ async function mountHydrogen() {
|
||||||
tiles,
|
tiles,
|
||||||
};
|
};
|
||||||
|
|
||||||
const roomViewModel = new RoomViewModel({
|
|
||||||
room,
|
|
||||||
// This is an arbitrary string (doesn't need to match anything and it shouldn't)
|
|
||||||
ownUserId: 'xxx-ownUserId',
|
|
||||||
platform,
|
|
||||||
urlCreator: urlRouter,
|
|
||||||
navigation,
|
|
||||||
});
|
|
||||||
|
|
||||||
roomViewModel.openRightPanel = function () {
|
|
||||||
let path = this.navigation.path.until('room');
|
|
||||||
path = path.with(this.navigation.segment('right-panel', true));
|
|
||||||
path = path.with(this.navigation.segment('change-dates', true));
|
|
||||||
this.navigation.applyPath(path);
|
|
||||||
};
|
|
||||||
|
|
||||||
roomViewModel.roomDirectoryUrl = matrixPublicArchiveURLCreator.roomDirectoryUrl();
|
|
||||||
|
|
||||||
Object.defineProperty(roomViewModel, 'timelineViewModel', {
|
|
||||||
get() {
|
|
||||||
return timelineViewModel;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const archiveRoomViewModel = new ArchiveRoomViewModel({
|
const archiveRoomViewModel = new ArchiveRoomViewModel({
|
||||||
// Hydrogen options
|
// Hydrogen options
|
||||||
navigation: navigation,
|
navigation: navigation,
|
||||||
urlCreator: urlRouter,
|
urlCreator: urlRouter,
|
||||||
history: archiveHistory,
|
history: archiveHistory,
|
||||||
// Our options
|
// Our options
|
||||||
roomViewModel,
|
homeserverUrl: config.matrixServerUrl,
|
||||||
|
timelineViewModel,
|
||||||
room,
|
room,
|
||||||
fromDate: new Date(fromTimestamp),
|
// The timestamp from the URL that was originally visited
|
||||||
|
dayTimestamp: fromTimestamp,
|
||||||
eventEntriesByEventId,
|
eventEntriesByEventId,
|
||||||
shouldIndex,
|
shouldIndex,
|
||||||
basePath: config.basePath,
|
basePath: config.basePath,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create a custom disabled composer view that shows our archive message.
|
|
||||||
class DisabledArchiveComposerViewModel extends ViewModel {
|
|
||||||
constructor(options) {
|
|
||||||
super(options);
|
|
||||||
|
|
||||||
// Whenever the `archiveRoomViewModel.currentTopPositionEventEntry`
|
|
||||||
// changes, re-render the composer view with the updated date.
|
|
||||||
archiveRoomViewModel.on('change', (changedProps) => {
|
|
||||||
if (changedProps === 'currentTopPositionEventEntry') {
|
|
||||||
this.emitChange();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
get kind() {
|
|
||||||
return 'disabled';
|
|
||||||
}
|
|
||||||
|
|
||||||
get description() {
|
|
||||||
return [
|
|
||||||
(/*vm*/) => {
|
|
||||||
const activeDate = new Date(
|
|
||||||
// If the date from our `archiveRoomViewModel` is available, use that
|
|
||||||
archiveRoomViewModel?.currentTopPositionEventEntry?.timestamp ||
|
|
||||||
// Otherwise, use our initial `fromTimestamp`
|
|
||||||
fromTimestamp
|
|
||||||
);
|
|
||||||
const dateString = activeDate.toISOString().split('T')[0];
|
|
||||||
return `You're viewing an archive of events from ${dateString}. Use a `;
|
|
||||||
},
|
|
||||||
tag.a(
|
|
||||||
{
|
|
||||||
href: matrixPublicArchiveURLCreator.permalinkForRoom(roomData.id),
|
|
||||||
rel: 'noopener',
|
|
||||||
target: '_blank',
|
|
||||||
},
|
|
||||||
['Matrix client']
|
|
||||||
),
|
|
||||||
` to start chatting in this room.`,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const disabledArchiveComposerViewModel = new DisabledArchiveComposerViewModel({});
|
|
||||||
Object.defineProperty(roomViewModel, 'composerViewModel', {
|
|
||||||
get() {
|
|
||||||
return disabledArchiveComposerViewModel;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -9,18 +9,29 @@ const MatrixPublicArchiveURLCreator = require('matrix-public-archive-shared/lib/
|
||||||
const CalendarViewModel = require('matrix-public-archive-shared/viewmodels/CalendarViewModel');
|
const CalendarViewModel = require('matrix-public-archive-shared/viewmodels/CalendarViewModel');
|
||||||
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');
|
||||||
|
|
||||||
class ArchiveRoomViewModel extends ViewModel {
|
class ArchiveRoomViewModel extends ViewModel {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
super(options);
|
super(options);
|
||||||
const { roomViewModel, room, fromDate, eventEntriesByEventId, shouldIndex, basePath } = options;
|
const {
|
||||||
assert(roomViewModel);
|
homeserverUrl,
|
||||||
|
timelineViewModel,
|
||||||
|
room,
|
||||||
|
dayTimestamp,
|
||||||
|
eventEntriesByEventId,
|
||||||
|
shouldIndex,
|
||||||
|
basePath,
|
||||||
|
} = options;
|
||||||
|
assert(homeserverUrl);
|
||||||
|
assert(timelineViewModel);
|
||||||
assert(room);
|
assert(room);
|
||||||
assert(fromDate);
|
assert(dayTimestamp);
|
||||||
assert(shouldIndex !== undefined);
|
assert(shouldIndex !== undefined);
|
||||||
assert(eventEntriesByEventId);
|
assert(eventEntriesByEventId);
|
||||||
|
|
||||||
this._room = room;
|
this._room = room;
|
||||||
|
this._dayTimestamp = dayTimestamp;
|
||||||
this._eventEntriesByEventId = eventEntriesByEventId;
|
this._eventEntriesByEventId = eventEntriesByEventId;
|
||||||
this._currentTopPositionEventEntry = null;
|
this._currentTopPositionEventEntry = null;
|
||||||
this._matrixPublicArchiveURLCreator = new MatrixPublicArchiveURLCreator(basePath);
|
this._matrixPublicArchiveURLCreator = new MatrixPublicArchiveURLCreator(basePath);
|
||||||
|
@ -28,11 +39,25 @@ class ArchiveRoomViewModel extends ViewModel {
|
||||||
const navigation = this.navigation;
|
const navigation = this.navigation;
|
||||||
const urlCreator = this.urlCreator;
|
const urlCreator = this.urlCreator;
|
||||||
|
|
||||||
|
this._roomAvatarViewModel = new AvatarViewModel({
|
||||||
|
homeserverUrlToPullMediaFrom: homeserverUrl,
|
||||||
|
avatarUrl: this._room.avatarUrl,
|
||||||
|
avatarTitle: this._room.name || this._room.canonicalAlias || this._room.id,
|
||||||
|
avatarLetterString:
|
||||||
|
this._room.name ||
|
||||||
|
// Strip the `#` off the alias
|
||||||
|
this._room.canonicalAlias?.[1] ||
|
||||||
|
// Strip the `!` off the room_id
|
||||||
|
this._room.id?.[1],
|
||||||
|
entityId: this._room.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
const initialDate = new Date(dayTimestamp);
|
||||||
this._calendarViewModel = new CalendarViewModel({
|
this._calendarViewModel = new CalendarViewModel({
|
||||||
// The day being shown in the archive
|
// The day being shown in the archive
|
||||||
activeDate: fromDate,
|
activeDate: initialDate,
|
||||||
// The month displayed in the calendar
|
// The month displayed in the calendar
|
||||||
calendarDate: fromDate,
|
calendarDate: initialDate,
|
||||||
room,
|
room,
|
||||||
basePath,
|
basePath,
|
||||||
});
|
});
|
||||||
|
@ -55,7 +80,7 @@ class ArchiveRoomViewModel extends ViewModel {
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
this.roomViewModel = roomViewModel;
|
this._timelineViewModel = timelineViewModel;
|
||||||
// FIXME: Do we have to fake this?
|
// FIXME: Do we have to fake this?
|
||||||
this.rightPanelModel = {
|
this.rightPanelModel = {
|
||||||
navigation,
|
navigation,
|
||||||
|
@ -136,6 +161,10 @@ class ArchiveRoomViewModel extends ViewModel {
|
||||||
handleLightBoxNavigationChange(initialLightBoxEventId);
|
handleLightBoxNavigationChange(initialLightBoxEventId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get timelineViewModel() {
|
||||||
|
return this._timelineViewModel;
|
||||||
|
}
|
||||||
|
|
||||||
setShouldShowDeveloperOptions(shouldShowDeveloperOptions) {
|
setShouldShowDeveloperOptions(shouldShowDeveloperOptions) {
|
||||||
this._developerOptionsModalViewModel.setOpen(shouldShowDeveloperOptions);
|
this._developerOptionsModalViewModel.setOpen(shouldShowDeveloperOptions);
|
||||||
}
|
}
|
||||||
|
@ -175,6 +204,33 @@ class ArchiveRoomViewModel extends ViewModel {
|
||||||
) + window.location.hash
|
) + window.location.hash
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get dayTimestamp() {
|
||||||
|
return this._dayTimestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
get roomDirectoryUrl() {
|
||||||
|
return this._matrixPublicArchiveURLCreator.roomDirectoryUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
get roomPermalink() {
|
||||||
|
return this._matrixPublicArchiveURLCreator.permalinkForRoom(this._room.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
get roomName() {
|
||||||
|
return this._room.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
get roomAvatarViewModel() {
|
||||||
|
return this._roomAvatarViewModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
openRightPanel() {
|
||||||
|
let path = this.navigation.path.until('room');
|
||||||
|
path = path.with(this.navigation.segment('right-panel', true));
|
||||||
|
path = path.with(this.navigation.segment('change-dates', true));
|
||||||
|
this.navigation.applyPath(path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = ArchiveRoomViewModel;
|
module.exports = ArchiveRoomViewModel;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
const {
|
const {
|
||||||
TemplateView,
|
TemplateView,
|
||||||
AvatarView,
|
AvatarView,
|
||||||
RoomView,
|
TimelineView,
|
||||||
RightPanelView,
|
RightPanelView,
|
||||||
LightboxView,
|
LightboxView,
|
||||||
} = require('hydrogen-view-sdk');
|
} = require('hydrogen-view-sdk');
|
||||||
|
@ -43,8 +43,8 @@ class RoomHeaderView extends TemplateView {
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
t.view(new AvatarView(vm, 32)),
|
t.view(new AvatarView(vm.roomAvatarViewModel, 32)),
|
||||||
t.div({ className: 'room-description' }, [t.h2((vm) => vm.name)]),
|
t.div({ className: 'room-description' }, [t.h2((vm) => vm.roomName)]),
|
||||||
t.button(
|
t.button(
|
||||||
{
|
{
|
||||||
className: 'button-utility RoomHeader_actionButton RoomHeader_changeDatesButton',
|
className: 'button-utility RoomHeader_actionButton RoomHeader_changeDatesButton',
|
||||||
|
@ -82,6 +82,37 @@ class RoomHeaderView extends TemplateView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class DisabledComposerView extends TemplateView {
|
||||||
|
render(t /*, vm*/) {
|
||||||
|
return t.div({ className: 'DisabledComposerView' }, [
|
||||||
|
t.h3([
|
||||||
|
t.map(
|
||||||
|
(vm) => vm.currentTopPositionEventEntry,
|
||||||
|
(_currentTopPositionEventEntry, t, vm) => {
|
||||||
|
const activeDate = new Date(
|
||||||
|
// If the date from our `archiveRoomViewModel` is available, use that
|
||||||
|
vm?.currentTopPositionEventEntry?.timestamp ||
|
||||||
|
// Otherwise, use our initial `dayTimestamp`
|
||||||
|
vm.dayTimestamp
|
||||||
|
);
|
||||||
|
const dateString = activeDate.toISOString().split('T')[0];
|
||||||
|
return t.span(`You're viewing an archive of events from ${dateString}. Use a `);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
t.a(
|
||||||
|
{
|
||||||
|
href: (vm) => vm.roomPermalink,
|
||||||
|
rel: 'noopener',
|
||||||
|
target: '_blank',
|
||||||
|
},
|
||||||
|
['Matrix client']
|
||||||
|
),
|
||||||
|
` to start chatting in this room.`,
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ArchiveRoomView extends TemplateView {
|
class ArchiveRoomView extends TemplateView {
|
||||||
render(t, vm) {
|
render(t, vm) {
|
||||||
const rootElement = t.div(
|
const rootElement = t.div(
|
||||||
|
@ -112,11 +143,13 @@ class ArchiveRoomView extends TemplateView {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
t.view(
|
t.main({ className: 'ArchiveRoomView_mainArea' }, [
|
||||||
new RoomView(vm.roomViewModel, customViewClassForTile, {
|
t.view(new RoomHeaderView(vm)),
|
||||||
RoomHeaderView,
|
t.main({ className: 'ArchiveRoomView_mainBody' }, [
|
||||||
})
|
t.view(new TimelineView(vm.timelineViewModel, customViewClassForTile)),
|
||||||
),
|
t.view(new DisabledComposerView(vm)),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
t.view(new RightPanelView(vm.rightPanelModel)),
|
t.view(new RightPanelView(vm.rightPanelModel)),
|
||||||
t.mapView(
|
t.mapView(
|
||||||
(vm) => vm.lightboxViewModel,
|
(vm) => vm.lightboxViewModel,
|
||||||
|
|
Loading…
Reference in New Issue