fix(calls): harden ML denoise shim against static; fix lint/format
CI / Build & Quality Checks (push) Successful in 10m26s
Trigger Desktop Build / trigger (push) Successful in 17s

ML noise suppression produced loud static on real calls. RNNoise requires
mono 48kHz float input; feeding it stereo or wrong-rate data is the classic
cause of that static. Harden the shim:
- request mono (channelCount:1) + 48kHz capture
- run a 48kHz AudioContext and BAIL to the raw mic if the browser won't
  give a true 48kHz context (wrong-rate data -> static)
- force the worklet node to explicit mono in/out
- use the non-SIMD rnnoise.wasm (SIMD build artifacts on some GPUs)
- share one AudioContext across captures

Also fix the two CI-blocking eslint errors (unused vars in UrlPreviewCard
and useLocalMessageSearch) and apply repo-wide prettier formatting so
check:eslint and check:prettier pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-15 20:50:00 -04:00
parent 5deed79b42
commit 4a401cf816
13 changed files with 388 additions and 357 deletions
@@ -10,7 +10,11 @@ type AvatarDecorationProps = {
inset?: number;
};
export function AvatarDecoration({ userId, children, inset = DEFAULT_INSET }: AvatarDecorationProps) {
export function AvatarDecoration({
userId,
children,
inset = DEFAULT_INSET,
}: AvatarDecorationProps) {
const slug = useAvatarDecoration(userId);
if (!slug) {
@@ -282,9 +282,7 @@ export function PollContent({
style={{
padding: '7px 12px',
borderRadius: '8px',
background: selected
? 'var(--accent-cyan-dim)'
: 'rgba(255,255,255,0.04)',
background: selected ? 'var(--accent-cyan-dim)' : 'rgba(255,255,255,0.04)',
border: `1.5px solid ${selected ? 'var(--accent-cyan)' : 'var(--border-color)'}`,
fontSize: '0.88rem',
lineHeight: 1.4,
@@ -308,9 +306,7 @@ export function PollContent({
inset: 0,
right: 'auto',
width: `${pct}%`,
background: selected
? 'var(--accent-cyan-dim)'
: 'rgba(255,255,255,0.03)',
background: selected ? 'var(--accent-cyan-dim)' : 'rgba(255,255,255,0.03)',
pointerEvents: 'none',
transition: 'width 0.3s ease',
}}
+8 -11
View File
@@ -109,9 +109,7 @@ function HalloweenOverlay({ reduced }: { reduced: boolean }) {
height: `${size}px`,
borderRadius: '50%',
backgroundColor: isOrange ? 'rgba(255,100,0,0.75)' : 'rgba(160,0,255,0.7)',
boxShadow: isOrange
? '0 0 8px rgba(255,100,0,0.5)'
: '0 0 8px rgba(160,0,255,0.5)',
boxShadow: isOrange ? '0 0 8px rgba(255,100,0,0.5)' : '0 0 8px rgba(160,0,255,0.5)',
animation: `${animSeasonFall} ${duration}s ease-in ${delay}s infinite`,
}}
/>
@@ -379,8 +377,9 @@ function LunarNewYearOverlay({ reduced }: { reduced: boolean }) {
position: 'absolute',
left: `${left}%`,
top: `${top}%`,
animation:
reduced ? 'none' : `${animBob} ${duration}s ease-in-out ${delay}s infinite`,
animation: reduced
? 'none'
: `${animBob} ${duration}s ease-in-out ${delay}s infinite`,
}}
>
<div
@@ -419,10 +418,9 @@ function LunarNewYearOverlay({ reduced }: { reduced: boolean }) {
height: '14px',
backgroundColor: '#ffd700',
margin: '0 auto',
animation:
reduced
? 'none'
: `${animTasselSway} ${duration * 0.6}s ease-in-out ${delay}s infinite`,
animation: reduced
? 'none'
: `${animTasselSway} ${duration * 0.6}s ease-in-out ${delay}s infinite`,
transformOrigin: 'top center',
}}
/>
@@ -789,8 +787,7 @@ export function SeasonalPreview({ theme }: { theme: SeasonTheme }) {
export function SeasonalEffect() {
const settings = useAtomValue(settingsAtom);
const reduced =
typeof window !== 'undefined' &&
window.matchMedia('(prefers-reduced-motion: reduce)').matches;
typeof window !== 'undefined' && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
const theme = useMemo<SeasonTheme | null>(() => {
const override = settings.seasonalThemeOverride ?? 'auto';
@@ -1651,7 +1651,6 @@ function GenericCard({
const title = prev['og:title'] ?? '';
const description = prev['og:description'] ?? '';
const siteName = typeof prev['og:site_name'] === 'string' ? prev['og:site_name'] : undefined;
const domain = getDomain(url);
return (
<>
@@ -216,8 +216,7 @@ export function MessageSearch({
// term === undefined → no search started
// term === '' → sender-only search (from:user with no body text)
// term === 'foo' → normal text search
const hasActiveSearch =
msgSearchParams.term !== undefined || !!msgSearchParams.senders?.length;
const hasActiveSearch = msgSearchParams.term !== undefined || !!msgSearchParams.senders?.length;
const senderOnlyMode = !msgSearchParams.term && !!msgSearchParams.senders?.length;
// Run synchronous client-side search immediately.
@@ -534,52 +533,53 @@ export function MessageSearch({
</Box>
)}
{localResult && (senderOnlyMode ? localResult.groups.length > 0 : localResult.encryptedRoomsCount > 0) && (
<Box direction="Column" gap="300">
<Box direction="Column" gap="200">
<Box alignItems="Center" gap="200">
<Icon size="200" src={senderOnlyMode ? Icons.User : Icons.Lock} />
<Text size="H5">{senderOnlyMode ? 'Messages from user' : 'Encrypted Rooms'}</Text>
{!senderOnlyMode && (
<Text size="T200" style={{ opacity: 0.55 }}>
{`${localResult.searchedRoomsCount} / ${localResult.encryptedRoomsCount} cached`}
</Text>
)}
{localResult &&
(senderOnlyMode ? localResult.groups.length > 0 : localResult.encryptedRoomsCount > 0) && (
<Box direction="Column" gap="300">
<Box direction="Column" gap="200">
<Box alignItems="Center" gap="200">
<Icon size="200" src={senderOnlyMode ? Icons.User : Icons.Lock} />
<Text size="H5">{senderOnlyMode ? 'Messages from user' : 'Encrypted Rooms'}</Text>
{!senderOnlyMode && (
<Text size="T200" style={{ opacity: 0.55 }}>
{`${localResult.searchedRoomsCount} / ${localResult.encryptedRoomsCount} cached`}
</Text>
)}
</Box>
<Text size="T300" priority="300">
{senderOnlyMode
? `Showing locally cached messages from this user across all rooms. Open more rooms or load history below to extend coverage.`
: localResult.groups.length > 0
? `Showing locally cached messages from ${localResult.searchedRoomsCount} encrypted room${localResult.searchedRoomsCount !== 1 ? 's' : ''}. Load more history below to extend coverage.`
: `No matches in your local cache. Load messages below to search further back.`}
</Text>
<Line size="300" variant="Surface" />
</Box>
<Text size="T300" priority="300">
{senderOnlyMode
? `Showing locally cached messages from this user across all rooms. Open more rooms or load history below to extend coverage.`
: localResult.groups.length > 0
? `Showing locally cached messages from ${localResult.searchedRoomsCount} encrypted room${localResult.searchedRoomsCount !== 1 ? 's' : ''}. Load more history below to extend coverage.`
: `No matches in your local cache. Load messages below to search further back.`}
</Text>
<Line size="300" variant="Surface" />
{localResult.groups.length > 0 && (
<Box direction="Column" gap="300">
{localResult.groups.map((group) => {
const groupRoom = mx.getRoom(group.roomId);
if (!groupRoom) return null;
return (
<SearchResultGroup
key={group.roomId}
room={groupRoom}
highlights={[msgSearchParams.term ?? '']}
items={group.items}
mediaAutoLoad={mediaAutoLoad}
urlPreview={urlPreview}
onOpen={navigateRoom}
legacyUsernameColor={legacyUsernameColor || mDirects.has(groupRoom.roomId)}
hour24Clock={hour24Clock}
dateFormatString={dateFormatString}
/>
);
})}
</Box>
)}
<EncryptedRoomCachePanel roomIds={localSearchRooms} onLoaded={handleCacheLoaded} />
</Box>
{localResult.groups.length > 0 && (
<Box direction="Column" gap="300">
{localResult.groups.map((group) => {
const groupRoom = mx.getRoom(group.roomId);
if (!groupRoom) return null;
return (
<SearchResultGroup
key={group.roomId}
room={groupRoom}
highlights={[msgSearchParams.term ?? '']}
items={group.items}
mediaAutoLoad={mediaAutoLoad}
urlPreview={urlPreview}
onOpen={navigateRoom}
legacyUsernameColor={legacyUsernameColor || mDirects.has(groupRoom.roomId)}
hour24Clock={hour24Clock}
dateFormatString={dateFormatString}
/>
);
})}
</Box>
)}
<EncryptedRoomCachePanel roomIds={localSearchRooms} onLoaded={handleCacheLoaded} />
</Box>
)}
)}
{error && (
<Box
@@ -75,8 +75,7 @@ export const useLocalMessageSearch = () => {
if (senderOnlyMode) continue;
const evType = event.getType();
const isSticker = evType === 'm.sticker';
const isPoll =
evType === 'm.poll.start' || evType === 'org.matrix.msc3381.poll.start';
const isPoll = evType === 'm.poll.start' || evType === 'org.matrix.msc3381.poll.start';
if (!isSticker && !isPoll) continue;
}
@@ -90,9 +89,7 @@ export const useLocalMessageSearch = () => {
// Sender-only mode: no text filter needed
if (!senderOnlyMode) {
const evType = event.getType();
const isSticker = evType === 'm.sticker';
const isPoll =
evType === 'm.poll.start' || evType === 'org.matrix.msc3381.poll.start';
const isPoll = evType === 'm.poll.start' || evType === 'org.matrix.msc3381.poll.start';
let body = '';
let formattedBody = '';
+1 -5
View File
@@ -37,11 +37,7 @@ export function usePresenceUpdater() {
return mx
.setPresence({
presence: 'unavailable',
...(statusMsg
? { status_msg: statusMsg }
: status
? { status_msg: status }
: {}),
...(statusMsg ? { status_msg: statusMsg } : status ? { status_msg: status } : {}),
})
.catch(() => undefined);
};
+5 -8
View File
@@ -21,14 +21,11 @@ export function useUserNotes(): {
useAccountDataCallback(
mx,
useCallback(
(evt) => {
if (evt.getType() === NOTES_KEY) {
setNotes(evt.getContent<UserNotesContent>() ?? {});
}
},
[],
),
useCallback((evt) => {
if (evt.getType() === NOTES_KEY) {
setNotes(evt.getContent<UserNotesContent>() ?? {});
}
}, []),
);
useEffect(() => {