From 4c98eef1201c42100597d0093988db60b03b0e32 Mon Sep 17 00:00:00 2001 From: Shav Kinderlehrer Date: Sat, 13 Jan 2024 02:20:20 -0500 Subject: [PATCH] Start implementing ItemPersonView --- Jel.xcodeproj/project.pbxproj | 16 +++- Jel/Views/Item/ItemView.swift | 2 + Jel/Views/Item/Person/ItemPeopleView.swift | 6 +- .../Item/Person/ItemPersonDetailView.swift | 47 +++++++++++ Jel/Views/Item/Types/ItemPersonView.swift | 81 +++++++++++++++++++ 5 files changed, 146 insertions(+), 6 deletions(-) create mode 100644 Jel/Views/Item/Person/ItemPersonDetailView.swift create mode 100644 Jel/Views/Item/Types/ItemPersonView.swift diff --git a/Jel.xcodeproj/project.pbxproj b/Jel.xcodeproj/project.pbxproj index 6237f55..6f74bf0 100644 --- a/Jel.xcodeproj/project.pbxproj +++ b/Jel.xcodeproj/project.pbxproj @@ -48,6 +48,8 @@ 3DDD67932B293BC40026781E /* DashboardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DDD67922B293BC40026781E /* DashboardView.swift */; }; 3DDD67962B29E28B0026781E /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DDD67952B29E28B0026781E /* SettingsView.swift */; }; 3DF1ED3E2B282836000AD8EA /* JellyfinClientController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF1ED3D2B282836000AD8EA /* JellyfinClientController.swift */; }; + 3DFE7AF72B5260FF005461FE /* ItemPersonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DFE7AF62B5260FF005461FE /* ItemPersonView.swift */; }; + 3DFE7AF92B5264A4005461FE /* ItemPersonDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DFE7AF82B5264A4005461FE /* ItemPersonDetailView.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -122,6 +124,8 @@ 3DDD67922B293BC40026781E /* DashboardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashboardView.swift; sourceTree = ""; }; 3DDD67952B29E28B0026781E /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = ""; }; 3DF1ED3D2B282836000AD8EA /* JellyfinClientController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JellyfinClientController.swift; sourceTree = ""; }; + 3DFE7AF62B5260FF005461FE /* ItemPersonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemPersonView.swift; sourceTree = ""; }; + 3DFE7AF82B5264A4005461FE /* ItemPersonDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemPersonDetailView.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -299,6 +303,7 @@ isa = PBXGroup; children = ( 3DAFA8EE2B3B707B00D71AD1 /* ItemMovieView.swift */, + 3DFE7AF62B5260FF005461FE /* ItemPersonView.swift */, ); path = Types; sourceTree = ""; @@ -308,6 +313,7 @@ children = ( 3DBAC9E12B4C31BE005F8764 /* ItemPeopleView.swift */, 3DBAC9E92B4C8927005F8764 /* ItemPersonIconView.swift */, + 3DFE7AF82B5264A4005461FE /* ItemPersonDetailView.swift */, ); path = Person; sourceTree = ""; @@ -403,7 +409,7 @@ attributes = { BuildIndependentTargetsInParallel = 1; LastSwiftUpdateCheck = 1500; - LastUpgradeCheck = 1500; + LastUpgradeCheck = 1520; TargetAttributes = { 3D9063C62B279A310063DD2A = { CreatedOnToolsVersion = 15.0.1; @@ -483,6 +489,7 @@ 3D3816C92B4B5648006414D7 /* ItemGenresView.swift in Sources */, 3DAFA8EC2B394F9F00D71AD1 /* ViewExtensions.swift in Sources */, 3D9063CB2B279A310063DD2A /* JelApp.swift in Sources */, + 3DFE7AF92B5264A4005461FE /* ItemPersonDetailView.swift in Sources */, 3DBAC9E42B4C7404005F8764 /* UIScreenCurrent.swift in Sources */, 3D13F9692B389FA300E91913 /* ViewOffsetKey.swift in Sources */, 3D91FDCD2B2907E800919017 /* JellyfinDateFormatter.swift in Sources */, @@ -492,6 +499,7 @@ 3D8AB2A82B366353005BD7D0 /* LibraryDetailView.swift in Sources */, 3DDD67932B293BC40026781E /* DashboardView.swift in Sources */, 3D13F9612B37637500E91913 /* ItemMediaView.swift in Sources */, + 3DFE7AF72B5260FF005461FE /* ItemPersonView.swift in Sources */, 3D41D1FA2B2CAE0000E58234 /* ItemIconView.swift in Sources */, 3D8AB2A52B36440D005BD7D0 /* BlurHashDecode.swift in Sources */, 3DBAC9EA2B4C8927005F8764 /* ItemPersonIconView.swift in Sources */, @@ -665,6 +673,7 @@ CODE_SIGN_ENTITLEMENTS = Jel/Jel.entitlements; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; DEVELOPMENT_ASSET_PATHS = "\"Jel/Preview Content\""; DEVELOPMENT_TEAM = H4TSJQG42B; ENABLE_HARDENED_RUNTIME = YES; @@ -705,6 +714,7 @@ CODE_SIGN_ENTITLEMENTS = Jel/Jel.entitlements; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; DEVELOPMENT_ASSET_PATHS = "\"Jel/Preview Content\""; DEVELOPMENT_TEAM = H4TSJQG42B; ENABLE_HARDENED_RUNTIME = YES; @@ -743,6 +753,7 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = H4TSJQG42B; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 17.0; @@ -766,6 +777,7 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = H4TSJQG42B; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 17.0; @@ -788,6 +800,7 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = H4TSJQG42B; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 17.0; @@ -810,6 +823,7 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = H4TSJQG42B; GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 17.0; diff --git a/Jel/Views/Item/ItemView.swift b/Jel/Views/Item/ItemView.swift index da85f32..7611450 100644 --- a/Jel/Views/Item/ItemView.swift +++ b/Jel/Views/Item/ItemView.swift @@ -16,6 +16,8 @@ struct ItemView: View { switch item.type { case .movie: ItemMovieView(item: item) + case .person: + ItemPersonView(item: item) default: ItemMediaView(item: item) } diff --git a/Jel/Views/Item/Person/ItemPeopleView.swift b/Jel/Views/Item/Person/ItemPeopleView.swift index f007796..1a60ca2 100644 --- a/Jel/Views/Item/Person/ItemPeopleView.swift +++ b/Jel/Views/Item/Person/ItemPeopleView.swift @@ -7,7 +7,6 @@ import SwiftUI import JellyfinKit -import NukeUI struct ItemPeopleView: View { @@ -24,10 +23,7 @@ struct ItemPeopleView: View { HStack(alignment: .top) { ForEach(item.people ?? [], id: \.iterId) {person in NavigationLink { - VStack { - ItemPersonIconView(person: person) - Text("Subview") - } + ItemPersonDetailView(person: person) .navigationTitle(person.name ?? "Unnamed") } label: { ItemPersonIconView(person: person) diff --git a/Jel/Views/Item/Person/ItemPersonDetailView.swift b/Jel/Views/Item/Person/ItemPersonDetailView.swift new file mode 100644 index 0000000..5e0bddf --- /dev/null +++ b/Jel/Views/Item/Person/ItemPersonDetailView.swift @@ -0,0 +1,47 @@ +// +// ItemPersonDetailView.swift +// Jel +// +// Created by zerocool on 1/13/24. +// + +import SwiftUI +import JellyfinKit + +struct ItemPersonDetailView: View { + @StateObject var authState: AuthStateController = AuthStateController.shared + @EnvironmentObject var jellyfinClient: JellyfinClientController + + var person: BaseItemPerson + + @State var personItem: BaseItemDto? + @State var loading: Bool = true + + var body: some View { + VStack { + if loading { + ProgressView() + .progressViewStyle(.circular) + } + + if let personItem = personItem { + ItemView(item: personItem) + } + } + .onAppear { + Task { + let request = Paths.getItem(userID: authState.userId ?? "", itemID: person.id ?? "") + + do { + let res = try await jellyfinClient.send(request) + personItem = res.value + loading = false + } catch {} + } + } + } +} + +//#Preview { +// ItemPersonDetailView() +//} diff --git a/Jel/Views/Item/Types/ItemPersonView.swift b/Jel/Views/Item/Types/ItemPersonView.swift new file mode 100644 index 0000000..b827480 --- /dev/null +++ b/Jel/Views/Item/Types/ItemPersonView.swift @@ -0,0 +1,81 @@ +// +// ItemPersonView.swift +// Jel +// +// Created by zerocool on 1/13/24. +// + +import SwiftUI +import JellyfinKit + +struct ItemPersonView: View { + @EnvironmentObject var jellyfinClient: JellyfinClientController + + var item: BaseItemDto + + @State var items: [BaseItemDto]? + + var body: some View { + VStack(alignment: .leading) { + Text(item.name ?? "---") + .font(.title) + .padding() + + if let overview = item.overview { + Text(overview) + .padding([.horizontal, .bottom]) + } + + if let items = items { + // TODO: Extract to view to maintain DRY + let movies = items.filter({$0.type == .movie}) + if movies.count > 0 { + Text("Movies") + .font(.title2) + .padding(.horizontal) + ScrollView(.horizontal) { + LazyHStack { + ForEach(movies) {movie in + Text(movie.name ?? "") + } + } + .padding(.horizontal) + } + } + + let shows = items.filter({$0.type == .series}) + if shows.count > 0 { + Text("Shows") + .font(.title2) + .padding(.horizontal) + ScrollView(.horizontal) { + LazyHStack { + ForEach(shows) {show in + Text(show.name ?? "") + } + } + .padding(.horizontal) + } + } + } + } + .onAppear { + Task { + let parameters = Paths.GetItemsParameters( + isRecursive: true, + personIDs: [item.id ?? ""] + ) + let request = Paths.getItems(parameters: parameters) + + do { + let res = try await jellyfinClient.send(request) + items = res.value.items ?? [] + } catch {} + } + } + } +} + +//#Preview { +// ItemPersonView() +//}