diff --git a/JellyfinPlayer.xcodeproj/project.pbxproj b/JellyfinPlayer.xcodeproj/project.pbxproj
index 8382552e..92612ce6 100644
--- a/JellyfinPlayer.xcodeproj/project.pbxproj
+++ b/JellyfinPlayer.xcodeproj/project.pbxproj
@@ -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;
diff --git a/JellyfinPlayer/ConnectToServerView.swift b/JellyfinPlayer/ConnectToServerView.swift
index 692bb5be..62a804a7 100644
--- a/JellyfinPlayer/ConnectToServerView.swift
+++ b/JellyfinPlayer/ConnectToServerView.swift
@@ -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)
diff --git a/JellyfinPlayer/ContentView.swift b/JellyfinPlayer/ContentView.swift
index 17ac0507..c36783f0 100644
--- a/JellyfinPlayer/ContentView.swift
+++ b/JellyfinPlayer/ContentView.swift
@@ -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 {
diff --git a/JellyfinPlayer/ContinueWatchingView.swift b/JellyfinPlayer/ContinueWatchingView.swift
index 95f695bc..858be88a 100644
--- a/JellyfinPlayer/ContinueWatchingView.swift
+++ b/JellyfinPlayer/ContinueWatchingView.swift
@@ -172,6 +172,7 @@ struct ContinueWatchingView: View {
}.padding(.trailing, 5)
}
}
+ Spacer().frame(width: 2)
}.frame(height: 215)
} else {
EmptyView()
diff --git a/JellyfinPlayer/Info.plist b/JellyfinPlayer/Info.plist
index 161fabef..0f27d5d9 100644
--- a/JellyfinPlayer/Info.plist
+++ b/JellyfinPlayer/Info.plist
@@ -19,7 +19,7 @@
CFBundleShortVersionString
$(MARKETING_VERSION)
CFBundleVersion
- 26
+ 29
ITSAppUsesNonExemptEncryption
LSRequiresIPhoneOS
diff --git a/JellyfinPlayer/ItemView.swift b/JellyfinPlayer/ItemView.swift
index b94254be..b4a8e26a 100644
--- a/JellyfinPlayer/ItemView.swift
+++ b/JellyfinPlayer/ItemView.swift
@@ -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)
diff --git a/JellyfinPlayer/LoadingView.swift b/JellyfinPlayer/LoadingView.swift
index 738ea724..820eef35 100644
--- a/JellyfinPlayer/LoadingView.swift
+++ b/JellyfinPlayer/LoadingView.swift
@@ -2,10 +2,10 @@ import SwiftUI
struct LoadingView: View where Content: View {
@Environment(\.colorScheme) var colorScheme
- @Binding var isShowing: Bool // should the modal be visible?
+ @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) {
@@ -38,3 +38,42 @@ struct LoadingView: View where Content: View {
}
}
}
+
+struct LoadingViewNoBlur: 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)
+ }
+ }
+ }
+ }
+}
+
diff --git a/JellyfinPlayer/Views/VideoPlayer.storyboard b/JellyfinPlayer/Views/VideoPlayer.storyboard
index d4b80988..fd4b4ff9 100644
--- a/JellyfinPlayer/Views/VideoPlayer.storyboard
+++ b/JellyfinPlayer/Views/VideoPlayer.storyboard
@@ -44,7 +44,7 @@
-
+
@@ -125,7 +125,7 @@
-
+
diff --git a/JellyfinPlayer/Views/VideoPlayer.swift b/JellyfinPlayer/Views/VideoPlayer.swift
index fb498b4a..26248a40 100644
--- a/JellyfinPlayer/Views/VideoPlayer.swift
+++ b/JellyfinPlayer/Views/VideoPlayer.swift
@@ -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,8 +190,7 @@ 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
- }
+ 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"
diff --git a/JellyfinPlayer/Views/VideoPlayerSettingsView.swift b/JellyfinPlayer/Views/VideoPlayerSettingsView.swift
index ff40adbd..7b744ef0 100644
--- a/JellyfinPlayer/Views/VideoPlayerSettingsView.swift
+++ b/JellyfinPlayer/Views/VideoPlayerSettingsView.swift
@@ -6,139 +6,76 @@
//
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()
-
- var subtitleTrackID: Int32 = 0 {
- didSet {
- self.subtitlesDidChange.send(self)
- }
- }
-
- var audioTrackDidChange = PassthroughSubject()
-
- var audioTrackID: Int32 = 0 {
- didSet {
- self.audioTrackDidChange.send(self)
- }
- }
-
- var shouldClose = PassthroughSubject()
-
- 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!
+ 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 {
- Form() {
- if(UIDevice.current.userInterfaceIdiom == .phone) {
- Button {
- delegate.close = true
- } label: {
- HStack() {
- Image(systemName: "chevron.left")
- Text("Back").font(.callout)
+ 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 {
+ self.delegate.settingsPopoverDismissed()
+ } label: {
+ HStack() {
+ Image(systemName: "chevron.left")
+ Text("Back").font(.callout)
+ }
+ }
}
}
}
- 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
+ })
}
}
diff --git a/fastlane/Fastfile b/fastlane/Fastfile
index ac4ac7ca..9dcf555b 100644
--- a/fastlane/Fastfile
+++ b/fastlane/Fastfile
@@ -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",