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>
This commit is contained in:
@@ -26,6 +26,7 @@ import {
|
||||
Scroll,
|
||||
Spinner,
|
||||
Text,
|
||||
color,
|
||||
config,
|
||||
toRem,
|
||||
} from 'folds';
|
||||
@@ -122,6 +123,7 @@ import { usePowerLevelTags } from '../../hooks/usePowerLevelTags';
|
||||
import { useComposingCheck } from '../../hooks/useComposingCheck';
|
||||
import { VoiceMessageRecorder } from '../../components/VoiceMessageRecorder';
|
||||
import { PollCreator } from './PollCreator';
|
||||
import { useRoomUnverifiedDeviceCount } from '../../hooks/useDeviceVerificationStatus';
|
||||
|
||||
const GifPicker = React.lazy(() =>
|
||||
import('../../components/GifPicker').then((m) => ({ default: m.GifPicker })),
|
||||
@@ -144,6 +146,15 @@ export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
|
||||
const [isMarkdown] = useSetting(settingsAtom, 'isMarkdown');
|
||||
const [hideActivity] = useSetting(settingsAtom, 'hideActivity');
|
||||
const [legacyUsernameColor] = useSetting(settingsAtom, 'legacyUsernameColor');
|
||||
const [warnOnUnverifiedDevices] = useSetting(settingsAtom, 'warnOnUnverifiedDevices');
|
||||
const crypto = mx.getCrypto();
|
||||
const roomUnverifiedDeviceCount = useRoomUnverifiedDeviceCount(crypto, room);
|
||||
const isEncrypted = room.hasEncryptionStateEvent();
|
||||
const showUnverifiedWarning =
|
||||
warnOnUnverifiedDevices &&
|
||||
isEncrypted &&
|
||||
roomUnverifiedDeviceCount !== undefined &&
|
||||
roomUnverifiedDeviceCount > 0;
|
||||
const direct = useIsDirectRoom();
|
||||
const commands = useCommands(mx, room);
|
||||
const emojiBtnRef = useRef<HTMLButtonElement>(null);
|
||||
@@ -718,6 +729,27 @@ export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
|
||||
requestClose={handleCloseAutocomplete}
|
||||
/>
|
||||
)}
|
||||
{showUnverifiedWarning && (
|
||||
<Box
|
||||
alignItems="Center"
|
||||
gap="200"
|
||||
style={{
|
||||
padding: `${config.space.S100} ${config.space.S300}`,
|
||||
background: color.Warning.Container,
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
size="100"
|
||||
src={Icons.Shield}
|
||||
style={{ color: color.Warning.OnContainer, flexShrink: 0 }}
|
||||
/>
|
||||
<Text size="T200" style={{ color: color.Warning.OnContainer }}>
|
||||
{roomUnverifiedDeviceCount}{' '}
|
||||
{roomUnverifiedDeviceCount === 1 ? 'unverified device' : 'unverified devices'} in this
|
||||
room
|
||||
</Text>
|
||||
</Box>
|
||||
)}
|
||||
<CustomEditor
|
||||
editableName="RoomInput"
|
||||
editor={editor}
|
||||
|
||||
Reference in New Issue
Block a user