From a1e062c585ff4938a52ac50cda44f89742659863 Mon Sep 17 00:00:00 2001 From: Gianni Carlo Date: Mon, 12 Jun 2023 07:25:44 -0500 Subject: [PATCH 1/4] Pass environmentObject and remove coordinator --- BookPlayer.xcodeproj/project.pbxproj | 4 -- .../Coordinators/ItemDetailsCoordinator.swift | 69 ------------------- .../Coordinators/ItemListCoordinator.swift | 22 +++--- .../ClearableTextField.swift | 2 +- .../ItemDetailsViewController.swift | 2 +- .../ItemDetailsViewModel.swift | 2 +- .../Views/ItemDetailsArtworkSectionView.swift | 2 +- .../Views/ItemDetailsForm.swift | 1 + .../Views/ItemDetailsView.swift | 2 +- .../PricingOptionsView.swift | 2 + .../PricingRowView.swift | 2 +- .../Profile/Profile Screen/ProfileView.swift | 17 ++--- .../QueuedSyncTaskRowView.swift | 2 +- .../Profile Screen/QueuedSyncTasksView.swift | 2 + .../Views/ProfileCardView.swift | 7 +- .../Views/ProfileListenedTimeView.swift | 5 +- 16 files changed, 37 insertions(+), 106 deletions(-) delete mode 100644 BookPlayer/Coordinators/ItemDetailsCoordinator.swift diff --git a/BookPlayer.xcodeproj/project.pbxproj b/BookPlayer.xcodeproj/project.pbxproj index 101548f4a..3b9df79aa 100644 --- a/BookPlayer.xcodeproj/project.pbxproj +++ b/BookPlayer.xcodeproj/project.pbxproj @@ -385,7 +385,6 @@ 9F5F13682978D9E100F061A0 /* ProfileSyncTasksStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F5F13672978D9E100F061A0 /* ProfileSyncTasksStatusView.swift */; }; 9F5FBB08293EDCD8009F4B0E /* ItemDetailsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F5FBB07293EDCD8009F4B0E /* ItemDetailsViewController.swift */; }; 9F5FBB0A293EE0C2009F4B0E /* ItemDetailsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F5FBB09293EE0C2009F4B0E /* ItemDetailsViewModel.swift */; }; - 9F5FBB0E293EE116009F4B0E /* ItemDetailsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F5FBB0D293EE116009F4B0E /* ItemDetailsCoordinator.swift */; }; 9F646006283AD6B700710D3C /* PlayerSettingsViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F646005283AD6B700710D3C /* PlayerSettingsViewModelTests.swift */; }; 9F64C6212793C31600B2493C /* PlayerControlsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F64C6202793C31600B2493C /* PlayerControlsCoordinator.swift */; }; 9F64C6242793C3DA00B2493C /* PlayerControlsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F64C6232793C3DA00B2493C /* PlayerControlsViewModel.swift */; }; @@ -1037,7 +1036,6 @@ 9F5F13672978D9E100F061A0 /* ProfileSyncTasksStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileSyncTasksStatusView.swift; sourceTree = ""; }; 9F5FBB07293EDCD8009F4B0E /* ItemDetailsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemDetailsViewController.swift; sourceTree = ""; }; 9F5FBB09293EE0C2009F4B0E /* ItemDetailsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemDetailsViewModel.swift; sourceTree = ""; }; - 9F5FBB0D293EE116009F4B0E /* ItemDetailsCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemDetailsCoordinator.swift; sourceTree = ""; }; 9F646005283AD6B700710D3C /* PlayerSettingsViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerSettingsViewModelTests.swift; sourceTree = ""; }; 9F64C6202793C31600B2493C /* PlayerControlsCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerControlsCoordinator.swift; sourceTree = ""; }; 9F64C6232793C3DA00B2493C /* PlayerControlsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerControlsViewModel.swift; sourceTree = ""; }; @@ -1376,7 +1374,6 @@ 4158386826EAF4A300F4A12B /* ItemListCoordinator.swift */, 4158388226EBD76A00F4A12B /* LibraryListCoordinator.swift */, 4158386D26EAF76700F4A12B /* FolderListCoordinator.swift */, - 9F5FBB0D293EE116009F4B0E /* ItemDetailsCoordinator.swift */, 4158388426EBEE9800F4A12B /* PlayerCoordinator.swift */, 4158388A26EC2CC500F4A12B /* ImportCoordinator.swift */, 41188D1F26ECDDD50017124E /* BookmarkCoordinator.swift */, @@ -2985,7 +2982,6 @@ 9FBDDBA227DD13FA005FB447 /* ProfileCoordinator.swift in Sources */, 9F22DE39288CBE6A00056FCD /* FormButton.swift in Sources */, 4151A6A826E48C3400E49DBE /* Storyboarded.swift in Sources */, - 9F5FBB0E293EE116009F4B0E /* ItemDetailsCoordinator.swift in Sources */, 9F00A5FC294F9B9A005EA316 /* ItemDetailsForm.swift in Sources */, 9F7B647C2804798800895ECC /* IconsViewModel.swift in Sources */, 9F3D0CE728C2BF7700E9E8A3 /* ButtonFreeViewModel.swift in Sources */, diff --git a/BookPlayer/Coordinators/ItemDetailsCoordinator.swift b/BookPlayer/Coordinators/ItemDetailsCoordinator.swift deleted file mode 100644 index 061567fcf..000000000 --- a/BookPlayer/Coordinators/ItemDetailsCoordinator.swift +++ /dev/null @@ -1,69 +0,0 @@ -// -// ItemDetailsCoordinator.swift -// BookPlayer -// -// Created by gianni.carlo on 5/12/22. -// Copyright © 2022 Tortuga Power. All rights reserved. -// - -import BookPlayerKit -import SwiftUI -import UIKit - -class ItemDetailsCoordinator: Coordinator { - /// Routes for this coordinator - public enum Routes { - case infoUpdated - } - /// Item being modified - let item: SimpleLibraryItem - /// Library service used for modifications - let libraryService: LibraryServiceProtocol - /// Service to sync new artwork - let syncService: SyncServiceProtocol - /// Weak reference to the navigation used to show the flow - weak var flowNav: UINavigationController? - /// Callback when the coordinator is done - public var onFinish: ((Routes) -> Void)? - - /// Initializer - init( - item: SimpleLibraryItem, - libraryService: LibraryServiceProtocol, - syncService: SyncServiceProtocol, - navigationController: UINavigationController - ) { - self.item = item - self.libraryService = libraryService - self.syncService = syncService - - super.init( - navigationController: navigationController, - flowType: .modal - ) - } - - override func start() { - let viewModel = ItemDetailsViewModel( - item: item, - libraryService: libraryService, - syncService: syncService - ) - viewModel.onTransition = { route in - switch route { - case .done: - self.onFinish?(.infoUpdated) - case .cancel: - /// do nothing on cancel - break - } - self.flowNav?.dismiss(animated: true) - } - let vc = ItemDetailsViewController(viewModel: viewModel) - let nav = AppNavigationController.instantiate(from: .Main) - nav.viewControllers = [vc] - flowNav = nav - - navigationController.present(nav, animated: true) - } -} diff --git a/BookPlayer/Coordinators/ItemListCoordinator.swift b/BookPlayer/Coordinators/ItemListCoordinator.swift index 62dcfaae1..2f3c98ff3 100644 --- a/BookPlayer/Coordinators/ItemListCoordinator.swift +++ b/BookPlayer/Coordinators/ItemListCoordinator.swift @@ -172,21 +172,27 @@ extension ItemListCoordinator { } func showItemDetails(_ item: SimpleLibraryItem) { - let coordinator = ItemDetailsCoordinator( + let viewModel = ItemDetailsViewModel( item: item, libraryService: libraryService, - syncService: syncService, - navigationController: navigationController + syncService: syncService ) - - coordinator.onFinish = { route in + viewModel.onTransition = { [weak self] route in switch route { - case .infoUpdated: - self.reloadItemsWithPadding() + case .done: + self?.reloadItemsWithPadding() + case .cancel: + /// do nothing on cancel + break } + self?.navigationController.dismiss(animated: true) } - coordinator.start() + let vc = ItemDetailsViewController(viewModel: viewModel) + let nav = AppNavigationController.instantiate(from: .Main) + nav.viewControllers = [vc] + + navigationController.present(nav, animated: true, completion: nil) } func showItemSelectionScreen( diff --git a/BookPlayer/Library/ItemDetails Screen/ClearableTextField.swift b/BookPlayer/Library/ItemDetails Screen/ClearableTextField.swift index 502424c36..a6037dcb7 100644 --- a/BookPlayer/Library/ItemDetails Screen/ClearableTextField.swift +++ b/BookPlayer/Library/ItemDetails Screen/ClearableTextField.swift @@ -15,7 +15,7 @@ struct ClearableTextField: View { /// Input's text @Binding var text: String /// Current theme - @StateObject var themeViewModel = ThemeViewModel() + @EnvironmentObject var themeViewModel: ThemeViewModel init(_ placeholder: String, text: Binding) { self.placeholder = placeholder diff --git a/BookPlayer/Library/ItemDetails Screen/ItemDetailsViewController.swift b/BookPlayer/Library/ItemDetails Screen/ItemDetailsViewController.swift index 1a49d2763..b7f1be5e3 100644 --- a/BookPlayer/Library/ItemDetails Screen/ItemDetailsViewController.swift +++ b/BookPlayer/Library/ItemDetails Screen/ItemDetailsViewController.swift @@ -12,7 +12,7 @@ import SwiftUI import Themeable import UIKit -class ItemDetailsViewController: BaseViewController { +class ItemDetailsViewController: BaseViewController { // MARK: - UI components private lazy var detailsView: UIView = { diff --git a/BookPlayer/Library/ItemDetails Screen/ItemDetailsViewModel.swift b/BookPlayer/Library/ItemDetails Screen/ItemDetailsViewModel.swift index 5ce2f1584..ebe8820eb 100644 --- a/BookPlayer/Library/ItemDetails Screen/ItemDetailsViewModel.swift +++ b/BookPlayer/Library/ItemDetails Screen/ItemDetailsViewModel.swift @@ -10,7 +10,7 @@ import Foundation import BookPlayerKit import Combine -class ItemDetailsViewModel: BaseViewModel { +class ItemDetailsViewModel: BaseViewModel { /// Possible routes for the screen enum Routes { case cancel diff --git a/BookPlayer/Library/ItemDetails Screen/Views/ItemDetailsArtworkSectionView.swift b/BookPlayer/Library/ItemDetails Screen/Views/ItemDetailsArtworkSectionView.swift index 6fd9bbd72..009e53387 100644 --- a/BookPlayer/Library/ItemDetails Screen/Views/ItemDetailsArtworkSectionView.swift +++ b/BookPlayer/Library/ItemDetails Screen/Views/ItemDetailsArtworkSectionView.swift @@ -15,7 +15,7 @@ struct ItemDetailsArtworkSectionView: View { /// Callback for action handler var actionHandler: () -> Void /// Theme view model to update colors - @StateObject var themeViewModel = ThemeViewModel() + @EnvironmentObject var themeViewModel: ThemeViewModel var body: some View { Section( diff --git a/BookPlayer/Library/ItemDetails Screen/Views/ItemDetailsForm.swift b/BookPlayer/Library/ItemDetails Screen/Views/ItemDetailsForm.swift index efdba47d2..037039955 100644 --- a/BookPlayer/Library/ItemDetails Screen/Views/ItemDetailsForm.swift +++ b/BookPlayer/Library/ItemDetails Screen/Views/ItemDetailsForm.swift @@ -69,6 +69,7 @@ struct ItemDetailsForm: View { dismissButton: .default(Text("ok_button".localized)) ) } + .environmentObject(themeViewModel) } } diff --git a/BookPlayer/Library/ItemDetails Screen/Views/ItemDetailsView.swift b/BookPlayer/Library/ItemDetails Screen/Views/ItemDetailsView.swift index 6fc67333f..c2c15a96f 100644 --- a/BookPlayer/Library/ItemDetails Screen/Views/ItemDetailsView.swift +++ b/BookPlayer/Library/ItemDetails Screen/Views/ItemDetailsView.swift @@ -15,7 +15,7 @@ struct ItemDetailsView: View { var body: some View { if #available(iOS 16.0, *) { ItemDetailsForm(viewModel: viewModel) - .scrollContentBackground(.hidden) + .scrollContentBackground(.hidden) } else { ItemDetailsForm(viewModel: viewModel) } diff --git a/BookPlayer/Profile/CompleteAccount Screen/PricingOptionsView.swift b/BookPlayer/Profile/CompleteAccount Screen/PricingOptionsView.swift index 16adbd71f..3acd79005 100644 --- a/BookPlayer/Profile/CompleteAccount Screen/PricingOptionsView.swift +++ b/BookPlayer/Profile/CompleteAccount Screen/PricingOptionsView.swift @@ -11,6 +11,7 @@ import SwiftUI struct PricingOptionsView: View { @ObservedObject var viewModel: PricingViewModel + @StateObject var themeViewModel = ThemeViewModel() var body: some View { VStack(spacing: Spacing.S1) { @@ -25,6 +26,7 @@ struct PricingOptionsView: View { } } } + .environmentObject(themeViewModel) } } diff --git a/BookPlayer/Profile/CompleteAccount Screen/PricingRowView.swift b/BookPlayer/Profile/CompleteAccount Screen/PricingRowView.swift index c12743c0b..28c4990ec 100644 --- a/BookPlayer/Profile/CompleteAccount Screen/PricingRowView.swift +++ b/BookPlayer/Profile/CompleteAccount Screen/PricingRowView.swift @@ -14,7 +14,7 @@ struct PricingRowView: View { @Binding var isSelected: Bool @Binding var isLoading: Bool /// Theme view model to update colors - @StateObject var themeViewModel = ThemeViewModel() + @EnvironmentObject var themeViewModel: ThemeViewModel var imageLength: CGFloat = 24 diff --git a/BookPlayer/Profile/Profile Screen/ProfileView.swift b/BookPlayer/Profile/Profile Screen/ProfileView.swift index 948384489..f87c4555e 100644 --- a/BookPlayer/Profile/Profile Screen/ProfileView.swift +++ b/BookPlayer/Profile/Profile Screen/ProfileView.swift @@ -17,18 +17,14 @@ struct ProfileView: View { GeometryReader { geometryProxy in ScrollView { VStack(spacing: Spacing.M) { - ProfileCardView( - account: $viewModel.account, - themeViewModel: themeViewModel - ) - .onTapGesture { - viewModel.showAccount() - } - .padding([.top, .trailing, .leading], Spacing.S) + ProfileCardView(account: $viewModel.account) + .onTapGesture { + viewModel.showAccount() + } + .padding([.top, .trailing, .leading], Spacing.S) ProfileListenedTimeView( - formattedListeningTime: $viewModel.totalListeningTimeFormatted, - themeViewModel: themeViewModel + formattedListeningTime: $viewModel.totalListeningTimeFormatted ) Spacer() @@ -50,6 +46,7 @@ struct ProfileView: View { .frame(maxWidth: .infinity, minHeight: geometryProxy.size.height) } } + .environmentObject(themeViewModel) } } diff --git a/BookPlayer/Profile/Profile Screen/QueuedSyncTaskRowView.swift b/BookPlayer/Profile/Profile Screen/QueuedSyncTaskRowView.swift index d255831fa..5bf0eeff2 100644 --- a/BookPlayer/Profile/Profile Screen/QueuedSyncTaskRowView.swift +++ b/BookPlayer/Profile/Profile Screen/QueuedSyncTaskRowView.swift @@ -13,7 +13,7 @@ struct QueuedSyncTaskRowView: View { @Binding var imageName: String @Binding var title: String - @StateObject var themeViewModel = ThemeViewModel() + @EnvironmentObject var themeViewModel: ThemeViewModel var body: some View { HStack { diff --git a/BookPlayer/Profile/Profile Screen/QueuedSyncTasksView.swift b/BookPlayer/Profile/Profile Screen/QueuedSyncTasksView.swift index 16a754fac..9a931732f 100644 --- a/BookPlayer/Profile/Profile Screen/QueuedSyncTasksView.swift +++ b/BookPlayer/Profile/Profile Screen/QueuedSyncTasksView.swift @@ -46,6 +46,7 @@ struct QueuedSyncTasksView: View { } } .scrollContentBackground(.hidden) + .environmentObject(themeViewModel) } else { List { ForEach(viewModel.queuedJobs) { job in @@ -55,6 +56,7 @@ struct QueuedSyncTasksView: View { ) } } + .environmentObject(themeViewModel) } } } diff --git a/BookPlayer/Profile/Profile Screen/Views/ProfileCardView.swift b/BookPlayer/Profile/Profile Screen/Views/ProfileCardView.swift index 2731371fd..ad5d15ebd 100644 --- a/BookPlayer/Profile/Profile Screen/Views/ProfileCardView.swift +++ b/BookPlayer/Profile/Profile Screen/Views/ProfileCardView.swift @@ -16,7 +16,7 @@ struct ProfileCardView: View { var cornerRadius: CGFloat = 10 @Binding var account: Account? - @ObservedObject var themeViewModel: ThemeViewModel + @EnvironmentObject var themeViewModel: ThemeViewModel var title: String { if let account, @@ -72,9 +72,6 @@ struct ProfileCardView: View { struct ProfileCardView_Previews: PreviewProvider { static var previews: some View { - ProfileCardView( - account: .constant(Account()), - themeViewModel: ThemeViewModel() - ) + ProfileCardView(account: .constant(Account())) } } diff --git a/BookPlayer/Profile/Profile Screen/Views/ProfileListenedTimeView.swift b/BookPlayer/Profile/Profile Screen/Views/ProfileListenedTimeView.swift index 3285978ec..c682106ea 100644 --- a/BookPlayer/Profile/Profile Screen/Views/ProfileListenedTimeView.swift +++ b/BookPlayer/Profile/Profile Screen/Views/ProfileListenedTimeView.swift @@ -11,7 +11,7 @@ import SwiftUI struct ProfileListenedTimeView: View { @Binding var formattedListeningTime: String - @ObservedObject var themeViewModel: ThemeViewModel + @EnvironmentObject var themeViewModel: ThemeViewModel var body: some View { VStack { @@ -28,8 +28,7 @@ struct ProfileListenedTimeView: View { struct ProfileStatsView_Previews: PreviewProvider { static var previews: some View { ProfileListenedTimeView( - formattedListeningTime: .constant("0m"), - themeViewModel: ThemeViewModel() + formattedListeningTime: .constant("0m") ) } } From d0757e4532712c9b0f038c3d6cc4d03cfc4ba231 Mon Sep 17 00:00:00 2001 From: Gianni Carlo Date: Mon, 12 Jun 2023 07:26:45 -0500 Subject: [PATCH 2/4] Update mocks --- BookPlayer/Generated/AutoMockable.generated.swift | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/BookPlayer/Generated/AutoMockable.generated.swift b/BookPlayer/Generated/AutoMockable.generated.swift index 937a0122b..b66b137ba 100644 --- a/BookPlayer/Generated/AutoMockable.generated.swift +++ b/BookPlayer/Generated/AutoMockable.generated.swift @@ -1469,22 +1469,18 @@ class SyncServiceProtocolMock: SyncServiceProtocol { } //MARK: - scheduleUpload - var scheduleUploadItemsThrowableError: Error? var scheduleUploadItemsCallsCount = 0 var scheduleUploadItemsCalled: Bool { return scheduleUploadItemsCallsCount > 0 } var scheduleUploadItemsReceivedItems: [SimpleLibraryItem]? var scheduleUploadItemsReceivedInvocations: [[SimpleLibraryItem]] = [] - var scheduleUploadItemsClosure: (([SimpleLibraryItem]) throws -> Void)? - func scheduleUpload(items: [SimpleLibraryItem]) throws { - if let error = scheduleUploadItemsThrowableError { - throw error - } + var scheduleUploadItemsClosure: (([SimpleLibraryItem]) -> Void)? + func scheduleUpload(items: [SimpleLibraryItem]) { scheduleUploadItemsCallsCount += 1 scheduleUploadItemsReceivedItems = items scheduleUploadItemsReceivedInvocations.append(items) - try scheduleUploadItemsClosure?(items) + scheduleUploadItemsClosure?(items) } //MARK: - scheduleDelete From 45d897c3afa5f69beeede974a16ee0333acffa2a Mon Sep 17 00:00:00 2001 From: Gianni Carlo Date: Mon, 12 Jun 2023 08:31:29 -0500 Subject: [PATCH 3/4] Separate title and author sections --- BookPlayer/Base.lproj/Localizable.strings | 4 +- .../ItemDetailsFormViewModel.swift | 6 ++ .../ItemDetailsViewModel.swift | 84 ++++++++++++------- .../Views/ItemDetailsForm.swift | 16 ++-- BookPlayer/ar.lproj/Localizable.strings | 4 +- BookPlayer/cs.lproj/Localizable.strings | 4 +- BookPlayer/da.lproj/Localizable.strings | 4 +- BookPlayer/de.lproj/Localizable.strings | 4 +- BookPlayer/en.lproj/Localizable.strings | 4 +- BookPlayer/es.lproj/Localizable.strings | 4 +- BookPlayer/fi.lproj/Localizable.strings | 4 +- BookPlayer/fr.lproj/Localizable.strings | 4 +- BookPlayer/hu.lproj/Localizable.strings | 4 +- BookPlayer/it.lproj/Localizable.strings | 4 +- BookPlayer/nl.lproj/Localizable.strings | 4 +- BookPlayer/pl.lproj/Localizable.strings | 4 +- BookPlayer/pt-BR.lproj/Localizable.strings | 4 +- BookPlayer/ro.lproj/Localizable.strings | 4 +- BookPlayer/ru.lproj/Localizable.strings | 4 +- BookPlayer/sk-SK.lproj/Localizable.strings | 4 +- BookPlayer/sv.lproj/Localizable.strings | 4 +- BookPlayer/tr.lproj/Localizable.strings | 4 +- BookPlayer/uk.lproj/Localizable.strings | 4 +- BookPlayer/zh-Hans.lproj/Localizable.strings | 4 +- 24 files changed, 114 insertions(+), 76 deletions(-) diff --git a/BookPlayer/Base.lproj/Localizable.strings b/BookPlayer/Base.lproj/Localizable.strings index 821358c70..4bee59954 100644 --- a/BookPlayer/Base.lproj/Localizable.strings +++ b/BookPlayer/Base.lproj/Localizable.strings @@ -234,8 +234,8 @@ "search_title" = "Search"; "books_title" = "Books"; "folders_title" = "Folders"; -"item_title_placeholder" = "Title"; -"item_author_placeholder" = "Author"; +"section_item_title" = "Title"; +"section_item_author" = "Author"; "artwork_options_title" = "Artwork options"; "artwork_photolibrary_title" = "Choose from Photo Library"; "artwork_clipboard_title" = "Paste from clipboard"; diff --git a/BookPlayer/Library/ItemDetails Screen/ItemDetailsFormViewModel.swift b/BookPlayer/Library/ItemDetails Screen/ItemDetailsFormViewModel.swift index 1570f6f83..8b8970da9 100644 --- a/BookPlayer/Library/ItemDetails Screen/ItemDetailsFormViewModel.swift +++ b/BookPlayer/Library/ItemDetails Screen/ItemDetailsFormViewModel.swift @@ -18,6 +18,10 @@ class ItemDetailsFormViewModel: ObservableObject { @Published var author: String /// Artwork image @Published var selectedImage: UIImage? + /// Original item title + var titlePlaceholder: String + /// Original item author + var authorPlaceholder: String /// Determines if there's an update for the artwork var artworkIsUpdated: Bool = false /// Flag to show the author field @@ -28,7 +32,9 @@ class ItemDetailsFormViewModel: ObservableObject { /// Initializer init(item: SimpleLibraryItem) { self.title = item.title + self.titlePlaceholder = item.title self.author = item.details + self.authorPlaceholder = item.details self.showAuthor = item.type == .book self.originalImageDataProvider = ArtworkService.getArtworkProvider(for: item.relativePath) let cachedImageURL = ArtworkService.getCachedImageURL(for: item.relativePath) diff --git a/BookPlayer/Library/ItemDetails Screen/ItemDetailsViewModel.swift b/BookPlayer/Library/ItemDetails Screen/ItemDetailsViewModel.swift index ebe8820eb..c935f9fe5 100644 --- a/BookPlayer/Library/ItemDetails Screen/ItemDetailsViewModel.swift +++ b/BookPlayer/Library/ItemDetails Screen/ItemDetailsViewModel.swift @@ -57,39 +57,18 @@ class ItemDetailsViewModel: BaseViewModel { onTransition?(.cancel) } - // swiftlint:disable:next function_body_length func handleSaveAction() { - var cacheKey = item.relativePath + let cacheKey: String - let storedTitle = libraryService.getItemProperty( - #keyPath(LibraryItem.title), - relativePath: item.relativePath - ) as? String - - if storedTitle != formViewModel.title { - switch item.type { - case .book: - libraryService.renameBook(at: item.relativePath, with: formViewModel.title) - case .bound, .folder: - do { - let newRelativePath = try libraryService.renameFolder(at: item.relativePath, with: formViewModel.title) - cacheKey = newRelativePath - syncService.scheduleRenameFolder(at: item.relativePath, name: formViewModel.title) - } catch { - sendEvent(.showAlert(content: BPAlertContent.errorAlert(message: error.localizedDescription))) - return - } - } + do { + cacheKey = try updateTitle(formViewModel.title, relativePath: item.relativePath) + } catch { + sendEvent(.showAlert(content: BPAlertContent.errorAlert(message: error.localizedDescription))) + return } - let storedDetails = libraryService.getItemProperty( - #keyPath(LibraryItem.details), - relativePath: item.relativePath - ) as? String - - if formViewModel.showAuthor, - storedDetails != formViewModel.author { - libraryService.updateDetails(at: item.relativePath, details: formViewModel.author) + if formViewModel.showAuthor { + updateAuthor(formViewModel.author, relativePath: item.relativePath) } guard formViewModel.artworkIsUpdated else { @@ -120,6 +99,53 @@ class ItemDetailsViewModel: BaseViewModel { } } + /// Update the item title if necessary + /// - Returns: The new relative path to be used as the cache key + func updateTitle(_ newTitle: String, relativePath: String) throws -> String { + var cacheKey = relativePath + let cleanedTitle = newTitle.trimmingCharacters(in: .whitespacesAndNewlines) + + guard !cleanedTitle.isEmpty else { + return cacheKey + } + + let storedTitle = libraryService.getItemProperty( + #keyPath(LibraryItem.title), + relativePath: relativePath + ) as? String + + guard storedTitle != cleanedTitle else { + return cacheKey + } + + switch item.type { + case .book: + libraryService.renameBook(at: relativePath, with: cleanedTitle) + case .bound, .folder: + let newRelativePath = try libraryService.renameFolder(at: relativePath, with: cleanedTitle) + cacheKey = newRelativePath + syncService.scheduleRenameFolder(at: relativePath, name: cleanedTitle) + } + + return cacheKey + } + + /// Update the item's author if necessary + func updateAuthor(_ newAuthor: String, relativePath: String) { + let cleanedAuthor = newAuthor.trimmingCharacters(in: .whitespacesAndNewlines) + + guard !cleanedAuthor.isEmpty else { return } + + let storedDetails = libraryService.getItemProperty( + #keyPath(LibraryItem.details), + relativePath: relativePath + ) as? String + + guard storedDetails != cleanedAuthor else { return } + + libraryService.updateDetails(at: relativePath, details: cleanedAuthor) + } + private func sendEvent(_ event: ItemDetailsViewModel.Events) { eventsPublisher.send(event) } diff --git a/BookPlayer/Library/ItemDetails Screen/Views/ItemDetailsForm.swift b/BookPlayer/Library/ItemDetails Screen/Views/ItemDetailsForm.swift index 037039955..2329bb469 100644 --- a/BookPlayer/Library/ItemDetails Screen/Views/ItemDetailsForm.swift +++ b/BookPlayer/Library/ItemDetails Screen/Views/ItemDetailsForm.swift @@ -24,16 +24,22 @@ struct ItemDetailsForm: View { var body: some View { Form { - Section(header: Text("details_title".localized) + Section(header: Text("section_item_title".localized) .foregroundColor(themeViewModel.secondaryColor) ) { - ClearableTextField("item_title_placeholder".localized, text: $viewModel.title) - if viewModel.showAuthor { - ClearableTextField("item_author_placeholder".localized, text: $viewModel.author) - } + ClearableTextField(viewModel.titlePlaceholder, text: $viewModel.title) } .listRowBackground(themeViewModel.secondarySystemBackgroundColor) + if viewModel.showAuthor { + Section(header: Text("section_item_author".localized) + .foregroundColor(themeViewModel.secondaryColor) + ) { + ClearableTextField(viewModel.authorPlaceholder, text: $viewModel.author) + } + .listRowBackground(themeViewModel.secondarySystemBackgroundColor) + } + ItemDetailsArtworkSectionView(image: $viewModel.selectedImage) { showingArtworkOptions = true } diff --git a/BookPlayer/ar.lproj/Localizable.strings b/BookPlayer/ar.lproj/Localizable.strings index dc9d8b2ca..d3786157b 100644 --- a/BookPlayer/ar.lproj/Localizable.strings +++ b/BookPlayer/ar.lproj/Localizable.strings @@ -234,8 +234,8 @@ "search_title" = "يبحث"; "books_title" = "كتب"; "folders_title" = "المجلدات"; -"item_title_placeholder" = "عنوان"; -"item_author_placeholder" = "مؤلف"; +"section_item_title" = "عنوان"; +"section_item_author" = "مؤلف"; "artwork_options_title" = "خيارات العمل الفني"; "artwork_photolibrary_title" = "اختر من مكتبة الصور"; "artwork_clipboard_title" = "لصق من الحافظة"; diff --git a/BookPlayer/cs.lproj/Localizable.strings b/BookPlayer/cs.lproj/Localizable.strings index 81d876c1d..881075c2b 100644 --- a/BookPlayer/cs.lproj/Localizable.strings +++ b/BookPlayer/cs.lproj/Localizable.strings @@ -234,8 +234,8 @@ "search_title" = "Vyhledávání"; "books_title" = "knihy"; "folders_title" = "Složky"; -"item_title_placeholder" = "Titul"; -"item_author_placeholder" = "Autor"; +"section_item_title" = "Titul"; +"section_item_author" = "Autor"; "artwork_options_title" = "Možnosti uměleckého díla"; "artwork_photolibrary_title" = "Vyberte si z knihovny fotografií"; "artwork_clipboard_title" = "Vložit ze schránky"; diff --git a/BookPlayer/da.lproj/Localizable.strings b/BookPlayer/da.lproj/Localizable.strings index e5851cea2..aeca0e384 100644 --- a/BookPlayer/da.lproj/Localizable.strings +++ b/BookPlayer/da.lproj/Localizable.strings @@ -234,8 +234,8 @@ "search_title" = "Søg"; "books_title" = "Bøger"; "folders_title" = "Mapper"; -"item_title_placeholder" = "Titel"; -"item_author_placeholder" = "Forfatter"; +"section_item_title" = "Titel"; +"section_item_author" = "Forfatter"; "artwork_options_title" = "Muligheder for kunstværker"; "artwork_photolibrary_title" = "Vælg fra Fotobibliotek"; "artwork_clipboard_title" = "Indsæt fra udklipsholder"; diff --git a/BookPlayer/de.lproj/Localizable.strings b/BookPlayer/de.lproj/Localizable.strings index e5a99ff34..31c03b1ea 100644 --- a/BookPlayer/de.lproj/Localizable.strings +++ b/BookPlayer/de.lproj/Localizable.strings @@ -234,8 +234,8 @@ "search_title" = "Suchen"; "books_title" = "Bücher"; "folders_title" = "Ordner"; -"item_title_placeholder" = "Titel"; -"item_author_placeholder" = "Autor"; +"section_item_title" = "Titel"; +"section_item_author" = "Autor"; "artwork_options_title" = "Artwork-Optionen"; "artwork_photolibrary_title" = "Wählen Sie aus der Fotobibliothek"; "artwork_clipboard_title" = "Aus Zwischenablage einfügen"; diff --git a/BookPlayer/en.lproj/Localizable.strings b/BookPlayer/en.lproj/Localizable.strings index 821358c70..4bee59954 100644 --- a/BookPlayer/en.lproj/Localizable.strings +++ b/BookPlayer/en.lproj/Localizable.strings @@ -234,8 +234,8 @@ "search_title" = "Search"; "books_title" = "Books"; "folders_title" = "Folders"; -"item_title_placeholder" = "Title"; -"item_author_placeholder" = "Author"; +"section_item_title" = "Title"; +"section_item_author" = "Author"; "artwork_options_title" = "Artwork options"; "artwork_photolibrary_title" = "Choose from Photo Library"; "artwork_clipboard_title" = "Paste from clipboard"; diff --git a/BookPlayer/es.lproj/Localizable.strings b/BookPlayer/es.lproj/Localizable.strings index 0195b39af..804185e2d 100644 --- a/BookPlayer/es.lproj/Localizable.strings +++ b/BookPlayer/es.lproj/Localizable.strings @@ -234,8 +234,8 @@ "search_title" = "Buscar"; "books_title" = "Libros"; "folders_title" = "Carpetas"; -"item_title_placeholder" = "Título"; -"item_author_placeholder" = "Autor"; +"section_item_title" = "Título"; +"section_item_author" = "Autor"; "artwork_options_title" = "Opciones de ilustraciones"; "artwork_photolibrary_title" = "Elija de la biblioteca de fotos"; "artwork_clipboard_title" = "Pegar desde el portapapeles"; diff --git a/BookPlayer/fi.lproj/Localizable.strings b/BookPlayer/fi.lproj/Localizable.strings index e763e822e..3879da4a9 100644 --- a/BookPlayer/fi.lproj/Localizable.strings +++ b/BookPlayer/fi.lproj/Localizable.strings @@ -234,8 +234,8 @@ "search_title" = "Hae"; "books_title" = "Kirjat"; "folders_title" = "Kansiot"; -"item_title_placeholder" = "Otsikko"; -"item_author_placeholder" = "Tekijä"; +"section_item_title" = "Otsikko"; +"section_item_author" = "Tekijä"; "artwork_options_title" = "Taideteosvaihtoehdot"; "artwork_photolibrary_title" = "Valitse valokuvakirjastosta"; "artwork_clipboard_title" = "Liitä leikepöydältä"; diff --git a/BookPlayer/fr.lproj/Localizable.strings b/BookPlayer/fr.lproj/Localizable.strings index fd0f9f521..319b8903c 100644 --- a/BookPlayer/fr.lproj/Localizable.strings +++ b/BookPlayer/fr.lproj/Localizable.strings @@ -234,8 +234,8 @@ "search_title" = "Recherche"; "books_title" = "Livres"; "folders_title" = "Dossiers"; -"item_title_placeholder" = "Titre"; -"item_author_placeholder" = "Auteur"; +"section_item_title" = "Titre"; +"section_item_author" = "Auteur"; "artwork_options_title" = "Options d'illustration"; "artwork_photolibrary_title" = "Choisissez parmi la photothèque"; "artwork_clipboard_title" = "Coller depuis le presse-papiers"; diff --git a/BookPlayer/hu.lproj/Localizable.strings b/BookPlayer/hu.lproj/Localizable.strings index 8b13404af..748be3b36 100644 --- a/BookPlayer/hu.lproj/Localizable.strings +++ b/BookPlayer/hu.lproj/Localizable.strings @@ -234,8 +234,8 @@ "search_title" = "Keresés"; "books_title" = "Könyvek"; "folders_title" = "Mappák"; -"item_title_placeholder" = "Cím"; -"item_author_placeholder" = "Szerző"; +"section_item_title" = "Cím"; +"section_item_author" = "Szerző"; "artwork_options_title" = "Műalkotási lehetőségek"; "artwork_photolibrary_title" = "Válasszon a Photo Library közül"; "artwork_clipboard_title" = "Beillesztés a vágólapról"; diff --git a/BookPlayer/it.lproj/Localizable.strings b/BookPlayer/it.lproj/Localizable.strings index f90339ef4..2934e0724 100644 --- a/BookPlayer/it.lproj/Localizable.strings +++ b/BookPlayer/it.lproj/Localizable.strings @@ -234,8 +234,8 @@ "search_title" = "Ricerca"; "books_title" = "Libri"; "folders_title" = "Cartelle"; -"item_title_placeholder" = "Titolo"; -"item_author_placeholder" = "Autore"; +"section_item_title" = "Titolo"; +"section_item_author" = "Autore"; "artwork_options_title" = "Opzioni di opere d'arte"; "artwork_photolibrary_title" = "Scegli dalla Libreria foto"; "artwork_clipboard_title" = "Incolla dagli appunti"; diff --git a/BookPlayer/nl.lproj/Localizable.strings b/BookPlayer/nl.lproj/Localizable.strings index cc29c6dc4..7782dd31e 100644 --- a/BookPlayer/nl.lproj/Localizable.strings +++ b/BookPlayer/nl.lproj/Localizable.strings @@ -234,8 +234,8 @@ "search_title" = "Zoekopdracht"; "books_title" = "Boeken"; "folders_title" = "mappen"; -"item_title_placeholder" = "Titel"; -"item_author_placeholder" = "Auteur"; +"section_item_title" = "Titel"; +"section_item_author" = "Auteur"; "artwork_options_title" = "Kunstwerk opties"; "artwork_photolibrary_title" = "Kies uit de fotobibliotheek"; "artwork_clipboard_title" = "Plakken vanaf het klembord"; diff --git a/BookPlayer/pl.lproj/Localizable.strings b/BookPlayer/pl.lproj/Localizable.strings index ef236a0d6..f9d6677e4 100644 --- a/BookPlayer/pl.lproj/Localizable.strings +++ b/BookPlayer/pl.lproj/Localizable.strings @@ -234,8 +234,8 @@ "search_title" = "Szukaj"; "books_title" = "Książki"; "folders_title" = "Lornetka składana"; -"item_title_placeholder" = "Tytuł"; -"item_author_placeholder" = "Autor"; +"section_item_title" = "Tytuł"; +"section_item_author" = "Autor"; "artwork_options_title" = "Opcje grafiki"; "artwork_photolibrary_title" = "Wybierz z biblioteki zdjęć"; "artwork_clipboard_title" = "Wklej ze schowka"; diff --git a/BookPlayer/pt-BR.lproj/Localizable.strings b/BookPlayer/pt-BR.lproj/Localizable.strings index 391d1fd1a..e36926b50 100644 --- a/BookPlayer/pt-BR.lproj/Localizable.strings +++ b/BookPlayer/pt-BR.lproj/Localizable.strings @@ -234,8 +234,8 @@ "search_title" = "Procurar"; "books_title" = "livros"; "folders_title" = "Pastas"; -"item_title_placeholder" = "Título"; -"item_author_placeholder" = "Autor"; +"section_item_title" = "Título"; +"section_item_author" = "Autor"; "artwork_options_title" = "Opções de arte"; "artwork_photolibrary_title" = "Escolha na biblioteca de fotos"; "artwork_clipboard_title" = "Colar da área de transferência"; diff --git a/BookPlayer/ro.lproj/Localizable.strings b/BookPlayer/ro.lproj/Localizable.strings index 6e0a17d4e..6688fcd25 100644 --- a/BookPlayer/ro.lproj/Localizable.strings +++ b/BookPlayer/ro.lproj/Localizable.strings @@ -234,8 +234,8 @@ "search_title" = "Căutare"; "books_title" = "Cărți"; "folders_title" = "Foldere"; -"item_title_placeholder" = "Titlu"; -"item_author_placeholder" = "Autor"; +"section_item_title" = "Titlu"; +"section_item_author" = "Autor"; "artwork_options_title" = "Opțiuni de artă"; "artwork_photolibrary_title" = "Alegeți din Biblioteca foto"; "artwork_clipboard_title" = "Lipiți din clipboard"; diff --git a/BookPlayer/ru.lproj/Localizable.strings b/BookPlayer/ru.lproj/Localizable.strings index 6c708f9aa..1ec4f89e6 100644 --- a/BookPlayer/ru.lproj/Localizable.strings +++ b/BookPlayer/ru.lproj/Localizable.strings @@ -234,8 +234,8 @@ "search_title" = "Поиск"; "books_title" = "Книги"; "folders_title" = "Папки"; -"item_title_placeholder" = "Заголовок"; -"item_author_placeholder" = "Автор"; +"section_item_title" = "Заголовок"; +"section_item_author" = "Автор"; "artwork_options_title" = "Варианты оформления"; "artwork_photolibrary_title" = "Выберите из библиотеки фотографий"; "artwork_clipboard_title" = "Вставить из буфера обмена"; diff --git a/BookPlayer/sk-SK.lproj/Localizable.strings b/BookPlayer/sk-SK.lproj/Localizable.strings index d34b62498..5f0cfd6f4 100644 --- a/BookPlayer/sk-SK.lproj/Localizable.strings +++ b/BookPlayer/sk-SK.lproj/Localizable.strings @@ -234,8 +234,8 @@ "search_title" = "Vyhľadávanie"; "books_title" = "knihy"; "folders_title" = "Priečinky"; -"item_title_placeholder" = "Názov"; -"item_author_placeholder" = "Autor"; +"section_item_title" = "Názov"; +"section_item_author" = "Autor"; "artwork_options_title" = "Možnosti umeleckých diel"; "artwork_photolibrary_title" = "Vyberte si z knižnice fotografií"; "artwork_clipboard_title" = "Prilepiť zo schránky"; diff --git a/BookPlayer/sv.lproj/Localizable.strings b/BookPlayer/sv.lproj/Localizable.strings index 3f7f2155d..6a4992a7c 100644 --- a/BookPlayer/sv.lproj/Localizable.strings +++ b/BookPlayer/sv.lproj/Localizable.strings @@ -234,8 +234,8 @@ "search_title" = "Sök"; "books_title" = "Böcker"; "folders_title" = "Mappar"; -"item_title_placeholder" = "Titel"; -"item_author_placeholder" = "Författare"; +"section_item_title" = "Titel"; +"section_item_author" = "Författare"; "artwork_options_title" = "Alternativ för konstverk"; "artwork_photolibrary_title" = "Välj från Fotobibliotek"; "artwork_clipboard_title" = "Klistra in från urklipp"; diff --git a/BookPlayer/tr.lproj/Localizable.strings b/BookPlayer/tr.lproj/Localizable.strings index 1f4b22b49..4b5ae12de 100644 --- a/BookPlayer/tr.lproj/Localizable.strings +++ b/BookPlayer/tr.lproj/Localizable.strings @@ -234,8 +234,8 @@ "search_title" = "Aramak"; "books_title" = "Kitabın"; "folders_title" = "Klasörler"; -"item_title_placeholder" = "Başlık"; -"item_author_placeholder" = "Yazar"; +"section_item_title" = "Başlık"; +"section_item_author" = "Yazar"; "artwork_options_title" = "Sanat eseri seçenekleri"; "artwork_photolibrary_title" = "Fotoğraf Kitaplığından Seçin"; "artwork_clipboard_title" = "Panodan yapıştır"; diff --git a/BookPlayer/uk.lproj/Localizable.strings b/BookPlayer/uk.lproj/Localizable.strings index e11102cfb..c2cc11529 100644 --- a/BookPlayer/uk.lproj/Localizable.strings +++ b/BookPlayer/uk.lproj/Localizable.strings @@ -234,8 +234,8 @@ "search_title" = "Пошук"; "books_title" = "Книги"; "folders_title" = "Папки"; -"item_title_placeholder" = "Назва"; -"item_author_placeholder" = "Автор"; +"section_item_title" = "Назва"; +"section_item_author" = "Автор"; "artwork_options_title" = "Варіанти художніх робіт"; "artwork_photolibrary_title" = "Виберіть із бібліотеки фотографій"; "artwork_clipboard_title" = "Вставити з буфера обміну"; diff --git a/BookPlayer/zh-Hans.lproj/Localizable.strings b/BookPlayer/zh-Hans.lproj/Localizable.strings index 7e2836d37..d146eb5b4 100644 --- a/BookPlayer/zh-Hans.lproj/Localizable.strings +++ b/BookPlayer/zh-Hans.lproj/Localizable.strings @@ -234,8 +234,8 @@ "search_title" = "搜索"; "books_title" = "图书"; "folders_title" = "文件夹"; -"item_title_placeholder" = "标题"; -"item_author_placeholder" = "作者"; +"section_item_title" = "标题"; +"section_item_author" = "作者"; "artwork_options_title" = "艺术品选项"; "artwork_photolibrary_title" = "从照片库中选择"; "artwork_clipboard_title" = "从剪贴板粘贴"; From 6823925f6449991e86044e82e63c88ea43838e47 Mon Sep 17 00:00:00 2001 From: Gianni Carlo Date: Mon, 12 Jun 2023 08:43:50 -0500 Subject: [PATCH 4/4] Add environmentObject to previews --- BookPlayer/Library/ItemDetails Screen/ClearableTextField.swift | 1 + .../ItemDetails Screen/Views/ItemDetailsArtworkSectionView.swift | 1 + BookPlayer/Profile/CompleteAccount Screen/PricingRowView.swift | 1 + BookPlayer/Profile/Profile Screen/QueuedSyncTaskRowView.swift | 1 + BookPlayer/Profile/Profile Screen/Views/ProfileCardView.swift | 1 + .../Profile/Profile Screen/Views/ProfileListenedTimeView.swift | 1 + 6 files changed, 6 insertions(+) diff --git a/BookPlayer/Library/ItemDetails Screen/ClearableTextField.swift b/BookPlayer/Library/ItemDetails Screen/ClearableTextField.swift index a6037dcb7..dbdd25b71 100644 --- a/BookPlayer/Library/ItemDetails Screen/ClearableTextField.swift +++ b/BookPlayer/Library/ItemDetails Screen/ClearableTextField.swift @@ -38,5 +38,6 @@ struct ClearableTextField: View { struct ClearableTextField_Previews: PreviewProvider { static var previews: some View { ClearableTextField("Title", text: .constant("")) + .environmentObject(ThemeViewModel()) } } diff --git a/BookPlayer/Library/ItemDetails Screen/Views/ItemDetailsArtworkSectionView.swift b/BookPlayer/Library/ItemDetails Screen/Views/ItemDetailsArtworkSectionView.swift index 009e53387..27f1cb0dc 100644 --- a/BookPlayer/Library/ItemDetails Screen/Views/ItemDetailsArtworkSectionView.swift +++ b/BookPlayer/Library/ItemDetails Screen/Views/ItemDetailsArtworkSectionView.swift @@ -49,5 +49,6 @@ struct ItemDetailsArtworkSectionView_Previews: PreviewProvider { image: .constant(nil), actionHandler: {} ) + .environmentObject(ThemeViewModel()) } } diff --git a/BookPlayer/Profile/CompleteAccount Screen/PricingRowView.swift b/BookPlayer/Profile/CompleteAccount Screen/PricingRowView.swift index 28c4990ec..cfb62f881 100644 --- a/BookPlayer/Profile/CompleteAccount Screen/PricingRowView.swift +++ b/BookPlayer/Profile/CompleteAccount Screen/PricingRowView.swift @@ -94,5 +94,6 @@ struct PricingRowView_Previews: PreviewProvider { isLoading: .constant(true) ) } + .environmentObject(ThemeViewModel()) } } diff --git a/BookPlayer/Profile/Profile Screen/QueuedSyncTaskRowView.swift b/BookPlayer/Profile/Profile Screen/QueuedSyncTaskRowView.swift index 5bf0eeff2..76d2c0518 100644 --- a/BookPlayer/Profile/Profile Screen/QueuedSyncTaskRowView.swift +++ b/BookPlayer/Profile/Profile Screen/QueuedSyncTaskRowView.swift @@ -37,5 +37,6 @@ struct QueuedSyncTaskRowView_Previews: PreviewProvider { imageName: .constant("bookmark"), title: .constant("Task") ) + .environmentObject(ThemeViewModel()) } } diff --git a/BookPlayer/Profile/Profile Screen/Views/ProfileCardView.swift b/BookPlayer/Profile/Profile Screen/Views/ProfileCardView.swift index ad5d15ebd..ebcd4b50e 100644 --- a/BookPlayer/Profile/Profile Screen/Views/ProfileCardView.swift +++ b/BookPlayer/Profile/Profile Screen/Views/ProfileCardView.swift @@ -73,5 +73,6 @@ struct ProfileCardView: View { struct ProfileCardView_Previews: PreviewProvider { static var previews: some View { ProfileCardView(account: .constant(Account())) + .environmentObject(ThemeViewModel()) } } diff --git a/BookPlayer/Profile/Profile Screen/Views/ProfileListenedTimeView.swift b/BookPlayer/Profile/Profile Screen/Views/ProfileListenedTimeView.swift index c682106ea..c79351517 100644 --- a/BookPlayer/Profile/Profile Screen/Views/ProfileListenedTimeView.swift +++ b/BookPlayer/Profile/Profile Screen/Views/ProfileListenedTimeView.swift @@ -30,5 +30,6 @@ struct ProfileStatsView_Previews: PreviewProvider { ProfileListenedTimeView( formattedListeningTime: .constant("0m") ) + .environmentObject(ThemeViewModel()) } }