Skip to content

Commit

Permalink
Merge pull request #1227 from TortugaPower/develop
Browse files Browse the repository at this point in the history
Release v5.5.0
  • Loading branch information
GianniCarlo authored Dec 15, 2024
2 parents bfe5bf5 + 275a4b9 commit 3eb4006
Show file tree
Hide file tree
Showing 159 changed files with 7,956 additions and 657 deletions.
1 change: 1 addition & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
excluded:
- BookPlayer/Generated/AutoMockable.generated.swift
- BookPlayerTests
- BookPlayer/Utils/Extensions/BlurHashDecode.swift
cyclomatic_complexity:
ignores_case_statements: true
# line_length: 120
Expand Down
338 changes: 310 additions & 28 deletions BookPlayer.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"originHash" : "a666f382d5a4884d3a9212a8e4b32eb8280bc2409cc22962bfa19e19731621ac",
"originHash" : "ba453c3eb37ad982efef5d10374603d6da1a1e576981abea5aa656dce0280e2e",
"pins" : [
{
"identity" : "devicekit",
Expand All @@ -19,6 +19,15 @@
"version" : "2.7.3"
}
},
{
"identity" : "get",
"kind" : "remoteSourceControl",
"location" : "https://github.com/kean/Get",
"state" : {
"revision" : "31249885da1052872e0ac91a2943f62567c0d96d",
"version" : "2.2.1"
}
},
{
"identity" : "idzswiftcommoncrypto",
"kind" : "remoteSourceControl",
Expand All @@ -28,6 +37,15 @@
"version" : "0.16.1"
}
},
{
"identity" : "jellyfin-sdk-swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/jellyfin/jellyfin-sdk-swift.git",
"state" : {
"revision" : "a0e848a7aaec55991610818de6128b15cfcec725",
"version" : "0.4.0"
}
},
{
"identity" : "kingfisher",
"kind" : "remoteSourceControl",
Expand Down Expand Up @@ -91,6 +109,15 @@
"version" : "1.1.0"
}
},
{
"identity" : "urlqueryencoder",
"kind" : "remoteSourceControl",
"location" : "https://github.com/CreateAPI/URLQueryEncoder",
"state" : {
"revision" : "4ce950479707ea109f229d7230ec074a133b15d7",
"version" : "0.2.1"
}
},
{
"identity" : "ziparchive",
"kind" : "remoteSourceControl",
Expand Down
25 changes: 24 additions & 1 deletion BookPlayer/Base.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"ok_button" = "OK";
"siri_alert_description" = "Siri Shortcuts are available on iOS 12 and above";
"support_bookplayer_title" = "Support BookPlayer";
"support_bookplayer_description" = "Get BookPlayer Pro to support future development and get extra themes, app icons and cloud sync";
"support_bookplayer_description" = "Support future development and get extra themes, app icons, cloud sync and stand-alone playback on the Apple Watch";
"learn_more_title" = "LEARN MORE";
"settings_appearance_title" = "Appearance";
"settings_theme_title" = "Theme";
Expand Down Expand Up @@ -321,3 +321,26 @@ We're working hard on providing a seamless experience, if possible, please conta
"more_title" = "More";
"repeat_turn_on_title" = "Turn on Repeat for this book";
"repeat_turn_off_title" = "Turn off Repeat for this book";
"benefits_watchapp_description" = "Stream or download your books and listen on the go without your phone.";
"download_from_jellyfin_title" = "Download from Jellyfin";
"jellyfin_connection_details_title" = "Connection Details";
"jellyfin_connect_button" = "Connect";
"jellyfin_sign_in_button" = "Sign In";
"jellyfin_section_server_url" = "Server URL";
"jellyfin_section_server_url_footer" = "Connect to your Jellyfin server";
"jellyfin_section_server" = "Server";
"jellyfin_server_name_label" = "Name";
"jellyfin_server_url_label" = "URL";
"jellyfin_section_login" = "Login";
"jellyfin_username_placeholder" = "Username";
"jellyfin_password_placeholder" = "Password";
"jellyfin_password_remember_me_label" = "Remember Me";
"settings_jellyfin_manage_connection_title" = "Manage Connection";
"jellyfin_internal_error_invalid_url" = "Internal error: Request URL is invalid: %@";
"jellyfin_internal_error_build_url" = "Internal error: Failed to build request URL";
"jellyfin_internal_error_no_client" = "Cannot contact Jellyfin server. Check the provided server URL.";
"jellyfin_error_unexpected_response" = "Unexpected server response";
"jellyfin_error_unexpected_response_with_code" = "Unexpected server response (Code: %d - %@)";
"jellyfin_error_unauthorized" = "Sign In failed. Check your username and password.";
"file_size_unknown" = "Unknown size";
"runtime_unknown" = "Unknown duration";
43 changes: 23 additions & 20 deletions BookPlayer/Coordinators/DataInitializerCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class DataInitializerCoordinator: BPLogger {
|| error.code == NSMigrationMissingMappingModelError || error.code == NSMigrationManagerSourceStoreError
|| error.code == NSMigrationManagerDestinationStoreError || error.code == NSEntityMigrationPolicyError
|| error.code == NSValidationMultipleErrorsError || error.code == NSValidationMissingMandatoryPropertyError
|| error.code == NSPersistentStoreIncompatibleSchemaError
{
Self.logger.warning("Failed to perform migration, attempting recovery with the loading library sequence")
await MainActor.run {
Expand All @@ -79,26 +80,28 @@ class DataInitializerCoordinator: BPLogger {
Additional Info
\(error.userInfo)
"""
alertPresenter.showAlert(BPAlertContent(
title: "error_title".localized,
message: errorDescription,
style: .alert,
actionItems: [
BPActionItem(
title: "ok_button".localized,
handler: {
fatalError("Unresolved error \(error.domain) (\(error.code)): \(error.localizedDescription)")
}
),
.init(
title: "Reset and recover database",
style: .destructive,
handler: {
self.recoverLibraryFromFailedMigration()
}
)
]
))
alertPresenter.showAlert(
BPAlertContent(
title: "error_title".localized,
message: errorDescription,
style: .alert,
actionItems: [
BPActionItem(
title: "ok_button".localized,
handler: {
fatalError("Unresolved error \(error.domain) (\(error.code)): \(error.localizedDescription)")
}
),
.init(
title: "Reset and recover database",
style: .destructive,
handler: {
self.recoverLibraryFromFailedMigration()
}
),
]
)
)
}
}
}
Expand Down
12 changes: 9 additions & 3 deletions BookPlayer/Coordinators/FolderListCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,26 @@ class FolderListCoordinator: ItemListCoordinator {
flow: BPCoordinatorPresentationFlow,
folderRelativePath: String,
playerManager: PlayerManagerProtocol,
singleFileDownloadService: SingleFileDownloadService,
libraryService: LibraryServiceProtocol,
playbackService: PlaybackServiceProtocol,
syncService: SyncServiceProtocol,
importManager: ImportManager,
listRefreshService: ListSyncRefreshService
listRefreshService: ListSyncRefreshService,
jellyfinConnectionService: JellyfinConnectionService
) {
self.folderRelativePath = folderRelativePath

super.init(
flow: flow,
playerManager: playerManager,
singleFileDownloadService: singleFileDownloadService,
libraryService: libraryService,
playbackService: playbackService,
syncService: syncService,
importManager: importManager,
listRefreshService: listRefreshService
listRefreshService: listRefreshService,
jellyfinConnectionService: jellyfinConnectionService
)
}

Expand All @@ -40,7 +44,7 @@ class FolderListCoordinator: ItemListCoordinator {
let viewModel = ItemListViewModel(
folderRelativePath: self.folderRelativePath,
playerManager: self.playerManager,
networkClient: NetworkClient(),
singleFileDownloadService: self.singleFileDownloadService,
libraryService: self.libraryService,
playbackService: self.playbackService,
syncService: self.syncService,
Expand All @@ -56,6 +60,8 @@ class FolderListCoordinator: ItemListCoordinator {
self.loadPlayer(relativePath)
case .showDocumentPicker:
self.showDocumentPicker()
case .showJellyfinDownloader:
self.showJellyfinDownloader()
case .showSearchList(let relativePath, let placeholderTitle):
self.showSearchList(at: relativePath, placeholderTitle: placeholderTitle)
case .showItemDetails(let item):
Expand Down
21 changes: 19 additions & 2 deletions BookPlayer/Coordinators/ItemListCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,37 @@ import UniformTypeIdentifiers

class ItemListCoordinator: NSObject, Coordinator, AlertPresenter, BPLogger {
let playerManager: PlayerManagerProtocol
let singleFileDownloadService: SingleFileDownloadService
let libraryService: LibraryServiceProtocol
let playbackService: PlaybackServiceProtocol
let syncService: SyncServiceProtocol
let importManager: ImportManager
let listRefreshService: ListSyncRefreshService
let jellyfinConnectionService: JellyfinConnectionService
let flow: BPCoordinatorPresentationFlow

weak var documentPickerDelegate: UIDocumentPickerDelegate?

init(
flow: BPCoordinatorPresentationFlow,
playerManager: PlayerManagerProtocol,
singleFileDownloadService: SingleFileDownloadService,
libraryService: LibraryServiceProtocol,
playbackService: PlaybackServiceProtocol,
syncService: SyncServiceProtocol,
importManager: ImportManager,
listRefreshService: ListSyncRefreshService
listRefreshService: ListSyncRefreshService,
jellyfinConnectionService: JellyfinConnectionService
) {
self.flow = flow
self.playerManager = playerManager
self.singleFileDownloadService = singleFileDownloadService
self.libraryService = libraryService
self.playbackService = playbackService
self.syncService = syncService
self.importManager = importManager
self.listRefreshService = listRefreshService
self.jellyfinConnectionService = jellyfinConnectionService
}

func start() {
Expand All @@ -54,11 +60,13 @@ class ItemListCoordinator: NSObject, Coordinator, AlertPresenter, BPLogger {
flow: .pushFlow(navigationController: flow.navigationController),
folderRelativePath: relativePath,
playerManager: playerManager,
singleFileDownloadService: singleFileDownloadService,
libraryService: libraryService,
playbackService: playbackService,
syncService: syncService,
importManager: importManager,
listRefreshService: listRefreshService
listRefreshService: listRefreshService,
jellyfinConnectionService: jellyfinConnectionService
)
child.start()
}
Expand Down Expand Up @@ -160,6 +168,15 @@ extension ItemListCoordinator {
flow.navigationController.present(providerList, animated: true, completion: nil)
}

func showJellyfinDownloader() {
let child = JellyfinCoordinator(
flow: .modalFlow(presentingController: flow.navigationController, modalPresentationStyle: .pageSheet),
singleFileDownloadService: singleFileDownloadService,
jellyfinConnectionService: jellyfinConnectionService
)
child.start()
}

func showExportController(for items: [SimpleLibraryItem]) {
let providers = items.map { BookActivityItemProvider($0) }

Expand Down
21 changes: 9 additions & 12 deletions BookPlayer/Coordinators/LibraryListCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,27 @@ class LibraryListCoordinator: ItemListCoordinator, UINavigationControllerDelegat
init(
flow: BPCoordinatorPresentationFlow,
playerManager: PlayerManagerProtocol,
singleFileDownloadService: SingleFileDownloadService,
libraryService: LibraryServiceProtocol,
playbackService: PlaybackServiceProtocol,
syncService: SyncServiceProtocol,
importManager: ImportManager,
listRefreshService: ListSyncRefreshService,
accountService: AccountServiceProtocol
accountService: AccountServiceProtocol,
jellyfinConnectionService: JellyfinConnectionService
) {
self.accountService = accountService

super.init(
flow: flow,
playerManager: playerManager,
singleFileDownloadService: singleFileDownloadService,
libraryService: libraryService,
playbackService: playbackService,
syncService: syncService,
importManager: importManager,
listRefreshService: listRefreshService
listRefreshService: listRefreshService,
jellyfinConnectionService: jellyfinConnectionService
)
}

Expand All @@ -54,7 +58,7 @@ class LibraryListCoordinator: ItemListCoordinator, UINavigationControllerDelegat
let viewModel = ItemListViewModel(
folderRelativePath: nil,
playerManager: self.playerManager,
networkClient: NetworkClient(),
singleFileDownloadService: self.singleFileDownloadService,
libraryService: self.libraryService,
playbackService: self.playbackService,
syncService: self.syncService,
Expand All @@ -70,6 +74,8 @@ class LibraryListCoordinator: ItemListCoordinator, UINavigationControllerDelegat
self.loadPlayer(relativePath)
case .showDocumentPicker:
self.showDocumentPicker()
case .showJellyfinDownloader:
self.showJellyfinDownloader()
case .showSearchList(let relativePath, let placeholderTitle):
self.showSearchList(at: relativePath, placeholderTitle: placeholderTitle)
case .showItemDetails(let item):
Expand Down Expand Up @@ -311,15 +317,6 @@ class LibraryListCoordinator: ItemListCoordinator, UINavigationControllerDelegat
lastItemListViewController.viewModel.viewDidAppear()
}

func handleDownloadAction(url: URL) {
guard
let libraryListViewController = flow.navigationController.viewControllers.first as? ItemListViewController
else { return }

libraryListViewController.setEditing(false, animated: false)
libraryListViewController.viewModel.handleDownload(url)
}

override func syncList() {
/// Process any deferred progress calculations for folders
if playbackService.processFoldersStaleProgress() {
Expand Down
11 changes: 9 additions & 2 deletions BookPlayer/Coordinators/MainCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@ class MainCoordinator: NSObject {
var tabBarController: AppTabBarController?

let playerManager: PlayerManagerProtocol
let singleFileDownloadService: SingleFileDownloadService
let libraryService: LibraryServiceProtocol
let playbackService: PlaybackServiceProtocol
let accountService: AccountServiceProtocol
var syncService: SyncServiceProtocol
let watchConnectivityService: PhoneWatchConnectivityService
let jellyfinConnectionService: JellyfinConnectionService

let navigationController: UINavigationController
var libraryCoordinator: LibraryListCoordinator?
Expand All @@ -36,7 +38,9 @@ class MainCoordinator: NSObject {
self.syncService = coreServices.syncService
self.playbackService = coreServices.playbackService
self.playerManager = coreServices.playerManager
self.singleFileDownloadService = SingleFileDownloadService(networkClient: NetworkClient())
self.watchConnectivityService = coreServices.watchService
self.jellyfinConnectionService = JellyfinConnectionService(keychainService: KeychainService())

ThemeManager.shared.libraryService = libraryService

Expand Down Expand Up @@ -84,6 +88,7 @@ class MainCoordinator: NSObject {
let libraryCoordinator = LibraryListCoordinator(
flow: .pushFlow(navigationController: AppNavigationController.instantiate(from: .Main)),
playerManager: self.playerManager,
singleFileDownloadService: self.singleFileDownloadService,
libraryService: self.libraryService,
playbackService: self.playbackService,
syncService: syncService,
Expand All @@ -92,7 +97,8 @@ class MainCoordinator: NSObject {
playerManager: playerManager,
syncService: syncService
),
accountService: self.accountService
accountService: self.accountService,
jellyfinConnectionService: jellyfinConnectionService
)
playerManager.syncProgressDelegate = libraryCoordinator
self.libraryCoordinator = libraryCoordinator
Expand All @@ -117,7 +123,8 @@ class MainCoordinator: NSObject {
flow: .pushFlow(navigationController: AppNavigationController.instantiate(from: .Settings)),
libraryService: self.libraryService,
syncService: self.syncService,
accountService: self.accountService
accountService: self.accountService,
jellyfinConnectionService: jellyfinConnectionService
)
settingsCoordinator.tabBarController = tabBarController
settingsCoordinator.start()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import UIKit

protocol BPCoordinatorPresentationFlow {
public protocol BPCoordinatorPresentationFlow {
/// Navigation used for the flow of the coordinator
var navigationController: UINavigationController { get }
/// Start the flow with the specified starting screen
Expand Down
Loading

0 comments on commit 3eb4006

Please sign in to comment.