One generator rather than one per repo. The point of the contract is that four codebases agree on keys, types, scopes and defaults, and four independently written generators would be four chances to disagree. Go and TypeScript land in this repo; Kotlin and Swift are written into the sibling client checkouts, skipped with a note when they are not present so a server-only developer can still run it. Output is sorted by key so an unrelated manifest edit does not produce spurious diffs. The Kotlin output is the interesting one: it generates the DeviceSettings allowlist Android maintained by hand, plus the BOOLEAN_KEYS/INT_KEYS/ DOUBLE_KEYS classification it kept as a *second* hand-maintained table that had to agree with the first. Both are manifest questions now, so the whole class of "wrote a local key to the server" and "flushed a value the store could not parse" bugs stops being possible by construction. The TypeScript output carries the full definition table — labels, controls, enum members, bounds — so web/src/lib/settingsManifest.ts can be deleted rather than kept in sync: it declared 17 definitions against the contract's 49, with its own two-scope model that does not match the contract's five. make verify-settings-bindings fails when the committed output disagrees with the manifest, wired into CI, so a manifest change cannot merge leaving every client reading stale keys. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
172 lines
5.2 KiB
Go
172 lines
5.2 KiB
Go
// Code generated by cmd/settingsgen from contracts/settings/v1/manifest.json. DO NOT EDIT.
|
|
//
|
|
// Regenerate with: make settings-bindings
|
|
//
|
|
// Every key, type, scope and default here comes from the manifest, so a client
|
|
// cannot drift from the server's contract by editing a constant. Adding a setting
|
|
// is a manifest change plus a regeneration, never a hand-written key.
|
|
|
|
package settingskeys
|
|
|
|
// Revision is the manifest revision these bindings were generated from.
|
|
const Revision = 1
|
|
|
|
// Setting keys, one constant per definition.
|
|
const (
|
|
// Metadata language
|
|
CatalogMetadataLanguage = "catalog.metadata_language"
|
|
// Download quality
|
|
DownloadsDefaultQuality = "downloads.default_quality"
|
|
// Keep watched downloads
|
|
DownloadsKeepWatched = "downloads.keep_watched"
|
|
// Download over Wi-Fi only
|
|
DownloadsWifiOnly = "downloads.wifi_only"
|
|
// Show audiobooks
|
|
NavShowAudiobooks = "nav.show_audiobooks"
|
|
// Preferred audio language
|
|
PlaybackAudioLanguage = "playback.audio_language"
|
|
// Auto-play next episode
|
|
PlaybackAutoPlayNext = "playback.auto_play_next"
|
|
// Preview next episode
|
|
PlaybackAutoPlayNextPreview = "playback.auto_play_next_preview"
|
|
// Auto-skip credits
|
|
PlaybackAutoSkipCredits = "playback.auto_skip_credits"
|
|
// Auto-skip intros
|
|
PlaybackAutoSkipIntro = "playback.auto_skip_intro"
|
|
// Auto-skip recaps
|
|
PlaybackAutoSkipRecap = "playback.auto_skip_recap"
|
|
// Maximum bitrate
|
|
PlaybackMaxBitrateKbps = "playback.max_bitrate_kbps"
|
|
// Next up prompt
|
|
PlaybackNextUpPromptSeconds = "playback.next_up_prompt_seconds"
|
|
// Preferred quality
|
|
PlaybackPreferredQuality = "playback.preferred_quality"
|
|
// Show forced subtitles
|
|
PlaybackShowForcedSubtitles = "playback.show_forced_subtitles"
|
|
// Subtitle appearance
|
|
PlaybackSubtitleAppearance = "playback.subtitle_appearance"
|
|
// Preferred subtitle language
|
|
PlaybackSubtitleLanguage = "playback.subtitle_language"
|
|
// Subtitles
|
|
PlaybackSubtitleMode = "playback.subtitle_mode"
|
|
// Audio sync offset
|
|
PlayerAudioSyncMs = "player.audio_sync_ms"
|
|
// Dolby Vision
|
|
PlayerDolbyVisionEnabled = "player.dolby_vision_enabled"
|
|
// Dolby Vision Profile 7 fallback
|
|
PlayerDvProfile7Hdr10Fallback = "player.dv_profile7_hdr10_fallback"
|
|
// HDR
|
|
PlayerHdrEnabled = "player.hdr_enabled"
|
|
// Match content frame rate
|
|
PlayerMatchFrameRate = "player.match_frame_rate"
|
|
// Screen orientation
|
|
PlayerOrientationMode = "player.orientation_mode"
|
|
// Still watching prompt
|
|
PlayerPassoutThreshold = "player.passout_threshold"
|
|
// Picture in picture
|
|
PlayerPictureInPictureEnabled = "player.picture_in_picture_enabled"
|
|
// Playback speed
|
|
PlayerPlaybackSpeed = "player.playback_speed"
|
|
// Rewind on resume
|
|
PlayerResumeRewindSeconds = "player.resume_rewind_seconds"
|
|
// Seek cache
|
|
PlayerSeekCacheEnabled = "player.seek_cache_enabled"
|
|
// Default sleep timer
|
|
PlayerSleepTimerDefaultMinutes = "player.sleep_timer_default_minutes"
|
|
// Subtitle sync offset
|
|
PlayerSubtitleSyncMs = "player.subtitle_sync_ms"
|
|
// Video sizing
|
|
PlayerVideoGravity = "player.video_gravity"
|
|
// Search scope
|
|
SearchMediaScope = "search.media_scope"
|
|
// Match device caption settings
|
|
SubtitleMatchesDevice = "subtitle.matches_device"
|
|
// Poster badges
|
|
UiCardOverlays = "ui.card_overlays"
|
|
// Custom CSS
|
|
UiCustomCss = "ui.custom_css"
|
|
// Custom theme variables
|
|
UiCustomThemeVars = "ui.custom_theme_vars"
|
|
// Date format
|
|
UiDateFormat = "ui.date_format"
|
|
// Hidden libraries
|
|
UiDisabledLibraryIds = "ui.disabled_library_ids"
|
|
// High contrast
|
|
UiHighContrast = "ui.high_contrast"
|
|
// Library order
|
|
UiLibraryOrder = "ui.library_order"
|
|
// Remembered library view
|
|
UiLibraryPageState = "ui.library_page_state"
|
|
// Next up episodes
|
|
UiNextUpMode = "ui.next_up_mode"
|
|
// Remember library view
|
|
UiRememberLibraryPageState = "ui.remember_library_page_state"
|
|
// Pinned sidebar items
|
|
UiSidebarPins = "ui.sidebar_pins"
|
|
// Text size
|
|
UiTextScale = "ui.text_scale"
|
|
// Text weight
|
|
UiTextWeight = "ui.text_weight"
|
|
// Theme
|
|
UiTheme = "ui.theme"
|
|
// Time format
|
|
UiTimeFormat = "ui.time_format"
|
|
)
|
|
|
|
// Remote lists every key the server stores.
|
|
var Remote = []string{
|
|
CatalogMetadataLanguage,
|
|
PlaybackAudioLanguage,
|
|
PlaybackAutoPlayNext,
|
|
PlaybackAutoPlayNextPreview,
|
|
PlaybackAutoSkipCredits,
|
|
PlaybackAutoSkipIntro,
|
|
PlaybackAutoSkipRecap,
|
|
PlaybackMaxBitrateKbps,
|
|
PlaybackNextUpPromptSeconds,
|
|
PlaybackPreferredQuality,
|
|
PlaybackShowForcedSubtitles,
|
|
PlaybackSubtitleAppearance,
|
|
PlaybackSubtitleLanguage,
|
|
PlaybackSubtitleMode,
|
|
PlayerAudioSyncMs,
|
|
PlayerDolbyVisionEnabled,
|
|
PlayerDvProfile7Hdr10Fallback,
|
|
PlayerHdrEnabled,
|
|
PlayerMatchFrameRate,
|
|
PlayerOrientationMode,
|
|
PlayerPlaybackSpeed,
|
|
PlayerSeekCacheEnabled,
|
|
PlayerSleepTimerDefaultMinutes,
|
|
PlayerSubtitleSyncMs,
|
|
PlayerVideoGravity,
|
|
SearchMediaScope,
|
|
UiCardOverlays,
|
|
UiCustomCss,
|
|
UiCustomThemeVars,
|
|
UiDateFormat,
|
|
UiDisabledLibraryIds,
|
|
UiHighContrast,
|
|
UiLibraryOrder,
|
|
UiLibraryPageState,
|
|
UiNextUpMode,
|
|
UiRememberLibraryPageState,
|
|
UiSidebarPins,
|
|
UiTextScale,
|
|
UiTextWeight,
|
|
UiTheme,
|
|
UiTimeFormat,
|
|
}
|
|
|
|
// ClientLocal lists keys the contract defines but the server never stores.
|
|
var ClientLocal = []string{
|
|
DownloadsDefaultQuality,
|
|
DownloadsKeepWatched,
|
|
DownloadsWifiOnly,
|
|
NavShowAudiobooks,
|
|
PlayerPassoutThreshold,
|
|
PlayerPictureInPictureEnabled,
|
|
PlayerResumeRewindSeconds,
|
|
SubtitleMatchesDevice,
|
|
}
|