mirror of
https://github.com/yattee/yattee.git
synced 2024-12-22 21:43:41 +00:00
Improved Captions handling
New options for captions in `Settings-Player`: - Always show captions - Default language User can now select whether they want to show captions automatically when the video starts, and select the language. Captions selector now shows proper name -> `English (en)` instead of only `en`
This commit is contained in:
parent
90777d91f6
commit
4db02b2638
@ -217,10 +217,16 @@ final class MPVBackend: PlayerBackend {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
var captions: Captions?
|
var captions: Captions?
|
||||||
if let captionsLanguageCode = Defaults[.captionsLanguageCode] {
|
|
||||||
|
if Defaults[.captionsAutoShow] == true {
|
||||||
|
let captionsLanguageCode = Defaults[.captionsDefaultLanguageCode]
|
||||||
|
if !captionsLanguageCode.isEmpty {
|
||||||
captions = video.captions.first { $0.code == captionsLanguageCode } ??
|
captions = video.captions.first { $0.code == captionsLanguageCode } ??
|
||||||
video.captions.first { $0.code.contains(captionsLanguageCode) }
|
video.captions.first { $0.code.contains(captionsLanguageCode) }
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
captions = nil
|
||||||
|
}
|
||||||
|
|
||||||
let updateCurrentStream = {
|
let updateCurrentStream = {
|
||||||
DispatchQueue.main.async { [weak self] in
|
DispatchQueue.main.async { [weak self] in
|
||||||
@ -254,9 +260,8 @@ final class MPVBackend: PlayerBackend {
|
|||||||
|
|
||||||
self.startClientUpdates()
|
self.startClientUpdates()
|
||||||
|
|
||||||
// Captions should only be displayed when selected by the user,
|
if Defaults[.captionsAutoShow] { self.client?.setSubToAuto() } else { self.client?.setSubToNo() }
|
||||||
// not when the video starts. So, we remove them.
|
PlayerModel.shared.captions = self.captions
|
||||||
self.client?.removeSubs()
|
|
||||||
|
|
||||||
if !preservingTime,
|
if !preservingTime,
|
||||||
!upgrading,
|
!upgrading,
|
||||||
|
@ -405,6 +405,14 @@ final class MPVClient: ObservableObject {
|
|||||||
setString("video", "no")
|
setString("video", "no")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setSubToAuto() {
|
||||||
|
setString("sub", "auto")
|
||||||
|
}
|
||||||
|
|
||||||
|
func setSubToNo() {
|
||||||
|
setString("sub", "no")
|
||||||
|
}
|
||||||
|
|
||||||
var tracksCount: Int {
|
var tracksCount: Int {
|
||||||
Int(getString("track-list/count") ?? "-1") ?? -1
|
Int(getString("track-list/count") ?? "-1") ?? -1
|
||||||
}
|
}
|
||||||
|
@ -301,7 +301,9 @@ extension Defaults.Keys {
|
|||||||
static let lastPlayed = Key<PlayerQueueItem?>("lastPlayed")
|
static let lastPlayed = Key<PlayerQueueItem?>("lastPlayed")
|
||||||
|
|
||||||
static let activeBackend = Key<PlayerBackendType>("activeBackend", default: .mpv)
|
static let activeBackend = Key<PlayerBackendType>("activeBackend", default: .mpv)
|
||||||
|
static let captionsAutoShow = Key<Bool>("captionsAutoShow", default: false)
|
||||||
static let captionsLanguageCode = Key<String?>("captionsLanguageCode")
|
static let captionsLanguageCode = Key<String?>("captionsLanguageCode")
|
||||||
|
static let captionsDefaultLanguageCode = Key<String>("captionsDefaultLanguageCode", default: LanguageCodes.English.rawValue)
|
||||||
|
|
||||||
static let lastUsedPlaylistID = Key<Playlist.ID?>("lastPlaylistID")
|
static let lastUsedPlaylistID = Key<Playlist.ID?>("lastPlaylistID")
|
||||||
static let lastAccountIsPublic = Key<Bool>("lastAccountIsPublic", default: false)
|
static let lastAccountIsPublic = Key<Bool>("lastAccountIsPublic", default: false)
|
||||||
|
107
Shared/LanguageCodes.swift
Normal file
107
Shared/LanguageCodes.swift
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
enum LanguageCodes: String, CaseIterable {
|
||||||
|
case Afrikaans = "af"
|
||||||
|
case Arabic = "ar"
|
||||||
|
case Azerbaijani = "az"
|
||||||
|
case Bengali = "bn"
|
||||||
|
case Catalan = "ca"
|
||||||
|
case Czech = "cs"
|
||||||
|
case Welsh = "cy"
|
||||||
|
case Danish = "da"
|
||||||
|
case German = "de"
|
||||||
|
case Greek = "el"
|
||||||
|
case English = "en"
|
||||||
|
case Spanish = "es"
|
||||||
|
case Persian = "fa"
|
||||||
|
case Finnish = "fi"
|
||||||
|
case Filipino = "fil"
|
||||||
|
case French = "fr"
|
||||||
|
case Irish = "ga"
|
||||||
|
case Hebrew = "he"
|
||||||
|
case Hindi = "hi"
|
||||||
|
case Hungarian = "hu"
|
||||||
|
case Indonesian = "id"
|
||||||
|
case Italian = "it"
|
||||||
|
case Japanese = "ja"
|
||||||
|
case Javanese = "jv"
|
||||||
|
case Korean = "ko"
|
||||||
|
case Lithuanian = "lt"
|
||||||
|
case Malay = "ms"
|
||||||
|
case Maltese = "mt"
|
||||||
|
case Dutch = "nl"
|
||||||
|
case Norwegian = "no"
|
||||||
|
case Polish = "pl"
|
||||||
|
case Portuguese = "pt"
|
||||||
|
case Romanian = "ro"
|
||||||
|
case Russian = "ru"
|
||||||
|
case Slovak = "sk"
|
||||||
|
case Slovene = "sl"
|
||||||
|
case Swedish = "sv"
|
||||||
|
case Swahili = "sw"
|
||||||
|
case Thai = "th"
|
||||||
|
case Tagalog = "tl"
|
||||||
|
case Turkish = "tr"
|
||||||
|
case Ukrainian = "uk"
|
||||||
|
case Urdu = "ur"
|
||||||
|
case Uzbek = "uz"
|
||||||
|
case Vietnamese = "vi"
|
||||||
|
case Xhosa = "xh"
|
||||||
|
case Chinese = "zh"
|
||||||
|
case Zulu = "zu"
|
||||||
|
|
||||||
|
var description: String {
|
||||||
|
switch self {
|
||||||
|
case .Afrikaans: return "Afrikaans"
|
||||||
|
case .Arabic: return "Arabic"
|
||||||
|
case .Azerbaijani: return "Azerbaijani"
|
||||||
|
case .Bengali: return "Bengali"
|
||||||
|
case .Catalan: return "Catalan"
|
||||||
|
case .Czech: return "Czech"
|
||||||
|
case .Welsh: return "Welsh"
|
||||||
|
case .Danish: return "Danish"
|
||||||
|
case .German: return "German"
|
||||||
|
case .Greek: return "Greek"
|
||||||
|
case .English: return "English"
|
||||||
|
case .Spanish: return "Spanish"
|
||||||
|
case .Persian: return "Persian"
|
||||||
|
case .Finnish: return "Finnish"
|
||||||
|
case .Filipino: return "Filipino"
|
||||||
|
case .French: return "French"
|
||||||
|
case .Irish: return "Irish"
|
||||||
|
case .Hebrew: return "Hebrew"
|
||||||
|
case .Hindi: return "Hindi"
|
||||||
|
case .Hungarian: return "Hungarian"
|
||||||
|
case .Indonesian: return "Indonesian"
|
||||||
|
case .Italian: return "Italian"
|
||||||
|
case .Japanese: return "Japanese"
|
||||||
|
case .Javanese: return "Javanese"
|
||||||
|
case .Korean: return "Korean"
|
||||||
|
case .Lithuanian: return "Lithuanian"
|
||||||
|
case .Malay: return "Malay"
|
||||||
|
case .Maltese: return "Maltese"
|
||||||
|
case .Dutch: return "Dutch"
|
||||||
|
case .Norwegian: return "Norwegian"
|
||||||
|
case .Polish: return "Polish"
|
||||||
|
case .Portuguese: return "Portuguese"
|
||||||
|
case .Romanian: return "Romanian"
|
||||||
|
case .Russian: return "Russian"
|
||||||
|
case .Slovak: return "Slovak"
|
||||||
|
case .Slovene: return "Slovene"
|
||||||
|
case .Swedish: return "Swedish"
|
||||||
|
case .Swahili: return "Swahili"
|
||||||
|
case .Thai: return "Thai"
|
||||||
|
case .Tagalog: return "Tagalog"
|
||||||
|
case .Turkish: return "Turkish"
|
||||||
|
case .Ukrainian: return "Ukrainian"
|
||||||
|
case .Urdu: return "Urdu"
|
||||||
|
case .Uzbek: return "Uzbek"
|
||||||
|
case .Vietnamese: return "Vietnamese"
|
||||||
|
case .Xhosa: return "Xhosa"
|
||||||
|
case .Chinese: return "Chinese"
|
||||||
|
case .Zulu: return "Zulu"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func languageName(for code: String) -> String {
|
||||||
|
return LanguageCodes(rawValue: code)?.description ?? "Unknown"
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
import Combine
|
||||||
import Defaults
|
import Defaults
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
@ -393,8 +394,10 @@ struct PlaybackSettings: View {
|
|||||||
} label: {
|
} label: {
|
||||||
HStack(spacing: 4) {
|
HStack(spacing: 4) {
|
||||||
Image(systemName: "text.bubble")
|
Image(systemName: "text.bubble")
|
||||||
if let captions = player.captions {
|
if let captions = player.captions,
|
||||||
Text(captions.code)
|
let language = LanguageCodes(rawValue: captions.code)
|
||||||
|
{
|
||||||
|
Text("\(language.description.capitalized) (\(language.rawValue))")
|
||||||
.foregroundColor(.accentColor)
|
.foregroundColor(.accentColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,12 +30,16 @@ struct PlayerSettings: View {
|
|||||||
|
|
||||||
@Default(.enableReturnYouTubeDislike) private var enableReturnYouTubeDislike
|
@Default(.enableReturnYouTubeDislike) private var enableReturnYouTubeDislike
|
||||||
|
|
||||||
|
@Default(.showRelated) private var showRelated
|
||||||
@Default(.showInspector) private var showInspector
|
@Default(.showInspector) private var showInspector
|
||||||
|
|
||||||
@Default(.showChapters) private var showChapters
|
@Default(.showChapters) private var showChapters
|
||||||
@Default(.showChapterThumbnails) private var showThumbnails
|
@Default(.showChapterThumbnails) private var showThumbnails
|
||||||
@Default(.showChapterThumbnailsOnlyWhenDifferent) private var showThumbnailsOnlyWhenDifferent
|
@Default(.showChapterThumbnailsOnlyWhenDifferent) private var showThumbnailsOnlyWhenDifferent
|
||||||
@Default(.expandChapters) private var expandChapters
|
@Default(.expandChapters) private var expandChapters
|
||||||
@Default(.showRelated) private var showRelated
|
|
||||||
|
@Default(.captionsAutoShow) private var captionsAutoShow
|
||||||
|
@Default(.captionsDefaultLanguageCode) private var captionsDefaultLanguageCode
|
||||||
|
|
||||||
@ObservedObject private var accounts = AccountsModel.shared
|
@ObservedObject private var accounts = AccountsModel.shared
|
||||||
|
|
||||||
@ -93,7 +97,14 @@ struct PlayerSettings: View {
|
|||||||
inspectorVisibilityPicker
|
inspectorVisibilityPicker
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Section(header: SettingsHeader(text: "Captions".localized())) {
|
||||||
|
showCaptionsAutoShowToggle
|
||||||
|
captionDefaultLanguagePicker
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !os(tvOS)
|
||||||
Section(header: SettingsHeader(text: "Chapters".localized())) {
|
Section(header: SettingsHeader(text: "Chapters".localized())) {
|
||||||
showChaptersToggle
|
showChaptersToggle
|
||||||
showThumbnailsToggle
|
showThumbnailsToggle
|
||||||
@ -290,6 +301,21 @@ struct PlayerSettings: View {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var showCaptionsAutoShowToggle: some View {
|
||||||
|
Toggle("Always show captions", isOn: $captionsAutoShow)
|
||||||
|
}
|
||||||
|
|
||||||
|
private var captionDefaultLanguagePicker: some View {
|
||||||
|
Picker("Default language", selection: $captionsDefaultLanguageCode) {
|
||||||
|
ForEach(LanguageCodes.allCases, id: \.self) { language in
|
||||||
|
Text("\(language.description.capitalized) (\(language.rawValue))").tag(language.rawValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if os(macOS)
|
||||||
|
.labelsHidden()
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
private var showChaptersToggle: some View {
|
private var showChaptersToggle: some View {
|
||||||
Toggle("Show chapters", isOn: $showChapters)
|
Toggle("Show chapters", isOn: $showChapters)
|
||||||
}
|
}
|
||||||
|
@ -1076,6 +1076,9 @@
|
|||||||
E258F38A2BF61BD2005B8C28 /* URLTester.swift in Sources */ = {isa = PBXBuildFile; fileRef = E258F3892BF61BD2005B8C28 /* URLTester.swift */; };
|
E258F38A2BF61BD2005B8C28 /* URLTester.swift in Sources */ = {isa = PBXBuildFile; fileRef = E258F3892BF61BD2005B8C28 /* URLTester.swift */; };
|
||||||
E258F38B2BF61BD2005B8C28 /* URLTester.swift in Sources */ = {isa = PBXBuildFile; fileRef = E258F3892BF61BD2005B8C28 /* URLTester.swift */; };
|
E258F38B2BF61BD2005B8C28 /* URLTester.swift in Sources */ = {isa = PBXBuildFile; fileRef = E258F3892BF61BD2005B8C28 /* URLTester.swift */; };
|
||||||
E258F38C2BF61BD2005B8C28 /* URLTester.swift in Sources */ = {isa = PBXBuildFile; fileRef = E258F3892BF61BD2005B8C28 /* URLTester.swift */; };
|
E258F38C2BF61BD2005B8C28 /* URLTester.swift in Sources */ = {isa = PBXBuildFile; fileRef = E258F3892BF61BD2005B8C28 /* URLTester.swift */; };
|
||||||
|
E27568B92BFAAC2000BDF0AF /* LanguageCodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = E27568B82BFAAC2000BDF0AF /* LanguageCodes.swift */; };
|
||||||
|
E27568BA2BFAAC2000BDF0AF /* LanguageCodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = E27568B82BFAAC2000BDF0AF /* LanguageCodes.swift */; };
|
||||||
|
E27568BB2BFAAC2000BDF0AF /* LanguageCodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = E27568B82BFAAC2000BDF0AF /* LanguageCodes.swift */; };
|
||||||
FA97174C2A494700001FF53D /* MPVKit in Frameworks */ = {isa = PBXBuildFile; productRef = FA97174B2A494700001FF53D /* MPVKit */; };
|
FA97174C2A494700001FF53D /* MPVKit in Frameworks */ = {isa = PBXBuildFile; productRef = FA97174B2A494700001FF53D /* MPVKit */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
@ -1547,6 +1550,7 @@
|
|||||||
3DA101AF287C30F50027D920 /* Shared.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; };
|
3DA101AF287C30F50027D920 /* Shared.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; };
|
||||||
E25028AF2BF790F5002CB9FC /* HTTPStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTTPStatus.swift; sourceTree = "<group>"; };
|
E25028AF2BF790F5002CB9FC /* HTTPStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTTPStatus.swift; sourceTree = "<group>"; };
|
||||||
E258F3892BF61BD2005B8C28 /* URLTester.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLTester.swift; sourceTree = "<group>"; };
|
E258F3892BF61BD2005B8C28 /* URLTester.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLTester.swift; sourceTree = "<group>"; };
|
||||||
|
E27568B82BFAAC2000BDF0AF /* LanguageCodes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LanguageCodes.swift; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@ -2295,6 +2299,7 @@
|
|||||||
37D2E0D328B67EFC00F64D52 /* Delay.swift */,
|
37D2E0D328B67EFC00F64D52 /* Delay.swift */,
|
||||||
3761ABFC26F0F8DE00AA496F /* EnvironmentValues.swift */,
|
3761ABFC26F0F8DE00AA496F /* EnvironmentValues.swift */,
|
||||||
E25028AF2BF790F5002CB9FC /* HTTPStatus.swift */,
|
E25028AF2BF790F5002CB9FC /* HTTPStatus.swift */,
|
||||||
|
E27568B82BFAAC2000BDF0AF /* LanguageCodes.swift */,
|
||||||
375B537828DF6CBB004C1D19 /* Localizable.strings */,
|
375B537828DF6CBB004C1D19 /* Localizable.strings */,
|
||||||
3729037D2739E47400EA99F6 /* MenuCommands.swift */,
|
3729037D2739E47400EA99F6 /* MenuCommands.swift */,
|
||||||
37B7958F2771DAE0001CF27B /* OpenURLHandler.swift */,
|
37B7958F2771DAE0001CF27B /* OpenURLHandler.swift */,
|
||||||
@ -3225,6 +3230,7 @@
|
|||||||
37C3A24D272360470087A57A /* ChannelPlaylist+Fixtures.swift in Sources */,
|
37C3A24D272360470087A57A /* ChannelPlaylist+Fixtures.swift in Sources */,
|
||||||
37484C2D26FC844700287258 /* InstanceSettings.swift in Sources */,
|
37484C2D26FC844700287258 /* InstanceSettings.swift in Sources */,
|
||||||
37DD9DA32785BBC900539416 /* NoCommentsView.swift in Sources */,
|
37DD9DA32785BBC900539416 /* NoCommentsView.swift in Sources */,
|
||||||
|
E27568B92BFAAC2000BDF0AF /* LanguageCodes.swift in Sources */,
|
||||||
377A20A92693C9A2002842B8 /* TypedContentAccessors.swift in Sources */,
|
377A20A92693C9A2002842B8 /* TypedContentAccessors.swift in Sources */,
|
||||||
37484C3126FCB8F900287258 /* AccountValidator.swift in Sources */,
|
37484C3126FCB8F900287258 /* AccountValidator.swift in Sources */,
|
||||||
377ABC48286E5887009C986F /* Sequence+Unique.swift in Sources */,
|
377ABC48286E5887009C986F /* Sequence+Unique.swift in Sources */,
|
||||||
@ -3405,6 +3411,7 @@
|
|||||||
371F2F1B269B43D300E4A7AB /* NavigationModel.swift in Sources */,
|
371F2F1B269B43D300E4A7AB /* NavigationModel.swift in Sources */,
|
||||||
3756C2AB2861151C00E4B059 /* NetworkStateModel.swift in Sources */,
|
3756C2AB2861151C00E4B059 /* NetworkStateModel.swift in Sources */,
|
||||||
375EC95A289EEB8200751258 /* QualityProfileForm.swift in Sources */,
|
375EC95A289EEB8200751258 /* QualityProfileForm.swift in Sources */,
|
||||||
|
E27568BA2BFAAC2000BDF0AF /* LanguageCodes.swift in Sources */,
|
||||||
37001564271B1F250049C794 /* AccountsModel.swift in Sources */,
|
37001564271B1F250049C794 /* AccountsModel.swift in Sources */,
|
||||||
378FFBC528660172009E3FBE /* URLParser.swift in Sources */,
|
378FFBC528660172009E3FBE /* URLParser.swift in Sources */,
|
||||||
3761ABFE26F0F8DE00AA496F /* EnvironmentValues.swift in Sources */,
|
3761ABFE26F0F8DE00AA496F /* EnvironmentValues.swift in Sources */,
|
||||||
@ -4000,6 +4007,7 @@
|
|||||||
37FB28432721B22200A57617 /* ContentItem.swift in Sources */,
|
37FB28432721B22200A57617 /* ContentItem.swift in Sources */,
|
||||||
37A7D6EF2B67E3BF009CB1ED /* BrowsingSettingsGroupImporter.swift in Sources */,
|
37A7D6EF2B67E3BF009CB1ED /* BrowsingSettingsGroupImporter.swift in Sources */,
|
||||||
37D2E0D228B67DBC00F64D52 /* AnimationCompletionObserverModifier.swift in Sources */,
|
37D2E0D228B67DBC00F64D52 /* AnimationCompletionObserverModifier.swift in Sources */,
|
||||||
|
E27568BB2BFAAC2000BDF0AF /* LanguageCodes.swift in Sources */,
|
||||||
37A7D6EB2B67E334009CB1ED /* BrowsingSettingsGroupExporter.swift in Sources */,
|
37A7D6EB2B67E334009CB1ED /* BrowsingSettingsGroupExporter.swift in Sources */,
|
||||||
37AAF2A226741C97007FC770 /* FeedView.swift in Sources */,
|
37AAF2A226741C97007FC770 /* FeedView.swift in Sources */,
|
||||||
37484C1B26FC837400287258 /* PlayerSettings.swift in Sources */,
|
37484C1B26FC837400287258 /* PlayerSettings.swift in Sources */,
|
||||||
|
Loading…
Reference in New Issue
Block a user