mirror of
https://github.com/wukko/cobalt.git
synced 2024-11-15 12:50:01 +00:00
web: respect reduced motion & transparency preferences
also cleaned up settings & device libs
This commit is contained in:
parent
1160b90c17
commit
d27bed7add
10 changed files with 71 additions and 52 deletions
|
@ -75,8 +75,8 @@
|
||||||
"accessibility": "accessibility",
|
"accessibility": "accessibility",
|
||||||
"accessibility.transparency.title": "reduce visual transparency",
|
"accessibility.transparency.title": "reduce visual transparency",
|
||||||
"accessibility.transparency.description": "reduces transparency of surfaces and disables blur effects.",
|
"accessibility.transparency.description": "reduces transparency of surfaces and disables blur effects.",
|
||||||
"accessibility.animations.title": "reduce motion",
|
"accessibility.motion.title": "reduce motion",
|
||||||
"accessibility.animations.description": "replaces animations with instant transitions when possible.",
|
"accessibility.motion.description": "replaces animations with instant transitions when possible.",
|
||||||
|
|
||||||
"language": "language",
|
"language": "language",
|
||||||
"language.auto.title": "use default browser language",
|
"language.auto.title": "use default browser language",
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="viewport-fit=cover, width=device-width, height=device-height, initial-scale=1, maximum-scale=1" />
|
<meta name="viewport" content="viewport-fit=cover, width=device-width, height=device-height, initial-scale=1, maximum-scale=1">
|
||||||
|
|
||||||
<title>cobalt</title>
|
<title>cobalt</title>
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||||
<meta name="apple-mobile-web-app-title" content="cobalt">
|
<meta name="apple-mobile-web-app-title" content="cobalt">
|
||||||
|
|
||||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
<link rel="icon" href="%sveltekit.assets%/favicon.png">
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="%sveltekit.assets%/icons/apple-touch-icon.png">
|
<link rel="apple-touch-icon" sizes="180x180" href="%sveltekit.assets%/icons/apple-touch-icon.png">
|
||||||
|
|
||||||
<link crossorigin="use-credentials" rel="manifest" href="%sveltekit.assets%/manifest.json">
|
<link crossorigin="use-credentials" rel="manifest" href="%sveltekit.assets%/manifest.json">
|
||||||
|
|
|
@ -35,6 +35,10 @@
|
||||||
animation: highlight 2s;
|
animation: highlight 2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(.reduce-motion) .settings-content.animate {
|
||||||
|
animation: highlight-lite 2s !important;
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes highlight {
|
@keyframes highlight {
|
||||||
0% {
|
0% {
|
||||||
box-shadow: none;
|
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) {
|
@media screen and (max-width: 750px) {
|
||||||
.settings-content {
|
.settings-content {
|
||||||
padding: var(--padding);
|
padding: var(--padding);
|
||||||
|
|
|
@ -8,10 +8,13 @@ const android = ua.includes("android") || ua.includes("diordna");
|
||||||
|
|
||||||
const mobile = iOS || android;
|
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 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 = {
|
const device = {
|
||||||
is: {
|
is: {
|
||||||
iPhone,
|
iPhone,
|
||||||
|
@ -20,7 +23,11 @@ const device = {
|
||||||
android,
|
android,
|
||||||
mobile,
|
mobile,
|
||||||
},
|
},
|
||||||
preferredLocale,
|
prefers: {
|
||||||
|
language,
|
||||||
|
reducedMotion,
|
||||||
|
reducedTransparency,
|
||||||
|
},
|
||||||
userAgent: navigator.userAgent,
|
userAgent: navigator.userAgent,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,6 @@ import type { CobaltSettings } from "$lib/types/settings";
|
||||||
|
|
||||||
const defaultSettings: CobaltSettings = {
|
const defaultSettings: CobaltSettings = {
|
||||||
schemaVersion: 1,
|
schemaVersion: 1,
|
||||||
accessibility: {
|
|
||||||
reduceAnimations: false,
|
|
||||||
reduceTransparency: false,
|
|
||||||
},
|
|
||||||
advanced: {
|
advanced: {
|
||||||
debug: false,
|
debug: false,
|
||||||
},
|
},
|
||||||
|
@ -15,11 +11,8 @@ const defaultSettings: CobaltSettings = {
|
||||||
theme: "auto",
|
theme: "auto",
|
||||||
language: defaultLocale,
|
language: defaultLocale,
|
||||||
autoLanguage: true,
|
autoLanguage: true,
|
||||||
},
|
reduceMotion: false,
|
||||||
general: {
|
reduceTransparency: false,
|
||||||
customProcessingEndpoint: "",
|
|
||||||
seenOnboarding: false,
|
|
||||||
seenSafetyWarning: false,
|
|
||||||
},
|
},
|
||||||
save: {
|
save: {
|
||||||
audioFormat: "mp3",
|
audioFormat: "mp3",
|
||||||
|
@ -34,9 +27,6 @@ const defaultSettings: CobaltSettings = {
|
||||||
youtubeVideoCodec: "h264",
|
youtubeVideoCodec: "h264",
|
||||||
youtubeDubBrowserLang: false,
|
youtubeDubBrowserLang: false,
|
||||||
},
|
},
|
||||||
privacy: {
|
|
||||||
trafficAnalytics: true,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultSettingsPage = () => {
|
const defaultSettingsPage = () => {
|
||||||
|
|
|
@ -1,10 +1,5 @@
|
||||||
import languages from '$i18n/languages.json';
|
import languages from '$i18n/languages.json';
|
||||||
|
|
||||||
export type CobaltSettingsAccessibility = {
|
|
||||||
reduceAnimations: boolean,
|
|
||||||
reduceTransparency: boolean,
|
|
||||||
};
|
|
||||||
|
|
||||||
export const themeOptions = ["auto", "light", "dark"] as const;
|
export const themeOptions = ["auto", "light", "dark"] as const;
|
||||||
export const audioFormatOptions = ["best", "mp3", "ogg", "wav", "opus"] as const;
|
export const audioFormatOptions = ["best", "mp3", "ogg", "wav", "opus"] as const;
|
||||||
export const downloadModeOptions = ["auto", "audio", "mute"] as const;
|
export const downloadModeOptions = ["auto", "audio", "mute"] as const;
|
||||||
|
@ -16,18 +11,14 @@ type CobaltSettingsAppearance = {
|
||||||
theme: typeof themeOptions[number],
|
theme: typeof themeOptions[number],
|
||||||
language: keyof typeof languages,
|
language: keyof typeof languages,
|
||||||
autoLanguage: boolean,
|
autoLanguage: boolean,
|
||||||
|
reduceMotion: boolean,
|
||||||
|
reduceTransparency: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
type CobaltSettingsAdvanced = {
|
type CobaltSettingsAdvanced = {
|
||||||
debug: boolean,
|
debug: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
type CobaltSettingsGeneral = {
|
|
||||||
customProcessingEndpoint: string,
|
|
||||||
seenOnboarding: boolean,
|
|
||||||
seenSafetyWarning: boolean,
|
|
||||||
};
|
|
||||||
|
|
||||||
type CobaltSettingsSave = {
|
type CobaltSettingsSave = {
|
||||||
audioFormat: typeof audioFormatOptions[number],
|
audioFormat: typeof audioFormatOptions[number],
|
||||||
disableMetadata: boolean,
|
disableMetadata: boolean,
|
||||||
|
@ -42,18 +33,11 @@ type CobaltSettingsSave = {
|
||||||
youtubeDubBrowserLang: boolean,
|
youtubeDubBrowserLang: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
type CobaltSettingsPrivacy = {
|
|
||||||
trafficAnalytics: boolean,
|
|
||||||
};
|
|
||||||
|
|
||||||
export type CobaltSettings = {
|
export type CobaltSettings = {
|
||||||
schemaVersion: number,
|
schemaVersion: number,
|
||||||
accessibility: CobaltSettingsAccessibility,
|
|
||||||
advanced: CobaltSettingsAdvanced,
|
advanced: CobaltSettingsAdvanced,
|
||||||
appearance: CobaltSettingsAppearance,
|
appearance: CobaltSettingsAppearance,
|
||||||
general: CobaltSettingsGeneral,
|
|
||||||
save: CobaltSettingsSave,
|
save: CobaltSettingsSave,
|
||||||
privacy: CobaltSettingsPrivacy,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type DownloadModeOption = CobaltSettings['save']['downloadMode'];
|
export type DownloadModeOption = CobaltSettings['save']['downloadMode'];
|
||||||
|
|
|
@ -1,12 +1,20 @@
|
||||||
<script>
|
<script lang="ts">
|
||||||
import "@fontsource/ibm-plex-mono/400.css";
|
import "@fontsource/ibm-plex-mono/400.css";
|
||||||
import "@fontsource/ibm-plex-mono/500.css";
|
import "@fontsource/ibm-plex-mono/500.css";
|
||||||
|
|
||||||
|
import settings from "$lib/settings";
|
||||||
import { device, app } from "$lib/device";
|
import { device, app } from "$lib/device";
|
||||||
import currentTheme, { statusBarColors } from "$lib/state/theme";
|
import currentTheme, { statusBarColors } from "$lib/state/theme";
|
||||||
|
|
||||||
import Sidebar from "$components/sidebar/Sidebar.svelte";
|
import Sidebar from "$components/sidebar/Sidebar.svelte";
|
||||||
import NotchSticker from "$components/misc/NotchSticker.svelte";
|
import NotchSticker from "$components/misc/NotchSticker.svelte";
|
||||||
|
|
||||||
|
$: reduceMotion =
|
||||||
|
$settings.appearance.reduceMotion
|
||||||
|
|| device.prefers.reducedMotion;
|
||||||
|
$: reduceTransparency =
|
||||||
|
$settings.appearance.reduceTransparency
|
||||||
|
|| device.prefers.reducedTransparency;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
|
@ -16,7 +24,12 @@
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<div style="display: contents" data-theme={$currentTheme}>
|
<div style="display: contents" data-theme={$currentTheme}>
|
||||||
<div id="cobalt" class:on-iPhone={device.is.iPhone}>
|
<div
|
||||||
|
id="cobalt"
|
||||||
|
class:on-iPhone={device.is.iPhone}
|
||||||
|
class:reduce-motion={reduceMotion}
|
||||||
|
class:reduce-transparency={reduceTransparency}
|
||||||
|
>
|
||||||
{#if device.is.iPhone && app.is.installed}
|
{#if device.is.iPhone && app.is.installed}
|
||||||
<NotchSticker />
|
<NotchSticker />
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -75,7 +88,7 @@
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
:global([data-theme=dark]) {
|
:global([data-theme="dark"]) {
|
||||||
--primary: #000000;
|
--primary: #000000;
|
||||||
--secondary: #e1e1e1;
|
--secondary: #e1e1e1;
|
||||||
|
|
||||||
|
@ -131,7 +144,8 @@
|
||||||
@media screen and (orientation: landscape) {
|
@media screen and (orientation: landscape) {
|
||||||
#cobalt.on-iPhone {
|
#cobalt.on-iPhone {
|
||||||
grid-template-columns:
|
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 {
|
#cobalt.on-iPhone #content {
|
||||||
|
@ -164,7 +178,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(*) {
|
: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;
|
user-select: none;
|
||||||
scrollbar-width: none;
|
scrollbar-width: none;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
|
@ -281,4 +296,9 @@
|
||||||
padding: 0 var(--padding);
|
padding: 0 var(--padding);
|
||||||
white-space: pre-line;
|
white-space: pre-line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.reduce-motion :global(*) {
|
||||||
|
animation: none !important;
|
||||||
|
transition: none !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -17,7 +17,7 @@ export const load: Load = async ({ url }) => {
|
||||||
if (browser) {
|
if (browser) {
|
||||||
const device = (await import('$lib/device')).device;
|
const device = (await import('$lib/device')).device;
|
||||||
const settings = get((await import('$lib/settings')).default);
|
const settings = get((await import('$lib/settings')).default);
|
||||||
const deviceLanguage = device.preferredLocale;
|
const deviceLanguage = device.prefers.language;
|
||||||
const settingsLanguage = settings.appearance.language;
|
const settingsLanguage = settings.appearance.language;
|
||||||
|
|
||||||
const isValid = (lang: string) => (
|
const isValid = (lang: string) => (
|
||||||
|
|
|
@ -15,23 +15,25 @@
|
||||||
|
|
||||||
{#if $settings.advanced.debug}
|
{#if $settings.advanced.debug}
|
||||||
<div id="advanced-page">
|
<div id="advanced-page">
|
||||||
device:
|
<h3>device:</h3>
|
||||||
<div class="message-container subtext">
|
<div class="message-container subtext">
|
||||||
is.iPad: {device.is.iPad}
|
is.iPad: {device.is.iPad}
|
||||||
is.iPhone: {device.is.iPhone}
|
is.iPhone: {device.is.iPhone}
|
||||||
is.iOS: {device.is.iOS}
|
is.iOS: {device.is.iOS}
|
||||||
is.android: {device.is.android}
|
is.android: {device.is.android}
|
||||||
is.mobile: {device.is.mobile}
|
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}
|
userAgent: {device.userAgent}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
app:
|
<h3>app:</h3>
|
||||||
<div class="message-container subtext">
|
<div class="message-container subtext">
|
||||||
is.installed: {app.is.installed}
|
is.installed: {app.is.installed}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
version:
|
<h3>version:</h3>
|
||||||
<div class="message-container subtext">
|
<div class="message-container subtext">
|
||||||
version: {version.version}
|
version: {version.version}
|
||||||
commit: {version.commit.slice(0, 7)}
|
commit: {version.commit.slice(0, 7)}
|
||||||
|
|
|
@ -39,15 +39,15 @@
|
||||||
title={$t("settings.accessibility")}
|
title={$t("settings.accessibility")}
|
||||||
>
|
>
|
||||||
<SettingsToggle
|
<SettingsToggle
|
||||||
settingContext="accessibility"
|
settingContext="appearance"
|
||||||
settingId="reduceTransparency"
|
settingId="reduceTransparency"
|
||||||
title={$t("settings.accessibility.transparency.title")}
|
title={$t("settings.accessibility.transparency.title")}
|
||||||
description={$t("settings.accessibility.transparency.description")}
|
description={$t("settings.accessibility.transparency.description")}
|
||||||
/>
|
/>
|
||||||
<SettingsToggle
|
<SettingsToggle
|
||||||
settingContext="accessibility"
|
settingContext="appearance"
|
||||||
settingId="reduceAnimations"
|
settingId="reduceMotion"
|
||||||
title={$t("settings.accessibility.animations.title")}
|
title={$t("settings.accessibility.motion.title")}
|
||||||
description={$t("settings.accessibility.animations.description")}
|
description={$t("settings.accessibility.motion.description")}
|
||||||
/>
|
/>
|
||||||
</SettingsCategory>
|
</SettingsCategory>
|
||||||
|
|
Loading…
Reference in a new issue