Commit Graph
188 Commits
Author SHA1 Message Date
Jannis Braun f33ebe2aa7 chore(web): drop unused React import; static-import idbHandles consistently 2026-05-02 20:54:50 +02:00
Jannis Braun 348800bfca feat(web): channel-header transfer indicator + global tray panel 2026-05-02 17:11:41 +02:00
Jannis Braun 1ed70a90b1 fix(dm): render system messages in sidebar preview instead of raw JSON
DmLastMessagePreview lacked a `type` field, so the sidebar rendered
`lastMessage.content` verbatim — surfacing JSON like
`{"event":"space_invite",...}` for space invites and member-add events.

Adds `type` to the preview payload (populated server-side from
`dm_messages.type`) and routes all sidebar call sites through a single
`formatDmSidebarPreview` helper that renders human-readable text for
each system event and skips the group `Sender:` prefix on system rows.
2026-04-29 23:13:09 +02:00
Jannis Braun c9b08cdfd2 feat(devices): sweep stale persisted device ids on mount and devicechange 2026-04-27 20:30:54 +02:00
Jannis Braun 51ad54fda5 refactor(camera): unify toggle paths through handleCameraAction
- Voice-bar and mobile camera buttons now use the canonical handler
  (fixes mobile no-op and voice-bar wrong-preset bugs)
- Remove dead useLiveKit.toggleCamera
- Add _intentionalCameraOff flag with mark/consume helpers
2026-04-27 20:16:14 +02:00
Jannis Braun de2ef10129 fix(brand): home tile = Element 1 with #000 bg, drop tile lavender
Iterating-by-paint-over wasn't working. Going back to first
principles: the brand IS the badge — full Element 1 mass, mark with
its own internal padding, dark frame around it. That's what reads as
"Backspace" on every other surface (dock, taskbar, favicon, apple-
touch). The sidebar home tile should look the same.

The earlier "ugly grey" complaint about Element 1 in the sidebar
came down to one specific colour mismatch: the source SVG's
#1d1d1b (warm near-black) sat next to the sidebar's #1a1a23 (cool
near-black) and read as an off-grey rectangle. Fix: in the generator,
do a string-replace `#1d1d1b → #000000` on app-icon.svg before
rendering logo.png only — every other output (.icns, .ico, favicons,
PWA) keeps the original brand `#1d1d1b`. Pure black against the
sidebar's #1a1a23 reads as a deliberately darker tile, not a hue
mismatch.

Reverts the SpaceSidebar lavender-tile workaround: with the badge
filling the tile via object-cover, the button's overflow-hidden +
rounded-[20px → 13px] morph already animates the badge cleanly.
backgroundStyle for type === 'dm' returns undefined again; deps trim
back to what they were.

Determinism gate verified — only logo.png changed (other 21 outputs
byte-identical across two regen runs).
2026-04-27 15:39:54 +02:00
Jannis Braun 343fdd6e3d fix(sidebar): home tile uses brand lavender, not neutral grey
Translucent white over the cool-dark sidebar reads as muddy grey;
that's the same root cause as the earlier #1d1d1b warm-grey complaint.
Any unsaturated tint loses against the dark sidebar bg.

