Fix SwiftUI view crashing - fix captions in XIB
This commit is contained in:
parent
484bd445e6
commit
6bfd0c4fc6
|
@ -478,7 +478,7 @@
|
|||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 26;
|
||||
CURRENT_PROJECT_VERSION = 29;
|
||||
DEVELOPMENT_ASSET_PATHS = "";
|
||||
DEVELOPMENT_TEAM = 9R8RREG67J;
|
||||
ENABLE_BITCODE = NO;
|
||||
|
@ -504,7 +504,7 @@
|
|||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 26;
|
||||
CURRENT_PROJECT_VERSION = 29;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_ASSET_PATHS = "";
|
||||
DEVELOPMENT_TEAM = 9R8RREG67J;
|
||||
|
|
|
@ -32,6 +32,7 @@ struct ConnectToServerView: View {
|
|||
@State private var isSignInErrored = false;
|
||||
@State private var isConnected = false;
|
||||
@State private var serverName = "";
|
||||
@State private var usernameDisabled: Bool = false;
|
||||
@State private var publicUsers: [publicUser] = [];
|
||||
@State private var lastPublicUsers: [publicUser] = [];
|
||||
@Binding var rootIsActive : Bool
|
||||
|
@ -244,6 +245,7 @@ struct ConnectToServerView: View {
|
|||
TextField("Username", text: $username)
|
||||
.disableAutocorrection(true)
|
||||
.autocapitalization(.none)
|
||||
.disabled(usernameDisabled)
|
||||
SecureField("Password", text: $password)
|
||||
.disableAutocorrection(true)
|
||||
.autocapitalization(.none)
|
||||
|
@ -285,6 +287,7 @@ struct ConnectToServerView: View {
|
|||
Section() {
|
||||
Button {
|
||||
_publicUsers.wrappedValue = _lastPublicUsers.wrappedValue
|
||||
_usernameDisabled.wrappedValue = false;
|
||||
} label: {
|
||||
HStack() {
|
||||
HStack() {
|
||||
|
@ -304,6 +307,7 @@ struct ConnectToServerView: View {
|
|||
if(pubuser.hasPassword) {
|
||||
_lastPublicUsers.wrappedValue = _publicUsers.wrappedValue
|
||||
_username.wrappedValue = pubuser.username
|
||||
_usernameDisabled.wrappedValue = true;
|
||||
_publicUsers.wrappedValue = []
|
||||
} else {
|
||||
_publicUsers.wrappedValue = []
|
||||
|
@ -339,7 +343,9 @@ struct ConnectToServerView: View {
|
|||
|
||||
Section() {
|
||||
Button() {
|
||||
_lastPublicUsers.wrappedValue = _publicUsers.wrappedValue;
|
||||
_publicUsers.wrappedValue = []
|
||||
_username.wrappedValue = ""
|
||||
} label: {
|
||||
HStack() {
|
||||
Text("Other User").font(.subheadline).fontWeight(.semibold)
|
||||
|
|
|
@ -204,7 +204,7 @@ struct ContentView: View {
|
|||
LatestMediaView(library: library_id)
|
||||
}.padding(EdgeInsets(top: 4, leading: 0, bottom: 0, trailing: 0))
|
||||
}
|
||||
Spacer().frame(height: 20)
|
||||
Spacer().frame(height: UIDevice.current.userInterfaceIdiom == .phone ? 20 : 30)
|
||||
}
|
||||
.navigationTitle("Home")
|
||||
.toolbar {
|
||||
|
|
|
@ -172,6 +172,7 @@ struct ContinueWatchingView: View {
|
|||
}.padding(.trailing, 5)
|
||||
}
|
||||
}
|
||||
Spacer().frame(width: 2)
|
||||
}.frame(height: 215)
|
||||
} else {
|
||||
EmptyView()
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(MARKETING_VERSION)</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>26</string>
|
||||
<string>29</string>
|
||||
<key>ITSAppUsesNonExemptEncryption</key>
|
||||
<false/>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
|
|
|
@ -24,7 +24,7 @@ struct ItemView: View {
|
|||
|
||||
var body: some View {
|
||||
if(playback.shouldPlay) {
|
||||
LoadingView(isShowing: $shouldShowLoadingView) {
|
||||
LoadingViewNoBlur(isShowing: $shouldShowLoadingView) {
|
||||
VLCPlayerWithControls(item: playback.itemToPlay, loadBinding: $shouldShowLoadingView, pBinding: _playback.projectedValue.shouldPlay)
|
||||
.navigationBarHidden(true)
|
||||
.navigationBarBackButtonHidden(true)
|
||||
|
|
|
@ -38,3 +38,42 @@ struct LoadingView<Content>: View where Content: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct LoadingViewNoBlur<Content>: View where Content: View {
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
@Binding var isShowing: Bool // should the modal be visible?
|
||||
var content: () -> Content
|
||||
var text: String? // the text to display under the ProgressView - defaults to "Loading..."
|
||||
|
||||
var body: some View {
|
||||
GeometryReader { geometry in
|
||||
ZStack(alignment: .center) {
|
||||
// the content to display - if the modal is showing, we'll blur it
|
||||
content()
|
||||
.disabled(isShowing)
|
||||
|
||||
// all contents inside here will only be shown when isShowing is true
|
||||
if isShowing {
|
||||
// this Rectangle is a semi-transparent black overlay
|
||||
Rectangle()
|
||||
.fill(Color.black).opacity(isShowing ? 0.6 : 0)
|
||||
.edgesIgnoringSafeArea(.all)
|
||||
|
||||
// the magic bit - our ProgressView just displays an activity
|
||||
// indicator, with some text underneath showing what we are doing
|
||||
HStack() {
|
||||
ProgressView()
|
||||
Text(text ?? "Loading").fontWeight(.semibold).font(.callout).offset(x: 60)
|
||||
Spacer()
|
||||
}
|
||||
.padding(EdgeInsets(top: 20, leading: 20, bottom: 20, trailing: 10))
|
||||
.frame(width: 250)
|
||||
.background(colorScheme == .dark ? Color(UIColor.systemGray6) : Color.white)
|
||||
.foregroundColor(Color.primary)
|
||||
.cornerRadius(16)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
<constraint firstAttribute="width" constant="91" id="LbL-h0-EYA"/>
|
||||
<constraint firstAttribute="height" constant="34" id="OkD-Dr-Ina"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="19"/>
|
||||
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="18"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
|
@ -125,7 +125,7 @@
|
|||
<accessibility key="accessibilityConfiguration">
|
||||
<accessibilityTraits key="traits" staticText="YES" header="YES"/>
|
||||
</accessibility>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="20"/>
|
||||
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="19"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<color key="highlightedColor" systemColor="labelColor"/>
|
||||
</label>
|
||||
|
|
|
@ -39,7 +39,7 @@ protocol PlayerViewControllerDelegate: AnyObject {
|
|||
func exitPlayer(_ viewController: PlayerViewController)
|
||||
}
|
||||
|
||||
class PlayerViewController: UIViewController, VLCMediaDelegate, VLCMediaPlayerDelegate, VideoPlayerSettingsDelegate {
|
||||
class PlayerViewController: UIViewController, VLCMediaDelegate, VLCMediaPlayerDelegate {
|
||||
|
||||
weak var delegate: PlayerViewControllerDelegate?
|
||||
|
||||
|
@ -58,14 +58,23 @@ class PlayerViewController: UIViewController, VLCMediaDelegate, VLCMediaPlayerDe
|
|||
var shouldShowLoadingScreen: Bool = false;
|
||||
var ssTargetValueOffset: Int = 0;
|
||||
var ssStartValue: Int = 0;
|
||||
var optionsVC: VideoPlayerSettingsView?;
|
||||
|
||||
var paused: Bool = true;
|
||||
var lastTime: Float = 0.0;
|
||||
var startTime: Int = 0;
|
||||
var controlsAppearTime: Double = 0;
|
||||
|
||||
var selectedAudioTrack: Int32 = -1;
|
||||
var selectedCaptionTrack: Int32 = -1;
|
||||
var selectedAudioTrack: Int32 = -1 {
|
||||
didSet {
|
||||
print(selectedAudioTrack)
|
||||
}
|
||||
};
|
||||
var selectedCaptionTrack: Int32 = -1 {
|
||||
didSet {
|
||||
print(selectedCaptionTrack)
|
||||
}
|
||||
}
|
||||
var playSessionId: String = "";
|
||||
var lastProgressReportTime: Double = 0;
|
||||
|
||||
|
@ -155,23 +164,15 @@ class PlayerViewController: UIViewController, VLCMediaDelegate, VLCMediaPlayerDe
|
|||
}
|
||||
|
||||
@IBAction func settingsButtonTapped(_ sender: UIButton) {
|
||||
let optionsVC = VideoPlayerSettingsView()
|
||||
print(self.selectedAudioTrack)
|
||||
print(self.selectedCaptionTrack)
|
||||
optionsVC.currentSubtitleTrack = self.selectedCaptionTrack
|
||||
optionsVC.currentAudioTrack = self.selectedAudioTrack
|
||||
optionsVC.delegate = self;
|
||||
optionsVC.subtitles = subtitleTrackArray
|
||||
optionsVC.audioTracks = audioTrackArray
|
||||
// Use the popover presentation style for your view controller.
|
||||
let navVC = UINavigationController(rootViewController: optionsVC)
|
||||
navVC.modalPresentationStyle = .popover
|
||||
navVC.popoverPresentationController?.sourceView = playerSettingsButton
|
||||
optionsVC = VideoPlayerSettingsView()
|
||||
optionsVC?.delegate = self
|
||||
|
||||
optionsVC?.modalPresentationStyle = .popover
|
||||
optionsVC?.popoverPresentationController?.sourceView = playerSettingsButton
|
||||
|
||||
|
||||
// Present the view controller (in a popover).
|
||||
self.present(navVC, animated: true) {
|
||||
self.present(optionsVC!, animated: true) {
|
||||
print("popover visible, pause playback")
|
||||
self.mediaPlayer.pause()
|
||||
self.mainActionButton.setImage(UIImage(systemName: "play"), for: .normal)
|
||||
|
@ -179,6 +180,7 @@ class PlayerViewController: UIViewController, VLCMediaDelegate, VLCMediaPlayerDe
|
|||
}
|
||||
|
||||
func settingsPopoverDismissed() {
|
||||
optionsVC?.dismiss(animated: true, completion: nil)
|
||||
self.mediaPlayer.play()
|
||||
self.mainActionButton.setImage(UIImage(systemName: "pause"), for: .normal)
|
||||
}
|
||||
|
@ -188,7 +190,6 @@ class PlayerViewController: UIViewController, VLCMediaDelegate, VLCMediaPlayerDe
|
|||
|
||||
//View has loaded.
|
||||
//Show loading screen
|
||||
delegate?.showLoadingView(self)
|
||||
|
||||
mediaPlayer.perform(Selector(("setTextRendererFontSize:")), with: 14)
|
||||
//mediaPlayer.wrappedValue.perform(Selector(("setTextRendererFont:")), with: "Copperplate")
|
||||
|
@ -197,11 +198,7 @@ class PlayerViewController: UIViewController, VLCMediaDelegate, VLCMediaPlayerDe
|
|||
mediaPlayer.delegate = self
|
||||
mediaPlayer.drawable = videoContentView
|
||||
|
||||
if(manifest.Type == "Episode") {
|
||||
titleLabel.text = "\(manifest.Name) - S\(String(manifest.ParentIndexNumber ?? 0)):E\(String(manifest.IndexNumber ?? 0)) - \(manifest.SeriesName ?? "")"
|
||||
} else {
|
||||
titleLabel.text = manifest.Name
|
||||
}
|
||||
|
||||
//Fetch max bitrate from UserDefaults depending on current connection mode
|
||||
let defaults = UserDefaults.standard
|
||||
|
@ -333,10 +330,12 @@ class PlayerViewController: UIViewController, VLCMediaDelegate, VLCMediaPlayerDe
|
|||
|
||||
//MARK: VideoPlayerSettings Delegate
|
||||
func subtitleTrackChanged(newTrackID: Int32) {
|
||||
selectedCaptionTrack = newTrackID
|
||||
mediaPlayer.currentVideoSubTitleIndex = newTrackID
|
||||
}
|
||||
|
||||
func audioTrackChanged(newTrackID: Int32) {
|
||||
selectedAudioTrack = newTrackID
|
||||
mediaPlayer.currentAudioTrackIndex = newTrackID
|
||||
}
|
||||
|
||||
|
@ -400,7 +399,12 @@ class PlayerViewController: UIViewController, VLCMediaDelegate, VLCMediaPlayerDe
|
|||
timeText.text = timeTextStr
|
||||
|
||||
if(CACurrentMediaTime() - controlsAppearTime > 5) {
|
||||
videoControlsView.isHidden = true;
|
||||
UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseOut, animations: {
|
||||
self.videoControlsView.alpha = 0.0
|
||||
}, completion: { (finished: Bool) in
|
||||
self.videoControlsView.isHidden = true;
|
||||
self.videoControlsView.alpha = 1
|
||||
})
|
||||
controlsAppearTime = 10000000000000000000000;
|
||||
}
|
||||
} else {
|
||||
|
@ -419,10 +423,6 @@ class PlayerViewController: UIViewController, VLCMediaDelegate, VLCMediaPlayerDe
|
|||
var progressBody: String = "";
|
||||
progressBody = "{\"VolumeLevel\":100,\"IsMuted\":false,\"IsPaused\":\(mediaPlayer.state == .paused ? "true" : "false"),\"RepeatMode\":\"RepeatNone\",\"ShuffleMode\":\"Sorted\",\"MaxStreamingBitrate\":120000000,\"PositionTicks\":\(Int(mediaPlayer.position * Float(manifest.RuntimeTicks))),\"PlaybackStartTimeTicks\":\(startTime),\"AudioStreamIndex\":\(selectedAudioTrack),\"BufferedRanges\":[{\"start\":0,\"end\":569735888.888889}],\"PlayMethod\":\"\(playbackItem.videoType == .hls ? "Transcode" : "DirectStream")\",\"PlaySessionId\":\"\(playSessionId)\",\"PlaylistItemId\":\"playlistItem0\",\"MediaSourceId\":\"\(manifest.Id)\",\"CanSeek\":true,\"ItemId\":\"\(manifest.Id)\",\"EventName\":\"\(eventName)\"}";
|
||||
|
||||
print("");
|
||||
print("Sending progress report")
|
||||
print(progressBody)
|
||||
|
||||
let request = RestRequest(method: .post, url: (globalData.server?.baseURI ?? "") + "/Sessions/Playing/Progress")
|
||||
request.headerParameters["X-Emby-Authorization"] = globalData.authHeader
|
||||
request.contentType = "application/json"
|
||||
|
@ -445,10 +445,6 @@ class PlayerViewController: UIViewController, VLCMediaDelegate, VLCMediaPlayerDe
|
|||
|
||||
progressBody = "{\"VolumeLevel\":100,\"IsMuted\":false,\"IsPaused\":true,\"RepeatMode\":\"RepeatNone\",\"ShuffleMode\":\"Sorted\",\"MaxStreamingBitrate\":120000000,\"PositionTicks\":\(Int(mediaPlayer.position * Float(manifest.RuntimeTicks))),\"PlaybackStartTimeTicks\":\(startTime),\"AudioStreamIndex\":\(selectedAudioTrack),\"BufferedRanges\":[{\"start\":0,\"end\":100000}],\"PlayMethod\":\"\(playbackItem.videoType == .hls ? "Transcode" : "DirectStream")\",\"PlaySessionId\":\"\(playSessionId)\",\"PlaylistItemId\":\"playlistItem0\",\"MediaSourceId\":\"\(manifest.Id)\",\"CanSeek\":true,\"ItemId\":\"\(manifest.Id)\",\"NowPlayingQueue\":[{\"Id\":\"\(manifest.Id)\",\"PlaylistItemId\":\"playlistItem0\"}]}";
|
||||
|
||||
print("");
|
||||
print("Sending stop report")
|
||||
print(progressBody)
|
||||
|
||||
let request = RestRequest(method: .post, url: (globalData.server?.baseURI ?? "") + "/Sessions/Playing/Stopped")
|
||||
request.headerParameters["X-Emby-Authorization"] = globalData.authHeader
|
||||
request.contentType = "application/json"
|
||||
|
@ -472,10 +468,6 @@ class PlayerViewController: UIViewController, VLCMediaDelegate, VLCMediaPlayerDe
|
|||
|
||||
progressBody = "{\"VolumeLevel\":100,\"IsMuted\":false,\"IsPaused\":false,\"RepeatMode\":\"RepeatNone\",\"ShuffleMode\":\"Sorted\",\"MaxStreamingBitrate\":120000000,\"PositionTicks\":\(Int(manifest.Progress)),\"PlaybackStartTimeTicks\":\(startTime),\"AudioStreamIndex\":\(selectedAudioTrack),\"BufferedRanges\":[],\"PlayMethod\":\"\(playbackItem.videoType == .hls ? "Transcode" : "DirectStream")\",\"PlaySessionId\":\"\(playSessionId)\",\"PlaylistItemId\":\"playlistItem0\",\"MediaSourceId\":\"\(manifest.Id)\",\"CanSeek\":true,\"ItemId\":\"\(manifest.Id)\",\"NowPlayingQueue\":[{\"Id\":\"\(manifest.Id)\",\"PlaylistItemId\":\"playlistItem0\"}]}";
|
||||
|
||||
print("");
|
||||
print("Sending play report")
|
||||
print(progressBody)
|
||||
|
||||
let request = RestRequest(method: .post, url: (globalData.server?.baseURI ?? "") + "/Sessions/Playing")
|
||||
request.headerParameters["X-Emby-Authorization"] = globalData.authHeader
|
||||
request.contentType = "application/json"
|
||||
|
|
|
@ -6,118 +6,63 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
import Combine
|
||||
|
||||
enum SettingsChangedEventTypes {
|
||||
case subTrackChanged
|
||||
case audioTrackChanged
|
||||
}
|
||||
|
||||
struct settingsChangedEvent {
|
||||
let eventType: SettingsChangedEventTypes
|
||||
let payload: AnyObject
|
||||
}
|
||||
|
||||
protocol VideoPlayerSettingsDelegate: AnyObject {
|
||||
func subtitleTrackChanged(newTrackID: Int32)
|
||||
func audioTrackChanged(newTrackID: Int32)
|
||||
func settingsPopoverDismissed()
|
||||
}
|
||||
|
||||
class SettingsViewDelegate: ObservableObject {
|
||||
|
||||
var subtitlesDidChange = PassthroughSubject<SettingsViewDelegate, Never>()
|
||||
|
||||
var subtitleTrackID: Int32 = 0 {
|
||||
didSet {
|
||||
self.subtitlesDidChange.send(self)
|
||||
}
|
||||
}
|
||||
|
||||
var audioTrackDidChange = PassthroughSubject<SettingsViewDelegate, Never>()
|
||||
|
||||
var audioTrackID: Int32 = 0 {
|
||||
didSet {
|
||||
self.audioTrackDidChange.send(self)
|
||||
}
|
||||
}
|
||||
|
||||
var shouldClose = PassthroughSubject<SettingsViewDelegate, Never>()
|
||||
|
||||
var close: Bool = false {
|
||||
didSet {
|
||||
self.shouldClose.send(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VideoPlayerSettingsView: UIViewController {
|
||||
private var ctntView: VideoPlayerSettings?
|
||||
private var contentViewDelegate: SettingsViewDelegate = SettingsViewDelegate()
|
||||
weak var delegate: VideoPlayerSettingsDelegate?
|
||||
private var subChangePublisher: AnyCancellable?
|
||||
private var audioChangePublisher: AnyCancellable?
|
||||
private var shouldClosePublisher: AnyCancellable?
|
||||
var subtitles: [Subtitle] = []
|
||||
var audioTracks: [AudioTrack] = []
|
||||
var currentSubtitleTrack: Int32?
|
||||
var currentAudioTrack: Int32?
|
||||
private var contentView: UIHostingController<VideoPlayerSettings>!
|
||||
weak var delegate: PlayerViewController?
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
ctntView = VideoPlayerSettings(delegate: self.contentViewDelegate, subtitles: self.subtitles, audioTracks: self.audioTracks, initSub: currentSubtitleTrack ?? -1, initAudio: currentAudioTrack ?? 1)
|
||||
let contentView = UIHostingController(rootView: ctntView)
|
||||
contentView = UIHostingController(rootView: VideoPlayerSettings(delegate: self.delegate ?? PlayerViewController()))
|
||||
self.view.addSubview(contentView.view)
|
||||
contentView.view.translatesAutoresizingMaskIntoConstraints = false
|
||||
contentView.view.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
|
||||
contentView.view.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
|
||||
contentView.view.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
|
||||
contentView.view.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
|
||||
|
||||
self.subChangePublisher = self.contentViewDelegate.subtitlesDidChange.sink { suiDelegate in
|
||||
self.delegate?.subtitleTrackChanged(newTrackID: suiDelegate.subtitleTrackID)
|
||||
}
|
||||
|
||||
self.audioChangePublisher = self.contentViewDelegate.audioTrackDidChange.sink { suiDelegate in
|
||||
self.delegate?.audioTrackChanged(newTrackID: suiDelegate.audioTrackID)
|
||||
}
|
||||
|
||||
self.shouldClosePublisher = self.contentViewDelegate.shouldClose.sink { suiDelegate in
|
||||
if(suiDelegate.close == true) {
|
||||
self.delegate?.settingsPopoverDismissed()
|
||||
self.dismiss(animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func viewWillDisappear(_ animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
self.delegate?.settingsPopoverDismissed()
|
||||
}
|
||||
}
|
||||
|
||||
struct VideoPlayerSettings: View {
|
||||
@ObservedObject var delegate: SettingsViewDelegate
|
||||
@State private var subtitles: [Subtitle]
|
||||
@State private var audioTracks: [AudioTrack]
|
||||
@State private var subtitleSelection: Int32
|
||||
@State private var audioTrackSelection: Int32
|
||||
@State var delegate: PlayerViewController
|
||||
@State var captionTrack: Int32 = -99;
|
||||
@State var audioTrack: Int32 = -99;
|
||||
|
||||
init(delegate: SettingsViewDelegate, subtitles: [Subtitle], audioTracks: [AudioTrack], initSub: Int32, initAudio: Int32) {
|
||||
init(delegate: PlayerViewController) {
|
||||
self.delegate = delegate
|
||||
self.subtitles = subtitles
|
||||
self.audioTracks = audioTracks
|
||||
|
||||
subtitleSelection = initSub
|
||||
audioTrackSelection = initAudio
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
NavigationView() {
|
||||
Form() {
|
||||
Picker("Closed Captions", selection: $captionTrack) {
|
||||
ForEach(delegate.subtitleTrackArray, id: \.id) { caption in
|
||||
Text(caption.name).tag(caption.id)
|
||||
}
|
||||
}
|
||||
.onChange(of: captionTrack) { track in
|
||||
self.delegate.subtitleTrackChanged(newTrackID: track)
|
||||
}
|
||||
Picker("Audio Track", selection: $audioTrack) {
|
||||
ForEach(delegate.audioTrackArray, id: \.id) { caption in
|
||||
Text(caption.name).tag(caption.id).lineLimit(1)
|
||||
}
|
||||
}.onChange(of: audioTrack) { track in
|
||||
self.delegate.audioTrackChanged(newTrackID: track)
|
||||
}
|
||||
}.navigationBarTitleDisplayMode(.inline)
|
||||
.navigationTitle("Audio & Captions")
|
||||
.toolbar {
|
||||
ToolbarItemGroup(placement: .navigationBarLeading) {
|
||||
if(UIDevice.current.userInterfaceIdiom == .phone) {
|
||||
Button {
|
||||
delegate.close = true
|
||||
self.delegate.settingsPopoverDismissed()
|
||||
} label: {
|
||||
HStack() {
|
||||
Image(systemName: "chevron.left")
|
||||
|
@ -125,20 +70,12 @@ struct VideoPlayerSettings: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
Picker("Closed Captions", selection: $subtitleSelection) {
|
||||
ForEach(subtitles, id: \.id) { caption in
|
||||
Text(caption.name).tag(caption.id)
|
||||
}
|
||||
}.onChange(of: subtitleSelection) { id in
|
||||
delegate.subtitleTrackID = id
|
||||
}
|
||||
Picker("Audio Track", selection: $audioTrackSelection) {
|
||||
ForEach(audioTracks, id: \.id) { caption in
|
||||
Text(caption.name).tag(caption.id).lineLimit(1)
|
||||
}
|
||||
}.onChange(of: audioTrackSelection) { id in
|
||||
delegate.audioTrackID = id
|
||||
}
|
||||
}
|
||||
}.offset(y: 14)
|
||||
.onAppear(perform: {
|
||||
_captionTrack.wrappedValue = self.delegate.selectedCaptionTrack
|
||||
_audioTrack.wrappedValue = self.delegate.selectedAudioTrack
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,14 +31,6 @@ platform :ios do
|
|||
project_slug: 'jellyfin-swift-ios',
|
||||
dsym_path: "JellyfinPlayer.app.dSYM.zip"
|
||||
)
|
||||
set_github_release(
|
||||
repository_name: "jellyfin/JellyfinPlayer",
|
||||
name: "Release #{identifier_v}@#{identifier_s}",
|
||||
tag_name: "v#{identifier_s}",
|
||||
description: (File.read("Release Notes.rtf") rescue "No changelog provided"),
|
||||
commitish: "main",
|
||||
upload_assets: ["JellyfinPlayer.ipa"]
|
||||
)
|
||||
upload_to_testflight
|
||||
dynatrace_process_symbols(
|
||||
appId: "8c1f6941-ec78-480c-b589-b41aca29a52e",
|
||||
|
|
Loading…
Reference in New Issue