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>
This commit is contained in:
2026-06-02 19:31:30 -04:00
parent f07ff63ac1
commit afe957015b
11 changed files with 607 additions and 8 deletions
+32
View File
@@ -212,6 +212,17 @@ const RoomNavItemMenu = forwardRef<HTMLDivElement, RoomNavItemMenuProps>(
const [invitePrompt, setInvitePrompt] = useState(false);
const isServerNotice = room.getType() === 'm.server_notice';
const isFavorite = !!room.tags?.['m.favourite'];
const handleToggleFavorite = () => {
if (isFavorite) {
mx.deleteRoomTag(room.roomId, 'm.favourite');
} else {
mx.setRoomTag(room.roomId, 'm.favourite', { order: 0.5 });
}
requestClose();
};
const handleMarkAsRead = () => {
markAsRead(mx, room.roomId, hideActivity);
requestClose();
@@ -273,6 +284,17 @@ const RoomNavItemMenu = forwardRef<HTMLDivElement, RoomNavItemMenuProps>(
</Box>
<Line variant="Surface" size="300" />
<Box direction="Column" gap="100" style={{ padding: config.space.S100 }}>
<MenuItem
onClick={handleToggleFavorite}
size="300"
after={<Icon size="100" src={Icons.Star} filled={isFavorite} />}
radii="300"
aria-pressed={isFavorite}
>
<Text style={{ flexGrow: 1 }} as="span" size="T300" truncate>
{isFavorite ? 'Remove from Favorites' : 'Add to Favorites'}
</Text>
</MenuItem>
<MenuItem
onClick={handleInvite}
variant="Primary"
@@ -381,6 +403,7 @@ function RoomNavItem_({
notificationMode,
linkPath,
}: RoomNavItemProps) {
const isFavorite = !!room.tags?.['m.favourite'];
const mx = useMatrixClient();
const useAuthentication = useMediaAuthentication();
const [hover, setHover] = useState(false);
@@ -499,6 +522,15 @@ function RoomNavItem_({
style={{ opacity: config.opacity.P300, flexShrink: 0 }}
/>
)}
{isFavorite && (
<Icon
size="50"
src={Icons.Star}
filled
aria-label="Favorited"
style={{ opacity: config.opacity.P300, flexShrink: 0 }}
/>
)}
</Box>
{!optionsVisible && !unread && !selected && typingMember.length > 0 && (
<Badge size="300" variant="Secondary" fill="Soft" radii="Pill" outlined>