add LibraryListViewModel
This commit is contained in:
parent
ed224da0a4
commit
4dae6bc00e
|
@ -45,6 +45,7 @@
|
||||||
6213388E265F777C00A81A2A /* LibraryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6213388D265F777C00A81A2A /* LibraryViewModel.swift */; };
|
6213388E265F777C00A81A2A /* LibraryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6213388D265F777C00A81A2A /* LibraryViewModel.swift */; };
|
||||||
62133890265F83A900A81A2A /* LibraryListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6213388F265F83A900A81A2A /* LibraryListView.swift */; };
|
62133890265F83A900A81A2A /* LibraryListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6213388F265F83A900A81A2A /* LibraryListView.swift */; };
|
||||||
621338932660107500A81A2A /* String++.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621338922660107500A81A2A /* String++.swift */; };
|
621338932660107500A81A2A /* String++.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621338922660107500A81A2A /* String++.swift */; };
|
||||||
|
62133895266096EF00A81A2A /* LibraryListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62133894266096EF00A81A2A /* LibraryListViewModel.swift */; };
|
||||||
6273DD43265F4195009C1D0B /* Moya in Frameworks */ = {isa = PBXBuildFile; productRef = 6273DD42265F4195009C1D0B /* Moya */; };
|
6273DD43265F4195009C1D0B /* Moya in Frameworks */ = {isa = PBXBuildFile; productRef = 6273DD42265F4195009C1D0B /* Moya */; };
|
||||||
6273DD45265F4195009C1D0B /* CombineMoya in Frameworks */ = {isa = PBXBuildFile; productRef = 6273DD44265F4195009C1D0B /* CombineMoya */; };
|
6273DD45265F4195009C1D0B /* CombineMoya in Frameworks */ = {isa = PBXBuildFile; productRef = 6273DD44265F4195009C1D0B /* CombineMoya */; };
|
||||||
6273DD48265F41B3009C1D0B /* JellyfinAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6273DD47265F41B3009C1D0B /* JellyfinAPI.swift */; };
|
6273DD48265F41B3009C1D0B /* JellyfinAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6273DD47265F41B3009C1D0B /* JellyfinAPI.swift */; };
|
||||||
|
@ -112,6 +113,7 @@
|
||||||
6213388D265F777C00A81A2A /* LibraryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibraryViewModel.swift; sourceTree = "<group>"; };
|
6213388D265F777C00A81A2A /* LibraryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibraryViewModel.swift; sourceTree = "<group>"; };
|
||||||
6213388F265F83A900A81A2A /* LibraryListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibraryListView.swift; sourceTree = "<group>"; };
|
6213388F265F83A900A81A2A /* LibraryListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibraryListView.swift; sourceTree = "<group>"; };
|
||||||
621338922660107500A81A2A /* String++.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String++.swift"; sourceTree = "<group>"; };
|
621338922660107500A81A2A /* String++.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String++.swift"; sourceTree = "<group>"; };
|
||||||
|
62133894266096EF00A81A2A /* LibraryListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibraryListViewModel.swift; sourceTree = "<group>"; };
|
||||||
6273DD47265F41B3009C1D0B /* JellyfinAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JellyfinAPI.swift; sourceTree = "<group>"; };
|
6273DD47265F41B3009C1D0B /* JellyfinAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JellyfinAPI.swift; sourceTree = "<group>"; };
|
||||||
6273DD4D265F47B2009C1D0B /* LibrarySearchViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibrarySearchViewModel.swift; sourceTree = "<group>"; };
|
6273DD4D265F47B2009C1D0B /* LibrarySearchViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibrarySearchViewModel.swift; sourceTree = "<group>"; };
|
||||||
AE8C3153265D60BF008AA076 /* SettingsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsModel.swift; sourceTree = "<group>"; };
|
AE8C3153265D60BF008AA076 /* SettingsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsModel.swift; sourceTree = "<group>"; };
|
||||||
|
@ -224,6 +226,7 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
6213388D265F777C00A81A2A /* LibraryViewModel.swift */,
|
6213388D265F777C00A81A2A /* LibraryViewModel.swift */,
|
||||||
|
62133894266096EF00A81A2A /* LibraryListViewModel.swift */,
|
||||||
);
|
);
|
||||||
path = ViewModels;
|
path = ViewModels;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -417,6 +420,7 @@
|
||||||
53E4E649263F725B00F67C6B /* MultiSelector.swift in Sources */,
|
53E4E649263F725B00F67C6B /* MultiSelector.swift in Sources */,
|
||||||
53E4E647263F6CF100F67C6B /* LibraryFilterView.swift in Sources */,
|
53E4E647263F6CF100F67C6B /* LibraryFilterView.swift in Sources */,
|
||||||
6213388E265F777C00A81A2A /* LibraryViewModel.swift in Sources */,
|
6213388E265F777C00A81A2A /* LibraryViewModel.swift in Sources */,
|
||||||
|
62133895266096EF00A81A2A /* LibraryListViewModel.swift in Sources */,
|
||||||
6273DD48265F41B3009C1D0B /* JellyfinAPI.swift in Sources */,
|
6273DD48265F41B3009C1D0B /* JellyfinAPI.swift in Sources */,
|
||||||
53892777263CBB000035E14B /* JellyApiTypings.swift in Sources */,
|
53892777263CBB000035E14B /* JellyApiTypings.swift in Sources */,
|
||||||
5377CBF7263B596A003A4E83 /* ContentView.swift in Sources */,
|
5377CBF7263B596A003A4E83 /* ContentView.swift in Sources */,
|
||||||
|
|
|
@ -8,78 +8,98 @@
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
import KeychainSwift
|
import KeychainSwift
|
||||||
import SwiftyRequest
|
|
||||||
import SwiftyJSON
|
|
||||||
import Sentry
|
|
||||||
import SDWebImageSwiftUI
|
import SDWebImageSwiftUI
|
||||||
|
import Sentry
|
||||||
|
import SwiftyJSON
|
||||||
|
import SwiftyRequest
|
||||||
|
|
||||||
struct ContentView: View {
|
struct ContentView: View {
|
||||||
@Environment(\.managedObjectContext) private var viewContext
|
@Environment(\.managedObjectContext)
|
||||||
@EnvironmentObject var orientationInfo: OrientationInfo
|
private var viewContext
|
||||||
@StateObject private var globalData = GlobalData()
|
@EnvironmentObject
|
||||||
@EnvironmentObject var jsi: justSignedIn
|
var orientationInfo: OrientationInfo
|
||||||
|
@StateObject
|
||||||
|
private var globalData = GlobalData()
|
||||||
|
@EnvironmentObject
|
||||||
|
var jsi: justSignedIn
|
||||||
|
|
||||||
@FetchRequest(entity: Server.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Server.name, ascending: true)]) private var servers: FetchedResults<Server>
|
@FetchRequest(entity: Server.entity(),
|
||||||
|
sortDescriptors: [NSSortDescriptor(keyPath: \Server.name, ascending: true)])
|
||||||
@FetchRequest(entity: SignedInUser.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \SignedInUser.username, ascending: true)]) private var savedUsers: FetchedResults<SignedInUser>
|
private var servers: FetchedResults<Server>
|
||||||
|
|
||||||
@State private var needsToSelectServer = false;
|
@FetchRequest(entity: SignedInUser.entity(),
|
||||||
@State private var isSignInErrored = false;
|
sortDescriptors: [NSSortDescriptor(keyPath: \SignedInUser.username,
|
||||||
@State private var isNetworkErrored = false;
|
ascending: true)])
|
||||||
@State private var isLoading = false;
|
private var savedUsers: FetchedResults<SignedInUser>
|
||||||
@State private var tabSelection: String = "Home";
|
|
||||||
@State private var libraries: [String] = [];
|
@State
|
||||||
@State private var library_names: [String: String] = [:];
|
private var needsToSelectServer = false
|
||||||
@State private var librariesShowRecentlyAdded: [String] = [];
|
@State
|
||||||
@State private var libraryPrefillID: String = "";
|
private var isSignInErrored = false
|
||||||
@State private var showSettingsPopover: Bool = false;
|
@State
|
||||||
@State private var viewDidLoad: Bool = false;
|
private var isNetworkErrored = false
|
||||||
|
@State
|
||||||
|
private var isLoading = false
|
||||||
|
@State
|
||||||
|
private var tabSelection: String = "Home"
|
||||||
|
@State
|
||||||
|
private var libraries: [String] = []
|
||||||
|
@State
|
||||||
|
private var library_names: [String: String] = [:]
|
||||||
|
@State
|
||||||
|
private var librariesShowRecentlyAdded: [String] = []
|
||||||
|
@State
|
||||||
|
private var libraryPrefillID: String = ""
|
||||||
|
@State
|
||||||
|
private var showSettingsPopover: Bool = false
|
||||||
|
@State
|
||||||
|
private var viewDidLoad: Bool = false
|
||||||
|
|
||||||
func startup() {
|
func startup() {
|
||||||
let size = UIScreen.main.bounds.size
|
let size = UIScreen.main.bounds.size
|
||||||
if size.width < size.height {
|
if size.width < size.height {
|
||||||
orientationInfo.orientation = .portrait;
|
orientationInfo.orientation = .portrait
|
||||||
} else {
|
} else {
|
||||||
orientationInfo.orientation = .landscape;
|
orientationInfo.orientation = .landscape
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_viewDidLoad.wrappedValue) {
|
if _viewDidLoad.wrappedValue {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_viewDidLoad.wrappedValue = true;
|
_viewDidLoad.wrappedValue = true
|
||||||
SentrySDK.start { options in
|
SentrySDK.start { options in
|
||||||
options.dsn = "https://75ac77d6af4d406eb989f3d8ef0f119f@o513670.ingest.sentry.io/5778242"
|
options.dsn = "https://75ac77d6af4d406eb989f3d8ef0f119f@o513670.ingest.sentry.io/5778242"
|
||||||
options.debug = false // Enabled debug when first installing is always helpful
|
options.debug = false // Enabled debug when first installing is always helpful
|
||||||
options.tracesSampleRate = 1.0
|
options.tracesSampleRate = 1.0
|
||||||
options.releaseName = "ios-" + (Bundle.main.infoDictionary?["CFBundleVersion"] as! String);
|
options.releaseName = "ios-" + (Bundle.main.infoDictionary?["CFBundleVersion"] as! String)
|
||||||
options.enableOutOfMemoryTracking = true
|
options.enableOutOfMemoryTracking = true
|
||||||
}
|
}
|
||||||
|
|
||||||
let cache = SDImageCache(namespace: "tiny")
|
let cache = SDImageCache(namespace: "tiny")
|
||||||
cache.config.maxMemoryCost = 125 * 1024 * 1024 // 125MB memory
|
cache.config.maxMemoryCost = 125 * 1024 * 1024 // 125MB memory
|
||||||
cache.config.maxDiskSize = 1000 * 1024 * 1024 // 1000MB disk
|
cache.config.maxDiskSize = 1000 * 1024 * 1024 // 1000MB disk
|
||||||
SDImageCachesManager.shared.addCache(cache)
|
SDImageCachesManager.shared.addCache(cache)
|
||||||
SDWebImageManager.defaultImageCache = SDImageCachesManager.shared
|
SDWebImageManager.defaultImageCache = SDImageCachesManager.shared
|
||||||
|
|
||||||
_libraries.wrappedValue = []
|
_libraries.wrappedValue = []
|
||||||
_library_names.wrappedValue = [:]
|
_library_names.wrappedValue = [:]
|
||||||
_librariesShowRecentlyAdded.wrappedValue = []
|
_librariesShowRecentlyAdded.wrappedValue = []
|
||||||
if(servers.isEmpty) {
|
if servers.isEmpty {
|
||||||
_isLoading.wrappedValue = false;
|
_isLoading.wrappedValue = false
|
||||||
_needsToSelectServer.wrappedValue = true;
|
_needsToSelectServer.wrappedValue = true
|
||||||
} else {
|
} else {
|
||||||
_isLoading.wrappedValue = true;
|
_isLoading.wrappedValue = true
|
||||||
let savedUser = savedUsers[0];
|
let savedUser = savedUsers[0]
|
||||||
|
|
||||||
let keychain = KeychainSwift();
|
let keychain = KeychainSwift()
|
||||||
if(keychain.get("AccessToken_\(savedUser.user_id ?? "")") != nil) {
|
if keychain.get("AccessToken_\(savedUser.user_id ?? "")") != nil {
|
||||||
_globalData.wrappedValue.authToken = keychain.get("AccessToken_\(savedUser.user_id ?? "")") ?? ""
|
_globalData.wrappedValue.authToken = keychain.get("AccessToken_\(savedUser.user_id ?? "")") ?? ""
|
||||||
_globalData.wrappedValue.server = servers[0]
|
_globalData.wrappedValue.server = servers[0]
|
||||||
_globalData.wrappedValue.user = savedUser
|
_globalData.wrappedValue.user = savedUser
|
||||||
}
|
}
|
||||||
|
|
||||||
let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String;
|
let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
|
||||||
var header = "MediaBrowser "
|
var header = "MediaBrowser "
|
||||||
header.append("Client=\"SwiftFin\",")
|
header.append("Client=\"SwiftFin\",")
|
||||||
header.append("Device=\"\(UIDevice.current.name.removeRegexMatches(pattern: "[^\\w\\s]"))\",")
|
header.append("Device=\"\(UIDevice.current.name.removeRegexMatches(pattern: "[^\\w\\s]"))\",")
|
||||||
|
@ -87,48 +107,50 @@ struct ContentView: View {
|
||||||
header.append("Version=\"\(appVersion ?? "0.0.1")\",")
|
header.append("Version=\"\(appVersion ?? "0.0.1")\",")
|
||||||
header.append("Token=\"\(globalData.authToken)\"")
|
header.append("Token=\"\(globalData.authToken)\"")
|
||||||
globalData.authHeader = header
|
globalData.authHeader = header
|
||||||
|
|
||||||
let request = RestRequest(method: .get, url: (globalData.server?.baseURI ?? "") + "/Users/Me")
|
let request = RestRequest(method: .get, url: (globalData.server?.baseURI ?? "") + "/Users/Me")
|
||||||
request.headerParameters["X-Emby-Authorization"] = globalData.authHeader
|
request.headerParameters["X-Emby-Authorization"] = globalData.authHeader
|
||||||
request.contentType = "application/json"
|
request.contentType = "application/json"
|
||||||
request.acceptType = "application/json"
|
request.acceptType = "application/json"
|
||||||
|
|
||||||
request.responseData() { (result: Result<RestResponse<Data>, RestError>) in
|
request.responseData { (result: Result<RestResponse<Data>, RestError>) in
|
||||||
switch result {
|
switch result {
|
||||||
case .success( let resp):
|
case let .success(resp):
|
||||||
do {
|
do {
|
||||||
let json = try JSON(data: resp.body)
|
let json = try JSON(data: resp.body)
|
||||||
let array2 = json["Configuration"]["LatestItemsExcludes"].arrayObject as? [String] ?? []
|
let array2 = json["Configuration"]["LatestItemsExcludes"].arrayObject as? [String] ?? []
|
||||||
|
|
||||||
let request2 = RestRequest(method: .get, url: (globalData.server?.baseURI ?? "") + "/Users/\(globalData.user?.user_id ?? "")/Views")
|
let request2 = RestRequest(method: .get,
|
||||||
|
url: (globalData.server?.baseURI ?? "") +
|
||||||
|
"/Users/\(globalData.user?.user_id ?? "")/Views")
|
||||||
request2.headerParameters["X-Emby-Authorization"] = globalData.authHeader
|
request2.headerParameters["X-Emby-Authorization"] = globalData.authHeader
|
||||||
request2.contentType = "application/json"
|
request2.contentType = "application/json"
|
||||||
request2.acceptType = "application/json"
|
request2.acceptType = "application/json"
|
||||||
|
|
||||||
request2.responseData() { (result2: Result<RestResponse<Data>, RestError>) in
|
request2.responseData { (result2: Result<RestResponse<Data>, RestError>) in
|
||||||
switch result2 {
|
switch result2 {
|
||||||
case .success( let resp):
|
case let .success(resp):
|
||||||
do {
|
do {
|
||||||
let json2 = try JSON(data: resp.body)
|
let json2 = try JSON(data: resp.body)
|
||||||
for (_,item2):(String, JSON) in json2["Items"] {
|
for (_, item2): (String, JSON) in json2["Items"] {
|
||||||
_library_names.wrappedValue[item2["Id"].string ?? ""] = item2["Name"].string ?? ""
|
_library_names.wrappedValue[item2["Id"].string ?? ""] = item2["Name"].string ?? ""
|
||||||
}
|
}
|
||||||
|
|
||||||
for (_,item2):(String, JSON) in json2["Items"] {
|
for (_, item2): (String, JSON) in json2["Items"] {
|
||||||
if(item2["CollectionType"].string == "tvshows" || item2["CollectionType"].string == "movies") {
|
if item2["CollectionType"].string == "tvshows" || item2["CollectionType"].string == "movies" {
|
||||||
_libraries.wrappedValue.append(item2["Id"].string ?? "")
|
_libraries.wrappedValue.append(item2["Id"].string ?? "")
|
||||||
_librariesShowRecentlyAdded.wrappedValue.append(item2["Id"].string ?? "")
|
_librariesShowRecentlyAdded.wrappedValue.append(item2["Id"].string ?? "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_librariesShowRecentlyAdded.wrappedValue = _libraries.wrappedValue.filter { element in
|
_librariesShowRecentlyAdded.wrappedValue = _libraries.wrappedValue.filter { element in
|
||||||
return !array2.contains(element)
|
!array2.contains(element)
|
||||||
}
|
}
|
||||||
|
|
||||||
_libraries.wrappedValue.forEach { library in
|
_libraries.wrappedValue.forEach { library in
|
||||||
if(_library_names.wrappedValue[library] == nil) {
|
if _library_names.wrappedValue[library] == nil {
|
||||||
_libraries.wrappedValue.removeAll { ele in
|
_libraries.wrappedValue.removeAll { ele in
|
||||||
if(library == ele) {
|
if library == ele {
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
|
@ -136,39 +158,32 @@ struct ContentView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dump(_libraries.wrappedValue)
|
dump(_libraries.wrappedValue)
|
||||||
dump(_librariesShowRecentlyAdded.wrappedValue)
|
dump(_librariesShowRecentlyAdded.wrappedValue)
|
||||||
dump(_library_names.wrappedValue)
|
dump(_library_names.wrappedValue)
|
||||||
} catch {
|
} catch {}
|
||||||
|
case let .failure(error):
|
||||||
}
|
|
||||||
break
|
|
||||||
case .failure(let error):
|
|
||||||
SentrySDK.capture(error: error)
|
SentrySDK.capture(error: error)
|
||||||
break
|
|
||||||
}
|
}
|
||||||
let defaults = UserDefaults.standard;
|
let defaults = UserDefaults.standard
|
||||||
if(defaults.integer(forKey: "InNetworkBandwidth") == 0) {
|
if defaults.integer(forKey: "InNetworkBandwidth") == 0 {
|
||||||
defaults.setValue(40000000, forKey: "InNetworkBandwidth")
|
defaults.setValue(40_000_000, forKey: "InNetworkBandwidth")
|
||||||
}
|
}
|
||||||
if(defaults.integer(forKey: "OutOfNetworkBandwidth") == 0) {
|
if defaults.integer(forKey: "OutOfNetworkBandwidth") == 0 {
|
||||||
defaults.setValue(40000000, forKey: "OutOfNetworkBandwidth")
|
defaults.setValue(40_000_000, forKey: "OutOfNetworkBandwidth")
|
||||||
}
|
}
|
||||||
_isLoading.wrappedValue = false;
|
_isLoading.wrappedValue = false
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {}
|
||||||
|
case let .failure(error):
|
||||||
}
|
if error.response?.status.code == 401 {
|
||||||
break
|
_isLoading.wrappedValue = false
|
||||||
case .failure( let error):
|
_isSignInErrored.wrappedValue = true
|
||||||
if(error.response?.status.code == 401) {
|
|
||||||
_isLoading.wrappedValue = false;
|
|
||||||
_isSignInErrored.wrappedValue = true;
|
|
||||||
} else {
|
} else {
|
||||||
SentrySDK.capture(error: error)
|
SentrySDK.capture(error: error)
|
||||||
_isLoading.wrappedValue = false;
|
_isLoading.wrappedValue = false
|
||||||
_isNetworkErrored.wrappedValue = true;
|
_isNetworkErrored.wrappedValue = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,34 +191,37 @@ struct ContentView: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
if(needsToSelectServer) {
|
if needsToSelectServer {
|
||||||
NavigationView() {
|
NavigationView {
|
||||||
ConnectToServerView(isActive: $needsToSelectServer)
|
ConnectToServerView(isActive: $needsToSelectServer)
|
||||||
}
|
}
|
||||||
.navigationViewStyle(StackNavigationViewStyle())
|
.navigationViewStyle(StackNavigationViewStyle())
|
||||||
.environmentObject(globalData)
|
.environmentObject(globalData)
|
||||||
} else if(isSignInErrored) {
|
} else if isSignInErrored {
|
||||||
NavigationView() {
|
NavigationView {
|
||||||
ConnectToServerView(skip_server: true, skip_server_prefill: globalData.server, reauth_deviceId: globalData.user?.device_uuid ?? "", isActive: $isSignInErrored)
|
ConnectToServerView(skip_server: true, skip_server_prefill: globalData.server,
|
||||||
|
reauth_deviceId: globalData.user?.device_uuid ?? "", isActive: $isSignInErrored)
|
||||||
}
|
}
|
||||||
.navigationViewStyle(StackNavigationViewStyle())
|
.navigationViewStyle(StackNavigationViewStyle())
|
||||||
.environmentObject(globalData)
|
.environmentObject(globalData)
|
||||||
} else {
|
} else {
|
||||||
if(!jsi.did) {
|
if !jsi.did {
|
||||||
LoadingView(isShowing: $isLoading) {
|
LoadingView(isShowing: $isLoading) {
|
||||||
TabView(selection: $tabSelection) {
|
TabView(selection: $tabSelection) {
|
||||||
NavigationView() {
|
NavigationView {
|
||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
ScrollView() {
|
ScrollView {
|
||||||
Spacer().frame(height: orientationInfo.orientation == .portrait ? 0 : 15)
|
Spacer().frame(height: orientationInfo.orientation == .portrait ? 0 : 15)
|
||||||
ContinueWatchingView()
|
ContinueWatchingView()
|
||||||
NextUpView().padding(EdgeInsets(top: 4, leading: 0, bottom: 0, trailing: 0))
|
NextUpView().padding(EdgeInsets(top: 4, leading: 0, bottom: 0, trailing: 0))
|
||||||
ForEach(librariesShowRecentlyAdded, id: \.self) { library_id in
|
ForEach(librariesShowRecentlyAdded, id: \.self) { library_id in
|
||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
HStack() {
|
HStack {
|
||||||
Text("Latest \(library_names[library_id] ?? "")").font(.title2).fontWeight(.bold).padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 16))
|
Text("Latest \(library_names[library_id] ?? "")").font(.title2).fontWeight(.bold)
|
||||||
|
.padding(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 16))
|
||||||
Spacer()
|
Spacer()
|
||||||
NavigationLink(destination: LibraryView(viewModel: .init(filter: Filter(parentID: library_id)), title: library_names[library_id] ?? "")) {
|
NavigationLink(destination: LibraryView(viewModel: .init(filter: Filter(parentID: library_id)),
|
||||||
|
title: library_names[library_id] ?? "")) {
|
||||||
Text("See All").font(.subheadline).fontWeight(.bold)
|
Text("See All").font(.subheadline).fontWeight(.bold)
|
||||||
}
|
}
|
||||||
}.padding(EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16))
|
}.padding(EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16))
|
||||||
|
@ -216,28 +234,31 @@ struct ContentView: View {
|
||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarItemGroup(placement: .navigationBarTrailing) {
|
ToolbarItemGroup(placement: .navigationBarTrailing) {
|
||||||
Button {
|
Button {
|
||||||
showSettingsPopover = true;
|
showSettingsPopover = true
|
||||||
} label: {
|
} label: {
|
||||||
Image(systemName: "gear")
|
Image(systemName: "gear")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.fullScreenCover( isPresented: $showSettingsPopover) { SettingsView(viewModel: SettingsViewModel(), close: $showSettingsPopover) }
|
}
|
||||||
|
.fullScreenCover(isPresented: $showSettingsPopover) {
|
||||||
|
SettingsView(viewModel: SettingsViewModel(), close: $showSettingsPopover)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationViewStyle(StackNavigationViewStyle())
|
.navigationViewStyle(StackNavigationViewStyle())
|
||||||
.tabItem({
|
.tabItem {
|
||||||
Text("Home")
|
Text("Home")
|
||||||
Image(systemName: "house")
|
Image(systemName: "house")
|
||||||
})
|
}
|
||||||
.tag("Home")
|
.tag("Home")
|
||||||
NavigationView {
|
NavigationView {
|
||||||
LibraryListView(libraryNames: library_names, libraryIDs: libraries)
|
LibraryListView(viewModel: .init(libraryNames: library_names, libraryIDs: libraries))
|
||||||
}
|
}
|
||||||
.navigationViewStyle(StackNavigationViewStyle())
|
.navigationViewStyle(StackNavigationViewStyle())
|
||||||
.tabItem({
|
.tabItem {
|
||||||
Text("All Media")
|
Text("All Media")
|
||||||
Image(systemName: "folder")
|
Image(systemName: "folder")
|
||||||
})
|
}
|
||||||
.tag("All Media")
|
.tag("All Media")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -248,13 +269,13 @@ struct ContentView: View {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Text("Signing in...")
|
Text("Signing in...")
|
||||||
.onAppear(perform: {
|
.onAppear(perform: {
|
||||||
DispatchQueue.main.async { [self] in
|
DispatchQueue.main.async { [self] in
|
||||||
_viewDidLoad.wrappedValue = false
|
_viewDidLoad.wrappedValue = false
|
||||||
usleep(500000);
|
usleep(500_000)
|
||||||
self.jsi.did = false;
|
self.jsi.did = false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
//
|
||||||
|
// LibraryListViewModel.swift
|
||||||
|
// JellyfinPlayer
|
||||||
|
//
|
||||||
|
// Created by PangMo5 on 2021/05/28.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Combine
|
||||||
|
import CombineMoya
|
||||||
|
import Foundation
|
||||||
|
import Moya
|
||||||
|
import SwiftyJSON
|
||||||
|
|
||||||
|
final class LibraryListViewModel: ObservableObject {
|
||||||
|
fileprivate var provider =
|
||||||
|
MoyaProvider<JellyfinAPI>(plugins: [NetworkLoggerPlugin()])
|
||||||
|
|
||||||
|
@Published
|
||||||
|
var libraryIDs = [String]()
|
||||||
|
@Published
|
||||||
|
var libraryNames = [String: String]()
|
||||||
|
|
||||||
|
fileprivate var cancellables = Set<AnyCancellable>()
|
||||||
|
|
||||||
|
init(libraryNames: [String: String], libraryIDs: [String]) {
|
||||||
|
self.libraryIDs = libraryIDs
|
||||||
|
self.libraryNames = libraryNames
|
||||||
|
refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
func refresh() {
|
||||||
|
libraryIDs.append("favorites")
|
||||||
|
libraryNames["favorites"] = "Favorites"
|
||||||
|
|
||||||
|
libraryIDs.append("genres")
|
||||||
|
libraryNames["genres"] = "Genres - WIP"
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,48 +13,26 @@ struct LibraryListView: View {
|
||||||
private var viewContext
|
private var viewContext
|
||||||
@EnvironmentObject
|
@EnvironmentObject
|
||||||
var globalData: GlobalData
|
var globalData: GlobalData
|
||||||
@State
|
@ObservedObject
|
||||||
private var libraryIDs: [String] = []
|
var viewModel: LibraryListViewModel
|
||||||
@State
|
|
||||||
private var libraryNames: [String: String] = [:]
|
|
||||||
@State
|
|
||||||
private var viewDidLoad: Bool = false
|
|
||||||
@State
|
|
||||||
private var closeSearch: Bool = false
|
|
||||||
|
|
||||||
init(libraryNames: [String: String], libraryIDs: [String]) {
|
|
||||||
self._libraryNames = State(initialValue: libraryNames)
|
|
||||||
self._libraryIDs = State(initialValue: libraryIDs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func listOnAppear() {
|
|
||||||
if viewDidLoad == false {
|
|
||||||
viewDidLoad = true
|
|
||||||
libraryIDs.append("favorites")
|
|
||||||
libraryNames["favorites"] = "Favorites"
|
|
||||||
|
|
||||||
libraryIDs.append("genres")
|
|
||||||
libraryNames["genres"] = "Genres - WIP"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
List(libraryIDs, id: \.self) { id in
|
List(viewModel.libraryIDs, id: \.self) { id in
|
||||||
switch id {
|
switch id {
|
||||||
case "favorites":
|
case "favorites":
|
||||||
NavigationLink(destination: LibraryView(viewModel: .init(filter: Filter(filterTypes: [.isFavorite])),
|
NavigationLink(destination: LibraryView(viewModel: .init(filter: Filter(filterTypes: [.isFavorite])),
|
||||||
title: libraryNames[id] ?? "")) {
|
title: viewModel.libraryNames[id] ?? "")) {
|
||||||
Text(libraryNames[id] ?? "").foregroundColor(Color.primary)
|
Text(viewModel.libraryNames[id] ?? "").foregroundColor(Color.primary)
|
||||||
}
|
}
|
||||||
case "genres":
|
case "genres":
|
||||||
Text(libraryNames[id] ?? "").foregroundColor(Color.primary)
|
Text(viewModel.libraryNames[id] ?? "").foregroundColor(Color.primary)
|
||||||
default:
|
default:
|
||||||
NavigationLink(destination: LibraryView(viewModel: .init(filter: Filter(parentID: id)), title: libraryNames[id] ?? "")) {
|
NavigationLink(destination: LibraryView(viewModel: .init(filter: Filter(parentID: id)),
|
||||||
Text(libraryNames[id] ?? "").foregroundColor(Color.primary)
|
title: viewModel.libraryNames[id] ?? "")) {
|
||||||
|
Text(viewModel.libraryNames[id] ?? "").foregroundColor(Color.primary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onAppear(perform: listOnAppear)
|
|
||||||
.navigationTitle("All Media")
|
.navigationTitle("All Media")
|
||||||
.navigationBarItems(trailing:
|
.navigationBarItems(trailing:
|
||||||
NavigationLink(destination: LibrarySearchView(viewModel: .init(filter: .init()))) {
|
NavigationLink(destination: LibrarySearchView(viewModel: .init(filter: .init()))) {
|
||||||
|
|
Loading…
Reference in New Issue