diff --git a/JellyfinPlayer/ContentView.swift b/JellyfinPlayer/ContentView.swift
index c793ab18..f77b2ade 100644
--- a/JellyfinPlayer/ContentView.swift
+++ b/JellyfinPlayer/ContentView.swift
@@ -188,6 +188,7 @@ struct ContentView: View {
@State private var librariesShowRecentlyAdded: [String] = [];
@State private var libraryPrefillID: String = "";
@State private var showSettingsPopover: Bool = false;
+ @State private var viewDidLoad: Bool = false;
@Environment(\.verticalSizeClass) var verticalSizeClass: UserInterfaceSizeClass?
@Environment(\.horizontalSizeClass) var horizontalSizeClass: UserInterfaceSizeClass?
@@ -198,6 +199,10 @@ struct ContentView: View {
}
func startup() {
+ if(_viewDidLoad.wrappedValue) {
+ return
+ }
+ _viewDidLoad.wrappedValue = true;
SentrySDK.start { options in
options.dsn = "https://75ac77d6af4d406eb989f3d8ef0f119f@o513670.ingest.sentry.io/5778242"
options.debug = false // Enabled debug when first installing is always helpful
@@ -274,6 +279,18 @@ struct ContentView: View {
_librariesShowRecentlyAdded.wrappedValue = _libraries.wrappedValue.filter { element in
return !array2.contains(element)
}
+
+ _libraries.wrappedValue.forEach { library in
+ if(_library_names.wrappedValue[library] == nil) {
+ _libraries.wrappedValue.removeAll { ele in
+ if(library == ele) {
+ return true
+ } else {
+ return false
+ }
+ }
+ }
+ }
} catch {
}
@@ -301,84 +318,95 @@ struct ContentView: View {
}
var body: some View {
- if(!jsi.did) {
- LoadingView(isShowing: $isLoading) {
- TabView(selection: $tabSelection) {
- NavigationView() {
- VStack {
- NavigationLink(destination: ConnectToServerView(isActive: $needsToSelectServer), isActive: $needsToSelectServer) {
- EmptyView()
- }.isDetailLink(false)
- NavigationLink(destination: ConnectToServerView(skip_server: true, skip_server_prefill: globalData.server, reauth_deviceId: globalData.user?.device_uuid ?? "", isActive: $isSignInErrored), isActive: $isSignInErrored) {
- EmptyView()
- }.isDetailLink(false)
- if(!needsToSelectServer && !isSignInErrored) {
- VStack(alignment: .leading) {
- ScrollView() {
- Spacer().frame(height: self.isPortrait ? 0 : 15)
- ContinueWatchingView()
- NextUpView().padding(EdgeInsets(top: 4, leading: 0, bottom: 0, trailing: 0))
- ForEach(librariesShowRecentlyAdded, id: \.self) { library_id in
- VStack(alignment: .leading) {
- HStack() {
- Text("Latest \(library_names[library_id] ?? "")").font(.title2).fontWeight(.bold).padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 16))
- Spacer()
- NavigationLink(destination: LibraryView(prefill: library_id, names: library_names, libraries: libraries, filter: "&SortBy=DateCreated&SortOrder=Descending")) {
- Text("See All").font(.subheadline).fontWeight(.bold)
- }
- }.padding(EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16))
- LatestMediaView(library: library_id)
- }.padding(EdgeInsets(top: 4, leading: 0, bottom: 0, trailing: 0))
+ if(needsToSelectServer) {
+ NavigationView() {
+ ConnectToServerView(isActive: $needsToSelectServer)
+ }
+ } else if(isSignInErrored) {
+ NavigationView() {
+ ConnectToServerView(skip_server: true, skip_server_prefill: globalData.server, reauth_deviceId: globalData.user?.device_uuid ?? "", isActive: $isSignInErrored)
+ }
+ } else {
+ if(!jsi.did) {
+ LoadingView(isShowing: $isLoading) {
+ TabView(selection: $tabSelection) {
+ NavigationView() {
+ VStack {
+ NavigationLink(destination: ConnectToServerView(isActive: $needsToSelectServer), isActive: $needsToSelectServer) {
+ EmptyView()
+ }.isDetailLink(false)
+ NavigationLink(destination: ConnectToServerView(skip_server: true, skip_server_prefill: globalData.server, reauth_deviceId: globalData.user?.device_uuid ?? "", isActive: $isSignInErrored), isActive: $isSignInErrored) {
+ EmptyView()
+ }.isDetailLink(false)
+ if(!needsToSelectServer && !isSignInErrored) {
+ VStack(alignment: .leading) {
+ ScrollView() {
+ Spacer().frame(height: self.isPortrait ? 0 : 15)
+ ContinueWatchingView()
+ NextUpView().padding(EdgeInsets(top: 4, leading: 0, bottom: 0, trailing: 0))
+ ForEach(librariesShowRecentlyAdded, id: \.self) { library_id in
+ VStack(alignment: .leading) {
+ HStack() {
+ Text("Latest \(library_names[library_id] ?? "")").font(.title2).fontWeight(.bold).padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 16))
+ Spacer()
+ NavigationLink(destination: LibraryView(prefill: library_id, names: library_names, libraries: libraries, filter: "&SortBy=DateCreated&SortOrder=Descending")) {
+ Text("See All").font(.subheadline).fontWeight(.bold)
+ }
+ }.padding(EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16))
+ LatestMediaView(library: library_id)
+ }.padding(EdgeInsets(top: 4, leading: 0, bottom: 0, trailing: 0))
+ }
+ Spacer().frame(height: 7)
}
- Spacer().frame(height: 7)
}
}
}
- }
- .navigationTitle("Home")
- .toolbar {
- ToolbarItemGroup(placement: .navigationBarTrailing) {
- Button {
- showSettingsPopover = true;
- } label: {
- Image(systemName: "gear")
+ .navigationTitle("Home")
+ .toolbar {
+ ToolbarItemGroup(placement: .navigationBarTrailing) {
+ Button {
+ showSettingsPopover = true;
+ } label: {
+ Image(systemName: "gear")
+ }
}
- }
- }.popover( isPresented: self.$showSettingsPopover, arrowEdge: .bottom) { SettingsView(close: $showSettingsPopover).environmentObject(self.globalData) }
- }
- .tabItem({
- Text("Home")
- Image(systemName: "house")
- })
- .tag("Home")
- NavigationView() {
- LibraryView(prefill: "", names: library_names, libraries: libraries)
- .navigationTitle("Library")
- }
- .tabItem({
- Text("All Media")
- Image(systemName: "folder")
- })
- .tag("All Media")
-
- }.edgesIgnoringSafeArea(isPortrait ? [] : [.leading,.trailing])
- }.environmentObject(globalData)
- .edgesIgnoringSafeArea(isPortrait ? [] : [.leading,.trailing])
- .onAppear(perform: startup)
- .navigationViewStyle(StackNavigationViewStyle())
- .alert(isPresented: $isNetworkErrored) {
- Alert(title: Text("Network Error"), message: Text("Couldn't connect to Jellyfin"), dismissButton: .default(Text("Ok")))
- }.introspectTabBarController { (UITabBarController) in
- UITabBarController.tabBar.isHidden = false
- }
- } else {
- Text("Signing in...")
- .onAppear(perform: {
- DispatchQueue.main.async { [self] in
- usleep(500000);
- self.jsi.did = false;
+ }.popover( isPresented: self.$showSettingsPopover, arrowEdge: .bottom) { SettingsView(close: $showSettingsPopover).environmentObject(self.globalData) }
+ }
+ .tabItem({
+ Text("Home")
+ Image(systemName: "house")
+ })
+ .tag("Home")
+ NavigationView() {
+ LibraryView(prefill: "", names: library_names, libraries: libraries)
+ .navigationTitle("Library")
+ }
+ .tabItem({
+ Text("All Media")
+ Image(systemName: "folder")
+ })
+ .tag("All Media")
+
+ }.edgesIgnoringSafeArea(isPortrait ? [] : [.leading,.trailing])
+ }.environmentObject(globalData)
+ .edgesIgnoringSafeArea(isPortrait ? [] : [.leading,.trailing])
+ .onAppear(perform: startup)
+ .navigationViewStyle(StackNavigationViewStyle())
+ .alert(isPresented: $isNetworkErrored) {
+ Alert(title: Text("Network Error"), message: Text("Couldn't connect to Jellyfin"), dismissButton: .default(Text("Ok")))
+ }.introspectTabBarController { (UITabBarController) in
+ UITabBarController.tabBar.isHidden = false
}
- })
+ } else {
+ Text("Signing in...")
+ .onAppear(perform: {
+ DispatchQueue.main.async { [self] in
+ _viewDidLoad.wrappedValue = false
+ usleep(500000);
+ self.jsi.did = false;
+ }
+ })
+ }
}
}
}
diff --git a/JellyfinPlayer/ContinueWatchingView.swift b/JellyfinPlayer/ContinueWatchingView.swift
index cdecc48b..9dac7dcf 100644
--- a/JellyfinPlayer/ContinueWatchingView.swift
+++ b/JellyfinPlayer/ContinueWatchingView.swift
@@ -10,6 +10,30 @@ import SwiftyRequest
import SwiftyJSON
import SDWebImageSwiftUI
+struct CustomShape: Shape {
+ let radius: CGFloat
+
+ func path(in rect: CGRect) -> Path {
+ var path = Path()
+
+ let tl = CGPoint(x: rect.minX, y: rect.minY)
+ let tr = CGPoint(x: rect.maxX, y: rect.minY)
+ let br = CGPoint(x: rect.maxX, y: rect.maxY)
+ let bls = CGPoint(x: rect.minX + radius, y: rect.maxY)
+ let blc = CGPoint(x: rect.minX + radius, y: rect.maxY - radius)
+
+ path.move(to: tl)
+ path.addLine(to: tr)
+ path.addLine(to: br)
+ path.addLine(to: bls)
+ path.addRelativeArc(center: blc, radius: radius,
+ startAngle: Angle.degrees(90), delta: Angle.degrees(90))
+
+ return path
+ }
+}
+
+
struct ContinueWatchingView: View {
@Environment(\.managedObjectContext) private var viewContext
@EnvironmentObject var globalData: GlobalData
@@ -44,12 +68,18 @@ struct ContinueWatchingView: View {
//portrait; use backdrop instead
itemObj.Image = item["BackdropImageTags"][0].string ?? ""
itemObj.ImageType = "Backdrop"
+
+ if(itemObj.Image == "") {
+ itemObj.Image = item["ParentBackdropImageTags"][0].string ?? ""
+ }
+
itemObj.BlurHash = item["ImageBlurHashes"]["Backdrop"][itemObj.Image].string ?? ""
} else {
itemObj.Image = item["ImageTags"]["Primary"].string ?? ""
itemObj.ImageType = "Primary"
itemObj.BlurHash = item["ImageBlurHashes"]["Primary"][itemObj.Image].string ?? ""
}
+
itemObj.Name = item["Name"].string ?? ""
itemObj.Type = item["Type"].string ?? ""
itemObj.IndexNumber = item["IndexNumber"].int ?? nil
@@ -108,10 +138,11 @@ struct ContinueWatchingView: View {
.padding(6), alignment: .topTrailing
)
.overlay(
- RoundedRectangle(cornerRadius: 10, style: .circular)
- .fill(Color(red: 172/255, green: 92/255, blue: 195/255).opacity(0.4))
- .frame(width: CGFloat((item.ItemProgress/100)*320), height: 180)
- .padding(0), alignment: .bottomLeading
+ 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 {
@@ -126,9 +157,10 @@ struct ContinueWatchingView: View {
.frame(width: 320, height: 180)
.cornerRadius(10)
.overlay(
- RoundedRectangle(cornerRadius: 10, style: .circular)
- .fill(Color(red: 172/255, green: 92/255, blue: 195/255).opacity(0.4))
- .frame(width: CGFloat((item.ItemProgress/100)*320), height: 180)
+ 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)
@@ -137,6 +169,8 @@ struct ContinueWatchingView: View {
.font(.callout)
.fontWeight(.semibold)
.foregroundColor(.primary)
+ .lineLimit(1)
+ .frame(width: 320, alignment: .leading)
Spacer().frame(height: 5)
}.padding(.trailing, 5)
}
diff --git a/JellyfinPlayer/EpisodeItemView.swift b/JellyfinPlayer/EpisodeItemView.swift
index 9edcd7ac..ba501beb 100644
--- a/JellyfinPlayer/EpisodeItemView.swift
+++ b/JellyfinPlayer/EpisodeItemView.swift
@@ -265,7 +265,7 @@ struct EpisodeItemView: View {
.stroke(Color.secondary, lineWidth: 1)
)
}
- if(fullItem.CommunityRating != "") {
+ if(fullItem.CommunityRating != "0") {
HStack() {
Image(systemName: "star").foregroundColor(.secondary)
Text(fullItem.CommunityRating).font(.subheadline)
@@ -275,9 +275,8 @@ struct EpisodeItemView: View {
.offset(x: -7, y: 0.7)
}
}
- }
-
- }.offset(x: 0, y: -46).padding(.trailing, 16)
+ }.frame(maxWidth: .infinity, alignment: .leading)
+ }.frame(maxWidth: .infinity, alignment: .leading).offset(x: 0, y: -46).padding(.trailing, 16)
}.offset(x: 16, y: 40)
, alignment: .bottomLeading)
VStack(alignment: .leading) {
@@ -466,7 +465,7 @@ struct EpisodeItemView: View {
.stroke(Color.secondary, lineWidth: 1)
)
}
- if(fullItem.CommunityRating != "") {
+ if(fullItem.CommunityRating != "0") {
HStack() {
Image(systemName: "star").foregroundColor(.secondary)
Text(fullItem.CommunityRating).font(.subheadline)
diff --git a/JellyfinPlayer/Info.plist b/JellyfinPlayer/Info.plist
index b84f7c33..cc9ab1e3 100644
--- a/JellyfinPlayer/Info.plist
+++ b/JellyfinPlayer/Info.plist
@@ -20,6 +20,14 @@
$(MARKETING_VERSION)
CFBundleVersion
7
+ DTXApplicationID
+ 8c1f6941-ec78-480c-b589-b41aca29a52e
+ DTXBeaconURL
+ https://bf64941kgh.bf.dynatrace.com/mbeacon
+ DTXStartupLoadBalancing
+
+ DTXUserOptIn
+
ITSAppUsesNonExemptEncryption
LSRequiresIPhoneOS
@@ -42,6 +50,8 @@
armv7
+ UIRequiresFullScreen
+
UIStatusBarHidden
UISupportedInterfaceOrientations
@@ -53,17 +63,8 @@
UISupportedInterfaceOrientations~ipad
UIInterfaceOrientationPortrait
- UIInterfaceOrientationPortraitUpsideDown
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
- DTXApplicationID
- 8c1f6941-ec78-480c-b589-b41aca29a52e
- DTXBeaconURL
- https://bf64941kgh.bf.dynatrace.com/mbeacon
- DTXUserOptIn
-
- DTXStartupLoadBalancing
-
diff --git a/JellyfinPlayer/LatestMediaView.swift b/JellyfinPlayer/LatestMediaView.swift
index 394aabe5..13584ed8 100644
--- a/JellyfinPlayer/LatestMediaView.swift
+++ b/JellyfinPlayer/LatestMediaView.swift
@@ -103,10 +103,17 @@ struct LatestMediaView: View {
.cornerRadius(10)
.overlay(
ZStack {
- Text("\(String(item.ItemBadge ?? 0))")
- .font(.caption)
- .padding(3)
- .foregroundColor(.white)
+ if(item.ItemBadge == 0) {
+ Image(systemName: "checkmark")
+ .font(.caption)
+ .padding(3)
+ .foregroundColor(.white)
+ } else {
+ Text("\(String(item.ItemBadge ?? 0))")
+ .font(.caption)
+ .padding(3)
+ .foregroundColor(.white)
+ }
}.background(Color.black)
.opacity(0.8)
.cornerRadius(10.0)
diff --git a/JellyfinPlayer/LibraryFilterView.swift b/JellyfinPlayer/LibraryFilterView.swift
index b7ae8a15..a16c4a5b 100644
--- a/JellyfinPlayer/LibraryFilterView.swift
+++ b/JellyfinPlayer/LibraryFilterView.swift
@@ -34,6 +34,10 @@ struct LibraryFilterView: View {
@Binding var close: Bool;
func onAppear() {
+ if(_viewDidLoad.wrappedValue == true) {
+ return
+ }
+ _viewDidLoad.wrappedValue = true;
if(_output.wrappedValue.contains("&Filters=IsUnplayed")) {
_onlyUnplayed.wrappedValue = true;
}
@@ -55,10 +59,6 @@ struct LibraryFilterView: View {
_sortOrder.wrappedValue = sortOrder;
recalculateFilters()
- if(_viewDidLoad.wrappedValue == true) {
- return
- }
- _viewDidLoad.wrappedValue = true;
_allGenres.wrappedValue = []
let url = "/Items/Filters?UserId=\(globalData.user?.user_id ?? "")&ParentId=\(library)"
let request = RestRequest(method: .get, url: (globalData.server?.baseURI ?? "") + url)
@@ -98,6 +98,7 @@ struct LibraryFilterView: View {
}
func recalculateFilters() {
+ print("recalcFilters running");
output = "";
if(_onlyUnplayed.wrappedValue) {
output = "&Filters=IsUnPlayed";
diff --git a/JellyfinPlayer/LibrarySearchView.swift b/JellyfinPlayer/LibrarySearchView.swift
index 2dd62278..8287500b 100644
--- a/JellyfinPlayer/LibrarySearchView.swift
+++ b/JellyfinPlayer/LibrarySearchView.swift
@@ -32,7 +32,7 @@ struct LibrarySearchView: View {
func onAppear() {
_isLoading.wrappedValue = true;
_items.wrappedValue = [];
- let request = RestRequest(method: .get, url: (globalData.server?.baseURI ?? "") + _url.wrappedValue + "&searchTerm=" + searchQuery.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!)
+ let request = RestRequest(method: .get, url: (globalData.server?.baseURI ?? "") + _url.wrappedValue + "&searchTerm=" + searchQuery.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)! + (_url.wrappedValue.contains("SortBy") ? "" : "&SortBy=Name&SortOrder=Descending"))
request.headerParameters["X-Emby-Authorization"] = globalData.authHeader
request.contentType = "application/json"
request.acceptType = "application/json"
@@ -151,10 +151,17 @@ struct LibrarySearchView: View {
.frame(width:100, height: 150)
.cornerRadius(10).overlay(
ZStack {
- Text("\(String(item.ItemBadge ?? 0))")
- .font(.caption)
- .padding(3)
- .foregroundColor(.white)
+ if(item.ItemBadge == 0) {
+ Image(systemName: "checkmark")
+ .font(.caption)
+ .padding(3)
+ .foregroundColor(.white)
+ } else {
+ Text("\(String(item.ItemBadge ?? 0))")
+ .font(.caption)
+ .padding(3)
+ .foregroundColor(.white)
+ }
}.background(Color.black)
.opacity(0.8)
.cornerRadius(10.0)
diff --git a/JellyfinPlayer/LibraryView.swift b/JellyfinPlayer/LibraryView.swift
index de9d8ced..cb98276a 100644
--- a/JellyfinPlayer/LibraryView.swift
+++ b/JellyfinPlayer/LibraryView.swift
@@ -71,7 +71,7 @@ struct LibraryView: View {
_library_names.wrappedValue["favorites"] = "Favorites"
_library_ids.wrappedValue.append("genres")
- _library_names.wrappedValue["genres"] = "Genres"
+ _library_names.wrappedValue["genres"] = "Genres - WIP"
}
}
@@ -196,10 +196,17 @@ struct LibraryView: View {
.frame(width:100, height: 150)
.cornerRadius(10).overlay(
ZStack {
- Text("\(String(item.ItemBadge ?? 0))")
- .font(.caption)
- .padding(3)
- .foregroundColor(.white)
+ if(item.ItemBadge == 0) {
+ Image(systemName: "checkmark")
+ .font(.caption)
+ .padding(3)
+ .foregroundColor(.white)
+ } else {
+ Text("\(String(item.ItemBadge ?? 0))")
+ .font(.caption)
+ .padding(3)
+ .foregroundColor(.white)
+ }
}.background(Color.black)
.opacity(0.8)
.cornerRadius(10.0)
diff --git a/JellyfinPlayer/MovieItemView.swift b/JellyfinPlayer/MovieItemView.swift
index dc607020..cd897181 100644
--- a/JellyfinPlayer/MovieItemView.swift
+++ b/JellyfinPlayer/MovieItemView.swift
@@ -312,7 +312,7 @@ struct MovieItemView: View {
.stroke(Color.secondary, lineWidth: 1)
)
}
- if(fullItem.CommunityRating != "") {
+ if(fullItem.CommunityRating != "0") {
HStack() {
Image(systemName: "star").foregroundColor(.secondary)
Text(fullItem.CommunityRating).font(.subheadline)
@@ -322,8 +322,7 @@ struct MovieItemView: View {
.offset(x: -7, y: 0.7)
}
}
- }
-
+ }.frame(maxWidth: .infinity, alignment: .leading)
}.offset(x: 0, y: -46).padding(.trailing, 16)
}.offset(x: 16, y: 40)
, alignment: .bottomLeading)
@@ -512,7 +511,7 @@ struct MovieItemView: View {
.stroke(Color.secondary, lineWidth: 1)
)
}
- if(fullItem.CommunityRating != "") {
+ if(fullItem.CommunityRating != "0") {
HStack() {
Image(systemName: "star").foregroundColor(.secondary)
Text(fullItem.CommunityRating).font(.subheadline)
@@ -523,9 +522,9 @@ struct MovieItemView: View {
}
}
Spacer()
- }.frame(maxWidth: .infinity)
+ }.frame(maxWidth: .infinity, alignment: .leading)
.offset(x: 14)
- }.frame(maxWidth: .infinity)
+ }.frame(maxWidth: .infinity, alignment: .leading)
Spacer()
HStack() {
Button() {
diff --git a/JellyfinPlayer/SeasonItemView.swift b/JellyfinPlayer/SeasonItemView.swift
index 8daa4c03..10cbcdfb 100644
--- a/JellyfinPlayer/SeasonItemView.swift
+++ b/JellyfinPlayer/SeasonItemView.swift
@@ -218,10 +218,12 @@ struct SeasonItemView: View {
.foregroundColor(.primary)
.fixedSize(horizontal: false, vertical: true)
.offset(y: -4)
- Text(String(fullItem.ProductionYear)).font(.subheadline)
- .fontWeight(.medium)
- .foregroundColor(.secondary)
- .lineLimit(1)
+ if(fullItem.ProductionYear != 0) {
+ Text(String(fullItem.ProductionYear)).font(.subheadline)
+ .fontWeight(.medium)
+ .foregroundColor(.secondary)
+ .lineLimit(1)
+ }
}.offset(x: 0, y: 45)
}.offset(x: 16, y: 22)
, alignment: .bottomLeading)
@@ -324,9 +326,11 @@ struct SeasonItemView: View {
.frame(width: 120, height: 180)
.cornerRadius(10)
Spacer().frame(height: 4)
- Text(String(fullItem.ProductionYear)).font(.subheadline)
- .fontWeight(.medium)
- .foregroundColor(.secondary)
+ if(fullItem.ProductionYear != 0) {
+ Text(String(fullItem.ProductionYear)).font(.subheadline)
+ .fontWeight(.medium)
+ .foregroundColor(.secondary)
+ }
Spacer()
}
ScrollView() {
diff --git a/JellyfinPlayer/SeriesItemView.swift b/JellyfinPlayer/SeriesItemView.swift
index ee19b341..7934d57d 100644
--- a/JellyfinPlayer/SeriesItemView.swift
+++ b/JellyfinPlayer/SeriesItemView.swift
@@ -43,6 +43,11 @@ struct SeriesItemView: View {
itemObj.ProductionYear = item["ProductionYear"].int ?? 0
itemObj.ItemBadge = item["UserData"]["UnplayedItemCount"].int ?? 0
itemObj.Image = item["ImageTags"]["Primary"].string ?? ""
+
+ if(itemObj.Image == "") {
+ itemObj.Image = item["ParentBackdropImageTags"][0].string ?? ""
+ }
+
itemObj.ImageType = "Primary"
itemObj.SeasonImage = item["ParentBackdropImageTags"][0].string ?? ""
itemObj.SeasonImageType = "Backdrop"
@@ -93,10 +98,17 @@ struct SeriesItemView: View {
.cornerRadius(10)
}.overlay(
ZStack {
- Text("\(String(item.ItemBadge ?? 0))")
- .font(.caption)
- .padding(3)
- .foregroundColor(.white)
+ if(item.ItemBadge == 0) {
+ Image(systemName: "checkmark")
+ .font(.caption)
+ .padding(3)
+ .foregroundColor(.white)
+ } else {
+ Text("\(String(item.ItemBadge ?? 0))")
+ .font(.caption)
+ .padding(3)
+ .foregroundColor(.white)
+ }
}.background(Color.black)
.opacity(0.8)
.cornerRadius(10.0)
diff --git a/Release Notes.rtf b/Release Notes.rtf
new file mode 100644
index 00000000..0db3bb8e
--- /dev/null
+++ b/Release Notes.rtf
@@ -0,0 +1,31 @@
+{\rtf1\ansi\ansicpg1252\cocoartf2580
+\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fswiss\fcharset0 Helvetica-Bold;\f1\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+{\*\expandedcolortbl;;}
+{\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid1\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid1}
+{\list\listtemplateid2\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{hyphen\}}{\leveltext\leveltemplateid101\'01\uc0\u8259 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid2}}
+{\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}{\listoverride\listid2\listoverridecount0\ls2}}
+\margl1440\margr1440\vieww11520\viewh8400\viewkind0
+\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0
+
+\f0\b\fs26 \cf0 1.0.0 (Build: 8)
+\f1\b0\fs24 \
+\
+\pard\tx220\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\li720\fi-720\pardirnatural\partightenfactor0
+\ls1\ilvl0\cf0 {\listtext \uc0\u8226 }Fix progress bar on ContinueWatchingView\
+{\listtext \uc0\u8226 }Sort search if no sorting active\
+{\listtext \uc0\u8226 }Limit text length on ContinueWatchingView\
+{\listtext \uc0\u8226 }Fix \'930\'94 for some production years on SeasonItemView\
+{\listtext \uc0\u8226 }Fix \'930\'94 for some CommunityRatings on EpisodeItemView & MovieItemView\
+{\listtext \uc0\u8226 }Fix placeholder image for some episodes on ContinueWatchingView\
+{\listtext \uc0\u8226 }Fix placeholder image for some seasons w/o their own images in SeriesItemView\
+{\listtext \uc0\u8226 }Show checkmarks instead of \'930\'94 on ItemBadges\
+{\listtext \uc0\u8226 }Fix having to click twice on selections in LibraryFilterView\
+{\listtext \uc0\u8226 }Fix bug where sign in page would disappear on orientation change or app relaunch\
+{\listtext \uc0\u8226 }Fix bug where some users would have access to libraries they were not supposed to see.\
+{\listtext \uc0\u8226 }Adds Dynatrace session tracking to try and find the cause for random crashes (app is FOOMing)\
+{\listtext \uc0\u8226 }Fix memory leak when viewing the main page multiple times\
+\pard\tx220\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\li720\fi-720\pardirnatural\partightenfactor0
+\ls2\ilvl0\cf0 {\listtext \uc0\u8259 }Squashed some commits in the repo as sensitive tokens were exposed for Sentry & Dynatrace\
+{\listtext \uc0\u8259 }Also adds Fastlane\
+}
\ No newline at end of file