new log structure

This commit is contained in:
Ethan Pippin 2022-01-25 12:35:38 -07:00
parent 4e8a419dbc
commit 4c76ac1438
26 changed files with 147 additions and 137 deletions

View File

@ -61,13 +61,13 @@ final class MainCoordinator: NavigationCoordinatable {
@objc
func didLogIn() {
LogManager.shared.log.info("Received `didSignIn` from SwiftfinNotificationCenter.")
LogManager.log.info("Received `didSignIn` from SwiftfinNotificationCenter.")
root(\.mainTab)
}
@objc
func didLogOut() {
LogManager.shared.log.info("Received `didSignOut` from SwiftfinNotificationCenter.")
LogManager.log.info("Received `didSignOut` from SwiftfinNotificationCenter.")
root(\.serverList)
}

View File

@ -47,13 +47,13 @@ final class MainCoordinator: NavigationCoordinatable {
@objc
func didLogIn() {
LogManager.shared.log.info("Received `didSignIn` from NSNotificationCenter.")
LogManager.log.info("Received `didSignIn` from NSNotificationCenter.")
root(\.mainTab)
}
@objc
func didLogOut() {
LogManager.shared.log.info("Received `didSignOut` from NSNotificationCenter.")
LogManager.log.info("Received `didSignOut` from NSNotificationCenter.")
root(\.serverList)
}

View File

@ -44,19 +44,19 @@ enum NetworkError: Error {
switch logConstructor.level {
case .trace:
logFunction = LogManager.shared.log.trace
logFunction = LogManager.log.trace
case .debug:
logFunction = LogManager.shared.log.debug
logFunction = LogManager.log.debug
case .information:
logFunction = LogManager.shared.log.info
logFunction = LogManager.log.info
case .warning:
logFunction = LogManager.shared.log.warning
logFunction = LogManager.log.warning
case .error:
logFunction = LogManager.shared.log.error
logFunction = LogManager.log.error
case .critical:
logFunction = LogManager.shared.log.critical
logFunction = LogManager.log.critical
case ._none:
logFunction = LogManager.shared.log.debug
logFunction = LogManager.log.debug
}
logFunction(logConstructor.message, logConstructor.tag, logConstructor.function, logConstructor.file, logConstructor.line)

View File

@ -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

View File

@ -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)
}

View File

@ -10,39 +10,44 @@ import Foundation
import Puppy
class LogManager {
static let shared = LogManager()
let log = Puppy()
static let log = Puppy()
static func setup() {
let logsDirectory = getDocumentsDirectory().appendingPathComponent("logs", isDirectory: true)
do {
try FileManager.default.createDirectory(atPath: logsDirectory.path,
withIntermediateDirectories: true,
attributes: nil)
} catch {
// logs directory already created
}
let logFileURL = logsDirectory.appendingPathComponent("swiftfin_log.log")
let fileRotationLogger = try! FileRotationLogger("org.jellyfin.swiftfin.logger.file-rotation",
fileURL: logFileURL)
fileRotationLogger.suffixExtension = .numbering
fileRotationLogger.maxFileSize = 10 * 1024
fileRotationLogger.maxArchivedFilesCount = 5
fileRotationLogger.format = LogFormatter()
let consoleLogger = ConsoleLogger("org.jellyfin.swiftfin.logger.console")
consoleLogger.format = LogFormatter()
log.add(fileRotationLogger, withLevel: .debug)
log.add(consoleLogger, withLevel: .debug)
}
private static func getDocumentsDirectory() -> URL {
// find all possible documents directories for this user
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
init() {
let console = ConsoleLogger("com.swiftfin.ConsoleLogger")
let fileURL = self.getDocumentsDirectory().appendingPathComponent("logs.txt")
let FM = FileManager()
_ = try? FM.removeItem(at: fileURL)
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)
}
console.format = LogFormatter()
log.add(console, withLevel: .debug)
log.info("Logger initialized.")
}
func logFileURL() -> URL {
self.getDocumentsDirectory().appendingPathComponent("logs.txt")
}
func getDocumentsDirectory() -> URL {
// find all possible documents directories for this user
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
// just send back the first one, which ought to be the only one
return paths[0]
}
// just send back the first one, which ought to be the only one
return paths[0]
}
}
class LogFormatter: LogFormattable {

View File

@ -55,7 +55,7 @@ final class ConnectToServerViewModel: ViewModel {
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
@ -103,7 +103,7 @@ final class ConnectToServerViewModel: ViewModel {
}
}
}, 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)

View File

@ -64,7 +64,7 @@ final class HomeViewModel: ViewModel {
@objc
func refresh() {
LogManager.shared.log.debug("Refresh called.")
LogManager.log.debug("Refresh called.")
refreshLibrariesLatest()
refreshLatestAddedItems()
@ -90,7 +90,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)
@ -148,7 +148,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
}
@ -179,7 +179,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 ?? []
})
@ -224,7 +224,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 ?? []
})

