Commit Graph

72 Commits

Author SHA1 Message Date
jared 891f2daf99 feat(P3-6): configurable composer toolbar buttons
CI / Build & Quality Checks (push) Successful in 10m24s
Trigger Desktop Build / trigger (push) Successful in 7s
Each button (Format, Emoji, Sticker, GIF, Location, Poll, Voice,
Schedule) can be individually hidden in Settings → Editor.
All default to on, stored in composerToolbarButtons object.
getSettings deep-merges the nested object so new buttons default
to true for existing users with saved settings.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 13:20:29 -04:00
jared 9447e64e5e feat(P5-4): animated chat backgrounds + pause toggle
5 new CSS-only animated backgrounds in the chat background picker:
- Digital Rain: two-layer vertical stripe scroll with parallax (wide
  stripes at 8s, narrow at 4s via single keyframe with split positions)
- Star Drift: three-layer radial-gradient star field drifting diagonally
- Grid Pulse: neon grid lines that expand/contract (backgroundSize keyframe)
- Aurora Flow: large radial gradient bands sweeping across 200% canvas
- Fireflies: three layers of glowing dots drifting across the viewport

All use vanilla-extract keyframes (GPU-composited transforms/positions,
no canvas, no JS timers). prefers-reduced-motion is respected in
getChatBg() by stripping the animation property at call time. A "Pause
Background Animations" toggle in Settings → Appearance provides an
in-app override for the same purpose.

BG labels de-duplicated ("Digital Rain", "Star Drift", "Aurora Flow")
to avoid the duplicate "Stars" and "Aurora" entries that had appeared.
LIGHT anim-fireflies background corrected from near-black #0a0a10 to
warm white #fffdf0. Four unused keyframe exports removed from
Animations.css.ts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 11:46:16 -04:00
jared c6932b45fb feat: glassmorphism sidebar toggle (P5-3)
Settings → Appearance: "Glassmorphism Sidebar" toggle (off by default).
When enabled, applies backdrop-filter: blur(12px) and a semi-transparent
background to the left sidebar so chat background patterns show through.
SidebarGlass vanilla-extract class in Sidebar.css.ts; wired in
SidebarNav.tsx via classNames conditional.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 22:02:18 -04:00
jared 51a355fe77 feat: extended profile fields, push rule editor, server ACL editor
P2-8: Pronouns (m.pronouns) and Timezone (m.tz) fields in Settings →
Account → Profile; saved via MSC4133 PUT /profile/{userId}/{field};
useExtendedProfile hook fetches both in parallel; UserHero displays
pronouns below display name and timezone string below username

P2-11: Full push rule editor in Settings → Notifications below keyword
rules; covers override/room/sender/underride rule kinds; enable/disable
toggle per rule, human-readable labels for built-in rules, delete button
for custom rules, add-rule form for room and sender rules

P2-12: Server ACL viewer/editor in room settings (Server ACL tab);
reads m.room.server_acl state event; allow/deny server lists with
wildcard validation; allow IP literals toggle; power-level gated
(edit requires sufficient PL, otherwise read-only view)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-03 23:13:33 -04:00
jared ee717e8361 feat: PiP mute indicator, export history, activity log, unverified device warning
- PiP call window: mute overlay using MutationObserver on EC iframe's
  [data-testid="incall_mute"] button (data-kind="primary" = muted),
  same pattern as screenshare detection in CallControl.ts

- P2-4 Export Room History: new tab in room settings — Plain Text / JSON /
  HTML formats, optional date range, progress counter, paginated via
  paginateEventTimeline, blob download; E2EE-aware (skips failed decryptions)

- P2-6 Room Activity Log: new tab in room settings — filterable log of
  m.room.member, m.room.power_levels, m.room.name/topic/avatar/server_acl
  events with human-readable descriptions, relative timestamps, Load More
  pagination

