diff --git a/JellyfinPlayer.xcodeproj/project.pbxproj b/JellyfinPlayer.xcodeproj/project.pbxproj index 6bdb5412..de2c151c 100644 --- a/JellyfinPlayer.xcodeproj/project.pbxproj +++ b/JellyfinPlayer.xcodeproj/project.pbxproj @@ -462,7 +462,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 14; + CURRENT_PROJECT_VERSION = 15; DEVELOPMENT_ASSET_PATHS = "\"JellyfinPlayer/Preview Content\""; DEVELOPMENT_TEAM = 9R8RREG67J; ENABLE_BITCODE = NO; @@ -491,7 +491,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 14; + CURRENT_PROJECT_VERSION = 15; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_ASSET_PATHS = "\"JellyfinPlayer/Preview Content\""; DEVELOPMENT_TEAM = 9R8RREG67J; diff --git a/JellyfinPlayer/ContinueWatchingView.swift b/JellyfinPlayer/ContinueWatchingView.swift index 07320130..d9b5af60 100644 --- a/JellyfinPlayer/ContinueWatchingView.swift +++ b/JellyfinPlayer/ContinueWatchingView.swift @@ -107,74 +107,78 @@ struct ContinueWatchingView: View { var body: some View { ScrollView(.horizontal, showsIndicators: false) { - LazyHStack() { - Spacer().frame(width:16) - ForEach(resumeItems, id: \.Id) { item in - NavigationLink(destination: ItemView(item: item)) { - VStack(alignment: .leading) { - Spacer().frame(height: 10) - if(item.Type == "Episode") { - WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?maxWidth=550&quality=80&tag=\(item.Image)")!) - .resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size - .placeholder { - Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 6, height: 6))!) - .resizable() - .frame(width: 320, height: 180) - .cornerRadius(10) - } - .frame(width: 320, height: 180) - .cornerRadius(10) - .overlay( - ZStack { - Text("S\(String(item.ParentIndexNumber ?? 0)):E\(String(item.IndexNumber ?? 0)) - \(item.Name)") - .font(.caption) - .padding(6) - .foregroundColor(.white) - }.background(Color.black) - .opacity(0.8) - .cornerRadius(10.0) - .padding(6), alignment: .topTrailing - ) - .overlay( - Rectangle() - .fill(Color(red: 172/255, green: 92/255, blue: 195/255)) - .mask(CustomShape(radius: 10)) - .frame(width: CGFloat((item.ItemProgress/100)*320), height: 7) + if(_resumeItems.wrappedValue.count > 0) { + LazyHStack() { + Spacer().frame(width:16) + ForEach(resumeItems, id: \.Id) { item in + NavigationLink(destination: ItemView(item: item)) { + VStack(alignment: .leading) { + Spacer().frame(height: 10) + if(item.Type == "Episode") { + WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?maxWidth=550&quality=80&tag=\(item.Image)")!) + .resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size + .placeholder { + Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 6, height: 6))!) + .resizable() + .frame(width: 320, height: 180) + .cornerRadius(10) + } + .frame(width: 320, height: 180) + .cornerRadius(10) + .overlay( + ZStack { + Text("S\(String(item.ParentIndexNumber ?? 0)):E\(String(item.IndexNumber ?? 0)) - \(item.Name)") + .font(.caption) + .padding(6) + .foregroundColor(.white) + }.background(Color.black) + .opacity(0.8) + .cornerRadius(10.0) + .padding(6), alignment: .topTrailing + ) + .overlay( + Rectangle() + .fill(Color(red: 172/255, green: 92/255, blue: 195/255)) + .mask(CustomShape(radius: 10)) + .frame(width: CGFloat((item.ItemProgress/100)*320), height: 7) + .padding(0), alignment: .bottomLeading + ) + .shadow(radius: 5) + } else { + WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?maxWidth=550&quality=80&tag=\(item.Image)")!) + .resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size + .placeholder { + Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 6, height: 6))!) + .resizable() + .frame(width: 320, height: 180) + .cornerRadius(10) + } + .frame(width: 320, height: 180) + .cornerRadius(10) + .overlay( + Rectangle() + .fill(Color(red: 172/255, green: 92/255, blue: 195/255)) + .mask(CustomShape(radius: 10)) + .frame(width: CGFloat((item.ItemProgress/100)*320), height: 7) .padding(0), alignment: .bottomLeading - ) - .shadow(radius: 5) - } else { - WebImage(url: URL(string: "\(globalData.server?.baseURI ?? "")/Items/\(item.Id)/Images/\(item.ImageType)?maxWidth=550&quality=80&tag=\(item.Image)")!) - .resizable() // Resizable like SwiftUI.Image, you must use this modifier or the view will use the image bitmap size - .placeholder { - Image(uiImage: UIImage(blurHash: (item.BlurHash == "" ? "W$H.4}D%bdo#a#xbtpxVW?W?jXWsXVt7Rjf5axWqxbWXnhada{s-" : item.BlurHash), size: CGSize(width: 6, height: 6))!) - .resizable() - .frame(width: 320, height: 180) - .cornerRadius(10) - } - .frame(width: 320, height: 180) - .cornerRadius(10) - .overlay( - Rectangle() - .fill(Color(red: 172/255, green: 92/255, blue: 195/255)) - .mask(CustomShape(radius: 10)) - .frame(width: CGFloat((item.ItemProgress/100)*320), height: 7) - .padding(0), alignment: .bottomLeading - ) - .shadow(radius: 5) - } - Text("\(item.Type == "Episode" ? item.SeriesName ?? "" : item.Name)") - .font(.callout) - .fontWeight(.semibold) - .foregroundColor(.primary) - .lineLimit(1) - .frame(width: 320, alignment: .leading) - Spacer().frame(height: 5) - }.padding(.trailing, 5) + ) + .shadow(radius: 5) + } + Text("\(item.Type == "Episode" ? item.SeriesName ?? "" : item.Name)") + .font(.callout) + .fontWeight(.semibold) + .foregroundColor(.primary) + .lineLimit(1) + .frame(width: 320, alignment: .leading) + Spacer().frame(height: 5) + }.padding(.trailing, 5) + } } - } - Spacer().frame(width:14) - }.frame(height: 215) + Spacer().frame(width:14) + }.frame(height: 215) + } else { + EmptyView() + } }.onAppear(perform: onAppear) .frame(height: 215) .padding(.bottom, 10) diff --git a/JellyfinPlayer/EpisodeItemView.swift b/JellyfinPlayer/EpisodeItemView.swift index c63b7555..20526aa6 100644 --- a/JellyfinPlayer/EpisodeItemView.swift +++ b/JellyfinPlayer/EpisodeItemView.swift @@ -18,7 +18,13 @@ struct EpisodeItemView: View { var item: ResumeItem; @EnvironmentObject var orientationInfo: OrientationInfo var fullItem: DetailItem; - @State private var playing: Bool = false; + @State private var playing: Bool = false { + didSet { + if(_playing.wrappedValue == false) { + unlockOrientations() + } + } + }; @State private var vc: PreferenceUIHostingController? = nil; @State private var progressString: String = ""; @State private var viewDidLoad: Bool = false; diff --git a/JellyfinPlayer/Info.plist b/JellyfinPlayer/Info.plist index 39262099..de41309f 100644 --- a/JellyfinPlayer/Info.plist +++ b/JellyfinPlayer/Info.plist @@ -19,7 +19,7 @@ CFBundleShortVersionString $(MARKETING_VERSION) CFBundleVersion - 14 + 15 DTXApplicationID 8c1f6941-ec78-480c-b589-b41aca29a52e DTXBeaconURL diff --git a/JellyfinPlayer/MovieItemView.swift b/JellyfinPlayer/MovieItemView.swift index ae5d948e..15fbcd35 100644 --- a/JellyfinPlayer/MovieItemView.swift +++ b/JellyfinPlayer/MovieItemView.swift @@ -66,7 +66,13 @@ struct MovieItemView: View { @State private var isLoading: Bool = true; var item: ResumeItem; var fullItem: DetailItem; - @State private var playing: Bool = false; + @State private var playing: Bool = false { + didSet { + if(_playing.wrappedValue == false) { + unlockOrientations() + } + } + }; @State private var vc: PreferenceUIHostingController? = nil; @State private var progressString: String = ""; @State private var viewDidLoad: Bool = false; @@ -255,7 +261,7 @@ struct MovieItemView: View { var body: some View { if(playing) { - VideoPlayerView(item: fullItem, playing: $playing).onAppear(perform: lockOrientations) + VideoPlayerView(item: fullItem, playing: $playing).onAppear(perform: lockOrientations).onDisappear(perform: unlockOrientations) } else { LoadingView(isShowing: $isLoading) { VStack(alignment:.leading) { diff --git a/JellyfinPlayer/VideoPlayerView.swift b/JellyfinPlayer/VideoPlayerView.swift index 60c76b9f..dfee0ca7 100644 --- a/JellyfinPlayer/VideoPlayerView.swift +++ b/JellyfinPlayer/VideoPlayerView.swift @@ -274,7 +274,9 @@ struct VideoPlayerView: View { } if(_selectedAudioTrack.wrappedValue == -1) { - _selectedAudioTrack.wrappedValue = _audioTracks.wrappedValue[0].id; + if(_audioTracks.wrappedValue.count > 0) { + _selectedAudioTrack.wrappedValue = _audioTracks.wrappedValue[0].id; + } } let streamUrl = streamURL.absoluteString; @@ -319,6 +321,7 @@ struct VideoPlayerView: View { _selectedAudioTrack.wrappedValue = _audioTracks.wrappedValue[0].id; } + sendPlayReport() pbitem = item; pbitem.subtitles = subtitles; _isPlaying.wrappedValue = true;