From 1e095994473d3a3424696bb5e5f43cb3ac3ae072 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Wed, 15 Dec 2021 06:34:47 -0600 Subject: [PATCH] Add `/jumptodate` slash command (#7372) Fix https://github.com/vector-im/element-web/issues/7677 Utilizing MSC3030: https://github.com/matrix-org/matrix-doc/pull/3030 Experimental Synapse implementation added in https://github.com/matrix-org/synapse/pull/9445 --- Jump to date headers are being worked on in https://github.com/matrix-org/matrix-react-sdk/pull/7339 --- src/SlashCommands.tsx | 45 +++++++++++++++++++ .../tabs/user/LabsUserSettingsTab.tsx | 16 +++++++ src/i18n/strings/en_EN.json | 3 ++ src/settings/Settings.tsx | 9 ++++ 4 files changed, 73 insertions(+) diff --git a/src/SlashCommands.tsx b/src/SlashCommands.tsx index f7435ddda8..0004f78628 100644 --- a/src/SlashCommands.tsx +++ b/src/SlashCommands.tsx @@ -19,6 +19,7 @@ limitations under the License. import * as React from 'react'; import { User } from "matrix-js-sdk/src/models/user"; +import { Direction } from 'matrix-js-sdk/src/models/event-timeline'; import { EventType } from "matrix-js-sdk/src/@types/event"; import * as ContentHelpers from 'matrix-js-sdk/src/content-helpers'; import { parseFragment as parseHtml, Element as ChildElement } from "parse5"; @@ -286,6 +287,50 @@ export const Commands = [ category: CommandCategories.admin, renderingTypes: [TimelineRenderingType.Room], }), + new Command({ + command: 'jumptodate', + args: '', + description: _td('Jump to the given date in the timeline (YYYY-MM-DD)'), + isEnabled: () => SettingsStore.getValue("feature_jump_to_date"), + runFn: function(roomId, args) { + if (args) { + return success((async () => { + const unixTimestamp = Date.parse(args); + if (!unixTimestamp) { + throw new Error( + // FIXME: Use newTranslatableError here instead + // otherwise the rageshake error messages will be + // translated too + _t( + // eslint-disable-next-line max-len + 'We were unable to understand the given date (%(inputDate)s). Try using the format YYYY-MM-DD.', + { inputDate: args }, + ), + ); + } + + const cli = MatrixClientPeg.get(); + const { event_id: eventId, origin_server_ts: originServerTs } = await cli.timestampToEvent( + roomId, + unixTimestamp, + Direction.Forward, + ); + logger.log( + `/timestamp_to_event: found ${eventId} (${originServerTs}) for timestamp=${unixTimestamp}`, + ); + dis.dispatch({ + action: Action.ViewRoom, + eventId, + highlighted: true, + room_id: roomId, + }); + })()); + } + + return reject(this.getUsage()); + }, + category: CommandCategories.actions, + }), new Command({ command: 'nick', args: '', diff --git a/src/components/views/settings/tabs/user/LabsUserSettingsTab.tsx b/src/components/views/settings/tabs/user/LabsUserSettingsTab.tsx index d8ecbc2815..496f2fc1e6 100644 --- a/src/components/views/settings/tabs/user/LabsUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/LabsUserSettingsTab.tsx @@ -49,6 +49,7 @@ export class LabsSettingToggle extends React.Component interface IState { showHiddenReadReceipts: boolean; + showJumpToDate: boolean; } @replaceableComponent("views.settings.tabs.user.LabsUserSettingsTab") @@ -60,8 +61,13 @@ export default class LabsUserSettingsTab extends React.Component<{}, IState> { this.setState({ showHiddenReadReceipts }); }); + MatrixClientPeg.get().doesServerSupportUnstableFeature("org.matrix.msc2716").then((showJumpToDate) => { + this.setState({ showJumpToDate }); + }); + this.state = { showHiddenReadReceipts: false, + showJumpToDate: false, }; } @@ -135,6 +141,16 @@ export default class LabsUserSettingsTab extends React.Component<{}, IState> { ); } + if (this.state.showJumpToDate) { + groups.getOrCreate(LabGroup.Messaging, []).push( + , + ); + } + labsSection =
{ sortBy(Array.from(groups.entries()), "0").map(([group, flags]) => (
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index bae4cc2d7c..6cc5f8ca46 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -435,6 +435,8 @@ "Sends a message as html, without interpreting it as markdown": "Sends a message as html, without interpreting it as markdown", "Upgrades a room to a new version": "Upgrades a room to a new version", "You do not have the required permissions to use this command.": "You do not have the required permissions to use this command.", + "Jump to the given date in the timeline (YYYY-MM-DD)": "Jump to the given date in the timeline (YYYY-MM-DD)", + "We were unable to understand the given date (%(inputDate)s). Try using the format YYYY-MM-DD.": "We were unable to understand the given date (%(inputDate)s). Try using the format YYYY-MM-DD.", "Changes your display nickname": "Changes your display nickname", "Changes your display nickname in the current room only": "Changes your display nickname in the current room only", "Changes the avatar of the current room": "Changes the avatar of the current room", @@ -860,6 +862,7 @@ "Meta Spaces": "Meta Spaces", "Use new room breadcrumbs": "Use new room breadcrumbs", "New spotlight search experience": "New spotlight search experience", + "Jump to date (adds /jumptodate)": "Jump to date (adds /jumptodate)", "Don't send read receipts": "Don't send read receipts", "Font size": "Font size", "Use custom size": "Use custom size", diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx index a86f053512..ff295484fb 100644 --- a/src/settings/Settings.tsx +++ b/src/settings/Settings.tsx @@ -367,6 +367,15 @@ export const SETTINGS: {[setting: string]: ISetting} = { displayName: _td("New spotlight search experience"), default: false, }, + "feature_jump_to_date": { + // We purposely leave out `isFeature: true` so it doesn't show in Labs + // by default. We will conditionally show it depending on whether we can + // detect MSC3030 support (see LabUserSettingsTab.tsx). + // labsGroup: LabGroup.Messaging, + displayName: _td("Jump to date (adds /jumptodate)"), + supportedLevels: LEVELS_FEATURE, + default: false, + }, "RoomList.backgroundImage": { supportedLevels: LEVELS_ACCOUNT_SETTINGS, default: null,