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