Commit Graph
731 Commits
Author SHA1 Message Date
Jannis Braun becd5c8ac8 fix: exempt existing DM members from friend check in createGroup
When converting a 1-on-1 DM to a group, the existing DM partner was
incorrectly required to be your friend. DMs don't require friendship,
so this check was over-strict. Added fromDmChannelId parameter to
createGroup — existing members of the source DM are exempt from the
friendship validation.
2026-03-27 02:48:26 +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 d11923f6a5 fix: remove unused import and guard URL parsing in AddDmMemberModal
Remove unused TaggedFriend type import. Wrap new URL() in try/catch
for federation origin display to handle malformed _instanceOrigin.
2026-03-27 02:32:13 +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 06f8ffb37d feat: overhaul AddDmMemberModal with friends-only multi-select
Replace global user search with socialStore friends list, fixing
federation ID mismatch that caused false 'not your friend' errors.
Add multi-select with chips, immediate friend list display, and
client-side search filtering.
2026-03-27 02:26:36 +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 b8a41c4484 fix: update discoverStore on friend accept and remove WS events
The friend_request_accepted and friend_removed WS handlers updated
socialStore but not discoverStore, so the discovery page buttons
stayed stale until page refresh. Decline/cancel already updated
both stores correctly.
2026-03-27 01:24:14 +01:00
Jannis Braun 660505b954 feat(federation): use isSelf and identity objects in AddDmMemberModal
Replace myUserId with full myUser object so isSelf() can handle cross-instance
identity matching when finding the other 1-on-1 DM member. Pass GroupDmUserIdentity
objects (id, homeUserId, homeInstance) to api.dm.createGroup instead of raw id strings.
2026-03-26 23:18:23 +01:00
Jannis Braun bf8fc589f9 fix(dm): populate store before navigating to new group DM
addDmChannel must be called before navigate() so the route effect
finds the channel in the store immediately. Without this, the chat
view renders empty until the WS dm_channel_created event arrives.
Also show an error instead of silently returning when otherMember
cannot be determined.
2026-03-26 22:36:21 +01:00
Jannis Braun be20f23500 feat(frontend): add createGroup API method and update AddDmMemberModal branching
- Add CreateGroupDmRequest to API client imports, type declaration, and implementation (POST /dm/group)
- Update AddDmMemberModal to branch on channel type: 1-on-1 DMs call createGroup and navigate to new channel, group DMs call addMember directly
- Remove legacy getApiForOrigin/channelOriginMap usage — S2S federation relay is now entirely server-side
2026-03-26 22:32:30 +01:00
Jannis Braun 6a83b6c6a5 fix(federation): compute relay targets before member deletion in leave handler
getGroupDmTargetOrigins() was called after the leaving user's dm_members row
was deleted, causing their instance to be excluded from member_remove and
ownership_transfer relay fan-out if they were the only member from that peer.
Move the target origins and leaving user lookups to before the deletion.
2026-03-26 20:19:55 +01:00
Jannis Braun 523cb0c4b3 fix(federation): deduplicate relay DM messages in chatStore
When a user has federated WS connections, they can receive both the
original message (from their home instance) and the relay copy (from the
remote instance). The relay copy has a different message ID but carries
sourceMessageId pointing to the original. The dedup now checks both
directions: incoming relay copy vs existing original, and incoming
original vs existing relay copy.
2026-03-26 17:55:58 +01:00
Jannis Braun f362f5530c fix(federation): prevent duplicate DM sidebar entries from relay broadcasts
When a relay-created dm_message_created arrives for an unknown channel,
check if an existing DM has the same member (by homeUserId). If so,
route the message to the existing channel instead of adding a duplicate
sidebar entry. Prevents the transient duplicate that required page
refresh to dedup.
2026-03-26 14:45:04 +01:00
Jannis Braun 73a4b69fe6 fix(federation): auto-peering on reconnect and DM deduplication across origins 2026-03-26 03:59:59 +01:00
Jannis Braun 44de9b6f41 feat(federation): add client peering integration, transparency indicator, and admin federation settings
Task 13: Hook server-to-server peering into connectToRemote (non-fatal)
and add federation API namespace to the client (initiate, peers, revoke).

Task 14: Show a transparency notice in the DM welcome header when the
other user is on a remote instance, informing that messages are stored
on both home instances and are not end-to-end encrypted.

