feat(call): add docked call panel and remote cursor overlay

- Implemented DockedCallPanel component to render the docked call interface when an active call is present.
- Created RemoteCursorOverlay component to display remote cursor positions during screen sharing.
- Added hooks for managing docked call state and remote cursor functionality.
- Introduced pending drag state management for seamless transitions between docked and floating states.
- Developed embed filter management components for personal and room-wide settings, allowing users to customize URL embed visibility.
- Implemented auto-joining functionality for rooms within spaces, enhancing user experience during space navigation.
- Added state management for tracking joining progress of rooms in spaces.
This commit is contained in:
2026-02-19 17:49:48 +11:00
parent bfbdf98468
commit 3f6f2134ad
42 changed files with 3801 additions and 219 deletions

View File

@@ -126,6 +126,11 @@ import { useAccessiblePowerTagColors, useGetMemberPowerTag } from '../../hooks/u
import { useTheme } from '../../hooks/useTheme';
import { useRoomCreatorsTag } from '../../hooks/useRoomCreatorsTag';
import { usePowerLevelTags } from '../../hooks/usePowerLevelTags';
import {
useRoomEmbedFilters,
useRoomWideEmbedFilters,
combineEmbedFilters,
} from '../../hooks/useRoomEmbedFilters';
/** Information about a call member event for grouping */
interface CallEventInfo {
@@ -455,6 +460,12 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
const [urlPreview] = useSetting(settingsAtom, 'urlPreview');
const [encUrlPreview] = useSetting(settingsAtom, 'encUrlPreview');
const showUrlPreview = room.hasEncryptionStateEvent() ? encUrlPreview : urlPreview;
const [personalEmbedFilters] = useRoomEmbedFilters(room);
const roomWideEmbedFilters = useRoomWideEmbedFilters(room);
const combinedEmbedFilters = useMemo(
() => combineEmbedFilters(personalEmbedFilters, roomWideEmbedFilters),
[personalEmbedFilters, roomWideEmbedFilters]
);
const [showHiddenEvents] = useSetting(settingsAtom, 'showHiddenEvents');
const [showDeveloperTools] = useSetting(settingsAtom, 'developerTools');
@@ -1119,6 +1130,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
htmlReactParserOptions={htmlReactParserOptions}
linkifyOpts={linkifyOpts}
outlineAttachment={messageLayout === MessageLayout.Bubble}
disabledEmbedPatterns={combinedEmbedFilters}
/>
)}
</Message>
@@ -1225,6 +1237,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, editor }: RoomTimeli
htmlReactParserOptions={htmlReactParserOptions}
linkifyOpts={linkifyOpts}
outlineAttachment={messageLayout === MessageLayout.Bubble}
disabledEmbedPatterns={combinedEmbedFilters}
/>
);
}

View File

@@ -509,7 +509,17 @@ export const MessageDeleteItem = as<
size="300"
after={<Icon size="100" src={Icons.Delete} />}
radii="300"
onClick={() => setOpen(true)}
onClick={(evt) => {
if (evt.shiftKey) {
const eventId = mEvent.getId();
if (eventId) {
mx.redactEvent(room.roomId, eventId);
onClose?.();
}
} else {
setOpen(true);
}
}}
aria-pressed={open}
{...props}
ref={ref}