From be3092f484a8a1e5cce5bea313e8a10f1409a6cf Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Tue, 16 Dec 2025 12:36:00 +0000 Subject: [PATCH] Initial work --- package.json | 2 +- src/components/structures/MatrixChat.tsx | 1 + .../rooms/RoomStatusBarViewModel.tsx | 80 +++++++++++-------- src/i18n/strings/en_EN.json | 8 ++ yarn.lock | 32 +++----- 5 files changed, 70 insertions(+), 53 deletions(-) diff --git a/package.json b/package.json index 5075e25257..7212c22adf 100644 --- a/package.json +++ b/package.json @@ -129,7 +129,7 @@ "lodash": "^4.17.21", "maplibre-gl": "^5.0.0", "matrix-encrypt-attachment": "^1.0.3", - "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop", + "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#hs/safety-error-code", "matrix-widget-api": "^1.14.0", "memoize-one": "^6.0.0", "mime": "^4.0.4", diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index 3764051384..faf8f8248c 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -14,6 +14,7 @@ import { HttpApiEvent, type MatrixClient, MatrixEvent, + MatrixSafetyError, MsgType, type RoomType, SyncState, diff --git a/src/components/viewmodels/rooms/RoomStatusBarViewModel.tsx b/src/components/viewmodels/rooms/RoomStatusBarViewModel.tsx index 25c5578d62..1d00cfbe51 100644 --- a/src/components/viewmodels/rooms/RoomStatusBarViewModel.tsx +++ b/src/components/viewmodels/rooms/RoomStatusBarViewModel.tsx @@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details. import { ClientEvent, EventStatus, - type MatrixError, + MatrixSafetyError, type Room, RoomEvent, SyncState, @@ -66,6 +66,24 @@ interface IProps { room: Room; } +export function getTextForSafetyHarm(error: MatrixSafetyError): string { + const translatedStrings = []; + for (const harmCategory of error.harms) { + switch (harmCategory) { + case "org.matrix.msc4387.spam": + // case "m.spam": + translatedStrings.push(_t("room|safety|harms|spam")); + break; + } + } + if (translatedStrings.length > 1) { + return _t("room|safety|harms|multiple"); + } else if (translatedStrings.length === 0) { + return error.data.error ?? _t("room|safety|harms|generic"); + } + return translatedStrings[0]; +} + export function useRoomStatusBarViewModel({ room }: IProps): RoomStatusBarVM { const client = useMatrixClientContext(); const syncState = useTypedEventEmitterState( @@ -77,6 +95,7 @@ export function useRoomStatusBarViewModel({ room }: IProps): RoomStatusBarVM { ); const [isResending, setResending] = useState(false); const unsentMessages = useTypedEventEmitterState(room, RoomEvent.LocalEchoUpdated, () => { + return [{error: new MatrixSafetyError({ harms: ["something.unknown", "other.thing"], errcode: "ORG.MATRIX.MSC4387_SAFETY", expires: Date.now() + 60000})}]; return room.getPendingEvents().filter(function (ev) { const isNotSent = ev.status === EventStatus.NOT_SENT; return isNotSent; @@ -97,46 +116,43 @@ export function useRoomStatusBarViewModel({ room }: IProps): RoomStatusBarVM { }, [room]); const unsentMessagesTitle = useMemo(() => { - let consentError: MatrixError | null = null; - let resourceLimitError: MatrixError | null = null; for (const m of unsentMessages) { if (!m.error) { continue; } if (m.error.errcode === "M_CONSENT_NOT_GIVEN") { - consentError = m.error; - break; + return _t( + "room|status_bar|requires_consent_agreement", + {}, + { + consentLink: (sub) => ( + + {sub} + + ), + }, + ); } if (m.error.errcode === "M_RESOURCE_LIMIT_EXCEEDED") { - resourceLimitError = m.error; - break; + return messageForResourceLimitError( + m.error.data.limit_type, + m.error.data.admin_contact, + { + "monthly_active_user": _td("room|status_bar|monthly_user_limit_reached"), + "hs_disabled": _td("room|status_bar|homeserver_blocked"), + "": _td("room|status_bar|exceeded_resource_limit"), + }, + ); + } + if (m.error instanceof MatrixSafetyError) { + return _t( + "room|safety|message_not_sent_unsafe", { + specificError: getTextForSafetyHarm(m.error) + } + ); } } - if (consentError) { - return _t( - "room|status_bar|requires_consent_agreement", - {}, - { - consentLink: (sub) => ( - - {sub} - - ), - }, - ); - } else if (resourceLimitError) { - return messageForResourceLimitError( - resourceLimitError.data.limit_type, - resourceLimitError.data.admin_contact, - { - "monthly_active_user": _td("room|status_bar|monthly_user_limit_reached"), - "hs_disabled": _td("room|status_bar|homeserver_blocked"), - "": _td("room|status_bar|exceeded_resource_limit"), - }, - ); - } else { - return _t("room|status_bar|some_messages_not_sent"); - } + return _t("room|status_bar|some_messages_not_sent"); }, [unsentMessages]); const hasConnectionError = useMemo(() => { diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index ddd45e35e5..511059eeea 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2111,6 +2111,14 @@ "rejoin_button": "Re-join", "room_content": "Room content", "room_is_low_priority": "This is a low priority room", + "safety": { + "harms": { + "multiple": "The message contained multiple problematic aspects", + "generic": "The server declined to give a reason", + "spam": "The messages are considered spam" + }, + "message_not_sent_unsafe": "The message you are trying to send is unsafe: %(specificError)s" + }, "search": { "all_rooms_button": "Search all rooms", "placeholder": "Search messages…", diff --git a/yarn.lock b/yarn.lock index ae89602239..a5876458ab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1579,17 +1579,8 @@ yaml "^2.7.0" "@element-hq/web-shared-components@link:packages/shared-components": - version "0.0.0-test.11" - dependencies: - "@element-hq/element-web-module-api" "^1.8.0" - "@vector-im/compound-design-tokens" "^6.3.0" - classnames "^2.5.1" - counterpart "^0.18.6" - lodash "^4.17.21" - matrix-web-i18n "^3.4.0" - patch-package "^8.0.1" - react-merge-refs "^3.0.2" - temporal-polyfill "^0.3.0" + version "0.0.0" + uid "" "@emnapi/core@^1.4.3", "@emnapi/core@^1.5.0": version "1.7.0" @@ -2394,10 +2385,10 @@ emojibase "^17.0.0" emojibase-data "^17.0.0" -"@matrix-org/matrix-sdk-crypto-wasm@^15.3.0": - version "15.3.0" - resolved "https://registry.yarnpkg.com/@matrix-org/matrix-sdk-crypto-wasm/-/matrix-sdk-crypto-wasm-15.3.0.tgz#141fd041ae382b793369bcee4394b0b577bdea0c" - integrity sha512-QyxHvncvkl7nf+tnn92PjQ54gMNV8hMSpiukiDgNrqF6IYwgySTlcSdkPYdw8QjZJ0NR6fnVrNzMec0OohM3wA== +"@matrix-org/matrix-sdk-crypto-wasm@^16.0.0": + version "16.0.0" + resolved "https://registry.yarnpkg.com/@matrix-org/matrix-sdk-crypto-wasm/-/matrix-sdk-crypto-wasm-16.0.0.tgz#6cd8cde24a9b374d9d1da3a768becbfc346de37e" + integrity sha512-c+0eu/ckG+ik62CaOFvHAulJlspw2CBKcLrWbiEQsXv4J3PC4xaaDI5VHFAl7FDU+U9Ww2DDNTieszCh4Lk0/Q== "@matrix-org/react-sdk-module-api@^2.4.0": version "2.5.0" @@ -4221,15 +4212,16 @@ classnames "^2.5.1" vaul "^1.0.0" -"@vector-im/matrix-wysiwyg-wasm@link:../../../.cache/yarn/v6/npm-@vector-im-matrix-wysiwyg-2.40.0-53c9ca5ea907d91e4515da64f20a82e5586b882c-integrity/node_modules/bindings/wysiwyg-wasm": +"@vector-im/matrix-wysiwyg-wasm@link:../../.cache/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" resolved "https://registry.yarnpkg.com/@vector-im/matrix-wysiwyg/-/matrix-wysiwyg-2.40.0.tgz#53c9ca5ea907d91e4515da64f20a82e5586b882c" integrity sha512-8LRFLs5PEKYs4lOL7aJ4lL/hGCrvEvOYkCR3JggXYXDVMtX4LmfdlKYucSAe98pCmqAAbLRvlRcR1bTOYvM8ug== dependencies: - "@vector-im/matrix-wysiwyg-wasm" "link:../../../.cache/yarn/v6/npm-@vector-im-matrix-wysiwyg-2.40.0-53c9ca5ea907d91e4515da64f20a82e5586b882c-integrity/node_modules/bindings/wysiwyg-wasm" + "@vector-im/matrix-wysiwyg-wasm" "link:../../.cache/yarn/v6/npm-@vector-im-matrix-wysiwyg-2.40.0-53c9ca5ea907d91e4515da64f20a82e5586b882c-integrity/node_modules/bindings/wysiwyg-wasm" "@vitest/expect@3.2.4": version "3.2.4" @@ -9697,12 +9689,12 @@ matrix-events-sdk@0.0.1: resolved "https://registry.yarnpkg.com/matrix-events-sdk/-/matrix-events-sdk-0.0.1.tgz#c8c38911e2cb29023b0bbac8d6f32e0de2c957dd" integrity sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA== -"matrix-js-sdk@github:matrix-org/matrix-js-sdk#develop": +"matrix-js-sdk@github:matrix-org/matrix-js-sdk#hs/safety-error-code": version "39.3.0" - resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/942fdf5bee0f0303f32c2cae87df6108666bb780" + resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/62515599d64f69ac1b8e5bbd9fba85ffefb21f1b" dependencies: "@babel/runtime" "^7.12.5" - "@matrix-org/matrix-sdk-crypto-wasm" "^15.3.0" + "@matrix-org/matrix-sdk-crypto-wasm" "^16.0.0" another-json "^0.2.0" bs58 "^6.0.0" content-type "^1.0.4"