Skip to content

Commit

Permalink
Merge pull request #926 from TortugaPower/develop
Browse files Browse the repository at this point in the history
Release v5.0.1
  • Loading branch information
GianniCarlo authored Jun 21, 2023
2 parents 38c3696 + a167ea9 commit e390c67
Show file tree
Hide file tree
Showing 11 changed files with 594 additions and 347 deletions.
24 changes: 12 additions & 12 deletions BookPlayer.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -469,11 +469,6 @@
9FC1E4772815F97E00522FA8 /* KeychainServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FC1E4762815F97E00522FA8 /* KeychainServiceTests.swift */; };
9FC1E4782816001400522FA8 /* KeychainService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FC1E4742815C6A300522FA8 /* KeychainService.swift */; };
9FC1E4792816001400522FA8 /* KeychainService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FC1E4742815C6A300522FA8 /* KeychainService.swift */; };
9FCC228C2A172669003DD895 /* MappingModel_v8_to_v9.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = 9FCC228B2A172669003DD895 /* MappingModel_v8_to_v9.xcmappingmodel */; };
9FCC228D2A172669003DD895 /* MappingModel_v8_to_v9.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = 9FCC228B2A172669003DD895 /* MappingModel_v8_to_v9.xcmappingmodel */; };
9FCC228E2A172669003DD895 /* MappingModel_v8_to_v9.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = 9FCC228B2A172669003DD895 /* MappingModel_v8_to_v9.xcmappingmodel */; };
9FCC228F2A172669003DD895 /* MappingModel_v8_to_v9.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = 9FCC228B2A172669003DD895 /* MappingModel_v8_to_v9.xcmappingmodel */; };
9FCC22902A172669003DD895 /* MappingModel_v8_to_v9.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = 9FCC228B2A172669003DD895 /* MappingModel_v8_to_v9.xcmappingmodel */; };
9FD8D95829DC53750074C2D8 /* CoreServices.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FD8D95729DC53750074C2D8 /* CoreServices.swift */; };
9FDDD2D8289B64440020C428 /* SyncStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FDDD2D7289B64440020C428 /* SyncStatus.swift */; };
9FDDD2D9289B64440020C428 /* SyncStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FDDD2D7289B64440020C428 /* SyncStatus.swift */; };
Expand All @@ -485,6 +480,11 @@
9FEC87AE27FA9E98006C71D5 /* LoginCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FEC87AD27FA9E98006C71D5 /* LoginCoordinator.swift */; };
9FEC87B027FA9F0F006C71D5 /* LoginViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FEC87AF27FA9F0F006C71D5 /* LoginViewController.swift */; };
9FEC87B227FA9F1C006C71D5 /* LoginViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FEC87B127FA9F1C006C71D5 /* LoginViewModel.swift */; };
9FF383D12A40F97000BBAC11 /* MappingModel_v8_to_v9.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = 9FF383D02A40F97000BBAC11 /* MappingModel_v8_to_v9.xcmappingmodel */; };
9FF383D22A40F97000BBAC11 /* MappingModel_v8_to_v9.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = 9FF383D02A40F97000BBAC11 /* MappingModel_v8_to_v9.xcmappingmodel */; };
9FF383D32A40F97000BBAC11 /* MappingModel_v8_to_v9.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = 9FF383D02A40F97000BBAC11 /* MappingModel_v8_to_v9.xcmappingmodel */; };
9FF383D42A40F97000BBAC11 /* MappingModel_v8_to_v9.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = 9FF383D02A40F97000BBAC11 /* MappingModel_v8_to_v9.xcmappingmodel */; };
9FF383D52A40F97000BBAC11 /* MappingModel_v8_to_v9.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = 9FF383D02A40F97000BBAC11 /* MappingModel_v8_to_v9.xcmappingmodel */; };
9FF710AC2A212221006490E0 /* QueuedSyncTasksViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FF710AB2A212221006490E0 /* QueuedSyncTasksViewController.swift */; };
9FF710B72A212A19006490E0 /* QueuedSyncTasksView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FF710B62A212A19006490E0 /* QueuedSyncTasksView.swift */; };
9FF710B92A213084006490E0 /* QueuedSyncTaskRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FF710B82A213084006490E0 /* QueuedSyncTaskRowView.swift */; };
Expand Down Expand Up @@ -1099,7 +1099,6 @@
9FC1E46A2815A8A800522FA8 /* LibraryAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibraryAPI.swift; sourceTree = "<group>"; };
9FC1E4742815C6A300522FA8 /* KeychainService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainService.swift; sourceTree = "<group>"; };
9FC1E4762815F97E00522FA8 /* KeychainServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainServiceTests.swift; sourceTree = "<group>"; };
9FCC228B2A172669003DD895 /* MappingModel_v8_to_v9.xcmappingmodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcmappingmodel; path = MappingModel_v8_to_v9.xcmappingmodel; sourceTree = "<group>"; };
9FD8D95729DC53750074C2D8 /* CoreServices.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreServices.swift; sourceTree = "<group>"; };
9FDDD2D7289B64440020C428 /* SyncStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncStatus.swift; sourceTree = "<group>"; };
9FDDD2DD289BEE590020C428 /* SyncJobScheduler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncJobScheduler.swift; sourceTree = "<group>"; };
Expand All @@ -1109,6 +1108,7 @@
9FEC87AD27FA9E98006C71D5 /* LoginCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginCoordinator.swift; sourceTree = "<group>"; };
9FEC87AF27FA9F0F006C71D5 /* LoginViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewController.swift; sourceTree = "<group>"; };
9FEC87B127FA9F1C006C71D5 /* LoginViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewModel.swift; sourceTree = "<group>"; };
9FF383D02A40F97000BBAC11 /* MappingModel_v8_to_v9.xcmappingmodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcmappingmodel; path = MappingModel_v8_to_v9.xcmappingmodel; sourceTree = "<group>"; };
9FF710AB2A212221006490E0 /* QueuedSyncTasksViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueuedSyncTasksViewController.swift; sourceTree = "<group>"; };
9FF710B62A212A19006490E0 /* QueuedSyncTasksView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueuedSyncTasksView.swift; sourceTree = "<group>"; };
9FF710B82A213084006490E0 /* QueuedSyncTaskRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueuedSyncTaskRowView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1637,7 +1637,7 @@
41C3394825E04091003ED2B0 /* MappingModel_v2_to_v3.xcmappingmodel */,
418CABB025EF28FC00D8C878 /* MappingModel_v3_to_v4.xcmappingmodel */,
41A359C2276232E00020D5F5 /* MappingModel_v7_to_v8.xcmappingmodel */,
9FCC228B2A172669003DD895 /* MappingModel_v8_to_v9.xcmappingmodel */,
9FF383D02A40F97000BBAC11 /* MappingModel_v8_to_v9.xcmappingmodel */,
);
path = Migrations;
sourceTree = "<group>";
Expand Down Expand Up @@ -2833,7 +2833,7 @@
41A8BAFE227E6C88003C9895 /* Notification+BookPlayerWatchApp.swift in Sources */,
41D20DB125D5F5A100AAEE30 /* MappingModel_v1_to_v2.xcmappingmodel in Sources */,
9F82DF6D27DE985A001B0EA8 /* NowPlayingPlaybackControlsView.swift in Sources */,
9FCC228D2A172669003DD895 /* MappingModel_v8_to_v9.xcmappingmodel in Sources */,
9FF383D22A40F97000BBAC11 /* MappingModel_v8_to_v9.xcmappingmodel in Sources */,
9FA334C327C2833B0064E8EA /* ResizeableImageView.swift in Sources */,
9F82DF6F27DEE83E001B0EA8 /* SkipDirection.swift in Sources */,
9FA334AB27C058210064E8EA /* ItemListView.swift in Sources */,
Expand All @@ -2855,6 +2855,7 @@
4140EA6C2272898F0009F794 /* DataManager.swift in Sources */,
4140EA71227289A20009F794 /* UIColor+BookPlayer.swift in Sources */,
9F0872DC2A19867C00B7FD4A /* ArtworkResponse.swift in Sources */,
9FF383D42A40F97000BBAC11 /* MappingModel_v8_to_v9.xcmappingmodel in Sources */,
4138CE1726E584B60014F11E /* BookmarkType.swift in Sources */,
9F9C7B5429F9672700E257B0 /* SyncableBookmark.swift in Sources */,
5126F123258E9F18009965DC /* URL+BookPlayer.swift in Sources */,
Expand All @@ -2872,7 +2873,6 @@
4140EA7D227289CB0009F794 /* LibraryItem+CoreDataProperties.swift in Sources */,
4140EA73227289A80009F794 /* Notification+BookPlayerKit.swift in Sources */,
41A894212652A5DE0032E972 /* Configuration.swift in Sources */,
9FCC228F2A172669003DD895 /* MappingModel_v8_to_v9.xcmappingmodel in Sources */,
9FACAC6A2970F2F500D01EB7 /* SyncableItem.swift in Sources */,
4140EA702272899D0009F794 /* CommandParser.swift in Sources */,
9FDDD2DF289BEE590020C428 /* SyncJobScheduler.swift in Sources */,
Expand Down Expand Up @@ -2952,7 +2952,7 @@
416A29DA256AB6A900605395 /* BookPlayer.xcdatamodeld in Sources */,
418CABB625EF28FC00D8C878 /* MappingModel_v3_to_v4.xcmappingmodel in Sources */,
41ADD6DA2570AC6300660C64 /* RecentBooksWidgetView.swift in Sources */,
9FCC22902A172669003DD895 /* MappingModel_v8_to_v9.xcmappingmodel in Sources */,
9FF383D52A40F97000BBAC11 /* MappingModel_v8_to_v9.xcmappingmodel in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -3097,7 +3097,6 @@
9F22DE46288E517600056FCD /* AccountProBenefitsView.swift in Sources */,
4151A6A626E3A40600E49DBE /* SpeedService.swift in Sources */,
C33E843C20C6E179004A0489 /* ItemProgress.swift in Sources */,
9FCC228C2A172669003DD895 /* MappingModel_v8_to_v9.xcmappingmodel in Sources */,
62F2F25F25E18C7500E1D6A0 /* ImportableItem.swift in Sources */,
4158388B26EC2CC500F4A12B /* ImportCoordinator.swift in Sources */,
41A1B12E226FC7E500EA0400 /* ImportOperation.swift in Sources */,
Expand All @@ -3113,6 +3112,7 @@
41188D1E26ECDAA30017124E /* MiniPlayerViewModel.swift in Sources */,
41B2A5DE21CAF20E00917584 /* ThemesViewController.swift in Sources */,
41D20DAF25D5F5A100AAEE30 /* MappingModel_v1_to_v2.xcmappingmodel in Sources */,
9FF383D12A40F97000BBAC11 /* MappingModel_v8_to_v9.xcmappingmodel in Sources */,
9F134605293D0A410089B1DE /* ThemeViewModel.swift in Sources */,
41188D2A26ED4D8E0017124E /* ItemListViewModel.swift in Sources */,
C398559C20C492FF00BE9EC0 /* AddButton.swift in Sources */,
Expand Down Expand Up @@ -3217,7 +3217,6 @@
9FC1E45F2814F66F00522FA8 /* AccountAPI.swift in Sources */,
9FC1E4782816001400522FA8 /* KeychainService.swift in Sources */,
41A1B122226F88C500EA0400 /* PlaybackRecord+CoreDataProperties.swift in Sources */,
9FCC228E2A172669003DD895 /* MappingModel_v8_to_v9.xcmappingmodel in Sources */,
9F49072C2903663800054AD6 /* SortType.swift in Sources */,
9F1345B92938E0010089B1DE /* ImageIcons.swift in Sources */,
9FBDBC7D287940D900D315A2 /* ContentsResponse.swift in Sources */,
Expand All @@ -3230,6 +3229,7 @@
4138CE1326E554320014F11E /* Bookmark+CoreDataProperties.swift in Sources */,
41A1B123226F88C500EA0400 /* Book+CoreDataClass.swift in Sources */,
41A1B105226E9DBD00EA0400 /* UIColor+Sweetercolor.swift in Sources */,
9FF383D32A40F97000BBAC11 /* MappingModel_v8_to_v9.xcmappingmodel in Sources */,
41A1B10C226E9E9700EA0400 /* DeleteMode.swift in Sources */,
9FC1E44A2814C4DE00522FA8 /* NetworkClient.swift in Sources */,
9F07B72529B512F1005A939D /* LibraryItemSyncJob.swift in Sources */,
Expand Down
23 changes: 11 additions & 12 deletions BookPlayer/Coordinators/DataInitializerCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import Combine
import CoreData
import Foundation

