From 8e03e53a1673120c6fdc094ae3a8c15bee2aa303 Mon Sep 17 00:00:00 2001 From: mntone <901816+mntone@users.noreply.github.com> Date: Thu, 4 Jan 2024 21:19:58 +0900 Subject: [PATCH] Improves FavoriteButton implementation. --- src/App/ViewModels/GameItemViewModel.swift | 2 +- src/App/ViewModels/MonsterViewModel.swift | 2 +- .../Protocols/FavoriteViewModel.swift | 5 ---- src/App/Views/Details/FavoriteButton.swift | 17 +++++-------- src/App/Views/Details/MonsterView.swift | 2 +- src/App/Views/FavoriteContextMenuButton.swift | 24 +++++++------------ src/App/Views/MonsterListItem.swift | 5 ++-- src/MonsterAnalyzer.xcodeproj/project.pbxproj | 6 ----- 8 files changed, 20 insertions(+), 43 deletions(-) delete mode 100644 src/App/ViewModels/Protocols/FavoriteViewModel.swift diff --git a/src/App/ViewModels/GameItemViewModel.swift b/src/App/ViewModels/GameItemViewModel.swift index d3bea58..172c095 100644 --- a/src/App/ViewModels/GameItemViewModel.swift +++ b/src/App/ViewModels/GameItemViewModel.swift @@ -1,7 +1,7 @@ import Foundation import MonsterAnalyzerCore -final class GameItemViewModel: ObservableObject, Identifiable, FavoriteViewModel { +final class GameItemViewModel: ObservableObject, Identifiable { private let monster: Monster @Published diff --git a/src/App/ViewModels/MonsterViewModel.swift b/src/App/ViewModels/MonsterViewModel.swift index 35bf213..3c7bcef 100644 --- a/src/App/ViewModels/MonsterViewModel.swift +++ b/src/App/ViewModels/MonsterViewModel.swift @@ -2,7 +2,7 @@ import Combine import Foundation import MonsterAnalyzerCore -final class MonsterViewModel: ObservableObject, Identifiable, FavoriteViewModel { +final class MonsterViewModel: ObservableObject, Identifiable { private let monster: Monster #if !os(watchOS) private let notifier: DebounceNotifier diff --git a/src/App/ViewModels/Protocols/FavoriteViewModel.swift b/src/App/ViewModels/Protocols/FavoriteViewModel.swift deleted file mode 100644 index 0953406..0000000 --- a/src/App/ViewModels/Protocols/FavoriteViewModel.swift +++ /dev/null @@ -1,5 +0,0 @@ -import protocol Combine.ObservableObject - -protocol FavoriteViewModel: ObservableObject { - var isFavorited: Bool { get set } -} diff --git a/src/App/Views/Details/FavoriteButton.swift b/src/App/Views/Details/FavoriteButton.swift index acfca1d..e90eef4 100644 --- a/src/App/Views/Details/FavoriteButton.swift +++ b/src/App/Views/Details/FavoriteButton.swift @@ -1,12 +1,12 @@ import SwiftUI -struct FavoriteButton: View { - @ObservedObject - private(set) var viewModel: ViewModel +struct FavoriteButton: View { + @Binding + private(set) var favorite: Bool var body: some View { let text: LocalizedStringKey, image: String - if viewModel.isFavorited { + if favorite { text = "Remove Favorite" image = "star.fill" } else { @@ -15,14 +15,9 @@ struct FavoriteButton: View { } return Button(text, systemImage: image) { -#if os(watchOS) - viewModel.isFavorited.toggle() -#else - withAnimation { - viewModel.isFavorited.toggle() - } -#endif + favorite.toggle() } + .animation(.easeInOut, value: favorite) #if os(watchOS) .foregroundStyle(.yellow) #else diff --git a/src/App/Views/Details/MonsterView.swift b/src/App/Views/Details/MonsterView.swift index b6e23b3..916bbde 100644 --- a/src/App/Views/Details/MonsterView.swift +++ b/src/App/Views/Details/MonsterView.swift @@ -103,7 +103,7 @@ struct MonsterView: View { } #endif .toolbarItemBackport(alignment: .trailing) { - FavoriteButton(viewModel: viewModel) + FavoriteButton(favorite: $viewModel.isFavorited) } #if os(iOS) .navigationBarTitleDisplayMode(.inline) diff --git a/src/App/Views/FavoriteContextMenuButton.swift b/src/App/Views/FavoriteContextMenuButton.swift index 53d837d..d499476 100644 --- a/src/App/Views/FavoriteContextMenuButton.swift +++ b/src/App/Views/FavoriteContextMenuButton.swift @@ -1,39 +1,31 @@ import SwiftUI @available(watchOS, unavailable) -struct FavoriteContextMenuButton: View { - @ObservedObject - private(set) var viewModel: ViewModel +struct FavoriteContextMenuButton: View { + @Binding + private(set) var favorite: Bool var body: some View { let text: LocalizedStringKey, image: String - if viewModel.isFavorited { + if favorite { text = "Remove Favorite" - image = "star.fill" + image = "star.slash" } else { text = "Add to Favorites" image = "star" } return Button(text, systemImage: image) { - viewModel.isFavorited.toggle() + favorite.toggle() } } } -final class _PreviewFavoriteViewModel: FavoriteViewModel { - var isFavorited: Bool - - init(isFavorited: Bool) { - self.isFavorited = isFavorited - } -} - #Preview("Favorite") { Text(verbatim: "Sample Context Menu") .padding() .contextMenu { - FavoriteContextMenuButton(viewModel: _PreviewFavoriteViewModel(isFavorited: false)) + FavoriteContextMenuButton(favorite: .constant(false)) } } @@ -41,6 +33,6 @@ final class _PreviewFavoriteViewModel: FavoriteViewModel { Text(verbatim: "Sample Context Menu") .padding() .contextMenu { - FavoriteContextMenuButton(viewModel: _PreviewFavoriteViewModel(isFavorited: true)) + FavoriteContextMenuButton(favorite: .constant(true)) } } diff --git a/src/App/Views/MonsterListItem.swift b/src/App/Views/MonsterListItem.swift index 780c2f8..a2425cb 100644 --- a/src/App/Views/MonsterListItem.swift +++ b/src/App/Views/MonsterListItem.swift @@ -14,12 +14,13 @@ struct MonsterListItem: View { Image(systemName: "star.fill") .foregroundStyle(.yellow) .accessibilityLabel("Favorited") - .transition(.opacity.animation(.easeInOut(duration: 0.1))) + .transition(.opacity) } } + .animation(.easeInOut(duration: 0.1), value: viewModel.isFavorited) #if !os(watchOS) .contextMenu { - FavoriteContextMenuButton(viewModel: viewModel) + FavoriteContextMenuButton(favorite: $viewModel.isFavorited) } #endif } diff --git a/src/MonsterAnalyzer.xcodeproj/project.pbxproj b/src/MonsterAnalyzer.xcodeproj/project.pbxproj index 8315f62..410d09d 100644 --- a/src/MonsterAnalyzer.xcodeproj/project.pbxproj +++ b/src/MonsterAnalyzer.xcodeproj/project.pbxproj @@ -238,8 +238,6 @@ EBF9282F2B1038CB007D59D4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EBF9282E2B1038CB007D59D4 /* Assets.xcassets */; }; EBF928332B1038CB007D59D4 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EBF928322B1038CB007D59D4 /* Preview Assets.xcassets */; }; EBFEAB842B45A5DC005363F7 /* FavoriteContextMenuButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBFEAB832B45A5DC005363F7 /* FavoriteContextMenuButton.swift */; }; - EBFEAB872B45A805005363F7 /* FavoriteViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBFEAB862B45A805005363F7 /* FavoriteViewModel.swift */; }; - EBFEAB882B45A805005363F7 /* FavoriteViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBFEAB862B45A805005363F7 /* FavoriteViewModel.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -485,7 +483,6 @@ EBF928302B1038CB007D59D4 /* app.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = app.entitlements; sourceTree = ""; }; EBF928322B1038CB007D59D4 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; EBFEAB832B45A5DC005363F7 /* FavoriteContextMenuButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoriteContextMenuButton.swift; sourceTree = ""; }; - EBFEAB862B45A805005363F7 /* FavoriteViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoriteViewModel.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -1025,7 +1022,6 @@ EBFEAB852B45A7F7005363F7 /* Protocols */ = { isa = PBXGroup; children = ( - EBFEAB862B45A805005363F7 /* FavoriteViewModel.swift */, ); path = Protocols; sourceTree = ""; @@ -1270,7 +1266,6 @@ EBB4B20E2B175DE2004D63EA /* Effective.swift in Sources */, EB8778292B26BDEF00B3359C /* EnvironmentValues+PresentSettingsSheetAction.swift in Sources */, EB560BCF2B42F48800E91E01 /* FavoriteButton.swift in Sources */, - EBFEAB882B45A805005363F7 /* FavoriteViewModel.swift in Sources */, EBB4B21C2B176CE7004D63EA /* FixedWidthWeaknessView.swift in Sources */, EBBBAABA2B3FE27000BBAB23 /* GameGroupViewModel.swift in Sources */, EBBBAAB52B3FADEB00BBAB23 /* GameItemViewModel.swift in Sources */, @@ -1421,7 +1416,6 @@ EB8778282B26BDEF00B3359C /* EnvironmentValues+PresentSettingsSheetAction.swift in Sources */, EB560BCE2B42F48800E91E01 /* FavoriteButton.swift in Sources */, EBFEAB842B45A5DC005363F7 /* FavoriteContextMenuButton.swift in Sources */, - EBFEAB872B45A805005363F7 /* FavoriteViewModel.swift in Sources */, EBCA222E2B228C6800C487AD /* FixedWidthWeaknessView.swift in Sources */, EBDFD8512B3C112A00AF1832 /* GameGroupViewModel.swift in Sources */, EBBBAAB42B3FADEB00BBAB23 /* GameItemViewModel.swift in Sources */,