- P2-10 Unverified Device Warning: warnOnUnverifiedDevices setting (default
  off); Warning.Container banner above composer in encrypted rooms with
  unverified devices; toggle in Settings → General → Privacy

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-03 22:13:22 -04:00
jared 5ae84cbeaf feat: P2-3 sort rooms, P2-5 quiet hours, P2-2 custom notification sounds
P2-3 — Sort Non-Space Rooms:
- homeRoomSort: 'recent' | 'alpha' | 'unread' setting (default 'recent')
- factoryRoomIdByUnread comparator: unread rooms first, tie-break by count
- Sort icon button in Rooms NavCategoryHeader opens PopOut menu with
  three options (Recent Activity / A→Z / Unread First), checkmark on active
- Collapsed state still filters to unread-only regardless of sort choice

P2-5 — Notification Quiet Hours:
- quietHoursEnabled / quietHoursStart / quietHoursEnd added to settings
  (defaults: false, '23:00', '08:00')
- isInQuietHours() helper handles both normal and overnight spans;
  start===end treated as zero-length window (disabled) to avoid silent no-op
- Both InviteNotifications and MessageNotifications gate notify() and
  playSound() behind the quiet-hours check
- Settings → Notifications: new Quiet Hours card with Switch + two
  <input type="time"> fields (only shown when enabled)

P2-2 — Custom Notification Sounds:
- messageSoundId / inviteSoundId settings: 'notification'|'invite'|'call'|'none'
- notificationSounds.ts: shared NOTIFICATION_SOUND_MAP (removes duplication
  between ClientNonUIFeatures and SystemNotification — code review fix)
- Audio source updated reactively via useEffect when sound ID changes
- Settings → Notifications: Message Sound + Invite Sound selects expand
  when the master sound toggle is on; each has a ▶ preview button
- playPreview() catches audio.play() rejections (code review fix)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-03 19:41:02 -04:00
jared 3eabc8f4dd fix: auto-clear dropdown unreadable in dark mode
var(--bg-surface-variant) and var(--border-surface-variant) are not
defined in Cinny's vanilla-extract theme, so the select element renders
with a transparent/white background. Also native <option> elements ignore
most inherited CSS.

Fix: use folds color tokens (color.SurfaceVariant.*) for background,
border, and text color; add colorScheme:'dark' so the browser renders
the OS popup with dark styling; apply background+color to <option>
elements as a belt-and-suspenders fallback for browsers that honour it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-03 15:50:05 -04:00
jared e18e089043 revert: remove redundant QuickSwitcher (Ctrl+K already does this better)
The existing SearchModalRenderer (Ctrl+K) is already a polished room/DM
switcher with avatars, unread badges, fuzzy search, and keyboard nav.
Our QuickSwitcher was an inferior duplicate. Removing it entirely:
- Delete QuickSwitcher.tsx
- Remove QuickSwitcherFeature from ClientNonUIFeatures
- Remove quickSwitcherKey from settingsAtom
- Remove Keyboard Shortcuts section from General settings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-03 01:03:50 -04:00
jared 9d4679d260 feat: configurable keybindings for push-to-deafen and quick switcher
- Add deafenKey (default M) and quickSwitcherKey (default P) to settingsAtom
- Settings → Calls: Push to Deafen keybind tile using shared useKeyBind hook
- Settings → Keyboard Shortcuts: new section with Quick Room Switcher keybind
- Extract useKeyBind + keyLabel helpers to reduce duplication in Calls section
- CallControls reads deafenKey from settings (reactive, re-registers on change)
- ClientNonUIFeatures reads quickSwitcherKey from settings (same pattern)
- QuickSwitcher now toggles open/closed on repeat press (Ctrl+key again closes)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-03 00:45:43 -04:00
jared afe957015b feat: P1 features — voice speed, private receipts, room filter, favorites, invite link, poll creation
P1-5: Voice message playback speed toggle (0.75×/1×/1.5×/2×) in AudioContent.tsx
P1-10: Private read receipts toggle in Privacy settings; wired to notifications.ts
P1-3: Room filter input on Home tab and DMs tab (client-side, clears on tab switch)
P1-8: Favorite rooms via m.favourite tag — Favorites section in Home sidebar, star/unstar in right-click menu
P1-9: Room invite link + QR code in room settings (Share Room tile, api.qrserver.com QR)
P1-6: Poll creation modal in composer (PollCreator.tsx, sends m.poll.start)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 19:31:30 -04:00
jared dedbd54199 feat: typing indicator orange dots, push-to-deafen hotkey, night light filter, message length counter
- #108: TypingIndicator reads lotusTerminal setting; applies var(--lt-accent-orange)
  to container so dots inherit via backgroundColor:currentColor
