From ea302162ee901854a5dd7e962fafe019799be4ff Mon Sep 17 00:00:00 2001 From: Andy Balaam Date: Wed, 4 Feb 2026 12:32:15 +0000 Subject: [PATCH 1/9] Remove unused UIFeature.BulkUnverifiedSessionsReminder setting (#31943) --- docs/config.md | 2 -- src/DeviceListener.ts | 10 +--------- src/settings/Settings.tsx | 4 ---- src/settings/UIFeature.ts | 1 - test/unit-tests/DeviceListener-test.ts | 23 +---------------------- 5 files changed, 2 insertions(+), 38 deletions(-) diff --git a/docs/config.md b/docs/config.md index c8773544fe..5856ce8c43 100644 --- a/docs/config.md +++ b/docs/config.md @@ -581,8 +581,6 @@ Currently, the following UI feature flags are supported: This should only be used if the room history visibility options are managed by the server. - `UIFeature.TimelineEnableRelativeDates` - Display relative date separators (eg: 'Today', 'Yesterday') in the timeline for recent messages. When false day dates will be used. -- `UIFeature.BulkUnverifiedSessionsReminder` - Display popup reminders to verify or remove unverified sessions. Defaults - to true. - `UIFeature.locationSharing` - Whether or not location sharing menus will be shown. - `UIFeature.allowCreatingPublicRooms` - Whether or not public rooms can be created. - `UIFeature.allowCreatingPublicSpaces` - Whether or not public spaces can be created. diff --git a/src/DeviceListener.ts b/src/DeviceListener.ts index 410f40add8..e9c723b75d 100644 --- a/src/DeviceListener.ts +++ b/src/DeviceListener.ts @@ -43,7 +43,6 @@ import SdkConfig from "./SdkConfig"; import PlatformPeg from "./PlatformPeg"; import { recordClientInformation, removeClientInformation } from "./utils/device/clientInformation"; import SettingsStore, { type CallbackFn } from "./settings/SettingsStore"; -import { UIFeature } from "./settings/UIFeature"; import { isBulkUnverifiedDeviceReminderSnoozed } from "./utils/device/snoozeBulkUnverifiedDeviceReminder"; import { getUserDeviceIds } from "./utils/crypto/deviceInfo"; import { asyncSomeParallel } from "./utils/arrays.ts"; @@ -125,7 +124,6 @@ export default class DeviceListener extends TypedEventEmitter 0 && - isCurrentDeviceTrusted && - this.enableBulkUnverifiedSessionsReminder && - !isBulkUnverifiedSessionsReminderSnoozed - ) { + if (oldUnverifiedDeviceIds.size > 0 && isCurrentDeviceTrusted && !isBulkUnverifiedSessionsReminderSnoozed) { showBulkUnverifiedSessionsToast(oldUnverifiedDeviceIds); } else { hideBulkUnverifiedSessionsToast(); diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx index 8c57e234ae..b871152d8f 100644 --- a/src/settings/Settings.tsx +++ b/src/settings/Settings.tsx @@ -1437,10 +1437,6 @@ export const SETTINGS: Settings = { supportedLevels: LEVELS_UI_FEATURE, default: true, }, - [UIFeature.BulkUnverifiedSessionsReminder]: { - supportedLevels: LEVELS_UI_FEATURE, - default: true, - }, [UIFeature.AllowCreatingPublicSpaces]: { supportedLevels: LEVELS_UI_FEATURE, default: true, diff --git a/src/settings/UIFeature.ts b/src/settings/UIFeature.ts index 12b0c7c089..0215b79175 100644 --- a/src/settings/UIFeature.ts +++ b/src/settings/UIFeature.ts @@ -24,7 +24,6 @@ export const enum UIFeature { AdvancedSettings = "UIFeature.advancedSettings", RoomHistorySettings = "UIFeature.roomHistorySettings", TimelineEnableRelativeDates = "UIFeature.timelineEnableRelativeDates", - BulkUnverifiedSessionsReminder = "UIFeature.BulkUnverifiedSessionsReminder", AllowCreatingPublicRooms = "UIFeature.allowCreatingPublicRooms", AllowCreatingPublicSpaces = "UIFeature.allowCreatingPublicSpaces", } diff --git a/test/unit-tests/DeviceListener-test.ts b/test/unit-tests/DeviceListener-test.ts index 4810d82001..f9339cd38b 100644 --- a/test/unit-tests/DeviceListener-test.ts +++ b/test/unit-tests/DeviceListener-test.ts @@ -35,7 +35,6 @@ import { Action } from "../../src/dispatcher/actions"; import SettingsStore from "../../src/settings/SettingsStore"; import { SettingLevel } from "../../src/settings/SettingLevel"; import { getMockClientWithEventEmitter, mockPlatformPeg } from "../test-utils"; -import { UIFeature } from "../../src/settings/UIFeature"; import { isBulkUnverifiedDeviceReminderSnoozed } from "../../src/utils/device/snoozeBulkUnverifiedDeviceReminder"; import { PosthogAnalytics } from "../../src/PosthogAnalytics"; @@ -653,10 +652,8 @@ describe("DeviceListener", () => { // all devices verified by default mockCrypto!.getDeviceVerificationStatus.mockResolvedValue(deviceTrustVerified); mockClient!.deviceId = currentDevice.deviceId; - jest.spyOn(SettingsStore, "getValue").mockImplementation( - (settingName) => settingName === UIFeature.BulkUnverifiedSessionsReminder, - ); }); + describe("bulk unverified sessions toasts", () => { it("hides toast when cross signing is not ready", async () => { mockCrypto!.isCrossSigningReady.mockResolvedValue(false); @@ -671,24 +668,6 @@ describe("DeviceListener", () => { expect(BulkUnverifiedSessionsToast.showToast).not.toHaveBeenCalled(); }); - it("hides toast when feature is disabled", async () => { - // BulkUnverifiedSessionsReminder set to false - jest.spyOn(SettingsStore, "getValue").mockReturnValue(false); - // currentDevice, device2 are verified, device3 is unverified - // ie if reminder was enabled it should be shown - mockCrypto!.getDeviceVerificationStatus.mockImplementation(async (_userId, deviceId) => { - switch (deviceId) { - case currentDevice.deviceId: - case device2.deviceId: - return deviceTrustVerified; - default: - return deviceTrustUnverified; - } - }); - await createAndStart(); - expect(BulkUnverifiedSessionsToast.hideToast).toHaveBeenCalled(); - }); - it("hides toast when current device is unverified", async () => { // device2 verified, current and device3 unverified mockCrypto!.getDeviceVerificationStatus.mockImplementation(async (_userId, deviceId) => { From c647c8ee3dba202f0068670a0bb2bcc2264278bc Mon Sep 17 00:00:00 2001 From: Zack Date: Wed, 4 Feb 2026 14:25:36 +0100 Subject: [PATCH 2/9] Refactor Timeline Seperator (#31937) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Refactor TimelineSeparator to shared-components package • New TimelineSeparator component in packages/shared-components/ • Updated MessagePanel.tsx to import from shared-components * Fix copyright text * Timeline Unit Tests + Timeline Snapshot Tests * Imported correct timeline seperator * Update snapshots because of css update * Apply suggestion from @florianduros Co-authored-by: Florian Duros * Created className prop * Removal of element x unused css * Update snapshot because of Flex * Update snapshots because of Flex * Update css to correct values and compund name * Added letter spacing to timelineseperator * rremoval of letter spacing * added align center to flex to apply correct css changes * Update snapshots to reflect new css changes * Update snapshots to reflect css changes * Added letter-spacing to timeline seperator * Update snapshots after css update * update snapshots --------- Co-authored-by: Florian Duros --- .../default-auto.png | Bin 0 -> 18955 bytes .../with-date-event-auto.png | Bin 0 -> 18626 bytes .../with-html-child-auto.png | Bin 0 -> 17932 bytes .../with-late-event-auto.png | Bin 0 -> 18721 bytes .../without-children-auto.png | Bin 0 -> 3629 bytes packages/shared-components/src/index.ts | 1 + .../TimelineSeparator.module.css | 21 ++++ .../TimelineSeparator.stories.tsx | 54 ++++++++++ .../TimelineSeparator.test.tsx | 48 +++++++++ .../TimelineSeparator/TimelineSeparator.tsx | 54 ++++++++++ .../TimelineSeparator.test.tsx.snap | 100 ++++++++++++++++++ .../message-body/TimelineSeparator/index.ts | 8 ++ res/css/_components.pcss | 1 - .../views/messages/_TimelineSeparator.pcss | 23 ---- src/components/structures/MessagePanel.tsx | 16 ++- .../structures/grouper/CreationGrouper.tsx | 3 +- .../structures/grouper/MainGrouper.tsx | 3 +- .../views/messages/DateSeparator.tsx | 8 +- .../views/messages/TimelineSeparator.tsx | 39 ------- .../__snapshots__/MessagePanel-test.tsx.snap | 3 +- .../MessageEditHistoryDialog-test.tsx.snap | 6 +- .../__snapshots__/DateSeparator-test.tsx.snap | 9 +- .../__snapshots__/HTMLExport-test.ts.snap | 2 +- 23 files changed, 321 insertions(+), 78 deletions(-) create mode 100644 packages/shared-components/__vis__/linux/__baselines__/message-body/TimelineSeparator/TimelineSeparator.stories.tsx/default-auto.png create mode 100644 packages/shared-components/__vis__/linux/__baselines__/message-body/TimelineSeparator/TimelineSeparator.stories.tsx/with-date-event-auto.png create mode 100644 packages/shared-components/__vis__/linux/__baselines__/message-body/TimelineSeparator/TimelineSeparator.stories.tsx/with-html-child-auto.png create mode 100644 packages/shared-components/__vis__/linux/__baselines__/message-body/TimelineSeparator/TimelineSeparator.stories.tsx/with-late-event-auto.png create mode 100644 packages/shared-components/__vis__/linux/__baselines__/message-body/TimelineSeparator/TimelineSeparator.stories.tsx/without-children-auto.png create mode 100644 packages/shared-components/src/message-body/TimelineSeparator/TimelineSeparator.module.css create mode 100644 packages/shared-components/src/message-body/TimelineSeparator/TimelineSeparator.stories.tsx create mode 100644 packages/shared-components/src/message-body/TimelineSeparator/TimelineSeparator.test.tsx create mode 100644 packages/shared-components/src/message-body/TimelineSeparator/TimelineSeparator.tsx create mode 100644 packages/shared-components/src/message-body/TimelineSeparator/__snapshots__/TimelineSeparator.test.tsx.snap create mode 100644 packages/shared-components/src/message-body/TimelineSeparator/index.ts delete mode 100644 res/css/views/messages/_TimelineSeparator.pcss delete mode 100644 src/components/views/messages/TimelineSeparator.tsx diff --git a/packages/shared-components/__vis__/linux/__baselines__/message-body/TimelineSeparator/TimelineSeparator.stories.tsx/default-auto.png b/packages/shared-components/__vis__/linux/__baselines__/message-body/TimelineSeparator/TimelineSeparator.stories.tsx/default-auto.png new file mode 100644 index 0000000000000000000000000000000000000000..9830d14901a261ff7cff285aae433d9a2ee41011 GIT binary patch literal 18955 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 WHh%1TZbzE literal 0 HcmV?d00001 diff --git a/packages/shared-components/__vis__/linux/__baselines__/message-body/TimelineSeparator/TimelineSeparator.stories.tsx/with-late-event-auto.png b/packages/shared-components/__vis__/linux/__baselines__/message-body/TimelineSeparator/TimelineSeparator.stories.tsx/with-late-event-auto.png new file mode 100644 index 0000000000000000000000000000000000000000..9cb04d975778234f0d3720e0e04335c231a4e1fd GIT binary patch literal 18721 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 )X($95joXBx#|ntf043W;;zH< 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 WK4*2&5Jy;HEL&=`Bz2MdKmP;&ppZ2H literal 0 HcmV?d00001 diff --git a/packages/shared-components/__vis__/linux/__baselines__/message-body/TimelineSeparator/TimelineSeparator.stories.tsx/without-children-auto.png b/packages/shared-components/__vis__/linux/__baselines__/message-body/TimelineSeparator/TimelineSeparator.stories.tsx/without-children-auto.png new file mode 100644 index 0000000000000000000000000000000000000000..2e132bb28b03d378b09f73896707a47acc128999 GIT binary patch literal 3629 zcmeAS@N?(olHy`uVBq!ia0y~yU_QXWz;uCw2`F+wwC^!c{E?@NV@SoEH+MF29(E96 zxhNd-f2kCYpAPGCv42nAhZ-K-^n1=`28M>2dx3-@BQFC(V*?vQgM$MzgM-2XMh1l& z^WWz)GB6ll|6eD@z+h1Pvk@q5DV@Q hr { + flex: 1 1 0; + height: 0; + border: none; + border-bottom: 1px solid var(--cpd-color-gray-400); +} diff --git a/packages/shared-components/src/message-body/TimelineSeparator/TimelineSeparator.stories.tsx b/packages/shared-components/src/message-body/TimelineSeparator/TimelineSeparator.stories.tsx new file mode 100644 index 0000000000..cf067f4ecd --- /dev/null +++ b/packages/shared-components/src/message-body/TimelineSeparator/TimelineSeparator.stories.tsx @@ -0,0 +1,54 @@ +/* + * Copyright 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +import React from "react"; + +import type { Meta, StoryFn } from "@storybook/react-vite"; +import TimelineSeparator from "./TimelineSeparator"; +import styles from "./TimelineSeparator.module.css"; + +export default { + title: "MessageBody/TimelineSeparator", + component: TimelineSeparator, + tags: ["autodocs"], + args: { + label: "Label Separator", + children: "Timeline Separator", + }, +} as Meta; + +const Template: StoryFn = (args) => ; + +export const Default = Template.bind({}); + +export const WithHtmlChild = Template.bind({}); +WithHtmlChild.args = { + label: "Custom Label", + children: ( + + ), +}; + +export const WithDateEvent = Template.bind({}); +WithDateEvent.args = { + label: "Date Event Separator", + children: "Wednesday", +}; + +export const WithLateEvent = Template.bind({}); +WithLateEvent.args = { + label: "Late Event Separator", + children: "Fri, Jan 9, 2026", +}; + +export const WithoutChildren = Template.bind({}); +WithoutChildren.args = { + children: undefined, + label: "Separator without children", +}; diff --git a/packages/shared-components/src/message-body/TimelineSeparator/TimelineSeparator.test.tsx b/packages/shared-components/src/message-body/TimelineSeparator/TimelineSeparator.test.tsx new file mode 100644 index 0000000000..859142b49c --- /dev/null +++ b/packages/shared-components/src/message-body/TimelineSeparator/TimelineSeparator.test.tsx @@ -0,0 +1,48 @@ +/* + * Copyright 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +import { render } from "@test-utils"; +import { composeStories } from "@storybook/react-vite"; +import React from "react"; +import { afterEach, describe, expect, it, vi } from "vitest"; + +import * as stories from "./TimelineSeparator.stories.tsx"; + +const { Default, WithHtmlChild, WithoutChildren, WithDateEvent, WithLateEvent } = composeStories(stories); + +describe("TimelineSeparator", () => { + afterEach(() => { + vi.clearAllMocks(); + }); + + describe("Snapshot tests", () => { + it("renders the timeline separator in default state", () => { + const { container } = render(); + expect(container).toMatchSnapshot(); + }); + + it("renders the timeline separator with HTML child", () => { + const { container } = render(); + expect(container).toMatchSnapshot(); + }); + + it("renders the timeline separator with date event", () => { + const { container } = render(); + expect(container).toMatchSnapshot(); + }); + + it("renders the timeline separator with late event", () => { + const { container } = render(); + expect(container).toMatchSnapshot(); + }); + + it("renders the timeline separator without children", () => { + const { container } = render(); + expect(container).toMatchSnapshot(); + }); + }); +}); diff --git a/packages/shared-components/src/message-body/TimelineSeparator/TimelineSeparator.tsx b/packages/shared-components/src/message-body/TimelineSeparator/TimelineSeparator.tsx new file mode 100644 index 0000000000..cd3af1c1a7 --- /dev/null +++ b/packages/shared-components/src/message-body/TimelineSeparator/TimelineSeparator.tsx @@ -0,0 +1,54 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE files in the repository root for full details. +*/ + +import React, { type PropsWithChildren } from "react"; +import classNames from "classnames"; + +import styles from "./TimelineSeparator.module.css"; +import { Flex } from "../.."; + +/** + * Timeline separator props + */ +export interface TimelineSeparatorProps { + /** + * Accessible label for the separator (for example: "Today", "Yesterday", or a date). + */ + label: string; + /** + * The CSS class name. + */ + className?: string; + /** + * Optional children to render inside the timeline separator + */ + children?: PropsWithChildren["children"]; +} + +/** + * Generic timeline separator component to render within a MessagePanel + * + * @param label the accessible label string describing the separator + * @param children the children to draw within the timeline separator + */ +const TimelineSeparator: React.FC = ({ label, className, children }) => { + // ARIA treats
s as separators, here we abuse them slightly so manually treat this entire thing as one + return ( + +
+ {children} +
+
+ ); +}; + +export default TimelineSeparator; diff --git a/packages/shared-components/src/message-body/TimelineSeparator/__snapshots__/TimelineSeparator.test.tsx.snap b/packages/shared-components/src/message-body/TimelineSeparator/__snapshots__/TimelineSeparator.test.tsx.snap new file mode 100644 index 0000000000..e45501e14d --- /dev/null +++ b/packages/shared-components/src/message-body/TimelineSeparator/__snapshots__/TimelineSeparator.test.tsx.snap @@ -0,0 +1,100 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`TimelineSeparator > Snapshot tests > renders the timeline separator in default state 1`] = ` +
+ +
+`; + +exports[`TimelineSeparator > Snapshot tests > renders the timeline separator with HTML child 1`] = ` +
+ +
+`; + +exports[`TimelineSeparator > Snapshot tests > renders the timeline separator with date event 1`] = ` +
+ +
+`; + +exports[`TimelineSeparator > Snapshot tests > renders the timeline separator with late event 1`] = ` +
+ +
+`; + +exports[`TimelineSeparator > Snapshot tests > renders the timeline separator without children 1`] = ` +
+ +
+`; diff --git a/packages/shared-components/src/message-body/TimelineSeparator/index.ts b/packages/shared-components/src/message-body/TimelineSeparator/index.ts new file mode 100644 index 0000000000..c5812abb07 --- /dev/null +++ b/packages/shared-components/src/message-body/TimelineSeparator/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright 2026 Element Creations Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +export { default as TimelineSeparator, type TimelineSeparatorProps } from "./TimelineSeparator"; diff --git a/res/css/_components.pcss b/res/css/_components.pcss index a47fc0ac82..28458c899f 100644 --- a/res/css/_components.pcss +++ b/res/css/_components.pcss @@ -246,7 +246,6 @@ @import "./views/messages/_RedactedBody.pcss"; @import "./views/messages/_RoomAvatarEvent.pcss"; @import "./views/messages/_TextualEvent.pcss"; -@import "./views/messages/_TimelineSeparator.pcss"; @import "./views/messages/_UnknownBody.pcss"; @import "./views/messages/_ViewSourceEvent.pcss"; @import "./views/messages/_common_CryptoEvent.pcss"; diff --git a/res/css/views/messages/_TimelineSeparator.pcss b/res/css/views/messages/_TimelineSeparator.pcss deleted file mode 100644 index aab77d4e03..0000000000 --- a/res/css/views/messages/_TimelineSeparator.pcss +++ /dev/null @@ -1,23 +0,0 @@ -/* -Copyright 2024 New Vector Ltd. -Copyright 2017 Vector Creations Ltd - -SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE files in the repository root for full details. -*/ - -.mx_TimelineSeparator { - clear: both; - margin: 4px 0; - display: flex; - align-items: center; - font: var(--cpd-font-body-md-regular); - color: var(--cpd-color-text-primary); -} - -.mx_TimelineSeparator > hr { - flex: 1 1 0; - height: 0; - border: none; - border-bottom: 1px solid var(--cpd-color-gray-400); -} diff --git a/src/components/structures/MessagePanel.tsx b/src/components/structures/MessagePanel.tsx index 30f9b474a6..40b69130a7 100644 --- a/src/components/structures/MessagePanel.tsx +++ b/src/components/structures/MessagePanel.tsx @@ -18,6 +18,7 @@ import { } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; import { isSupportedReceiptType } from "matrix-js-sdk/src/utils"; +import { TimelineSeparator } from "@element-hq/web-shared-components"; import shouldHideEvent from "../../shouldHideEvent"; import { formatDate, wantsDateSeparator } from "../../DateUtils"; @@ -37,7 +38,6 @@ import type LegacyCallEventGrouper from "./LegacyCallEventGrouper"; import WhoIsTypingTile from "../views/rooms/WhoIsTypingTile"; import ScrollPanel, { type IScrollState } from "./ScrollPanel"; import DateSeparator from "../views/messages/DateSeparator"; -import TimelineSeparator, { SeparatorKind } from "../views/messages/TimelineSeparator"; import ErrorBoundary from "../views/elements/ErrorBoundary"; import Spinner from "../views/elements/Spinner"; import { type RoomPermalinkCreator } from "../../utils/permalinks/Permalinks"; @@ -57,6 +57,18 @@ import { getLateEventInfo } from "./grouper/LateEventGrouper"; const CONTINUATION_MAX_INTERVAL = 5 * 60 * 1000; // 5 minutes const continuedTypes = [EventType.Sticker, EventType.RoomMessage]; +/** + * Indicates which separator (if any) should be rendered between timeline events. + */ +export const enum SeparatorKind { + /** No separator should be shown between the two events. */ + None, + /** Insert a date separator (oriented by event date boundaries). */ + Date, + /** Insert a late-event separator when events belong to different late groups. */ + LateEvent, +} + // check if there is a previous event and it has the same sender as this event // and the types are the same/is in continuedTypes and the time between them is <= CONTINUATION_MAX_INTERVAL export function shouldFormContinuation( @@ -756,7 +768,7 @@ export default class MessagePanel extends React.Component { }); ret.push(
  • - + {text}
  • , diff --git a/src/components/structures/grouper/CreationGrouper.tsx b/src/components/structures/grouper/CreationGrouper.tsx index 009f5bdc26..80c9bfedcd 100644 --- a/src/components/structures/grouper/CreationGrouper.tsx +++ b/src/components/structures/grouper/CreationGrouper.tsx @@ -11,14 +11,13 @@ import { EventType, M_BEACON_INFO, type MatrixEvent } from "matrix-js-sdk/src/ma import { KnownMembership } from "matrix-js-sdk/src/types"; import { BaseGrouper } from "./BaseGrouper"; -import { type WrappedEvent } from "../MessagePanel"; +import { SeparatorKind, type WrappedEvent } from "../MessagePanel"; import type MessagePanel from "../MessagePanel"; import DMRoomMap from "../../../utils/DMRoomMap"; import { _t } from "../../../languageHandler"; import DateSeparator from "../../views/messages/DateSeparator"; import NewRoomIntro from "../../views/rooms/NewRoomIntro"; import GenericEventListSummary from "../../views/elements/GenericEventListSummary"; -import { SeparatorKind } from "../../views/messages/TimelineSeparator"; // Wrap initial room creation events into a GenericEventListSummary // Grouping only events sent by the same user that sent the `m.room.create` and only until diff --git a/src/components/structures/grouper/MainGrouper.tsx b/src/components/structures/grouper/MainGrouper.tsx index e686f1aa81..6766f0e5b7 100644 --- a/src/components/structures/grouper/MainGrouper.tsx +++ b/src/components/structures/grouper/MainGrouper.tsx @@ -10,14 +10,13 @@ import React, { type ReactNode } from "react"; import { EventType, type MatrixEvent } from "matrix-js-sdk/src/matrix"; import type MessagePanel from "../MessagePanel"; -import type { WrappedEvent } from "../MessagePanel"; +import { SeparatorKind, type WrappedEvent } from "../MessagePanel"; import { BaseGrouper } from "./BaseGrouper"; import { hasText } from "../../../TextForEvent"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; import DateSeparator from "../../views/messages/DateSeparator"; import HistoryTile from "../../views/rooms/HistoryTile"; import EventListSummary from "../../views/elements/EventListSummary"; -import { SeparatorKind } from "../../views/messages/TimelineSeparator"; const groupedStateEvents = [ EventType.RoomMember, diff --git a/src/components/views/messages/DateSeparator.tsx b/src/components/views/messages/DateSeparator.tsx index 7d49042533..061cc76204 100644 --- a/src/components/views/messages/DateSeparator.tsx +++ b/src/components/views/messages/DateSeparator.tsx @@ -12,6 +12,7 @@ import { Direction, ConnectionError, MatrixError, HTTPError } from "matrix-js-sd import { logger } from "matrix-js-sdk/src/logger"; import { capitalize } from "lodash"; import { ChevronDownIcon } from "@vector-im/compound-design-tokens/assets/web/icons"; +import { TimelineSeparator } from "@element-hq/web-shared-components"; import { _t, getUserLanguage } from "../../../languageHandler"; import { formatFullDateNoDay, formatFullDateNoTime, getDaysArray } from "../../../DateUtils"; @@ -32,7 +33,6 @@ import IconizedContextMenu, { } from "../context_menus/IconizedContextMenu"; import JumpToDatePicker from "./JumpToDatePicker"; import { type ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload"; -import TimelineSeparator from "./TimelineSeparator"; import RoomContext from "../../../contexts/RoomContext"; interface IProps { @@ -335,6 +335,10 @@ export default class DateSeparator extends React.Component { ); } - return {dateHeaderContent}; + return ( + + {dateHeaderContent} + + ); } } diff --git a/src/components/views/messages/TimelineSeparator.tsx b/src/components/views/messages/TimelineSeparator.tsx deleted file mode 100644 index 4735c8e00c..0000000000 --- a/src/components/views/messages/TimelineSeparator.tsx +++ /dev/null @@ -1,39 +0,0 @@ -/* -Copyright 2024 New Vector Ltd. -Copyright 2023 The Matrix.org Foundation C.I.C. - -SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE files in the repository root for full details. -*/ - -import React, { type ReactNode } from "react"; - -interface Props { - label: string; - children?: ReactNode; -} - -export const enum SeparatorKind { - None, - Date, - LateEvent, -} - -/** - * Generic timeline separator component to render within a MessagePanel - * - * @param label the accessible label string describing the separator - * @param children the children to draw within the timeline separator - */ -const TimelineSeparator: React.FC = ({ label, children }) => { - // ARIA treats
    s as separators, here we abuse them slightly so manually treat this entire thing as one - return ( -
    -
    - {children} -
    -
    - ); -}; - -export default TimelineSeparator; diff --git a/test/unit-tests/components/structures/__snapshots__/MessagePanel-test.tsx.snap b/test/unit-tests/components/structures/__snapshots__/MessagePanel-test.tsx.snap index 716b0e7257..f31612ae13 100644 --- a/test/unit-tests/components/structures/__snapshots__/MessagePanel-test.tsx.snap +++ b/test/unit-tests/components/structures/__snapshots__/MessagePanel-test.tsx.snap @@ -39,8 +39,9 @@ exports[`MessagePanel should handle lots of membership events quickly 1`] = ` > From 323a325981a714764620ed445fb4c4962c92dfcb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 4 Feb 2026 14:03:06 +0000 Subject: [PATCH 3/9] Update docker.io/docker/dockerfile Docker tag to v1.21 (#31959) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 09e0d30984..9b418ac7fc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -# syntax=docker.io/docker/dockerfile:1.20-labs@sha256:dbcde2ebc4abc8bb5c3c499b9c9a6876842bf5da243951cd2697f921a7aeb6a9 +# syntax=docker.io/docker/dockerfile:1.21-labs@sha256:2e681d22e86e738a057075f930b81b2ab8bc2a34cd16001484a7453cfa7a03fb # Builder FROM --platform=$BUILDPLATFORM node:24-bullseye@sha256:8036dbe5b1f465e3acb8b866031cd06e4f84c31b0e83dabbdc59397a40dbe288 AS builder From bef626a61c7105abdf2da8b4bf52817ff6f1763c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 4 Feb 2026 14:20:28 +0000 Subject: [PATCH 4/9] Update dependency matrix-widget-api to v1.17.0 (#31958) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/yarn.lock b/yarn.lock index 03671c8044..2e9835857e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1727,8 +1727,18 @@ yaml "^2.7.0" "@element-hq/web-shared-components@link:packages/shared-components": - version "0.0.0" - uid "" + version "0.0.1" + dependencies: + "@element-hq/element-web-module-api" "^1.8.0" + "@matrix-org/spec" "^1.7.0" + "@vector-im/compound-design-tokens" "^6.4.3" + classnames "^2.5.1" + counterpart "^0.18.6" + lodash "^4.17.21" + matrix-web-i18n "3.6.0" + react-merge-refs "^3.0.2" + react-virtuoso "^4.14.0" + temporal-polyfill "^0.3.0" "@emnapi/core@^1.4.3": version "1.7.0" @@ -4500,7 +4510,6 @@ "@vector-im/matrix-wysiwyg-wasm@link:../../Library/Caches/Yarn/v6/npm-@vector-im-matrix-wysiwyg-2.40.0-53c9ca5ea907d91e4515da64f20a82e5586b882c-integrity/node_modules/bindings/wysiwyg-wasm": version "0.0.0" - uid "" "@vector-im/matrix-wysiwyg@2.40.0": version "2.40.0" @@ -9797,9 +9806,9 @@ matrix-web-i18n@3.6.0: walk "^2.3.15" matrix-widget-api@^1.16.1: - version "1.16.1" - resolved "https://registry.yarnpkg.com/matrix-widget-api/-/matrix-widget-api-1.16.1.tgz#a447f28f0af07e1bdc960881971de7d1ec9e6464" - integrity sha512-oCfTV4xNPo02qIgveqdkIyKQjOPpsjhF3bmJBotHrhr8TsrhVa7kx8PtuiUPnQTjz0tdBle7falR2Fw8VKsedw== + version "1.17.0" + resolved "https://registry.yarnpkg.com/matrix-widget-api/-/matrix-widget-api-1.17.0.tgz#2336de2186fe70d8bd741c1603c162f60b2099c2" + integrity sha512-5FHoo3iEP3Bdlv5jsYPWOqj+pGdFQNLWnJLiB0V7Ygne7bb+Gsj3ibyFyHWC6BVw+Z+tSW4ljHpO17I9TwStwQ== dependencies: "@types/events" "^3.0.0" events "^3.2.0" From 2a1708aa27142f16d274fd3adf21bbd69496cbcb Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 4 Feb 2026 14:26:05 +0000 Subject: [PATCH 5/9] Fix user pill deserialisation (#31947) when containing slashes This also fixes `m.mentions` calculations on edits Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/utils/permalinks/MatrixToPermalinkConstructor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/permalinks/MatrixToPermalinkConstructor.ts b/src/utils/permalinks/MatrixToPermalinkConstructor.ts index 77b4830e19..d7cbc5e927 100644 --- a/src/utils/permalinks/MatrixToPermalinkConstructor.ts +++ b/src/utils/permalinks/MatrixToPermalinkConstructor.ts @@ -63,7 +63,7 @@ export default class MatrixToPermalinkConstructor extends PermalinkConstructor { const entity = parts[0]; if (entity[0] === "@") { // Probably a user, no further parsing needed. - return PermalinkParts.forUser(entity); + return PermalinkParts.forUser(matches[1]); } else if (entity[0] === "#" || entity[0] === "!") { if (parts.length === 1) { // room without event permalink From a05b359c28f56f9333d38ca74b8ef2cf6defc4ab Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 4 Feb 2026 15:48:53 +0000 Subject: [PATCH 6/9] Update dependency caniuse-lite to v1.0.30001766 (#31954) * Update dependency caniuse-lite to v1.0.30001766 * Update browser versions --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: David Baker --- package.json | 2 +- test/unit-tests/SupportedBrowser-test.ts | 12 ++++++------ yarn.lock | 8 ++++---- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 397465c8fe..45214833c1 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,7 @@ "@types/react-dom": "19.2.3", "oidc-client-ts": "3.4.1", "jwt-decode": "4.0.0", - "caniuse-lite": "1.0.30001764", + "caniuse-lite": "1.0.30001766", "testcontainers": "^11.0.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0", "wrap-ansi": "npm:wrap-ansi@^7.0.0", diff --git a/test/unit-tests/SupportedBrowser-test.ts b/test/unit-tests/SupportedBrowser-test.ts index 3607b35a08..bd5cd9355b 100644 --- a/test/unit-tests/SupportedBrowser-test.ts +++ b/test/unit-tests/SupportedBrowser-test.ts @@ -66,17 +66,17 @@ describe("SupportedBrowser", () => { // Safari 26.0 on macOS "Mozilla/5.0 (Macintosh; Intel Mac OS X 15_7_2) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Safari/605.1.15", // Latest Firefox on macOS Sonoma - "Mozilla/5.0 (Macintosh; Intel Mac OS X 15.7; rv:145.0) Gecko/20100101 Firefox/145.0", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 15.7; rv:145.0) Gecko/20100101 Firefox/147.0", // Latest Edge on Windows - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.3595.76", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36 Edg/144.0.3595.76", // Latest Edge on macOS - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.3595.76", + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36 Edg/144.0.3595.76", // Latest Firefox on Windows - "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:145.0) Gecko/20100101 Firefox/145.0", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:147.0) Gecko/20100101 Firefox/147.0", // Latest Firefox on Linux - "Mozilla/5.0 (X11; Linux i686; rv:145.0) Gecko/20100101 Firefox/145.0", + "Mozilla/5.0 (X11; Linux i686; rv:147.0) Gecko/20100101 Firefox/147.0", // Latest Chrome on Windows - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36", ])("should not warn for supported browsers", testUserAgentFactory()); it.each([ diff --git a/yarn.lock b/yarn.lock index 2e9835857e..ecae3791dd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5573,10 +5573,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@1.0.30001764, caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001759, caniuse-lite@^1.0.30001760: - version "1.0.30001764" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001764.tgz#03206c56469f236103b90f9ae10bcb8b9e1f6005" - integrity sha512-9JGuzl2M+vPL+pz70gtMF9sHdMFbY9FJaQBi186cHKH3pSzDvzoUJUPV6fqiKIMyXbud9ZLg4F3Yza1vJ1+93g== +caniuse-lite@1.0.30001766, caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001759, caniuse-lite@^1.0.30001760: + version "1.0.30001766" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001766.tgz#b6f6b55cb25a2d888d9393104d14751c6a7d6f7a" + integrity sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA== chalk@4.1.2, chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.2: version "4.1.2" From 7738be32ec284fffe2750842545e2767c74ec9a8 Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Wed, 4 Feb 2026 17:56:08 +0100 Subject: [PATCH 7/9] chore: allow 3px of difference in SC visual tests (#31972) --- packages/shared-components/vitest.config.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/shared-components/vitest.config.ts b/packages/shared-components/vitest.config.ts index 32a0f9ae24..2d5d55bc16 100644 --- a/packages/shared-components/vitest.config.ts +++ b/packages/shared-components/vitest.config.ts @@ -81,7 +81,10 @@ export default defineConfig({ configDir: path.join(dirname, ".storybook"), storybookScript: "storybook --ci", }), - storybookVis({}), + storybookVis({ + // 3px of difference allowed before marking as failed + failureThreshold: 3, + }), ], test: { name: "storybook", From b82c34d9d3ec0e5e61c5bbcf5c485cb58afc4ddd Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Thu, 5 Feb 2026 10:18:02 +0100 Subject: [PATCH 8/9] doc: add note about `Flex` And `Box` in code style (#31962) --- code_style.md | 1 + 1 file changed, 1 insertion(+) diff --git a/code_style.md b/code_style.md index b6c1e46e95..bd1fb4371c 100644 --- a/code_style.md +++ b/code_style.md @@ -274,6 +274,7 @@ Inheriting all the rules of TypeScript, the following additionally apply: 20. Do not use `React.Component::forceUpdate`. 21. Prefer to use [compound typography components](https://compound.element.io/?path=/docs/compound-web_typography--docs) instead of raw HTML elements for text. This ensures consistent font usage and letter spacing across the app. 22. If you can't use 21, don't forget to apply the correct CSS classes for font and letter spacing. +23. Prefer to use `Flex` or `Box` components from shared-components for layout instead of raw HTML elements with CSS flexbox styles. ## Stylesheets From 2a8ea7a2308a94f2c56161b798cbb67c2e8b1376 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Thu, 5 Feb 2026 10:24:10 +0100 Subject: [PATCH 9/9] [create-pull-request] automated change (#31976) Co-authored-by: t3chguy <2403652+t3chguy@users.noreply.github.com> --- playwright/testcontainers/synapse.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright/testcontainers/synapse.ts b/playwright/testcontainers/synapse.ts index d68dddf672..e5b962ab86 100644 --- a/playwright/testcontainers/synapse.ts +++ b/playwright/testcontainers/synapse.ts @@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details. import { SynapseContainer as BaseSynapseContainer } from "@element-hq/element-web-playwright-common/lib/testcontainers"; -const TAG = "develop@sha256:9abab158a1cd7af619d5889fc8c83496e569e647068a8b856f4ad05e8cf342e8"; +const TAG = "develop@sha256:4620e446582e79a3942f5438ebf714da18c281143496e53be318334b4697b449"; /** * SynapseContainer which freezes the docker digest to stabilise tests,