From 108e30a11c47fb6bbf3f392349dd37fc3d1dc8dd Mon Sep 17 00:00:00 2001 From: pochoclin Date: Thu, 2 Oct 2025 15:50:54 -0400 Subject: [PATCH] feat: optional telemetry (#3131) --- Cargo.lock | 8 + apps/desktop/package.json | 1 + apps/desktop/src/components/header.tsx | 24 +- .../src/components/modal/preferences.tsx | 21 +- .../desktop/src/components/modal/settings.tsx | 144 +++++++++ .../src/components/onboarding/timeline.tsx | 8 +- apps/desktop/src/layout.tsx | 3 +- apps/desktop/src/loaders/settings.test.tsx | 6 +- apps/desktop/src/loaders/settings.tsx | 4 +- apps/desktop/src/metrics.tsx | 39 +++ apps/desktop/src/providers.tsx | 37 +-- apps/desktop/src/routes/splash.test.tsx | 12 +- apps/desktop/src/routes/splash.tsx | 2 +- apps/desktop/src/stores/global.test.ts | 4 +- apps/desktop/src/stores/global.ts | 30 +- apps/desktop/src/tauri/types.ts | 34 ++- crates/popcorntime-session/Cargo.toml | 2 +- crates/popcorntime-settings/Cargo.toml | 5 + crates/popcorntime-settings/src/lib.rs | 77 +++++ crates/popcorntime-tauri/Cargo.toml | 1 + crates/popcorntime-tauri/dictionaries.lock | 286 ++++++++++++++++-- crates/popcorntime-tauri/dictionaries/ar.json | 15 +- crates/popcorntime-tauri/dictionaries/da.json | 15 +- crates/popcorntime-tauri/dictionaries/de.json | 15 +- crates/popcorntime-tauri/dictionaries/el.json | 15 +- crates/popcorntime-tauri/dictionaries/en.json | 15 +- crates/popcorntime-tauri/dictionaries/es.json | 15 +- crates/popcorntime-tauri/dictionaries/et.json | 15 +- crates/popcorntime-tauri/dictionaries/fa.json | 15 +- crates/popcorntime-tauri/dictionaries/fi.json | 15 +- crates/popcorntime-tauri/dictionaries/fr.json | 15 +- crates/popcorntime-tauri/dictionaries/ga.json | 15 +- crates/popcorntime-tauri/dictionaries/he.json | 15 +- crates/popcorntime-tauri/dictionaries/hi.json | 15 +- crates/popcorntime-tauri/dictionaries/it.json | 15 +- crates/popcorntime-tauri/dictionaries/ja.json | 15 +- crates/popcorntime-tauri/dictionaries/nl.json | 15 +- crates/popcorntime-tauri/dictionaries/no.json | 15 +- crates/popcorntime-tauri/dictionaries/pl.json | 15 +- crates/popcorntime-tauri/dictionaries/pt.json | 15 +- crates/popcorntime-tauri/dictionaries/sr.json | 15 +- crates/popcorntime-tauri/dictionaries/sv.json | 15 +- crates/popcorntime-tauri/dictionaries/tr.json | 15 +- crates/popcorntime-tauri/dictionaries/ur.json | 15 +- crates/popcorntime-tauri/src/lib.rs | 1 + crates/popcorntime-tauri/src/main.rs | 20 +- crates/popcorntime-tauri/src/session.rs | 14 - crates/popcorntime-tauri/src/settings.rs | 32 ++ packages/popcorntime-ui/package.json | 9 +- .../popcorntime-ui/src/components/switch.tsx | 27 ++ pnpm-lock.yaml | 82 ++++- 51 files changed, 1087 insertions(+), 191 deletions(-) create mode 100644 apps/desktop/src/components/modal/settings.tsx create mode 100644 apps/desktop/src/metrics.tsx create mode 100644 crates/popcorntime-tauri/src/settings.rs create mode 100644 packages/popcorntime-ui/src/components/switch.tsx diff --git a/Cargo.lock b/Cargo.lock index 5a46f2d89..5cec71919 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3731,6 +3731,13 @@ dependencies = [ [[package]] name = "popcorntime-settings" version = "0.0.1" +dependencies = [ + "anyhow", + "serde", + "specta", + "tokio", + "toml 0.9.7", +] [[package]] name = "popcorntime-tauri" @@ -3744,6 +3751,7 @@ dependencies = [ "popcorntime-error", "popcorntime-graphql-client", "popcorntime-session", + "popcorntime-settings", "popcorntime-tauri-splash", "serde", "serde_json", diff --git a/apps/desktop/package.json b/apps/desktop/package.json index a8a024c4f..395156ccc 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -25,6 +25,7 @@ "i18next-resources-to-backend": "catalog:", "immer": "catalog:", "lucide-react": "catalog:", + "posthog-js": "^1.266.0", "react": "catalog:", "react-dom": "catalog:", "react-fast-compare": "catalog:", diff --git a/apps/desktop/src/components/header.tsx b/apps/desktop/src/components/header.tsx index 77568269b..3f22fec24 100644 --- a/apps/desktop/src/components/header.tsx +++ b/apps/desktop/src/components/header.tsx @@ -9,13 +9,11 @@ import { } from "@popcorntime/ui/components/menubar"; import { Tooltip, TooltipContent, TooltipTrigger } from "@popcorntime/ui/components/tooltip"; import { cn } from "@popcorntime/ui/lib/utils"; -import { appLogDir } from "@tauri-apps/api/path"; -import { openPath } from "@tauri-apps/plugin-opener"; + import { - Bug, CircleUserIcon, Clapperboard, - FileText, + Cog, Film, Globe, Headphones, @@ -36,6 +34,7 @@ export function Header() { const preferFavorites = useGlobalStore(state => state.browse.preferFavorites); const togglePreferFavorites = useGlobalStore(state => state.togglePreferFavorites); const togglePreferences = useGlobalStore(state => state.togglePreferences); + const toggleSettings = useGlobalStore(state => state.toggleSettings); const toggleWatchPreferences = useGlobalStore(state => state.toggleWatchPreferences); const sessionCleared = useGlobalStore(state => state.sessionCleared); const direction = useGlobalStore(state => state.i18n.direction); @@ -47,11 +46,6 @@ export function Header() { return (searchParams.get("kind") || "MOVIE") as MediaKind; }, [searchParams]); - const openLogsDir = useCallback(async () => { - const appLogDirPath = await appLogDir(); - openPath(appLogDirPath); - }, []); - const logout = useCallback(() => { api.logout().then(sessionCleared); }, [api.logout, sessionCleared]); @@ -153,16 +147,10 @@ export function Header() { {t("menu.watchPreferences")} - - - - {t("menu.manifest")} - - - - - {t("menu.logs")} + + + {t("menu.settings")} diff --git a/apps/desktop/src/components/modal/preferences.tsx b/apps/desktop/src/components/modal/preferences.tsx index 75db37182..741efaa75 100644 --- a/apps/desktop/src/components/modal/preferences.tsx +++ b/apps/desktop/src/components/modal/preferences.tsx @@ -16,7 +16,6 @@ import { useTranslation } from "react-i18next"; import { useNavigate } from "react-router"; import { toast } from "sonner"; import { z } from "zod"; -import { useShallow } from "zustand/shallow"; import { CountryPopover } from "@/components/popover/country"; import { LanguagePopover } from "@/components/popover/language"; import { useCountry } from "@/hooks/useCountry"; @@ -35,8 +34,7 @@ export function PreferencesDialog() { const shouldOpen = useGlobalStore(state => state.dialogs.preferences.isOpen); const togglePreferences = useGlobalStore(state => state.togglePreferences); - const preferences = useGlobalStore(useShallow(state => state.preferences)); - const sessionStatus = useGlobalStore(state => state.session.status); + const preferences = useGlobalStore(state => state.preferences); const [submitted, setSubmitted] = useState(false); const { api } = useTauri(); const { t } = useTranslation(); @@ -47,8 +45,8 @@ export function PreferencesDialog() { const form = useForm({ resolver: zodResolver(accountFormSchema), defaultValues: { - country: i18n.defaultCountry, - language: i18n.defaultLocale, + country: preferences.country ?? i18n.defaultCountry, + language: preferences.language ?? i18n.defaultLocale, }, }); @@ -61,17 +59,6 @@ export function PreferencesDialog() { }; }, [shouldOpen, hide]); - useEffect(() => { - if (sessionStatus === "ready") { - if (preferences.country) { - form.setValue("country", preferences.country); - } - if (preferences.language) { - form.setValue("language", preferences.language); - } - } - }, [form, preferences, sessionStatus]); - const onSubmit = useCallback( (values: AccountFormValues) => { if (submitted) { @@ -106,7 +93,7 @@ export function PreferencesDialog() { [submitted, api.updateUserPreferences, t, country, navigate, togglePreferences] ); - if (!sessionStatus || !shouldOpen) { + if (preferences.status !== "ready" || !shouldOpen) { return null; } diff --git a/apps/desktop/src/components/modal/settings.tsx b/apps/desktop/src/components/modal/settings.tsx new file mode 100644 index 000000000..9adf54db0 --- /dev/null +++ b/apps/desktop/src/components/modal/settings.tsx @@ -0,0 +1,144 @@ +import { zodResolver } from "@hookform/resolvers/zod"; +import { Button } from "@popcorntime/ui/components/button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@popcorntime/ui/components/dialog"; +import { + Form, + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, +} from "@popcorntime/ui/components/form"; +import { Switch } from "@popcorntime/ui/components/switch"; +import { appLogDir } from "@tauri-apps/api/path"; +import { openPath } from "@tauri-apps/plugin-opener"; +import { useCallback, useEffect, useState } from "react"; +import { useForm } from "react-hook-form"; +import { useTranslation } from "react-i18next"; +import { toast } from "sonner"; +import { z } from "zod"; +import { useTauri } from "@/hooks/useTauri"; +import { useUpdater } from "@/hooks/useUpdater"; +import { useGlobalStore } from "@/stores/global"; + +const settingsFormSchema = z.object({ + enableAnalytics: z.boolean(), +}); + +type SettingsFormValues = z.infer; + +export function SettingsDialog() { + const shouldOpen = useGlobalStore(state => state.dialogs.settings.isOpen); + const toggleSettings = useGlobalStore(state => state.toggleSettings); + const settings = useGlobalStore(state => state.settings); + const [submitted, setSubmitted] = useState(false); + const { api } = useTauri(); + const { t } = useTranslation(); + const { hide } = useUpdater(); + + const openLogsDir = useCallback(async () => { + const appLogDirPath = await appLogDir(); + openPath(appLogDirPath); + }, []); + + const form = useForm({ + resolver: zodResolver(settingsFormSchema), + defaultValues: { + enableAnalytics: settings.enableAnalytics ?? false, + }, + }); + + useEffect(() => { + const withUpdateAvailable = hide(shouldOpen); + return () => { + if (withUpdateAvailable) { + hide(false); + } + }; + }, [shouldOpen, hide]); + + const onSubmit = useCallback( + (values: SettingsFormValues) => { + if (submitted) { + return; + } + + const { settingsSucceeded, settingsFailed } = useGlobalStore.getState(); + + setSubmitted(true); + settingsSucceeded(values); + api + .updateSettings(values) + .then(() => + toast.success(t("settings.toast"), { + closeButton: true, + dismissible: true, + }) + ) + .catch(settingsFailed) + .finally(() => { + setSubmitted(false); + toggleSettings(); + }); + }, + [submitted, api.updateSettings, t, toggleSettings] + ); + + if (settings.status !== "ready" || !shouldOpen) { + return null; + } + + return ( + + +
+ + + {t("settings.settings")} + {t("settings.description")} + +
+ ( + +
+ {t("settings.analytics")} + {t("settings.analytics-description")} +
+ + + +
+ )} + /> + +
+
+
{t("settings.logs")}
+

{t("settings.logs-description")}