- #100: CallControls registers KeyM as push-to-deafen (e.code, e.repeat guard,
  ownerDocument.body iframe-safe editable check, [callEmbed] dep array)
- P5-5: nightLightEnabled/nightLightOpacity settings; position:fixed rgba(255,140,0)
  overlay inside JotaiProvider; Night Light tile + intensity slider (5–80%) in
  Settings → Appearance
- #101: RoomInput charCount state via Slate onChange + toPlainText; resets on
  room switch; displayed before send button when count > 0

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 15:36:45 -04:00
jared fc9ba03943 fix: remove unused useRoomName import, run prettier on all changed files
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 21:38:35 -04:00
jared 16dddcb9f0 fix: comprehensive P0 quality pass — audit findings resolved
- ReportRoomModal: use mx.reportRoom() SDK method, fix undefined CSS vars
  (--mx-surface/border → folds color tokens), add role/aria-modal/aria-labelledby,
  accessible select/input labels, per-error-code messages, auto-close on success
- About.tsx: clickable matrix_id + email_address links (Text as="a"), AbortController
  cleanup, runtime JSON type guard, loading state, role display for all role values,
  remove classList theming hack, use mx.getHomeserverUrl()
- RoomViewHeader: useLocalRoomName for header title, useReportRoomSupported gate,
  hide Invite/Settings/Report for server notice rooms, isCreator guard on Report,
  FocusTrap returnFocusOnDeactivate on topic overlay, Server Notice chip tooltip
- RoomInput: replace raw <div> with folds <Box> for server notice read-only message
- EditHistoryModal: isRawEditEvent type guard, handle next_batch truncation,
  getVersionBody handles formatted_body (strips HTML for text display),
  role/aria-modal/aria-labelledby accessibility, guard for undefined eventId,
  use config.space tokens (remove var(--mx-spacing-*) strings)
- RoomNavItem: remove duplicate getExistingContent (use exported getLocalRoomNamesContent),
  maxLength={255} on rename input, fix FocusTrap nesting (renameDialog state moved to
  RoomNavItem_, RenameRoomDialog rendered outside menu, menu closes before dialog opens),
  pencil icon opacity via config.opacity.P300
- useRoomMeta: export getLocalRoomNamesContent for reuse
- RoomIntro: useLocalRoomName, formatted topic viewer with Overlay/FocusTrap/RoomTopicViewer
- CallRoomName: useLocalRoomName for consistent rename display in call overlay
- General.tsx: fix #980000/#FF6B00 hardcoded hex → color tokens/CSS vars, URL Preview
  capitalization, improved encrypted preview warning text + Warning chip, add
  description to plain urlPreview setting
