feat(settings): add playback.intro_skip_mode and deprecate auto_skip_intro
Skipping intros stops being a switch and becomes a three-way choice —
never / ask / always — matching what Jellyfin offers and giving viewers a
way to turn the prompt off, which the boolean could not express.
Contract revision 6 → 7: adds playback.intro_skip_mode (enum, default
"ask", profile + profile_device scopes) and marks playback.auto_skip_intro
deprecated without removing it. Every shipped client still reads the
boolean, so for one release the server keeps the pair in step at write
time: canonical PUT/DELETE, the legacy /profiles route, and the legacy
runtime /settings/{key} route all land both rows, and a profile-scope enum
write refreshes user_profiles.auto_skip_intro so GET /profiles stays
truthful. Existing rows are carried onto the new key by a Goose migration
(Postgres) and an InitSchema twin (per-user SQLite); the settings-migrate
planner emits the companion for installs whose backfill runs later.
The spec in docs/design/2026-08-16-intro-skip-mode.md also defines the
prompt state machine every client (web, Android, Apple; browser, tablet,
mobile, TV) implements against this key. It builds on the Android TV
Skip Intro work in silo-android#210 — wall-clock timer, rebuffer-vs-pause
debounce, root-level key handling.
Co-authored-by: evulhotdog <365456+evulhotdog@users.noreply.github.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
evulhotdog
Claude Fable 5
parent
edd919c5f7
commit
af974edfe9
@@ -0,0 +1,50 @@
|
||||
-- Carry every stored playback.auto_skip_intro onto playback.intro_skip_mode.
|
||||
--
|
||||
-- Contract revision 7 replaces the boolean with a three-way enum: the boolean
|
||||
-- could only say "prompt" or "count down then skip", and had no way to turn the
|
||||
-- prompt off. Both spellings stay live for one release — every shipped client
|
||||
-- reads the boolean — so each existing choice needs its enum row or a current
|
||||
-- client would resolve the contract default and quietly discard a preference
|
||||
-- the household already made.
|
||||
--
|
||||
-- Nobody can hold "never" yet, so nothing becomes unrepresentable here.
|
||||
-- ON CONFLICT DO NOTHING covers the partial unique index on each scope, which
|
||||
-- makes a re-run a no-op and, more importantly, never overwrites an enum a
|
||||
-- client wrote itself. See docs/design/2026-08-16-intro-skip-mode.md.
|
||||
|
||||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
INSERT INTO public.user_setting_values (
|
||||
user_id,
|
||||
key,
|
||||
scope,
|
||||
profile_id,
|
||||
client_family,
|
||||
device_id,
|
||||
library_id,
|
||||
series_id,
|
||||
value
|
||||
)
|
||||
SELECT
|
||||
legacy.user_id,
|
||||
'playback.intro_skip_mode',
|
||||
legacy.scope,
|
||||
legacy.profile_id,
|
||||
legacy.client_family,
|
||||
legacy.device_id,
|
||||
legacy.library_id,
|
||||
legacy.series_id,
|
||||
CASE WHEN legacy.value = 'true'::jsonb
|
||||
THEN '"always"'::jsonb
|
||||
ELSE '"ask"'::jsonb
|
||||
END
|
||||
FROM public.user_setting_values AS legacy
|
||||
WHERE legacy.key = 'playback.auto_skip_intro'
|
||||
ON CONFLICT DO NOTHING;
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
DELETE FROM public.user_setting_values
|
||||
WHERE key = 'playback.intro_skip_mode';
|
||||
-- +goose StatementEnd
|
||||
Reference in New Issue
Block a user