more final work
This commit is contained in:
parent
00aaa246fd
commit
f2374de291
|
@ -70,7 +70,7 @@ struct LandscapeItemElement: View {
|
||||||
.frame(width: 445, height: 90)
|
.frame(width: 445, height: 90)
|
||||||
.mask(CutOffShadow())
|
.mask(CutOffShadow())
|
||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
Text("CONTINUE • \(item.getItemProgressString())")
|
Text("CONTINUE • \(item.getItemProgressString() ?? "")")
|
||||||
.font(.caption)
|
.font(.caption)
|
||||||
.fontWeight(.medium)
|
.fontWeight(.medium)
|
||||||
.offset(y: 5)
|
.offset(y: 5)
|
||||||
|
|
|
@ -32,12 +32,13 @@ struct CinematicEpisodeItemView: View {
|
||||||
ZStack(alignment: .topLeading) {
|
ZStack(alignment: .topLeading) {
|
||||||
|
|
||||||
Color.black.ignoresSafeArea()
|
Color.black.ignoresSafeArea()
|
||||||
|
.frame(minHeight: UIScreen.main.bounds.height)
|
||||||
|
|
||||||
VStack(alignment: .leading, spacing: 20) {
|
VStack(alignment: .leading, spacing: 20) {
|
||||||
|
|
||||||
CinematicItemAboutView(viewModel: viewModel)
|
CinematicItemAboutView(viewModel: viewModel)
|
||||||
|
|
||||||
EpisodesRowView(viewModel: viewModel)
|
EpisodesRowView(viewModel: EpisodesRowViewModel(episodeItemViewModel: viewModel))
|
||||||
.focusSection()
|
.focusSection()
|
||||||
|
|
||||||
if !viewModel.similarItems.isEmpty {
|
if !viewModel.similarItems.isEmpty {
|
||||||
|
|
|
@ -13,58 +13,118 @@ import SwiftUI
|
||||||
struct EpisodesRowView: View {
|
struct EpisodesRowView: View {
|
||||||
|
|
||||||
@EnvironmentObject var itemRouter: ItemCoordinator.Router
|
@EnvironmentObject var itemRouter: ItemCoordinator.Router
|
||||||
@ObservedObject var viewModel: EpisodeItemViewModel
|
@ObservedObject var viewModel: EpisodesRowViewModel
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
|
|
||||||
Text("Episodes")
|
Text(viewModel.selectedSeason?.name ?? "Episodes")
|
||||||
.font(.title3)
|
.font(.title3)
|
||||||
.padding(.horizontal, 50)
|
.padding(.horizontal, 50)
|
||||||
|
|
||||||
ScrollView(.horizontal) {
|
ScrollView(.horizontal) {
|
||||||
ScrollViewReader { reader in
|
ScrollViewReader { reader in
|
||||||
HStack(alignment: .top) {
|
HStack(alignment: .top) {
|
||||||
ForEach(viewModel.seasonEpisodes, id:\.self) { episode in
|
if viewModel.isLoading {
|
||||||
Button {
|
VStack(alignment: .leading) {
|
||||||
itemRouter.route(to: \.item, episode)
|
|
||||||
} label: {
|
ZStack {
|
||||||
HStack(alignment: .top) {
|
Color.secondary.ignoresSafeArea()
|
||||||
|
|
||||||
|
ProgressView()
|
||||||
|
}
|
||||||
|
.mask(Rectangle().frame(width: 500, height: 280))
|
||||||
|
.frame(width: 500, height: 280)
|
||||||
|
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
Text("S-E-")
|
||||||
|
.font(.caption)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
Text("--")
|
||||||
|
.font(.footnote)
|
||||||
|
.padding(.bottom, 1)
|
||||||
|
Text("--")
|
||||||
|
.font(.caption)
|
||||||
|
.fontWeight(.light)
|
||||||
|
.lineLimit(4)
|
||||||
|
}
|
||||||
|
.padding(.horizontal)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.frame(width: 500)
|
||||||
|
.focusable()
|
||||||
|
} else if let selectedSeason = viewModel.selectedSeason {
|
||||||
|
if viewModel.seasonsEpisodes[selectedSeason]!.isEmpty {
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
|
||||||
|
Color.secondary
|
||||||
|
.mask(Rectangle().frame(width: 500, height: 280))
|
||||||
|
.frame(width: 500, height: 280)
|
||||||
|
|
||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
|
Text("--")
|
||||||
ImageView(src: episode.getBackdropImage(maxWidth: 445),
|
.font(.caption)
|
||||||
bh: episode.getBackdropImageBlurHash())
|
.foregroundColor(.secondary)
|
||||||
.mask(Rectangle().frame(width: 500, height: 280))
|
Text("No episodes available")
|
||||||
.frame(width: 500, height: 280)
|
.font(.footnote)
|
||||||
|
.padding(.bottom, 1)
|
||||||
VStack(alignment: .leading) {
|
|
||||||
Text(episode.getEpisodeLocator() ?? "")
|
|
||||||
.font(.caption)
|
|
||||||
.foregroundColor(.secondary)
|
|
||||||
Text(episode.name ?? "")
|
|
||||||
.font(.footnote)
|
|
||||||
.padding(.bottom, 1)
|
|
||||||
Text(episode.overview ?? "")
|
|
||||||
.font(.caption)
|
|
||||||
.fontWeight(.light)
|
|
||||||
.lineLimit(4)
|
|
||||||
}
|
|
||||||
.padding(.horizontal)
|
|
||||||
|
|
||||||
Spacer()
|
|
||||||
}
|
}
|
||||||
.frame(width: 500)
|
.padding(.horizontal)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.frame(width: 500)
|
||||||
|
.focusable()
|
||||||
|
} else {
|
||||||
|
ForEach(viewModel.seasonsEpisodes[selectedSeason]!, id:\.self) { episode in
|
||||||
|
Button {
|
||||||
|
itemRouter.route(to: \.item, episode)
|
||||||
|
} label: {
|
||||||
|
HStack(alignment: .top) {
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
|
||||||
|
ImageView(src: episode.getBackdropImage(maxWidth: 445),
|
||||||
|
bh: episode.getBackdropImageBlurHash())
|
||||||
|
.mask(Rectangle().frame(width: 500, height: 280))
|
||||||
|
.frame(width: 500, height: 280)
|
||||||
|
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
Text(episode.getEpisodeLocator() ?? "")
|
||||||
|
.font(.caption)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
Text(episode.name ?? "")
|
||||||
|
.font(.footnote)
|
||||||
|
.padding(.bottom, 1)
|
||||||
|
Text(episode.overview ?? "")
|
||||||
|
.font(.caption)
|
||||||
|
.fontWeight(.light)
|
||||||
|
.lineLimit(4)
|
||||||
|
}
|
||||||
|
.padding(.horizontal)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.frame(width: 500)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.buttonStyle(PlainButtonStyle())
|
||||||
|
.id(episode.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.buttonStyle(PlainButtonStyle())
|
|
||||||
.id(episode.name)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(.horizontal, 50)
|
.padding(.horizontal, 50)
|
||||||
.padding(.vertical)
|
.padding(.vertical)
|
||||||
.onAppear {
|
.onChange(of: viewModel.selectedSeason) { _ in
|
||||||
// TODO: Get this working
|
if viewModel.selectedSeason?.id == viewModel.episodeItemViewModel.item.seasonId {
|
||||||
reader.scrollTo(viewModel.item.name)
|
reader.scrollTo(viewModel.episodeItemViewModel.item.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onChange(of: viewModel.seasonsEpisodes) { _ in
|
||||||
|
if viewModel.selectedSeason?.id == viewModel.episodeItemViewModel.item.seasonId {
|
||||||
|
reader.scrollTo(viewModel.episodeItemViewModel.item.name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.edgesIgnoringSafeArea(.horizontal)
|
.edgesIgnoringSafeArea(.horizontal)
|
||||||
|
|
|
@ -23,12 +23,12 @@ struct ItemDetailsView: View {
|
||||||
|
|
||||||
HStack(alignment: .top) {
|
HStack(alignment: .top) {
|
||||||
VStack(alignment: .leading, spacing: 20) {
|
VStack(alignment: .leading, spacing: 20) {
|
||||||
Text("Details")
|
Text("Information")
|
||||||
.font(.title3)
|
.font(.title3)
|
||||||
.padding(.bottom, 5)
|
.padding(.bottom, 5)
|
||||||
|
|
||||||
ForEach(detailItems, id: \.self.0) { (title, content) in
|
ForEach(viewModel.informationItems, id: \.self.title) { informationItem in
|
||||||
ItemDetail(title: title, content: content)
|
ItemDetail(title: informationItem.title, content: informationItem.content)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,8 +39,8 @@ struct ItemDetailsView: View {
|
||||||
.font(.title3)
|
.font(.title3)
|
||||||
.padding(.bottom, 5)
|
.padding(.bottom, 5)
|
||||||
|
|
||||||
ForEach(mediaItems, id: \.self.0) { (title, content) in
|
ForEach(viewModel.mediaItems, id: \.self.title) { mediaItem in
|
||||||
ItemDetail(title: title, content: content)
|
ItemDetail(title: mediaItem.title, content: mediaItem.content)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,8 +49,7 @@ struct ItemDetailsView: View {
|
||||||
.ignoresSafeArea()
|
.ignoresSafeArea()
|
||||||
.focusable()
|
.focusable()
|
||||||
.focused($focused)
|
.focused($focused)
|
||||||
.padding(.horizontal, 50)
|
.padding(50)
|
||||||
.padding(.bottom, 50)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1324,8 +1324,8 @@
|
||||||
E14F7D0A26DB3714007C3AE6 /* ItemView */ = {
|
E14F7D0A26DB3714007C3AE6 /* ItemView */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
535BAE9E2649E569005FA86D /* ItemView.swift */,
|
|
||||||
E10D87DB2784EC5200BD264C /* EpisodesRowView.swift */,
|
E10D87DB2784EC5200BD264C /* EpisodesRowView.swift */,
|
||||||
|
535BAE9E2649E569005FA86D /* ItemView.swift */,
|
||||||
E18845F726DEA9C900B0C5B7 /* ItemViewBody.swift */,
|
E18845F726DEA9C900B0C5B7 /* ItemViewBody.swift */,
|
||||||
E10D87D92784E4F100BD264C /* ItemViewDetailsView.swift */,
|
E10D87D92784E4F100BD264C /* ItemViewDetailsView.swift */,
|
||||||
E18845FB26DEACC400B0C5B7 /* Landscape */,
|
E18845FB26DEACC400B0C5B7 /* Landscape */,
|
||||||
|
@ -1399,8 +1399,8 @@
|
||||||
children = (
|
children = (
|
||||||
E1E5D53C2783A85F00692DFE /* CinematicItemView */,
|
E1E5D53C2783A85F00692DFE /* CinematicItemView */,
|
||||||
53272538268C20100035FBF1 /* EpisodeItemView.swift */,
|
53272538268C20100035FBF1 /* EpisodeItemView.swift */,
|
||||||
E1E5D5432783BB5100692DFE /* ItemDetailsView.swift */,
|
|
||||||
E1E5D5382783A56B00692DFE /* EpisodesRowView.swift */,
|
E1E5D5382783A56B00692DFE /* EpisodesRowView.swift */,
|
||||||
|
E1E5D5432783BB5100692DFE /* ItemDetailsView.swift */,
|
||||||
53CD2A3F268A49C2002ABD4E /* ItemView.swift */,
|
53CD2A3F268A49C2002ABD4E /* ItemView.swift */,
|
||||||
53CD2A41268A4B38002ABD4E /* MovieItemView.swift */,
|
53CD2A41268A4B38002ABD4E /* MovieItemView.swift */,
|
||||||
E1E5D5412783B33900692DFE /* PortraitItemsRowView.swift */,
|
E1E5D5412783B33900692DFE /* PortraitItemsRowView.swift */,
|
||||||
|
|
|
@ -59,10 +59,10 @@ struct EpisodesRowView: View {
|
||||||
.frame(width: 200, height: 112)
|
.frame(width: 200, height: 112)
|
||||||
|
|
||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
Text("--")
|
Text("S-E-")
|
||||||
.font(.footnote)
|
.font(.footnote)
|
||||||
.foregroundColor(.secondary)
|
.foregroundColor(.secondary)
|
||||||
Text("Loading")
|
Text("--")
|
||||||
.font(.body)
|
.font(.body)
|
||||||
.padding(.bottom, 1)
|
.padding(.bottom, 1)
|
||||||
.lineLimit(2)
|
.lineLimit(2)
|
||||||
|
|
|
@ -32,7 +32,7 @@ final class VideoPlayerCoordinator: NavigationCoordinatable {
|
||||||
.statusBar(hidden: true)
|
.statusBar(hidden: true)
|
||||||
.ignoresSafeArea()
|
.ignoresSafeArea()
|
||||||
.prefersHomeIndicatorAutoHidden(true)
|
.prefersHomeIndicatorAutoHidden(true)
|
||||||
.supportedOrientations(.landscape)
|
.supportedOrientations(UIDevice.current.userInterfaceIdiom == .pad ? .all : .landscape)
|
||||||
}.ignoresSafeArea()
|
}.ignoresSafeArea()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,5 @@ enum SwiftfinNotificationCenter {
|
||||||
static let processDeepLink = Notification.Name("processDeepLink")
|
static let processDeepLink = Notification.Name("processDeepLink")
|
||||||
static let didPurge = Notification.Name("didPurge")
|
static let didPurge = Notification.Name("didPurge")
|
||||||
static let didChangeServerCurrentURI = Notification.Name("didChangeCurrentLoginURI")
|
static let didChangeServerCurrentURI = Notification.Name("didChangeCurrentLoginURI")
|
||||||
|
|
||||||
static let didEndPlayback = Notification.Name("didEndPlayback")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,10 +49,10 @@ final class ConnectToServerViewModel: ViewModel {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
let uri = uri.trimmingCharacters(in: .whitespaces)
|
let trimmedURI = uri.trimmingCharacters(in: .whitespaces)
|
||||||
|
|
||||||
LogManager.shared.log.debug("Attempting to connect to server at \"\(uri)\"", tag: "connectToServer")
|
LogManager.shared.log.debug("Attempting to connect to server at \"\(trimmedURI)\"", tag: "connectToServer")
|
||||||
SessionManager.main.connectToServer(with: uri)
|
SessionManager.main.connectToServer(with: trimmedURI)
|
||||||
.trackActivity(loading)
|
.trackActivity(loading)
|
||||||
.sink(receiveCompletion: { completion in
|
.sink(receiveCompletion: { completion in
|
||||||
// This is disgusting. ViewModel Error handling overall needs to be refactored
|
// This is disgusting. ViewModel Error handling overall needs to be refactored
|
||||||
|
|
|
@ -32,11 +32,6 @@ final class HomeViewModel: ViewModel {
|
||||||
let nc = SwiftfinNotificationCenter.main
|
let nc = SwiftfinNotificationCenter.main
|
||||||
nc.addObserver(self, selector: #selector(didSignIn), name: SwiftfinNotificationCenter.Keys.didSignIn, object: nil)
|
nc.addObserver(self, selector: #selector(didSignIn), name: SwiftfinNotificationCenter.Keys.didSignIn, object: nil)
|
||||||
nc.addObserver(self, selector: #selector(didSignOut), name: SwiftfinNotificationCenter.Keys.didSignOut, object: nil)
|
nc.addObserver(self, selector: #selector(didSignOut), name: SwiftfinNotificationCenter.Keys.didSignOut, object: nil)
|
||||||
nc.addObserver(self, selector: #selector(didEndPlayback), name: SwiftfinNotificationCenter.Keys.didEndPlayback, object: nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
deinit {
|
|
||||||
SwiftfinNotificationCenter.main.removeObserver(self)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func didSignIn() {
|
@objc private func didSignIn() {
|
||||||
|
@ -59,11 +54,6 @@ final class HomeViewModel: ViewModel {
|
||||||
|
|
||||||
cancellables.removeAll()
|
cancellables.removeAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func didEndPlayback() {
|
|
||||||
refreshResumeItems()
|
|
||||||
refreshNextUpItems()
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func refresh() {
|
@objc func refresh() {
|
||||||
LogManager.shared.log.debug("Refresh called.")
|
LogManager.shared.log.debug("Refresh called.")
|
||||||
|
|
Loading…
Reference in New Issue