View File

@ -47,7 +47,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],
@ -57,7 +57,7 @@ final class SeasonItemViewModel: ItemViewModel, EpisodesRowManager {
// self?.handleAPIRequestError(completion: completion)
// }, receiveValue: { [weak self] response in
// self?.episodes = response.items ?? []
// LogManager.shared.log.debug("Retrieved \(String(self?.episodes.count ?? 0)) episodes")
// LogManager.log.debug("Retrieved \(String(self?.episodes.count ?? 0)) episodes")
//
// self?.setNextUpInSeason()
// })

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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 {

View File

@ -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 ?? []
})

View File

@ -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

View File

@ -30,8 +30,8 @@ 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")
LogManager.log.debug("username: \(username), password: \(password)", tag: "login")
SessionManager.main.loginUser(server: server, username: username, password: password)
.trackActivity(loading)

View File

@ -472,7 +472,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)
}
@ -508,7 +508,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)
}
@ -553,7 +553,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)
@ -580,7 +580,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")")
SwiftfinNotificationCenter.main.post(name: SwiftfinNotificationCenter.Keys.didSendStopReport,
object: self.item.id)
}

View File

@ -43,16 +43,16 @@ class ViewModel: ObservableObject {
case .error(-1, _, _, _):
networkError = .URLError(response: errorResponse, displayMessage: displayMessage, logConstructor: logConstructor)
// 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
LogManager.log
.error("Request failed: HTTP URL request failed with description: \(errorResponse.localizedDescription)")
default:
networkError = .JellyfinError(response: errorResponse, displayMessage: displayMessage, logConstructor: logConstructor)
// Able to use user-facing friendly description here since just HTTP status codes
LogManager.shared.log
LogManager.log
.error("Request failed: \(networkError.errorMessage.code) - \(networkError.errorMessage.title): \(networkError.errorMessage.logConstructor.message)\n\(error.localizedDescription)")
}
@ -67,7 +67,7 @@ class ViewModel: ObservableObject {
displayMessage: swiftfinError.errorDescription ?? "",
logConstructor: logConstructor)
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,
@ -75,7 +75,7 @@ class ViewModel: ObservableObject {
displayMessage: error.localizedDescription,
logConstructor: logConstructor)
self.errorMessage = genericErrorMessage
LogManager.shared.log.error("Request failed: Generic error - \(error.localizedDescription)")
LogManager.log.error("Request failed: Generic error - \(error.localizedDescription)")
}
}
}

View File

@ -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")

View File

@ -463,11 +463,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 ?? "--")")
}
}

View File

