diff --git a/public/styles/styles.css b/public/styles/styles.css
index d7eede9..9bed638 100644
--- a/public/styles/styles.css
+++ b/public/styles/styles.css
@@ -29,9 +29,50 @@ body {
min-width: 0;
}
+/* No need to open the right-panel when it's always visible at desktop widths */
+.room-header-change-dates-button {
+ display: none;
+ color: var(--icon-color--darker-20);
+}
+/* No need to close the right-panel when it's always visible at desktop widths */
+.RightPanelView_buttons .close {
+ display: none;
+}
+
+@media screen and (max-width: 800px) {
+ /* Only the middle needs to be visible mobile by default */
+ .ArchiveView {
+ grid-template:
+ 'status' auto
+ 'middle' 1fr /
+ 1fr;
+ }
+ /* Which also means hiding the right-panel by default on mobile */
+ .ArchiveView:not(.right-shown) .RightPanelView {
+ display: none;
+ }
+
+ /* When the user opens the right-panel, show it */
+ .ArchiveView.right-shown {
+ grid-template:
+ 'status' auto
+ 'right' 1fr /
+ 1fr;
+ }
+ .ArchiveView.right-shown .middle {
+ display: none;
+ }
+ /* And show the button to open the right-panel on mobile */
+ .room-header-change-dates-button {
+ display: block;
+ }
+ /* And show the button to close the right-panel on mobile */
+ .RightPanelView_buttons .close {
+ display: block;
+ }
+}
+
.CalendarView {
- max-width: 280px;
- font: 100% system-ui;
}
.CalendarView_header {
@@ -132,7 +173,8 @@ body {
.CalendarView_dayLink {
display: inline-block;
width: 100%;
- padding: 2px 5px;
+ padding-top: 18%;
+ padding-bottom: 18%;
text-decoration: none;
}
@@ -154,7 +196,6 @@ body {
opacity: 0.5;
}
-
/* Error pages */
.heading-sub-detail {
@@ -162,7 +203,6 @@ body {
}
.tracing-span-list {
-
}
.tracing-span-list-item {
@@ -170,7 +210,6 @@ body {
}
.tracing-span-item-http-details {
-
}
.tracing-span-item-sub-details {
diff --git a/server/routes/install-routes.js b/server/routes/install-routes.js
index 22fa237..92d122c 100644
--- a/server/routes/install-routes.js
+++ b/server/routes/install-routes.js
@@ -209,6 +209,7 @@ function installRoutes(app) {
+
${sanitizeHtml(`${roomData.name} - Matrix Public Archive`)}
diff --git a/server/routes/timeout-middleware.js b/server/routes/timeout-middleware.js
index 4fb0fa9..4905252 100644
--- a/server/routes/timeout-middleware.js
+++ b/server/routes/timeout-middleware.js
@@ -55,6 +55,7 @@ async function timeoutMiddleware(req, res, next) {
+
Server timeout - Matrix Public Archive
diff --git a/shared/4-hydrogen-vm-render-script.js b/shared/4-hydrogen-vm-render-script.js
index e134081..ae188d0 100644
--- a/shared/4-hydrogen-vm-render-script.js
+++ b/shared/4-hydrogen-vm-render-script.js
@@ -234,6 +234,13 @@ async function mountHydrogen() {
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);
+ };
+
// FIXME: We shouldn't have to dive into the internal fields to make this work
roomViewModel._timelineVM = timelineViewModel;
roomViewModel._composerVM = {
@@ -292,6 +299,7 @@ async function mountHydrogen() {
class ArchiveViewModel extends ViewModel {
roomViewModel = roomViewModel;
rightPanelModel = {
+ navigation,
activeViewModel: {
type: 'custom',
customView: RightPanelContentView,
@@ -302,15 +310,27 @@ async function mountHydrogen() {
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,
@@ -318,6 +338,11 @@ async function mountHydrogen() {
};
});
}
+
+ _updateRightPanel() {
+ this._shouldShowRightPanel = !!this.navigation.path.get('right-panel')?.value;
+ this.emitChange('shouldShowRightPanel');
+ }
}
const archiveViewModel = new ArchiveViewModel({
diff --git a/shared/ArchiveView.js b/shared/ArchiveView.js
index 343cafa..46c7590 100644
--- a/shared/ArchiveView.js
+++ b/shared/ArchiveView.js
@@ -2,22 +2,70 @@
const {
TemplateView,
+ AvatarView,
RoomView,
RightPanelView,
LightboxView,
viewClassForTile,
} = require('hydrogen-view-sdk');
+class RoomHeaderView extends TemplateView {
+ render(t, vm) {
+ return t.div({ className: 'RoomHeader middle-header' }, [
+ t.view(new AvatarView(vm, 32)),
+ t.div({ className: 'room-description' }, [t.h2((vm) => vm.name)]),
+ t.button(
+ {
+ className: 'button-utility room-header-change-dates-button',
+ 'aria-label': vm.i18n`Change dates`,
+ onClick: (/*evt*/) => {
+ vm.openRightPanel();
+ },
+ },
+ [
+ // Calendar icon (via `calendar2-date` from Bootstrap)
+ t.svg(
+ {
+ xmlns: 'http://www.w3.org/2000/svg',
+ width: '16',
+ height: '16',
+ viewBox: '0 0 16 16',
+ fill: 'currentColor',
+ style: 'vertical-align: middle;',
+ },
+ [
+ t.path({
+ d: 'M6.445 12.688V7.354h-.633A12.6 12.6 0 0 0 4.5 8.16v.695c.375-.257.969-.62 1.258-.777h.012v4.61h.675zm1.188-1.305c.047.64.594 1.406 1.703 1.406 1.258 0 2-1.066 2-2.871 0-1.934-.781-2.668-1.953-2.668-.926 0-1.797.672-1.797 1.809 0 1.16.824 1.77 1.676 1.77.746 0 1.23-.376 1.383-.79h.027c-.004 1.316-.461 2.164-1.305 2.164-.664 0-1.008-.45-1.05-.82h-.684zm2.953-2.317c0 .696-.559 1.18-1.184 1.18-.601 0-1.144-.383-1.144-1.2 0-.823.582-1.21 1.168-1.21.633 0 1.16.398 1.16 1.23z',
+ }),
+ t.path({
+ d: 'M3.5 0a.5.5 0 0 1 .5.5V1h8V.5a.5.5 0 0 1 1 0V1h1a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h1V.5a.5.5 0 0 1 .5-.5zM2 2a1 1 0 0 0-1 1v11a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H2z',
+ }),
+ t.path({
+ d: 'M2.5 4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5H3a.5.5 0 0 1-.5-.5V4z',
+ }),
+ ]
+ ),
+ ]
+ ),
+ ]);
+ }
+}
+
class ArchiveView extends TemplateView {
render(t, vm) {
return t.div(
{
className: {
ArchiveView: true,
+ 'right-shown': (vm) => vm.shouldShowRightPanel,
},
},
[
- t.view(new RoomView(vm.roomViewModel, viewClassForTile)),
+ t.view(
+ new RoomView(vm.roomViewModel, viewClassForTile, {
+ RoomHeaderView,
+ })
+ ),
t.view(new RightPanelView(vm.rightPanelModel)),
t.mapView(
(vm) => vm.lightboxViewModel,
diff --git a/shared/CalendarView.js b/shared/CalendarView.js
index 5f0620a..98cc06f 100644
--- a/shared/CalendarView.js
+++ b/shared/CalendarView.js
@@ -66,6 +66,7 @@ class CalendarView extends TemplateView {
month: 'long',
timeZone: 'UTC',
}),
+ // Dropdown arrow
t.svg(
{
xmlns: 'http://www.w3.org/2000/svg',
diff --git a/shared/lib/archive-history.js b/shared/lib/archive-history.js
index 35d0a30..39ea817 100644
--- a/shared/lib/archive-history.js
+++ b/shared/lib/archive-history.js
@@ -27,10 +27,24 @@ class ArchiveHistory extends History {
// downstream call of `urlRouter.attach()` which we do when bootstraping
// everything.
if (window.history) {
- super.replaceUrlSilently(url);
+ let replacingUrl = url;
+ // This is a way to make sure the hash gets cleared out
+ if (url === '') {
+ replacingUrl = window.location.pathname;
+ }
+ super.replaceUrlSilently(replacingUrl);
}
}
+ pushUrlSilently(url) {
+ let replacingUrl = url;
+ // This is a way to make sure the hash gets cleared out
+ if (url === '') {
+ replacingUrl = window.location.pathname;
+ }
+ super.pushUrlSilently(replacingUrl);
+ }
+
// Make the URLs we use in the UI of the app relative to the room:
// Before: #/session/123/room/!HBehERstyQBxyJDLfR:my.synapse.server/lightbox/$17cgP6YBP9ny9xuU1vBmpOYFhRG4zpOe9SOgWi2Wxsk
// After: #/lightbox/$17cgP6YBP9ny9xuU1vBmpOYFhRG4zpOe9SOgWi2Wxsk