diff --git a/Shared/Coordinators/MainCoordinator/iOSMainCoordinator.swift b/Shared/Coordinators/MainCoordinator/iOSMainCoordinator.swift index 7db2b6eb..ec07d8e5 100644 --- a/Shared/Coordinators/MainCoordinator/iOSMainCoordinator.swift +++ b/Shared/Coordinators/MainCoordinator/iOSMainCoordinator.swift @@ -59,13 +59,13 @@ final class MainCoordinator: NavigationCoordinatable { @objc func didSignIn() { - LogManager.shared.log.info("Received `didSignIn` from SwiftfinNotificationCenter.") + LogManager.log.info("Received `didSignIn` from SwiftfinNotificationCenter.") root(\.mainTab) } @objc func didSignOut() { - LogManager.shared.log.info("Received `didSignOut` from SwiftfinNotificationCenter.") + LogManager.log.info("Received `didSignOut` from SwiftfinNotificationCenter.") root(\.serverList) } diff --git a/Shared/Coordinators/MainCoordinator/tvOSMainCoordinator.swift b/Shared/Coordinators/MainCoordinator/tvOSMainCoordinator.swift index 8e1d6390..3f7e48a9 100644 --- a/Shared/Coordinators/MainCoordinator/tvOSMainCoordinator.swift +++ b/Shared/Coordinators/MainCoordinator/tvOSMainCoordinator.swift @@ -46,13 +46,13 @@ final class MainCoordinator: NavigationCoordinatable { @objc func didSignIn() { - LogManager.shared.log.info("Received `didSignIn` from NSNotificationCenter.") + LogManager.log.info("Received `didSignIn` from NSNotificationCenter.") root(\.mainTab) } @objc func didSignOut() { - LogManager.shared.log.info("Received `didSignOut` from NSNotificationCenter.") + LogManager.log.info("Received `didSignOut` from NSNotificationCenter.") root(\.serverList) } diff --git a/Shared/Errors/ErrorMessage.swift b/Shared/Errors/ErrorMessage.swift index 38cb0d55..75b72f5b 100644 --- a/Shared/Errors/ErrorMessage.swift +++ b/Shared/Errors/ErrorMessage.swift @@ -13,22 +13,19 @@ struct ErrorMessage: Identifiable { let code: Int let title: String - let displayMessage: String - let logConstructor: LogConstructor + let message: String // Chosen value such that if an error has this code, don't show the code to the UI // This was chosen because of its unlikelyhood to ever be used static let noShowErrorCode = -69420 var id: String { - "\(code)\(title)\(logConstructor.message)" + "\(code)\(title)\(message)" } - /// If the custom displayMessage is `nil`, it will be set to the given logConstructor's message - init(code: Int, title: String, displayMessage: String?, logConstructor: LogConstructor) { + init(code: Int, title: String, message: String) { self.code = code self.title = title - self.displayMessage = displayMessage ?? logConstructor.message - self.logConstructor = logConstructor + self.message = message } } diff --git a/Shared/Errors/LogConstructor.swift b/Shared/Errors/LogConstructor.swift deleted file mode 100644 index cd59a3bb..00000000 --- a/Shared/Errors/LogConstructor.swift +++ /dev/null @@ -1,19 +0,0 @@ -// -// 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 (c) 2022 Jellyfin & Jellyfin Contributors -// - -import Foundation -import JellyfinAPI - -struct LogConstructor { - var message: String - let tag: String - let level: LogLevel - let function: String - let file: String - let line: UInt -} diff --git a/Shared/Errors/NetworkError.swift b/Shared/Errors/NetworkError.swift index b6cf2c73..7778f61a 100644 --- a/Shared/Errors/NetworkError.swift +++ b/Shared/Errors/NetworkError.swift @@ -9,127 +9,75 @@ import Foundation import JellyfinAPI -/** - The implementation of the network errors here are a temporary measure. - It is very repetitive, messy, and doesn't fulfill the entire specification of "error reporting". - - Needs to be replaced - */ - enum NetworkError: Error { /// For the case that the ErrorResponse object has a code of -1 - case URLError(response: ErrorResponse, displayMessage: String?, logConstructor: LogConstructor) + case URLError(response: ErrorResponse, displayMessage: String?) /// For the case that the ErrorRespones object has a code of -2 - case HTTPURLError(response: ErrorResponse, displayMessage: String?, logConstructor: LogConstructor) + case HTTPURLError(response: ErrorResponse, displayMessage: String?) /// For the case that the ErrorResponse object has a positive code - case JellyfinError(response: ErrorResponse, displayMessage: String?, logConstructor: LogConstructor) + case JellyfinError(response: ErrorResponse, displayMessage: String?) var errorMessage: ErrorMessage { switch self { - case let .URLError(response, displayMessage, logConstructor): - return NetworkError.parseURLError(from: response, displayMessage: displayMessage, logConstructor: logConstructor) - case let .HTTPURLError(response, displayMessage, logConstructor): - return NetworkError.parseHTTPURLError(from: response, displayMessage: displayMessage, logConstructor: logConstructor) - case let .JellyfinError(response, displayMessage, logConstructor): - return NetworkError.parseJellyfinError(from: response, displayMessage: displayMessage, logConstructor: logConstructor) + case let .URLError(response, displayMessage): + return NetworkError.parseURLError(from: response, displayMessage: displayMessage) + case let .HTTPURLError(response, displayMessage): + return NetworkError.parseHTTPURLError(from: response, displayMessage: displayMessage) + case let .JellyfinError(response, displayMessage): + return NetworkError.parseJellyfinError(from: response, displayMessage: displayMessage) } } - func logMessage() { - let logConstructor = errorMessage.logConstructor - let logFunction: (@autoclosure () -> String, String, String, String, UInt) -> Void - - switch logConstructor.level { - case .trace: - logFunction = LogManager.shared.log.trace - case .debug: - logFunction = LogManager.shared.log.debug - case .information: - logFunction = LogManager.shared.log.info - case .warning: - logFunction = LogManager.shared.log.warning - case .error: - logFunction = LogManager.shared.log.error - case .critical: - logFunction = LogManager.shared.log.critical - case ._none: - logFunction = LogManager.shared.log.debug - } - - logFunction(logConstructor.message, logConstructor.tag, logConstructor.function, logConstructor.file, logConstructor.line) - } - - private static func parseURLError(from response: ErrorResponse, displayMessage: String?, - logConstructor: LogConstructor) -> ErrorMessage - { - + private static func parseURLError(from response: ErrorResponse, displayMessage: String?) -> ErrorMessage { let errorMessage: ErrorMessage - var logMessage = L10n.unknownError - var logConstructor = logConstructor switch response { case let .error(_, _, _, err): - // These codes are currently referenced from: + // Code references: // https://developer.apple.com/documentation/foundation/1508628-url_loading_system_error_codes switch err._code { case -1001: - logMessage = L10n.networkTimedOut - logConstructor.message = logMessage errorMessage = ErrorMessage(code: err._code, title: L10n.error, - displayMessage: displayMessage, - logConstructor: logConstructor) + message: L10n.networkTimedOut) + case -1003: + errorMessage = ErrorMessage(code: err._code, + title: L10n.error, + message: L10n.unableToFindHost) case -1004: - logMessage = L10n.cannotConnectToHost - logConstructor.message = logMessage errorMessage = ErrorMessage(code: err._code, title: L10n.error, - displayMessage: displayMessage, - logConstructor: logConstructor) + message: L10n.cannotConnectToHost) default: - logConstructor.message = logMessage errorMessage = ErrorMessage(code: err._code, title: L10n.error, - displayMessage: displayMessage, - logConstructor: logConstructor) + message: L10n.unknownError) } } return errorMessage } - private static func parseHTTPURLError(from response: ErrorResponse, displayMessage: String?, - logConstructor: LogConstructor) -> ErrorMessage - { - + private static func parseHTTPURLError(from response: ErrorResponse, displayMessage: String?) -> ErrorMessage { let errorMessage: ErrorMessage - let logMessage = "An HTTP URL error has occurred" - var logConstructor = logConstructor // Not implemented as has not run into one of these errors as time of writing switch response { case .error: - logConstructor.message = logMessage errorMessage = ErrorMessage(code: 0, title: L10n.error, - displayMessage: displayMessage, - logConstructor: logConstructor) + message: "An HTTP URL error has occurred") } return errorMessage } - private static func parseJellyfinError(from response: ErrorResponse, displayMessage: String?, - logConstructor: LogConstructor) -> ErrorMessage - { - + private static func parseJellyfinError(from response: ErrorResponse, displayMessage: String?) -> ErrorMessage { let errorMessage: ErrorMessage - var logMessage = L10n.unknownError - var logConstructor = logConstructor switch response { case let .error(code, _, _, _): @@ -137,18 +85,13 @@ enum NetworkError: Error { // Generic HTTP status codes switch code { case 401: - logMessage = L10n.unauthorizedUser - logConstructor.message = logMessage errorMessage = ErrorMessage(code: code, title: L10n.unauthorized, - displayMessage: displayMessage, - logConstructor: logConstructor) + message: L10n.unauthorizedUser) default: - logConstructor.message = logMessage errorMessage = ErrorMessage(code: code, title: L10n.error, - displayMessage: displayMessage, - logConstructor: logConstructor) + message: L10n.unknownError) } } diff --git a/Shared/Extensions/JellyfinAPIExtensions/BaseItemDto+VideoPlayerViewModel.swift b/Shared/Extensions/JellyfinAPIExtensions/BaseItemDto+VideoPlayerViewModel.swift index 6df7c30c..34a0176b 100644 --- a/Shared/Extensions/JellyfinAPIExtensions/BaseItemDto+VideoPlayerViewModel.swift +++ b/Shared/Extensions/JellyfinAPIExtensions/BaseItemDto+VideoPlayerViewModel.swift @@ -14,7 +14,7 @@ import UIKit extension BaseItemDto { func createVideoPlayerViewModel() -> AnyPublisher<[VideoPlayerViewModel], Error> { - LogManager.shared.log.debug("Creating video player view model for item: \(id ?? "")") + LogManager.log.debug("Creating video player view model for item: \(id ?? "")") let builder = DeviceProfileBuilder() // TODO: fix bitrate settings @@ -169,7 +169,7 @@ extension BaseItemDto { func createLiveTVVideoPlayerViewModel() -> AnyPublisher<[VideoPlayerViewModel], Error> { - LogManager.shared.log.debug("Creating liveTV video player view model for item: \(id ?? "")") + LogManager.log.debug("Creating liveTV video player view model for item: \(id ?? "")") let builder = DeviceProfileBuilder() // TODO: fix bitrate settings diff --git a/Shared/Generated/Strings.swift b/Shared/Generated/Strings.swift index aab098bd..e022f597 100644 --- a/Shared/Generated/Strings.swift +++ b/Shared/Generated/Strings.swift @@ -392,6 +392,8 @@ internal enum L10n { internal static var tvShows: String { return L10n.tr("Localizable", "tvShows") } /// Unable to connect to server internal static var unableToConnectServer: String { return L10n.tr("Localizable", "unableToConnectServer") } + /// Unable to find host + internal static var unableToFindHost: String { return L10n.tr("Localizable", "unableToFindHost") } /// Unaired internal static var unaired: String { return L10n.tr("Localizable", "unaired") } /// Unauthorized diff --git a/Shared/ServerDiscovery/ServerDiscovery.swift b/Shared/ServerDiscovery/ServerDiscovery.swift index 81f6de75..2ee6122b 100644 --- a/Shared/ServerDiscovery/ServerDiscovery.swift +++ b/Shared/ServerDiscovery/ServerDiscovery.swift @@ -59,7 +59,7 @@ public class ServerDiscovery { func receiveHandler(_ ipAddress: String, _ port: Int, _ data: Data) { do { let response = try JSONDecoder().decode(ServerLookupResponse.self, from: data) - LogManager.shared.log.debug("Received JellyfinServer from \"\(response.name)\"", tag: "ServerDiscovery") + LogManager.log.debug("Received JellyfinServer from \"\(response.name)\"", tag: "ServerDiscovery") completion(response) } catch { completion(nil) @@ -68,7 +68,7 @@ public class ServerDiscovery { self.broadcastConn.handler = receiveHandler do { try broadcastConn.sendBroadcast("Who is JellyfinServer?") - LogManager.shared.log.debug("Discovery broadcast sent", tag: "ServerDiscovery") + LogManager.log.debug("Discovery broadcast sent", tag: "ServerDiscovery") } catch { print(error) } diff --git a/Shared/Singleton/LogManager.swift b/Shared/Singleton/LogManager.swift index de1af46b..9b3dbaca 100644 --- a/Shared/Singleton/LogManager.swift +++ b/Shared/Singleton/LogManager.swift @@ -10,33 +10,35 @@ import Foundation import Puppy class LogManager { - static let shared = LogManager() - let log = Puppy() - init() { - let console = ConsoleLogger("com.swiftfin.ConsoleLogger") - let fileURL = self.getDocumentsDirectory().appendingPathComponent("logs.txt") - let FM = FileManager() - _ = try? FM.removeItem(at: fileURL) + static let log = Puppy() + + static func setup() { + + let logsDirectory = getDocumentsDirectory().appendingPathComponent("logs", isDirectory: true) do { - let file = try FileLogger("com.swiftfin", fileURL: fileURL) - file.format = LogFormatter() - log.add(file, withLevel: .debug) - } catch let err { - log.error("Couldn't initialize file logger.") - print(err) + try FileManager.default.createDirectory(atPath: logsDirectory.path, + withIntermediateDirectories: true, + attributes: nil) + } catch { + // logs directory already created } - console.format = LogFormatter() - log.add(console, withLevel: .debug) - log.info("Logger initialized.") + + let logFileURL = logsDirectory.appendingPathComponent("swiftfin_log.log") + + let fileRotationLogger = try! FileRotationLogger("org.jellyfin.swiftfin.logger.file-rotation", + fileURL: logFileURL) + fileRotationLogger.format = LogFormatter() + + let consoleLogger = ConsoleLogger("org.jellyfin.swiftfin.logger.console") + consoleLogger.format = LogFormatter() + + log.add(fileRotationLogger, withLevel: .debug) + log.add(consoleLogger, withLevel: .debug) } - func logFileURL() -> URL { - self.getDocumentsDirectory().appendingPathComponent("logs.txt") - } - - func getDocumentsDirectory() -> URL { + private static func getDocumentsDirectory() -> URL { // find all possible documents directories for this user let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) diff --git a/Shared/Singleton/SessionManager.swift b/Shared/Singleton/SessionManager.swift index 2d3fffd2..5ee49bac 100644 --- a/Shared/Singleton/SessionManager.swift +++ b/Shared/Singleton/SessionManager.swift @@ -104,7 +104,7 @@ final class SessionManager { [Where("id == %@", newServer.id)]) { - throw SwiftfinStore.Errors.existingServer(existingServer.state) + throw SwiftfinStore.Error.existingServer(existingServer.state) } return (newServer, transaction) @@ -210,7 +210,7 @@ final class SessionManager { [Where("id == %@", newUser.id)]) { - throw SwiftfinStore.Errors.existingUser(existingUser.state) + throw SwiftfinStore.Error.existingUser(existingUser.state) } let newAccessToken = transaction.create(Into()) diff --git a/Shared/SwiftfinStore/SwiftfinStore.swift b/Shared/SwiftfinStore/SwiftfinStore.swift index f44b3ab2..578af623 100644 --- a/Shared/SwiftfinStore/SwiftfinStore.swift +++ b/Shared/SwiftfinStore/SwiftfinStore.swift @@ -147,9 +147,9 @@ enum SwiftfinStore { } } - // MARK: Errors + // MARK: Error - enum Errors { + enum Error { case existingServer(State.Server) case existingUser(State.User) } @@ -193,7 +193,7 @@ enum SwiftfinStore { // MARK: LocalizedError -extension SwiftfinStore.Errors: LocalizedError { +extension SwiftfinStore.Error: LocalizedError { var title: String { switch self { diff --git a/Shared/ViewModels/ConnectToServerViewModel.swift b/Shared/ViewModels/ConnectToServerViewModel.swift index 426b5a37..14d33e6a 100644 --- a/Shared/ViewModels/ConnectToServerViewModel.swift +++ b/Shared/ViewModels/ConnectToServerViewModel.swift @@ -48,14 +48,14 @@ final class ConnectToServerViewModel: ViewModel { #if targetEnvironment(simulator) var uri = uri - if uri == "localhost" { + if uri == "http://localhost" || uri == "localhost" { uri = "http://localhost:8096" } #endif let trimmedURI = uri.trimmingCharacters(in: .whitespaces) - LogManager.shared.log.debug("Attempting to connect to server at \"\(trimmedURI)\"", tag: "connectToServer") + LogManager.log.debug("Attempting to connect to server at \"\(trimmedURI)\"", tag: "connectToServer") SessionManager.main.connectToServer(with: trimmedURI) .trackActivity(loading) .sink(receiveCompletion: { completion in @@ -71,10 +71,7 @@ final class ConnectToServerViewModel: ViewModel { // a url in the response is the result if a redirect if let newURL = response?.url { if redirectCount > 2 { - self.handleAPIRequestError(displayMessage: L10n.tooManyRedirects, - logLevel: .critical, - tag: "connectToServer", - completion: completion) + self.handleAPIRequestError(displayMessage: L10n.tooManyRedirects, completion: completion) } else { self .connectToServer(uri: newURL.absoluteString @@ -85,25 +82,21 @@ final class ConnectToServerViewModel: ViewModel { self.handleAPIRequestError(completion: completion) } } - case is SwiftfinStore.Errors: - let swiftfinError = error as! SwiftfinStore.Errors + case is SwiftfinStore.Error: + let swiftfinError = error as! SwiftfinStore.Error switch swiftfinError { case let .existingServer(server): self.addServerURIPayload = AddServerURIPayload(server: server, uri: uri) self.backAddServerURIPayload = AddServerURIPayload(server: server, uri: uri) default: - self.handleAPIRequestError(displayMessage: L10n.unableToConnectServer, logLevel: .critical, - tag: "connectToServer", - completion: completion) + self.handleAPIRequestError(displayMessage: L10n.unableToConnectServer, completion: completion) } default: - self.handleAPIRequestError(displayMessage: L10n.unableToConnectServer, logLevel: .critical, - tag: "connectToServer", - completion: completion) + self.handleAPIRequestError(displayMessage: L10n.unableToConnectServer, completion: completion) } } }, receiveValue: { server in - LogManager.shared.log.debug("Connected to server at \"\(uri)\"", tag: "connectToServer") + LogManager.log.debug("Connected to server at \"\(uri)\"", tag: "connectToServer") self.router?.route(to: \.userSignIn, server) }) .store(in: &cancellables) @@ -128,14 +121,11 @@ final class ConnectToServerViewModel: ViewModel { func addURIToServer(addServerURIPayload: AddServerURIPayload) { SessionManager.main.addURIToServer(server: addServerURIPayload.server, uri: addServerURIPayload.uri) .sink { completion in - self.handleAPIRequestError(displayMessage: L10n.unableToConnectServer, logLevel: .critical, tag: "connectToServer", - completion: completion) + self.handleAPIRequestError(displayMessage: L10n.unableToConnectServer, completion: completion) } receiveValue: { server in SessionManager.main.setServerCurrentURI(server: server, uri: addServerURIPayload.uri) .sink { completion in - self.handleAPIRequestError(displayMessage: L10n.unableToConnectServer, logLevel: .critical, - tag: "connectToServer", - completion: completion) + self.handleAPIRequestError(displayMessage: L10n.unableToConnectServer, completion: completion) } receiveValue: { _ in self.router?.dismissCoordinator() } diff --git a/Shared/ViewModels/HomeViewModel.swift b/Shared/ViewModels/HomeViewModel.swift index 3d4dccba..617cd852 100644 --- a/Shared/ViewModels/HomeViewModel.swift +++ b/Shared/ViewModels/HomeViewModel.swift @@ -63,7 +63,7 @@ final class HomeViewModel: ViewModel { @objc func refresh() { - LogManager.shared.log.debug("Refresh called.") + LogManager.log.debug("Refresh called.") refreshLibrariesLatest() refreshLatestAddedItems() @@ -89,7 +89,7 @@ final class HomeViewModel: ViewModel { var newLibraries: [BaseItemDto] = [] response.items!.forEach { item in - LogManager.shared.log + LogManager.log .debug("Retrieved user view: \(item.id!) (\(item.name ?? "nil")) with type \(item.collectionType ?? "nil")") if item.collectionType == "movies" || item.collectionType == "tvshows" { newLibraries.append(item) @@ -147,7 +147,7 @@ final class HomeViewModel: ViewModel { self.handleAPIRequestError(completion: completion) } } receiveValue: { items in - LogManager.shared.log.debug("Retrieved \(String(items.count)) resume items") + LogManager.log.debug("Retrieved \(String(items.count)) resume items") self.latestAddedItems = items } @@ -178,7 +178,7 @@ final class HomeViewModel: ViewModel { self.handleAPIRequestError(completion: completion) } }, receiveValue: { response in - LogManager.shared.log.debug("Retrieved \(String(response.items!.count)) resume items") + LogManager.log.debug("Retrieved \(String(response.items!.count)) resume items") self.resumeItems = response.items ?? [] }) @@ -223,7 +223,7 @@ final class HomeViewModel: ViewModel { self.handleAPIRequestError(completion: completion) } }, receiveValue: { response in - LogManager.shared.log.debug("Retrieved \(String(response.items!.count)) nextup items") + LogManager.log.debug("Retrieved \(String(response.items!.count)) nextup items") self.nextUpItems = response.items ?? [] }) diff --git a/Shared/ViewModels/ItemViewModel/SeasonItemViewModel.swift b/Shared/ViewModels/ItemViewModel/SeasonItemViewModel.swift index edb9fb87..3c2da092 100644 --- a/Shared/ViewModels/ItemViewModel/SeasonItemViewModel.swift +++ b/Shared/ViewModels/ItemViewModel/SeasonItemViewModel.swift @@ -44,7 +44,7 @@ final class SeasonItemViewModel: ItemViewModel, EpisodesRowManager { } private func requestEpisodes() { - LogManager.shared.log + LogManager.log .debug("Getting episodes in season \(item.id!) (\(item.name!)) of show \(item.seriesId!) (\(item.seriesName!))") TvShowsAPI.getEpisodes(seriesId: item.seriesId ?? "", userId: SessionManager.main.currentLogin.user.id, fields: [.primaryImageAspectRatio, .seriesPrimaryImage, .seasonUserData, .overview, .genres, .people], @@ -55,7 +55,7 @@ final class SeasonItemViewModel: ItemViewModel, EpisodesRowManager { }, receiveValue: { [weak self] response in guard let self = self else { return } self.episodes = response.items ?? [] - LogManager.shared.log.debug("Retrieved \(String(self.episodes.count)) episodes") + LogManager.log.debug("Retrieved \(String(self.episodes.count)) episodes") self.setNextUpInSeason() }) @@ -78,7 +78,7 @@ final class SeasonItemViewModel: ItemViewModel, EpisodesRowManager { !episode.unaired && !episode.missing && episode.seasonId ?? "" == self.item.id! }) { self.playButtonItem = nextUpItem - LogManager.shared.log.debug("Nextup in season \(self.item.id!) (\(self.item.name!)): \(nextUpItem.id!)") + LogManager.log.debug("Nextup in season \(self.item.id!) (\(self.item.name!)): \(nextUpItem.id!)") } if self.playButtonItem == nil && !self.episodes.isEmpty { diff --git a/Shared/ViewModels/ItemViewModel/SeriesItemViewModel.swift b/Shared/ViewModels/ItemViewModel/SeriesItemViewModel.swift index 05dfb4e8..55ac91ea 100644 --- a/Shared/ViewModels/ItemViewModel/SeriesItemViewModel.swift +++ b/Shared/ViewModels/ItemViewModel/SeriesItemViewModel.swift @@ -43,7 +43,7 @@ final class SeriesItemViewModel: ItemViewModel { private func getNextUp() { - LogManager.shared.log.debug("Getting next up for show \(self.item.id!) (\(self.item.name!))") + LogManager.log.debug("Getting next up for show \(self.item.id!) (\(self.item.name!))") TvShowsAPI.getNextUp(userId: SessionManager.main.currentLogin.user.id, fields: [.primaryImageAspectRatio, .seriesPrimaryImage, .seasonUserData, .overview, .genres, .people], seriesId: self.item.id!, @@ -78,7 +78,7 @@ final class SeriesItemViewModel: ItemViewModel { } private func requestSeasons() { - LogManager.shared.log.debug("Getting seasons of show \(self.item.id!) (\(self.item.name!))") + LogManager.log.debug("Getting seasons of show \(self.item.id!) (\(self.item.name!))") TvShowsAPI.getSeasons(seriesId: item.id ?? "", userId: SessionManager.main.currentLogin.user.id, fields: [.primaryImageAspectRatio, .seriesPrimaryImage, .seasonUserData, .overview, .genres, .people], isMissing: Defaults[.shouldShowMissingSeasons] ? nil : false, @@ -88,7 +88,7 @@ final class SeriesItemViewModel: ItemViewModel { self?.handleAPIRequestError(completion: completion) }, receiveValue: { [weak self] response in self?.seasons = response.items ?? [] - LogManager.shared.log.debug("Retrieved \(String(self?.seasons.count ?? 0)) seasons") + LogManager.log.debug("Retrieved \(String(self?.seasons.count ?? 0)) seasons") }) .store(in: &cancellables) } diff --git a/Shared/ViewModels/LatestMediaViewModel.swift b/Shared/ViewModels/LatestMediaViewModel.swift index aac3cbf1..85012299 100644 --- a/Shared/ViewModels/LatestMediaViewModel.swift +++ b/Shared/ViewModels/LatestMediaViewModel.swift @@ -25,7 +25,7 @@ final class LatestMediaViewModel: ViewModel { } func requestLatestMedia() { - LogManager.shared.log.debug("Requesting latest media for user id \(SessionManager.main.currentLogin.user.id)") + LogManager.log.debug("Requesting latest media for user id \(SessionManager.main.currentLogin.user.id)") UserLibraryAPI.getLatestMedia(userId: SessionManager.main.currentLogin.user.id, parentId: library.id ?? "", fields: [ @@ -43,7 +43,7 @@ final class LatestMediaViewModel: ViewModel { self?.handleAPIRequestError(completion: completion) }, receiveValue: { [weak self] response in self?.items = response - LogManager.shared.log.debug("Retrieved \(String(self?.items.count ?? 0)) items") + LogManager.log.debug("Retrieved \(String(self?.items.count ?? 0)) items") }) .store(in: &cancellables) } diff --git a/Shared/ViewModels/LiveTVChannelsViewModel.swift b/Shared/ViewModels/LiveTVChannelsViewModel.swift index e425af55..ef59115f 100644 --- a/Shared/ViewModels/LiveTVChannelsViewModel.swift +++ b/Shared/ViewModels/LiveTVChannelsViewModel.swift @@ -68,7 +68,7 @@ final class LiveTVChannelsViewModel: ViewModel { .sink(receiveCompletion: { [weak self] completion in self?.handleAPIRequestError(completion: completion) }, receiveValue: { [weak self] _ in - LogManager.shared.log.debug("Received Guide Info") + LogManager.log.debug("Received Guide Info") guard let self = self else { return } self.getChannels() }) @@ -86,7 +86,7 @@ final class LiveTVChannelsViewModel: ViewModel { .sink(receiveCompletion: { [weak self] completion in self?.handleAPIRequestError(completion: completion) }, receiveValue: { [weak self] response in - LogManager.shared.log.debug("Received \(response.items?.count ?? 0) Channels") + LogManager.log.debug("Received \(response.items?.count ?? 0) Channels") guard let self = self else { return } self.channels = response.items ?? [] self.getPrograms() @@ -97,7 +97,7 @@ final class LiveTVChannelsViewModel: ViewModel { private func getPrograms() { // http://192.168.1.50:8096/LiveTv/Programs guard !channels.isEmpty else { - LogManager.shared.log.debug("Cannot get programs, channels list empty. ") + LogManager.log.debug("Cannot get programs, channels list empty. ") return } let channelIds = channels.compactMap(\.id) @@ -121,7 +121,7 @@ final class LiveTVChannelsViewModel: ViewModel { .sink(receiveCompletion: { [weak self] completion in self?.handleAPIRequestError(completion: completion) }, receiveValue: { [weak self] response in - LogManager.shared.log.debug("Received \(response.items?.count ?? 0) Programs") + LogManager.log.debug("Received \(response.items?.count ?? 0) Programs") guard let self = self else { return } self.programs = response.items ?? [] self.channelPrograms = self.processChannelPrograms() @@ -173,7 +173,7 @@ final class LiveTVChannelsViewModel: ViewModel { } timer = Timer(fire: nextMinute, interval: 60 * 10, repeats: true) { [weak self] _ in guard let self = self else { return } - LogManager.shared.log.debug("LiveTVChannels schedule check...") + LogManager.log.debug("LiveTVChannels schedule check...") DispatchQueue.global(qos: .background).async { let newChanPrgs = self.processChannelPrograms() DispatchQueue.main.async { diff --git a/Shared/ViewModels/LiveTVProgramsViewModel.swift b/Shared/ViewModels/LiveTVProgramsViewModel.swift index 8c64a9f6..09e88b67 100644 --- a/Shared/ViewModels/LiveTVProgramsViewModel.swift +++ b/Shared/ViewModels/LiveTVProgramsViewModel.swift @@ -47,7 +47,7 @@ final class LiveTVProgramsViewModel: ViewModel { .sink(receiveCompletion: { [weak self] completion in self?.handleAPIRequestError(completion: completion) }, receiveValue: { [weak self] response in - LogManager.shared.log.debug("Received \(response.items?.count ?? 0) Channels") + LogManager.log.debug("Received \(response.items?.count ?? 0) Channels") guard let self = self else { return } if let chans = response.items { for chan in chans { @@ -78,7 +78,7 @@ final class LiveTVProgramsViewModel: ViewModel { .sink(receiveCompletion: { [weak self] completion in self?.handleAPIRequestError(completion: completion) }, receiveValue: { [weak self] response in - LogManager.shared.log.debug("Received \(String(response.items?.count ?? 0)) Recommended Programs") + LogManager.log.debug("Received \(String(response.items?.count ?? 0)) Recommended Programs") guard let self = self else { return } self.recommendedItems = response.items ?? [] }) @@ -103,7 +103,7 @@ final class LiveTVProgramsViewModel: ViewModel { .sink(receiveCompletion: { [weak self] completion in self?.handleAPIRequestError(completion: completion) }, receiveValue: { [weak self] response in - LogManager.shared.log.debug("Received \(String(response.items?.count ?? 0)) Series Items") + LogManager.log.debug("Received \(String(response.items?.count ?? 0)) Series Items") guard let self = self else { return } self.seriesItems = response.items ?? [] }) @@ -128,7 +128,7 @@ final class LiveTVProgramsViewModel: ViewModel { .sink(receiveCompletion: { [weak self] completion in self?.handleAPIRequestError(completion: completion) }, receiveValue: { [weak self] response in - LogManager.shared.log.debug("Received \(String(response.items?.count ?? 0)) Movie Items") + LogManager.log.debug("Received \(String(response.items?.count ?? 0)) Movie Items") guard let self = self else { return } self.movieItems = response.items ?? [] }) @@ -149,7 +149,7 @@ final class LiveTVProgramsViewModel: ViewModel { .sink(receiveCompletion: { [weak self] completion in self?.handleAPIRequestError(completion: completion) }, receiveValue: { [weak self] response in - LogManager.shared.log.debug("Received \(String(response.items?.count ?? 0)) Sports Items") + LogManager.log.debug("Received \(String(response.items?.count ?? 0)) Sports Items") guard let self = self else { return } self.sportsItems = response.items ?? [] }) @@ -170,7 +170,7 @@ final class LiveTVProgramsViewModel: ViewModel { .sink(receiveCompletion: { [weak self] completion in self?.handleAPIRequestError(completion: completion) }, receiveValue: { [weak self] response in - LogManager.shared.log.debug("Received \(String(response.items?.count ?? 0)) Kids Items") + LogManager.log.debug("Received \(String(response.items?.count ?? 0)) Kids Items") guard let self = self else { return } self.kidsItems = response.items ?? [] }) @@ -191,7 +191,7 @@ final class LiveTVProgramsViewModel: ViewModel { .sink(receiveCompletion: { [weak self] completion in self?.handleAPIRequestError(completion: completion) }, receiveValue: { [weak self] response in - LogManager.shared.log.debug("Received \(String(response.items?.count ?? 0)) News Items") + LogManager.log.debug("Received \(String(response.items?.count ?? 0)) News Items") guard let self = self else { return } self.newsItems = response.items ?? [] }) diff --git a/Shared/ViewModels/SettingsViewModel.swift b/Shared/ViewModels/SettingsViewModel.swift index 92a6d6bd..a88a23ca 100644 --- a/Shared/ViewModels/SettingsViewModel.swift +++ b/Shared/ViewModels/SettingsViewModel.swift @@ -31,10 +31,10 @@ final class SettingsViewModel: ObservableObject { do { self.bitrates = try JSONDecoder().decode([Bitrates].self, from: jsonData) } catch { - LogManager.shared.log.error("Error converting processed JSON into Swift compatible schema.") + LogManager.log.error("Error converting processed JSON into Swift compatible schema.") } } catch { - LogManager.shared.log.error("Error processing JSON file `bitrates.json`") + LogManager.log.error("Error processing JSON file `bitrates.json`") } // Track languages diff --git a/Shared/ViewModels/UserSignInViewModel.swift b/Shared/ViewModels/UserSignInViewModel.swift index fbe5d501..a9b154dc 100644 --- a/Shared/ViewModels/UserSignInViewModel.swift +++ b/Shared/ViewModels/UserSignInViewModel.swift @@ -30,14 +30,12 @@ final class UserSignInViewModel: ViewModel { } func login(username: String, password: String) { - LogManager.shared.log.debug("Attempting to login to server at \"\(server.currentURI)\"", tag: "login") - LogManager.shared.log.debug("username: \(username), password: \(password)", tag: "login") + LogManager.log.debug("Attempting to login to server at \"\(server.currentURI)\"", tag: "login") SessionManager.main.loginUser(server: server, username: username, password: password) .trackActivity(loading) .sink { completion in - self.handleAPIRequestError(displayMessage: L10n.unableToConnectServer, logLevel: .critical, tag: "login", - completion: completion) + self.handleAPIRequestError(displayMessage: L10n.unableToConnectServer, completion: completion) } receiveValue: { _ in } .store(in: &cancellables) diff --git a/Shared/ViewModels/VideoPlayerViewModel/VideoPlayerViewModel.swift b/Shared/ViewModels/VideoPlayerViewModel/VideoPlayerViewModel.swift index db64d182..f65d15ed 100644 --- a/Shared/ViewModels/VideoPlayerViewModel/VideoPlayerViewModel.swift +++ b/Shared/ViewModels/VideoPlayerViewModel/VideoPlayerViewModel.swift @@ -482,7 +482,7 @@ extension VideoPlayerViewModel { .sink { completion in self.handleAPIRequestError(completion: completion) } receiveValue: { _ in - LogManager.shared.log.debug("Start report sent for item: \(self.item.id ?? "No ID")") + LogManager.log.debug("Start report sent for item: \(self.item.id ?? "No ID")") } .store(in: &cancellables) } @@ -518,7 +518,7 @@ extension VideoPlayerViewModel { .sink { completion in self.handleAPIRequestError(completion: completion) } receiveValue: { _ in - LogManager.shared.log.debug("Pause report sent for item: \(self.item.id ?? "No ID")") + LogManager.log.debug("Pause report sent for item: \(self.item.id ?? "No ID")") } .store(in: &cancellables) } @@ -563,7 +563,7 @@ extension VideoPlayerViewModel { .sink { completion in self.handleAPIRequestError(completion: completion) } receiveValue: { _ in - LogManager.shared.log.debug("Playback progress sent for item: \(self.item.id ?? "No ID")") + LogManager.log.debug("Playback progress sent for item: \(self.item.id ?? "No ID")") } .store(in: &cancellables) @@ -590,7 +590,7 @@ extension VideoPlayerViewModel { .sink { completion in self.handleAPIRequestError(completion: completion) } receiveValue: { _ in - LogManager.shared.log.debug("Stop report sent for item: \(self.item.id ?? "No ID")") + LogManager.log.debug("Stop report sent for item: \(self.item.id ?? "No ID")") Notifications[.didSendStopReport].post(object: self.item.id) } .store(in: &cancellables) diff --git a/Shared/ViewModels/ViewModel.swift b/Shared/ViewModels/ViewModel.swift index 8531106e..f96488cd 100644 --- a/Shared/ViewModels/ViewModel.swift +++ b/Shared/ViewModels/ViewModel.swift @@ -25,57 +25,49 @@ class ViewModel: ObservableObject { loading.loading.assign(to: \.isLoading, on: self).store(in: &cancellables) } - func handleAPIRequestError(displayMessage: String? = nil, logLevel: LogLevel = .error, tag: String = "", function: String = #function, - file: String = #file, line: UInt = #line, completion: Subscribers.Completion) - { + func handleAPIRequestError(displayMessage: String? = nil, completion: Subscribers.Completion) { switch completion { case .finished: self.errorMessage = nil case let .failure(error): - let logConstructor = LogConstructor(message: "__NOTHING__", tag: tag, level: logLevel, function: function, file: file, - line: line) - switch error { case is ErrorResponse: let networkError: NetworkError let errorResponse = error as! ErrorResponse + switch errorResponse { case .error(-1, _, _, _): - networkError = .URLError(response: errorResponse, displayMessage: displayMessage, logConstructor: logConstructor) + networkError = .URLError(response: errorResponse, displayMessage: displayMessage) // Use the errorResponse description for debugging, rather than the user-facing friendly description which may not be implemented - LogManager.shared.log + LogManager.log .error("Request failed: URL request failed with error \(networkError.errorMessage.code): \(errorResponse.localizedDescription)") case .error(-2, _, _, _): - networkError = .HTTPURLError(response: errorResponse, displayMessage: displayMessage, logConstructor: logConstructor) - LogManager.shared.log + networkError = .HTTPURLError(response: errorResponse, displayMessage: displayMessage) + LogManager.log .error("Request failed: HTTP URL request failed with description: \(errorResponse.localizedDescription)") default: - networkError = .JellyfinError(response: errorResponse, displayMessage: displayMessage, logConstructor: logConstructor) + networkError = .JellyfinError(response: errorResponse, displayMessage: displayMessage) // Able to use user-facing friendly description here since just HTTP status codes - LogManager.shared.log - .error("Request failed: \(networkError.errorMessage.code) - \(networkError.errorMessage.title): \(networkError.errorMessage.logConstructor.message)\n\(error.localizedDescription)") + LogManager.log + .error("Request failed: \(networkError.errorMessage.code) - \(networkError.errorMessage.title): \(networkError.errorMessage.message)\n\(error.localizedDescription)") } self.errorMessage = networkError.errorMessage - networkError.logMessage() - - case is SwiftfinStore.Errors: - let swiftfinError = error as! SwiftfinStore.Errors + case is SwiftfinStore.Error: + let swiftfinError = error as! SwiftfinStore.Error let errorMessage = ErrorMessage(code: ErrorMessage.noShowErrorCode, title: swiftfinError.title, - displayMessage: swiftfinError.errorDescription ?? "", - logConstructor: logConstructor) + message: swiftfinError.errorDescription ?? "") self.errorMessage = errorMessage - LogManager.shared.log.error("Request failed: \(swiftfinError.errorDescription ?? "")") + LogManager.log.error("Request failed: \(swiftfinError.errorDescription ?? "")") default: let genericErrorMessage = ErrorMessage(code: ErrorMessage.noShowErrorCode, title: "Generic Error", - displayMessage: error.localizedDescription, - logConstructor: logConstructor) + message: error.localizedDescription) self.errorMessage = genericErrorMessage - LogManager.shared.log.error("Request failed: Generic error - \(error.localizedDescription)") + LogManager.log.error("Request failed: Generic error - \(error.localizedDescription)") } } } diff --git a/Swiftfin tvOS/Views/ConnectToServerView.swift b/Swiftfin tvOS/Views/ConnectToServerView.swift index 26da99c7..690777bd 100644 --- a/Swiftfin tvOS/Views/ConnectToServerView.swift +++ b/Swiftfin tvOS/Views/ConnectToServerView.swift @@ -77,7 +77,7 @@ struct ConnectToServerView: View { } .alert(item: $viewModel.errorMessage) { _ in Alert(title: Text(viewModel.alertTitle), - message: Text(viewModel.errorMessage?.displayMessage ?? L10n.unknownError), + message: Text(viewModel.errorMessage?.message ?? L10n.unknownError), dismissButton: .cancel()) } .navigationTitle(L10n.connect) diff --git a/Swiftfin tvOS/Views/ItemView/CinematicItemView/CinematicItemViewTopRow.swift b/Swiftfin tvOS/Views/ItemView/CinematicItemView/CinematicItemViewTopRow.swift index f3c3da8f..38099a00 100644 --- a/Swiftfin tvOS/Views/ItemView/CinematicItemView/CinematicItemViewTopRow.swift +++ b/Swiftfin tvOS/Views/ItemView/CinematicItemView/CinematicItemViewTopRow.swift @@ -62,7 +62,7 @@ struct CinematicItemViewTopRow: View { if let selectedVideoPlayerViewModel = viewModel.selectedVideoPlayerViewModel { itemRouter.route(to: \.videoPlayer, selectedVideoPlayerViewModel) } else { - LogManager.shared.log.error("Attempted to play item but no playback information available") + LogManager.log.error("Attempted to play item but no playback information available") } } label: { HStack(spacing: 15) { @@ -85,7 +85,7 @@ struct CinematicItemViewTopRow: View { selectedVideoPlayerViewModel.injectCustomValues(startFromBeginning: true) itemRouter.route(to: \.videoPlayer, selectedVideoPlayerViewModel) } else { - LogManager.shared.log.error("Attempted to play item but no playback information available") + LogManager.log.error("Attempted to play item but no playback information available") } } label: { Label(L10n.playFromBeginning, systemImage: "gobackward") diff --git a/Swiftfin tvOS/Views/UserSignInView.swift b/Swiftfin tvOS/Views/UserSignInView.swift index 739599a5..b779f7bb 100644 --- a/Swiftfin tvOS/Views/UserSignInView.swift +++ b/Swiftfin tvOS/Views/UserSignInView.swift @@ -49,7 +49,7 @@ struct UserSignInView: View { } .alert(item: $viewModel.errorMessage) { _ in Alert(title: Text(viewModel.alertTitle), - message: Text(viewModel.errorMessage?.displayMessage ?? L10n.unknownError), + message: Text(viewModel.errorMessage?.message ?? L10n.unknownError), dismissButton: .cancel()) } .navigationTitle(L10n.signIn) diff --git a/Swiftfin tvOS/Views/VideoPlayer/LiveTVPlayerViewController.swift b/Swiftfin tvOS/Views/VideoPlayer/LiveTVPlayerViewController.swift index e726e723..0878a873 100644 --- a/Swiftfin tvOS/Views/VideoPlayer/LiveTVPlayerViewController.swift +++ b/Swiftfin tvOS/Views/VideoPlayer/LiveTVPlayerViewController.swift @@ -464,11 +464,11 @@ extension LiveTVPlayerViewController { viewModel = newViewModel if viewModel.streamType == .direct { - LogManager.shared.log.debug("Player set up with direct play stream for item: \(viewModel.item.id ?? "--")") + LogManager.log.debug("Player set up with direct play stream for item: \(viewModel.item.id ?? "--")") } else if viewModel.streamType == .transcode && Defaults[.Experimental.forceDirectPlay] { - LogManager.shared.log.debug("Player set up with forced direct stream for item: \(viewModel.item.id ?? "--")") + LogManager.log.debug("Player set up with forced direct stream for item: \(viewModel.item.id ?? "--")") } else { - LogManager.shared.log.debug("Player set up with transcoded stream for item: \(viewModel.item.id ?? "--")") + LogManager.log.debug("Player set up with transcoded stream for item: \(viewModel.item.id ?? "--")") } } diff --git a/Swiftfin tvOS/Views/VideoPlayer/VLCPlayerViewController.swift b/Swiftfin tvOS/Views/VideoPlayer/VLCPlayerViewController.swift index 36382579..64c7d643 100644 --- a/Swiftfin tvOS/Views/VideoPlayer/VLCPlayerViewController.swift +++ b/Swiftfin tvOS/Views/VideoPlayer/VLCPlayerViewController.swift @@ -464,11 +464,11 @@ extension VLCPlayerViewController { viewModel = newViewModel if viewModel.streamType == .direct { - LogManager.shared.log.debug("Player set up with direct play stream for item: \(viewModel.item.id ?? "--")") + LogManager.log.debug("Player set up with direct play stream for item: \(viewModel.item.id ?? "--")") } else if viewModel.streamType == .transcode && Defaults[.Experimental.forceDirectPlay] { - LogManager.shared.log.debug("Player set up with forced direct stream for item: \(viewModel.item.id ?? "--")") + LogManager.log.debug("Player set up with forced direct stream for item: \(viewModel.item.id ?? "--")") } else { - LogManager.shared.log.debug("Player set up with transcoded stream for item: \(viewModel.item.id ?? "--")") + LogManager.log.debug("Player set up with transcoded stream for item: \(viewModel.item.id ?? "--")") } } diff --git a/Swiftfin.xcodeproj/project.pbxproj b/Swiftfin.xcodeproj/project.pbxproj index e37de740..537b1932 100644 --- a/Swiftfin.xcodeproj/project.pbxproj +++ b/Swiftfin.xcodeproj/project.pbxproj @@ -53,12 +53,9 @@ 535870AA2669D8AE00D05A09 /* BlurHashDecode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5389277B263CC3DB0035E14B /* BlurHashDecode.swift */; }; 535870AD2669D8DD00D05A09 /* Typings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 535870AC2669D8DD00D05A09 /* Typings.swift */; }; 535BAE9F2649E569005FA86D /* ItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 535BAE9E2649E569005FA86D /* ItemView.swift */; }; - 53649AAD269CFAEA00A2D8B7 /* Puppy in Frameworks */ = {isa = PBXBuildFile; productRef = 53649AAC269CFAEA00A2D8B7 /* Puppy */; }; - 53649AAF269CFAF600A2D8B7 /* Puppy in Frameworks */ = {isa = PBXBuildFile; productRef = 53649AAE269CFAF600A2D8B7 /* Puppy */; }; 53649AB1269CFB1900A2D8B7 /* LogManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53649AB0269CFB1900A2D8B7 /* LogManager.swift */; }; 53649AB2269D019100A2D8B7 /* LogManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53649AB0269CFB1900A2D8B7 /* LogManager.swift */; }; 53649AB3269D3F5B00A2D8B7 /* LogManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53649AB0269CFB1900A2D8B7 /* LogManager.swift */; }; - 53649AB5269D423A00A2D8B7 /* Puppy in Frameworks */ = {isa = PBXBuildFile; productRef = 53649AB4269D423A00A2D8B7 /* Puppy */; }; 5364F455266CA0DC0026ECBA /* BaseItemPersonExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5364F454266CA0DC0026ECBA /* BaseItemPersonExtensions.swift */; }; 5364F456266CA0DC0026ECBA /* BaseItemPersonExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5364F454266CA0DC0026ECBA /* BaseItemPersonExtensions.swift */; }; 536D3D74267BA8170004248C /* BackgroundManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 536D3D73267BA8170004248C /* BackgroundManager.swift */; }; @@ -316,6 +313,7 @@ E10EAA51277BBCC4000269ED /* CGSizeExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E10EAA4E277BBCC4000269ED /* CGSizeExtensions.swift */; }; E10EAA53277BBD17000269ED /* BaseItemDto+VideoPlayerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E10EAA52277BBD17000269ED /* BaseItemDto+VideoPlayerViewModel.swift */; }; E10EAA54277BBD17000269ED /* BaseItemDto+VideoPlayerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E10EAA52277BBD17000269ED /* BaseItemDto+VideoPlayerViewModel.swift */; }; + E1101177281B1E8A006A3584 /* Puppy in Frameworks */ = {isa = PBXBuildFile; productRef = E1101176281B1E8A006A3584 /* Puppy */; }; E111DE222790BB46008118A3 /* DetectBottomScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E111DE212790BB46008118A3 /* DetectBottomScrollView.swift */; }; E11B1B6C2718CD68006DA3E8 /* JellyfinAPIError.swift in Sources */ = {isa = PBXBuildFile; fileRef = E11B1B6B2718CD68006DA3E8 /* JellyfinAPIError.swift */; }; E11B1B6D2718CD68006DA3E8 /* JellyfinAPIError.swift in Sources */ = {isa = PBXBuildFile; fileRef = E11B1B6B2718CD68006DA3E8 /* JellyfinAPIError.swift */; }; @@ -330,9 +328,9 @@ E1267D3E271A1F46003C492E /* PreferenceUIHostingController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1267D3D271A1F46003C492E /* PreferenceUIHostingController.swift */; }; E126F741278A656C00A522BF /* ServerStreamType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E126F740278A656C00A522BF /* ServerStreamType.swift */; }; E126F742278A656C00A522BF /* ServerStreamType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E126F740278A656C00A522BF /* ServerStreamType.swift */; }; - E131691726C583BC0074BFEE /* LogConstructor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E131691626C583BC0074BFEE /* LogConstructor.swift */; }; - E131691826C583BC0074BFEE /* LogConstructor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E131691626C583BC0074BFEE /* LogConstructor.swift */; }; - E131691926C583BC0074BFEE /* LogConstructor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E131691626C583BC0074BFEE /* LogConstructor.swift */; }; + E1347DB2279E3C6200BC6161 /* Puppy in Frameworks */ = {isa = PBXBuildFile; productRef = E1347DB1279E3C6200BC6161 /* Puppy */; }; + E1347DB4279E3C9E00BC6161 /* Puppy in Frameworks */ = {isa = PBXBuildFile; productRef = E1347DB3279E3C9E00BC6161 /* Puppy */; }; + E1347DB6279E3CA500BC6161 /* Puppy in Frameworks */ = {isa = PBXBuildFile; productRef = E1347DB5279E3CA500BC6161 /* Puppy */; }; E1361DA7278FA7A300BEC523 /* NukeUI in Frameworks */ = {isa = PBXBuildFile; productRef = E1361DA6278FA7A300BEC523 /* NukeUI */; }; E1384944278036C70024FB48 /* VLCPlayerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1384943278036C70024FB48 /* VLCPlayerViewController.swift */; }; E13849452780370B0024FB48 /* PlaybackSpeed.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1C812B4277A8E5D00918266 /* PlaybackSpeed.swift */; }; @@ -782,7 +780,6 @@ E122A9122788EAAD0060FA63 /* MediaStreamExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaStreamExtension.swift; sourceTree = ""; }; E1267D3D271A1F46003C492E /* PreferenceUIHostingController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferenceUIHostingController.swift; sourceTree = ""; }; E126F740278A656C00A522BF /* ServerStreamType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerStreamType.swift; sourceTree = ""; }; - E131691626C583BC0074BFEE /* LogConstructor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogConstructor.swift; sourceTree = ""; }; E1384943278036C70024FB48 /* VLCPlayerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VLCPlayerViewController.swift; sourceTree = ""; }; E13AD72D2798BC8D00FDCEE8 /* NativePlayerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativePlayerViewController.swift; sourceTree = ""; }; E13AD72F2798C60F00FDCEE8 /* NativePlayerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativePlayerViewController.swift; sourceTree = ""; }; @@ -894,7 +891,6 @@ buildActionMask = 2147483647; files = ( 62666E1727E501CC00EC0ECD /* CFNetwork.framework in Frameworks */, - 53649AAF269CFAF600A2D8B7 /* Puppy in Frameworks */, E11D83AF278FA998006E9776 /* NukeUI in Frameworks */, 62666DFA27E5013700EC0ECD /* TVVLCKit.xcframework in Frameworks */, 62666E3227E5021E00EC0ECD /* UIKit.framework in Frameworks */, @@ -921,6 +917,7 @@ E1AE8E7E2789136D00FBDDAA /* Nuke in Frameworks */, E178857D278037FD0094FBCF /* JellyfinAPI in Frameworks */, E12186DE2718F1C50010884C /* Defaults in Frameworks */, + E1347DB6279E3CA500BC6161 /* Puppy in Frameworks */, 53ABFDED26799D7700886593 /* ActivityIndicator in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -932,8 +929,8 @@ 62666E3E27E503FA00EC0ECD /* MediaAccessibility.framework in Frameworks */, 62666DFF27E5016400EC0ECD /* CFNetwork.framework in Frameworks */, E13DD3D327168E65009D4DAF /* Defaults in Frameworks */, + E1101177281B1E8A006A3584 /* Puppy in Frameworks */, E1361DA7278FA7A300BEC523 /* NukeUI in Frameworks */, - 53649AAD269CFAEA00A2D8B7 /* Puppy in Frameworks */, E1002B682793CFBA00E47059 /* Algorithms in Frameworks */, 62666E1127E501B900EC0ECD /* UIKit.framework in Frameworks */, 62666DF727E5012C00EC0ECD /* MobileVLCKit.xcframework in Frameworks */, @@ -961,6 +958,7 @@ 625CB57A2678C4A400530A6E /* ActivityIndicator in Frameworks */, 62666E3927E502CE00EC0ECD /* SwizzleSwift in Frameworks */, E1B6DCE8271A23780015B715 /* CombineExt in Frameworks */, + E1347DB2279E3C6200BC6161 /* Puppy in Frameworks */, E10EAA45277BB646000269ED /* JellyfinAPI in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -969,11 +967,11 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + E1347DB4279E3C9E00BC6161 /* Puppy in Frameworks */, E1D7E5A827892566009D0EF7 /* Nuke in Frameworks */, 628B95242670CABD0091AF3B /* SwiftUI.framework in Frameworks */, 531ABF6C2671F5CC00C0FE20 /* WidgetKit.framework in Frameworks */, E13DD3DD27175CE3009D4DAF /* Defaults in Frameworks */, - 53649AB5269D423A00A2D8B7 /* Puppy in Frameworks */, 536D3D7D267BD5F90004248C /* ActivityIndicator in Frameworks */, E13DD3CF27164E1F009D4DAF /* CoreStore in Frameworks */, E10EAA47277BB670000269ED /* JellyfinAPI in Frameworks */, @@ -1859,7 +1857,6 @@ isa = PBXGroup; children = ( E1FCD09526C47118007C8DCF /* ErrorMessage.swift */, - E131691626C583BC0074BFEE /* LogConstructor.swift */, E1FCD08726C35A0D007C8DCF /* NetworkError.swift */, ); path = Errors; @@ -1887,7 +1884,6 @@ 535870902669D7A800D05A09 /* Introspect */, 53ABFDEC26799D7700886593 /* ActivityIndicator */, 536D3D83267BEA550004248C /* ParallaxView */, - 53649AAE269CFAF600A2D8B7 /* Puppy */, 6220D0C826D63F3700B8E046 /* Stinsen */, E13DD3CC27164CA7009D4DAF /* CoreStore */, E12186DD2718F1C50010884C /* Defaults */, @@ -1897,6 +1893,7 @@ E1AE8E7D2789136D00FBDDAA /* Nuke */, E11D83AE278FA998006E9776 /* NukeUI */, E1002B6A2793E36600E47059 /* Algorithms */, + E1347DB5279E3CA500BC6161 /* Puppy */, ); productName = "JellyfinPlayer tvOS"; productReference = 535870602669D21600D05A09 /* Swiftfin tvOS.app */; @@ -1923,7 +1920,6 @@ packageProductDependencies = ( 53352570265EA0A0006CCA86 /* Introspect */, 625CB5792678C4A400530A6E /* ActivityIndicator */, - 53649AAC269CFAEA00A2D8B7 /* Puppy */, 62C29E9B26D0FE4200C1D2E7 /* Stinsen */, E13DD3C52716499E009D4DAF /* CoreStore */, E13DD3D227168E65009D4DAF /* Defaults */, @@ -1936,6 +1932,7 @@ E1361DA6278FA7A300BEC523 /* NukeUI */, E1002B672793CFBA00E47059 /* Algorithms */, 62666E3827E502CE00EC0ECD /* SwizzleSwift */, + E1101176281B1E8A006A3584 /* Puppy */, ); productName = JellyfinPlayer; productReference = 5377CBF1263B596A003A4E83 /* Swiftfin iOS.app */; @@ -1956,11 +1953,11 @@ name = "Swiftfin Widget"; packageProductDependencies = ( 536D3D7C267BD5F90004248C /* ActivityIndicator */, - 53649AB4269D423A00A2D8B7 /* Puppy */, E13DD3CE27164E1F009D4DAF /* CoreStore */, E13DD3DC27175CE3009D4DAF /* Defaults */, E10EAA46277BB670000269ED /* JellyfinAPI */, E1D7E5A727892566009D0EF7 /* Nuke */, + E1347DB3279E3C9E00BC6161 /* Puppy */, ); productName = WidgetExtensionExtension; productReference = 628B95202670CABD0091AF3B /* Swiftfin Widget.appex */; @@ -2017,7 +2014,6 @@ 5335256F265EA0A0006CCA86 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */, 625CB5782678C4A400530A6E /* XCRemoteSwiftPackageReference "ActivityIndicator" */, 536D3D82267BEA550004248C /* XCRemoteSwiftPackageReference "ParallaxView" */, - 53649AAB269CFAEA00A2D8B7 /* XCRemoteSwiftPackageReference "Puppy" */, 62C29E9A26D0FE4100C1D2E7 /* XCRemoteSwiftPackageReference "stinsen" */, E13DD3C42716499E009D4DAF /* XCRemoteSwiftPackageReference "CoreStore" */, E13DD3D127168E65009D4DAF /* XCRemoteSwiftPackageReference "Defaults" */, @@ -2030,6 +2026,7 @@ E1361DA5278FA7A300BEC523 /* XCRemoteSwiftPackageReference "NukeUI" */, E1002B662793CFBA00E47059 /* XCRemoteSwiftPackageReference "swift-algorithms" */, 62666E3727E502CE00EC0ECD /* XCRemoteSwiftPackageReference "SwizzleSwift" */, + E1101175281B1E8A006A3584 /* XCRemoteSwiftPackageReference "Puppy" */, ); productRefGroup = 5377CBF2263B596A003A4E83 /* Products */; projectDirPath = ""; @@ -2340,7 +2337,6 @@ 5364F456266CA0DC0026ECBA /* BaseItemPersonExtensions.swift in Sources */, 531690FA267AD6EC005D8AB9 /* PlainNavigationLinkButton.swift in Sources */, C4BE0764271FC0BB003F4AD1 /* TVLibrariesCoordinator.swift in Sources */, - E131691826C583BC0074BFEE /* LogConstructor.swift in Sources */, E1E5D5512783E67700692DFE /* ExperimentalSettingsView.swift in Sources */, E1A2C160279A7DCA005EC829 /* AboutView.swift in Sources */, C4BE076A271FC164003F4AD1 /* TVLibrariesView.swift in Sources */, @@ -2417,7 +2413,6 @@ C4AE2C3227498D6A00AE13CF /* LiveTVProgramsView.swift in Sources */, 62ECA01826FA685A00E8EBB7 /* DeepLink.swift in Sources */, 62E632E6267D3F5B0063E547 /* EpisodeItemViewModel.swift in Sources */, - E131691726C583BC0074BFEE /* LogConstructor.swift in Sources */, 5321753B2671BCFC005491E6 /* SettingsViewModel.swift in Sources */, E14F7D0926DB36F7007C3AE6 /* ItemLandscapeMainView.swift in Sources */, E107BB9327880A8F00354E07 /* CollectionItemViewModel.swift in Sources */, @@ -2539,7 +2534,6 @@ E1D4BF8D2719F3A300A11E64 /* VideoPlayerJumpLength.swift in Sources */, 6220D0AF26D5EABE00B8E046 /* ViewExtensions.swift in Sources */, E13DD3D7271693CD009D4DAF /* SwiftfinStoreDefaults.swift in Sources */, - E131691926C583BC0074BFEE /* LogConstructor.swift in Sources */, E13DD3CA27164B80009D4DAF /* SwiftfinStore.swift in Sources */, E10EAA51277BBCC4000269ED /* CGSizeExtensions.swift in Sources */, 62E1DCC5273CE19800C9AE76 /* URLExtensions.swift in Sources */, @@ -3045,14 +3039,6 @@ minimumVersion = 0.1.3; }; }; - 53649AAB269CFAEA00A2D8B7 /* XCRemoteSwiftPackageReference "Puppy" */ = { - isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/sushichop/Puppy"; - requirement = { - kind = upToNextMajorVersion; - minimumVersion = 0.2.0; - }; - }; 536D3D82267BEA550004248C /* XCRemoteSwiftPackageReference "ParallaxView" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/PGSSoft/ParallaxView"; @@ -3117,6 +3103,14 @@ kind = branch; }; }; + E1101175281B1E8A006A3584 /* XCRemoteSwiftPackageReference "Puppy" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/sushichop/Puppy"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 0.5.0; + }; + }; E1267D42271A212C003C492E /* XCRemoteSwiftPackageReference "CombineExt" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/CombineCommunity/CombineExt"; @@ -3125,6 +3119,14 @@ minimumVersion = 1.0.0; }; }; + E1347DB0279E3C6200BC6161 /* XCRemoteSwiftPackageReference "Puppy" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/LePips/Puppy"; + requirement = { + branch = main; + kind = branch; + }; + }; E1361DA5278FA7A300BEC523 /* XCRemoteSwiftPackageReference "NukeUI" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/kean/NukeUI"; @@ -3178,21 +3180,6 @@ package = 5335256F265EA0A0006CCA86 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */; productName = Introspect; }; - 53649AAC269CFAEA00A2D8B7 /* Puppy */ = { - isa = XCSwiftPackageProductDependency; - package = 53649AAB269CFAEA00A2D8B7 /* XCRemoteSwiftPackageReference "Puppy" */; - productName = Puppy; - }; - 53649AAE269CFAF600A2D8B7 /* Puppy */ = { - isa = XCSwiftPackageProductDependency; - package = 53649AAB269CFAEA00A2D8B7 /* XCRemoteSwiftPackageReference "Puppy" */; - productName = Puppy; - }; - 53649AB4269D423A00A2D8B7 /* Puppy */ = { - isa = XCSwiftPackageProductDependency; - package = 53649AAB269CFAEA00A2D8B7 /* XCRemoteSwiftPackageReference "Puppy" */; - productName = Puppy; - }; 536D3D7C267BD5F90004248C /* ActivityIndicator */ = { isa = XCSwiftPackageProductDependency; package = 625CB5782678C4A400530A6E /* XCRemoteSwiftPackageReference "ActivityIndicator" */; @@ -3253,6 +3240,11 @@ package = E10EAA4B277BB716000269ED /* XCRemoteSwiftPackageReference "swiftui-sliders" */; productName = Sliders; }; + E1101176281B1E8A006A3584 /* Puppy */ = { + isa = XCSwiftPackageProductDependency; + package = E1101175281B1E8A006A3584 /* XCRemoteSwiftPackageReference "Puppy" */; + productName = Puppy; + }; E11D83AE278FA998006E9776 /* NukeUI */ = { isa = XCSwiftPackageProductDependency; package = E1361DA5278FA7A300BEC523 /* XCRemoteSwiftPackageReference "NukeUI" */; @@ -3268,6 +3260,21 @@ package = E1267D42271A212C003C492E /* XCRemoteSwiftPackageReference "CombineExt" */; productName = CombineExt; }; + E1347DB1279E3C6200BC6161 /* Puppy */ = { + isa = XCSwiftPackageProductDependency; + package = E1347DB0279E3C6200BC6161 /* XCRemoteSwiftPackageReference "Puppy" */; + productName = Puppy; + }; + E1347DB3279E3C9E00BC6161 /* Puppy */ = { + isa = XCSwiftPackageProductDependency; + package = E1347DB0279E3C6200BC6161 /* XCRemoteSwiftPackageReference "Puppy" */; + productName = Puppy; + }; + E1347DB5279E3CA500BC6161 /* Puppy */ = { + isa = XCSwiftPackageProductDependency; + package = E1347DB0279E3C6200BC6161 /* XCRemoteSwiftPackageReference "Puppy" */; + productName = Puppy; + }; E1361DA6278FA7A300BEC523 /* NukeUI */ = { isa = XCSwiftPackageProductDependency; package = E1361DA5278FA7A300BEC523 /* XCRemoteSwiftPackageReference "NukeUI" */; diff --git a/Swiftfin.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Swiftfin.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index c3e87965..b8168ffe 100644 --- a/Swiftfin.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Swiftfin.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -14,8 +14,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/Flight-School/AnyCodable", "state" : { - "revision" : "22f302d4c048aafcda09a4ab5b8c0b03855316fb", - "version" : "0.6.3" + "revision" : "11423ef0c756e8a1f6b4bb576dab9d97bc016c70", + "version" : "0.6.4" } }, { @@ -50,8 +50,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/kaishin/Gifu", "state" : { - "revision" : "0ffe24744cc3d82ab9edece53670d0352c6d5507", - "version" : "3.3.0" + "revision" : "51f2eab32903e336f590c013267cfa4d7f8b06c4", + "version" : "3.3.1" } }, { @@ -68,8 +68,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/kean/Nuke.git", "state" : { - "revision" : "78fa963b8491fc520791d8c2a509f1b8593d8aae", - "version" : "10.7.1" + "revision" : "0ea7545b5c918285aacc044dc75048625c8257cc", + "version" : "10.8.0" } }, { @@ -77,8 +77,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/kean/NukeUI", "state" : { - "revision" : "71398392943f2538fd0f2ebc6f282920f6775b0c", - "version" : "0.8.0" + "revision" : "17f26c07e6b1d3b9258287f99f528111fcd7b7ad", + "version" : "0.8.1" } }, { @@ -140,8 +140,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/siteline/SwiftUI-Introspect", "state" : { - "revision" : "2e09be8af614401bc9f87d40093ec19ce56ccaf2", - "version" : "0.1.3" + "revision" : "f2616860a41f9d9932da412a8978fec79c06fe24", + "version" : "0.1.4" } }, { @@ -150,7 +150,7 @@ "location" : "https://github.com/spacenation/swiftui-sliders", "state" : { "branch" : "master", - "revision" : "518bed3bfc7bd522f3c49404a0d1efb98fa1bf2c" + "revision" : "538e16b35ad7a066a8f5624da9ecee6327886bf7" } }, { diff --git a/Swiftfin/App/AppDelegate.swift b/Swiftfin/App/AppDelegate.swift index aacfa0b9..5ed7e036 100644 --- a/Swiftfin/App/AppDelegate.swift +++ b/Swiftfin/App/AppDelegate.swift @@ -19,6 +19,7 @@ class AppDelegate: NSObject, UIApplicationDelegate { // Lazily initialize datastack _ = SwiftfinStore.dataStack + LogManager.setup() let audioSession = AVAudioSession.sharedInstance() do { diff --git a/Swiftfin/Info.plist b/Swiftfin/Info.plist index dc65aac2..e78d7487 100644 --- a/Swiftfin/Info.plist +++ b/Swiftfin/Info.plist @@ -35,6 +35,8 @@ LSRequiresIPhoneOS + LSSupportsOpeningDocumentsInPlace + NSAppTransportSecurity NSAllowsArbitraryLoads @@ -61,6 +63,8 @@ network. UIApplicationSupportsIndirectInputEvents + UIFileSharingEnabled + UILaunchScreen UIColorName diff --git a/Swiftfin/Views/ConnectToServerView.swift b/Swiftfin/Views/ConnectToServerView.swift index 41efc43b..0c09d6d1 100644 --- a/Swiftfin/Views/ConnectToServerView.swift +++ b/Swiftfin/Views/ConnectToServerView.swift @@ -103,7 +103,7 @@ struct ConnectToServerView: View { } .alert(item: $viewModel.errorMessage) { _ in Alert(title: Text(viewModel.alertTitle), - message: Text(viewModel.errorMessage?.displayMessage ?? L10n.unknownError), + message: Text(viewModel.errorMessage?.message ?? L10n.unknownError), dismissButton: .cancel()) } .alert(item: $viewModel.addServerURIPayload) { _ in diff --git a/Swiftfin/Views/HomeView.swift b/Swiftfin/Views/HomeView.swift index 0d2fafeb..a7d1fbe1 100644 --- a/Swiftfin/Views/HomeView.swift +++ b/Swiftfin/Views/HomeView.swift @@ -35,7 +35,7 @@ struct HomeView: View { } Text("\(errorMessage.code)") - Text(errorMessage.displayMessage) + Text(errorMessage.message) .frame(minWidth: 50, maxWidth: 240) .multilineTextAlignment(.center) diff --git a/Swiftfin/Views/ItemView/Landscape/ItemLandscapeMainView.swift b/Swiftfin/Views/ItemView/Landscape/ItemLandscapeMainView.swift index 14001bcc..3ab2a04b 100644 --- a/Swiftfin/Views/ItemView/Landscape/ItemLandscapeMainView.swift +++ b/Swiftfin/Views/ItemView/Landscape/ItemLandscapeMainView.swift @@ -58,7 +58,7 @@ struct ItemLandscapeMainView: View { selectedVideoPlayerViewModel.injectCustomValues(startFromBeginning: true) itemRouter.route(to: \.videoPlayer, selectedVideoPlayerViewModel) } else { - LogManager.shared.log.error("Attempted to play item but no playback information available") + LogManager.log.error("Attempted to play item but no playback information available") } } label: { Label(L10n.playFromBeginning, systemImage: "gobackward") diff --git a/Swiftfin/Views/ItemView/Portrait/ItemPortraitHeaderOverlayView.swift b/Swiftfin/Views/ItemView/Portrait/ItemPortraitHeaderOverlayView.swift index d9cba8eb..bc700c0b 100644 --- a/Swiftfin/Views/ItemView/Portrait/ItemPortraitHeaderOverlayView.swift +++ b/Swiftfin/Views/ItemView/Portrait/ItemPortraitHeaderOverlayView.swift @@ -118,7 +118,7 @@ struct PortraitHeaderOverlayView: View { if let selectedVideoPlayerViewModel = viewModel.selectedVideoPlayerViewModel { itemRouter.route(to: \.videoPlayer, selectedVideoPlayerViewModel) } else { - LogManager.shared.log.error("Attempted to play item but no playback information available") + LogManager.log.error("Attempted to play item but no playback information available") } } label: { HStack { @@ -142,7 +142,7 @@ struct PortraitHeaderOverlayView: View { selectedVideoPlayerViewModel.injectCustomValues(startFromBeginning: true) itemRouter.route(to: \.videoPlayer, selectedVideoPlayerViewModel) } else { - LogManager.shared.log.error("Attempted to play item but no playback information available") + LogManager.log.error("Attempted to play item but no playback information available") } } label: { Label(L10n.playFromBeginning, systemImage: "gobackward") diff --git a/Swiftfin/Views/UserSignInView.swift b/Swiftfin/Views/UserSignInView.swift index b8002034..eec3f212 100644 --- a/Swiftfin/Views/UserSignInView.swift +++ b/Swiftfin/Views/UserSignInView.swift @@ -50,7 +50,7 @@ struct UserSignInView: View { } .alert(item: $viewModel.errorMessage) { _ in Alert(title: Text(viewModel.alertTitle), - message: Text(viewModel.errorMessage?.displayMessage ?? L10n.unknownError), + message: Text(viewModel.errorMessage?.message ?? L10n.unknownError), dismissButton: .cancel()) } .navigationTitle(L10n.signIn) diff --git a/Swiftfin/Views/VideoPlayer/VLCPlayerViewController.swift b/Swiftfin/Views/VideoPlayer/VLCPlayerViewController.swift index 7a8e14e2..9deaf472 100644 --- a/Swiftfin/Views/VideoPlayer/VLCPlayerViewController.swift +++ b/Swiftfin/Views/VideoPlayer/VLCPlayerViewController.swift @@ -551,11 +551,11 @@ extension VLCPlayerViewController { viewModel = newViewModel if viewModel.streamType == .direct { - LogManager.shared.log.debug("Player set up with direct play stream for item: \(viewModel.item.id ?? "--")") + LogManager.log.debug("Player set up with direct play stream for item: \(viewModel.item.id ?? "--")") } else if viewModel.streamType == .transcode && Defaults[.Experimental.forceDirectPlay] { - LogManager.shared.log.debug("Player set up with forced direct stream for item: \(viewModel.item.id ?? "--")") + LogManager.log.debug("Player set up with forced direct stream for item: \(viewModel.item.id ?? "--")") } else { - LogManager.shared.log.debug("Player set up with transcoded stream for item: \(viewModel.item.id ?? "--")") + LogManager.log.debug("Player set up with transcoded stream for item: \(viewModel.item.id ?? "--")") } } diff --git a/Translations/en.lproj/Localizable.strings b/Translations/en.lproj/Localizable.strings index 268945c5..3f710b26 100644 Binary files a/Translations/en.lproj/Localizable.strings and b/Translations/en.lproj/Localizable.strings differ diff --git a/Translations/pl.lproj/Localizable.strings b/Translations/pl.lproj/Localizable.strings index e5cb7e63..f3d7425a 100644 Binary files a/Translations/pl.lproj/Localizable.strings and b/Translations/pl.lproj/Localizable.strings differ diff --git a/Translations/sv.lproj/Localizable.strings b/Translations/sv.lproj/Localizable.strings index 57992ce7..84d5087c 100644 Binary files a/Translations/sv.lproj/Localizable.strings and b/Translations/sv.lproj/Localizable.strings differ