- sanitize.ts: fix hex color regex to support 3/4/6/8 digit hex (CSS4 #RGBA, #RRGGBBAA)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 21:30:27 -04:00
jared 134ebb231d feat: server support contact display (MSC1929) and server notices UI
- Settings Help/About fetches /.well-known/matrix/support and displays
  admin contact + support page link (graceful 404 degradation)
- Server notice rooms (m.server_notice) now show a Warning badge in the
  room header and hide the message composer

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 17:15:01 -04:00
jared 572bc6a4c0 feat: add Report Room (MSC4151) and fix URL preview default for encrypted rooms
- Report Room: new ReportRoomModal with reason + category, POST /rooms/{id}/report
- URL preview: encUrlPreview default changed to true; security note added to settings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-01 17:11:21 -04:00
jared bc63714a07 fix/polish: wave 1+2 improvements across six features
B1 - GIF upload progress: spinner on GIF button + disabled state while
     fetch+upload is in flight; clears on success or error
B2 - PiP position persistence: drag end saves left/top to localStorage;
     entering PiP restores saved position (clamped to current viewport)
B3 - PiP snap-to-corner: double-click the PiP overlay snaps to nearest
     corner with a 180ms CSS transition; saves new position
B4 - Device sessions loading state: useOtherUserDevices now returns
     {status:'loading'|'error'|'success', devices} instead of bare
     array; UserDeviceSessions shows spinner while loading
B5 - Device sessions error state: catch in hook sets status:'error';
     panel shows warning icon + 'Could not load sessions' message
B6 - Screenshare fullscreen Safari guard: hide button when
     document.fullscreenEnabled is false (iOS Safari, some mobile)
B7 - Status save error: show critical-coloured error text below Save
     button when saveState.status === AsyncStatus.Error
B9 - Encrypted search coverage counter: 'X / Y cached' badge next to
     'Encrypted Rooms' heading using existing localResult fields
D2 - PiP screenshare spotlight: track auto-spotlight in a ref; release
     spotlight when screenshare ends while in PiP mode

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 17:13:54 -04:00
jared 98cbb32b86 fix: suppress unhandled rejection from saveStatus on rate limit
useAsync re-throws after setting error state, so callers that don't
await or catch the returned promise get an unhandled rejection. Fixes
JAVASCRIPT-REACT-E (429 on presence endpoint).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 19:36:26 -04:00
jared db4a39ff56 refactor: move privacy settings into dedicated Privacy section
Hide Typing & Read Receipts and Hide Online Status were buried in
the Editor section. Extracted into a new Privacy section that sits
between Messages and Calls, where users would naturally look.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 19:31:36 -04:00
jared 08b1a5c2a3 feat: full Discord-style presence tracking
- Announce online immediately on app startup
- Idle detection: unavailable after 10 min of no input, online on return
- Tab visibility: unavailable when hidden, online when focused again
- Page close: offline via fetch+keepalive (survives unload without bfcache penalty)
- hidePresence setting: broadcasts offline and stops all tracking
- Added 'Hide Online Status' toggle in General settings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 19:28:52 -04:00
jared eb283c29ff feat: add character counter to status message input
Shows X/64 below the input. Fades in at 56 chars (warning colour) and
turns critical red at the limit so users always know where they stand.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 16:58:37 -04:00
jared f8ab136492 fix: cap status message length and constrain display overflow
Add maxLength=128 to the status input to prevent absurdly long statuses.
In UserHeroName (profile panel), tighten the status display to LineClamp2,
add overflow:hidden on the container, and use overflowWrap:anywhere so
unbroken strings (emoji chains, URLs) wrap instead of overflowing.
Member list already truncates via the truncate prop.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 16:29:11 -04:00
jared 221bd825b1 fix: import EmojiBoard directly in ProfileStatus to fix emoji selection
React.lazy + Suspense interacted badly with the nested FocusTraps (the
settings Modal500 outer trap and EmojiBoard's inner trap). During the
suspend/resolve cycle targetFromEvent returned undefined, causing
handleGroupItemClick to bail before calling onEmojiSelect.

Switched to a direct import matching MessageEditor and PowersEditor
which both use EmojiBoard inside settings panels without lazy loading.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 16:01:17 -04:00
jared 60cbfec951 fix: emoji picker works + silence 429 presence rate-limit errors
Emoji bug root cause: EmojiBoard wraps itself in a FocusTrap with
clickOutsideDeactivates:true. When the picker was rendered inside
Input's 'after' prop, the FocusTrap treated clicks on the emoji items
as outside-clicks and deactivated (calling requestClose) before the
onEmojiSelect callback fired. Fixed by moving the emoji PopOut to be
a direct sibling of Input in the form row instead of nesting it inside
Input.after — matching the established pattern used in MessageEditor.

429 rate-limit: mx.setPresence() calls in handleClear and the
auto-clear timer effect had no rejection handling, causing unhandled
promise rejections logged to Sentry when Synapse rate-limits presence
updates. Added .catch(() => undefined) to both call sites. Sentry
issue JAVASCRIPT-REACT-E resolved.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 15:20:42 -04:00
jared 90cb70c128 fix: emoji selection appends correctly to status input
When focus moves to the emoji picker the input loses focus, making
selectionStart/selectionEnd unreliable. Replace the cursor-tracking
insertion with a simple functional state updater that always appends
the emoji to the end — reliable and appropriate for a short status field.

Also removes the now-unused inputRef and useRef import.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 13:41:48 -04:00
jared 01a61e3ec2 feat: auto-clear status after configurable duration
Adds an 'Auto-clear after' dropdown to the Status Message settings tile
with options: Never / 30 min / 1 hr / 4 hr / 8 hr / Until midnight /
1 day / 7 days.

How it works:
- On save, stores the expiry timestamp in localStorage keyed by userId
  (lotus-status-expiry-<userId>) and sets expiryTs state
- A single useEffect on expiryTs drives the timer — re-saving cancels
  the previous timer cleanly via useEffect cleanup
- On mount, reads stored expiry from localStorage so auto-clear
  survives page reloads (fires immediately if already expired)
- Manual Clear Status also removes the stored expiry and cancels any
  active timer

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 13:10:46 -04:00
jared e280f0e312 fix: capture emoji button rect before state updater to avoid null currentTarget
React nullifies synthetic event's currentTarget before async state
updater callbacks run. Capture getBoundingClientRect() synchronously
in the onClick handler, then pass the already-computed rect into
setEmojiAnchor.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 13:06:31 -04:00
jared 46da4458ff feat: custom status message — display + editor with emoji picker
- MembersDrawer: show presence.status as small muted text below
  username in every member row (live via useUserPresence)
- UserHero/UserHeroName: accept optional status prop; render below
  the @username handle in user profile popouts
- UserRoomProfile: pass presence?.status down to UserHeroName
- Profile settings: new ProfileStatus tile below Display Name
  * Input with inline emoji picker (lazy-loaded EmojiBoard)
  * Cursor-aware emoji insertion (preserves caret position)
  * Save via mx.setPresence({ status_msg }) / Clear button
  * Pre-fills from current presence; syncs on remote update

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 12:39:51 -04:00
Lotus Bot d3fba1d685 fix: reduce ESLint errors and npm audit vulnerabilities
ESLint (476 → 187 errors):
- Fix import/first: move React.lazy() declarations after all imports in RoomInput.tsx and Router.tsx
- Disable react-hooks v7 React Compiler rules (refs, set-state-in-effect, immutability, purity, use-memo, react-compiler) - not using React Compiler yet
- Add eslint-disable for lotus-terminal.css.ts (no-explicit-any in CSS-in-JS)
- Add eslint-disable for cryptE2ERoomKeys.js (intentional bitwise crypto ops)
- Auto-fix 17 remaining fixable errors

npm audit (14 → 11 vulns, 5 → 3 HIGH in prod):
- Upgrade @giphy/react-components 5.9.4 → 10.1.2, js-fetch-api → 5.8.0, js-types → 5.1.0
- Add npm overrides to force dompurify >=3.3.4 and uuid >=11.1.1 in @giphy/js-util
- CI audit now uses --omit=dev to exclude devDep transitive vulns (lodash in commitizen)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 12:08:50 -04:00
Lotus Bot 266e47f240 chore: upgrade TypeScript 4.9 to 5.9, ESLint 8.29 to 8.57, @typescript-eslint 5 to 7
Resolves all TS2345/TS2347/TS7006 type errors introduced by stricter TypeScript 5.x.
Fix Icons.Settings to Icons.Setting, cast account data returns, fix implicit any.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 11:16:11 -04:00
Lotus Bot 61a1f008d0 chore: upgrade i18next 26, prettier 3, fontsource-variable, domhandler 6, lint-staged 17
- i18next 23->26 + react-i18next 15->17
- prettier 2->3, reformat all files
- replace @fontsource/inter with @fontsource-variable/inter 5, update import path
- domhandler 5->6 (aligns with transitive deps)
- lint-staged 16->17
2026-05-21 23:30:50 -04:00
Lotus Bot 42b9cc2b64 chore: prettier format all files, brotli, Sentry release tagging, CI gates
Prettier: auto-formatted 103 files to fix baseline. Prettier check in CI
  is now a hard gate (removed continue-on-error).

Brotli: installed libnginx-mod-http-brotli-filter/static. Enabled in nginx
  with brotli_static on for pre-compressed assets and comp_level 6.

Sentry releases: deploy script now exports VITE_APP_VERSION=<git-short-sha>
  before building so each Sentry release maps to an exact commit.
  CI also passes github.sha as VITE_APP_VERSION.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 20:49:33 -04:00
Lotus Bot d707c4441c feat(a11y): form input labels (H-6), remaining button labels (C-1)
H-6: aria-label on all form inputs missing accessible names:
  - Login: username, password (already done)
  - Register: username, password, confirm, token, email
  - Password reset: email, new password, confirm password
  - Settings: display name, user ID to ignore, keyword, page zoom,
    date format, device name, backup passwords (new/confirm/restore)
  - Auth: server URL picker input
C-1: additional icon buttons:
  - RoomInput: toolbar toggle (aria-pressed + label)
  - Lobby/Members: scroll to top, toggle member list
  - UIAFlowOverlay: cancel authentication
  - BackupRestore: backup options menu
  - UrlPreview: previous/next preview buttons
  - RoomPacks: undo remove/remove pack buttons
  - RoomViewHeader: start call, member list toggle
  - ServerPicker: change server button

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 12:03:26 -04:00
Lotus Bot 4e80c0a0f5 feat(a11y,perf): comprehensive icon button labels, toolbar a11y, timeline binary search
A11y C-1: aria-label on 30+ remaining icon-only buttons across:
  - settings panels (close, reset, info, expand, remove, undo)
  - editor toolbar (bold, italic, underline, strike, code, spoiler,
    blockquote, code block, ordered/unordered list, headings 1-3)
  - auth stages (cancel buttons in SSO, Password stages)
  - device verification (cancel buttons)
  - password input (show/hide toggle with dynamic label)
  - event readers, account data editor close buttons
  - global emoji packs (add/remove buttons)
Perf-5: Replace O(N×T) getTimelineAndBaseIndex scan with precomputed binary
  search (timelineSegments useMemo) — O(log T) per visible message render

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 21:54:33 -04:00
Lotus Bot d4705f9235 fix(a11y,sec): remove tabIndex=-1 from interactive buttons, npm audit fix
H-3: tabIndex=-1 removed from login info, settings reset, settings info buttons
      + aria-label added to each for screen reader discoverability
SEC: npm audit fix - 18 non-breaking dependency updates (34 vulns -> 16 remaining)
     Remaining 16 require --force (breaking changes, deferred)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 21:47:20 -04:00
root daca1e0cca feat: URL preview TDS styling, settings description update
- UrlPreview.tsx: add data-url-preview attribute for CSS targeting
- lotus-terminal.css.ts: dark cyan border-left accent + transparent bg
  for URL preview cards in TDS mode (dark + light variants)
- General.tsx: mention Escape-to-skip in boot animation description
2026-05-16 02:11:52 -04:00
root 83cbb09bae fix: VideoButton disabled state, PTT listener leak, TS prop errors
- VideoButton now accepts disabled prop with tooltip and visual feedback;
  PrescreenControls passes disabled=true when cameraOnJoin=false
- PTT key listener in settings tracked via ref, cleaned up on unmount,
  guarded against stacking on double-click; useCallback + useRef
- CallControls screenshare cancel button: variant Surface -> Secondary
- General.tsx Box align prop: align -> alignItems (TS2322 fix)
2026-05-15 15:38:02 -04:00
root 038bde8b62 feat(call): PTT, deafen label, camera default off, screenshare confirm, noise suppression setting
- Push to Talk: keydown/keyup binds mic to configurable key (default Space)
  with visual PTT indicator and key-binding UI in Settings > General > Calls
- Camera always defaults OFF on join; cameraOnJoin setting for explicit opt-in
- Deafen button tooltip corrected to Deafen/Undeafen instead of Turn Off/On Sound
- Screenshare confirmation dialog before broadcasting to call participants
- Noise suppression toggle wired from settings through CallEmbed URL params
- CallControl.setMicrophone() public method for programmatic mic control
- Calls settings section added to General settings page

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 11:14:04 -04:00
root dc26e15df1 Audit fixes: Lotus URLs, branding, editor toolbar setting, dynamic version 2026-05-13 23:03:14 -04:00
root 893aa92b38 Deepen TDS integration: full terminal CSS coverage + 3 new backgrounds
Terminal Mode:
- Text selection: orange highlight rgba(255,107,0,0.28)
- Links: cyan (#00D4FF) with orange hover glow (#FF6B00)
- Code/pre: TDS green (#00FF88) on terminal bg, left green border
- Strong/b → orange, em/i → cyan, mark → amber, del → red
- Blockquote: orange left border (matches chat reply quotes)
- HR: cyan border with dim glow
- Input/textarea/[contenteditable] focus: orange glow ring
- Tables: TDS headers (orange+uppercase), cyan borders, hover rows
- List markers: cyan ▸ for ul, orange for ol
- Boot box-drawing alignment fixed (51→52 ═)
- data-theme=\"dark\" set on html element when terminal active
- Updated description: correct TDS palette names
- ▶ Boot replay button in settings (visible when terminal on)

Chat backgrounds (+3):
- Tactical: LotusGuild TDS exact cyan dot-grid (28px)
- Circuit: green grid + node dots on dark terminal bg
- Hex Grid: isometric cyan hexagonal outlines

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 22:44:34 -04:00
root f3ec49fe88 Add Lotus Terminal Mode + fix all remaining Cinny branding
- New: Lotus Terminal Mode toggle in Appearance settings
  - Red phosphor color scheme (bg #0a0000, primary #ff3300, accent #00dd66)
  - Monospace font override (JetBrains Mono / Fira Code / Cascadia Code)
  - Retro CRT scanline overlay via CSS pseudo-element
  - Wired into ThemeManager with dedicated lotusTerminalBodyClass
- Branding: replace all user-visible Cinny references with Lotus Chat
  - WelcomePage, AuthLayout, SplashScreen, index.html meta tags
  - Device display names in login/register/token flows
  - System notification brand field
  - (Preserved internal Matrix protocol CinnySpaces event type)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 22:22:06 -04:00
root d67fe80906 Backgrounds: theme-aware patterns and visual preview grid 2026-05-13 21:51:19 -04:00
root 0df997eecf Redesign chat backgrounds: blueprint, carbon, stars, topographic, herringbone, crosshatch 2026-05-13 21:42:12 -04:00
root dcb3ff3129 Phase 2+3: Chat backgrounds and per-message profiles settings 2026-05-13 21:17:59 -04:00
root ccc919d2c8 Use official Lotus.png logo in About and Auth pages 2026-05-13 19:53:29 -04:00
root 5d984a4af4 Phase 1: Lotus Chat branding — title, favicon, logo, meta tags, SVG icons, all icon sizes 2026-05-13 17:56:39 -04:00
Krishan a1053ce8f1 chore(release): v4.11.1 [skip ci] (#2765)
* chore(release): 4.11.0 [skip ci]

* chore(release): 4.11.1 [skip ci]
2026-03-11 23:07:37 +11:00
Krishan d24ad8374b chore(release): 4.11.0 [skip ci] 2026-03-11 04:03:48 +00:00
Krishan 449b2c5a5e Release v4.10.5 (#2692) 2026-02-23 23:05:01 +11:00
Krishan bc80365ba0 Release v4.10.4 (#2688) 2026-02-23 22:32:06 +11:00
Krishan 88c8b0eea8 Release v4.10.3 (#2608) 2026-02-16 22:19:21 +11:00