Skip to content

Commit 9cee38e

Browse files
Magneaclaude
andcommitted
feat(settings): add mobile grouped-list settings overview
Restructure how settings are presented on mobile web only: - New SettingsMobileOverview renders grouped cards on the /settings landing page: Behavior toggles inline (spoilers, multiple plays, rating prompts) plus chevron link rows grouped into Sync (streaming, flag-gated Plex), Apps (connected, API) and More (data, advanced, preview). - GeneralSettings swaps the Behavior card for the overview on mobile via RenderFor; tablet and desktop render unchanged. - SettingsNavbar hides the drawer nav menu on the mobile landing page since the overview rows now provide navigation; sub-pages and tablet-sm keep the menu. - SettingsGroupRow icon snippet is now optional so overview rows can render label-only (no impact on existing callers). - New i18n meta keys: header_sync, header_more_settings. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent ed5ce05 commit 9cee38e

5 files changed

Lines changed: 152 additions & 6 deletions

File tree

projects/client/i18n/meta/en.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,14 @@
7575
"default": "Streaming Sync",
7676
"description": "Header for the streaming sync settings section."
7777
},
78+
"header_sync": {
79+
"default": "Sync",
80+
"description": "Header for the sync group on the mobile settings overview."
81+
},
82+
"header_more_settings": {
83+
"default": "More",
84+
"description": "Header for the additional settings group on the mobile settings overview."
85+
},
7886
"description_streaming_sync": {
7987
"default": "Automatically sync your watched history and ratings.",
8088
"description": "Description for the streaming sync settings section."

projects/client/src/lib/sections/settings/GeneralSettings.svelte

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,22 @@
66
import BlockedUsers from "./_internal/BlockedUsers.svelte";
77
import Genres from "./_internal/Genres.svelte";
88
import Profile from "./_internal/Profile.svelte";
9+
import SettingsMobileOverview from "./_internal/SettingsMobileOverview.svelte";
910
</script>
1011

1112
<div class="trakt-general-settings">
1213
<Profile />
13-
<Behavior />
14+
15+
<RenderFor audience="authenticated" device={["mobile"]}>
16+
<SettingsMobileOverview />
17+
</RenderFor>
18+
<RenderFor
19+
audience="authenticated"
20+
device={["tablet-sm", "tablet-lg", "desktop"]}
21+
>
22+
<Behavior />
23+
</RenderFor>
24+
1425
<Genres />
1526
<BlockedUsers />
1627
<Appearance />

projects/client/src/lib/sections/settings/_internal/SettingsGroupRow.svelte

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
type CommonRowProps = {
66
title: string;
77
description?: string;
8-
icon: Snippet;
8+
icon?: Snippet;
99
tag?: Snippet;
1010
};
1111
@@ -34,9 +34,11 @@
3434
</script>
3535

3636
{#snippet rowContent()}
37-
<div class="row-icon-container">
38-
{@render icon()}
39-
</div>
37+
{#if icon}
38+
<div class="row-icon-container">
39+
{@render icon()}
40+
</div>
41+
{/if}
4042

4143
<div class="row-body">
4244
<div class="row-title-line">
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
<script lang="ts">
2+
import Switch from "$lib/components/toggles/Switch.svelte";
3+
import { FeatureFlag } from "$lib/features/feature-flag/models/FeatureFlag.ts";
4+
import RenderForFeature from "$lib/guards/RenderForFeature.svelte";
5+
import * as m from "$lib/features/i18n/messages.ts";
6+
import { UrlBuilder } from "$lib/utils/url/UrlBuilder.ts";
7+
import SettingsGroupCard from "./SettingsGroupCard.svelte";
8+
import SettingsGroupRow from "./SettingsGroupRow.svelte";
9+
import { useSettings } from "./useSettings.ts";
10+
11+
const { watchAgain, spoilers, ratingPrompt, isSavingSettings } =
12+
useSettings();
13+
</script>
14+
15+
<div class="trakt-settings-mobile-overview">
16+
<SettingsGroupCard title={m.header_behavior()}>
17+
<SettingsGroupRow title={m.text_show_spoilers()} variant="custom">
18+
<Switch
19+
label={m.switch_label_spoilers()}
20+
checked={!$spoilers.isHidden}
21+
onclick={() => $spoilers.set(!$spoilers.isHidden)}
22+
disabled={$isSavingSettings}
23+
color="purple"
24+
/>
25+
</SettingsGroupRow>
26+
27+
<SettingsGroupRow
28+
title={m.text_settings_enable_multiple_plays()}
29+
variant="custom"
30+
>
31+
<Switch
32+
label={m.switch_label_multiple_watches()}
33+
checked={$watchAgain.hasWatchAgain}
34+
onclick={() => $watchAgain.set(!$watchAgain.hasWatchAgain)}
35+
disabled={$isSavingSettings}
36+
color="purple"
37+
/>
38+
</SettingsGroupRow>
39+
40+
<SettingsGroupRow
41+
title={m.text_settings_show_rating_prompt()}
42+
variant="custom"
43+
>
44+
<Switch
45+
label={m.switch_label_rating_prompt()}
46+
checked={$ratingPrompt.showRatingPrompt}
47+
onclick={() => $ratingPrompt.set(!$ratingPrompt.showRatingPrompt)}
48+
disabled={$isSavingSettings}
49+
color="purple"
50+
/>
51+
</SettingsGroupRow>
52+
</SettingsGroupCard>
53+
54+
<SettingsGroupCard title={m.header_sync()}>
55+
<SettingsGroupRow
56+
title={m.link_text_streaming_sync_settings()}
57+
variant="link"
58+
href={UrlBuilder.settings.streamingServices()}
59+
/>
60+
61+
<RenderForFeature flag={FeatureFlag.PlexSync}>
62+
{#snippet enabled()}
63+
<SettingsGroupRow
64+
title={m.link_text_plex_settings()}
65+
variant="link"
66+
href={UrlBuilder.settings.plex()}
67+
/>
68+
{/snippet}
69+
</RenderForFeature>
70+
</SettingsGroupCard>
71+
72+
<SettingsGroupCard title={m.link_text_apps_settings()}>
73+
<SettingsGroupRow
74+
title={m.heading_connected_apps()}
75+
variant="link"
76+
href={UrlBuilder.settings.appsConnected()}
77+
/>
78+
79+
<SettingsGroupRow
80+
title={m.heading_api_applications()}
81+
variant="link"
82+
href={UrlBuilder.settings.appsApi()}
83+
/>
84+
</SettingsGroupCard>
85+
86+
<SettingsGroupCard title={m.header_more_settings()}>
87+
<SettingsGroupRow
88+
title={m.link_text_data_settings()}
89+
variant="link"
90+
href={UrlBuilder.settings.data()}
91+
/>
92+
93+
<SettingsGroupRow
94+
title={m.link_text_advanced_settings()}
95+
variant="link"
96+
href={UrlBuilder.settings.advanced()}
97+
/>
98+
99+
<SettingsGroupRow
100+
title={m.link_text_preview_settings()}
101+
variant="link"
102+
href={UrlBuilder.settings.preview()}
103+
/>
104+
</SettingsGroupCard>
105+
</div>
106+
107+
<style lang="scss">
108+
.trakt-settings-mobile-overview {
109+
display: flex;
110+
flex-direction: column;
111+
gap: var(--gap-xl);
112+
}
113+
</style>

projects/client/src/lib/sections/settings/_internal/SettingsNavbar.svelte

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
<script lang="ts">
2+
import { page } from "$app/state";
23
import RenderFor from "$lib/guards/RenderFor.svelte";
4+
import { UrlBuilder } from "$lib/utils/url/UrlBuilder.ts";
35
import SettingsNavLinks from "./SettingsNavLinks.svelte";
46
import SettingsNavMenu from "./SettingsNavMenu.svelte";
7+
8+
const isGeneralSettings = $derived(
9+
page.url.pathname === UrlBuilder.settings.general(),
10+
);
511
</script>
612

713
<RenderFor audience="authenticated" device={["tablet-lg", "desktop"]}>
@@ -10,10 +16,16 @@
1016
</nav>
1117
</RenderFor>
1218

13-
<RenderFor audience="authenticated" device={["tablet-sm", "mobile"]}>
19+
<RenderFor audience="authenticated" device={["tablet-sm"]}>
1420
<SettingsNavMenu />
1521
</RenderFor>
1622

23+
<RenderFor audience="authenticated" device={["mobile"]}>
24+
{#if !isGeneralSettings}
25+
<SettingsNavMenu />
26+
{/if}
27+
</RenderFor>
28+
1729
<style lang="scss">
1830
.trakt-settings-navbar {
1931
position: sticky;

0 commit comments

Comments
 (0)