Move the theme settings onto the content settings page
This commit is contained in:
parent
227834e947
commit
028ae1bedb
6 changed files with 88 additions and 107 deletions
|
|
@ -1410,8 +1410,8 @@ Acceptance:
|
||||||
- Selecting "Dark" applies the dark theme to the document immediately, and
|
- Selecting "Dark" applies the dark theme to the document immediately, and
|
||||||
"System" follows the OS color-scheme preference.
|
"System" follows the OS color-scheme preference.
|
||||||
- Choosing a different app theme applies it and persists after a reload.
|
- Choosing a different app theme applies it and persists after a reload.
|
||||||
- Dragging the font-size slider updates the displayed percentage and saves
|
- Dragging the font-size slider updates the displayed percentage, and saving the
|
||||||
without a separate save button.
|
page applies it and persists it across a reload.
|
||||||
|
|
||||||
### US-091 — Set up how people zap you
|
### US-091 — Set up how people zap you
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -155,8 +155,7 @@ test("US-088 adjust send delay and media servers", async ({seed, as}) => {
|
||||||
|
|
||||||
const page = await as(users.alice, "/settings/content")
|
const page = await as(users.alice, "/settings/content")
|
||||||
|
|
||||||
// The send delay is the only slider on this page.
|
await page.getByLabel("Send delay").fill("3000")
|
||||||
await page.locator('input[type="range"]').fill("3000")
|
|
||||||
|
|
||||||
await page.getByRole("button", {name: "Add Server"}).click()
|
await page.getByRole("button", {name: "Add Server"}).click()
|
||||||
await page.getByRole("listitem").first().locator("input").fill("https://media.test/")
|
await page.getByRole("listitem").first().locator("input").fill("https://media.test/")
|
||||||
|
|
@ -168,7 +167,7 @@ test("US-088 adjust send delay and media servers", async ({seed, as}) => {
|
||||||
await waitForToastToClear(page)
|
await waitForToastToClear(page)
|
||||||
await page.reload()
|
await page.reload()
|
||||||
|
|
||||||
await expect(page.locator('input[type="range"]')).toHaveValue("3000")
|
await expect(page.getByLabel("Send delay")).toHaveValue("3000")
|
||||||
})
|
})
|
||||||
|
|
||||||
test("US-089 configure privacy preferences", async ({seed, as}) => {
|
test("US-089 configure privacy preferences", async ({seed, as}) => {
|
||||||
|
|
@ -235,7 +234,7 @@ test("US-090 change the app's appearance", async ({seed, as}) => {
|
||||||
space.relayList(user.alice)
|
space.relayList(user.alice)
|
||||||
})
|
})
|
||||||
|
|
||||||
const page = await as(users.alice, "/settings/theme", {context: {colorScheme: "light"}})
|
const page = await as(users.alice, "/settings/content", {context: {colorScheme: "light"}})
|
||||||
const body = page.locator("body")
|
const body = page.locator("body")
|
||||||
|
|
||||||
await page.getByRole("button", {name: "Dark", exact: true}).click()
|
await page.getByRole("button", {name: "Dark", exact: true}).click()
|
||||||
|
|
@ -259,11 +258,14 @@ test("US-090 change the app's appearance", async ({seed, as}) => {
|
||||||
|
|
||||||
await expect(body).toHaveAttribute("data-fl-theme", "navy")
|
await expect(body).toHaveAttribute("data-fl-theme", "navy")
|
||||||
|
|
||||||
// Font size is the only slider on this page, and moving it is the save.
|
// Font size is a setting, so it goes out with the rest of the page.
|
||||||
await page.locator('input[type="range"]').fill("1.25")
|
await page.getByLabel("Font size").fill("1.25")
|
||||||
|
await page.getByRole("button", {name: "Save Changes"}).click()
|
||||||
|
|
||||||
|
await expect(page.getByRole("alert")).toContainText("Your settings have been saved!")
|
||||||
await expect(page.locator("html")).toHaveAttribute("style", /font-size:\s*1\.25rem/)
|
await expect(page.locator("html")).toHaveAttribute("style", /font-size:\s*1\.25rem/)
|
||||||
|
|
||||||
|
await waitForToastToClear(page)
|
||||||
await page.reload()
|
await page.reload()
|
||||||
|
|
||||||
await expect(page.locator("html")).toHaveAttribute("style", /font-size:\s*1\.25rem/)
|
await expect(page.locator("html")).toHaveAttribute("style", /font-size:\s*1\.25rem/)
|
||||||
|
|
|
||||||
|
|
@ -67,8 +67,6 @@
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex gap-3 items-center opacity-75 text-sm">
|
<div class="flex gap-3 items-center opacity-75 text-sm">
|
||||||
<Link href="/settings/theme">Theme</Link>
|
|
||||||
/
|
|
||||||
<Link href="/settings/about">About</Link>
|
<Link href="/settings/about">About</Link>
|
||||||
/
|
/
|
||||||
<Button onclick={logout}>Log Out</Button>
|
<Button onclick={logout}>Log Out</Button>
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
import UserCircle from "@assets/icons/user-circle.svg?dataurl"
|
import UserCircle from "@assets/icons/user-circle.svg?dataurl"
|
||||||
import Wallet from "@assets/icons/wallet.svg?dataurl"
|
import Wallet from "@assets/icons/wallet.svg?dataurl"
|
||||||
import ServerPath from "@assets/icons/server-path.svg?dataurl"
|
import ServerPath from "@assets/icons/server-path.svg?dataurl"
|
||||||
import Moon from "@assets/icons/moon.svg?dataurl"
|
|
||||||
import Code2 from "@assets/icons/code-2.svg?dataurl"
|
import Code2 from "@assets/icons/code-2.svg?dataurl"
|
||||||
import Exit from "@assets/icons/logout-3.svg?dataurl"
|
import Exit from "@assets/icons/logout-3.svg?dataurl"
|
||||||
import GalleryMinimalistic from "@assets/icons/gallery-minimalistic.svg?dataurl"
|
import GalleryMinimalistic from "@assets/icons/gallery-minimalistic.svg?dataurl"
|
||||||
|
|
@ -55,9 +54,6 @@
|
||||||
<SecondaryNavItem href="/settings/privacy">
|
<SecondaryNavItem href="/settings/privacy">
|
||||||
<Icon icon={Shield} /> Privacy
|
<Icon icon={Shield} /> Privacy
|
||||||
</SecondaryNavItem>
|
</SecondaryNavItem>
|
||||||
<SecondaryNavItem href="/settings/theme">
|
|
||||||
<Icon icon={Moon} /> Theme
|
|
||||||
</SecondaryNavItem>
|
|
||||||
<SecondaryNavItem href="/settings/about">
|
<SecondaryNavItem href="/settings/about">
|
||||||
<Icon icon={Code2} /> About
|
<Icon icon={Code2} /> About
|
||||||
</SecondaryNavItem>
|
</SecondaryNavItem>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,14 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import cx from "classnames"
|
||||||
import {BlossomServerLists, MuteLists, publish} from "@welshman/app"
|
import {BlossomServerLists, MuteLists, publish} from "@welshman/app"
|
||||||
import NotesMinimalistic from "@assets/icons/notes-minimalistic.svg?dataurl"
|
import NotesMinimalistic from "@assets/icons/notes-minimalistic.svg?dataurl"
|
||||||
|
import Accessibility from "@assets/icons/accessibility.svg?dataurl"
|
||||||
import AddCircle from "@assets/icons/add-circle.svg?dataurl"
|
import AddCircle from "@assets/icons/add-circle.svg?dataurl"
|
||||||
import Microphone from "@assets/icons/microphone.svg?dataurl"
|
import Microphone from "@assets/icons/microphone.svg?dataurl"
|
||||||
|
import Monitor from "@assets/icons/monitor.svg?dataurl"
|
||||||
|
import Moon from "@assets/icons/moon.svg?dataurl"
|
||||||
|
import Palette from "@assets/icons/palette.svg?dataurl"
|
||||||
|
import Sun from "@assets/icons/sun.svg?dataurl"
|
||||||
import {preventDefault} from "@lib/html"
|
import {preventDefault} from "@lib/html"
|
||||||
import Field from "@lib/components/Field.svelte"
|
import Field from "@lib/components/Field.svelte"
|
||||||
import FieldInline from "@lib/components/FieldInline.svelte"
|
import FieldInline from "@lib/components/FieldInline.svelte"
|
||||||
|
|
@ -18,6 +24,7 @@
|
||||||
import {blossomServerLists, deriveUserItem, muteLists} from "@app/core"
|
import {blossomServerLists, deriveUserItem, muteLists} from "@app/core"
|
||||||
import {pushToast} from "@app/toast"
|
import {pushToast} from "@app/toast"
|
||||||
import {PLATFORM_NAME} from "@app/env"
|
import {PLATFORM_NAME} from "@app/env"
|
||||||
|
import {flTheme, flThemes, theme} from "@app/theme"
|
||||||
import {userSettingsValues, publishSettings, createSettingsForm} from "@app/settings"
|
import {userSettingsValues, publishSettings, createSettingsForm} from "@app/settings"
|
||||||
|
|
||||||
const userMuteList = deriveUserItem(MuteLists)
|
const userMuteList = deriveUserItem(MuteLists)
|
||||||
|
|
@ -74,6 +81,16 @@
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
{#snippet colorScheme(value: string, label: string, icon: string)}
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
class={cx("join-item button button-xs", $theme === value ? "button-primary" : "button-neutral")}
|
||||||
|
onclick={() => theme.set(value)}>
|
||||||
|
<Icon {icon} size={4} />
|
||||||
|
{label}
|
||||||
|
</Button>
|
||||||
|
{/snippet}
|
||||||
|
|
||||||
<form {onsubmit}>
|
<form {onsubmit}>
|
||||||
<PageContent>
|
<PageContent>
|
||||||
<Card class="flex flex-col gap-4">
|
<Card class="flex flex-col gap-4">
|
||||||
|
|
@ -116,6 +133,66 @@
|
||||||
{/snippet}
|
{/snippet}
|
||||||
</Field>
|
</Field>
|
||||||
</Card>
|
</Card>
|
||||||
|
<Card class="flex flex-col gap-4">
|
||||||
|
<strong class="flex items-center gap-3 text-lg">
|
||||||
|
<Icon icon={Palette} />
|
||||||
|
Theme Settings
|
||||||
|
</strong>
|
||||||
|
<FieldInline>
|
||||||
|
{#snippet label()}
|
||||||
|
<p>Color scheme</p>
|
||||||
|
{/snippet}
|
||||||
|
{#snippet input()}
|
||||||
|
<div class="join">
|
||||||
|
{@render colorScheme("system", "System", Monitor)}
|
||||||
|
{@render colorScheme("light", "Light", Sun)}
|
||||||
|
{@render colorScheme("dark", "Dark", Moon)}
|
||||||
|
</div>
|
||||||
|
{/snippet}
|
||||||
|
{#snippet info()}
|
||||||
|
<p>System follows whatever your device is set to.</p>
|
||||||
|
{/snippet}
|
||||||
|
</FieldInline>
|
||||||
|
<FieldInline>
|
||||||
|
{#snippet label()}
|
||||||
|
<p>App theme</p>
|
||||||
|
{/snippet}
|
||||||
|
{#snippet input()}
|
||||||
|
<select class="select input capitalize" bind:value={$flTheme} aria-label="Style">
|
||||||
|
{#each flThemes as option (option)}
|
||||||
|
<option value={option}>{option}</option>
|
||||||
|
{/each}
|
||||||
|
</select>
|
||||||
|
{/snippet}
|
||||||
|
{#snippet info()}
|
||||||
|
<p>Changes the shape and texture of everything, not just its colors.</p>
|
||||||
|
{/snippet}
|
||||||
|
</FieldInline>
|
||||||
|
</Card>
|
||||||
|
<Card class="flex flex-col gap-4">
|
||||||
|
<strong class="flex items-center gap-3 text-lg">
|
||||||
|
<Icon icon={Accessibility} />
|
||||||
|
Accessibility
|
||||||
|
</strong>
|
||||||
|
<Field>
|
||||||
|
{#snippet label()}
|
||||||
|
<p>Font size</p>
|
||||||
|
{/snippet}
|
||||||
|
{#snippet secondary()}
|
||||||
|
<p>{Math.round($settings.font_size * 100)}%</p>
|
||||||
|
{/snippet}
|
||||||
|
{#snippet input()}
|
||||||
|
<input
|
||||||
|
class="range w-full"
|
||||||
|
type="range"
|
||||||
|
min="0.8"
|
||||||
|
max="1.3"
|
||||||
|
step="0.05"
|
||||||
|
aria-label="Font size"
|
||||||
|
bind:value={$settings.font_size} />
|
||||||
|
{/snippet}
|
||||||
|
</Field>
|
||||||
|
</Card>
|
||||||
<Card class="flex flex-col gap-4 shadow-md">
|
<Card class="flex flex-col gap-4 shadow-md">
|
||||||
<strong class="text-lg">Editor Settings</strong>
|
<strong class="text-lg">Editor Settings</strong>
|
||||||
<Field>
|
<Field>
|
||||||
|
|
@ -129,6 +206,7 @@
|
||||||
min="0"
|
min="0"
|
||||||
max="10000"
|
max="10000"
|
||||||
step="1000"
|
step="1000"
|
||||||
|
aria-label="Send delay"
|
||||||
bind:value={$settings.send_delay} />
|
bind:value={$settings.send_delay} />
|
||||||
{/snippet}
|
{/snippet}
|
||||||
{#snippet info()}
|
{#snippet info()}
|
||||||
|
|
|
||||||
|
|
@ -1,93 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
import cx from "classnames"
|
|
||||||
import Accessibility from "@assets/icons/accessibility.svg?dataurl"
|
|
||||||
import Monitor from "@assets/icons/monitor.svg?dataurl"
|
|
||||||
import Moon from "@assets/icons/moon.svg?dataurl"
|
|
||||||
import Palette from "@assets/icons/palette.svg?dataurl"
|
|
||||||
import Sun from "@assets/icons/sun.svg?dataurl"
|
|
||||||
import Button from "@lib/components/Button.svelte"
|
|
||||||
import Icon from "@lib/components/Icon.svelte"
|
|
||||||
import Card from "@lib/components/Card.svelte"
|
|
||||||
import Field from "@lib/components/Field.svelte"
|
|
||||||
import FieldInline from "@lib/components/FieldInline.svelte"
|
|
||||||
import PageContent from "@lib/components/PageContent.svelte"
|
|
||||||
import {publishSettings, userSettingsValues} from "@app/settings"
|
|
||||||
import {flTheme, flThemes, theme} from "@app/theme"
|
|
||||||
|
|
||||||
const saveFontSize = () => publishSettings({font_size: fontSize})
|
|
||||||
|
|
||||||
let fontSize = $state($userSettingsValues.font_size)
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{#snippet colorScheme(value: string, label: string, icon: string)}
|
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
class={cx("join-item button button-xs", $theme === value ? "button-primary" : "button-neutral")}
|
|
||||||
onclick={() => theme.set(value)}>
|
|
||||||
<Icon {icon} size={4} />
|
|
||||||
{label}
|
|
||||||
</Button>
|
|
||||||
{/snippet}
|
|
||||||
|
|
||||||
<PageContent>
|
|
||||||
<Card class="flex flex-col gap-4">
|
|
||||||
<strong class="flex items-center gap-3 text-lg">
|
|
||||||
<Icon icon={Palette} />
|
|
||||||
Theme Settings
|
|
||||||
</strong>
|
|
||||||
<FieldInline>
|
|
||||||
{#snippet label()}
|
|
||||||
<p>Color scheme</p>
|
|
||||||
{/snippet}
|
|
||||||
{#snippet input()}
|
|
||||||
<div class="join">
|
|
||||||
{@render colorScheme("system", "System", Monitor)}
|
|
||||||
{@render colorScheme("light", "Light", Sun)}
|
|
||||||
{@render colorScheme("dark", "Dark", Moon)}
|
|
||||||
</div>
|
|
||||||
{/snippet}
|
|
||||||
{#snippet info()}
|
|
||||||
<p>System follows whatever your device is set to.</p>
|
|
||||||
{/snippet}
|
|
||||||
</FieldInline>
|
|
||||||
<FieldInline>
|
|
||||||
{#snippet label()}
|
|
||||||
<p>App theme</p>
|
|
||||||
{/snippet}
|
|
||||||
{#snippet input()}
|
|
||||||
<select class="select input capitalize" bind:value={$flTheme} aria-label="Style">
|
|
||||||
{#each flThemes as option (option)}
|
|
||||||
<option value={option}>{option}</option>
|
|
||||||
{/each}
|
|
||||||
</select>
|
|
||||||
{/snippet}
|
|
||||||
{#snippet info()}
|
|
||||||
<p>Changes the shape and texture of everything, not just its colors.</p>
|
|
||||||
{/snippet}
|
|
||||||
</FieldInline>
|
|
||||||
</Card>
|
|
||||||
<Card class="flex flex-col gap-4">
|
|
||||||
<strong class="flex items-center gap-3 text-lg">
|
|
||||||
<Icon icon={Accessibility} />
|
|
||||||
Accessibility
|
|
||||||
</strong>
|
|
||||||
<Field>
|
|
||||||
{#snippet label()}
|
|
||||||
<p>Font size</p>
|
|
||||||
{/snippet}
|
|
||||||
{#snippet secondary()}
|
|
||||||
<p>{Math.round(fontSize * 100)}%</p>
|
|
||||||
{/snippet}
|
|
||||||
{#snippet input()}
|
|
||||||
<input
|
|
||||||
class="range w-full"
|
|
||||||
type="range"
|
|
||||||
min="0.8"
|
|
||||||
max="1.3"
|
|
||||||
step="0.05"
|
|
||||||
bind:value={fontSize}
|
|
||||||
onchange={saveFontSize} />
|
|
||||||
{/snippet}
|
|
||||||
</Field>
|
|
||||||
</Card>
|
|
||||||
</PageContent>
|
|
||||||
Loading…
Reference in a new issue