Task 15: Add Federation section to the instance settings General panel
with DM relay toggle, TTL config, and a live peer list with revoke
buttons. Also extends InstanceAdminSettings type and the server settings
route to support federationRelayEnabled / federationRelayTtlDays.
2026-03-25 21:47:10 +01:00
Jannis Braun a1363a1ab3 fix: match GIF-only message size to standard media constraints
GIFs from Klipy were capped at 250×250px while all other visual media
(attachments, image embeds) used 400×300px. Unified to 400×300px.
2026-03-25 14:42:27 +01:00
Jannis Braun f7fa7371d6 fix: hide Open Original when sourceUrl is present to avoid redundancy 2026-03-25 05:13:14 +01:00
Jannis Braun e0d45da97c refactor: skip imageEmbedSourceUrl computation when isGifOnly is true 2026-03-25 05:05:49 +01:00
Jannis Braun 4fd72cd29b fix: remove redundant !isEditing guard in image-embed-only branch 2026-03-25 05:02:38 +01:00
Jannis Braun 001d45da2b feat: suppress URL text for image-only messages, add sourceUrl to context menu 2026-03-25 04:59:53 +01:00
Jannis Braun 5c45a55ef7 fix: add clipboard error handling for Copy Link context menu item 2026-03-25 04:58:27 +01:00
Jannis Braun d1fad2b262 feat: add sourceUrl param to context menu with Copy Link and Open Link items 2026-03-25 04:55:44 +01:00
Jannis Braun f433093777 fix: remove 150px threshold from scroll observers
The dist < 150 check caused the ResizeObserver and media load
listener to miss large layout shifts (e.g., GIF loading adding
400+ px of height). The isAtBottomRef gate already determines
whether to auto-scroll — the pixel threshold is redundant.
2026-03-25 04:50:24 +01:00
Jannis Braun f0104d19b7 feat: conditionally show bitrate slider based on instance allowCustomBitrate 2026-03-25 04:09:18 +01:00
Jannis Braun 3627974ba1 feat: add Allow Custom Bitrate toggle to admin streaming panel 2026-03-25 04:08:10 +01:00
Jannis Braun de6db687c4 feat: enforce allowCustomBitrate flag in stream option builders 2026-03-25 04:07:15 +01:00
Jannis Braun 64d919c765 feat: add allowCustomBitrate to DEFAULT_LIMITS in settingsStore 2026-03-25 04:05:50 +01:00
Jannis Braun c60fb5af6d fix: resolve chat scroll race condition on channel open
Remove isAtBottom state from scroll effect deps to break the
re-triggering feedback loop. Use isAtBottomRef (ref) instead.
Gate ResizeObserver and media load effects behind the ref so
they only auto-scroll after the initial snap completes.
2026-03-25 04:03:14 +01:00
Jannis Braun dae6f2d518 fix: remove forced 4/3 aspect ratio and dark background from image containers
Images now size naturally within max constraints instead of being
letterboxed into a 4/3 bg-surface-input container. Fixes dark bars
on GIFs and images whose aspect ratio doesn't match 4/3.
2026-03-25 03:37:18 +01:00
Jannis Braun c255b0066a fix: copy GIF URLs as text to preserve animation
PNG conversion strips GIF animation. GIFs are now detected by URL
pattern (.gif extension or Tenor/Klipy CDN) and copied as URL text
instead, so pasting back into chat re-renders the animated GIF.
2026-03-25 03:28:00 +01:00
Jannis Braun aeb4ea6e1d fix: exclude embed thumbnails from image context menu actions
Add data-embed-thumbnail marker to VideoEmbed, GenericEmbed, and
RichEmbed thumbnail containers. Update detection logic to skip
these alongside avatars. Also remove redundant filename derivation
in Save Image menu item.
2026-03-25 03:23:23 +01:00
Jannis Braun 4ea319646a feat: add save/copy buttons to image preview modal 2026-03-25 03:19:17 +01:00
Jannis Braun 91ffbb5d0a fix: add noopener to window.open fallback in saveImage 2026-03-25 03:15:54 +01:00
Jannis Braun 97f0ebc915 feat: add image actions to message context menu
Detect right-clicked images in handleContextMenu and prepend
Save Image, Copy Image, and Open Original to the custom menu.
Avatars are excluded via the data-avatar semantic marker.
2026-03-25 03:13:58 +01:00
Jannis Braun 74939f045f feat: add data-avatar attribute for image context menu exclusion 2026-03-25 03:10:37 +01:00
Jannis Braun 6bd2100e04 feat: add saveImage and copyImageToClipboard utilities
Implements image save/download (blob fetch + anchor trigger, fallback to window.open)
and clipboard copy (PNG write via ClipboardItem, fallback to URL text copy) with
toast feedback. Also adds ClipboardItem polyfill and Response.blob() content-type
fix to the jsdom test setup so the clipboard test suite runs correctly.
2026-03-25 03:09:51 +01:00
Jannis Braun 78555a43f8 fix(voice): stabilize grid layout across focus-mode and fullscreen transitions
Refactor useGridLayout from RefObject to callback-ref API so the
ResizeObserver reattaches when the grid container remounts after
focus-mode toggle. Fixes tiles rendering at stale fullscreen dimensions
on 4:3 monitors.