class DataInitializerCoordinator {
class DataInitializerCoordinator: BPLogger {
let dataMigrationManager: DataMigrationManager
let alertPresenter: AlertPresenter

Expand All @@ -38,30 +38,28 @@ class DataInitializerCoordinator {
}

private func handleMigrations() {
guard self.dataMigrationManager.needsMigration() else {
self.loadLibrary()
guard dataMigrationManager.needsMigration() else {
loadLibrary()
return
}

do {
try self.dataMigrationManager.performMigration { [weak self] error in
if let error = error {
self?.alertPresenter.showAlert("error_title".localized, message: error.localizedDescription, completion: nil)
return
}

self?.handleMigrations()
try dataMigrationManager.performMigration {
self.handleMigrations()
}
} catch {
self.alertPresenter.showAlert("error_title".localized, message: error.localizedDescription, completion: nil)
Self.logger.info("Failed to perform migration")
loadLibrary()
}
}

func loadLibrary() {
Self.logger.info("Loading store")
let stack = self.dataMigrationManager.getCoreDataStack()

stack.loadStore { [weak self] _, error in
if let error = error {
Self.logger.error("Failed to load store")
self?.handleCoreDataError(error)
return
}
Expand Down Expand Up @@ -96,7 +94,8 @@ class DataInitializerCoordinator {
error.code == NSMigrationMissingMappingModelError ||
error.code == NSMigrationManagerSourceStoreError ||
error.code == NSMigrationManagerDestinationStoreError ||
error.code == NSEntityMigrationPolicyError {
error.code == NSEntityMigrationPolicyError ||
error.code == NSValidationMultipleErrorsError {
self.alertPresenter.showAlert("error_title".localized, message: "coredata_error_migration_description".localized) {
self.dataMigrationManager.cleanupStoreFile()
let urls = self.getLibraryFiles()
Expand Down
18 changes: 16 additions & 2 deletions BookPlayer/Coordinators/SettingsCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,14 @@ class SettingsCoordinator: Coordinator {

func showThemes() {
let viewModel = ThemesViewModel(accountService: self.accountService)
viewModel.coordinator = self

viewModel.onTransition = { [weak self] routes in
switch routes {
case .showPro:
self?.showPro()
}
}

let vc = ThemesViewController.instantiate(from: .Settings)
vc.viewModel = viewModel
vc.navigationItem.largeTitleDisplayMode = .never
Expand All @@ -106,7 +113,14 @@ class SettingsCoordinator: Coordinator {

func showIcons() {
let viewModel = IconsViewModel(accountService: self.accountService)
viewModel.coordinator = self

viewModel.onTransition = { [weak self] routes in
switch routes {
case .showPro:
self?.showPro()
}
}

let vc = IconsViewController.instantiate(from: .Settings)
vc.viewModel = viewModel
vc.navigationItem.largeTitleDisplayMode = .never
Expand Down
46 changes: 42 additions & 4 deletions BookPlayer/Settings/Icons Screen/IconsViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ class IconsViewController: UIViewController, Storyboarded {
target: self,
action: #selector(self.didPressClose)
)
self.navigationItem.rightBarButtonItem = UIBarButtonItem(
title: "restore_title".localized,
style: .plain,
target: self,
action: #selector(self.didPressRestore)
)

self.icons = self.getIcons()

Expand All @@ -45,6 +51,32 @@ class IconsViewController: UIViewController, Storyboarded {
self.bannerView.showPlus = { [weak self] in
self?.viewModel.showPro()
}

bindDataItems()
}

func bindDataItems() {
self.viewModel.observeEvents()
.receive(on: DispatchQueue.main)
.sink { [weak self] event in
switch event {
case .showAlert(let content):
self?.showAlert(content)
case .showLoader(let flag):
self?.showLoader(flag)
case .donationMade:
self?.donationMade()
}
}
.store(in: &disposeBag)
}

func showLoader(_ flag: Bool) {
if flag {
LoadingUtils.loadAndBlock(in: self)
} else {
LoadingUtils.stopLoading(in: self)
}
}

func handleDonationObserver() {
Expand All @@ -66,11 +98,17 @@ class IconsViewController: UIViewController, Storyboarded {
self.dismiss(animated: true, completion: nil)
}

@objc func donationMade() {
self.bannerView.isHidden = true
self.bannerHeightConstraint.constant = 0
self.tableView.reloadData()
@objc func didPressRestore() {
viewModel.handleRestorePurchases()
}

@objc func donationMade() {
if self.viewModel.hasSubscription {
self.bannerView.isHidden = true
self.bannerHeightConstraint.constant = 0
}
self.tableView.reloadData()
}

func getIcons() -> [Icon] {
guard
Expand Down
76 changes: 73 additions & 3 deletions BookPlayer/Settings/Icons Screen/IconsViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,18 @@ import BookPlayerKit
import Combine

final class IconsViewModel {
weak var coordinator: SettingsCoordinator!
/// Available routes for this screen
enum Routes {
case showPro
}

/// Events that the screen can handle
enum Events {
case showAlert(content: BPAlertContent)
case showLoader(Bool)
case donationMade
}

let accountService: AccountServiceProtocol

@Published var account: Account?
Expand All @@ -19,6 +30,11 @@ final class IconsViewModel {
return account?.hasSubscription == true
}

/// Callback to handle actions on this screen
public var onTransition: Transition<Routes>?
/// Events publisher
private var eventsPublisher = InterfaceUpdater<IconsViewModel.Events>()

private var disposeBag = Set<AnyCancellable>()

init(accountService: AccountServiceProtocol) {
Expand All @@ -28,14 +44,22 @@ final class IconsViewModel {
self.bindObservers()
}

func bindObservers() {
func observeEvents() -> AnyPublisher<IconsViewModel.Events, Never> {
eventsPublisher.eraseToAnyPublisher()
}

private func bindObservers() {
NotificationCenter.default.publisher(for: .accountUpdate, object: nil)
.sink(receiveValue: { [weak self] _ in
self?.reloadAccount()
})
.store(in: &disposeBag)
}

private func sendEvent(_ event: IconsViewModel.Events) {
eventsPublisher.send(event)
}

func reloadAccount() {
self.account = self.accountService.getAccount()
}
Expand All @@ -45,6 +69,52 @@ final class IconsViewModel {
}

func showPro() {
self.coordinator.showPro()
onTransition?(.showPro)
}

func handleRestorePurchases() {
Task { @MainActor [weak self] in
guard let self = self else { return }

self.sendEvent(.showLoader(true))

do {
let customerInfo = try await self.accountService.restorePurchases()

self.sendEvent(.showLoader(false))

if customerInfo.nonSubscriptions.isEmpty {
self.sendEvent(.showAlert(
content: BPAlertContent(
title: "tip_missing_title".localized,
style: .alert,
actionItems: [BPActionItem.okAction]
)
))
} else {
self.accountService.updateAccount(
id: nil,
email: nil,
donationMade: true,
hasSubscription: nil
)

self.sendEvent(.showAlert(
content: BPAlertContent(
title: "purchases_restored_title".localized,
style: .alert,
actionItems: [BPActionItem.okAction]
)
))

self.sendEvent(.donationMade)
}
} catch {
self.sendEvent(.showLoader(false))
self.sendEvent(.showAlert(
content: BPAlertContent.errorAlert(message: error.localizedDescription)
))
}
}
}
}
Loading

0 comments on commit e390c67

Please sign in to comment.