Implement ItemSeriesSelectableEpisodesView
This commit is contained in:
parent
be11eed89d
commit
aaf0207164
@ -40,6 +40,7 @@
|
|||||||
3D91FDC92B28C62800919017 /* SignInView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D91FDC82B28C62800919017 /* SignInView.swift */; };
|
3D91FDC92B28C62800919017 /* SignInView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D91FDC82B28C62800919017 /* SignInView.swift */; };
|
||||||
3D91FDCB2B28CA2500919017 /* SignInToServerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D91FDCA2B28CA2500919017 /* SignInToServerView.swift */; };
|
3D91FDCB2B28CA2500919017 /* SignInToServerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D91FDCA2B28CA2500919017 /* SignInToServerView.swift */; };
|
||||||
3D91FDCD2B2907E800919017 /* JellyfinDateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D91FDCC2B2907E800919017 /* JellyfinDateFormatter.swift */; };
|
3D91FDCD2B2907E800919017 /* JellyfinDateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D91FDCC2B2907E800919017 /* JellyfinDateFormatter.swift */; };
|
||||||
|
3DADBBC42B8A30DD006C242C /* ItemSeriesSelectableEpisodesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DADBBC32B8A30DD006C242C /* ItemSeriesSelectableEpisodesView.swift */; };
|
||||||
3DAFA8E82B38AFED00D71AD1 /* ItemInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DAFA8E72B38AFED00D71AD1 /* ItemInfoView.swift */; };
|
3DAFA8E82B38AFED00D71AD1 /* ItemInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DAFA8E72B38AFED00D71AD1 /* ItemInfoView.swift */; };
|
||||||
3DAFA8EA2B39039900D71AD1 /* BaseItemDtoExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DAFA8E92B39039900D71AD1 /* BaseItemDtoExtensions.swift */; };
|
3DAFA8EA2B39039900D71AD1 /* BaseItemDtoExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DAFA8E92B39039900D71AD1 /* BaseItemDtoExtensions.swift */; };
|
||||||
3DAFA8EC2B394F9F00D71AD1 /* ViewExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DAFA8EB2B394F9F00D71AD1 /* ViewExtensions.swift */; };
|
3DAFA8EC2B394F9F00D71AD1 /* ViewExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DAFA8EB2B394F9F00D71AD1 /* ViewExtensions.swift */; };
|
||||||
@ -102,6 +103,7 @@
|
|||||||
3D91FDC82B28C62800919017 /* SignInView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInView.swift; sourceTree = "<group>"; };
|
3D91FDC82B28C62800919017 /* SignInView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInView.swift; sourceTree = "<group>"; };
|
||||||
3D91FDCA2B28CA2500919017 /* SignInToServerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInToServerView.swift; sourceTree = "<group>"; };
|
3D91FDCA2B28CA2500919017 /* SignInToServerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInToServerView.swift; sourceTree = "<group>"; };
|
||||||
3D91FDCC2B2907E800919017 /* JellyfinDateFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JellyfinDateFormatter.swift; sourceTree = "<group>"; };
|
3D91FDCC2B2907E800919017 /* JellyfinDateFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JellyfinDateFormatter.swift; sourceTree = "<group>"; };
|
||||||
|
3DADBBC32B8A30DD006C242C /* ItemSeriesSelectableEpisodesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemSeriesSelectableEpisodesView.swift; sourceTree = "<group>"; };
|
||||||
3DAFA8E72B38AFED00D71AD1 /* ItemInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemInfoView.swift; sourceTree = "<group>"; };
|
3DAFA8E72B38AFED00D71AD1 /* ItemInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemInfoView.swift; sourceTree = "<group>"; };
|
||||||
3DAFA8E92B39039900D71AD1 /* BaseItemDtoExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseItemDtoExtensions.swift; sourceTree = "<group>"; };
|
3DAFA8E92B39039900D71AD1 /* BaseItemDtoExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseItemDtoExtensions.swift; sourceTree = "<group>"; };
|
||||||
3DAFA8EB2B394F9F00D71AD1 /* ViewExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewExtensions.swift; sourceTree = "<group>"; };
|
3DAFA8EB2B394F9F00D71AD1 /* ViewExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewExtensions.swift; sourceTree = "<group>"; };
|
||||||
@ -194,6 +196,7 @@
|
|||||||
3D2552482B7A8B3100192879 /* ItemSeriesSeasonsView.swift */,
|
3D2552482B7A8B3100192879 /* ItemSeriesSeasonsView.swift */,
|
||||||
3DDF35D42B7D384000423923 /* ItemSeriesEpisodesView.swift */,
|
3DDF35D42B7D384000423923 /* ItemSeriesEpisodesView.swift */,
|
||||||
3DDF35D62B7D4D0100423923 /* ItemSeriesEpisodeIconView.swift */,
|
3DDF35D62B7D4D0100423923 /* ItemSeriesEpisodeIconView.swift */,
|
||||||
|
3DADBBC32B8A30DD006C242C /* ItemSeriesSelectableEpisodesView.swift */,
|
||||||
);
|
);
|
||||||
path = Series;
|
path = Series;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -397,6 +400,7 @@
|
|||||||
files = (
|
files = (
|
||||||
3D6A0DC12B867B4C001FDA40 /* ScreenSize.swift in Sources */,
|
3D6A0DC12B867B4C001FDA40 /* ScreenSize.swift in Sources */,
|
||||||
3D9063CD2B279A310063DD2A /* ContentView.swift in Sources */,
|
3D9063CD2B279A310063DD2A /* ContentView.swift in Sources */,
|
||||||
|
3DADBBC42B8A30DD006C242C /* ItemSeriesSelectableEpisodesView.swift in Sources */,
|
||||||
3D13F96F2B38A32500E91913 /* StickyHeaderView.swift in Sources */,
|
3D13F96F2B38A32500E91913 /* StickyHeaderView.swift in Sources */,
|
||||||
3DF1ED3E2B282836000AD8EA /* JellyfinClientController.swift in Sources */,
|
3DF1ED3E2B282836000AD8EA /* JellyfinClientController.swift in Sources */,
|
||||||
3D1015D92B27F57400F5C29A /* AddServerView.swift in Sources */,
|
3D1015D92B27F57400F5C29A /* AddServerView.swift in Sources */,
|
||||||
|
@ -27,7 +27,7 @@ struct ItemView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.scrollIndicators(.hidden)
|
// .scrollIndicators(.hidden)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,6 @@ struct ItemSeriesEpisodeIconView: View {
|
|||||||
ExpandableText((item.overviewNL ?? "").replacingOccurrences(of: "<br>", with: "\n"))
|
ExpandableText((item.overviewNL ?? "").replacingOccurrences(of: "<br>", with: "\n"))
|
||||||
.foregroundColor(.secondary)
|
.foregroundColor(.secondary)
|
||||||
}
|
}
|
||||||
.padding(.vertical)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,36 +10,46 @@ import JellyfinKit
|
|||||||
|
|
||||||
struct ItemSeriesEpisodesView: View {
|
struct ItemSeriesEpisodesView: View {
|
||||||
@EnvironmentObject var jellyfinClient: JellyfinClientController
|
@EnvironmentObject var jellyfinClient: JellyfinClientController
|
||||||
@EnvironmentObject var size: ScreenSize
|
|
||||||
|
|
||||||
@ObservedObject var authState: AuthStateController = AuthStateController.shared
|
@ObservedObject var authState: AuthStateController = AuthStateController.shared
|
||||||
|
|
||||||
var item: BaseItemDto
|
var item: BaseItemDto
|
||||||
|
|
||||||
@State var episodeItems: [BaseItemDto] = []
|
@State var episodeItems: [BaseItemDto] = []
|
||||||
|
@State var loading: Bool = true
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(alignment: .leading) {
|
LazyVStack(alignment: .leading) {
|
||||||
ForEach(episodeItems) {episode in
|
ForEach(episodeItems) {episode in
|
||||||
ItemSeriesEpisodeIconView(item: episode)
|
ItemSeriesEpisodeIconView(item: episode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.if(loading) {view in
|
||||||
|
view
|
||||||
|
.redacted(reason: .placeholder)
|
||||||
|
}
|
||||||
|
.onChange(of: item) {
|
||||||
|
self.loadEpisodes()
|
||||||
|
}
|
||||||
.onAppear {
|
.onAppear {
|
||||||
Task {
|
self.loadEpisodes()
|
||||||
let parameters = Paths.GetItemsParameters(
|
|
||||||
userID: authState.userId,
|
|
||||||
parentID: item.id ?? ""
|
|
||||||
)
|
|
||||||
let req = Paths.getItems(parameters: parameters)
|
|
||||||
|
|
||||||
do {
|
|
||||||
let res = try await jellyfinClient.send(req)
|
|
||||||
episodeItems = res.value.items ?? []
|
|
||||||
} catch {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
func loadEpisodes() {
|
||||||
|
Task {
|
||||||
|
let parameters = Paths.GetItemsParameters(
|
||||||
|
userID: authState.userId,
|
||||||
|
parentID: item.id ?? ""
|
||||||
|
)
|
||||||
|
let req = Paths.getItems(parameters: parameters)
|
||||||
|
|
||||||
|
do {
|
||||||
|
let res = try await jellyfinClient.send(req)
|
||||||
|
episodeItems = res.value.items ?? []
|
||||||
|
loading = false
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
|
||||||
//#Preview {
|
//#Preview {
|
||||||
// ItemSeriesEpisodesView()
|
// ItemSeriesEpisodesView()
|
||||||
|
@ -15,6 +15,7 @@ struct ItemSeriesSeasonsView: View {
|
|||||||
@ObservedObject var authState: AuthStateController = AuthStateController.shared
|
@ObservedObject var authState: AuthStateController = AuthStateController.shared
|
||||||
|
|
||||||
@State var seriesItems: [BaseItemDto] = []
|
@State var seriesItems: [BaseItemDto] = []
|
||||||
|
@State var loading: Bool = true
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
@ -34,9 +35,12 @@ struct ItemSeriesSeasonsView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.padding(.horizontal)
|
}.padding(.horizontal)
|
||||||
}
|
}.scrollIndicators(.hidden)
|
||||||
}
|
}
|
||||||
.onAppear{
|
.if(loading) {view in
|
||||||
|
view.redacted(reason: .placeholder)
|
||||||
|
}
|
||||||
|
.onAppear {
|
||||||
Task {
|
Task {
|
||||||
let parameters = Paths.GetItemsParameters(
|
let parameters = Paths.GetItemsParameters(
|
||||||
userID: authState.userId ?? "",
|
userID: authState.userId ?? "",
|
||||||
@ -48,6 +52,8 @@ struct ItemSeriesSeasonsView: View {
|
|||||||
let res = try await jellyfinClient.send(req)
|
let res = try await jellyfinClient.send(req)
|
||||||
seriesItems = res.value.items ?? []
|
seriesItems = res.value.items ?? []
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
|
loading = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
84
Jel/Views/Item/Series/ItemSeriesSelectableEpisodesView.swift
Normal file
84
Jel/Views/Item/Series/ItemSeriesSelectableEpisodesView.swift
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
//
|
||||||
|
// ItemSeriesSelectableEpisodesView.swift
|
||||||
|
// Jel
|
||||||
|
//
|
||||||
|
// Created by zerocool on 2/24/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import JellyfinKit
|
||||||
|
|
||||||
|
struct Season: Identifiable, Hashable {
|
||||||
|
var name: String
|
||||||
|
var id: String
|
||||||
|
var season: BaseItemDto
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Season {
|
||||||
|
static let emptySelection = Season(name: "", id: "", season: BaseItemDto())
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ItemSeriesSelectableEpisodesView: View {
|
||||||
|
@EnvironmentObject var jellyfinClient: JellyfinClientController
|
||||||
|
@StateObject var authState: AuthStateController = AuthStateController.shared
|
||||||
|
|
||||||
|
var item: BaseItemDto // series
|
||||||
|
|
||||||
|
@State var seasons: [Season] = []
|
||||||
|
@State var currentSeason: Season = .emptySelection
|
||||||
|
@State var currentSeasonCopy: Season = .emptySelection
|
||||||
|
|
||||||
|
@State var loading: Bool = true
|
||||||
|
var body: some View {
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
HStack {
|
||||||
|
Text("Episodes")
|
||||||
|
.font(.title2)
|
||||||
|
.padding(.horizontal)
|
||||||
|
|
||||||
|
Picker("Season", selection: $currentSeason) {
|
||||||
|
ForEach(seasons, id: \.self) {season in
|
||||||
|
Text(season.name).tag(season)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemSeriesEpisodesView(item: currentSeasonCopy.season)
|
||||||
|
.padding(.horizontal)
|
||||||
|
}
|
||||||
|
.if(loading) {view in
|
||||||
|
view.redacted(reason: .placeholder)
|
||||||
|
}
|
||||||
|
.onChange(of: currentSeason) {
|
||||||
|
currentSeasonCopy = currentSeason
|
||||||
|
}
|
||||||
|
.onAppear {
|
||||||
|
Task {
|
||||||
|
let parameters = Paths.GetItemsParameters(
|
||||||
|
userID: authState.userId ?? "",
|
||||||
|
parentID: item.id ?? ""
|
||||||
|
)
|
||||||
|
let req = Paths.getItems(parameters: parameters)
|
||||||
|
|
||||||
|
do {
|
||||||
|
let res = try await jellyfinClient.send(req)
|
||||||
|
seasons = []
|
||||||
|
for season in res.value.items ?? [] {
|
||||||
|
let newSeason = Season(
|
||||||
|
name: season.name ?? "---",
|
||||||
|
id: season.id ?? "",
|
||||||
|
season: season
|
||||||
|
)
|
||||||
|
seasons.append(newSeason)
|
||||||
|
currentSeason = seasons.first ?? .emptySelection
|
||||||
|
loading = false
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//#Preview {
|
||||||
|
// ItemSeriesSelectableEpisodesView()
|
||||||
|
//}
|
@ -34,7 +34,7 @@ struct ItemSeriesView: View {
|
|||||||
ItemGenresView(item: item)
|
ItemGenresView(item: item)
|
||||||
.foregroundStyle(Color.primary)
|
.foregroundStyle(Color.primary)
|
||||||
|
|
||||||
// TODO: Settable series with ItemSeriesEpisodesView
|
ItemSeriesSelectableEpisodesView(item: item)
|
||||||
|
|
||||||
ItemSeriesSeasonsView(item: item)
|
ItemSeriesSeasonsView(item: item)
|
||||||
.foregroundStyle(Color.primary)
|
.foregroundStyle(Color.primary)
|
||||||
|
Loading…
Reference in New Issue
Block a user