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