fix: persist SponsorBlock preference between launches
This commit is contained in:
@@ -30,6 +30,8 @@ struct ResolvedPlaybackCheck {
|
||||
}
|
||||
_ = NSApplication.shared
|
||||
NSApp.setActivationPolicy(.prohibited)
|
||||
sponsorPreferenceCheck()
|
||||
if CommandLine.arguments[1] == "--sponsor-preference" { return }
|
||||
let input = CommandLine.arguments[1]
|
||||
let file = URL(fileURLWithPath: input)
|
||||
let preference = CommandLine.arguments.first(where: { $0.hasPrefix("--provider=") }).map { String($0.dropFirst(11)) } ?? ""
|
||||
@@ -128,6 +130,31 @@ struct ResolvedPlaybackCheck {
|
||||
}
|
||||
}
|
||||
|
||||
static func sponsorPreferenceCheck() {
|
||||
let suite = "terebi.sponsor-preference." + UUID().uuidString
|
||||
let defaults = UserDefaults(suiteName: suite)!
|
||||
defer { defaults.removePersistentDomain(forName: suite) }
|
||||
func launch(_ configured: Bool = false) -> PlayerModel {
|
||||
PlayerModel(defaults: UserDefaults(suiteName: suite)!, configuration: .init(sponsorBlock: configured))
|
||||
}
|
||||
let first = launch()
|
||||
require(!first.sponsorBlockEnabled, "unconfigured SponsorBlock defaults to disabled")
|
||||
first.setSponsorBlockEnabled(true)
|
||||
first.shutdown()
|
||||
let second = launch()
|
||||
require(second.sponsorBlockEnabled, "enabled preference survives a fresh model/defaults instance")
|
||||
second.setSponsorBlockEnabled(false)
|
||||
second.shutdown()
|
||||
let third = launch(true)
|
||||
require(!third.sponsorBlockEnabled, "saved disabled preference survives restart and overrides config")
|
||||
third.shutdown()
|
||||
defaults.removePersistentDomain(forName: suite)
|
||||
let configured = launch(true)
|
||||
require(configured.sponsorBlockEnabled, "config supplies the initial choice without a saved preference")
|
||||
configured.shutdown()
|
||||
print("PASS: SponsorBlock preference persists enable/disable across launches, with config fallback")
|
||||
}
|
||||
|
||||
static var fixtureSponsors: [SponsorSegment] {
|
||||
[.init(start: 0.5, end: 1.5, videoDuration: 0)]
|
||||
}
|
||||
|
||||
@@ -79,20 +79,20 @@ The optional config file is `~/.config/terebi/config.toml`, or `$XDG_CONFIG_HOME
|
||||
terebi --default-config
|
||||
```
|
||||
|
||||
Copy the settings you want to change into the config file; omitted settings keep their defaults. Settings load at startup, so restart the player after editing. Changes made through menus are session-only.
|
||||
Copy the settings you want to change into the config file; omitted settings keep their defaults. Settings load at startup, so restart the player after editing. Menu changes are session-only except SponsorBlock, whose saved preference overrides its startup config setting.
|
||||
|
||||
The queue shortcut can be rebound with `show_queue` and `hide_queue` under `[keys]`; give both actions the same chord to keep a single toggle.
|
||||
|
||||
### SponsorBlock
|
||||
|
||||
SponsorBlock is **off by default**. Enable **Playback → SponsorBlock → Show Sponsored Ranges** for the session, or opt in at startup:
|
||||
SponsorBlock is **off by default**. **Playback → SponsorBlock → Show Sponsored Ranges** saves your choice across launches. A saved choice overrides the config setting; without one, the startup setting applies:
|
||||
|
||||
```toml
|
||||
[playback]
|
||||
sponsorblock = true
|
||||
```
|
||||
|
||||
Use `false` (the generated default) or omit the setting to stay opted out; non-boolean values are rejected. The optional lookup runs independently of playback, only for canonical YouTube videos. Failure leaves playback unchanged with no sponsored markers.
|
||||
Use `false` (the generated default) or omit the setting to default to disabled when no preference is saved; non-boolean values are rejected. The optional lookup runs independently of playback, only for canonical YouTube videos. Failure leaves playback unchanged with no sponsored markers.
|
||||
|
||||
Enabling it adds a connection to `sponsor.ajay.app`. Requests use a bucket identified by the first four hexadecimal characters of the video ID's SHA-256 hash, reducing disclosure compared with sending the full ID; this is **not anonymous**. Terebi sends no cookies, account credentials or API key and makes no submissions, votes or view reports.
|
||||
|
||||
|
||||
@@ -76,6 +76,7 @@ final class PlayerModel: ObservableObject {
|
||||
private var metadataLifecycle = MetadataLifecycle()
|
||||
private var metadataTask: Task<Void, Never>?
|
||||
@Published private(set) var sponsorBlockEnabled: Bool
|
||||
private let preferenceDefaults: UserDefaults
|
||||
private var sponsorVideoID: String?
|
||||
private var sponsorGeneration: UInt64 = 0
|
||||
private var sponsorTask: Task<Void, Never>?
|
||||
@@ -265,7 +266,8 @@ final class PlayerModel: ObservableObject {
|
||||
compactTitleProgress = configuration.compactTitleProgress
|
||||
automaticYouTubeQuality = configuration.automaticQuality
|
||||
showsBufferInfo = configuration.showBufferInfo
|
||||
sponsorBlockEnabled = configuration.sponsorBlock
|
||||
preferenceDefaults = defaults
|
||||
sponsorBlockEnabled = (defaults.object(forKey: "sponsorBlockEnabled") as? Bool) ?? configuration.sponsorBlock
|
||||
miruroVideoProvider = configuration.miruroVideoProvider
|
||||
miruroCaptionProvider = configuration.miruroCaptionProvider
|
||||
compactWindow = CompactWindowController(snappingEnabled: configuration.snapToEdges, defaults: defaults)
|
||||
@@ -842,6 +844,7 @@ final class PlayerModel: ObservableObject {
|
||||
func setSponsorBlockEnabled(_ enabled: Bool) {
|
||||
guard sponsorBlockEnabled != enabled else { return }
|
||||
sponsorBlockEnabled = enabled
|
||||
preferenceDefaults.set(enabled, forKey: "sponsorBlockEnabled")
|
||||
replaceSponsorMetadata(videoID: sponsorVideoID)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
- [ ] make sponsored blocks skippable:
|
||||
- display the skip button used for openings and endings but for sponsored blocks it shouldn't disappear after a timeout
|
||||
- add a setting for autoskipping (shouldn't activate if seeking onto the sponsored segment (or just before it) to avoid fighting user intention)
|
||||
Reference in New Issue
Block a user