mirror of
https://github.com/jellyfin/Swiftfin.git
synced 2025-02-24 17:21:00 +00:00
Merge branch 'main' into multi-server-url
This commit is contained in:
commit
eb901da824
@ -290,6 +290,9 @@
|
||||
E18845F826DEA9C900B0C5B7 /* ItemViewBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = E18845F726DEA9C900B0C5B7 /* ItemViewBody.swift */; };
|
||||
E188460026DECB9E00B0C5B7 /* ItemLandscapeTopBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E18845FF26DECB9E00B0C5B7 /* ItemLandscapeTopBarView.swift */; };
|
||||
E188460426DEF04800B0C5B7 /* EpisodeCardVStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E188460326DEF04800B0C5B7 /* EpisodeCardVStackView.swift */; };
|
||||
E19169CE272514760085832A /* HTTPScheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = E19169CD272514760085832A /* HTTPScheme.swift */; };
|
||||
E19169CF272514760085832A /* HTTPScheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = E19169CD272514760085832A /* HTTPScheme.swift */; };
|
||||
E19169D0272514760085832A /* HTTPScheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = E19169CD272514760085832A /* HTTPScheme.swift */; };
|
||||
E193D4D827193CAC00900D82 /* PortraitImageStackable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E193D4D727193CAC00900D82 /* PortraitImageStackable.swift */; };
|
||||
E193D4D927193CAC00900D82 /* PortraitImageStackable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E193D4D727193CAC00900D82 /* PortraitImageStackable.swift */; };
|
||||
E193D4DB27193CCA00900D82 /* PillStackable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E193D4DA27193CCA00900D82 /* PillStackable.swift */; };
|
||||
@ -342,6 +345,7 @@
|
||||
E1D4BF8C2719F39F00A11E64 /* AppAppearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1D4BF802719D22800A11E64 /* AppAppearance.swift */; };
|
||||
E1D4BF8D2719F3A300A11E64 /* VideoPlayerJumpLength.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1F0204D26CCCA74001C1C3B /* VideoPlayerJumpLength.swift */; };
|
||||
E1D4BF8F271A079A00A11E64 /* BasicAppSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1D4BF8E271A079A00A11E64 /* BasicAppSettingsView.swift */; };
|
||||
E1E48CC9271E6D410021A2F9 /* RefreshHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E48CC8271E6D410021A2F9 /* RefreshHelper.swift */; };
|
||||
E1F0204E26CCCA74001C1C3B /* VideoPlayerJumpLength.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1F0204D26CCCA74001C1C3B /* VideoPlayerJumpLength.swift */; };
|
||||
E1F0204F26CCCA74001C1C3B /* VideoPlayerJumpLength.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1F0204D26CCCA74001C1C3B /* VideoPlayerJumpLength.swift */; };
|
||||
E1FCD08826C35A0D007C8DCF /* NetworkError.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1FCD08726C35A0D007C8DCF /* NetworkError.swift */; };
|
||||
@ -575,6 +579,7 @@
|
||||
E18845F726DEA9C900B0C5B7 /* ItemViewBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemViewBody.swift; sourceTree = "<group>"; };
|
||||
E18845FF26DECB9E00B0C5B7 /* ItemLandscapeTopBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemLandscapeTopBarView.swift; sourceTree = "<group>"; };
|
||||
E188460326DEF04800B0C5B7 /* EpisodeCardVStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EpisodeCardVStackView.swift; sourceTree = "<group>"; };
|
||||
E19169CD272514760085832A /* HTTPScheme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTTPScheme.swift; sourceTree = "<group>"; };
|
||||
E193D4D727193CAC00900D82 /* PortraitImageStackable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PortraitImageStackable.swift; sourceTree = "<group>"; };
|
||||
E193D4DA27193CCA00900D82 /* PillStackable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillStackable.swift; sourceTree = "<group>"; };
|
||||
E193D5422719407E00900D82 /* tvOSMainCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = tvOSMainCoordinator.swift; sourceTree = "<group>"; };
|
||||
@ -597,6 +602,7 @@
|
||||
E1D4BF862719D27100A11E64 /* Bitrates.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bitrates.swift; sourceTree = "<group>"; };
|
||||
E1D4BF892719D3D000A11E64 /* BasicAppSettingsCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BasicAppSettingsCoordinator.swift; sourceTree = "<group>"; };
|
||||
E1D4BF8E271A079A00A11E64 /* BasicAppSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BasicAppSettingsView.swift; sourceTree = "<group>"; };
|
||||
E1E48CC8271E6D410021A2F9 /* RefreshHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshHelper.swift; sourceTree = "<group>"; };
|
||||
E1F0204D26CCCA74001C1C3B /* VideoPlayerJumpLength.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoPlayerJumpLength.swift; sourceTree = "<group>"; };
|
||||
E1FCD08726C35A0D007C8DCF /* NetworkError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkError.swift; sourceTree = "<group>"; };
|
||||
E1FCD09526C47118007C8DCF /* ErrorMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorMessage.swift; sourceTree = "<group>"; };
|
||||
@ -807,6 +813,7 @@
|
||||
E1AD104926D94822003E4A08 /* DetailItem.swift */,
|
||||
53192D5C265AA78A008A4215 /* DeviceProfileBuilder.swift */,
|
||||
62EC353326766B03000E9F2D /* DeviceRotationViewModifier.swift */,
|
||||
E19169CD272514760085832A /* HTTPScheme.swift */,
|
||||
E193D4DA27193CCA00900D82 /* PillStackable.swift */,
|
||||
E193D4D727193CAC00900D82 /* PortraitImageStackable.swift */,
|
||||
E1D4BF832719D25A00A11E64 /* TrackLanguage.swift */,
|
||||
@ -856,6 +863,7 @@
|
||||
5377CBF3263B596A003A4E83 /* JellyfinPlayer */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E1DD1127271E7D15005BE12F /* Objects */,
|
||||
E13DD3BB27163C3E009D4DAF /* App */,
|
||||
62ECA01926FA6D6900E8EBB7 /* AppURLHandler */,
|
||||
5377CBF8263B596B003A4E83 /* Assets.xcassets */,
|
||||
@ -1293,6 +1301,14 @@
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E1DD1127271E7D15005BE12F /* Objects */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E1E48CC8271E6D410021A2F9 /* RefreshHelper.swift */,
|
||||
);
|
||||
path = Objects;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E1FCD08E26C466F3007C8DCF /* Errors */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -1734,6 +1750,7 @@
|
||||
E193D549271941CC00900D82 /* UserSignInView.swift in Sources */,
|
||||
535870AA2669D8AE00D05A09 /* BlurHashDecode.swift in Sources */,
|
||||
53ABFDE5267974EF00886593 /* ViewModel.swift in Sources */,
|
||||
E19169CF272514760085832A /* HTTPScheme.swift in Sources */,
|
||||
C45B29BB26FAC5B600CEF5E0 /* ColorExtension.swift in Sources */,
|
||||
531069582684E7EE00CFFDBA /* MediaInfoView.swift in Sources */,
|
||||
E1D4BF822719D22800A11E64 /* AppAppearance.swift in Sources */,
|
||||
@ -1808,6 +1825,7 @@
|
||||
E173DA5426D050F500CC4EB7 /* ServerDetailViewModel.swift in Sources */,
|
||||
E188460426DEF04800B0C5B7 /* EpisodeCardVStackView.swift in Sources */,
|
||||
53F8377D265FF67C00F456B3 /* VideoPlayerSettingsView.swift in Sources */,
|
||||
E19169CE272514760085832A /* HTTPScheme.swift in Sources */,
|
||||
53192D5D265AA78A008A4215 /* DeviceProfileBuilder.swift in Sources */,
|
||||
62133890265F83A900A81A2A /* LibraryListView.swift in Sources */,
|
||||
62C29EA326D1030F00C1D2E7 /* ConnectToServerCoodinator.swift in Sources */,
|
||||
@ -1841,6 +1859,7 @@
|
||||
6220D0CC26D640C400B8E046 /* AppURLHandler.swift in Sources */,
|
||||
62E632F3267D54030063E547 /* ItemViewModel.swift in Sources */,
|
||||
53DE4BD2267098F300739748 /* SearchBarView.swift in Sources */,
|
||||
E1E48CC9271E6D410021A2F9 /* RefreshHelper.swift in Sources */,
|
||||
E1D4BF842719D25A00A11E64 /* TrackLanguage.swift in Sources */,
|
||||
E14F7D0726DB36EF007C3AE6 /* ItemPortraitMainView.swift in Sources */,
|
||||
E1AD106226D9B7CD003E4A08 /* ItemPortraitHeaderOverlayView.swift in Sources */,
|
||||
@ -1904,6 +1923,7 @@
|
||||
files = (
|
||||
53649AB3269D3F5B00A2D8B7 /* LogManager.swift in Sources */,
|
||||
E13DD3CB27164BA8009D4DAF /* UIDeviceExtensions.swift in Sources */,
|
||||
E19169D0272514760085832A /* HTTPScheme.swift in Sources */,
|
||||
6267B3D726710B9700A7371D /* CollectionExtensions.swift in Sources */,
|
||||
628B953C2670D2430091AF3B /* StringExtensions.swift in Sources */,
|
||||
6267B3DB2671139400A7371D /* ImageExtensions.swift in Sources */,
|
||||
|
@ -19,8 +19,7 @@ struct JellyfinPlayerApp: App {
|
||||
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
// TODO: Replace with a SplashView
|
||||
Color(appAppearance.style == .light ? UIColor.white : UIColor.black)
|
||||
EmptyView()
|
||||
.ignoresSafeArea()
|
||||
.onAppear {
|
||||
setupAppearance()
|
||||
|
@ -0,0 +1,38 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "1.000",
|
||||
"green" : "1.000",
|
||||
"red" : "1.000"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.000",
|
||||
"green" : "0.000",
|
||||
"red" : "0.000"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
23
JellyfinPlayer/Assets.xcassets/swiftfin-logo.imageset/Contents.json
vendored
Normal file
23
JellyfinPlayer/Assets.xcassets/swiftfin-logo.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "swiftfin-logo.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "swiftfin-logo-1.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "swiftfin-logo-2.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
JellyfinPlayer/Assets.xcassets/swiftfin-logo.imageset/swiftfin-logo-1.png
vendored
Normal file
BIN
JellyfinPlayer/Assets.xcassets/swiftfin-logo.imageset/swiftfin-logo-1.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
BIN
JellyfinPlayer/Assets.xcassets/swiftfin-logo.imageset/swiftfin-logo-2.png
vendored
Normal file
BIN
JellyfinPlayer/Assets.xcassets/swiftfin-logo.imageset/swiftfin-logo-2.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
BIN
JellyfinPlayer/Assets.xcassets/swiftfin-logo.imageset/swiftfin-logo.png
vendored
Normal file
BIN
JellyfinPlayer/Assets.xcassets/swiftfin-logo.imageset/swiftfin-logo.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
@ -62,9 +62,14 @@ network.</string>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>UILaunchScreen</key>
|
||||
<dict/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>VideoPlayer</string>
|
||||
<dict>
|
||||
<key>UIImageRespectsSafeAreaInsets</key>
|
||||
<true/>
|
||||
<key>UIImageName</key>
|
||||
<string>swiftfin-logo</string>
|
||||
<key>UIColorName</key>
|
||||
<string>LaunchScreenBackground</string>
|
||||
</dict>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
|
23
JellyfinPlayer/Objects/RefreshHelper.swift
Normal file
23
JellyfinPlayer/Objects/RefreshHelper.swift
Normal file
@ -0,0 +1,23 @@
|
||||
//
|
||||
/*
|
||||
* SwiftFin is subject to the terms of the Mozilla Public
|
||||
* License, v2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 2021 Aiden Vigue & Jellyfin Contributors
|
||||
*/
|
||||
|
||||
import UIKit
|
||||
|
||||
// A more general derivative of
|
||||
// https://stackoverflow.com/questions/65812080/introspect-library-uirefreshcontrol-with-swiftui-not-working
|
||||
class RefreshHelper {
|
||||
var refreshControl: UIRefreshControl?
|
||||
var refreshAction: (() -> Void)?
|
||||
|
||||
@objc func didRefresh() {
|
||||
guard let refreshControl = refreshControl else { return }
|
||||
refreshAction?()
|
||||
refreshControl.endRefreshing()
|
||||
}
|
||||
}
|
@ -18,6 +18,7 @@ struct BasicAppSettingsView: View {
|
||||
@State var resetTapped: Bool = false
|
||||
|
||||
@Default(.appAppearance) var appAppearance
|
||||
@Default(.defaultHTTPScheme) var defaultHTTPScheme
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
@ -33,6 +34,16 @@ struct BasicAppSettingsView: View {
|
||||
Text("Accessibility")
|
||||
}
|
||||
|
||||
Section {
|
||||
Picker("Default Scheme", selection: $defaultHTTPScheme) {
|
||||
ForEach(HTTPScheme.allCases, id: \.self) { scheme in
|
||||
Text("\(scheme.rawValue)")
|
||||
}
|
||||
}
|
||||
} header: {
|
||||
Text("Networking")
|
||||
}
|
||||
|
||||
Button {
|
||||
resetTapped = true
|
||||
} label: {
|
||||
|
@ -6,14 +6,17 @@
|
||||
* Copyright 2021 Aiden Vigue & Jellyfin Contributors
|
||||
*/
|
||||
|
||||
import SwiftUI
|
||||
import Defaults
|
||||
import Stinsen
|
||||
import SwiftUI
|
||||
|
||||
struct ConnectToServerView: View {
|
||||
|
||||
@ObservedObject var viewModel: ConnectToServerViewModel
|
||||
@State var uri = ""
|
||||
|
||||
@Default(.defaultHTTPScheme) var defaultHTTPScheme
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
Section {
|
||||
@ -21,6 +24,11 @@ struct ConnectToServerView: View {
|
||||
.disableAutocorrection(true)
|
||||
.autocapitalization(.none)
|
||||
.keyboardType(.URL)
|
||||
.onAppear {
|
||||
if uri == "" {
|
||||
uri = "\(defaultHTTPScheme.rawValue)://"
|
||||
}
|
||||
}
|
||||
|
||||
if viewModel.isLoading {
|
||||
Button(role: .destructive) {
|
||||
|
@ -8,12 +8,15 @@
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
import Introspect
|
||||
import SwiftUI
|
||||
|
||||
struct HomeView: View {
|
||||
|
||||
@EnvironmentObject var homeRouter: HomeCoordinator.Router
|
||||
@StateObject var viewModel = HomeViewModel()
|
||||
|
||||
private let refreshHelper = RefreshHelper()
|
||||
|
||||
@ViewBuilder
|
||||
var innerBody: some View {
|
||||
@ -28,33 +31,40 @@ struct HomeView: View {
|
||||
if !viewModel.nextUpItems.isEmpty {
|
||||
NextUpView(items: viewModel.nextUpItems)
|
||||
}
|
||||
if !viewModel.librariesShowRecentlyAddedIDs.isEmpty {
|
||||
ForEach(viewModel.librariesShowRecentlyAddedIDs, id: \.self) { libraryID in
|
||||
let library = viewModel.libraries.first(where: { $0.id == libraryID })
|
||||
HStack {
|
||||
Text("Latest \(library?.name ?? "")")
|
||||
.font(.title2)
|
||||
.fontWeight(.bold)
|
||||
Spacer()
|
||||
Button {
|
||||
homeRouter
|
||||
.route(to: \.library, (viewModel: .init(parentID: libraryID,
|
||||
filters: viewModel.recentFilterSet),
|
||||
title: library?.name ?? ""))
|
||||
} label: {
|
||||
HStack {
|
||||
Text("See All").font(.subheadline).fontWeight(.bold)
|
||||
Image(systemName: "chevron.right").font(Font.subheadline.bold())
|
||||
}
|
||||
|
||||
ForEach(viewModel.libraries, id: \.self) { library in
|
||||
HStack {
|
||||
Text("Latest \(library.name ?? "")")
|
||||
.font(.title2)
|
||||
.fontWeight(.bold)
|
||||
Spacer()
|
||||
Button {
|
||||
homeRouter
|
||||
.route(to: \.library, (viewModel: .init(parentID: library.id!,
|
||||
filters: viewModel.recentFilterSet),
|
||||
title: library.name ?? ""))
|
||||
} label: {
|
||||
HStack {
|
||||
Text("See All").font(.subheadline).fontWeight(.bold)
|
||||
Image(systemName: "chevron.right").font(Font.subheadline.bold())
|
||||
}
|
||||
}.padding(.leading, 16)
|
||||
.padding(.trailing, 16)
|
||||
LatestMediaView(viewModel: .init(libraryID: libraryID))
|
||||
}
|
||||
}
|
||||
}.padding(.leading, 16)
|
||||
.padding(.trailing, 16)
|
||||
LatestMediaView(viewModel: .init(libraryID: library.id!))
|
||||
}
|
||||
}
|
||||
.padding(.bottom, UIDevice.current.userInterfaceIdiom == .phone ? 20 : 30)
|
||||
}
|
||||
.introspectScrollView { scrollView in
|
||||
let control = UIRefreshControl()
|
||||
|
||||
refreshHelper.refreshControl = control
|
||||
refreshHelper.refreshAction = viewModel.refresh
|
||||
|
||||
control.addTarget(refreshHelper, action: #selector(RefreshHelper.didRefresh), for: .valueChanged)
|
||||
scrollView.refreshControl = control
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
16
Shared/Objects/HTTPScheme.swift
Normal file
16
Shared/Objects/HTTPScheme.swift
Normal file
@ -0,0 +1,16 @@
|
||||
//
|
||||
/*
|
||||
* SwiftFin is subject to the terms of the Mozilla Public
|
||||
* License, v2.0. If a copy of the MPL was not distributed with this
|
||||
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 2021 Aiden Vigue & Jellyfin Contributors
|
||||
*/
|
||||
|
||||
import Defaults
|
||||
import Foundation
|
||||
|
||||
enum HTTPScheme: String, Defaults.Serializable, CaseIterable {
|
||||
case http
|
||||
case https
|
||||
}
|
@ -37,7 +37,7 @@ public class ServerDiscovery {
|
||||
if let port = components?.port {
|
||||
return port
|
||||
}
|
||||
return 8096
|
||||
return 7359
|
||||
}
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
|
@ -54,10 +54,14 @@ final class SessionManager {
|
||||
|
||||
// Connects to a server at the given uri, storing if successful
|
||||
func connectToServer(with uri: String) -> AnyPublisher<SwiftfinStore.State.Server, Error> {
|
||||
var uri = uri
|
||||
if !uri.contains("http") {
|
||||
uri = "https://" + uri
|
||||
var uriComponents = URLComponents(string: uri) ?? URLComponents()
|
||||
|
||||
if uriComponents.scheme == nil {
|
||||
uriComponents.scheme = SwiftfinStore.Defaults.suite[.defaultHTTPScheme].rawValue
|
||||
}
|
||||
|
||||
var uri = uriComponents.string ?? ""
|
||||
|
||||
if uri.last == "/" {
|
||||
uri = String(uri.dropLast())
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ extension SwiftfinStore {
|
||||
extension Defaults.Keys {
|
||||
static let lastServerUserID = Defaults.Key<String?>("lastServerUserID", suite: SwiftfinStore.Defaults.suite)
|
||||
|
||||
static let defaultHTTPScheme = Key<HTTPScheme>("defaultHTTPScheme", default: .http, suite: SwiftfinStore.Defaults.suite)
|
||||
static let inNetworkBandwidth = Key<Int>("InNetworkBandwidth", default: 40_000_000, suite: SwiftfinStore.Defaults.suite)
|
||||
static let outOfNetworkBandwidth = Key<Int>("OutOfNetworkBandwidth", default: 40_000_000, suite: SwiftfinStore.Defaults.suite)
|
||||
static let isAutoSelectSubtitles = Key<Bool>("isAutoSelectSubtitles", default: false, suite: SwiftfinStore.Defaults.suite)
|
||||
|
@ -14,10 +14,10 @@ import JellyfinAPI
|
||||
|
||||
final class HomeViewModel: ViewModel {
|
||||
|
||||
@Published var librariesShowRecentlyAddedIDs = [String]()
|
||||
@Published var libraries = [BaseItemDto]()
|
||||
@Published var resumeItems = [BaseItemDto]()
|
||||
@Published var nextUpItems = [BaseItemDto]()
|
||||
@Published var librariesShowRecentlyAddedIDs: [String] = []
|
||||
@Published var libraries: [BaseItemDto] = []
|
||||
@Published var resumeItems: [BaseItemDto] = []
|
||||
@Published var nextUpItems: [BaseItemDto] = []
|
||||
|
||||
// temp
|
||||
var recentFilterSet: LibraryFilters = LibraryFilters(filters: [], sortOrder: [.descending], sortBy: [.dateAdded])
|
||||
@ -32,26 +32,42 @@ final class HomeViewModel: ViewModel {
|
||||
UserViewsAPI.getUserViews(userId: SessionManager.main.currentLogin.user.id)
|
||||
.trackActivity(loading)
|
||||
.sink(receiveCompletion: { completion in
|
||||
self.handleAPIRequestError(completion: completion)
|
||||
switch completion {
|
||||
case .finished: ()
|
||||
case .failure(_):
|
||||
self.libraries = []
|
||||
self.handleAPIRequestError(completion: completion)
|
||||
}
|
||||
}, receiveValue: { response in
|
||||
|
||||
var newLibraries: [BaseItemDto] = []
|
||||
|
||||
response.items!.forEach { item in
|
||||
LogManager.shared.log.debug("Retrieved user view: \(item.id!) (\(item.name ?? "nil")) with type \(item.collectionType ?? "nil")")
|
||||
if item.collectionType == "movies" || item.collectionType == "tvshows" {
|
||||
self.libraries.append(item)
|
||||
newLibraries.append(item)
|
||||
}
|
||||
}
|
||||
|
||||
UserAPI.getCurrentUser()
|
||||
.trackActivity(self.loading)
|
||||
.sink(receiveCompletion: { completion in
|
||||
self.handleAPIRequestError(completion: completion)
|
||||
switch completion {
|
||||
case .finished: ()
|
||||
case .failure(_):
|
||||
self.libraries = []
|
||||
self.handleAPIRequestError(completion: completion)
|
||||
}
|
||||
}, receiveValue: { response in
|
||||
self.libraries.forEach { library in
|
||||
if !(response.configuration?.latestItemsExcludes?.contains(library.id!))! {
|
||||
LogManager.shared.log.debug("Adding library \(library.id!) (\(library.name ?? "nil")) to recently added list")
|
||||
self.librariesShowRecentlyAddedIDs.append(library.id!)
|
||||
let excludeIDs = response.configuration?.latestItemsExcludes != nil ? response.configuration!.latestItemsExcludes! : []
|
||||
|
||||
for excludeID in excludeIDs {
|
||||
newLibraries.removeAll { library in
|
||||
return library.id == excludeID
|
||||
}
|
||||
}
|
||||
|
||||
self.libraries = newLibraries
|
||||
})
|
||||
.store(in: &self.cancellables)
|
||||
})
|
||||
@ -59,12 +75,20 @@ final class HomeViewModel: ViewModel {
|
||||
|
||||
ItemsAPI.getResumeItems(userId: SessionManager.main.currentLogin.user.id, limit: 12,
|
||||
fields: [.primaryImageAspectRatio, .seriesPrimaryImage, .seasonUserData, .overview, .genres, .people],
|
||||
mediaTypes: ["Video"], imageTypeLimit: 1, enableImageTypes: [.primary, .backdrop, .thumb])
|
||||
mediaTypes: ["Video"],
|
||||
imageTypeLimit: 1,
|
||||
enableImageTypes: [.primary, .backdrop, .thumb])
|
||||
.trackActivity(loading)
|
||||
.sink(receiveCompletion: { completion in
|
||||
self.handleAPIRequestError(completion: completion)
|
||||
switch completion {
|
||||
case .finished: ()
|
||||
case .failure(_):
|
||||
self.resumeItems = []
|
||||
self.handleAPIRequestError(completion: completion)
|
||||
}
|
||||
}, receiveValue: { response in
|
||||
LogManager.shared.log.debug("Retrieved \(String(response.items!.count)) resume items")
|
||||
|
||||
self.resumeItems = response.items ?? []
|
||||
})
|
||||
.store(in: &cancellables)
|
||||
@ -73,9 +97,15 @@ final class HomeViewModel: ViewModel {
|
||||
fields: [.primaryImageAspectRatio, .seriesPrimaryImage, .seasonUserData, .overview, .genres, .people])
|
||||
.trackActivity(loading)
|
||||
.sink(receiveCompletion: { completion in
|
||||
self.handleAPIRequestError(completion: completion)
|
||||
switch completion {
|
||||
case .finished: ()
|
||||
case .failure(_):
|
||||
self.nextUpItems = []
|
||||
self.handleAPIRequestError(completion: completion)
|
||||
}
|
||||
}, receiveValue: { response in
|
||||
LogManager.shared.log.debug("Retrieved \(String(response.items!.count)) nextup items")
|
||||
|
||||
self.nextUpItems = response.items ?? []
|
||||
})
|
||||
.store(in: &cancellables)
|
||||
|
BIN
Translations/ar.lproj/Localizable.strings
Normal file
BIN
Translations/ar.lproj/Localizable.strings
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Translations/eo.lproj/Localizable.strings
Normal file
BIN
Translations/eo.lproj/Localizable.strings
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user