diff --git a/apps/desktop/src/routes/(window-chrome)/index.tsx b/apps/desktop/src/routes/(window-chrome)/index.tsx index a41452ad..8e0b4d9b 100644 --- a/apps/desktop/src/routes/(window-chrome)/index.tsx +++ b/apps/desktop/src/routes/(window-chrome)/index.tsx @@ -4,7 +4,6 @@ import { createEventListener } from "@solid-primitives/event-listener"; import { cache, createAsync, redirect, useNavigate } from "@solidjs/router"; import { createMutation, createQuery } from "@tanstack/solid-query"; import { getVersion } from "@tauri-apps/api/app"; -import { Window } from "@tauri-apps/api/window"; import { cx } from "cva"; import { Show, @@ -47,7 +46,7 @@ export const route = { }; export default function () { - const options = createOptionsQuery(); + const { options, setOptions } = createOptionsQuery(); const windows = createQuery(() => listWindows); const videoDevices = createVideoDevicesQuery(); const audioDevices = createQuery(() => listAudioDevices); @@ -179,7 +178,7 @@ export default function () { if (!item || !options.data) return; - commands.setRecordingOptions({ + setOptions({ ...options.data, audioInputName: item.name !== "No Audio" ? item.name : null, }); @@ -247,7 +246,7 @@ export default function () { value={selectedWindow() ?? null} onChange={(d: CaptureWindow | null) => { if (!d || !options.data) return; - commands.setRecordingOptions({ + setOptions({ ...options.data, captureTarget: { variant: "window", ...d }, }); @@ -265,7 +264,7 @@ export default function () { return; } if (s === "screen") { - commands.setRecordingOptions({ + setOptions({ ...options.data, captureTarget: { variant: "screen" }, }); @@ -330,12 +329,12 @@ export default function () { if (!options.data) return; if (!item || !item.isCamera) { - await commands.setRecordingOptions({ + await setOptions({ ...options.data, cameraLabel: null, }); } else { - await commands.setRecordingOptions({ + await setOptions({ ...options.data, cameraLabel: item.name, }); @@ -401,7 +400,7 @@ export default function () { return requestPermission("camera"); } if (!options.data?.cameraLabel) return; - commands.setRecordingOptions({ + setOptions({ ...options.data, cameraLabel: null, }); @@ -492,14 +491,14 @@ export default function () { if (permissions?.data?.microphone !== "granted") { await requestPermission("microphone"); if (permissions?.data?.microphone === "granted") { - commands.setRecordingOptions({ + setOptions({ ...options.data!, audioInputName: audioDevice().name, }); } } else { if (!options.data?.audioInputName) return; - commands.setRecordingOptions({ + setOptions({ ...options.data, audioInputName: null, }); diff --git a/apps/desktop/src/routes/camera.tsx b/apps/desktop/src/routes/camera.tsx index 0cdb3e10..6613870b 100644 --- a/apps/desktop/src/routes/camera.tsx +++ b/apps/desktop/src/routes/camera.tsx @@ -19,7 +19,6 @@ import { ToggleButton as KToggleButton } from "@kobalte/core/toggle-button"; import { cx } from "cva"; import { createOptionsQuery } from "~/utils/queries"; -import { commands } from "~/utils/tauri"; import { createImageDataWS, createLazySignal } from "~/utils/socket"; namespace CameraWindow { @@ -37,7 +36,7 @@ const BAR_HEIGHT = 56; const { cameraWsPort } = (window as any).__CAP__; export default function () { - const options = createOptionsQuery(); + const { options, setOptions } = createOptionsQuery(); const [state, setState] = makePersisted( createStore({ @@ -133,7 +132,7 @@ export default function () {
{ - commands.setRecordingOptions({ + setOptions({ ...options(), cameraLabel: null, }); diff --git a/apps/desktop/src/utils/queries.ts b/apps/desktop/src/utils/queries.ts index b6d9ec1f..2c5f48fa 100644 --- a/apps/desktop/src/utils/queries.ts +++ b/apps/desktop/src/utils/queries.ts @@ -1,10 +1,10 @@ import { createQuery, queryOptions } from "@tanstack/solid-query"; -import { createTimer } from "@solid-primitives/timer"; -import { commands } from "./tauri"; +import { commands, RecordingOptions } from "./tauri"; import { createQueryInvalidate } from "./events"; import { createStore, reconcile } from "solid-js/store"; -import { createMemo } from "solid-js"; +import { createEffect, createMemo } from "solid-js"; +import { makePersisted } from "@solid-primitives/storage"; export const listWindows = queryOptions({ queryKey: ["capture", "windows"] as const, @@ -64,15 +64,48 @@ export const getPermissions = queryOptions({ refetchInterval: 1000, }); +type PartialRecordingOptions = Omit; export function createOptionsQuery() { - const options = createQuery(() => getOptions); + const KEY = "recordingOptionsQuery"; + const localState = localStorage.getItem(KEY); + const [state, setState, _init] = makePersisted( + createStore( + localState + ? JSON.parse(localState) + : { + cameraLabel: null, + audioInputName: null, + } + ) + ); + + const setOptions = (newOptions: RecordingOptions) => { + commands.setRecordingOptions(newOptions); + const { captureTarget: _, ...partialOptions } = newOptions; + setState(partialOptions); + }; + + createEffect(() => { + localStorage.setItem(KEY, JSON.stringify(state)); + }); + + const options = createQuery(() => ({ + ...getOptions, + select: (data) => { + if (data && state) { + return { ...data, ...state }; + } + }, + })); + createQueryInvalidate(options, "recordingOptionsChanged"); - return options; + return { options, setOptions }; } export function createCurrentRecordingQuery() { const currentRecording = createQuery(() => getCurrentRecording); + createQueryInvalidate(currentRecording, "currentRecordingChanged"); return currentRecording;