Skip to content

Commit bad266f

Browse files
committed
coderabbit: fixes
1 parent fa32f6f commit bad266f

File tree

15 files changed

+308
-319
lines changed

15 files changed

+308
-319
lines changed

apps/desktop/src/components/editor-area/note-header/listen-button.tsx

Lines changed: 18 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Trans, useLingui } from "@lingui/react/macro";
2-
import { useMutation, useQuery } from "@tanstack/react-query";
2+
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
33
import {
44
CheckIcon,
55
ChevronDownIcon,
@@ -16,6 +16,7 @@ import { useState } from "react";
1616
import SoundIndicator from "@/components/sound-indicator";
1717
import { useHypr } from "@/contexts";
1818
import { useEnhancePendingState } from "@/hooks/enhance-pending";
19+
import { MicrophoneDeviceInfo } from "@/utils/microphone-devices";
1920
import { commands as listenerCommands } from "@hypr/plugin-listener";
2021
import { commands as localSttCommands } from "@hypr/plugin-local-stt";
2122
import { Button } from "@hypr/ui/components/ui/button";
@@ -337,32 +338,6 @@ function AudioControlButton({
337338
);
338339
}
339340

340-
function parseDeviceData(result: string | null | undefined): { devices: string[]; selected?: string[] } | null {
341-
if (!result || !result.startsWith("DEVICES:")) {
342-
return null;
343-
}
344-
345-
const devicesJson = result.substring(8);
346-
try {
347-
const parsedData = JSON.parse(devicesJson);
348-
349-
// Check if it's the new format with devices and selected
350-
if (parsedData && typeof parsedData === "object" && parsedData.devices) {
351-
return parsedData;
352-
}
353-
354-
// Fallback to old format (array of devices)
355-
if (Array.isArray(parsedData)) {
356-
return { devices: parsedData };
357-
}
358-
359-
return null;
360-
} catch (e) {
361-
console.error("Failed to parse device data:", e);
362-
return null;
363-
}
364-
}
365-
366341
function MicControlWithDropdown({
367342
isMuted,
368343
onMuteClick,
@@ -373,6 +348,7 @@ function MicControlWithDropdown({
373348
disabled?: boolean;
374349
}) {
375350
const { t } = useLingui();
351+
const queryClient = useQueryClient();
376352

377353
const Icon = isMuted ? MicOffIcon : MicIcon;
378354

@@ -381,7 +357,7 @@ function MicControlWithDropdown({
381357
queryFn: () => listenerCommands.checkMicrophoneAccess(),
382358
});
383359

384-
const deviceQuery = useQuery({
360+
const deviceQuery = useQuery<MicrophoneDeviceInfo>({
385361
queryKey: ["microphoneDeviceInfo"],
386362
queryFn: async () => {
387363
const result = await listenerCommands.getSelectedMicrophoneDevice();
@@ -390,31 +366,6 @@ function MicControlWithDropdown({
390366
enabled: micPermissionStatus.data === true,
391367
});
392368

393-
const microphoneDevices = useQuery({
394-
queryKey: ["microphoneDevices", deviceQuery.data],
395-
queryFn: async () => {
396-
const result = deviceQuery.data;
397-
return parseDeviceData(result)?.devices || [];
398-
},
399-
enabled: micPermissionStatus.data === true && deviceQuery.data !== undefined,
400-
});
401-
402-
const selectedDevice = useQuery({
403-
queryKey: ["selectedMicrophoneDevice", deviceQuery.data],
404-
queryFn: async () => {
405-
const result = deviceQuery.data;
406-
const parsedData = parseDeviceData(result);
407-
408-
if (parsedData?.selected) {
409-
return parsedData.selected[0] || null; // Get first (and only) selected device
410-
}
411-
412-
// If no parsed data or no selected field, return the original result
413-
return result || null;
414-
},
415-
enabled: micPermissionStatus.data === true && deviceQuery.data !== undefined,
416-
});
417-
418369
const updateSelectedDevice = useMutation({
419370
mutationFn: (deviceName: string | null) => listenerCommands.setSelectedMicrophoneDevice(deviceName),
420371
onSuccess: (_, deviceName) => {
@@ -424,10 +375,10 @@ function MicControlWithDropdown({
424375
duration: 2000,
425376
});
426377

427-
// Force immediate refetch to ensure UI updates instantly
428-
deviceQuery.refetch();
429-
microphoneDevices.refetch();
430-
selectedDevice.refetch();
378+
// Invalidate all microphone-related queries
379+
queryClient.invalidateQueries({ queryKey: ["microphoneDeviceInfo"] });
380+
queryClient.invalidateQueries({ queryKey: ["microphoneDevices"] });
381+
queryClient.invalidateQueries({ queryKey: ["selectedMicrophoneDevice"] });
431382
},
432383
onError: (error, deviceName) => {
433384
const displayName = deviceName === null ? t`System Default` : deviceName;
@@ -437,10 +388,10 @@ function MicControlWithDropdown({
437388
duration: 4000,
438389
});
439390

440-
// Even on error, refresh to show correct state
441-
deviceQuery.refetch();
442-
microphoneDevices.refetch();
443-
selectedDevice.refetch();
391+
// Refresh state even on error
392+
queryClient.invalidateQueries({ queryKey: ["microphoneDeviceInfo"] });
393+
queryClient.invalidateQueries({ queryKey: ["microphoneDevices"] });
394+
queryClient.invalidateQueries({ queryKey: ["selectedMicrophoneDevice"] });
444395
},
445396
});
446397

@@ -450,11 +401,11 @@ function MicControlWithDropdown({
450401
};
451402

452403
const getSelectedDevice = () => {
453-
const currentDevice = selectedDevice.data;
404+
const currentDevice = deviceQuery.data?.selected;
454405
if (!currentDevice) {
455406
return "default";
456407
}
457-
if (microphoneDevices.data && !microphoneDevices.data.includes(currentDevice)) {
408+
if (deviceQuery.data?.devices && !deviceQuery.data.devices.includes(currentDevice)) {
458409
return "default";
459410
}
460411
return currentDevice;
@@ -487,7 +438,7 @@ function MicControlWithDropdown({
487438
variant="ghost"
488439
size="icon"
489440
className="w-6 px-1"
490-
disabled={microphoneDevices.isLoading || updateSelectedDevice.isPending}
441+
disabled={deviceQuery.isLoading || updateSelectedDevice.isPending}
491442
>
492443
<ChevronDownIcon size={12} />
493444
</Button>
@@ -498,14 +449,14 @@ function MicControlWithDropdown({
498449
<Trans>Microphone</Trans>
499450
</div>
500451

501-
{microphoneDevices.isLoading
452+
{deviceQuery.isLoading
502453
? (
503454
<div className="flex items-center gap-2 px-2 py-1.5 text-sm">
504455
<Spinner size={14} />
505456
<Trans>Loading devices...</Trans>
506457
</div>
507458
)
508-
: microphoneDevices.error
459+
: deviceQuery.error
509460
? (
510461
<div className="px-2 py-1.5 text-sm text-red-600">
511462
<Trans>Failed to load microphone devices. Please check permissions.</Trans>
@@ -523,7 +474,7 @@ function MicControlWithDropdown({
523474
{getSelectedDevice() === "default" && <CheckIcon size={16} className="text-green-600" />}
524475
</Button>
525476

526-
{microphoneDevices.data?.map((device) => (
477+
{deviceQuery.data?.devices?.map((device) => (
527478
<Button
528479
key={device}
529480
variant="ghost"

apps/desktop/src/components/settings/views/sound.tsx

Lines changed: 7 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { Button } from "@hypr/ui/components/ui/button";
77
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@hypr/ui/components/ui/select";
88
import { Spinner } from "@hypr/ui/components/ui/spinner";
99
import { cn } from "@hypr/ui/lib/utils";
10+
import { MicrophoneDeviceInfo } from "../../../utils/microphone-devices";
1011

1112
interface PermissionItemProps {
1213
icon: React.ReactNode;
@@ -78,51 +79,19 @@ export default function Sound() {
7879
queryFn: () => listenerCommands.checkSystemAudioAccess(),
7980
});
8081

81-
const deviceQuery = useQuery({
82+
const deviceQuery = useQuery<MicrophoneDeviceInfo>({
8283
queryKey: ["microphoneDeviceInfo"],
8384
queryFn: async () => {
84-
console.log("Attempting to call getSelectedMicrophoneDevice...");
8585
try {
8686
const result = await listenerCommands.getSelectedMicrophoneDevice();
87-
console.log("Device query result:", result);
8887
return result;
8988
} catch (error) {
90-
console.error("Device query failed:", error);
9189
throw error;
9290
}
9391
},
9492
enabled: micPermissionStatus.data === true,
9593
});
9694

97-
const microphoneDevices = useQuery({
98-
queryKey: ["microphoneDevices"],
99-
queryFn: async () => {
100-
const result = deviceQuery.data;
101-
console.log("Processing device query result:", result);
102-
if (result && result.startsWith("DEVICES:")) {
103-
const devicesJson = result.substring(8);
104-
console.log("Devices JSON:", devicesJson);
105-
const devices = JSON.parse(devicesJson) as string[];
106-
console.log("Parsed devices:", devices);
107-
return devices;
108-
}
109-
return [];
110-
},
111-
enabled: micPermissionStatus.data === true && deviceQuery.data !== undefined,
112-
});
113-
114-
const selectedDevice = useQuery({
115-
queryKey: ["selectedMicrophoneDevice"],
116-
queryFn: async () => {
117-
const result = deviceQuery.data;
118-
if (result && result.startsWith("DEVICES:")) {
119-
return null;
120-
}
121-
return result;
122-
},
123-
enabled: micPermissionStatus.data === true && deviceQuery.data !== undefined,
124-
});
125-
12695
const micPermission = useMutation({
12796
mutationFn: () => listenerCommands.requestMicrophoneAccess(),
12897
onSuccess: () => {
@@ -147,13 +116,13 @@ export default function Sound() {
147116
};
148117

149118
const getSelectedDevice = () => {
150-
const currentDevice = selectedDevice.data;
119+
const currentDevice = deviceQuery.data?.selected;
151120
if (!currentDevice) {
152121
return "default";
153122
}
154123

155124
// Check if the selected device is still available
156-
if (microphoneDevices.data && !microphoneDevices.data.includes(currentDevice)) {
125+
if (deviceQuery.data?.devices && !deviceQuery.data.devices.includes(currentDevice)) {
157126
return "default";
158127
}
159128

@@ -203,7 +172,7 @@ export default function Sound() {
203172
<Select
204173
value={getSelectedDevice()}
205174
onValueChange={handleMicrophoneDeviceChange}
206-
disabled={microphoneDevices.isLoading || updateSelectedDevice.isPending}
175+
disabled={deviceQuery.isLoading || updateSelectedDevice.isPending}
207176
>
208177
<SelectTrigger className="w-full">
209178
<SelectValue placeholder={t`Select microphone device`} />
@@ -212,15 +181,15 @@ export default function Sound() {
212181
<SelectItem value="default">
213182
<Trans>System Default</Trans>
214183
</SelectItem>
215-
{microphoneDevices.data?.map((device) => (
184+
{deviceQuery.data?.devices?.map((device) => (
216185
<SelectItem key={device} value={device}>
217186
{device}
218187
</SelectItem>
219188
))}
220189
</SelectContent>
221190
</Select>
222191

223-
{microphoneDevices.isLoading && (
192+
{deviceQuery.isLoading && (
224193
<div className="text-xs text-muted-foreground mt-2">
225194
<Trans>Loading available devices...</Trans>
226195
</div>

0 commit comments

Comments
 (0)