diff --git a/web/i18n/en/settings.json b/web/i18n/en/settings.json index aeb2e544..27c28bd8 100644 --- a/web/i18n/en/settings.json +++ b/web/i18n/en/settings.json @@ -75,8 +75,8 @@ "accessibility": "accessibility", "accessibility.transparency.title": "reduce visual transparency", "accessibility.transparency.description": "reduces transparency of surfaces and disables blur effects.", - "accessibility.animations.title": "reduce motion", - "accessibility.animations.description": "replaces animations with instant transitions when possible.", + "accessibility.motion.title": "reduce motion", + "accessibility.motion.description": "replaces animations with instant transitions when possible.", "language": "language", "language.auto.title": "use default browser language", diff --git a/web/src/app.html b/web/src/app.html index 101846d0..c1d1520e 100644 --- a/web/src/app.html +++ b/web/src/app.html @@ -1,8 +1,8 @@ - - + + cobalt @@ -10,7 +10,7 @@ - + diff --git a/web/src/components/settings/SettingsCategory.svelte b/web/src/components/settings/SettingsCategory.svelte index 728a9966..31205539 100644 --- a/web/src/components/settings/SettingsCategory.svelte +++ b/web/src/components/settings/SettingsCategory.svelte @@ -35,6 +35,10 @@ animation: highlight 2s; } + :global(.reduce-motion) .settings-content.animate { + animation: highlight-lite 2s !important; + } + @keyframes highlight { 0% { box-shadow: none; @@ -50,6 +54,18 @@ } } + @keyframes highlight-lite { + 0% { + box-shadow: none; + } + 10%, 50% { + box-shadow: 0 0 0 3px var(--blue) inset; + } + 100% { + box-shadow: none; + } + } + @media screen and (max-width: 750px) { .settings-content { padding: var(--padding); diff --git a/web/src/lib/device.ts b/web/src/lib/device.ts index 5f636f17..a06785a4 100644 --- a/web/src/lib/device.ts +++ b/web/src/lib/device.ts @@ -8,10 +8,13 @@ const android = ua.includes("android") || ua.includes("diordna"); const mobile = iOS || android; -const preferredLocale = navigator.language.toLowerCase().slice(0, 2); +const language = navigator.language.toLowerCase().slice(0, 2); const installed = window.matchMedia('(display-mode: standalone)').matches; +const reducedMotion = window.matchMedia(`(prefers-reduced-motion: reduce)`).matches; +const reducedTransparency = window.matchMedia(`(prefers-reduced-transparency: reduce)`).matches; + const device = { is: { iPhone, @@ -20,7 +23,11 @@ const device = { android, mobile, }, - preferredLocale, + prefers: { + language, + reducedMotion, + reducedTransparency, + }, userAgent: navigator.userAgent, } diff --git a/web/src/lib/settings/defaults.ts b/web/src/lib/settings/defaults.ts index 4e44a83e..3a727e1d 100644 --- a/web/src/lib/settings/defaults.ts +++ b/web/src/lib/settings/defaults.ts @@ -4,10 +4,6 @@ import type { CobaltSettings } from "$lib/types/settings"; const defaultSettings: CobaltSettings = { schemaVersion: 1, - accessibility: { - reduceAnimations: false, - reduceTransparency: false, - }, advanced: { debug: false, }, @@ -15,11 +11,8 @@ const defaultSettings: CobaltSettings = { theme: "auto", language: defaultLocale, autoLanguage: true, - }, - general: { - customProcessingEndpoint: "", - seenOnboarding: false, - seenSafetyWarning: false, + reduceMotion: false, + reduceTransparency: false, }, save: { audioFormat: "mp3", @@ -34,9 +27,6 @@ const defaultSettings: CobaltSettings = { youtubeVideoCodec: "h264", youtubeDubBrowserLang: false, }, - privacy: { - trafficAnalytics: true, - }, } const defaultSettingsPage = () => { diff --git a/web/src/lib/types/settings.ts b/web/src/lib/types/settings.ts index 5426adf3..dc962e71 100644 --- a/web/src/lib/types/settings.ts +++ b/web/src/lib/types/settings.ts @@ -1,10 +1,5 @@ import languages from '$i18n/languages.json'; -export type CobaltSettingsAccessibility = { - reduceAnimations: boolean, - reduceTransparency: boolean, -}; - export const themeOptions = ["auto", "light", "dark"] as const; export const audioFormatOptions = ["best", "mp3", "ogg", "wav", "opus"] as const; export const downloadModeOptions = ["auto", "audio", "mute"] as const; @@ -16,18 +11,14 @@ type CobaltSettingsAppearance = { theme: typeof themeOptions[number], language: keyof typeof languages, autoLanguage: boolean, + reduceMotion: boolean, + reduceTransparency: boolean, }; type CobaltSettingsAdvanced = { debug: boolean, }; -type CobaltSettingsGeneral = { - customProcessingEndpoint: string, - seenOnboarding: boolean, - seenSafetyWarning: boolean, -}; - type CobaltSettingsSave = { audioFormat: typeof audioFormatOptions[number], disableMetadata: boolean, @@ -42,18 +33,11 @@ type CobaltSettingsSave = { youtubeDubBrowserLang: boolean, }; -type CobaltSettingsPrivacy = { - trafficAnalytics: boolean, -}; - export type CobaltSettings = { schemaVersion: number, - accessibility: CobaltSettingsAccessibility, advanced: CobaltSettingsAdvanced, appearance: CobaltSettingsAppearance, - general: CobaltSettingsGeneral, save: CobaltSettingsSave, - privacy: CobaltSettingsPrivacy, }; export type DownloadModeOption = CobaltSettings['save']['downloadMode']; diff --git a/web/src/routes/+layout.svelte b/web/src/routes/+layout.svelte index 298e3581..ed34f4aa 100644 --- a/web/src/routes/+layout.svelte +++ b/web/src/routes/+layout.svelte @@ -1,12 +1,20 @@ - @@ -16,7 +24,12 @@
-
+
{#if device.is.iPhone && app.is.installed} {/if} @@ -75,7 +88,7 @@ ); } - :global([data-theme=dark]) { + :global([data-theme="dark"]) { --primary: #000000; --secondary: #e1e1e1; @@ -131,7 +144,8 @@ @media screen and (orientation: landscape) { #cobalt.on-iPhone { grid-template-columns: - calc(var(--sidebar-width) + env(safe-area-inset-left) + 8px) 1fr; + calc(var(--sidebar-width) + env(safe-area-inset-left) + 8px) + 1fr; } #cobalt.on-iPhone #content { @@ -164,7 +178,8 @@ } :global(*) { - font-family: "IBM Plex Mono", "Noto Sans Mono Variable", "Noto Sans Mono", monospace; + font-family: "IBM Plex Mono", "Noto Sans Mono Variable", + "Noto Sans Mono", monospace; user-select: none; scrollbar-width: none; -webkit-user-select: none; @@ -281,4 +296,9 @@ padding: 0 var(--padding); white-space: pre-line; } + + .reduce-motion :global(*) { + animation: none !important; + transition: none !important; + } diff --git a/web/src/routes/+layout.ts b/web/src/routes/+layout.ts index e28d0ed6..91e55ac2 100644 --- a/web/src/routes/+layout.ts +++ b/web/src/routes/+layout.ts @@ -17,7 +17,7 @@ export const load: Load = async ({ url }) => { if (browser) { const device = (await import('$lib/device')).device; const settings = get((await import('$lib/settings')).default); - const deviceLanguage = device.preferredLocale; + const deviceLanguage = device.prefers.language; const settingsLanguage = settings.appearance.language; const isValid = (lang: string) => ( diff --git a/web/src/routes/settings/advanced/debug/+page.svelte b/web/src/routes/settings/advanced/debug/+page.svelte index 556a9520..7bad72e6 100644 --- a/web/src/routes/settings/advanced/debug/+page.svelte +++ b/web/src/routes/settings/advanced/debug/+page.svelte @@ -15,23 +15,25 @@ {#if $settings.advanced.debug}
- device: +

device:

is.iPad: {device.is.iPad} is.iPhone: {device.is.iPhone} is.iOS: {device.is.iOS} is.android: {device.is.android} is.mobile: {device.is.mobile} - preferredLocale: {device.preferredLocale} + prefers.language: {device.prefers.language} + prefers.reducedMotion: {device.prefers.reducedMotion} + prefers.reducedTransparency: {device.prefers.reducedTransparency} userAgent: {device.userAgent}
- app: +

app:

is.installed: {app.is.installed}
- version: +

version:

version: {version.version} commit: {version.commit.slice(0, 7)} diff --git a/web/src/routes/settings/general/appearance/+page.svelte b/web/src/routes/settings/general/appearance/+page.svelte index 97c679e6..b3927f36 100644 --- a/web/src/routes/settings/general/appearance/+page.svelte +++ b/web/src/routes/settings/general/appearance/+page.svelte @@ -39,15 +39,15 @@ title={$t("settings.accessibility")} >