Also clamp focus-mode participant strip height (max-h-[20vh] min-h-[80px])
to prevent it from crowding the focused stream on short viewports.
2026-03-25 03:08:45 +01:00
Jannis Braun 7240aac2e0 fix(social): allow single-char search and prefer native federated profiles
Lower minimum query length from 2 to 1 character so single-letter
searches return results.

Fix dedup to prefer native profiles (homeUserId=null) over replicated
ones. Previously the first-seen result won, which was usually the
local replicated profile (no instance badge, namespaced username).
Now when a native profile is found on the remote instance, it replaces
the replicated copy — showing the clean username with the instance badge.
2026-03-25 02:26:33 +01:00
Jannis Braun f0e72dc257 fix(social): deduplicate federated search results by canonical identity
Replicated profiles on remote instances have different local IDs but
share the same homeUserId as the native profile. Use homeUserId ?? id
as the dedup key so the same person only appears once. Home instance
is queried first, so the native profile (with clean username) wins.
2026-03-25 02:19:51 +01:00
Jannis Braun d59ec4abf2 Merge branch 'feature/unified-friend-search' 2026-03-25 02:07:29 +01:00
Jannis Braun 277b69a732 test(friends): update tests for unified friend search UI
Replace old "Add Friend" form tests (placeholder/button/inline messages) with
new tests for the Find People panel: search input, Direct Add row, toast feedback,
and searchUsers debounce. Also fix ancillary mocks (discoverStore, authStore,
activityStore, ConnectInstanceModal, findExistingDmForUser) required by the
rewritten component.
2026-03-25 02:06:01 +01:00
Jannis Braun a9266a3ad8 feat(friends): rewrite AddFriendTab with unified search
Replace the two separate inputs (direct add + discover search) with a
single unified search field. When the user types, results come from
socialStore.searchUsers() across all connected instances. When empty,
the discover grid is shown as before. A user@instance pattern surfaces
a Direct Add action row for sending friend requests to federated users.

Parent FriendsPage no longer owns add-friend state — it all lives inside
AddFriendTab now, keeping the component self-contained.
2026-03-25 02:01:44 +01:00
Jannis Braun 30c3b9b352 fix(web): add aspect-ratio fallback for markdown inline images 2026-03-25 01:56:33 +01:00
Jannis Braun 970af77169 refactor(friends): extract onRelationshipChange prop from UserDiscoverCard 2026-03-25 01:56:25 +01:00
Jannis Braun 995c71367e fix(web): add aspect-ratio fallback for bare GIF URL messages 2026-03-25 01:56:08 +01:00
Jannis Braun 234ee9cd23 fix(web): add 16:9 aspect-ratio reservation to direct video embeds 2026-03-25 01:55:41 +01:00
Jannis Braun b96c16b622 fix(web): add dimension reservation to ImageEmbed component 2026-03-25 01:55:12 +01:00
Jannis Braun 4e170f0b69 feat(social): add TaggedUser type and origin-tag searchUsers results 2026-03-25 01:54:36 +01:00
Jannis Braun d9094fabe1 feat(ws): re-push activities on new instance connections
When a WS connection receives its ready event, push cached myActivities
to that instance so federated users see activities immediately without
waiting for the next debounce cycle.
2026-03-24 22:00:28 +01:00
Jannis Braun 9705304be9 feat(activity): fan out activity updates to all connected instances
Switch pushActivities and setShowActivity from wsSend (home-only) to
wsSendAll (all instances). Add myActivities cache for re-push on late
connections.
2026-03-24 21:55:45 +01:00