Switching the home tile to accent-lavender (RGB 196,181,253 — the
endpoint of the mark's gradient) breaks the grey because saturation
defeats the grey-on-grey muddiness. Lavender also (a) complements
the gradient mark sitting on top, (b) parallels Discord's brand-
coloured home button pattern, and (c) gives the sidebar a clear
semantic colour hierarchy: action = mint, home = lavender (brand),
spaces = user-defined.

Three states escalate by alpha (0.08 / 0.16 / 0.28) so corner-morph
and fill-brightness both signal interaction.
2026-04-27 15:32:48 +02:00
Jannis Braun 695f699ddf fix(sidebar): give home tile visible hover/active feedback
The home/DM tile previously set backgroundStyle to undefined — the
button had no fill, so the existing rounded-[20px] → rounded-[13px]
corner-radius transition had nothing to morph and produced zero
hover/active feedback. The regression became visible after the icon
rebrand: the old logo.png shipped a #1d1d1b rounded-square that
filled the tile and gave it a de-facto background; the new bare-mark
logo is centred with transparent padding, exposing the missing
button bg.

Apply the same pattern as the existing 'action' tile: a translucent
white surface that brightens through three states (rest/hover/active)
so both the corner morph and the fill change are visible. Active
state (rgba 0.10) is the strongest because it signals 'you are on
the home page right now', complementing the existing pill indicator
on the left edge.
2026-04-27 15:27:27 +02:00
Jannis Braun 39028ae56f feat: two-variant DM unreachable indicator for rejected vs awaiting_approval 2026-04-20 15:06:48 +02:00
Jannis Braun 70a421864c feat: DM unreachable member indicators and admin auto-accept peering toggle 2026-04-09 13:58:45 +02:00
Jannis Braun ba7b975bc8 feat: add federatedCallId and callOrigin to client call routing
Enable federated DM calls to route accept/reject/end through the correct
WebSocket connection using callOrigin, and include federatedCallId in all
dm_call payloads for server-side FederatedCallEntry lookup.
2026-04-08 03:26:48 +02:00
Jannis Braun 23517447c3 fix(web): flat separators with wrapper divs, first-row border, DM sidebar title case
- FriendItem/RequestItem: add plain wrapper div so divide-y border
  lands on a non-rounded element (fixes curved separator lines)
- Add border-t to divide-y containers so first row also gets top line
- Remove uppercase from "Direct Messages" in DM sidebar
2026-04-03 00:58:03 +02:00
Jannis Braun d7f82d5496 refactor(web): use DmListItem in ChannelSidebar, align nav item geometry
Replace ~105 lines of inline DM rendering with <DmListItem>.
Update Friends and Coming Soon nav items to rounded-[6px].
2026-04-02 23:50:48 +02:00
Jannis Braun f7b8770cab feat(web): extract DmListItem component with visual refinements
Extracts the inline DM list item rendering (~105 lines) from
ChannelSidebar.tsx into a standalone component. Applies cohesive
hover states, 6px border radius, 44px row height, and a selected-
state accent bar matching ChannelItem's pattern.
2026-04-02 23:44:03 +02:00
Jannis Braun c7c86007c4 feat(web): render smart timestamps and attachment-aware previews in DM sidebar 2026-04-02 18:00:02 +02:00
Jannis Braun 7f3ca4e6d1 feat(web): route DM creation to home instance with federated identity
All DM creation and add-member call sites now use the home api client
and pass homeUserId/homeInstance instead of routing to the remote instance.
Also updates addMember in the API client to accept AddDmMemberRequest.
2026-04-01 12:45:13 +02:00
Jannis Braun 41658ec2ef fix: repair corrupted group DMs, prevent ownerId nulling, show empty groups
Three fixes for group DM data integrity and display:

1. processOwnershipTransferEvent: use resolveOrCreateReplicatedUser instead
   of resolveLocalUser to guarantee a valid ownerId. The previous ?? null
   fallback converted group DMs into 1-on-1s when resolution failed.

2. Self-healing migration: detect group DMs with UUID-format federated_id
   but NULL owner_id (corrupted by the old fallback) and restore owner from
   the first remaining member. Found and repaired 7 across both instances.

3. Sidebar: group DMs with 0 other members (last person standing) now show
   as "Empty Group" instead of being hidden. 1-on-1 DMs with 0 others are
   still correctly filtered out.
2026-03-27 17:38:09 +01:00
Jannis Braun c9c0acf2c4 refactor: remove dead ConfirmDialog copy from space view branch
The leave-group-DM ConfirmDialog in the space/channel sidebar return
path was unreachable — group DMs only render in the DM view branch,
so setLeaveGroupDmId is never called from the space view.
2026-03-27 04:01:50 +01:00
Jannis Braun 6a4dd46729 fix: use ownerId for group DM detection in MobileChatScreen 2026-03-27 03:56:51 +01:00
Jannis Braun fffef6db49 fix: use ownerId for group DM detection in MobileDmsScreen
Also fixes the online-friends DM finder which used members.length === 2,
which would incorrectly match a 2-member group DM.
2026-03-27 03:56:47 +01:00
Jannis Braun 5c08c64e23 fix: use ownerId for group DM detection in DmSearchBar 2026-03-27 03:56:41 +01:00
Jannis Braun bbbbeaa955 fix: use ownerId for group DM detection in MainContent header 2026-03-27 03:56:37 +01:00
Jannis Braun 12d7fb365c feat: add leave confirmation dialog for group DM close button
The X button on group DMs now opens a ConfirmDialog instead of
soft-closing. The right-click 'Leave Group' context menu also
routes through the same confirmation. Prevents dead group DM data
from accumulating when users soft-close instead of leaving.
2026-03-27 03:52:57 +01:00
Jannis Braun 309ab75d5d fix: use ownerId for group DM detection in ChannelSidebar
members.length > 2 caused group DMs to lose their identity when a
member left and only 2 remained. ownerId is the canonical marker set
at group creation and persists through the group's lifecycle.
2026-03-27 03:51:58 +01:00
Jannis Braun 1607a8569c Reapply "fix(federation): normalize federated username display across UI"
This reverts commit 5c3185b69f.
2026-03-27 02:35:55 +01:00
Jannis Braun 5c3185b69f Revert "fix(federation): normalize federated username display across UI"
This reverts commit a9d330f013.
2026-03-27 02:31:42 +01:00
Jannis Braun a9d330f013 fix(federation): normalize federated username display across UI
Use parseFederatedUsername() consistently to show base username instead
of raw user@domain format. Replace inline domain text in Username
component with compact globe icon + tooltip. Add globe icons to DM
header and sidebar for federated users.
2026-03-27 02:23:04 +01:00
Jannis Braun 0d91df166a fix(context-menu): update all checkbox call sites to reactive subscribe+getChecked 2026-03-24 21:48:26 +01:00
Jannis Braun 7693cc737e fix: send voice_leave WS message from mobile disconnect handlers
MobileVoiceFullScreen and MobileVoiceMiniBar were missing voice_leave
(and dm_call_end) WS messages in their disconnect handlers, leaving
the server showing stale voice state. Now matches VoiceControls pattern.
2026-03-23 21:18:34 +01:00
Jannis Braun 9f8a4ffa90 fix: prevent native text selection on mobile long-press
iOS triggered both the app context menu and native text selection overlay
on long-press. Three-layer fix: CSS user-select:none on buttons/[role=button]/
[data-context-menu] elements; non-passive touchstart listener with conditional
preventDefault on context-menu targets; removeAllRanges() at timer fire to
clear any residual selection. Added data-context-menu to all mobile surfaces
that use onContextMenu handlers.
2026-03-23 21:12:06 +01:00
Jannis Braun 241451ca18 feat: gesture-aware voice connection, remove AppLayout auto-connect
Replace the useEffect-based auto-connect pattern in AppLayout with
direct connect/disconnect calls from user gesture contexts. This is
required for iOS (AudioContext.resume + getUserMedia must happen in
a gesture handler) and aligns with tightening autoplay policies on
desktop browsers.

Architecture:
- voiceStore gains connectFn/disconnectFn refs, registered by AppLayout
  from the single useLiveKit() instance.
- All voice join paths (ChannelSidebar, MobileSpacesScreen, MainContent,
  voice_moved WS handler) pass connectFn to joinVoiceChannel().
- All disconnect paths (VoiceControls, voiceActions, MobileVoiceFullScreen,
  MobileVoiceMiniBar, dm_call_ended/rejected WS handlers, ready handler)
  call disconnectFn() directly.
- dm_call_accepted WS handler calls connectFn() to initiate the DM call
  LiveKit connection.
- The 55-line auto-connect useEffect and lastAttemptedRef are removed.
2026-03-23 21:06:19 +01:00
Jannis Braun 8aa66816d8 feat: add MobileVoiceJoinSheet bottom sheet for voice preview 2026-03-23 20:59:26 +01:00
Jannis Braun acf6f6fe99 refactor: align MobileVoiceFullScreen voice state resolution
Brings mute/deafen state resolution in line with VoiceChannel.tsx:
- Use LiveKit participant state (then WS fallback) for mute/deafen instead of only voiceUserStates
- Use local isMuted/isDeafened store values for the current user (self)
- Add spaceMutedUserIds, spaceDeafenedUserIds, permissionMutedUserIds checks
- Render deafened indicator (headphones-slash) when user is deafened vs muted
- Add LiveKit participant username and userId as terminal fallbacks in display name chain
2026-03-23 20:55:51 +01:00
Jannis Braun cd30774596 feat: show inline voice users in mobile sidebar 2026-03-23 20:52:12 +01:00
Jannis Braun f27140f1c8 feat: add space folder support to MobileSpacesScreen
Folder-aware layout resolution, folder icons in space strip,
bottom sheet folder flyout with rename/color/ungroup management.
Full folder CRUD via context menus: create, move to, remove from.
2026-03-23 19:34:24 +01:00
Jannis Braun 0d9ee44eee feat: add federation badges to mobile surfaces
Globe/amber badge on federated space icons, @domain on federated
DM users, home instance on the You screen profile card.
2026-03-23 19:27:39 +01:00
Jannis Braun 32be1bceab feat: add voice participant context menus on mobile
Long-press on voice participants shows moderation items (space mute,
deafen, disconnect, move) and local audio controls (mute, volume).
Skips self and DM calls.
2026-03-23 19:25:41 +01:00
Jannis Braun 937c4b68b2 feat: add leave group context menu on MobileDmsScreen
Long-press on group DMs shows Leave Group option.
2026-03-23 19:24:17 +01:00
Jannis Braun f84b1726bf feat: add context menus to MobileSpacesScreen
Add onContextMenu handlers for space icons (invite, folder management,
transfer, leave), channel items (settings, delete), and category headers
(settings, delete). Includes full folder management handlers.
2026-03-23 19:21:14 +01:00
Jannis Braun 2c372a5d34 fix: three mobile bugs — scroll, GeneralPanel loading, activity tab
1. Chat scroll: add flex flex-col to MobileChatScreen messages wrapper
   so MessageList's flex-1 actually works (parent must be flex container)

2. Instance General panel: add fetchInstanceSettings/fetchStreamingLimits
   to MobileInstancePanel mount (mirrors desktop InstancePanel useEffect)

3. Friends activity: add Activity tab to mobile FriendsPage showing
   friends grouped by activity status (active, online, offline)
2026-03-23 14:56:07 +01:00
Jannis Braun 77a1a7920c feat: add standalone MobileMembersScreen replacing blank member panel
Create MobileMembersScreen that renders space members grouped by role
without depending on desktop memberListOpen flag or hidden md:block.
Add members button to voice full screen header for space channels.
2026-03-23 14:20:06 +01:00
Jannis Braun 54b367924d feat: add drill-down navigation for Instance settings on mobile
Replace inline InstancePanel render with MobileInstancePanel that shows
a navigation list for General, Streaming, Storage, and Users sub-panels.
Each sub-panel pushes onto the mobile screen stack with MobileScreenHeader.
2026-03-23 14:16:56 +01:00
Jannis Braun 7c40a230bc feat: add reusable MobileScreenHeader component
Extracts the back-button header pattern used across all mobile screens
into a single component. Props: title (string), rightActions (ReactNode).
2026-03-23 14:15:04 +01:00
Jannis Braun d8c5e7ff16 fix: restore mobile chat scrolling by fixing height constraint chain
Add overflow-hidden to MobileScreenStack stacked screen wrapper to
establish block formatting context. Add min-h-0 to MobileChatScreen
messages wrapper to override flex min-height: auto default.
2026-03-23 14:14:18 +01:00
Jannis Braun 313ff4ef87 feat: add Nori mascot to mobile empty states 2026-03-22 23:39:16 +01:00
Jannis Braun 4e23cb5bf9 feat: add sleeping Nori mascot to empty DM sidebar 2026-03-22 23:39:13 +01:00
Jannis Braun 895f665da9 feat(keybinds): wire useKeybinds hook into AppLayout 2026-03-22 20:37:45 +01:00
Jannis Braun 537f489432 feat: apply delayed loading to member sidebar skeleton 2026-03-22 03:17:01 +01:00
Jannis Braun 44e8b32c2f feat: apply delayed loading to app boot skeleton 2026-03-22 03:17:00 +01:00
Jannis Braun b6f4659849 feat: apply delayed loading to channel sidebar skeleton 2026-03-22 03:16:47 +01:00