@ -54,12 +54,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 */; };
@ -287,6 +284,9 @@
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 */; };
@ -805,7 +805,6 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
53649AAF269CFAF600A2D8B7 /* Puppy in Frameworks */,
E11D83AF278FA998006E9776 /* NukeUI in Frameworks */,
E1218C9E271A2CD600EA0737 /* CombineExt in Frameworks */,
E1002B6B2793E36600E47059 /* Algorithms in Frameworks */,
@ -818,6 +817,7 @@
E1AE8E7E2789136D00FBDDAA /* Nuke in Frameworks */,
E178857D278037FD0094FBCF /* JellyfinAPI in Frameworks */,
E12186DE2718F1C50010884C /* Defaults in Frameworks */,
E1347DB6279E3CA500BC6161 /* Puppy in Frameworks */,
53ABFDED26799D7700886593 /* ActivityIndicator in Frameworks */,
9EA03141D129DC2763660E29 /* Pods_Swiftfin_tvOS.framework in Frameworks */,
);
@ -829,7 +829,6 @@
files = (
E13DD3D327168E65009D4DAF /* Defaults in Frameworks */,
E1361DA7278FA7A300BEC523 /* NukeUI in Frameworks */,
53649AAD269CFAEA00A2D8B7 /* Puppy in Frameworks */,
E1002B682793CFBA00E47059 /* Algorithms in Frameworks */,
E10EAA4D277BB716000269ED /* Sliders in Frameworks */,
62C29E9C26D0FE4200C1D2E7 /* Stinsen in Frameworks */,
@ -840,6 +839,7 @@
E1AE8E7C2789135A00FBDDAA /* Nuke in Frameworks */,
625CB57A2678C4A400530A6E /* ActivityIndicator in Frameworks */,
E1B6DCE8271A23780015B715 /* CombineExt in Frameworks */,
E1347DB2279E3C6200BC6161 /* Puppy in Frameworks */,
E10EAA45277BB646000269ED /* JellyfinAPI in Frameworks */,
EEAF6CD6B3433126DEBC7E87 /* Pods_Swiftfin_iOS.framework in Frameworks */,
);
@ -849,11 +849,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 */,
@ -1757,7 +1757,6 @@
535870902669D7A800D05A09 /* Introspect */,
53ABFDEC26799D7700886593 /* ActivityIndicator */,
536D3D83267BEA550004248C /* ParallaxView */,
53649AAE269CFAF600A2D8B7 /* Puppy */,
6220D0C826D63F3700B8E046 /* Stinsen */,
E13DD3CC27164CA7009D4DAF /* CoreStore */,
E12186DD2718F1C50010884C /* Defaults */,
@ -1767,6 +1766,7 @@
E1AE8E7D2789136D00FBDDAA /* Nuke */,
E11D83AE278FA998006E9776 /* NukeUI */,
E1002B6A2793E36600E47059 /* Algorithms */,
E1347DB5279E3CA500BC6161 /* Puppy */,
);
productName = "JellyfinPlayer tvOS";
productReference = 535870602669D21600D05A09 /* Swiftfin tvOS.app */;
@ -1795,7 +1795,6 @@
packageProductDependencies = (
53352570265EA0A0006CCA86 /* Introspect */,
625CB5792678C4A400530A6E /* ActivityIndicator */,
53649AAC269CFAEA00A2D8B7 /* Puppy */,
62C29E9B26D0FE4200C1D2E7 /* Stinsen */,
E13DD3C52716499E009D4DAF /* CoreStore */,
E13DD3D227168E65009D4DAF /* Defaults */,
@ -1807,6 +1806,7 @@
E1AE8E7B2789135A00FBDDAA /* Nuke */,
E1361DA6278FA7A300BEC523 /* NukeUI */,
E1002B672793CFBA00E47059 /* Algorithms */,
E1347DB1279E3C6200BC6161 /* Puppy */,
);
productName = JellyfinPlayer;
productReference = 5377CBF1263B596A003A4E83 /* Swiftfin iOS.app */;
@ -1828,11 +1828,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 */;
@ -1889,7 +1889,6 @@
5335256F265EA0A0006CCA86 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */,
625CB5782678C4A400530A6E /* XCRemoteSwiftPackageReference "ActivityIndicator" */,
536D3D82267BEA550004248C /* XCRemoteSwiftPackageReference "ParallaxView" */,
53649AAB269CFAEA00A2D8B7 /* XCRemoteSwiftPackageReference "Puppy" */,
62C29E9A26D0FE4100C1D2E7 /* XCRemoteSwiftPackageReference "stinsen" */,
E13DD3C42716499E009D4DAF /* XCRemoteSwiftPackageReference "CoreStore" */,
E13DD3D127168E65009D4DAF /* XCRemoteSwiftPackageReference "Defaults" */,
@ -1901,6 +1900,7 @@
E1AE8E7A2789135A00FBDDAA /* XCRemoteSwiftPackageReference "Nuke" */,
E1361DA5278FA7A300BEC523 /* XCRemoteSwiftPackageReference "NukeUI" */,
E1002B662793CFBA00E47059 /* XCRemoteSwiftPackageReference "swift-algorithms" */,
E1347DB0279E3C6200BC6161 /* XCRemoteSwiftPackageReference "Puppy" */,
);
productRefGroup = 5377CBF2263B596A003A4E83 /* Products */;
projectDirPath = "";
@ -2865,7 +2865,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 70;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = TY84JMYEFE;
ENABLE_BITCODE = NO;
ENABLE_PREVIEWS = YES;
EXCLUDED_ARCHS = "";
@ -2902,7 +2902,7 @@
CURRENT_PROJECT_VERSION = 70;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = TY84JMYEFE;
ENABLE_BITCODE = NO;
ENABLE_PREVIEWS = YES;
EXCLUDED_ARCHS = "";
@ -2933,7 +2933,7 @@
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 70;
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = TY84JMYEFE;
INFOPLIST_FILE = WidgetExtension/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
@ -2960,7 +2960,7 @@
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 70;
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = TY84JMYEFE;
INFOPLIST_FILE = WidgetExtension/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
@ -3028,14 +3028,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";
@ -3100,6 +3092,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";
@ -3153,21 +3153,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" */;
@ -3238,6 +3223,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" */;

View File

@ -93,11 +93,11 @@
},
{
"package": "Puppy",
"repositoryURL": "https://github.com/sushichop/Puppy",
"repositoryURL": "https://github.com/LePips/Puppy",
"state": {
"branch": null,
"revision": "95ce04b0e778b8d7c351876bc98bbf68328dfc9b",
"version": "0.3.1"
"branch": "main",
"revision": "c34356e8e3879bb39656edd1b11622497ef6f290",
"version": null
}
},
{

View File

@ -19,6 +19,7 @@ class AppDelegate: NSObject, UIApplicationDelegate {
// Lazily initialize datastack
_ = SwiftfinStore.dataStack
LogManager.setup()
let audioSession = AVAudioSession.sharedInstance()
do {

View File

@ -2,6 +2,10 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
<key>UIFileSharingEnabled</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>

View File

@ -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")

View File

@ -117,7 +117,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 {
@ -141,7 +141,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")

View File

@ -423,11 +423,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 ?? "--")")
}
}