Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ kalosm-sound = { git = "https://github.com/floneum/floneum", rev = "52967ae", de
kalosm-streams = { git = "https://github.com/floneum/floneum", rev = "52967ae" }

deepgram = { version = "0.6.8", default-features = false }
libsql = "0.9.8"
libsql = "0.9.17"

block2 = "0.6"
objc2 = "0.6"
Expand Down
6 changes: 4 additions & 2 deletions apps/desktop/src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ pub async fn main() {
tauri::async_runtime::set(tokio::runtime::Handle::current());

{
let env_filter =
EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| {
EnvFilter::new("info")
.add_directive("ort::logging=error".parse().unwrap())
});
Comment on lines +20 to +23
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix formatting issue flagged by pipeline.

The logging configuration logic is correct - it maintains the default "info" level while specifically setting "ort::logging" to "error" level, which coordinates well with the ONNX crate changes. However, the pipeline indicates a formatting issue that needs to be resolved.

Please run the formatter to fix the dprint formatting issue:

dprint fmt
🤖 Prompt for AI Agents
In apps/desktop/src-tauri/src/lib.rs around lines 20 to 23, the code formatting
does not comply with the project's style guidelines, causing a pipeline
formatting error. To fix this, run the dprint formatter tool by executing
"dprint fmt" in the project root directory to automatically correct the
formatting issues in this file.


tracing_subscriber::Registry::default()
.with(fmt::layer())
Expand Down
170 changes: 141 additions & 29 deletions apps/desktop/src/components/editor-area/note-header/listen-button.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
import { Trans } from "@lingui/react/macro";
import { useMutation, useQuery } from "@tanstack/react-query";
import { MicIcon, MicOffIcon, PauseIcon, PlayIcon, StopCircleIcon, Volume2Icon, VolumeOffIcon } from "lucide-react";
import {
Check,
ChevronDown,
MicIcon,
MicOffIcon,
Pause,
PlayIcon,
Square,
Volume2Icon,
VolumeOffIcon,
} from "lucide-react";
import { useEffect, useState } from "react";

import SoundIndicator from "@/components/sound-indicator";
Expand Down Expand Up @@ -319,16 +329,14 @@ function RecordingControls({

return (
<>
<div className="flex w-full justify-between mb-3">
<AudioControlButton
<div className="flex w-full gap-2 mb-3">
<MicrophoneSelector
isMuted={ongoingSessionMuted.micMuted}
onClick={() => toggleMicMuted.mutate()}
type="mic"
onToggleMuted={() => toggleMicMuted.mutate()}
/>
<AudioControlButton
<SpeakerButton
isMuted={ongoingSessionMuted.speakerMuted}
onClick={() => toggleSpeakerMuted.mutate()}
type="speaker"
/>
</div>

Expand Down Expand Up @@ -361,51 +369,155 @@ function RecordingControls({
onClick={onPause}
className="w-full"
>
<PauseIcon size={16} />
<Pause size={16} />
<Trans>Pause</Trans>
</Button>
<Button
variant="destructive"
onClick={handleStopWithTemplate}
className="w-full"
>
<StopCircleIcon size={16} />
<Square size={16} />
<Trans>Stop</Trans>
</Button>
</div>
</>
);
}

function AudioControlButton({
type,
function MicrophoneSelector({
isMuted,
onToggleMuted,
disabled,
}: {
isMuted?: boolean;
onToggleMuted: () => void;
disabled?: boolean;
}) {
const [isOpen, setIsOpen] = useState(false);
const [selectedDevice, setSelectedDevice] = useState<string>("");

const { data: devices = [], isLoading } = useQuery({
queryKey: ["microphone-devices"],
queryFn: () => listenerCommands.listMicrophoneDevices(),
refetchOnWindowFocus: false,
});

useEffect(() => {
if (!selectedDevice && devices.length > 0) {
setSelectedDevice(devices[0]);
}
}, [devices, selectedDevice]);

const Icon = isMuted ? MicOffIcon : MicIcon;

return (
<div className="flex-1 min-w-0">
<Popover open={isOpen} onOpenChange={setIsOpen}>
<div className="flex -space-x-px">
<Button
variant="outline"
className="rounded-r-none flex-1 min-w-0 h-10"
disabled={disabled}
onClick={onToggleMuted}
>
<Icon
className={cn(
"w-4 h-4 flex-shrink-0",
isMuted ? "text-neutral-500" : "",
disabled && "text-neutral-300",
)}
/>
{!disabled && <SoundIndicator input="mic" size="long" />}
</Button>

<PopoverTrigger asChild>
<Button
variant="outline"
className="rounded-l-none px-0.5 flex-shrink-0"
disabled={disabled}
>
<ChevronDown className="w-4 h-4" />
</Button>
</PopoverTrigger>
</div>

<PopoverContent className="w-64 p-0" align="end">
<div className="p-2">
<div className="mb-2 px-2">
<span className="text-sm font-medium">Microphone</span>
</div>

{isLoading
? (
<div className="p-4 text-center">
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-neutral-600 mx-auto"></div>
<p className="text-sm text-neutral-500 mt-2">Loading devices...</p>
</div>
)
: devices.length === 0
? (
<div className="p-4 text-center">
<p className="text-sm text-neutral-500">No microphones found</p>
</div>
)
: (
<div className="space-y-1">
{devices.map((device) => {
const isSelected = device === selectedDevice;
return (
<Button
key={device}
variant="ghost"
className={cn(
"w-full justify-start text-left h-8 px-2",
isSelected && "bg-neutral-100",
)}
onClick={() => {
setSelectedDevice(device);
setIsOpen(false);
}}
>
<Icon className="w-3 h-3 mr-2 flex-shrink-0" />
<span className="text-sm truncate flex-1">{device}</span>
{isSelected && <Check className="w-3 h-3 ml-auto flex-shrink-0 text-green-600" />}
</Button>
);
})}
</div>
)}
</div>
</PopoverContent>
</Popover>
</div>
);
}
Comment on lines +388 to +494
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Device selection logic is incomplete.

The selectedDevice state is managed but never used to actually change the microphone device. This creates a misleading UI where users can select devices but the selection has no effect.

Add device switching functionality:

 const handleStopWithTemplate = () => {
   const actualTemplateId = selectedTemplate === "auto" ? null : selectedTemplate;
   onStop(actualTemplateId);
 };
+
+const switchMicrophone = useMutation({
+  mutationFn: (deviceId: string) => listenerCommands.setMicrophoneDevice(deviceId),
+});

 onClick={() => {
   setSelectedDevice(device);
+  switchMicrophone.mutate(device);
   setIsOpen(false);
 }}

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In apps/desktop/src/components/editor-area/note-header/listen-button.tsx around
lines 388 to 494, the selectedDevice state is updated on user selection but not
used to switch the actual microphone input device. To fix this, implement logic
that applies the selectedDevice to change the active microphone input. This
likely involves calling a function or command to switch the microphone device
whenever selectedDevice changes, ensuring the UI selection affects the actual
audio input source.


function SpeakerButton({
isMuted,
onClick,
disabled,
}: {
type: "mic" | "speaker";
isMuted?: boolean;
onClick: () => void;
disabled?: boolean;
}) {
const Icon = type === "mic"
? isMuted
? MicOffIcon
: MicIcon
: isMuted
? VolumeOffIcon
: Volume2Icon;
const Icon = isMuted ? VolumeOffIcon : Volume2Icon;

return (
<Button
variant="ghost"
size="icon"
onClick={onClick}
className="w-full"
disabled={disabled}
>
<Icon className={cn(isMuted ? "text-neutral-500" : "", disabled && "text-neutral-300")} size={20} />
{!disabled && <SoundIndicator input={type} size="long" />}
</Button>
<div className="flex-1 min-w-0">
<Button
variant="outline"
onClick={onClick}
className="w-full h-10"
disabled={disabled}
>
<Icon
className={cn("flex-shrink-0", isMuted ? "text-neutral-500" : "", disabled && "text-neutral-300")}
size={16}
/>
{!disabled && <SoundIndicator input="speaker" size="long" />}
</Button>
</div>
);
}
16 changes: 8 additions & 8 deletions apps/desktop/src/locales/en/messages.po
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,8 @@ msgstr "(Beta) Upcoming meeting notifications"
#. placeholder {0}: disabled ? "Wait..." : isHovered ? "Resume" : "Ended"
#: src/components/settings/views/templates.tsx:194
#: src/components/settings/components/wer-modal.tsx:116
#: src/components/editor-area/note-header/listen-button.tsx:179
#: src/components/editor-area/note-header/listen-button.tsx:218
#: src/components/editor-area/note-header/listen-button.tsx:189
#: src/components/editor-area/note-header/listen-button.tsx:228
msgid "{0}"
msgstr "{0}"

Expand Down Expand Up @@ -870,7 +870,7 @@ msgstr "No speech-to-text models available or failed to load."
#~ msgid "No Template"
#~ msgstr "No Template"

#: src/components/editor-area/note-header/listen-button.tsx:342
#: src/components/editor-area/note-header/listen-button.tsx:350
msgid "No Template (Default)"
msgstr "No Template (Default)"

Expand Down Expand Up @@ -939,7 +939,7 @@ msgstr "Optional for participant suggestions"
msgid "Owner"
msgstr "Owner"

#: src/components/editor-area/note-header/listen-button.tsx:365
#: src/components/editor-area/note-header/listen-button.tsx:373
msgid "Pause"
msgstr "Pause"

Expand All @@ -951,7 +951,7 @@ msgstr "people"
msgid "Performance difference between languages"
msgstr "Performance difference between languages"

#: src/components/editor-area/note-header/listen-button.tsx:198
#: src/components/editor-area/note-header/listen-button.tsx:208
msgid "Play video"
msgstr "Play video"

Expand Down Expand Up @@ -995,7 +995,7 @@ msgstr "Required to transcribe other people's voice during meetings"
msgid "Required to transcribe your voice during meetings"
msgstr "Required to transcribe your voice during meetings"

#: src/components/editor-area/note-header/listen-button.tsx:107
#: src/components/editor-area/note-header/listen-button.tsx:117
msgid "Resume"
msgstr "Resume"

Expand Down Expand Up @@ -1093,11 +1093,11 @@ msgstr "Start Annual Plan"
msgid "Start Monthly Plan"
msgstr "Start Monthly Plan"

#: src/components/editor-area/note-header/listen-button.tsx:154
#: src/components/editor-area/note-header/listen-button.tsx:164
msgid "Start recording"
msgstr "Start recording"

#: src/components/editor-area/note-header/listen-button.tsx:373
#: src/components/editor-area/note-header/listen-button.tsx:381
msgid "Stop"
msgstr "Stop"

Expand Down
Loading
Loading