diff --git a/LOTUS_FEATURES.md b/LOTUS_FEATURES.md index 68b5859be..607857e21 100644 --- a/LOTUS_FEATURES.md +++ b/LOTUS_FEATURES.md @@ -1179,6 +1179,10 @@ Links you paste, send, edit, or merely _see_ lose ad/analytics identifiers — ` The syncable subset of Lotus settings (theme, composer toolbar order, notification/quiet-hour preferences, call keys, privacy toggles, …) is mirrored to the `io.lotus.settings` account-data event on the user's own homeserver and applied on every other device. Device-bound keys stay local (`DEVICE_LOCAL_KEYS` in `src/app/utils/settingsSync.ts`: page zoom, media auto-load, animation pause, glassmorphism, noise-suppression tier/model, bitrates, volumes, notification permission, developer tools, PTT mode, camera-on-join, drawer state). Conflicts are last-write-wins on an `updatedAt` stamp forced monotonic per device; a per-account `lastSyncedAt` marker in localStorage stops a device from echoing a snapshot it just applied. **Settings → General → Sync** has the toggle (itself device-local), **Push now** (make this device win everywhere) and **Clear synced copy**. Hook: `src/app/hooks/useSettingsSync.ts`, mounted from `ClientNonUIFeatures`. +### Forwarded messages show their provenance + +A forwarded message used to arrive as if the forwarder had written it. `buildForwardContent` now stamps `io.lotus.forwarded` (`sender`, `origin_server_ts`, `room_id`, `event_id`; forwarding a forward keeps the _original_ stamp) and the timeline (main + threads) renders a reply-style line above the message — **↪ Forwarded from bob in Other Room · 9:05 PM** — which is a button that jumps to the original when you are in the source room; if you are not, it shows only the sender and time (the source room's name is deliberately not shared). Other Matrix clients ignore the key and see the plain content. Component: `src/app/components/message/ForwardedHeader.tsx`. + ### Copy Lotus Link — direct permalinks (Gitea #130) `matrix.to` cannot be pointed at this deployment (its Cinny adapter is hard-coded to `app.cinny.in`; `web-instance[]` only works for Element), so every **Copy Link** (message ⋯ menu, space header menu, sidebar space-tab menu) has a **Copy Lotus Link** beside it that yields `https://chat.lotusguild.org/home//?viaServers=…` (spaces: `//`). Helpers in `src/app/plugins/lotus-permalink.ts` (unit-tested). Lotus links pasted into a room render and click like matrix.to links (`toMatrixToHref` in the HTML parser rewrites them into the existing mention pipeline). Supporting fixes: `/home/` for a room you are already in but that lives under a space or in Direct now redirects to its own route instead of a preview card (this is also the form matrix.to → "Continue in Cinny" produces); `?via=a,b` is accepted as an alias of `?viaServers=` (the matrix.to Cinny adapter emits `via`); and a deep link opened while logged out is honoured after an **OIDC/SSO** login too — the OIDC callback reloads at the app root, which previously discarded the stored path (`takeAfterLoginPath` is now consumed by the index route as well as the password flow). matrix.to stays the default, interoperable link and the Share Room QR is unchanged. diff --git a/src/app/components/message/ForwardedHeader.tsx b/src/app/components/message/ForwardedHeader.tsx new file mode 100644 index 000000000..35a49d844 --- /dev/null +++ b/src/app/components/message/ForwardedHeader.tsx @@ -0,0 +1,71 @@ +import React, { MouseEventHandler } from 'react'; +import { Box, Icon, Icons, Text, as, toRem } from 'folds'; +import { MatrixClient } from 'matrix-js-sdk'; +import classNames from 'classnames'; +import * as css from './Reply.css'; +import { ForwardedMeta } from '../../features/room/message/forwardContent'; +import { getMemberDisplayName } from '../../utils/room'; +import { getMxIdLocalPart } from '../../utils/matrix'; +import { timeDayMonYear, timeHourMinute, today, yesterday } from '../../utils/time'; + +type ForwardedHeaderProps = { + mx: MatrixClient; + meta: ForwardedMeta; + hour24Clock: boolean; + dateFormatString: string; + /** Present when the viewer can open the original (they are in the source room). */ + onJump?: MouseEventHandler; +}; + +/** + * "↪ Forwarded · from in ·