+
+
+ +
+
+
+ + + +
+ +
+
+ ); +} diff --git a/apps/desktop/src/components/onboarding/timeline.tsx b/apps/desktop/src/components/onboarding/timeline.tsx index 88239920f..f8df6519c 100644 --- a/apps/desktop/src/components/onboarding/timeline.tsx +++ b/apps/desktop/src/components/onboarding/timeline.tsx @@ -37,14 +37,12 @@ export function OnboardingTimeline() { const startBrowsing = useCallback(() => { setIsWorking(true); - api.setOnboarded().then(() => { + api.updateSettings({ onboardingComplete: true }).then(settings => { setIsWorking(false); - settingsSucceeded({ - onboarded: true, - }); + settingsSucceeded(settings); navigate("/"); }); - }, [api.setOnboarded, navigate, settingsSucceeded]); + }, [api.updateSettings, navigate, settingsSucceeded]); return (
diff --git a/apps/desktop/src/layout.tsx b/apps/desktop/src/layout.tsx index f9b1ea321..7b4803f29 100644 --- a/apps/desktop/src/layout.tsx +++ b/apps/desktop/src/layout.tsx @@ -5,13 +5,13 @@ import { Header } from "@/components/header"; import { MediaDialog } from "@/components/modal/media"; import { PreferencesDialog } from "@/components/modal/preferences"; import { WatchPreferencesDialog } from "@/components/modal/watch-preferences"; +import { SettingsDialog } from "./components/modal/settings"; export function DefaultLayout() { return ( <>
- ); } @@ -35,6 +35,7 @@ export function BrowseLayout() { + ); } diff --git a/apps/desktop/src/loaders/settings.test.tsx b/apps/desktop/src/loaders/settings.test.tsx index a88a75d6f..79af65a34 100644 --- a/apps/desktop/src/loaders/settings.test.tsx +++ b/apps/desktop/src/loaders/settings.test.tsx @@ -12,7 +12,7 @@ afterEach(() => { describe("SettingsLoaderMount", () => { it("handle valid onboarding", async () => { mockIPC((cmd, _args) => { - if (cmd === "is_onboarded") return false; + if (cmd === "settings") return { onboardingComplete: false }; }); useGlobalStore.getState().sessionSucceeded(true); @@ -21,14 +21,14 @@ describe("SettingsLoaderMount", () => { await act(async () => {}); expect(useGlobalStore.getState().settings.status).toBe("ready"); - expect(useGlobalStore.getState().settings.onboarded).toBe(false); + expect(useGlobalStore.getState().settings.onboardingComplete).toBe(false); r.unmount(); }); it("handle invalid onboarding flow", async () => { mockIPC((cmd, _args) => { - if (cmd === "is_onboarded") + if (cmd === "settings") throw { message: "Failed to get settings", code: "errors.graphql.server" }; }); diff --git a/apps/desktop/src/loaders/settings.tsx b/apps/desktop/src/loaders/settings.tsx index 0eaf57ef0..cb9e25208 100644 --- a/apps/desktop/src/loaders/settings.tsx +++ b/apps/desktop/src/loaders/settings.tsx @@ -12,8 +12,8 @@ export function SettingsLoaderMount() { const { settingsRequested, settingsSucceeded, settingsFailed } = useGlobalStore.getState(); settingsRequested(); api - .isOnboarded() - .then(onboarded => settingsSucceeded({ onboarded })) + .settings() + .then(settings => settingsSucceeded(settings)) .catch(settingsFailed); }, [api, status]); diff --git a/apps/desktop/src/metrics.tsx b/apps/desktop/src/metrics.tsx new file mode 100644 index 000000000..7850e0162 --- /dev/null +++ b/apps/desktop/src/metrics.tsx @@ -0,0 +1,39 @@ +import posthog from "posthog-js"; +import { PostHogProvider } from "posthog-js/react"; +import { useEffect, useRef } from "react"; +import { useGlobalStore } from "@/stores/global"; + +export function MetricsProvider({ children }: React.PropsWithChildren) { + const enableAnalytics = useGlobalStore(s => s.settings.enableAnalytics); + const initializedRef = useRef(false); + + useEffect(() => { + if (initializedRef.current) return; + + posthog.init(import.meta.env.VITE_PUBLIC_POSTHOG_KEY, { + api_host: import.meta.env.VITE_PUBLIC_POSTHOG_HOST, + capture_pageview: true, + persistence: "localStorage", + opt_out_capturing_by_default: true, + disable_session_recording: true, + loaded: ph => { + if (enableAnalytics) { + ph.opt_in_capturing(); + } + }, + }); + + initializedRef.current = true; + }, [enableAnalytics]); + + useEffect(() => { + if (enableAnalytics) { + posthog.opt_in_capturing(); + } else { + posthog.opt_out_capturing(); + posthog.reset(); + } + }, [enableAnalytics]); + + return {children}; +} diff --git a/apps/desktop/src/providers.tsx b/apps/desktop/src/providers.tsx index a6f44b685..2d4c1a81a 100644 --- a/apps/desktop/src/providers.tsx +++ b/apps/desktop/src/providers.tsx @@ -4,25 +4,28 @@ import { TooltipProvider } from "@popcorntime/ui/components/tooltip"; import { CheckCircle } from "lucide-react"; import { CountryProvider } from "@/hooks/useCountry"; import { UpdaterProvider } from "@/hooks/useUpdater"; +import { MetricsProvider } from "@/metrics"; export function Providers({ children }: React.PropsWithChildren) { return ( - - - - - {children} - , - }} - className="-z-10" - /> - - - - + + + + + + {children} + , + }} + className="-z-10" + /> + + + + + ); } diff --git a/apps/desktop/src/routes/splash.test.tsx b/apps/desktop/src/routes/splash.test.tsx index 6b02e1f8d..807525721 100644 --- a/apps/desktop/src/routes/splash.test.tsx +++ b/apps/desktop/src/routes/splash.test.tsx @@ -38,7 +38,7 @@ describe("SplashRoute", () => { it("shows Splash while boot is not initialized", async () => { useGlobalStore.setState(s => { s.app.boot = "cold"; - s.settings.onboarded = false; + s.settings.onboardingComplete = false; s.session.isActive = false; }); @@ -54,7 +54,7 @@ describe("SplashRoute", () => { it("redirects to onboarding when not onboarded", async () => { useGlobalStore.setState(s => { s.app.boot = "booted"; - s.settings.onboarded = false; + s.settings.onboardingComplete = false; }); const r = renderWithRouter("/"); @@ -69,7 +69,7 @@ describe("SplashRoute", () => { it("redirects to login when onboarded but session is not active", async () => { useGlobalStore.setState(s => { s.app.boot = "booted"; - s.settings.onboarded = true; + s.settings.onboardingComplete = true; }); const r = renderWithRouter("/"); @@ -84,7 +84,7 @@ describe("SplashRoute", () => { it("shows splash when active but app not initialized", async () => { useGlobalStore.setState(s => { s.app.boot = "booting"; - s.settings.onboarded = true; + s.settings.onboardingComplete = true; s.session.isActive = true; // missing providers }); @@ -102,7 +102,7 @@ describe("SplashRoute", () => { useGlobalStore.setState(s => { s.app.boot = "booted"; // prevent onboarding - s.settings.onboarded = true; + s.settings.onboardingComplete = true; // prevent login s.session.isActive = true; s.preferences.country = "CA"; @@ -119,7 +119,7 @@ describe("SplashRoute", () => { it("reacts when app initialization flips", async () => { useGlobalStore.setState(s => { s.app.boot = "cold"; - s.settings.onboarded = true; + s.settings.onboardingComplete = true; }); const r = renderWithRouter("/"); diff --git a/apps/desktop/src/routes/splash.tsx b/apps/desktop/src/routes/splash.tsx index 9ed6e936a..2070ff84f 100644 --- a/apps/desktop/src/routes/splash.tsx +++ b/apps/desktop/src/routes/splash.tsx @@ -5,7 +5,7 @@ import { useGlobalStore } from "@/stores/global"; export function SplashRoute() { const appBoot = useGlobalStore(s => s.app.boot); - const onboarded = useGlobalStore(s => s.settings.onboarded); + const onboarded = useGlobalStore(s => s.settings.onboardingComplete); const isActive = useGlobalStore(s => s.session.isActive); const preferredCountry = useGlobalStore(s => s.preferences.country); const initialRedirectAttempted = useRef(false); diff --git a/apps/desktop/src/stores/global.test.ts b/apps/desktop/src/stores/global.test.ts index 9a679c906..0c9a2acc3 100644 --- a/apps/desktop/src/stores/global.test.ts +++ b/apps/desktop/src/stores/global.test.ts @@ -10,7 +10,7 @@ const setAllReady = () => { s.providersSucceeded([]); s.sessionSucceeded(true); s.preferencesSucceeded({ country: "US", language: "en" }); - s.settingsSucceeded({ onboarded: true }); + s.settingsSucceeded({ onboardingComplete: true }); }; beforeEach(() => { @@ -55,7 +55,7 @@ describe("boot & app flags", () => { it("sets app booting", () => { expect(useGlobalStore.getState().app.boot).toBe("cold"); useGlobalStore.getState().sessionSucceeded(false); - useGlobalStore.getState().settingsSucceeded({ onboarded: false }); + useGlobalStore.getState().settingsSucceeded({ onboardingComplete: false }); expect(useGlobalStore.getState().app.boot).toBe("booting"); }); diff --git a/apps/desktop/src/stores/global.ts b/apps/desktop/src/stores/global.ts index 563ca2d36..fe4c68785 100644 --- a/apps/desktop/src/stores/global.ts +++ b/apps/desktop/src/stores/global.ts @@ -8,7 +8,7 @@ import { subscribeWithSelector } from "zustand/middleware"; import { immer } from "zustand/middleware/immer"; import { isTauriError, type TauriError } from "@/hooks/useTauri"; import { devtools } from "@/stores/devtools"; -import type { Provider, SearchArguments, SortKey } from "@/tauri/types"; +import type { Provider, SearchArguments, Settings, SortKey } from "@/tauri/types"; export type SortOrder = "ASC" | "DESC"; type UpdateProgress = "downloading" | "downloaded" | "installing" | "installed"; @@ -33,11 +33,10 @@ interface PreferencesState { error?: TauriError; } -interface SettingsState { +type SettingsState = { status: Status; - onboarded: boolean; error?: TauriError; -} +} & Settings; interface ProvidersState { status: Status; @@ -72,9 +71,14 @@ interface DialogWatchPreferencesState { isOpen: boolean; } +interface DialogSettingsState { + isOpen: boolean; +} + interface DialogsState { media: DialogMediaState; preferences: DialogPreferencesState; + settings: DialogSettingsState; watchPreferences: DialogWatchPreferencesState; } @@ -120,7 +124,7 @@ interface GlobalMutations { preferencesFailed(err: unknown): void; settingsRequested(): void; - settingsSucceeded(partial?: { onboarded?: boolean }): void; + settingsSucceeded(settings: Settings): void; settingsFailed(err: unknown): void; providersRequested(): void; @@ -135,6 +139,7 @@ interface GlobalMutations { closeMedia(): void; togglePreferences(): void; toggleWatchPreferences(): void; + toggleSettings(): void; browseUpdate: (input: BrowseUpdateInput) => void; togglePreferFavorites: () => void; @@ -154,7 +159,8 @@ export const useGlobalStore = create()( }, settings: { status: "idle", - onboarded: false, + enableAnalytics: false, + onboardingComplete: false, }, preferences: { status: "idle", @@ -175,6 +181,9 @@ export const useGlobalStore = create()( media: { isOpen: false, }, + settings: { + isOpen: false, + }, preferences: { isOpen: false, }, @@ -239,12 +248,12 @@ export const useGlobalStore = create()( state.settings.error = undefined; }), - settingsSucceeded: (partial?: { onboarded?: boolean }) => + settingsSucceeded: (settings: Settings) => set(state => { state.settings.status = "ready"; state.settings = { ...state.settings, - ...partial, + ...settings, }; }), @@ -377,6 +386,11 @@ export const useGlobalStore = create()( set(state => { state.browse.preferFavorites = !state.browse.preferFavorites; }), + + toggleSettings: () => + set(state => { + state.dialogs.settings.isOpen = !state.dialogs.settings.isOpen; + }), })) ), { diff --git a/apps/desktop/src/tauri/types.ts b/apps/desktop/src/tauri/types.ts index aee6ef5c4..071596de3 100644 --- a/apps/desktop/src/tauri/types.ts +++ b/apps/desktop/src/tauri/types.ts @@ -74,22 +74,6 @@ async setMediaReaction(params: SetReactionInput) : Promise { await TAURI_INVOKE("show_main_window"); }, -async isOnboarded() : Promise> { - try { - return { status: "ok", data: await TAURI_INVOKE("is_onboarded") }; -} catch (e) { - if(e instanceof Error) throw e; - else return { status: "error", error: e as any }; -} -}, -async setOnboarded() : Promise> { - try { - return { status: "ok", data: await TAURI_INVOKE("set_onboarded") }; -} catch (e) { - if(e instanceof Error) throw e; - else return { status: "error", error: e as any }; -} -}, async validate() : Promise> { try { return { status: "ok", data: await TAURI_INVOKE("validate") }; @@ -113,6 +97,22 @@ async initializeSessionAuthorization() : Promise> { + try { + return { status: "ok", data: await TAURI_INVOKE("settings") }; +} catch (e) { + if(e instanceof Error) throw e; + else return { status: "error", error: e as any }; +} +}, +async updateSettings(settings: SettingsInput) : Promise> { + try { + return { status: "ok", data: await TAURI_INVOKE("update_settings", { settings }) }; +} catch (e) { + if(e instanceof Error) throw e; + else return { status: "error", error: e as any }; +} } } @@ -174,6 +174,8 @@ export type SetFavoriteProviderInput = { country: Country; providerKey: string; export type SetFavoriteProviderMutation = { setFavoriteProvider: boolean } export type SetReactionInput = { mediaId: number; reaction: UserReactionType | null } export type SetReactionMutation = { setReaction: boolean } +export type Settings = { onboardingComplete?: boolean; enableAnalytics?: boolean } +export type SettingsInput = { onboardingComplete?: boolean | null; enableAnalytics?: boolean | null } export type SortKey = "ID" | "RELEASED_AT" | "CREATED_AT" | "UPDATED_AT" | "POSITION" export type Tag = string export type Tvshow = { inProduction: boolean; id: number; __typename: string; title: string; slug: string; overview: string | null; tagline: string | null; languages: Language[]; poster: string | null; backdrop: string | null; released: string | null; year: number | null; country: Country | null; tags: Tag[]; trailers: string[]; genres: Genre[]; classification: string | null; countries: Country[]; kind: MediaKind; videos: MediaVideo[]; ratings: ExternalRating[]; ranking: Ranking | null; pochoclinReview: PochoclinReview | null; similars: MediaSimilar[]; similarsFree: MediaSimilar[]; charts: MediaCharts[]; availabilities: Availability[]; talents: People[]; reaction: UserReactionType | null } diff --git a/crates/popcorntime-session/Cargo.toml b/crates/popcorntime-session/Cargo.toml index 03c2c361a..09f6b97b3 100644 --- a/crates/popcorntime-session/Cargo.toml +++ b/crates/popcorntime-session/Cargo.toml @@ -19,11 +19,11 @@ serde_json.workspace = true uuid.workspace = true tauri.workspace = true poem.workspace = true +toml.workspace = true popcorntime-error.workspace = true oauth2 = "5.0.0" -toml = "0.9.7" keyring = { version = "3.6.3", features = [ "apple-native", "windows-native", diff --git a/crates/popcorntime-settings/Cargo.toml b/crates/popcorntime-settings/Cargo.toml index 97469341f..372d065e6 100644 --- a/crates/popcorntime-settings/Cargo.toml +++ b/crates/popcorntime-settings/Cargo.toml @@ -6,3 +6,8 @@ authors.workspace = true publish = false [dependencies] +toml.workspace = true +serde.workspace = true +specta.workspace = true +anyhow.workspace = true +tokio.workspace = true diff --git a/crates/popcorntime-settings/src/lib.rs b/crates/popcorntime-settings/src/lib.rs index 8b1378917..0a133394f 100644 --- a/crates/popcorntime-settings/src/lib.rs +++ b/crates/popcorntime-settings/src/lib.rs @@ -1 +1,78 @@ +use anyhow::{Ok, Result}; +use serde::{Deserialize, Serialize}; +use specta::Type; +use std::{ + path::{Path, PathBuf}, + sync::Arc, +}; +use tokio::sync::RwLock; +const SETTINGS_FILE: &str = "settings.toml"; + +#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Default, Type)] +#[serde(rename_all = "camelCase")] +pub struct Settings { + #[serde(default)] + pub onboarding_complete: bool, + #[serde(default)] + pub enable_analytics: bool, +} + +#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Default, Type)] +#[serde(rename_all = "camelCase")] +pub struct SettingsInput { + #[serde(default)] + pub onboarding_complete: Option, + #[serde(default)] + pub enable_analytics: Option, +} + +#[derive(Debug)] +pub struct SettingsService { + snapshot: Arc>, + config_dir: PathBuf, +} + +fn read_snapshot(path: &Path) -> Result { + if path.exists() { + let content = std::fs::read_to_string(path)?; + let settings: Settings = toml::from_str(&content)?; + Ok(settings) + } else { + Ok(Settings::default()) + } +} + +impl SettingsService { + pub fn new(config_dir: &Path) -> Result { + let snapshot = read_snapshot(&config_dir.join(SETTINGS_FILE))?; + Ok(Self { + snapshot: Arc::new(RwLock::new(snapshot)), + config_dir: config_dir.to_path_buf(), + }) + } + + pub async fn get(&self) -> Result { + Ok(self.snapshot.read().await.clone()) + } + + pub async fn update(&self, f: F) -> Result + where + F: FnOnce(&mut Settings), + { + let mut settings = self.snapshot.write().await; + + f(&mut settings); + + if !self.config_dir.exists() { + std::fs::create_dir_all(&self.config_dir)?; + } + + let path = self.config_dir.join(SETTINGS_FILE); + let settings_inner = settings.clone(); + let content = toml::to_string_pretty(&settings_inner)?; + std::fs::write(path, content)?; + + Ok(settings_inner) + } +} diff --git a/crates/popcorntime-tauri/Cargo.toml b/crates/popcorntime-tauri/Cargo.toml index 8cb9bc70c..9eb239e56 100644 --- a/crates/popcorntime-tauri/Cargo.toml +++ b/crates/popcorntime-tauri/Cargo.toml @@ -41,6 +41,7 @@ tauri-plugin-single-instance = { workspace = true, features = ["deep-link"] } popcorntime-session.workspace = true popcorntime-graphql-client.workspace = true popcorntime-error.workspace = true +popcorntime-settings.workspace = true specta.workspace = true tauri-specta = { workspace = true, features = ["derive", "typescript"] } diff --git a/crates/popcorntime-tauri/dictionaries.lock b/crates/popcorntime-tauri/dictionaries.lock index 63be2f4ae..c6b1388ca 100644 --- a/crates/popcorntime-tauri/dictionaries.lock +++ b/crates/popcorntime-tauri/dictionaries.lock @@ -485,7 +485,18 @@ "$['onboardingProviders']['selected']": "eef30365e9cc4bd8da360e251728fa69114d8cdf133b093249ee07223b2a7abb", "$['onboardingProviders']['noFound']": "dc3a0116c7c3d33dffde52310d11c2b039904039d5e13b4c915f621c7167ecf4", "$['onboardingPreferences']['showAll']": "ebd10fbf3cb038b4a7355c15c166c2deef946af74a1969b55f51faf5dc9cf501", - "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4" + "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4", + "$['menu']['settings']": "d43fb8a961ff2d1f037995587ed8883ac4b733ecaf1b0b74201123ada13df810", + "$['settings']['toast']": "36ffa4529bb50637e9f0d1e3d1c209ae8246236ea4e856d95ddcf993b5db4e2c", + "$['settings']['settings']": "74a883a037bc227f91891ab654a753d3a99f31ab06ae5b5d2b6e594a692b41f8", + "$['settings']['description']": "86095b212ba6d2fc7e54c102b3de1f62e698aee75939b54e12de918f6c060a5c", + "$['settings']['analytics']": "94c116ee118a72998db6cd10b586a9ef112a1891ff8ced8c7b2944ff62453b5f", + "$['settings']['analytics-description']": "b1cc043af19eedc5e22078ed0ef859091b321f0e2921ab915651e52c3ba42c8e", + "$['settings']['logs']": "ea2100dc89ae9fe21fa9b08ab1bf18662dca1e53a3eebd7d03afebcaf5d57515", + "$['settings']['logs-description']": "af971f78c75f6b9a8ae534b23a094723837e42415c1246923b746df5c80b84d7", + "$['settings']['open-logs']": "ed077f3d8125d60dca1979c7133601bd187d47c73ed9975028f677e49e709942", + "$['settings']['update']": "46ed69579c396feaa780e716e778b9dea387bebfe925e9d661ec6882c96525e9", + "$['settings']['error']": "63f6bf5375c13518fbc291863e4715083eeb5d50fa2c2aa00cdf3958267f693b" }, "es": { "$['header']['popular']": "76327dec9ae3a06a8c3c283e6a81d3710ae736021b583875c13e4e8fb2ad83c0", @@ -973,7 +984,18 @@ "$['onboardingProviders']['selected']": "eef30365e9cc4bd8da360e251728fa69114d8cdf133b093249ee07223b2a7abb", "$['onboardingProviders']['noFound']": "dc3a0116c7c3d33dffde52310d11c2b039904039d5e13b4c915f621c7167ecf4", "$['onboardingPreferences']['showAll']": "ebd10fbf3cb038b4a7355c15c166c2deef946af74a1969b55f51faf5dc9cf501", - "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4" + "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4", + "$['menu']['settings']": "d43fb8a961ff2d1f037995587ed8883ac4b733ecaf1b0b74201123ada13df810", + "$['settings']['toast']": "36ffa4529bb50637e9f0d1e3d1c209ae8246236ea4e856d95ddcf993b5db4e2c", + "$['settings']['settings']": "74a883a037bc227f91891ab654a753d3a99f31ab06ae5b5d2b6e594a692b41f8", + "$['settings']['description']": "86095b212ba6d2fc7e54c102b3de1f62e698aee75939b54e12de918f6c060a5c", + "$['settings']['analytics']": "94c116ee118a72998db6cd10b586a9ef112a1891ff8ced8c7b2944ff62453b5f", + "$['settings']['analytics-description']": "b1cc043af19eedc5e22078ed0ef859091b321f0e2921ab915651e52c3ba42c8e", + "$['settings']['logs']": "ea2100dc89ae9fe21fa9b08ab1bf18662dca1e53a3eebd7d03afebcaf5d57515", + "$['settings']['logs-description']": "af971f78c75f6b9a8ae534b23a094723837e42415c1246923b746df5c80b84d7", + "$['settings']['open-logs']": "ed077f3d8125d60dca1979c7133601bd187d47c73ed9975028f677e49e709942", + "$['settings']['update']": "46ed69579c396feaa780e716e778b9dea387bebfe925e9d661ec6882c96525e9", + "$['settings']['error']": "63f6bf5375c13518fbc291863e4715083eeb5d50fa2c2aa00cdf3958267f693b" }, "ar": { "$['header']['popular']": "76327dec9ae3a06a8c3c283e6a81d3710ae736021b583875c13e4e8fb2ad83c0", @@ -1461,7 +1483,18 @@ "$['onboardingProviders']['selected']": "eef30365e9cc4bd8da360e251728fa69114d8cdf133b093249ee07223b2a7abb", "$['onboardingProviders']['noFound']": "dc3a0116c7c3d33dffde52310d11c2b039904039d5e13b4c915f621c7167ecf4", "$['onboardingPreferences']['showAll']": "ebd10fbf3cb038b4a7355c15c166c2deef946af74a1969b55f51faf5dc9cf501", - "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4" + "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4", + "$['menu']['settings']": "d43fb8a961ff2d1f037995587ed8883ac4b733ecaf1b0b74201123ada13df810", + "$['settings']['toast']": "36ffa4529bb50637e9f0d1e3d1c209ae8246236ea4e856d95ddcf993b5db4e2c", + "$['settings']['settings']": "74a883a037bc227f91891ab654a753d3a99f31ab06ae5b5d2b6e594a692b41f8", + "$['settings']['description']": "86095b212ba6d2fc7e54c102b3de1f62e698aee75939b54e12de918f6c060a5c", + "$['settings']['analytics']": "94c116ee118a72998db6cd10b586a9ef112a1891ff8ced8c7b2944ff62453b5f", + "$['settings']['analytics-description']": "b1cc043af19eedc5e22078ed0ef859091b321f0e2921ab915651e52c3ba42c8e", + "$['settings']['logs']": "ea2100dc89ae9fe21fa9b08ab1bf18662dca1e53a3eebd7d03afebcaf5d57515", + "$['settings']['logs-description']": "af971f78c75f6b9a8ae534b23a094723837e42415c1246923b746df5c80b84d7", + "$['settings']['open-logs']": "ed077f3d8125d60dca1979c7133601bd187d47c73ed9975028f677e49e709942", + "$['settings']['update']": "46ed69579c396feaa780e716e778b9dea387bebfe925e9d661ec6882c96525e9", + "$['settings']['error']": "63f6bf5375c13518fbc291863e4715083eeb5d50fa2c2aa00cdf3958267f693b" }, "fa": { "$['header']['popular']": "76327dec9ae3a06a8c3c283e6a81d3710ae736021b583875c13e4e8fb2ad83c0", @@ -1949,7 +1982,18 @@ "$['onboardingProviders']['selected']": "eef30365e9cc4bd8da360e251728fa69114d8cdf133b093249ee07223b2a7abb", "$['onboardingProviders']['noFound']": "dc3a0116c7c3d33dffde52310d11c2b039904039d5e13b4c915f621c7167ecf4", "$['onboardingPreferences']['showAll']": "ebd10fbf3cb038b4a7355c15c166c2deef946af74a1969b55f51faf5dc9cf501", - "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4" + "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4", + "$['menu']['settings']": "d43fb8a961ff2d1f037995587ed8883ac4b733ecaf1b0b74201123ada13df810", + "$['settings']['toast']": "36ffa4529bb50637e9f0d1e3d1c209ae8246236ea4e856d95ddcf993b5db4e2c", + "$['settings']['settings']": "74a883a037bc227f91891ab654a753d3a99f31ab06ae5b5d2b6e594a692b41f8", + "$['settings']['description']": "86095b212ba6d2fc7e54c102b3de1f62e698aee75939b54e12de918f6c060a5c", + "$['settings']['analytics']": "94c116ee118a72998db6cd10b586a9ef112a1891ff8ced8c7b2944ff62453b5f", + "$['settings']['analytics-description']": "b1cc043af19eedc5e22078ed0ef859091b321f0e2921ab915651e52c3ba42c8e", + "$['settings']['logs']": "ea2100dc89ae9fe21fa9b08ab1bf18662dca1e53a3eebd7d03afebcaf5d57515", + "$['settings']['logs-description']": "af971f78c75f6b9a8ae534b23a094723837e42415c1246923b746df5c80b84d7", + "$['settings']['open-logs']": "ed077f3d8125d60dca1979c7133601bd187d47c73ed9975028f677e49e709942", + "$['settings']['update']": "46ed69579c396feaa780e716e778b9dea387bebfe925e9d661ec6882c96525e9", + "$['settings']['error']": "63f6bf5375c13518fbc291863e4715083eeb5d50fa2c2aa00cdf3958267f693b" }, "ur": { "$['header']['popular']": "76327dec9ae3a06a8c3c283e6a81d3710ae736021b583875c13e4e8fb2ad83c0", @@ -2437,7 +2481,18 @@ "$['onboardingProviders']['selected']": "eef30365e9cc4bd8da360e251728fa69114d8cdf133b093249ee07223b2a7abb", "$['onboardingProviders']['noFound']": "dc3a0116c7c3d33dffde52310d11c2b039904039d5e13b4c915f621c7167ecf4", "$['onboardingPreferences']['showAll']": "ebd10fbf3cb038b4a7355c15c166c2deef946af74a1969b55f51faf5dc9cf501", - "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4" + "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4", + "$['menu']['settings']": "d43fb8a961ff2d1f037995587ed8883ac4b733ecaf1b0b74201123ada13df810", + "$['settings']['toast']": "36ffa4529bb50637e9f0d1e3d1c209ae8246236ea4e856d95ddcf993b5db4e2c", + "$['settings']['settings']": "74a883a037bc227f91891ab654a753d3a99f31ab06ae5b5d2b6e594a692b41f8", + "$['settings']['description']": "86095b212ba6d2fc7e54c102b3de1f62e698aee75939b54e12de918f6c060a5c", + "$['settings']['analytics']": "94c116ee118a72998db6cd10b586a9ef112a1891ff8ced8c7b2944ff62453b5f", + "$['settings']['analytics-description']": "b1cc043af19eedc5e22078ed0ef859091b321f0e2921ab915651e52c3ba42c8e", + "$['settings']['logs']": "ea2100dc89ae9fe21fa9b08ab1bf18662dca1e53a3eebd7d03afebcaf5d57515", + "$['settings']['logs-description']": "af971f78c75f6b9a8ae534b23a094723837e42415c1246923b746df5c80b84d7", + "$['settings']['open-logs']": "ed077f3d8125d60dca1979c7133601bd187d47c73ed9975028f677e49e709942", + "$['settings']['update']": "46ed69579c396feaa780e716e778b9dea387bebfe925e9d661ec6882c96525e9", + "$['settings']['error']": "63f6bf5375c13518fbc291863e4715083eeb5d50fa2c2aa00cdf3958267f693b" }, "hi": { "$['header']['popular']": "76327dec9ae3a06a8c3c283e6a81d3710ae736021b583875c13e4e8fb2ad83c0", @@ -2925,7 +2980,18 @@ "$['onboardingProviders']['selected']": "eef30365e9cc4bd8da360e251728fa69114d8cdf133b093249ee07223b2a7abb", "$['onboardingProviders']['noFound']": "dc3a0116c7c3d33dffde52310d11c2b039904039d5e13b4c915f621c7167ecf4", "$['onboardingPreferences']['showAll']": "ebd10fbf3cb038b4a7355c15c166c2deef946af74a1969b55f51faf5dc9cf501", - "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4" + "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4", + "$['menu']['settings']": "d43fb8a961ff2d1f037995587ed8883ac4b733ecaf1b0b74201123ada13df810", + "$['settings']['toast']": "36ffa4529bb50637e9f0d1e3d1c209ae8246236ea4e856d95ddcf993b5db4e2c", + "$['settings']['settings']": "74a883a037bc227f91891ab654a753d3a99f31ab06ae5b5d2b6e594a692b41f8", + "$['settings']['description']": "86095b212ba6d2fc7e54c102b3de1f62e698aee75939b54e12de918f6c060a5c", + "$['settings']['analytics']": "94c116ee118a72998db6cd10b586a9ef112a1891ff8ced8c7b2944ff62453b5f", + "$['settings']['analytics-description']": "b1cc043af19eedc5e22078ed0ef859091b321f0e2921ab915651e52c3ba42c8e", + "$['settings']['logs']": "ea2100dc89ae9fe21fa9b08ab1bf18662dca1e53a3eebd7d03afebcaf5d57515", + "$['settings']['logs-description']": "af971f78c75f6b9a8ae534b23a094723837e42415c1246923b746df5c80b84d7", + "$['settings']['open-logs']": "ed077f3d8125d60dca1979c7133601bd187d47c73ed9975028f677e49e709942", + "$['settings']['update']": "46ed69579c396feaa780e716e778b9dea387bebfe925e9d661ec6882c96525e9", + "$['settings']['error']": "63f6bf5375c13518fbc291863e4715083eeb5d50fa2c2aa00cdf3958267f693b" }, "de": { "$['header']['popular']": "76327dec9ae3a06a8c3c283e6a81d3710ae736021b583875c13e4e8fb2ad83c0", @@ -3413,7 +3479,18 @@ "$['onboardingProviders']['selected']": "eef30365e9cc4bd8da360e251728fa69114d8cdf133b093249ee07223b2a7abb", "$['onboardingProviders']['noFound']": "dc3a0116c7c3d33dffde52310d11c2b039904039d5e13b4c915f621c7167ecf4", "$['onboardingPreferences']['showAll']": "ebd10fbf3cb038b4a7355c15c166c2deef946af74a1969b55f51faf5dc9cf501", - "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4" + "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4", + "$['menu']['settings']": "d43fb8a961ff2d1f037995587ed8883ac4b733ecaf1b0b74201123ada13df810", + "$['settings']['toast']": "36ffa4529bb50637e9f0d1e3d1c209ae8246236ea4e856d95ddcf993b5db4e2c", + "$['settings']['settings']": "74a883a037bc227f91891ab654a753d3a99f31ab06ae5b5d2b6e594a692b41f8", + "$['settings']['description']": "86095b212ba6d2fc7e54c102b3de1f62e698aee75939b54e12de918f6c060a5c", + "$['settings']['analytics']": "94c116ee118a72998db6cd10b586a9ef112a1891ff8ced8c7b2944ff62453b5f", + "$['settings']['analytics-description']": "b1cc043af19eedc5e22078ed0ef859091b321f0e2921ab915651e52c3ba42c8e", + "$['settings']['logs']": "ea2100dc89ae9fe21fa9b08ab1bf18662dca1e53a3eebd7d03afebcaf5d57515", + "$['settings']['logs-description']": "af971f78c75f6b9a8ae534b23a094723837e42415c1246923b746df5c80b84d7", + "$['settings']['open-logs']": "ed077f3d8125d60dca1979c7133601bd187d47c73ed9975028f677e49e709942", + "$['settings']['update']": "46ed69579c396feaa780e716e778b9dea387bebfe925e9d661ec6882c96525e9", + "$['settings']['error']": "63f6bf5375c13518fbc291863e4715083eeb5d50fa2c2aa00cdf3958267f693b" }, "nl": { "$['header']['popular']": "76327dec9ae3a06a8c3c283e6a81d3710ae736021b583875c13e4e8fb2ad83c0", @@ -3901,7 +3978,18 @@ "$['onboardingProviders']['selected']": "eef30365e9cc4bd8da360e251728fa69114d8cdf133b093249ee07223b2a7abb", "$['onboardingProviders']['noFound']": "dc3a0116c7c3d33dffde52310d11c2b039904039d5e13b4c915f621c7167ecf4", "$['onboardingPreferences']['showAll']": "ebd10fbf3cb038b4a7355c15c166c2deef946af74a1969b55f51faf5dc9cf501", - "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4" + "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4", + "$['menu']['settings']": "d43fb8a961ff2d1f037995587ed8883ac4b733ecaf1b0b74201123ada13df810", + "$['settings']['toast']": "36ffa4529bb50637e9f0d1e3d1c209ae8246236ea4e856d95ddcf993b5db4e2c", + "$['settings']['settings']": "74a883a037bc227f91891ab654a753d3a99f31ab06ae5b5d2b6e594a692b41f8", + "$['settings']['description']": "86095b212ba6d2fc7e54c102b3de1f62e698aee75939b54e12de918f6c060a5c", + "$['settings']['analytics']": "94c116ee118a72998db6cd10b586a9ef112a1891ff8ced8c7b2944ff62453b5f", + "$['settings']['analytics-description']": "b1cc043af19eedc5e22078ed0ef859091b321f0e2921ab915651e52c3ba42c8e", + "$['settings']['logs']": "ea2100dc89ae9fe21fa9b08ab1bf18662dca1e53a3eebd7d03afebcaf5d57515", + "$['settings']['logs-description']": "af971f78c75f6b9a8ae534b23a094723837e42415c1246923b746df5c80b84d7", + "$['settings']['open-logs']": "ed077f3d8125d60dca1979c7133601bd187d47c73ed9975028f677e49e709942", + "$['settings']['update']": "46ed69579c396feaa780e716e778b9dea387bebfe925e9d661ec6882c96525e9", + "$['settings']['error']": "63f6bf5375c13518fbc291863e4715083eeb5d50fa2c2aa00cdf3958267f693b" }, "sv": { "$['header']['popular']": "76327dec9ae3a06a8c3c283e6a81d3710ae736021b583875c13e4e8fb2ad83c0", @@ -4389,7 +4477,18 @@ "$['onboardingProviders']['selected']": "eef30365e9cc4bd8da360e251728fa69114d8cdf133b093249ee07223b2a7abb", "$['onboardingProviders']['noFound']": "dc3a0116c7c3d33dffde52310d11c2b039904039d5e13b4c915f621c7167ecf4", "$['onboardingPreferences']['showAll']": "ebd10fbf3cb038b4a7355c15c166c2deef946af74a1969b55f51faf5dc9cf501", - "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4" + "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4", + "$['menu']['settings']": "d43fb8a961ff2d1f037995587ed8883ac4b733ecaf1b0b74201123ada13df810", + "$['settings']['toast']": "36ffa4529bb50637e9f0d1e3d1c209ae8246236ea4e856d95ddcf993b5db4e2c", + "$['settings']['settings']": "74a883a037bc227f91891ab654a753d3a99f31ab06ae5b5d2b6e594a692b41f8", + "$['settings']['description']": "86095b212ba6d2fc7e54c102b3de1f62e698aee75939b54e12de918f6c060a5c", + "$['settings']['analytics']": "94c116ee118a72998db6cd10b586a9ef112a1891ff8ced8c7b2944ff62453b5f", + "$['settings']['analytics-description']": "b1cc043af19eedc5e22078ed0ef859091b321f0e2921ab915651e52c3ba42c8e", + "$['settings']['logs']": "ea2100dc89ae9fe21fa9b08ab1bf18662dca1e53a3eebd7d03afebcaf5d57515", + "$['settings']['logs-description']": "af971f78c75f6b9a8ae534b23a094723837e42415c1246923b746df5c80b84d7", + "$['settings']['open-logs']": "ed077f3d8125d60dca1979c7133601bd187d47c73ed9975028f677e49e709942", + "$['settings']['update']": "46ed69579c396feaa780e716e778b9dea387bebfe925e9d661ec6882c96525e9", + "$['settings']['error']": "63f6bf5375c13518fbc291863e4715083eeb5d50fa2c2aa00cdf3958267f693b" }, "ga": { "$['header']['popular']": "76327dec9ae3a06a8c3c283e6a81d3710ae736021b583875c13e4e8fb2ad83c0", @@ -4877,7 +4976,18 @@ "$['onboardingProviders']['selected']": "eef30365e9cc4bd8da360e251728fa69114d8cdf133b093249ee07223b2a7abb", "$['onboardingProviders']['noFound']": "dc3a0116c7c3d33dffde52310d11c2b039904039d5e13b4c915f621c7167ecf4", "$['onboardingPreferences']['showAll']": "ebd10fbf3cb038b4a7355c15c166c2deef946af74a1969b55f51faf5dc9cf501", - "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4" + "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4", + "$['menu']['settings']": "d43fb8a961ff2d1f037995587ed8883ac4b733ecaf1b0b74201123ada13df810", + "$['settings']['toast']": "36ffa4529bb50637e9f0d1e3d1c209ae8246236ea4e856d95ddcf993b5db4e2c", + "$['settings']['settings']": "74a883a037bc227f91891ab654a753d3a99f31ab06ae5b5d2b6e594a692b41f8", + "$['settings']['description']": "86095b212ba6d2fc7e54c102b3de1f62e698aee75939b54e12de918f6c060a5c", + "$['settings']['analytics']": "94c116ee118a72998db6cd10b586a9ef112a1891ff8ced8c7b2944ff62453b5f", + "$['settings']['analytics-description']": "b1cc043af19eedc5e22078ed0ef859091b321f0e2921ab915651e52c3ba42c8e", + "$['settings']['logs']": "ea2100dc89ae9fe21fa9b08ab1bf18662dca1e53a3eebd7d03afebcaf5d57515", + "$['settings']['logs-description']": "af971f78c75f6b9a8ae534b23a094723837e42415c1246923b746df5c80b84d7", + "$['settings']['open-logs']": "ed077f3d8125d60dca1979c7133601bd187d47c73ed9975028f677e49e709942", + "$['settings']['update']": "46ed69579c396feaa780e716e778b9dea387bebfe925e9d661ec6882c96525e9", + "$['settings']['error']": "63f6bf5375c13518fbc291863e4715083eeb5d50fa2c2aa00cdf3958267f693b" }, "fi": { "$['header']['popular']": "76327dec9ae3a06a8c3c283e6a81d3710ae736021b583875c13e4e8fb2ad83c0", @@ -5365,7 +5475,18 @@ "$['onboardingProviders']['selected']": "eef30365e9cc4bd8da360e251728fa69114d8cdf133b093249ee07223b2a7abb", "$['onboardingProviders']['noFound']": "dc3a0116c7c3d33dffde52310d11c2b039904039d5e13b4c915f621c7167ecf4", "$['onboardingPreferences']['showAll']": "ebd10fbf3cb038b4a7355c15c166c2deef946af74a1969b55f51faf5dc9cf501", - "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4" + "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4", + "$['menu']['settings']": "d43fb8a961ff2d1f037995587ed8883ac4b733ecaf1b0b74201123ada13df810", + "$['settings']['toast']": "36ffa4529bb50637e9f0d1e3d1c209ae8246236ea4e856d95ddcf993b5db4e2c", + "$['settings']['settings']": "74a883a037bc227f91891ab654a753d3a99f31ab06ae5b5d2b6e594a692b41f8", + "$['settings']['description']": "86095b212ba6d2fc7e54c102b3de1f62e698aee75939b54e12de918f6c060a5c", + "$['settings']['analytics']": "94c116ee118a72998db6cd10b586a9ef112a1891ff8ced8c7b2944ff62453b5f", + "$['settings']['analytics-description']": "b1cc043af19eedc5e22078ed0ef859091b321f0e2921ab915651e52c3ba42c8e", + "$['settings']['logs']": "ea2100dc89ae9fe21fa9b08ab1bf18662dca1e53a3eebd7d03afebcaf5d57515", + "$['settings']['logs-description']": "af971f78c75f6b9a8ae534b23a094723837e42415c1246923b746df5c80b84d7", + "$['settings']['open-logs']": "ed077f3d8125d60dca1979c7133601bd187d47c73ed9975028f677e49e709942", + "$['settings']['update']": "46ed69579c396feaa780e716e778b9dea387bebfe925e9d661ec6882c96525e9", + "$['settings']['error']": "63f6bf5375c13518fbc291863e4715083eeb5d50fa2c2aa00cdf3958267f693b" }, "he": { "$['header']['popular']": "76327dec9ae3a06a8c3c283e6a81d3710ae736021b583875c13e4e8fb2ad83c0", @@ -5853,7 +5974,18 @@ "$['onboardingProviders']['selected']": "eef30365e9cc4bd8da360e251728fa69114d8cdf133b093249ee07223b2a7abb", "$['onboardingProviders']['noFound']": "dc3a0116c7c3d33dffde52310d11c2b039904039d5e13b4c915f621c7167ecf4", "$['onboardingPreferences']['showAll']": "ebd10fbf3cb038b4a7355c15c166c2deef946af74a1969b55f51faf5dc9cf501", - "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4" + "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4", + "$['menu']['settings']": "d43fb8a961ff2d1f037995587ed8883ac4b733ecaf1b0b74201123ada13df810", + "$['settings']['toast']": "36ffa4529bb50637e9f0d1e3d1c209ae8246236ea4e856d95ddcf993b5db4e2c", + "$['settings']['settings']": "74a883a037bc227f91891ab654a753d3a99f31ab06ae5b5d2b6e594a692b41f8", + "$['settings']['description']": "86095b212ba6d2fc7e54c102b3de1f62e698aee75939b54e12de918f6c060a5c", + "$['settings']['analytics']": "94c116ee118a72998db6cd10b586a9ef112a1891ff8ced8c7b2944ff62453b5f", + "$['settings']['analytics-description']": "b1cc043af19eedc5e22078ed0ef859091b321f0e2921ab915651e52c3ba42c8e", + "$['settings']['logs']": "ea2100dc89ae9fe21fa9b08ab1bf18662dca1e53a3eebd7d03afebcaf5d57515", + "$['settings']['logs-description']": "af971f78c75f6b9a8ae534b23a094723837e42415c1246923b746df5c80b84d7", + "$['settings']['open-logs']": "ed077f3d8125d60dca1979c7133601bd187d47c73ed9975028f677e49e709942", + "$['settings']['update']": "46ed69579c396feaa780e716e778b9dea387bebfe925e9d661ec6882c96525e9", + "$['settings']['error']": "63f6bf5375c13518fbc291863e4715083eeb5d50fa2c2aa00cdf3958267f693b" }, "no": { "$['header']['popular']": "76327dec9ae3a06a8c3c283e6a81d3710ae736021b583875c13e4e8fb2ad83c0", @@ -6341,7 +6473,18 @@ "$['onboardingProviders']['selected']": "eef30365e9cc4bd8da360e251728fa69114d8cdf133b093249ee07223b2a7abb", "$['onboardingProviders']['noFound']": "dc3a0116c7c3d33dffde52310d11c2b039904039d5e13b4c915f621c7167ecf4", "$['onboardingPreferences']['showAll']": "ebd10fbf3cb038b4a7355c15c166c2deef946af74a1969b55f51faf5dc9cf501", - "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4" + "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4", + "$['menu']['settings']": "d43fb8a961ff2d1f037995587ed8883ac4b733ecaf1b0b74201123ada13df810", + "$['settings']['toast']": "36ffa4529bb50637e9f0d1e3d1c209ae8246236ea4e856d95ddcf993b5db4e2c", + "$['settings']['settings']": "74a883a037bc227f91891ab654a753d3a99f31ab06ae5b5d2b6e594a692b41f8", + "$['settings']['description']": "86095b212ba6d2fc7e54c102b3de1f62e698aee75939b54e12de918f6c060a5c", + "$['settings']['analytics']": "94c116ee118a72998db6cd10b586a9ef112a1891ff8ced8c7b2944ff62453b5f", + "$['settings']['analytics-description']": "b1cc043af19eedc5e22078ed0ef859091b321f0e2921ab915651e52c3ba42c8e", + "$['settings']['logs']": "ea2100dc89ae9fe21fa9b08ab1bf18662dca1e53a3eebd7d03afebcaf5d57515", + "$['settings']['logs-description']": "af971f78c75f6b9a8ae534b23a094723837e42415c1246923b746df5c80b84d7", + "$['settings']['open-logs']": "ed077f3d8125d60dca1979c7133601bd187d47c73ed9975028f677e49e709942", + "$['settings']['update']": "46ed69579c396feaa780e716e778b9dea387bebfe925e9d661ec6882c96525e9", + "$['settings']['error']": "63f6bf5375c13518fbc291863e4715083eeb5d50fa2c2aa00cdf3958267f693b" }, "da": { "$['header']['popular']": "76327dec9ae3a06a8c3c283e6a81d3710ae736021b583875c13e4e8fb2ad83c0", @@ -6829,7 +6972,18 @@ "$['onboardingProviders']['selected']": "eef30365e9cc4bd8da360e251728fa69114d8cdf133b093249ee07223b2a7abb", "$['onboardingProviders']['noFound']": "dc3a0116c7c3d33dffde52310d11c2b039904039d5e13b4c915f621c7167ecf4", "$['onboardingPreferences']['showAll']": "ebd10fbf3cb038b4a7355c15c166c2deef946af74a1969b55f51faf5dc9cf501", - "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4" + "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4", + "$['menu']['settings']": "d43fb8a961ff2d1f037995587ed8883ac4b733ecaf1b0b74201123ada13df810", + "$['settings']['toast']": "36ffa4529bb50637e9f0d1e3d1c209ae8246236ea4e856d95ddcf993b5db4e2c", + "$['settings']['settings']": "74a883a037bc227f91891ab654a753d3a99f31ab06ae5b5d2b6e594a692b41f8", + "$['settings']['description']": "86095b212ba6d2fc7e54c102b3de1f62e698aee75939b54e12de918f6c060a5c", + "$['settings']['analytics']": "94c116ee118a72998db6cd10b586a9ef112a1891ff8ced8c7b2944ff62453b5f", + "$['settings']['analytics-description']": "b1cc043af19eedc5e22078ed0ef859091b321f0e2921ab915651e52c3ba42c8e", + "$['settings']['logs']": "ea2100dc89ae9fe21fa9b08ab1bf18662dca1e53a3eebd7d03afebcaf5d57515", + "$['settings']['logs-description']": "af971f78c75f6b9a8ae534b23a094723837e42415c1246923b746df5c80b84d7", + "$['settings']['open-logs']": "ed077f3d8125d60dca1979c7133601bd187d47c73ed9975028f677e49e709942", + "$['settings']['update']": "46ed69579c396feaa780e716e778b9dea387bebfe925e9d661ec6882c96525e9", + "$['settings']['error']": "63f6bf5375c13518fbc291863e4715083eeb5d50fa2c2aa00cdf3958267f693b" }, "it": { "$['header']['popular']": "76327dec9ae3a06a8c3c283e6a81d3710ae736021b583875c13e4e8fb2ad83c0", @@ -7317,7 +7471,18 @@ "$['onboardingProviders']['selected']": "eef30365e9cc4bd8da360e251728fa69114d8cdf133b093249ee07223b2a7abb", "$['onboardingProviders']['noFound']": "dc3a0116c7c3d33dffde52310d11c2b039904039d5e13b4c915f621c7167ecf4", "$['onboardingPreferences']['showAll']": "ebd10fbf3cb038b4a7355c15c166c2deef946af74a1969b55f51faf5dc9cf501", - "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4" + "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4", + "$['menu']['settings']": "d43fb8a961ff2d1f037995587ed8883ac4b733ecaf1b0b74201123ada13df810", + "$['settings']['toast']": "36ffa4529bb50637e9f0d1e3d1c209ae8246236ea4e856d95ddcf993b5db4e2c", + "$['settings']['settings']": "74a883a037bc227f91891ab654a753d3a99f31ab06ae5b5d2b6e594a692b41f8", + "$['settings']['description']": "86095b212ba6d2fc7e54c102b3de1f62e698aee75939b54e12de918f6c060a5c", + "$['settings']['analytics']": "94c116ee118a72998db6cd10b586a9ef112a1891ff8ced8c7b2944ff62453b5f", + "$['settings']['analytics-description']": "b1cc043af19eedc5e22078ed0ef859091b321f0e2921ab915651e52c3ba42c8e", + "$['settings']['logs']": "ea2100dc89ae9fe21fa9b08ab1bf18662dca1e53a3eebd7d03afebcaf5d57515", + "$['settings']['logs-description']": "af971f78c75f6b9a8ae534b23a094723837e42415c1246923b746df5c80b84d7", + "$['settings']['open-logs']": "ed077f3d8125d60dca1979c7133601bd187d47c73ed9975028f677e49e709942", + "$['settings']['update']": "46ed69579c396feaa780e716e778b9dea387bebfe925e9d661ec6882c96525e9", + "$['settings']['error']": "63f6bf5375c13518fbc291863e4715083eeb5d50fa2c2aa00cdf3958267f693b" }, "ja": { "$['header']['popular']": "76327dec9ae3a06a8c3c283e6a81d3710ae736021b583875c13e4e8fb2ad83c0", @@ -7805,7 +7970,18 @@ "$['onboardingProviders']['selected']": "eef30365e9cc4bd8da360e251728fa69114d8cdf133b093249ee07223b2a7abb", "$['onboardingProviders']['noFound']": "dc3a0116c7c3d33dffde52310d11c2b039904039d5e13b4c915f621c7167ecf4", "$['onboardingPreferences']['showAll']": "ebd10fbf3cb038b4a7355c15c166c2deef946af74a1969b55f51faf5dc9cf501", - "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4" + "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4", + "$['menu']['settings']": "d43fb8a961ff2d1f037995587ed8883ac4b733ecaf1b0b74201123ada13df810", + "$['settings']['toast']": "36ffa4529bb50637e9f0d1e3d1c209ae8246236ea4e856d95ddcf993b5db4e2c", + "$['settings']['settings']": "74a883a037bc227f91891ab654a753d3a99f31ab06ae5b5d2b6e594a692b41f8", + "$['settings']['description']": "86095b212ba6d2fc7e54c102b3de1f62e698aee75939b54e12de918f6c060a5c", + "$['settings']['analytics']": "94c116ee118a72998db6cd10b586a9ef112a1891ff8ced8c7b2944ff62453b5f", + "$['settings']['analytics-description']": "b1cc043af19eedc5e22078ed0ef859091b321f0e2921ab915651e52c3ba42c8e", + "$['settings']['logs']": "ea2100dc89ae9fe21fa9b08ab1bf18662dca1e53a3eebd7d03afebcaf5d57515", + "$['settings']['logs-description']": "af971f78c75f6b9a8ae534b23a094723837e42415c1246923b746df5c80b84d7", + "$['settings']['open-logs']": "ed077f3d8125d60dca1979c7133601bd187d47c73ed9975028f677e49e709942", + "$['settings']['update']": "46ed69579c396feaa780e716e778b9dea387bebfe925e9d661ec6882c96525e9", + "$['settings']['error']": "63f6bf5375c13518fbc291863e4715083eeb5d50fa2c2aa00cdf3958267f693b" }, "pl": { "$['header']['popular']": "76327dec9ae3a06a8c3c283e6a81d3710ae736021b583875c13e4e8fb2ad83c0", @@ -8293,7 +8469,18 @@ "$['onboardingProviders']['selected']": "eef30365e9cc4bd8da360e251728fa69114d8cdf133b093249ee07223b2a7abb", "$['onboardingProviders']['noFound']": "dc3a0116c7c3d33dffde52310d11c2b039904039d5e13b4c915f621c7167ecf4", "$['onboardingPreferences']['showAll']": "ebd10fbf3cb038b4a7355c15c166c2deef946af74a1969b55f51faf5dc9cf501", - "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4" + "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4", + "$['menu']['settings']": "d43fb8a961ff2d1f037995587ed8883ac4b733ecaf1b0b74201123ada13df810", + "$['settings']['toast']": "36ffa4529bb50637e9f0d1e3d1c209ae8246236ea4e856d95ddcf993b5db4e2c", + "$['settings']['settings']": "74a883a037bc227f91891ab654a753d3a99f31ab06ae5b5d2b6e594a692b41f8", + "$['settings']['description']": "86095b212ba6d2fc7e54c102b3de1f62e698aee75939b54e12de918f6c060a5c", + "$['settings']['analytics']": "94c116ee118a72998db6cd10b586a9ef112a1891ff8ced8c7b2944ff62453b5f", + "$['settings']['analytics-description']": "b1cc043af19eedc5e22078ed0ef859091b321f0e2921ab915651e52c3ba42c8e", + "$['settings']['logs']": "ea2100dc89ae9fe21fa9b08ab1bf18662dca1e53a3eebd7d03afebcaf5d57515", + "$['settings']['logs-description']": "af971f78c75f6b9a8ae534b23a094723837e42415c1246923b746df5c80b84d7", + "$['settings']['open-logs']": "ed077f3d8125d60dca1979c7133601bd187d47c73ed9975028f677e49e709942", + "$['settings']['update']": "46ed69579c396feaa780e716e778b9dea387bebfe925e9d661ec6882c96525e9", + "$['settings']['error']": "63f6bf5375c13518fbc291863e4715083eeb5d50fa2c2aa00cdf3958267f693b" }, "tr": { "$['header']['popular']": "76327dec9ae3a06a8c3c283e6a81d3710ae736021b583875c13e4e8fb2ad83c0", @@ -8781,7 +8968,18 @@ "$['onboardingProviders']['selected']": "eef30365e9cc4bd8da360e251728fa69114d8cdf133b093249ee07223b2a7abb", "$['onboardingProviders']['noFound']": "dc3a0116c7c3d33dffde52310d11c2b039904039d5e13b4c915f621c7167ecf4", "$['onboardingPreferences']['showAll']": "ebd10fbf3cb038b4a7355c15c166c2deef946af74a1969b55f51faf5dc9cf501", - "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4" + "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4", + "$['menu']['settings']": "d43fb8a961ff2d1f037995587ed8883ac4b733ecaf1b0b74201123ada13df810", + "$['settings']['toast']": "36ffa4529bb50637e9f0d1e3d1c209ae8246236ea4e856d95ddcf993b5db4e2c", + "$['settings']['settings']": "74a883a037bc227f91891ab654a753d3a99f31ab06ae5b5d2b6e594a692b41f8", + "$['settings']['description']": "86095b212ba6d2fc7e54c102b3de1f62e698aee75939b54e12de918f6c060a5c", + "$['settings']['analytics']": "94c116ee118a72998db6cd10b586a9ef112a1891ff8ced8c7b2944ff62453b5f", + "$['settings']['analytics-description']": "b1cc043af19eedc5e22078ed0ef859091b321f0e2921ab915651e52c3ba42c8e", + "$['settings']['logs']": "ea2100dc89ae9fe21fa9b08ab1bf18662dca1e53a3eebd7d03afebcaf5d57515", + "$['settings']['logs-description']": "af971f78c75f6b9a8ae534b23a094723837e42415c1246923b746df5c80b84d7", + "$['settings']['open-logs']": "ed077f3d8125d60dca1979c7133601bd187d47c73ed9975028f677e49e709942", + "$['settings']['update']": "46ed69579c396feaa780e716e778b9dea387bebfe925e9d661ec6882c96525e9", + "$['settings']['error']": "63f6bf5375c13518fbc291863e4715083eeb5d50fa2c2aa00cdf3958267f693b" }, "et": { "$['header']['popular']": "76327dec9ae3a06a8c3c283e6a81d3710ae736021b583875c13e4e8fb2ad83c0", @@ -9269,7 +9467,18 @@ "$['onboardingProviders']['selected']": "eef30365e9cc4bd8da360e251728fa69114d8cdf133b093249ee07223b2a7abb", "$['onboardingProviders']['noFound']": "dc3a0116c7c3d33dffde52310d11c2b039904039d5e13b4c915f621c7167ecf4", "$['onboardingPreferences']['showAll']": "ebd10fbf3cb038b4a7355c15c166c2deef946af74a1969b55f51faf5dc9cf501", - "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4" + "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4", + "$['menu']['settings']": "d43fb8a961ff2d1f037995587ed8883ac4b733ecaf1b0b74201123ada13df810", + "$['settings']['toast']": "36ffa4529bb50637e9f0d1e3d1c209ae8246236ea4e856d95ddcf993b5db4e2c", + "$['settings']['settings']": "74a883a037bc227f91891ab654a753d3a99f31ab06ae5b5d2b6e594a692b41f8", + "$['settings']['description']": "86095b212ba6d2fc7e54c102b3de1f62e698aee75939b54e12de918f6c060a5c", + "$['settings']['analytics']": "94c116ee118a72998db6cd10b586a9ef112a1891ff8ced8c7b2944ff62453b5f", + "$['settings']['analytics-description']": "b1cc043af19eedc5e22078ed0ef859091b321f0e2921ab915651e52c3ba42c8e", + "$['settings']['logs']": "ea2100dc89ae9fe21fa9b08ab1bf18662dca1e53a3eebd7d03afebcaf5d57515", + "$['settings']['logs-description']": "af971f78c75f6b9a8ae534b23a094723837e42415c1246923b746df5c80b84d7", + "$['settings']['open-logs']": "ed077f3d8125d60dca1979c7133601bd187d47c73ed9975028f677e49e709942", + "$['settings']['update']": "46ed69579c396feaa780e716e778b9dea387bebfe925e9d661ec6882c96525e9", + "$['settings']['error']": "63f6bf5375c13518fbc291863e4715083eeb5d50fa2c2aa00cdf3958267f693b" }, "el": { "$['header']['popular']": "76327dec9ae3a06a8c3c283e6a81d3710ae736021b583875c13e4e8fb2ad83c0", @@ -9757,7 +9966,18 @@ "$['onboardingProviders']['selected']": "eef30365e9cc4bd8da360e251728fa69114d8cdf133b093249ee07223b2a7abb", "$['onboardingProviders']['noFound']": "dc3a0116c7c3d33dffde52310d11c2b039904039d5e13b4c915f621c7167ecf4", "$['onboardingPreferences']['showAll']": "ebd10fbf3cb038b4a7355c15c166c2deef946af74a1969b55f51faf5dc9cf501", - "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4" + "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4", + "$['menu']['settings']": "d43fb8a961ff2d1f037995587ed8883ac4b733ecaf1b0b74201123ada13df810", + "$['settings']['toast']": "36ffa4529bb50637e9f0d1e3d1c209ae8246236ea4e856d95ddcf993b5db4e2c", + "$['settings']['settings']": "74a883a037bc227f91891ab654a753d3a99f31ab06ae5b5d2b6e594a692b41f8", + "$['settings']['description']": "86095b212ba6d2fc7e54c102b3de1f62e698aee75939b54e12de918f6c060a5c", + "$['settings']['analytics']": "94c116ee118a72998db6cd10b586a9ef112a1891ff8ced8c7b2944ff62453b5f", + "$['settings']['analytics-description']": "b1cc043af19eedc5e22078ed0ef859091b321f0e2921ab915651e52c3ba42c8e", + "$['settings']['logs']": "ea2100dc89ae9fe21fa9b08ab1bf18662dca1e53a3eebd7d03afebcaf5d57515", + "$['settings']['logs-description']": "af971f78c75f6b9a8ae534b23a094723837e42415c1246923b746df5c80b84d7", + "$['settings']['open-logs']": "ed077f3d8125d60dca1979c7133601bd187d47c73ed9975028f677e49e709942", + "$['settings']['update']": "46ed69579c396feaa780e716e778b9dea387bebfe925e9d661ec6882c96525e9", + "$['settings']['error']": "63f6bf5375c13518fbc291863e4715083eeb5d50fa2c2aa00cdf3958267f693b" }, "pt": { "$['header']['popular']": "76327dec9ae3a06a8c3c283e6a81d3710ae736021b583875c13e4e8fb2ad83c0", @@ -10245,7 +10465,18 @@ "$['onboardingProviders']['selected']": "eef30365e9cc4bd8da360e251728fa69114d8cdf133b093249ee07223b2a7abb", "$['onboardingProviders']['noFound']": "dc3a0116c7c3d33dffde52310d11c2b039904039d5e13b4c915f621c7167ecf4", "$['onboardingPreferences']['showAll']": "ebd10fbf3cb038b4a7355c15c166c2deef946af74a1969b55f51faf5dc9cf501", - "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4" + "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4", + "$['menu']['settings']": "d43fb8a961ff2d1f037995587ed8883ac4b733ecaf1b0b74201123ada13df810", + "$['settings']['toast']": "36ffa4529bb50637e9f0d1e3d1c209ae8246236ea4e856d95ddcf993b5db4e2c", + "$['settings']['settings']": "74a883a037bc227f91891ab654a753d3a99f31ab06ae5b5d2b6e594a692b41f8", + "$['settings']['description']": "86095b212ba6d2fc7e54c102b3de1f62e698aee75939b54e12de918f6c060a5c", + "$['settings']['analytics']": "94c116ee118a72998db6cd10b586a9ef112a1891ff8ced8c7b2944ff62453b5f", + "$['settings']['analytics-description']": "b1cc043af19eedc5e22078ed0ef859091b321f0e2921ab915651e52c3ba42c8e", + "$['settings']['logs']": "ea2100dc89ae9fe21fa9b08ab1bf18662dca1e53a3eebd7d03afebcaf5d57515", + "$['settings']['logs-description']": "af971f78c75f6b9a8ae534b23a094723837e42415c1246923b746df5c80b84d7", + "$['settings']['open-logs']": "ed077f3d8125d60dca1979c7133601bd187d47c73ed9975028f677e49e709942", + "$['settings']['update']": "46ed69579c396feaa780e716e778b9dea387bebfe925e9d661ec6882c96525e9", + "$['settings']['error']": "63f6bf5375c13518fbc291863e4715083eeb5d50fa2c2aa00cdf3958267f693b" }, "sr": { "$['header']['popular']": "76327dec9ae3a06a8c3c283e6a81d3710ae736021b583875c13e4e8fb2ad83c0", @@ -10733,6 +10964,17 @@ "$['onboardingProviders']['selected']": "eef30365e9cc4bd8da360e251728fa69114d8cdf133b093249ee07223b2a7abb", "$['onboardingProviders']['noFound']": "dc3a0116c7c3d33dffde52310d11c2b039904039d5e13b4c915f621c7167ecf4", "$['onboardingPreferences']['showAll']": "ebd10fbf3cb038b4a7355c15c166c2deef946af74a1969b55f51faf5dc9cf501", - "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4" + "$['onboardingProviders']['selectCountry']": "e19b22ef6d936dbebc4cdb5ca340aa74af6b18c5b10115959c640d85a600a9d4", + "$['menu']['settings']": "d43fb8a961ff2d1f037995587ed8883ac4b733ecaf1b0b74201123ada13df810", + "$['settings']['toast']": "36ffa4529bb50637e9f0d1e3d1c209ae8246236ea4e856d95ddcf993b5db4e2c", + "$['settings']['settings']": "74a883a037bc227f91891ab654a753d3a99f31ab06ae5b5d2b6e594a692b41f8", + "$['settings']['description']": "86095b212ba6d2fc7e54c102b3de1f62e698aee75939b54e12de918f6c060a5c", + "$['settings']['analytics']": "94c116ee118a72998db6cd10b586a9ef112a1891ff8ced8c7b2944ff62453b5f", + "$['settings']['analytics-description']": "b1cc043af19eedc5e22078ed0ef859091b321f0e2921ab915651e52c3ba42c8e", + "$['settings']['logs']": "ea2100dc89ae9fe21fa9b08ab1bf18662dca1e53a3eebd7d03afebcaf5d57515", + "$['settings']['logs-description']": "af971f78c75f6b9a8ae534b23a094723837e42415c1246923b746df5c80b84d7", + "$['settings']['open-logs']": "ed077f3d8125d60dca1979c7133601bd187d47c73ed9975028f677e49e709942", + "$['settings']['update']": "46ed69579c396feaa780e716e778b9dea387bebfe925e9d661ec6882c96525e9", + "$['settings']['error']": "63f6bf5375c13518fbc291863e4715083eeb5d50fa2c2aa00cdf3958267f693b" } } \ No newline at end of file diff --git a/crates/popcorntime-tauri/dictionaries/ar.json b/crates/popcorntime-tauri/dictionaries/ar.json index 467b6ad18..132357b17 100644 --- a/crates/popcorntime-tauri/dictionaries/ar.json +++ b/crates/popcorntime-tauri/dictionaries/ar.json @@ -43,10 +43,21 @@ "menu": { "preferences": "اللغة والمنطقة", "watchPreferences": "تفضيلات المشاهدة", - "manifest": "بيان", - "logs": "سجلات التصحيح", + "settings": "إعدادات التطبيق", "signOut": "تسجيل الخروج" }, + "settings": { + "toast": "تم تحديث إعداداتك بنجاح.", + "settings": "الإعدادات", + "description": "قم بتكوين خيارات خاصة بالتطبيق مثل التحليلات والسمات والتفضيلات المحلية الأخرى.", + "analytics": "تحليلات", + "analytics-description": "إرسال بيانات الاستخدام المجهولة للمساعدة في تحسين التطبيق وتوجيه التطوير.", + "logs": "السجلات", + "logs-description": "عرض سجلات التطبيق لتصحيح الأخطاء واستكشاف المشكلات.", + "open-logs": "يفتح", + "update": "تحديث الإعدادات", + "error": "فشل في تحديث الإعدادات" + }, "preferences": { "preferences": "التفضيلات", "description": "اختر لغتك وبلدك المفضلين للاستمتاع بمحتوى مخصص.", diff --git a/crates/popcorntime-tauri/dictionaries/da.json b/crates/popcorntime-tauri/dictionaries/da.json index e56ed5299..13c07961b 100644 --- a/crates/popcorntime-tauri/dictionaries/da.json +++ b/crates/popcorntime-tauri/dictionaries/da.json @@ -43,10 +43,21 @@ "menu": { "preferences": "Sprog og region", "watchPreferences": "Seerpræferencer", - "manifest": "Manifest", - "logs": "Fejlretningslogfiler", + "settings": "App-indstillinger", "signOut": "Log ud" }, + "settings": { + "toast": "Dine indstillinger er blevet opdateret med succes.", + "settings": "Indstillinger", + "description": "Konfigurer app-specifikke indstillinger som analyser, temaer og andre lokale præferencer.", + "analytics": "Analyser", + "analytics-description": "Send anonyme brugsdata for at hjælpe med at forbedre appen og guide udviklingen.", + "logs": "Logfiler", + "logs-description": "Se applikationslogfiler for fejlfinding og problemløsning.", + "open-logs": "Åben", + "update": "Opdater indstillinger", + "error": "Kunne ikke opdatere indstillingerne" + }, "preferences": { "preferences": "Indstillinger", "description": "Vælg dit foretrukne sprog og land for at nyde skræddersyet indhold.", diff --git a/crates/popcorntime-tauri/dictionaries/de.json b/crates/popcorntime-tauri/dictionaries/de.json index 019515f46..e965001ad 100644 --- a/crates/popcorntime-tauri/dictionaries/de.json +++ b/crates/popcorntime-tauri/dictionaries/de.json @@ -43,10 +43,21 @@ "menu": { "preferences": "Sprache & Region", "watchPreferences": "Sehgewohnheiten", - "manifest": "Manifest", - "logs": "Debug-Protokolle", + "settings": "App-Einstellungen", "signOut": "Abmelden" }, + "settings": { + "toast": "Ihre Einstellungen wurden erfolgreich aktualisiert.", + "settings": "Einstellungen", + "description": "Konfigurieren Sie app-spezifische Optionen wie Analysen, Themen und andere lokale Einstellungen.", + "analytics": "Analytik", + "analytics-description": "Sende anonyme Nutzungsdaten, um die App zu verbessern und die Entwicklung zu steuern.", + "logs": "Protokolle", + "logs-description": "Anwendungsprotokolle zur Fehlerbehebung und Fehlersuche anzeigen.", + "open-logs": "Offen", + "update": "Einstellungen aktualisieren", + "error": "Aktualisierung der Einstellungen fehlgeschlagen" + }, "preferences": { "preferences": "Einstellungen", "description": "Wählen Sie Ihre bevorzugte Sprache und Ihr Land aus, um maßgeschneiderte Inhalte zu genießen.", diff --git a/crates/popcorntime-tauri/dictionaries/el.json b/crates/popcorntime-tauri/dictionaries/el.json index 8c648b760..6909619e4 100644 --- a/crates/popcorntime-tauri/dictionaries/el.json +++ b/crates/popcorntime-tauri/dictionaries/el.json @@ -43,10 +43,21 @@ "menu": { "preferences": "Γλώσσα & περιοχή", "watchPreferences": "Προτιμήσεις παρακολούθησης", - "manifest": "μανιφέστο", - "logs": "Αρχεία καταγραφής εντοπισμού σφαλμάτων", + "settings": "Ρυθμίσεις εφαρμογής", "signOut": "Αποσύνδεση" }, + "settings": { + "toast": "Οι ρυθμίσεις σας έχουν ενημερωθεί με επιτυχία.", + "settings": "Ρυθμίσεις", + "description": "Ρυθμίστε επιλογές συγκεκριμένες για την εφαρμογή όπως αναλύσεις, θέματα και άλλες τοπικές προτιμήσεις.", + "analytics": "Αναλύσεις", + "analytics-description": "Στείλτε ανώνυμα δεδομένα χρήσης για να βοηθήσετε στη βελτίωση της εφαρμογής και να καθοδηγήσετε την ανάπτυξη.", + "logs": "Αρχεία καταγραφής", + "logs-description": "Προβολή των αρχείων καταγραφής της εφαρμογής για εντοπισμό και επίλυση προβλημάτων.", + "open-logs": "Ανοιχτό", + "update": "Ρυθμίσεις ενημέρωσης", + "error": "Αποτυχία ενημέρωσης ρυθμίσεων" + }, "preferences": { "preferences": "Προτιμήσεις", "description": "Επιλέξτε την προτιμώμενη γλώσσα και χώρα σας για να απολαμβάνετε προσαρμοσμένο περιεχόμενο.", diff --git a/crates/popcorntime-tauri/dictionaries/en.json b/crates/popcorntime-tauri/dictionaries/en.json index 33910dd8e..19ce4e34c 100644 --- a/crates/popcorntime-tauri/dictionaries/en.json +++ b/crates/popcorntime-tauri/dictionaries/en.json @@ -43,10 +43,21 @@ "menu": { "preferences": "Language & region", "watchPreferences": "Watch preferences", - "manifest": "Manifesto", - "logs": "Debug logs", + "settings": "App settings", "signOut": "Sign out" }, + "settings": { + "toast": "Your settings have been successfully updated.", + "settings": "Settings", + "description": "Configure app-specific options like analytics, themes, and other local preferences.", + "analytics": "Analytics", + "analytics-description": "Send anonymous usage data to help improve the app and guide development.", + "logs": "Logs", + "logs-description": "View application logs for debugging and troubleshooting.", + "open-logs": "Open", + "update": "Update settings", + "error": "Failed to update settings" + }, "preferences": { "preferences": "Preferences", "description": "Select your preferred language and country to enjoy tailored content.", diff --git a/crates/popcorntime-tauri/dictionaries/es.json b/crates/popcorntime-tauri/dictionaries/es.json index 5001adfea..a9de85f68 100644 --- a/crates/popcorntime-tauri/dictionaries/es.json +++ b/crates/popcorntime-tauri/dictionaries/es.json @@ -43,10 +43,21 @@ "menu": { "preferences": "Idioma y región", "watchPreferences": "Preferencias de visualización", - "manifest": "Manifiesto", - "logs": "Registros de depuración", + "settings": "Configuración de la aplicación", "signOut": "Cerrar sesión" }, + "settings": { + "toast": "Tus configuraciones se han actualizado correctamente.", + "settings": "Configuración", + "description": "Configura opciones específicas de la aplicación como analíticas, temas y otras preferencias locales.", + "analytics": "Analíticas", + "analytics-description": "Enviar datos de uso anónimos para ayudar a mejorar la aplicación y guiar su desarrollo.", + "logs": "Registros", + "logs-description": "Ver registros de la aplicación para depuración y resolución de problemas.", + "open-logs": "Abierto", + "update": "Configuración de actualización", + "error": "Error al actualizar la configuración" + }, "preferences": { "preferences": "Preferencias", "description": "Selecciona tu idioma y país preferidos para disfrutar de contenido adaptado.", diff --git a/crates/popcorntime-tauri/dictionaries/et.json b/crates/popcorntime-tauri/dictionaries/et.json index 6bb9fbdb1..9bceff542 100644 --- a/crates/popcorntime-tauri/dictionaries/et.json +++ b/crates/popcorntime-tauri/dictionaries/et.json @@ -43,10 +43,21 @@ "menu": { "preferences": "Keel ja piirkond", "watchPreferences": "Vaatamise eelistused", - "manifest": "Manifesto", - "logs": "Logid", + "settings": "Rakenduse seaded", "signOut": "Logi välja" }, + "settings": { + "toast": "Seerotaatewochin keffilachehu.", + "settings": "አቀማመጦች", + "description": "የመተግበሪያ ልዩ አማራጮችን እንደ ትንታኔዎች፣ ገጽታዎች እና ሌሎች አካባቢ ተመሳሳይ ቅድመ አላባት ያቀናብሩ።", + "analytics": "Analüüsid", + "analytics-description": "Saada anonüümset kasutusandmeid, et aidata rakenduse täiustamisel ja arenduse suunamisel.", + "logs": "Logid", + "logs-description": "Rakibata galmee raawwii barnootaa fi rakkoo hiikuu ilaaluu.", + "open-logs": "Avatud", + "update": "አማራጮችን አዘምን", + "error": "ቅኝቱን ማሻሻል አልተቻለም" + }, "preferences": { "preferences": "ቅደም ተከተል፦", "description": "Valitud sisu nautimiseks valige oma eelistatud keel ja riik.", diff --git a/crates/popcorntime-tauri/dictionaries/fa.json b/crates/popcorntime-tauri/dictionaries/fa.json index 61d3e364e..4b3c3960a 100644 --- a/crates/popcorntime-tauri/dictionaries/fa.json +++ b/crates/popcorntime-tauri/dictionaries/fa.json @@ -43,10 +43,21 @@ "menu": { "preferences": "زبان و منطقه", "watchPreferences": "ترجیحات تماشا", - "manifest": "مانیفست", - "logs": "گزارش‌های اشکال‌زدایی", + "settings": "تنظیمات برنامه", "signOut": "خروج از حساب" }, + "settings": { + "toast": "تنظیمات شما با موفقیت به‌روزرسانی شدند.", + "settings": "تنظیمات", + "description": "تنظیم گزینه‌های خاص برنامه مانند تحلیل‌ها، تم‌ها و سایر تنظیمات محلی.", + "analytics": "تجزیه و تحلیل", + "analytics-description": "ارسال داده‌های ناشناس استفاده برای کمک به بهبود اپلیکیشن و هدایت توسعه.", + "logs": "سیاههها", + "logs-description": "مشاهده لاگ‌های برنامه برای اشکال‌زدایی و رفع مشکلات.", + "open-logs": "باز", + "update": "تنظیمات به‌روزرسانی", + "error": "تنظیمات به‌روزرسانی نشد" + }, "preferences": { "preferences": "تنظیمات", "description": "زبان و کشور مورد نظر خود را انتخاب کنید تا از محتوای متناسب با سلیقه خود لذت ببرید.", diff --git a/crates/popcorntime-tauri/dictionaries/fi.json b/crates/popcorntime-tauri/dictionaries/fi.json index 7f9c296aa..c72a6fa25 100644 --- a/crates/popcorntime-tauri/dictionaries/fi.json +++ b/crates/popcorntime-tauri/dictionaries/fi.json @@ -43,10 +43,21 @@ "menu": { "preferences": "Kieli ja alue", "watchPreferences": "Katseluvalinnat", - "manifest": "Manifesti", - "logs": "Virhelokin kirjaus", + "settings": "Sovelluksen asetukset", "signOut": "Kirjaudu ulos" }, + "settings": { + "toast": "Asetuksesi on päivitetty onnistuneesti.", + "settings": "Asetukset", + "description": "Määritä sovelluskohtaisia asetuksia, kuten analytiikkaa, teemoja ja muita paikallisia mieltymyksiä.", + "analytics": "Analytiikka", + "analytics-description": "Lähetä anonyymeja käyttötietoja auttamaan sovelluksen parantamisessa ja kehityksen ohjaamisessa.", + "logs": "Lokit", + "logs-description": "Tarkastele sovelluksen lokitietoja virheenkorjaukseen ja vianmääritykseen.", + "open-logs": "Avata", + "update": "Päivitä asetukset", + "error": "Asetusten päivittäminen epäonnistui" + }, "preferences": { "preferences": "Asetukset", "description": "Valitse haluamasi kieli ja maa nauttiaksesi räätälöidystä sisällöstä.", diff --git a/crates/popcorntime-tauri/dictionaries/fr.json b/crates/popcorntime-tauri/dictionaries/fr.json index d38ee1092..64dab21c0 100644 --- a/crates/popcorntime-tauri/dictionaries/fr.json +++ b/crates/popcorntime-tauri/dictionaries/fr.json @@ -43,10 +43,21 @@ "menu": { "preferences": "Langue et région", "watchPreferences": "Préférences de visionnage", - "manifest": "Manifeste", - "logs": "Journaux de débogage", + "settings": "Paramètres de l'application", "signOut": "Se déconnecter" }, + "settings": { + "toast": "Vos paramètres ont été mis à jour avec succès.", + "settings": "Paramètres", + "description": "Configurez des options spécifiques à l'application comme les analyses, les thèmes et d'autres préférences locales.", + "analytics": "Analytique", + "analytics-description": "Envoyer des données d'utilisation anonymes pour aider à améliorer l'application et orienter son développement.", + "logs": "Journaux", + "logs-description": "Afficher les journaux de l'application pour le débogage et le dépannage.", + "open-logs": "Ouvrir", + "update": "Paramètres de mise à jour", + "error": "Échec de la mise à jour des paramètres" + }, "preferences": { "preferences": "Préférences", "description": "Sélectionnez votre langue et votre pays préférés pour profiter d'un contenu personnalisé.", diff --git a/crates/popcorntime-tauri/dictionaries/ga.json b/crates/popcorntime-tauri/dictionaries/ga.json index 52d087a08..0682eca58 100644 --- a/crates/popcorntime-tauri/dictionaries/ga.json +++ b/crates/popcorntime-tauri/dictionaries/ga.json @@ -43,10 +43,21 @@ "menu": { "preferences": "Teanga & réigiún", "watchPreferences": "Roghanna féachana", - "manifest": "Manifiosta", - "logs": "Loga dífhabhtacha", + "settings": "Socruithe Aipe", "signOut": "Logáil amach" }, + "settings": { + "toast": "Tá do shocruithe nuashonraithe go rathúil.", + "settings": "Socruithe", + "description": "Cumraigh roghanna ar leith don aip cosúil le hanailísíocht, téamaí, agus roghanna áitiúla eile.", + "analytics": "Anailís", + "analytics-description": "Seol sonraí úsáide gan ainm chun cabhrú leis an aip a fheabhsú agus forbairt a threorú.", + "logs": "Logaí", + "logs-description": "Féach ar logaí feidhmchláir chun dífhabhtú agus fabhtcheartú a dhéanamh.", + "open-logs": "Oscail", + "update": "Nuashonraigh socruithe", + "error": "Theip ar shocruithe a nuashonrú" + }, "preferences": { "preferences": "Roghanna", "description": "Roghnaigh do theanga agus do thír is fearr leat chun taitneamh a bhaint as ábhar saincheaptha.", diff --git a/crates/popcorntime-tauri/dictionaries/he.json b/crates/popcorntime-tauri/dictionaries/he.json index 190fa5fb3..496b266fa 100644 --- a/crates/popcorntime-tauri/dictionaries/he.json +++ b/crates/popcorntime-tauri/dictionaries/he.json @@ -43,10 +43,21 @@ "menu": { "preferences": "שפה ואזור", "watchPreferences": "העדפות צפייה", - "manifest": "מניפסט", - "logs": "יומני ניפוי שגיאות", + "settings": "הגדרות האפליקציה", "signOut": "התנתק" }, + "settings": { + "toast": "ההגדרות שלך עודכנו בהצלחה.", + "settings": "הגדרות", + "description": "הגדר אפשרויות ספציפיות לאפליקציה כמו ניתוח נתונים, ערכות נושא והעדפות מקומיות אחרות.", + "analytics": "אנליטיקס", + "analytics-description": "שלח נתוני שימוש אנונימיים כדי לעזור לשפר את האפליקציה ולהנחות את הפיתוח.", + "logs": "יומני רישום", + "logs-description": "הצג יומני אפליקציה לאיתור תקלות ופתרון בעיות.", + "open-logs": "לִפְתוֹחַ", + "update": "עדכן הגדרות", + "error": "נכשל בעדכון ההגדרות" + }, "preferences": { "preferences": "העדפות", "description": "בחר את השפה והמדינה המועדפות עליך כדי ליהנות מתוכן מותאם.", diff --git a/crates/popcorntime-tauri/dictionaries/hi.json b/crates/popcorntime-tauri/dictionaries/hi.json index 6f529742a..df1ccf464 100644 --- a/crates/popcorntime-tauri/dictionaries/hi.json +++ b/crates/popcorntime-tauri/dictionaries/hi.json @@ -43,10 +43,21 @@ "menu": { "preferences": "भाषा और क्षेत्र", "watchPreferences": "देखने की प्राथमिकताएँ", - "manifest": "घोषणापत्र", - "logs": "डीबग लॉग्स", + "settings": "ऐप सेटिंग्स", "signOut": "साइन आउट करें" }, + "settings": { + "toast": "आपकी सेटिंग्स सफलतापूर्वक अपडेट कर दी गई हैं।", + "settings": "सेटिंग्स", + "description": "ऐप-विशिष्ट विकल्पों जैसे कि एनालिटिक्स, थीम्स और अन्य स्थानीय प्राथमिकताओं को कॉन्फ़िगर करें।", + "analytics": "एनालिटिक्स", + "analytics-description": "ऐप को सुधारने और विकास का मार्गदर्शन करने में मदद के लिए गुमनाम उपयोग डेटा भेजें।", + "logs": "लॉग्स", + "logs-description": "ऐप्लिकेशन लॉग्स को डिबगिंग और समस्याओं का समाधान करने के लिए देखें।", + "open-logs": "खुला", + "update": "सेटिंग्स अपडेट करें", + "error": "सेटिंग्स अपडेट करने में विफल रहा" + }, "preferences": { "preferences": "प्राथमिकताएँ", "description": "अपनी पसंदीदा भाषा और देश का चयन करें ताकि आप विशेष सामग्री का आनंद ले सकें।", diff --git a/crates/popcorntime-tauri/dictionaries/it.json b/crates/popcorntime-tauri/dictionaries/it.json index c89496f25..915fbdd26 100644 --- a/crates/popcorntime-tauri/dictionaries/it.json +++ b/crates/popcorntime-tauri/dictionaries/it.json @@ -43,10 +43,21 @@ "menu": { "preferences": "Lingua e regione", "watchPreferences": "Preferenze di visione", - "manifest": "Manifesto", - "logs": "Log di debug", + "settings": "Impostazioni dell'app", "signOut": "Esci" }, + "settings": { + "toast": "Le tue impostazioni sono state aggiornate con successo.", + "settings": "Impostazioni", + "description": "Configura opzioni specifiche dell'app come analisi, temi e altre preferenze locali.", + "analytics": "Analisi", + "analytics-description": "Invia dati di utilizzo anonimi per aiutare a migliorare l'app e guidare lo sviluppo.", + "logs": "Registri", + "logs-description": "Visualizza i registri dell'applicazione per il debug e la risoluzione dei problemi.", + "open-logs": "Aprire", + "update": "Aggiorna impostazioni", + "error": "Impossibile aggiornare le impostazioni" + }, "preferences": { "preferences": "Preferenze", "description": "Seleziona la tua lingua e il tuo paese preferiti per goderti contenuti su misura.", diff --git a/crates/popcorntime-tauri/dictionaries/ja.json b/crates/popcorntime-tauri/dictionaries/ja.json index ec9a1e140..d689c58c7 100644 --- a/crates/popcorntime-tauri/dictionaries/ja.json +++ b/crates/popcorntime-tauri/dictionaries/ja.json @@ -43,10 +43,21 @@ "menu": { "preferences": "言語と地域", "watchPreferences": "視聴設定", - "manifest": "マニフェスト", - "logs": "デバッグログ", + "settings": "アプリ設定", "signOut": "ログアウト" }, + "settings": { + "toast": "設定が正常に更新されました。", + "settings": "設定", + "description": "アプリ固有のオプションを設定して、分析、テーマ、その他のローカル設定を調整します。", + "analytics": "アナリティクス", + "analytics-description": "アプリを改善し、開発を進めるために匿名の使用データを送信します。", + "logs": "ログ", + "logs-description": "デバッグおよびトラブルシューティングのためにアプリケーションログを表示します。", + "open-logs": "開ける", + "update": "設定を更新する", + "error": "設定の更新に失敗しました" + }, "preferences": { "preferences": "設定", "description": "言語と国を選択して、あなたに合わせたコンテンツをお楽しみください。", diff --git a/crates/popcorntime-tauri/dictionaries/nl.json b/crates/popcorntime-tauri/dictionaries/nl.json index e582bd89a..7de8cde22 100644 --- a/crates/popcorntime-tauri/dictionaries/nl.json +++ b/crates/popcorntime-tauri/dictionaries/nl.json @@ -43,10 +43,21 @@ "menu": { "preferences": "Taal & regio", "watchPreferences": "Bekijk voorkeuren", - "manifest": "Manifest", - "logs": "Foutopsporingslogboeken", + "settings": "App-instellingen", "signOut": "Afmelden" }, + "settings": { + "toast": "Je instellingen zijn succesvol bijgewerkt.", + "settings": "Instellingen", + "description": "Configureer app-specifieke opties zoals analytics, thema's en andere lokale voorkeuren.", + "analytics": "Analytics", + "analytics-description": "Verzend anonieme gebruiksgegevens om de app te verbeteren en de ontwikkeling te begeleiden.", + "logs": "Logboeken", + "logs-description": "Bekijk toepassingslogboeken voor debuggen en probleemoplossing.", + "open-logs": "Open", + "update": "Instellingen bijwerken", + "error": "Instellingen bijwerken mislukt" + }, "preferences": { "preferences": "Voorkeuren", "description": "Selecteer je voorkeurstaal en land om van op maat gemaakte inhoud te genieten.", diff --git a/crates/popcorntime-tauri/dictionaries/no.json b/crates/popcorntime-tauri/dictionaries/no.json index e6b9c6597..ac6a40a98 100644 --- a/crates/popcorntime-tauri/dictionaries/no.json +++ b/crates/popcorntime-tauri/dictionaries/no.json @@ -43,10 +43,21 @@ "menu": { "preferences": "Språk og region", "watchPreferences": "Se preferanser for visning", - "manifest": "Manifest", - "logs": "Feilrettingslogger", + "settings": "App-innstillinger", "signOut": "Logg ut" }, + "settings": { + "toast": "Innstillingene dine har blitt oppdatert.", + "settings": "Innstillinger", + "description": "Konfigurer app-spesifikke alternativer som analyseverktøy, temaer og andre lokale preferanser.", + "analytics": "Analyser", + "analytics-description": "Send anonyme bruksdata for å hjelpe med å forbedre appen og veilede utviklingen.", + "logs": "Logger", + "logs-description": "Se programlogger for feilsøking og feilanalyse.", + "open-logs": "Åpne", + "update": "Oppdater innstillinger", + "error": "Kunne ikke oppdatere innstillinger" + }, "preferences": { "preferences": "Preferanser", "description": "Velg ditt foretrukne språk og land for å nyte skreddersydd innhold.", diff --git a/crates/popcorntime-tauri/dictionaries/pl.json b/crates/popcorntime-tauri/dictionaries/pl.json index 3bba1118f..d245840ab 100644 --- a/crates/popcorntime-tauri/dictionaries/pl.json +++ b/crates/popcorntime-tauri/dictionaries/pl.json @@ -43,10 +43,21 @@ "menu": { "preferences": "Język i region", "watchPreferences": "Preferencje oglądania", - "manifest": "Manifest", - "logs": "Dzienniki debugowania", + "settings": "Ustawienia aplikacji", "signOut": "Wyloguj się" }, + "settings": { + "toast": "Twoje ustawienia zostały pomyślnie zaktualizowane.", + "settings": "Ustawienia", + "description": "Skonfiguruj opcje specyficzne dla aplikacji, takie jak analityka, motywy i inne preferencje lokalne.", + "analytics": "Analityka", + "analytics-description": "Wyślij anonimowe dane użytkowania, aby pomóc w ulepszaniu aplikacji i kierować jej rozwojem.", + "logs": "Dzienniki", + "logs-description": "Zobacz dzienniki aplikacji w celu debugowania i rozwiązywania problemów.", + "open-logs": "Otwarte", + "update": "Zaktualizuj ustawienia", + "error": "Nie udało się zaktualizować ustawień" + }, "preferences": { "preferences": "Preferencje", "description": "Wybierz preferowany język i kraj, aby cieszyć się dostosowaną treścią.", diff --git a/crates/popcorntime-tauri/dictionaries/pt.json b/crates/popcorntime-tauri/dictionaries/pt.json index fefe1365b..253fa6097 100644 --- a/crates/popcorntime-tauri/dictionaries/pt.json +++ b/crates/popcorntime-tauri/dictionaries/pt.json @@ -43,10 +43,21 @@ "menu": { "preferences": "Idioma e região", "watchPreferences": "Preferências de visualização", - "manifest": "Manifesto", - "logs": "Registros de depuração", + "settings": "Configurações do aplicativo", "signOut": "Sair" }, + "settings": { + "toast": "Suas configurações foram atualizadas com sucesso.", + "settings": "Configurações", + "description": "Configure opções específicas do aplicativo como análises, temas e outras preferências locais.", + "analytics": "Analytics", + "analytics-description": "Envie dados de uso anônimos para ajudar a melhorar o aplicativo e orientar o desenvolvimento.", + "logs": "Registros", + "logs-description": "Visualizar logs do aplicativo para depuração e solução de problemas.", + "open-logs": "Abrir", + "update": "Configurações de atualização", + "error": "Falha ao atualizar as configurações" + }, "preferences": { "preferences": "Preferências", "description": "Selecione seu idioma e país preferidos para desfrutar de conteúdo personalizado.", diff --git a/crates/popcorntime-tauri/dictionaries/sr.json b/crates/popcorntime-tauri/dictionaries/sr.json index 6bb7a1756..3ffd18d31 100644 --- a/crates/popcorntime-tauri/dictionaries/sr.json +++ b/crates/popcorntime-tauri/dictionaries/sr.json @@ -43,10 +43,21 @@ "menu": { "preferences": "Језик и регион", "watchPreferences": "Preferencije gledanja", - "manifest": "Manifest", - "logs": "Дебаг логови", + "settings": "Podešavanja aplikacije", "signOut": "Odjavi se" }, + "settings": { + "toast": "Vaša podešavanja su uspešno ažurirana.", + "settings": "Podešavanja", + "description": "Konfigurišite opcije specifične za aplikaciju kao što su analitika, teme i druge lokalne postavke.", + "analytics": "Analitika", + "analytics-description": "Pošaljite anonimne podatke o korišćenju kako biste pomogli u poboljšanju aplikacije i usmeravanju razvoja.", + "logs": "Дневници", + "logs-description": "Pregledajte logove aplikacije za otklanjanje grešaka i rešavanje problema.", + "open-logs": "Отворено", + "update": "Ажурирање подешавања", + "error": "Nije uspelo ažuriranje podešavanja" + }, "preferences": { "preferences": "Preferencije", "description": "Izaberite željeni jezik i državu da biste uživali u sadržaju prilagođenom vama.", diff --git a/crates/popcorntime-tauri/dictionaries/sv.json b/crates/popcorntime-tauri/dictionaries/sv.json index a67d3adbe..9faabb08c 100644 --- a/crates/popcorntime-tauri/dictionaries/sv.json +++ b/crates/popcorntime-tauri/dictionaries/sv.json @@ -43,10 +43,21 @@ "menu": { "preferences": "Språk och region", "watchPreferences": "Tittarinställningar", - "manifest": "Manifest", - "logs": "Felsökningsloggar", + "settings": "Appinställningar", "signOut": "Logga ut" }, + "settings": { + "toast": "Dina inställningar har uppdaterats framgångsrikt.", + "settings": "Inställningar", + "description": "Konfigurera app-specifika alternativ som analys, teman och andra lokala inställningar.", + "analytics": "Analys", + "analytics-description": "Skicka anonym användardata för att hjälpa till att förbättra appen och vägleda utvecklingen.", + "logs": "Loggar", + "logs-description": "Visa applikationsloggar för felsökning och avhjälpning.", + "open-logs": "Öppna", + "update": "Uppdatera inställningar", + "error": "Misslyckades med att uppdatera inställningarna" + }, "preferences": { "preferences": "Inställningar", "description": "Välj ditt föredragna språk och land för att njuta av skräddarsytt innehåll.", diff --git a/crates/popcorntime-tauri/dictionaries/tr.json b/crates/popcorntime-tauri/dictionaries/tr.json index 58ef80893..00fd6a7b9 100644 --- a/crates/popcorntime-tauri/dictionaries/tr.json +++ b/crates/popcorntime-tauri/dictionaries/tr.json @@ -43,10 +43,21 @@ "menu": { "preferences": "Dil ve bölge", "watchPreferences": "İzleme tercihleri", - "manifest": "Manifesto", - "logs": "Hata ayıklama günlükleri", + "settings": "Uygulama ayarları", "signOut": "Oturum kapat" }, + "settings": { + "toast": "Ayarlarınız başarıyla güncellendi.", + "settings": "Ayarlar", + "description": "Uygulamaya özgü seçenekleri, analitik, temalar ve diğer yerel tercihler gibi yapılandırın.", + "analytics": "Analitikler", + "analytics-description": "Uygulamayı geliştirmek ve geliştirme sürecine rehberlik etmek için anonim kullanım verilerini gönder.", + "logs": "Günlükler", + "logs-description": "Uygulama günlüklerini hata ayıklama ve sorun giderme için görüntüle.", + "open-logs": "Açık", + "update": "Ayarları güncelle", + "error": "Ayarlar güncellenemedi" + }, "preferences": { "preferences": "Tercihler", "description": "Tercih ettiğiniz dili ve ülkeyi seçerek size özel içeriklerin keyfini çıkarın.", diff --git a/crates/popcorntime-tauri/dictionaries/ur.json b/crates/popcorntime-tauri/dictionaries/ur.json index 2c4869030..af90d38ad 100644 --- a/crates/popcorntime-tauri/dictionaries/ur.json +++ b/crates/popcorntime-tauri/dictionaries/ur.json @@ -43,10 +43,21 @@ "menu": { "preferences": "زبان اور علاقہ", "watchPreferences": "دیکھنے کی ترجیحات", - "manifest": "منشور", - "logs": "ڈی بگ لاگز", + "settings": "ایپ کی ترتیبات", "signOut": "سائن آؤٹ" }, + "settings": { + "toast": "آپ کی ترتیبات کامیابی سے اپڈیٹ ہو گئی ہیں۔", + "settings": "ترتیبات", + "description": "ایپ کی مخصوص اختیارات جیسے تجزیات، تھیمز، اور دیگر مقامی ترجیحات کو ترتیب دیں۔", + "analytics": "تجزیات", + "analytics-description": "ایپ کو بہتر بنانے اور ترقی کی رہنمائی کے لئے گمنام استعمال کا ڈیٹا بھیجیں۔", + "logs": "نوشتہ جات", + "logs-description": "ایپلیکیشن لاگز کو ڈیبگنگ اور مسئلہ حل کرنے کے لیے دیکھیں۔", + "open-logs": "کھولیں۔", + "update": "ترتیبات کو اپ ڈیٹ کریں", + "error": "ترتیبات کو اپ ڈیٹ کرنے میں ناکامی ہوئی ہے۔" + }, "preferences": { "preferences": "ترجیحات", "description": "اپنی پسندیدہ زبان اور ملک کا انتخاب کریں تاکہ آپ کو مخصوص مواد مل سکے۔", diff --git a/crates/popcorntime-tauri/src/lib.rs b/crates/popcorntime-tauri/src/lib.rs index 0b8cdb3d2..e432840f3 100644 --- a/crates/popcorntime-tauri/src/lib.rs +++ b/crates/popcorntime-tauri/src/lib.rs @@ -4,4 +4,5 @@ pub mod event; pub mod graphql; pub mod logs; pub mod session; +pub mod settings; pub mod window; diff --git a/crates/popcorntime-tauri/src/main.rs b/crates/popcorntime-tauri/src/main.rs index 56ef5246f..3b730f26f 100644 --- a/crates/popcorntime-tauri/src/main.rs +++ b/crates/popcorntime-tauri/src/main.rs @@ -3,6 +3,7 @@ use anyhow::Context; use popcorntime_error::Code; use popcorntime_graphql_client::client::ApiClient; use popcorntime_session::{AuthorizationService, SessionUpdateEvent}; +use popcorntime_settings::SettingsService; use popcorntime_tauri::event::{SessionServerReady, SessionUpdate}; #[cfg(debug_assertions)] use specta_typescript::Typescript; @@ -23,11 +24,11 @@ fn main() { popcorntime_tauri::graphql::set_favorites_multiple_providers, popcorntime_tauri::graphql::set_media_reaction, popcorntime_tauri::window::show_main_window, - popcorntime_tauri::session::is_onboarded, - popcorntime_tauri::session::set_onboarded, popcorntime_tauri::session::validate, popcorntime_tauri::session::logout, popcorntime_tauri::session::initialize_session_authorization, + popcorntime_tauri::settings::settings, + popcorntime_tauri::settings::update_settings, ]) .events(collect_events![SessionServerReady, SessionUpdate]); @@ -77,18 +78,24 @@ fn main() { ( paths.app_data_dir().expect("missing app data dir"), paths.app_cache_dir().expect("missing app cache dir"), - paths.config_dir().expect("missing config dir"), + paths.app_config_dir().expect("missing config dir"), ) }; std::fs::create_dir_all(&app_data_dir).expect("failed to create app data dir"); std::fs::create_dir_all(&app_cache_dir).expect("failed to create cache dir"); - let config_dir = config_dir.join(app_handle.config().identifier.as_str()); std::fs::create_dir_all(&config_dir).expect("failed to create config dir"); - tracing::info!(version = %app_handle.package_info().version, - name = %app_handle.package_info().name, "starting app"); + tracing::info!( + version = %app_handle.package_info().version, + name = %app_handle.package_info().name, "starting app" + ); + // settings service + let settings_service = SettingsService::new(&config_dir)?; + app_handle.manage(settings_service); + + // auth service let auth_service = AuthorizationService::new(&config_dir, app_handle.config().identifier.as_str())?; app_handle.manage(ApiClient::new(auth_service.try_access_token())?); @@ -109,6 +116,7 @@ fn main() { }, )?; + // deep links let app_handle_isolated = app_handle.clone(); app.deep_link().on_open_url(move |event| { tracing::info!( diff --git a/crates/popcorntime-tauri/src/session.rs b/crates/popcorntime-tauri/src/session.rs index 9c2e5b33a..f5eceb072 100644 --- a/crates/popcorntime-tauri/src/session.rs +++ b/crates/popcorntime-tauri/src/session.rs @@ -33,20 +33,6 @@ pub async fn validate(service: State<'_, AuthorizationService>) -> Result<(), Er service.validate().await.map_err(Into::into) } -#[tauri::command(async)] -#[specta::specta] -#[instrument(skip(service), err(Debug))] -pub async fn is_onboarded(service: State<'_, AuthorizationService>) -> Result { - service.is_onboarded().map_err(Into::into) -} - -#[tauri::command(async)] -#[specta::specta] -#[instrument(skip(service), err(Debug))] -pub async fn set_onboarded(service: State<'_, AuthorizationService>) -> Result<(), Error> { - service.set_onboarded(true).map_err(Into::into) -} - #[tauri::command(async)] #[specta::specta] #[instrument(skip(service), err(Debug))] diff --git a/crates/popcorntime-tauri/src/settings.rs b/crates/popcorntime-tauri/src/settings.rs new file mode 100644 index 000000000..a66194aab --- /dev/null +++ b/crates/popcorntime-tauri/src/settings.rs @@ -0,0 +1,32 @@ +use crate::error::Error; +use popcorntime_settings::{Settings, SettingsInput, SettingsService}; +use tauri::State; +use tracing::instrument; + +#[tauri::command(async)] +#[specta::specta] +#[instrument(skip(service), err(Debug))] +pub async fn settings(service: State<'_, SettingsService>) -> Result { + service.get().await.map_err(Into::into) +} + +#[tauri::command(async)] +#[specta::specta] +#[instrument(skip(service), err(Debug))] +pub async fn update_settings( + service: State<'_, SettingsService>, + settings: SettingsInput, +) -> Result { + service + .update(|current_settings| { + if let Some(onboarding_complete) = settings.onboarding_complete { + current_settings.onboarding_complete = onboarding_complete; + } + + if let Some(enable_analytics) = settings.enable_analytics { + current_settings.enable_analytics = enable_analytics; + } + }) + .await + .map_err(Into::into) +} diff --git a/packages/popcorntime-ui/package.json b/packages/popcorntime-ui/package.json index 2731b89a0..90c394764 100644 --- a/packages/popcorntime-ui/package.json +++ b/packages/popcorntime-ui/package.json @@ -29,17 +29,17 @@ "@types/react": "^19.1.16", "@types/react-dom": "^19.1.9", "@vitejs/plugin-react-swc": "4.1.0", + "@vitest/browser": "3.2.4", + "@vitest/coverage-v8": "3.2.4", "autoprefixer": "^10.4.20", "globals": "^16.4.0", + "playwright": "^1.55.1", "postcss": "^8.5.3", "storybook": "^9.1.10", "tailwind-merge": "^3.3.1", "typescript": "^5.9.3", "vite": "^6.1.0", - "vitest": "catalog:", - "@vitest/browser": "3.2.4", - "playwright": "^1.55.1", - "@vitest/coverage-v8": "3.2.4" + "vitest": "catalog:" }, "dependencies": { "@hookform/resolvers": "catalog:", @@ -56,6 +56,7 @@ "@radix-ui/react-scroll-area": "^1.2.10", "@radix-ui/react-separator": "^1.1.7", "@radix-ui/react-slot": "^1.2.3", + "@radix-ui/react-switch": "^1.2.6", "@radix-ui/react-tabs": "^1.1.13", "@radix-ui/react-toggle": "^1.1.10", "@radix-ui/react-toggle-group": "^1.1.11", diff --git a/packages/popcorntime-ui/src/components/switch.tsx b/packages/popcorntime-ui/src/components/switch.tsx new file mode 100644 index 000000000..a847a9519 --- /dev/null +++ b/packages/popcorntime-ui/src/components/switch.tsx @@ -0,0 +1,27 @@ +"use client"; + +import { cn } from "@popcorntime/ui/lib/utils"; +import * as SwitchPrimitive from "@radix-ui/react-switch"; +import type * as React from "react"; + +function Switch({ className, ...props }: React.ComponentProps) { + return ( + + + + ); +} + +export { Switch }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6ce011db4..685bcbfc0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -179,6 +179,9 @@ importers: lucide-react: specifier: 'catalog:' version: 0.544.0(react@19.1.1) + posthog-js: + specifier: ^1.266.0 + version: 1.269.0 react: specifier: 'catalog:' version: 19.1.1 @@ -345,6 +348,9 @@ importers: '@radix-ui/react-slot': specifier: ^1.2.3 version: 1.2.3(@types/react@19.1.16)(react@19.1.1) + '@radix-ui/react-switch': + specifier: ^1.2.6 + version: 1.2.6(@types/react-dom@19.1.9(@types/react@19.1.16))(@types/react@19.1.16)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@radix-ui/react-tabs': specifier: ^1.1.13 version: 1.1.13(@types/react-dom@19.1.9(@types/react@19.1.16))(@types/react@19.1.16)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) @@ -1143,6 +1149,9 @@ packages: '@polka/url@1.0.0-next.29': resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} + '@posthog/core@1.2.2': + resolution: {integrity: sha512-f16Ozx6LIigRG+HsJdt+7kgSxZTHeX5f1JlCGKI1lXcvlZgfsCR338FuMI2QRYXGl+jg/vYFzGOTQBxl90lnBg==} + '@protobufjs/aspromise@1.1.2': resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} @@ -1519,6 +1528,19 @@ packages: '@types/react': optional: true + '@radix-ui/react-switch@1.2.6': + resolution: {integrity: sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-tabs@1.1.13': resolution: {integrity: sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==} peerDependencies: @@ -2728,6 +2750,9 @@ packages: resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==} engines: {node: '>=18'} + core-js@3.45.1: + resolution: {integrity: sha512-L4NPsJlCfZsPeXukyzHFlg/i7IIVwHSItR0wg0FLNqYClJ4MQYTYLbC7EkjKYRLZF2iof2MUgN0EGy7MdQFChg==} + core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -3034,6 +3059,9 @@ packages: resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} engines: {node: ^12.20 || >= 14.13} + fflate@0.4.8: + resolution: {integrity: sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==} + fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} @@ -4120,6 +4148,20 @@ packages: resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} + posthog-js@1.269.0: + resolution: {integrity: sha512-Qwa6hiAxfUFRihPpulCs13IicDGYLrkXpxaD+dRjuUjT8lIFW/O3PQOOKvs2QvaxnZYkM81ZYvwlsUvrgrdKiw==} + peerDependencies: + '@rrweb/types': 2.0.0-alpha.17 + rrweb-snapshot: 2.0.0-alpha.17 + peerDependenciesMeta: + '@rrweb/types': + optional: true + rrweb-snapshot: + optional: true + + preact@10.27.2: + resolution: {integrity: sha512-5SYSgFKSyhCbk6SrXyMpqjb5+MQBgfvEKE/OC+PujcY34sOpqtr+0AZQtPYx5IA6VxynQ7rUPCtKzyovpj9Bpg==} + prelude-ls@1.1.2: resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==} engines: {node: '>= 0.8.0'} @@ -4976,6 +5018,9 @@ packages: resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==} engines: {node: '>= 14'} + web-vitals@4.2.4: + resolution: {integrity: sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==} + webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} @@ -5839,6 +5884,8 @@ snapshots: '@polka/url@1.0.0-next.29': {} + '@posthog/core@1.2.2': {} + '@protobufjs/aspromise@1.1.2': {} '@protobufjs/base64@1.1.2': {} @@ -6233,6 +6280,21 @@ snapshots: optionalDependencies: '@types/react': 19.1.16 + '@radix-ui/react-switch@1.2.6(@types/react-dom@19.1.9(@types/react@19.1.16))(@types/react@19.1.16)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.16)(react@19.1.1) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.16)(react@19.1.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.9(@types/react@19.1.16))(@types/react@19.1.16)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.16)(react@19.1.1) + '@radix-ui/react-use-previous': 1.1.1(@types/react@19.1.16)(react@19.1.1) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.1.16)(react@19.1.1) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) + optionalDependencies: + '@types/react': 19.1.16 + '@types/react-dom': 19.1.9(@types/react@19.1.16) + '@radix-ui/react-tabs@1.1.13(@types/react-dom@19.1.9(@types/react@19.1.16))(@types/react@19.1.16)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: '@radix-ui/primitive': 1.1.3 @@ -7080,9 +7142,9 @@ snapshots: std-env: 3.9.0 test-exclude: 7.0.1 tinyrainbow: 2.0.0 - vitest: 3.2.4(@types/debug@4.1.12)(@types/node@18.19.129)(@vitest/browser@3.2.4)(jiti@2.5.1)(jsdom@26.1.0)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.7.0) + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.5.0)(@vitest/browser@3.2.4)(jiti@2.5.1)(jsdom@26.1.0)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.7.0) optionalDependencies: - '@vitest/browser': 3.2.4(playwright@1.55.1)(vite@6.3.6(@types/node@18.19.129)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.7.0))(vitest@3.2.4) + '@vitest/browser': 3.2.4(playwright@1.55.1)(vite@6.3.6(@types/node@24.5.0)(jiti@2.5.1)(lightningcss@1.30.1)(terser@5.44.0)(tsx@4.20.6)(yaml@2.7.0))(vitest@3.2.4) transitivePeerDependencies: - supports-color @@ -7496,6 +7558,8 @@ snapshots: cookie@1.0.2: {} + core-js@3.45.1: {} + core-util-is@1.0.3: {} create-jest@29.7.0(@types/node@24.5.0): @@ -7792,6 +7856,8 @@ snapshots: node-domexception: 1.0.0 web-streams-polyfill: 3.3.3 + fflate@0.4.8: {} + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -9104,6 +9170,16 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 + posthog-js@1.269.0: + dependencies: + '@posthog/core': 1.2.2 + core-js: 3.45.1 + fflate: 0.4.8 + preact: 10.27.2 + web-vitals: 4.2.4 + + preact@10.27.2: {} + prelude-ls@1.1.2: {} prettier-plugin-tailwindcss@0.6.14(prettier@3.6.2): @@ -10019,6 +10095,8 @@ snapshots: web-streams-polyfill@4.0.0-beta.3: {} + web-vitals@4.2.4: {} + webidl-conversions@3.0.1: {} webidl-conversions@7.0.0: {}