Interface tweaks for SponsorBlock during playback

Show/Hide categories in timeline.
Show/Hide notice after skip.
Show adjusted or actual total time.
This commit is contained in:
Toni Förster 2024-04-23 22:08:08 +02:00
parent b5ac760af2
commit ae65acdd16
No known key found for this signature in database
GPG Key ID: 292F3E5086C83FC7
5 changed files with 34 additions and 12 deletions

View File

@ -71,13 +71,13 @@ final class SeekModel: ObservableObject {
func showOSD() { func showOSD() {
guard !presentingOSD else { return } guard !presentingOSD else { return }
withAnimation(.easeIn(duration: 0.1)) { self.presentingOSD = true } presentingOSD = true
} }
func hideOSD() { func hideOSD() {
guard presentingOSD else { return } guard presentingOSD else { return }
withAnimation(.easeIn(duration: 0.1)) { self.presentingOSD = false } presentingOSD = false
} }
func hideOSDWithDelay() { func hideOSDWithDelay() {

View File

@ -244,6 +244,9 @@ extension Defaults.Keys {
static let sponsorBlockInstance = Key<String>("sponsorBlockInstance", default: "https://sponsor.ajay.app") static let sponsorBlockInstance = Key<String>("sponsorBlockInstance", default: "https://sponsor.ajay.app")
static let sponsorBlockCategories = Key<Set<String>>("sponsorBlockCategories", default: Set(SponsorBlockAPI.categories)) static let sponsorBlockCategories = Key<Set<String>>("sponsorBlockCategories", default: Set(SponsorBlockAPI.categories))
static let sponsorBlockColors = Key<[String: String]>("sponsorBlockColors", default: SponsorBlockColors.dictionary) static let sponsorBlockColors = Key<[String: String]>("sponsorBlockColors", default: SponsorBlockColors.dictionary)
static let sponsorBlockShowTimeWithSkipsRemoved = Key<Bool>("sponsorBlockShowTimeWithSkipsRemoved", default: false)
static let sponsorBlockShowCategoriesInTimeline = Key<Bool>("sponsorBlockShowCategoriesInTimeline", default: true)
static let sponsorBlockShowNoticeAfterSkip = Key<Bool>("sponsorBlockShowNoticeAfterSkip", default: true)
// MARK: GROUP - Locations // MARK: GROUP - Locations

View File

@ -14,6 +14,7 @@ struct Seek: View {
@Default(.playerControlsLayout) private var regularPlayerControlsLayout @Default(.playerControlsLayout) private var regularPlayerControlsLayout
@Default(.fullScreenPlayerControlsLayout) private var fullScreenPlayerControlsLayout @Default(.fullScreenPlayerControlsLayout) private var fullScreenPlayerControlsLayout
@Default(.sponsorBlockColors) private var sponsorBlockColors @Default(.sponsorBlockColors) private var sponsorBlockColors
@Default(.sponsorBlockShowNoticeAfterSkip) private var showNoticeAfterSkip
private func getColor(for category: String) -> Color { private func getColor(for category: String) -> Color {
if let hexString = sponsorBlockColors[category], let rgbValue = Int(hexString.dropFirst(), radix: 16) { if let hexString = sponsorBlockColors[category], let rgbValue = Int(hexString.dropFirst(), radix: 16) {
@ -36,6 +37,7 @@ struct Seek: View {
#endif #endif
} }
.opacity(visible || YatteeApp.isForPreviews ? 1 : 0) .opacity(visible || YatteeApp.isForPreviews ? 1 : 0)
.animation(.easeIn)
} }
var content: some View { var content: some View {
@ -130,6 +132,7 @@ struct Seek: View {
var visible: Bool { var visible: Bool {
guard !(model.lastSeekTime.isNil && !model.isSeeking) else { return false } guard !(model.lastSeekTime.isNil && !model.isSeeking) else { return false }
if let type = model.lastSeekType, !type.presentable { return false } if let type = model.lastSeekType, !type.presentable { return false }
if !showNoticeAfterSkip { if case .segmentSkip? = model.lastSeekType { return false }}
return !controls.presentingControls && !controls.presentingOverlays && model.presentingOSD return !controls.presentingControls && !controls.presentingOverlays && model.presentingOSD
} }

View File

@ -52,6 +52,8 @@ struct TimelineView: View {
@Default(.playerControlsLayout) private var regularPlayerControlsLayout @Default(.playerControlsLayout) private var regularPlayerControlsLayout
@Default(.fullScreenPlayerControlsLayout) private var fullScreenPlayerControlsLayout @Default(.fullScreenPlayerControlsLayout) private var fullScreenPlayerControlsLayout
@Default(.sponsorBlockColors) private var sponsorBlockColors @Default(.sponsorBlockColors) private var sponsorBlockColors
@Default(.sponsorBlockShowTimeWithSkipsRemoved) private var showTimeWithSkipsRemoved
@Default(.sponsorBlockShowCategoriesInTimeline) private var showCategoriesInTimeline
var playerControlsLayout: PlayerControlsLayout { var playerControlsLayout: PlayerControlsLayout {
player.playingFullScreen ? fullScreenPlayerControlsLayout : regularPlayerControlsLayout player.playingFullScreen ? fullScreenPlayerControlsLayout : regularPlayerControlsLayout
@ -84,13 +86,15 @@ struct TimelineView: View {
Group { Group {
VStack(spacing: 3) { VStack(spacing: 3) {
if dragging { if dragging {
if let segment = projectedSegment, if showCategoriesInTimeline {
let description = SponsorBlockAPI.categoryDescription(segment.category) if let segment = projectedSegment,
{ let description = SponsorBlockAPI.categoryDescription(segment.category)
Text(description) {
.font(.system(size: playerControlsLayout.segmentFontSize)) Text(description)
.fixedSize() .font(.system(size: playerControlsLayout.segmentFontSize))
.foregroundColor(getColor(for: segment.category)) .fixedSize()
.foregroundColor(getColor(for: segment.category))
}
} }
if let chapter = projectedChapter { if let chapter = projectedChapter {
Text(chapter.title) Text(chapter.title)
@ -156,8 +160,10 @@ struct TimelineView: View {
.frame(width: (dragging ? projectedValue : current) * oneUnitWidth) .frame(width: (dragging ? projectedValue : current) * oneUnitWidth)
.zIndex(1) .zIndex(1)
segmentsLayers if showCategoriesInTimeline {
.zIndex(2) segmentsLayers
.zIndex(2)
}
} }
.clipShape(RoundedRectangle(cornerRadius: cornerRadius)) .clipShape(RoundedRectangle(cornerRadius: cornerRadius))
@ -247,7 +253,7 @@ struct TimelineView: View {
} }
} }
} else { } else {
Text(dragging ? playerTime.durationPlaybackTime : playerTime.withoutSegmentsPlaybackTime) Text(dragging || !showTimeWithSkipsRemoved ? playerTime.durationPlaybackTime : playerTime.withoutSegmentsPlaybackTime)
.clipShape(RoundedRectangle(cornerRadius: 3)) .clipShape(RoundedRectangle(cornerRadius: 3))
.frame(minWidth: 35) .frame(minWidth: 35)
} }

View File

@ -8,6 +8,9 @@ struct SponsorBlockSettings: View {
@Default(.sponsorBlockInstance) private var sponsorBlockInstance @Default(.sponsorBlockInstance) private var sponsorBlockInstance
@Default(.sponsorBlockCategories) private var sponsorBlockCategories @Default(.sponsorBlockCategories) private var sponsorBlockCategories
@Default(.sponsorBlockColors) private var sponsorBlockColors @Default(.sponsorBlockColors) private var sponsorBlockColors
@Default(.sponsorBlockShowTimeWithSkipsRemoved) private var showTimeWithSkipsRemoved
@Default(.sponsorBlockShowCategoriesInTimeline) private var showCategoriesInTimeline
@Default(.sponsorBlockShowNoticeAfterSkip) private var showNoticeAfterSkip
var body: some View { var body: some View {
Group { Group {
@ -42,6 +45,13 @@ struct SponsorBlockSettings: View {
.keyboardType(.URL) .keyboardType(.URL)
#endif #endif
} }
Section(header: Text("Playback")) {
Toggle("Categories in timeline", isOn: $showCategoriesInTimeline)
Toggle("Post-skip notice", isOn: $showNoticeAfterSkip)
Toggle("Adjusted total time", isOn: $showTimeWithSkipsRemoved)
}
Section(header: SettingsHeader(text: "Categories to Skip".localized())) { Section(header: SettingsHeader(text: "Categories to Skip".localized())) {
categoryRows categoryRows
} }