diff --git a/CommonWallet.xcodeproj/project.pbxproj b/CommonWallet.xcodeproj/project.pbxproj index 9ee021e..66bae2d 100644 --- a/CommonWallet.xcodeproj/project.pbxproj +++ b/CommonWallet.xcodeproj/project.pbxproj @@ -13,7 +13,6 @@ 871073B42990B7A600A0518C /* AllLogView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 871073B32990B7A600A0518C /* AllLogView.swift */; }; 871073B92990CDBE00A0518C /* DateCalculator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 871073B82990CDBE00A0518C /* DateCalculator.swift */; }; 871F09EC2A11945000F96394 /* ShareNumberManaging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 871F09EB2A11945000F96394 /* ShareNumberManaging.swift */; }; - 871F09EE2A11979600F96394 /* MainTabViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 871F09ED2A11979600F96394 /* MainTabViewModel.swift */; }; 8724AD8E29FDF50A0023AEC5 /* LaunchViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8724AD8D29FDF50A0023AEC5 /* LaunchViewModel.swift */; }; 872652F3297B92A8002C76D6 /* FirebaseErrorManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 872652F2297B92A8002C76D6 /* FirebaseErrorManager.swift */; }; 872652F6297BB8AB002C76D6 /* SignInViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 872652F5297BB8AB002C76D6 /* SignInViewModel.swift */; }; @@ -44,6 +43,7 @@ 87402F4929F37B960007320D /* AuthManaging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87402F4829F37B960007320D /* AuthManaging.swift */; }; 874613A62A2954A50068383B /* ImagePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 874613A52A2954A50068383B /* ImagePicker.swift */; }; 874A988529F206DB007CFB74 /* UserDefaultsError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 874A988429F206DB007CFB74 /* UserDefaultsError.swift */; }; + 874C19802A5933AB002812D5 /* MainTabViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 874C197F2A5933AB002812D5 /* MainTabViewModel.swift */; }; 874DBA062A2C1392000E1FD1 /* Userdefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 874DBA052A2C1392000E1FD1 /* Userdefaults.swift */; }; 874DBA082A2C1FF8000E1FD1 /* StorageManaging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 874DBA072A2C1FF8000E1FD1 /* StorageManaging.swift */; }; 874EF932297CB4C600C94233 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 874EF931297CB4C600C94233 /* GoogleService-Info.plist */; }; @@ -69,7 +69,6 @@ 87830E73297A1ACB00184A7C /* CreateUserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87830E71297A1ACB00184A7C /* CreateUserTests.swift */; }; 87830E74297A1B9E00184A7C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87EE8D7C297A1790005CCB6F /* AppDelegate.swift */; }; 87830E75297A1BA100184A7C /* CommonWalletApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87EE8D49297A1369005CCB6F /* CommonWalletApp.swift */; }; - 87830E7B297A1C6A00184A7C /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87EE8D4B297A1369005CCB6F /* ContentView.swift */; }; 87830E7D297A201F00184A7C /* SignInView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87830E7C297A201F00184A7C /* SignInView.swift */; }; 87830E7E297A201F00184A7C /* SignInView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87830E7C297A201F00184A7C /* SignInView.swift */; }; 87830E80297A20DB00184A7C /* CreateUserView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87830E7F297A20DB00184A7C /* CreateUserView.swift */; }; @@ -113,7 +112,6 @@ 87E5E9342A2E9857002CF7B2 /* MyNameEditView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87E5E9332A2E9857002CF7B2 /* MyNameEditView.swift */; }; 87E5E9362A2E9880002CF7B2 /* MyNameEditViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87E5E9352A2E9880002CF7B2 /* MyNameEditViewModel.swift */; }; 87EE8D4A297A1369005CCB6F /* CommonWalletApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87EE8D49297A1369005CCB6F /* CommonWalletApp.swift */; }; - 87EE8D4C297A1369005CCB6F /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87EE8D4B297A1369005CCB6F /* ContentView.swift */; }; 87EE8D4E297A136A005CCB6F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 87EE8D4D297A136A005CCB6F /* Assets.xcassets */; }; 87EE8D51297A136A005CCB6F /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 87EE8D50297A136A005CCB6F /* Preview Assets.xcassets */; }; 87EE8D65297A136A005CCB6F /* CommonWalletUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87EE8D64297A136A005CCB6F /* CommonWalletUITests.swift */; }; @@ -151,7 +149,6 @@ 871073B32990B7A600A0518C /* AllLogView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AllLogView.swift; sourceTree = ""; }; 871073B82990CDBE00A0518C /* DateCalculator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateCalculator.swift; sourceTree = ""; }; 871F09EB2A11945000F96394 /* ShareNumberManaging.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareNumberManaging.swift; sourceTree = ""; }; - 871F09ED2A11979600F96394 /* MainTabViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainTabViewModel.swift; sourceTree = ""; }; 871F09F12A12E4D600F96394 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 8724AD8D29FDF50A0023AEC5 /* LaunchViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchViewModel.swift; sourceTree = ""; }; 872652F2297B92A8002C76D6 /* FirebaseErrorManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirebaseErrorManager.swift; sourceTree = ""; }; @@ -169,6 +166,7 @@ 87402F4829F37B960007320D /* AuthManaging.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthManaging.swift; sourceTree = ""; }; 874613A52A2954A50068383B /* ImagePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImagePicker.swift; sourceTree = ""; }; 874A988429F206DB007CFB74 /* UserDefaultsError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsError.swift; sourceTree = ""; }; + 874C197F2A5933AB002812D5 /* MainTabViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainTabViewModel.swift; sourceTree = ""; }; 874DBA052A2C1392000E1FD1 /* Userdefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Userdefaults.swift; sourceTree = ""; }; 874DBA072A2C1FF8000E1FD1 /* StorageManaging.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageManaging.swift; sourceTree = ""; }; 874EF931297CB4C600C94233 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; @@ -224,7 +222,6 @@ 87E5E9352A2E9880002CF7B2 /* MyNameEditViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyNameEditViewModel.swift; sourceTree = ""; }; 87EE8D46297A1369005CCB6F /* CommonWallet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CommonWallet.app; sourceTree = BUILT_PRODUCTS_DIR; }; 87EE8D49297A1369005CCB6F /* CommonWalletApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonWalletApp.swift; sourceTree = ""; }; - 87EE8D4B297A1369005CCB6F /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 87EE8D4D297A136A005CCB6F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 87EE8D50297A136A005CCB6F /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 87EE8D56297A136A005CCB6F /* CommonWalletTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CommonWalletTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -289,40 +286,43 @@ path = Model; sourceTree = ""; }; - 871F09EF2A11979F00F96394 /* View */ = { + 8724AD8C29FDF4E40023AEC5 /* ViewModels */ = { isa = PBXGroup; children = ( - 87ABC58029908B17003E94F3 /* MainTabView.swift */, + 8724AD8D29FDF50A0023AEC5 /* LaunchViewModel.swift */, ); - path = View; + path = ViewModels; sourceTree = ""; }; - 871F09F02A1197A700F96394 /* ViewMdels */ = { + 87402F3F29F377210007320D /* Protocol */ = { isa = PBXGroup; children = ( - 871F09ED2A11979600F96394 /* MainTabViewModel.swift */, + 87402F4829F37B960007320D /* AuthManaging.swift */, + 87402F4229F377D70007320D /* FireStoreUserManaging.swift */, + 87402F4029F377C40007320D /* FireStoreTransactionManaging.swift */, + 87402F4629F37B040007320D /* FireStorePartnerManaging.swift */, + 871F09EB2A11945000F96394 /* ShareNumberManaging.swift */, + 874DBA072A2C1FF8000E1FD1 /* StorageManaging.swift */, ); - path = ViewMdels; + path = Protocol; sourceTree = ""; }; - 8724AD8C29FDF4E40023AEC5 /* ViewModels */ = { + 874C19792A58D6F6002812D5 /* Models */ = { isa = PBXGroup; children = ( - 8724AD8D29FDF50A0023AEC5 /* LaunchViewModel.swift */, + 87830E6A297A1A6000184A7C /* Firebase */, + 87ABC57B29907C54003E94F3 /* UserDefaults */, + 87D1A05329E770E30058A98F /* Error */, + 87C162DB2A2ACE9300382061 /* Domain */, + 8702F3F22A51068E002925A0 /* CoreData */, ); - path = ViewModels; + path = Models; sourceTree = ""; }; - 87402F3F29F377210007320D /* Protocol */ = { + 874C197A2A58D885002812D5 /* Protocol */ = { isa = PBXGroup; children = ( - 87402F4829F37B960007320D /* AuthManaging.swift */, - 87402F4229F377D70007320D /* FireStoreUserManaging.swift */, - 87402F4029F377C40007320D /* FireStoreTransactionManaging.swift */, - 87402F4629F37B040007320D /* FireStorePartnerManaging.swift */, 87402F4429F378330007320D /* UserDefaultsManaging.swift */, - 871F09EB2A11945000F96394 /* ShareNumberManaging.swift */, - 874DBA072A2C1FF8000E1FD1 /* StorageManaging.swift */, ); path = Protocol; sourceTree = ""; @@ -382,15 +382,13 @@ path = ViewModel; sourceTree = ""; }; - 87830E6A297A1A6000184A7C /* Models */ = { + 87830E6A297A1A6000184A7C /* Firebase */ = { isa = PBXGroup; children = ( 87402F3F29F377210007320D /* Protocol */, - 87D1A05329E770E30058A98F /* Error */, 874EF943297D0F3700C94233 /* Firebase */, - 87ABC57B29907C54003E94F3 /* General */, ); - path = Models; + path = Firebase; sourceTree = ""; }; 87830E76297A1C1900184A7C /* Frameworks */ = { @@ -518,14 +516,15 @@ path = Model; sourceTree = ""; }; - 87ABC57B29907C54003E94F3 /* General */ = { + 87ABC57B29907C54003E94F3 /* UserDefaults */ = { isa = PBXGroup; children = ( + 874C197A2A58D885002812D5 /* Protocol */, 874EF93B297CFC3900C94233 /* UserDefaultsManager.swift */, 874EF93E297D04DF00C94233 /* UserDefaultsKey.swift */, 879310232A2FF28200FDD061 /* ImageNameProperty.swift */, ); - path = General; + path = UserDefaults; sourceTree = ""; }; 87ABC57C29907CD3003E94F3 /* Sceans */ = { @@ -541,7 +540,7 @@ path = Sceans; sourceTree = ""; }; - 87ABC57D29907DA2003E94F3 /* Source */ = { + 87ABC57D29907DA2003E94F3 /* ViewTools */ = { isa = PBXGroup; children = ( 876EE23B2A26AEFC0073F1C3 /* WebView */, @@ -549,7 +548,7 @@ 874613A52A2954A50068383B /* ImagePicker.swift */, 87DDCDCB2A18373200F51DC8 /* PKHUDView.swift */, ); - path = Source; + path = ViewTools; sourceTree = ""; }; 87ABC58229908B65003E94F3 /* Log */ = { @@ -582,8 +581,8 @@ 87C0BADB2A03C50200A02978 /* MainTab */ = { isa = PBXGroup; children = ( - 871F09EF2A11979F00F96394 /* View */, - 871F09F02A1197A700F96394 /* ViewMdels */, + 87ABC58029908B17003E94F3 /* MainTabView.swift */, + 874C197F2A5933AB002812D5 /* MainTabViewModel.swift */, ); path = MainTab; sourceTree = ""; @@ -640,12 +639,9 @@ 874EF931297CB4C600C94233 /* GoogleService-Info.plist */, 87EE8D49297A1369005CCB6F /* CommonWalletApp.swift */, 87EE8D7C297A1790005CCB6F /* AppDelegate.swift */, - 87EE8D4B297A1369005CCB6F /* ContentView.swift */, - 87830E6A297A1A6000184A7C /* Models */, - 8702F3F22A51068E002925A0 /* CoreData */, - 87C162DB2A2ACE9300382061 /* Domain */, + 874C19792A58D6F6002812D5 /* Models */, 87ABC57C29907CD3003E94F3 /* Sceans */, - 87ABC57D29907DA2003E94F3 /* Source */, + 87ABC57D29907DA2003E94F3 /* ViewTools */, 874EF93D297D040000C94233 /* Extentions */, 87EE8D4D297A136A005CCB6F /* Assets.xcassets */, 87EE8D4F297A136A005CCB6F /* Preview Content */, @@ -832,11 +828,11 @@ files = ( 87402F4329F377D70007320D /* FireStoreUserManaging.swift in Sources */, 879310242A2FF28200FDD061 /* ImageNameProperty.swift in Sources */, - 871F09EE2A11979600F96394 /* MainTabViewModel.swift in Sources */, 874EF93F297D04DF00C94233 /* UserDefaultsKey.swift in Sources */, 87E5E9342A2E9857002CF7B2 /* MyNameEditView.swift in Sources */, 87EE8D7D297A1790005CCB6F /* AppDelegate.swift in Sources */, 872B9FDB2A42F9B100D15A84 /* FetchPartnerError.swift in Sources */, + 874C19802A5933AB002812D5 /* MainTabViewModel.swift in Sources */, 874EF93A297CC8B200C94233 /* FireStoreUserManager.swift in Sources */, 87830E80297A20DB00184A7C /* CreateUserView.swift in Sources */, 879379E2298B4C8D00D3A47B /* PartnerNameEditView.swift in Sources */, @@ -869,7 +865,6 @@ 872652F6297BB8AB002C76D6 /* SignInViewModel.swift in Sources */, 87391E50298A189900897A96 /* String.swift in Sources */, 87F53FE0297EA44E00293176 /* FireStoreTransactionManager.swift in Sources */, - 87EE8D4C297A1369005CCB6F /* ContentView.swift in Sources */, 87CDAABC297E6ADB00F52887 /* AccountView.swift in Sources */, 879379E0298B444500D3A47B /* ConnectPartnerView.swift in Sources */, 879379EF298BBDB800D3A47B /* PartnerNameEditViewModel.swift in Sources */, @@ -924,7 +919,6 @@ 8737FCEA297E0BDF0064E40D /* LaunchScreen.swift in Sources */, 87830E70297A1AB900184A7C /* SignInTests.swift in Sources */, 87F53FE1297EA44E00293176 /* FireStoreTransactionManager.swift in Sources */, - 87830E7B297A1C6A00184A7C /* ContentView.swift in Sources */, 87C162DC2A2ACEA300382061 /* Transaction.swift in Sources */, 87CDAAC0297E8CF900F52887 /* AddTransactionView.swift in Sources */, 87CDAAB6297E5C8000F52887 /* CommonWalletViewModel.swift in Sources */, @@ -1018,7 +1012,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -1072,7 +1066,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = iphoneos; diff --git a/CommonWallet/AppDelegate.swift b/CommonWallet/AppDelegate.swift index bbffaf4..9af7785 100644 --- a/CommonWallet/AppDelegate.swift +++ b/CommonWallet/AppDelegate.swift @@ -11,7 +11,6 @@ class AppDelegate: NSObject, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { FirebaseApp.configure() - return true } } diff --git a/CommonWallet/ContentView.swift b/CommonWallet/ContentView.swift deleted file mode 100644 index 19d6bae..0000000 --- a/CommonWallet/ContentView.swift +++ /dev/null @@ -1,70 +0,0 @@ -// -// ContentView.swift -// CommonWallet -// -// Created by 前田航汰 on 2023/01/20. -// - -import SwiftUI -import FirebaseAuth - -struct ContentView: View { - let authManager = AuthManager() - @State var fireStoreUserManager = FireStoreUserManager() - @State var user: User? - - var body: some View { - VStack { - Image(systemName: "globe") - .imageScale(.large) - .foregroundColor(.accentColor) - Text("Hello, world!") - - Text(user?.id ?? "") - Text(user?.name ?? "") - Text(user?.email ?? "") - - Button(action: { - Task { - do { - try await authManager.signOut() - } catch { - print("サインアウト失敗", error) - } - } - }) { - Text("サインアウト") - } - - Button(action: { - Task { - do { - try await authManager.deleteUser() - } catch { - print("アカウント削除失敗", error) - } - } - }) { - Text("アカウント削除") - } - - } - .padding() - .onAppear { - Task { - let uid = Auth.auth().currentUser!.uid - fireStoreUserManager.realtimeFetchInfo(userId: uid, completion: { userr, error in - if let user = userr { - self.user = user - } - }) - } - } - } -} - -struct ContentView_Previews: PreviewProvider { - static var previews: some View { - ContentView() - } -} diff --git a/CommonWallet/Domain/Partner.swift b/CommonWallet/Domain/Partner.swift deleted file mode 100644 index 5988ce9..0000000 --- a/CommonWallet/Domain/Partner.swift +++ /dev/null @@ -1,14 +0,0 @@ -// -// Partner.swift -// CommonWallet -// - -import Foundation - -struct Partner { - var userId: String - var userName: String - var shareNumber: String - var iconPath: String - var iconData: Data -} diff --git a/CommonWallet/CoreData/SelectedEditTransaction.swift b/CommonWallet/Models/CoreData/SelectedEditTransaction.swift similarity index 100% rename from CommonWallet/CoreData/SelectedEditTransaction.swift rename to CommonWallet/Models/CoreData/SelectedEditTransaction.swift diff --git a/CommonWallet/CoreData/TransactionData.swift b/CommonWallet/Models/CoreData/TransactionData.swift similarity index 98% rename from CommonWallet/CoreData/TransactionData.swift rename to CommonWallet/Models/CoreData/TransactionData.swift index c7bbec4..1852f6d 100644 --- a/CommonWallet/CoreData/TransactionData.swift +++ b/CommonWallet/Models/CoreData/TransactionData.swift @@ -53,21 +53,20 @@ final public class TransactionData: ObservableObject { private var addSnapShotListenerCount: Int = 0 init() { - fetchTransactions() + realtimeFetchTransactions() } - private func fetchTransactions() { + private func realtimeFetchTransactions() { fireStoreTransactionManager.fetchTransactions(myUserId: myUserId, partnerUserId: partnerUserId, completion: { [weak self] transactions, error in if let error = error { print(error) - } - - guard let transactions = transactions else { return } + guard let transactions = transactions else { return } + // トランザクションを時系列ごとに並べ替える let sortedTransactions = transactions.sorted(by: { (a, b) -> Bool in return a.createdAt > b.createdAt diff --git a/CommonWallet/Models/Domain/Partner.swift b/CommonWallet/Models/Domain/Partner.swift new file mode 100644 index 0000000..a5483b6 --- /dev/null +++ b/CommonWallet/Models/Domain/Partner.swift @@ -0,0 +1,15 @@ +// +// Partner.swift +// CommonWallet +// + +import Foundation + +struct Partner { + var userId: String? + var userName: String + var modifiedName: String? + var shareNumber: String? + var iconPath: String? + var iconData: Data? +} diff --git a/CommonWallet/Domain/Transaction.swift b/CommonWallet/Models/Domain/Transaction.swift similarity index 100% rename from CommonWallet/Domain/Transaction.swift rename to CommonWallet/Models/Domain/Transaction.swift diff --git a/CommonWallet/Domain/User.swift b/CommonWallet/Models/Domain/User.swift similarity index 59% rename from CommonWallet/Domain/User.swift rename to CommonWallet/Models/Domain/User.swift index 77a4d2f..6da35b7 100644 --- a/CommonWallet/Domain/User.swift +++ b/CommonWallet/Models/Domain/User.swift @@ -11,11 +11,11 @@ struct User: Codable, Identifiable { // TODO: @DocumentID付けときたい // @DocumentID var id : String? = UUID().uuidString - var id : String = UUID().uuidString + var id : String var name: String - var email: String var shareNumber: String // 共有番号 var iconPath: String // アイコンのパス情報 + var iconData: Data? // アイコンのパス情報 var createdAt: Date? // アカウント作成日時 var partnerUserId: String? var partnerName: String? @@ -24,17 +24,18 @@ struct User: Codable, Identifiable { var oldestResolvedDate: Date? // 精算の最も古い日時 var partnerShareNumber: String? - enum CodingKeys: String, CodingKey { - case id - case name - case email - case shareNumber - case iconPath - case createdAt - case oldestResolvedDate - case partnerUserId - case partnerName - case partnerShareNumber - } +// enum CodingKeys: String, CodingKey { +// case id +// case name +// case email +// case shareNumber +// case iconPath +// case iconData +// case createdAt +// case oldestResolvedDate +// case partnerUserId +// case partnerName +// case partnerShareNumber +// } } diff --git a/CommonWallet/Models/Firebase/AuthManager.swift b/CommonWallet/Models/Firebase/AuthManager.swift deleted file mode 100644 index 9e8e384..0000000 --- a/CommonWallet/Models/Firebase/AuthManager.swift +++ /dev/null @@ -1,168 +0,0 @@ -// -// AuthManager.swift -// CommonWallet -// - -import Foundation -import FirebaseAuth -import Firebase -import FirebaseFirestore - -class AuthManager: AuthManaging { - - private static let shared = AuthManager() - private let db = Firestore.firestore() - private var fireStoreUserManager = FireStoreUserManager() - private var userDefaultsManager = UserDefaultsManager() - private var storageManager = StorageManager() - - // MARK: - サインイン処理 - func signIn(email:String, password:String) async throws { - - var userId = String() - var fireStoreError: Error! - - do { - // 通信して認証を行う - let result = try await Auth.auth().signIn(withEmail: email, password: password) - userId = result.user.uid - } catch { - throw FirebaseErrorType.Auth(error as NSError) - } - - // サインインと同時に、UserDefaultsの情報も追加する処理 - fireStoreUserManager.realtimeFetchInfo(userId: userId, completion: { user, error in - if let user = user { - self.userDefaultsManager.setUser(user: user) - } else { - fireStoreError = error - } - }) - if let error = fireStoreError { - throw error - } - - userDefaultsManager.setIsSignedIn(isSignedIn: true) - - } - - // MARK: - サインアウト処理 - func signOut() async throws { - - var fireStoreError: Error! - - guard let userId = Auth.auth().currentUser?.uid else { - throw NSError(domain: "サインインができていません。", code: 0) - } - - // Authのサインアウト処理 - do { - try Auth.auth().signOut() - userDefaultsManager.clearUser() - } catch { - throw FirebaseErrorType.Auth(error as NSError) - } - - // サインアウトと同時に、UserDefaultsの情報も削除する処理 - fireStoreUserManager.realtimeFetchInfo(userId: userId, completion: { user, error in - if let user = user { - self.userDefaultsManager.setUser(user: user) - } else { - fireStoreError = error - } - }) - if let error = fireStoreError { - throw error - } - - userDefaultsManager.setIsSignedIn(isSignedIn: false) - - } - - // MARK: - アカウント登録処理 - func createUser(email: String, password: String, name: String, shareNumber: String) async throws { - - var userId = String() - var fireStoreError: Error! - // 20枚サンプル画像がある下のパスから、ランダムに取得 - let sampleMyIconPath = "icon-sample-images/sample\(Int.random(in: 1...20)).jpeg" - let samplePartnerIconPath = "icon-sample-images/initial-partner-icon.jpeg" - - // FirebaseAuthへのアカウント登録 - do { - let result = try await Auth.auth().createUser(withEmail: email, password: password) - userId = result.user.uid - } catch { - throw FirebaseErrorType.Auth(error as NSError) - } - - // FireStoreへのアカウント情報追加 - do { - try await fireStoreUserManager.createUser(userId: userId, userName: name, email: email, iconPath: sampleMyIconPath, shareNumber: shareNumber) - } catch { - throw FirebaseErrorType.FireStore(error as NSError) - } - - // sampleIconを取得して、ユーザーデフォルトに入れる - // 自分のアイコン - storageManager.download(path: sampleMyIconPath, completion: { data, error in - if let data = data { - self.userDefaultsManager.setMyIcon(path: sampleMyIconPath, imageData: data) - } else { - print("AuthManager: アカウント作成時、サンプルアイコンエラー") - - } - }) - // パートナーのアイコン - storageManager.download(path: samplePartnerIconPath, completion: { data, error in - if let data = data { - self.userDefaultsManager.setPartnerIcon(path: samplePartnerIconPath, imageData: data) - } else { - print("AuthManager: アカウント作成時、サンプルアイコンエラー") - } - }) - - // アカウント登録と同時に、UserDefaultsの情報も追加する処理 - fireStoreUserManager.realtimeFetchInfo(userId: userId, completion: { user, error in - if let user = user { - self.userDefaultsManager.setUser(user: user) - } else { - fireStoreError = error - } - }) - if let error = fireStoreError { - throw error - } - - userDefaultsManager.setIsSignedIn(isSignedIn: true) - - } - - // MARK: - アカウント削除処理 - func deleteUser() async throws { - - guard let userId = Auth.auth().currentUser?.uid else { - throw FirebaseErrorType.other("uidが見つからない") - } - - // ①FireStoreのユーザデータ削除。この順番でないとFireStoreのユーザデータが削除できない - do { - try await fireStoreUserManager.deleteUser(userId: userId) - // アカウント削除と同時に、UserDefaultsの情報も削除する処理 - userDefaultsManager.clearUser() - } catch { - throw FirebaseErrorType.FireStore(error as NSError) - } - - // ②FirebaseAuthのユーザデータ削除。この順番でないとFireStoreのユーザデータが削除できない - do { - try await Auth.auth().currentUser?.delete() - userDefaultsManager.clearUser() - } catch { - throw FirebaseErrorType.Auth(error as NSError) - } - - userDefaultsManager.setIsSignedIn(isSignedIn: false) - } - -} diff --git a/CommonWallet/Models/Firebase/Firebase/AuthManager.swift b/CommonWallet/Models/Firebase/Firebase/AuthManager.swift new file mode 100644 index 0000000..07015c2 --- /dev/null +++ b/CommonWallet/Models/Firebase/Firebase/AuthManager.swift @@ -0,0 +1,15 @@ +// +// AuthManager.swift +// CommonWallet +// + +import Foundation +import FirebaseAuth + +class AuthManager: AuthManaging { + + func signInAnonymously() async throws -> AuthDataResult { + return try await Auth.auth().signInAnonymously() + } + +} diff --git a/CommonWallet/Models/Firebase/FireStorePartnerManager.swift b/CommonWallet/Models/Firebase/Firebase/FireStorePartnerManager.swift similarity index 100% rename from CommonWallet/Models/Firebase/FireStorePartnerManager.swift rename to CommonWallet/Models/Firebase/Firebase/FireStorePartnerManager.swift diff --git a/CommonWallet/Models/Firebase/FireStoreTransactionManager.swift b/CommonWallet/Models/Firebase/Firebase/FireStoreTransactionManager.swift similarity index 56% rename from CommonWallet/Models/Firebase/FireStoreTransactionManager.swift rename to CommonWallet/Models/Firebase/Firebase/FireStoreTransactionManager.swift index 5dd9da3..b2f45e8 100644 --- a/CommonWallet/Models/Firebase/FireStoreTransactionManager.swift +++ b/CommonWallet/Models/Firebase/Firebase/FireStoreTransactionManager.swift @@ -26,8 +26,8 @@ struct FireStoreTransactionManager: FireStoreTransactionManaging { // Firestoreに書き込むデータの作成 let transaction: Dictionary = ["id": transactionId, - "creditorId": creditorId ?? NSNull(), - "debtorId": debtorId ?? NSNull(), + "creditorId": creditorId ?? "", + "debtorId": debtorId ?? "", "title": title, "description": description, "amount": amount, @@ -48,7 +48,6 @@ struct FireStoreTransactionManager: FireStoreTransactionManaging { - parameter resolvedAt: 精算日時 */ func updateResolvedAt(transactionIds: [String], resolvedAt: Date) async throws { - let splitTransactionIds = transactionIds.splitIntoChunks(ofSize: 300) for transactionIds in splitTransactionIds { let batch = db.batch() @@ -86,8 +85,8 @@ struct FireStoreTransactionManager: FireStoreTransactionManaging { */ func updateTransaction(transaction: Transaction) async throws { let data: Dictionary = ["id": transaction.id, - "creditorId": transaction.creditorId ?? NSNull(), - "debtorId": transaction.debtorId ?? NSNull(), + "creditorId": transaction.creditorId ?? "", + "debtorId": transaction.debtorId ?? "", "title": transaction.title, "description": transaction.description, "amount": transaction.amount, @@ -99,16 +98,95 @@ struct FireStoreTransactionManager: FireStoreTransactionManaging { .setData(data, merge: true) } + /** + 複数のFireStorageのトランザクションを上書きする + - parameter transaction: 上書きするtransactionデータの配列 + */ + func updateTransactions(transactions: [Transaction]) async throws { + let splitTransactions = transactions.splitIntoChunks(ofSize: 300) + + for transactions in splitTransactions { + let batch = db.batch() + for transaction in transactions { + let document = db.collection("Transactions").document(transaction.id) + let data: Dictionary = ["id": transaction.id, + "creditorId": transaction.creditorId ?? "", + "debtorId": transaction.debtorId ?? "", + "title": transaction.title, + "description": transaction.description, + "amount": transaction.amount, + "createdAt": transaction.createdAt, + "resolvedAt": transaction.resolvedAt ?? NSNull()] + batch.updateData(data, forDocument: document) + } + try await batch.commit() + } + } + + /** + FireStorageトランザクションのCreditorをNullにする + - parameter transaction: Nullにするtransactionデータの配列 + */ + func updateCreditorNullOnTransactionIds(transactionIds: [String]) async throws { + let creditorNullOnTransaction: Dictionary = ["creditorId": ""] + let splitTransactionIds = transactionIds.splitIntoChunks(ofSize: 300) + + for transactionIds in splitTransactionIds { + let batch = db.batch() + for transactionId in transactionIds { + let document = db.collection("Transactions").document(transactionId) + batch.updateData(creditorNullOnTransaction, forDocument: document) + } + try await batch.commit() + } + } + + /** + FireStorageトランザクションのdebtorをNullにする + - parameter transaction: Nullにするtransactionデータの配列 + */ + func updateDebtorNullOnTransactionIds(transactionIds: [String]) async throws { + let creditorNullOnTransaction: Dictionary = ["debtorId": ""] + let splitTransactionIds = transactionIds.splitIntoChunks(ofSize: 300) + + for transactionIds in splitTransactionIds { + let batch = db.batch() + for transactionId in transactionIds { + let document = db.collection("Transactions").document(transactionId) + batch.updateData(creditorNullOnTransaction, forDocument: document) + } + try await batch.commit() + } + } + // MARK: - Delete /** - FireStorageのトランザクションを削除する + 単一のFireStorageのトランザクションを削除する - parameter transactionId: 削除するtransactionId */ func deleteTransaction(transactionId: String) async throws { try await db.collection("Transactions").document(transactionId).delete() } + /** + 複数のFireStorageのトランザクションを削除する + - Description + - アカウント削除する際に利用 + - parameter transactionIds: 削除するtransactionIdの配列 + */ + func deleteTransactions(transactionIds: [String]) async throws { + let splitTransactionIds = transactionIds.splitIntoChunks(ofSize: 300) + for transactionIds in splitTransactionIds { + let batch = db.batch() + for transactionId in transactionIds { + let document = db.collection("Transactions").document(transactionId) + batch.deleteDocument(document) + } + try await batch.commit() + } + } + // MARK: - GET /** @@ -123,9 +201,18 @@ struct FireStoreTransactionManager: FireStoreTransactionManaging { */ func fetchTransactions(myUserId: String, partnerUserId: String?, completion: @escaping([Transaction]?, Error?) -> Void) { + // パートナーが""で渡ってくるので、ほぼ全検索みたいな状態になってしまう。 + // 空文字列で来た際は、"xxx"をFireStoreで調べるようにして、全検索にならないようにする + var searchPartnerUserId = partnerUserId + if let partnerUserId = partnerUserId { + if partnerUserId.isEmpty { + searchPartnerUserId = "xxx" + } + } + // inを含むwhereFieldとorderByは同時に使えない db.collection("Transactions") - .whereField("creditorId", in: [partnerUserId, myUserId]) + .whereField("creditorId", in: [searchPartnerUserId, myUserId]) .addSnapshotListener { snapShots, error in if let error = error { @@ -154,111 +241,6 @@ struct FireStoreTransactionManager: FireStoreTransactionManaging { } } - func fetchUnResolvedTransactions(myUserId: String, partnerUserId: String, completion: @escaping([Transaction]?, Error?) -> Void) { - - // Transactionsコレクションから未精算の取引を取得する - // inを含むwhereFieldとorderByは同時に使えない - db.collection("Transactions") - .whereField("creditorId", in: [partnerUserId, myUserId]) - .whereField("resolvedAt", isEqualTo: NSNull()) - .addSnapshotListener { snapShots, error in - - if let error = error { - print("FireStore UnResolvedTransactions Fetch Error") - completion(nil, error) - } - - var transactions = [Transaction]() - snapShots?.documents.forEach({ snapShot in - let data = snapShot.data() - guard let id = data["id"] as? String, - let title = data["title"] as? String, - let description = data["description"] as? String, - let amount = data["amount"] as? Int, - let createdAt = data["createdAt"] as? Timestamp else { return } - - // creditorIdもdebtorIdもパートナー連携していない場合のため空でも許される - let debtorId = data["creditorId"] as? String - let creditorId = data["creditorId"] as? String - - let transaction = Transaction(id: id, creditorId: creditorId, debtorId: debtorId, title: title, description: description, amount: amount, createdAt: createdAt.dateValue()) - transactions.append(transaction) - }) - completion(transactions, nil) - } - } - - /** - 精算済のトランザクションを取得する - - parameter myUserId: 自分のUserId - - parameter partnerUserId: パートナーのUserId - */ - func fetchResolvedTransactions(myUserId: String, partnerUserId: String, completion: @escaping([Transaction]?, Error?) -> Void) { - - // inを含むwhereFieldとorderByは同時に使えない - db.collection("Transactions") - .whereField("creditorId", in: [partnerUserId, myUserId]) - .whereField("resolvedAt", isNotEqualTo: NSNull()) - .addSnapshotListener { snapShots, error in - - if let error = error { - print("FireStore ResolvedTransactions Fetch Error") - completion(nil, error) - } - - var transactions = [Transaction]() - snapShots?.documents.forEach({ snapShot in - let data = snapShot.data() - guard let id = data["id"] as? String, - let title = data["title"] as? String, - let description = data["description"] as? String, - let amount = data["amount"] as? Int, - let createdAt = data["createdAt"] as? Timestamp, - let resolvedAt = data["resolvedAt"] as? Timestamp else { return } - - // creditorIdもdebtorIdもパートナー連携していない場合のため空でも許される - let creditorId = data["creditorId"] as? String - let debtorId = data["debtorId"] as? String - - let transaction = Transaction(id: id, creditorId: creditorId, debtorId: debtorId, title: title, description: description, amount: amount, createdAt: createdAt.dateValue(), resolvedAt: resolvedAt.dateValue()) - transactions.append(transaction) - }) - completion(transactions, nil) - } - } - - // TODO: FireStoreのアクセス数がこれでバク上がる気がして、この関数嫌だ - /** - 最も古い精算済のトランザクションの日付を取得する - - Note: FireStoreのアクセス数がこれでバク上がる気がして、ちょっとこれ嫌だ - - parameter myUserId: 自分のUserId - - parameter partnerUserId: パートナーのUserId - - returns: 最も古い日付 - */ - func fetchOldestDate(myUserId: String, partnerUserId: String) async throws -> Date? { - let currentTimestamp = Timestamp(date: Date()) - let currentDate = Date() - // Transactionsコレクションから未精算の取引を取得する - let querySnapshot = try await db.collection("Transactions") - .whereField("resolvedAt", isNotEqualTo: NSNull()) - .whereField("creditorId", in: [partnerUserId, myUserId]) -// .order(by: "createdAt") -// .limit(to: 1) - .getDocuments() - - print("here") - - // トランザクションを時系列ごとに並べ替える - let sortedDocuments = querySnapshot.documents.sorted(by: { (a, b) -> Bool in - return (a.get("createdAt") as? Timestamp)?.dateValue() ?? currentDate < (b.get("createdAt") as? Timestamp)?.dateValue() ?? currentDate - }) - - guard let doc = sortedDocuments.first, - let oldestTimestamp = doc.get("createdAt") as? Timestamp else - { return nil } - return oldestTimestamp.dateValue() - } - } diff --git a/CommonWallet/Models/Firebase/FireStoreUserManager.swift b/CommonWallet/Models/Firebase/Firebase/FireStoreUserManager.swift similarity index 85% rename from CommonWallet/Models/Firebase/FireStoreUserManager.swift rename to CommonWallet/Models/Firebase/Firebase/FireStoreUserManager.swift index 1df87a2..40a4407 100644 --- a/CommonWallet/Models/Firebase/FireStoreUserManager.swift +++ b/CommonWallet/Models/Firebase/Firebase/FireStoreUserManager.swift @@ -12,21 +12,18 @@ import FirebaseFirestoreSwift struct FireStoreUserManager: FireStoreUserManaging { private let db = Firestore.firestore() - private var userDefaultsManager = UserDefaultsManager() // MARK: POST /** User情報を初期登録 - parameter userId: ユーザーID - parameter userName: ユーザー名 - - parameter email: メール - parameter iconPath: アイコンのパス - parameter shareNumber: 共有番号 */ - func createUser(userId: String, userName: String, email: String, iconPath: String, shareNumber: String) async throws { + func createUser(userId: String, userName: String, iconPath: String, shareNumber: String) async throws { let user: Dictionary = ["id": userId, "name": userName, - "email": email, "iconPath": iconPath, "shareNumber": shareNumber, "createdAt": Timestamp(), @@ -85,7 +82,6 @@ struct FireStoreUserManager: FireStoreUserManaging { guard let data = snapShot?.data(), let userId = data["id"] as? String, let userName = data["name"] as? String, - let email = data["email"] as? String, let iconPath = data["iconPath"] as? String, let shareNumber = data["shareNumber"] as? String, let createdAt = data["createdAt"] as? Timestamp else { return } @@ -94,7 +90,7 @@ struct FireStoreUserManager: FireStoreUserManaging { let partnerName = data["partnerName"] as? String let partnerShareNumber = data["partnerShareNumber"] as? String - let user = User(id: userId, name: userName, email: email, shareNumber: shareNumber, iconPath: iconPath, createdAt: createdAt.dateValue(), partnerUserId: partnerUserId, partnerName: partnerName, partnerShareNumber: partnerShareNumber) + let user = User(id: userId, name: userName, shareNumber: shareNumber, iconPath: iconPath, createdAt: createdAt.dateValue(), partnerUserId: partnerUserId, partnerName: partnerName, partnerShareNumber: partnerShareNumber) completion(user, nil) } diff --git a/CommonWallet/Models/Firebase/ShareNumberManager.swift b/CommonWallet/Models/Firebase/Firebase/ShareNumberManager.swift similarity index 54% rename from CommonWallet/Models/Firebase/ShareNumberManager.swift rename to CommonWallet/Models/Firebase/Firebase/ShareNumberManager.swift index cc1ff6c..52183e7 100644 --- a/CommonWallet/Models/Firebase/ShareNumberManager.swift +++ b/CommonWallet/Models/Firebase/Firebase/ShareNumberManager.swift @@ -11,43 +11,36 @@ class ShareNumberManager: ShareNumberManaging { private let db = Firestore.firestore() - /* + /** 12桁をランダムで生成 */ - func createShareNumber() async -> String { + func createShareNumber() async throws -> String { var shareNumber = createRandom16NumberString() - var duplicateCheck = await checkDuplicateNumber(number: shareNumber) + var duplicateCheck = try await checkDuplicateNumber(number: shareNumber) // もしshareNumberが重複した場合に作り直す処理 while !duplicateCheck { sleep(1) shareNumber = createRandom16NumberString() - duplicateCheck = await checkDuplicateNumber(number: shareNumber) + duplicateCheck = try await checkDuplicateNumber(number: shareNumber) } return shareNumber } - private func checkDuplicateNumber(number: String) async -> Bool { - - do { - let snapShots = try await db.collection("Users") - .whereField("shareNumber", isEqualTo: number) - .getDocuments() - - // もしドキュメントに同じ値が存在しなければtrueを返す - if snapShots.documents.count == 0 { - return true - } else { - return false - } - } catch { - print("Firebase Check Duplicate Number Error") - } + private func checkDuplicateNumber(number: String) async throws -> Bool { + let snapShots = try await db.collection("Users") + .whereField("shareNumber", isEqualTo: number) + .getDocuments() - return false + // もしドキュメントに同じ値が存在しなければtrueを返す + if snapShots.documents.count == 0 { + return true + } else { + return false + } } // 12桁の乱数を生成する関数 diff --git a/CommonWallet/Models/Firebase/StorageManager.swift b/CommonWallet/Models/Firebase/Firebase/StorageManager.swift similarity index 100% rename from CommonWallet/Models/Firebase/StorageManager.swift rename to CommonWallet/Models/Firebase/Firebase/StorageManager.swift diff --git a/CommonWallet/Models/Firebase/Protocol/AuthManaging.swift b/CommonWallet/Models/Firebase/Protocol/AuthManaging.swift new file mode 100644 index 0000000..a4166d6 --- /dev/null +++ b/CommonWallet/Models/Firebase/Protocol/AuthManaging.swift @@ -0,0 +1,11 @@ +// +// AuthManaging.swift +// CommonWallet +// + +import Foundation +import FirebaseAuth + +protocol AuthManaging { + func signInAnonymously() async throws -> AuthDataResult +} diff --git a/CommonWallet/Models/Protocol/FireStorePartnerManaging.swift b/CommonWallet/Models/Firebase/Protocol/FireStorePartnerManaging.swift similarity index 100% rename from CommonWallet/Models/Protocol/FireStorePartnerManaging.swift rename to CommonWallet/Models/Firebase/Protocol/FireStorePartnerManaging.swift diff --git a/CommonWallet/Models/Protocol/FireStoreTransactionManaging.swift b/CommonWallet/Models/Firebase/Protocol/FireStoreTransactionManaging.swift similarity index 69% rename from CommonWallet/Models/Protocol/FireStoreTransactionManaging.swift rename to CommonWallet/Models/Firebase/Protocol/FireStoreTransactionManaging.swift index ad0fa20..d226816 100644 --- a/CommonWallet/Models/Protocol/FireStoreTransactionManaging.swift +++ b/CommonWallet/Models/Firebase/Protocol/FireStoreTransactionManaging.swift @@ -14,15 +14,16 @@ protocol FireStoreTransactionManaging { func updateResolvedAt(transactionIds: [String], resolvedAt: Date) async throws func updateResolvedAt(transactionId: String, resolvedAt: Date) async throws func updateTransaction(transaction: Transaction) async throws + func updateTransactions(transactions: [Transaction]) async throws func updateCancelResolvedAt(transactionId: String) async throws + func updateCreditorNullOnTransactionIds(transactionIds: [String]) async throws + func updateDebtorNullOnTransactionIds(transactionIds: [String]) async throws // DELETE func deleteTransaction(transactionId: String) async throws + func deleteTransactions(transactionIds: [String]) async throws // GET func fetchTransactions(myUserId: String, partnerUserId: String?, completion: @escaping([Transaction]?, Error?) -> Void) - func fetchUnResolvedTransactions(myUserId: String, partnerUserId: String, completion: @escaping([Transaction]?, Error?) -> Void) - func fetchResolvedTransactions(myUserId: String, partnerUserId: String, completion: @escaping([Transaction]?, Error?) -> Void) - func fetchOldestDate(myUserId: String, partnerUserId: String) async throws -> Date? } diff --git a/CommonWallet/Models/Protocol/FireStoreUserManaging.swift b/CommonWallet/Models/Firebase/Protocol/FireStoreUserManaging.swift similarity index 66% rename from CommonWallet/Models/Protocol/FireStoreUserManaging.swift rename to CommonWallet/Models/Firebase/Protocol/FireStoreUserManaging.swift index a7239e8..61121cc 100644 --- a/CommonWallet/Models/Protocol/FireStoreUserManaging.swift +++ b/CommonWallet/Models/Firebase/Protocol/FireStoreUserManaging.swift @@ -8,14 +8,11 @@ import Foundation protocol FireStoreUserManaging { // MARK: POST - func createUser(userId: String, userName: String, email: String, iconPath: String, shareNumber: String) async throws + func createUser(userId: String, userName: String, iconPath: String, shareNumber: String) async throws // MARK: PUT func putUserName(userId: String, userName: String) async throws - // MARK: Delete - func deleteUser(userId: String) async throws - // MARK: Fetch func fetchInfo(userId: String) async throws -> User? func realtimeFetchInfo(userId: String, completion: @escaping(User?, Error?) -> Void) diff --git a/CommonWallet/Models/Protocol/ShareNumberManaging.swift b/CommonWallet/Models/Firebase/Protocol/ShareNumberManaging.swift similarity index 67% rename from CommonWallet/Models/Protocol/ShareNumberManaging.swift rename to CommonWallet/Models/Firebase/Protocol/ShareNumberManaging.swift index dc36f07..e528091 100644 --- a/CommonWallet/Models/Protocol/ShareNumberManaging.swift +++ b/CommonWallet/Models/Firebase/Protocol/ShareNumberManaging.swift @@ -6,5 +6,5 @@ import Foundation protocol ShareNumberManaging { - func createShareNumber() async -> String + func createShareNumber() async throws -> String } diff --git a/CommonWallet/Models/Protocol/StorageManaging.swift b/CommonWallet/Models/Firebase/Protocol/StorageManaging.swift similarity index 100% rename from CommonWallet/Models/Protocol/StorageManaging.swift rename to CommonWallet/Models/Firebase/Protocol/StorageManaging.swift diff --git a/CommonWallet/Models/Protocol/AuthManaging.swift b/CommonWallet/Models/Protocol/AuthManaging.swift deleted file mode 100644 index 01881a8..0000000 --- a/CommonWallet/Models/Protocol/AuthManaging.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// AuthManaging.swift -// CommonWallet -// - -import Foundation - -protocol AuthManaging { - func signIn(email:String, password:String) async throws - func signOut() async throws - func createUser(email: String, password: String, name: String, shareNumber: String) async throws - func deleteUser() async throws -} diff --git a/CommonWallet/Models/General/ImageNameProperty.swift b/CommonWallet/Models/UserDefaults/ImageNameProperty.swift similarity index 100% rename from CommonWallet/Models/General/ImageNameProperty.swift rename to CommonWallet/Models/UserDefaults/ImageNameProperty.swift diff --git a/CommonWallet/Models/Protocol/UserDefaultsManaging.swift b/CommonWallet/Models/UserDefaults/Protocol/UserDefaultsManaging.swift similarity index 93% rename from CommonWallet/Models/Protocol/UserDefaultsManaging.swift rename to CommonWallet/Models/UserDefaults/Protocol/UserDefaultsManaging.swift index 45b7d89..b5c2a55 100644 --- a/CommonWallet/Models/Protocol/UserDefaultsManaging.swift +++ b/CommonWallet/Models/UserDefaults/Protocol/UserDefaultsManaging.swift @@ -10,9 +10,11 @@ protocol UserDefaultsManaging { var userDefaultsKey: UserDefaultsKey { get } // MARK: - Setter + func createUser(user: User) + func createPartner(partner: Partner) func setUser(user: User) - func setMyUserName(userName: String) func setPartner(partner: Partner) + func setMyUserName(userName: String) func setPartner(userId: String, name: String, modifiedName: String, iconPath: String, iconData: Data, shareNumber: String) func setPartner(userId: String, name: String, modifiedName: String, shareNumber: String) func setPartnerUserId(userId: String) @@ -42,6 +44,6 @@ protocol UserDefaultsManaging { // MARK: Delete func clearUser() - func deletePartner() + func clearPartner() } diff --git a/CommonWallet/Models/General/UserDefaultsKey.swift b/CommonWallet/Models/UserDefaults/UserDefaultsKey.swift similarity index 98% rename from CommonWallet/Models/General/UserDefaultsKey.swift rename to CommonWallet/Models/UserDefaults/UserDefaultsKey.swift index 993a0ea..7b875ab 100644 --- a/CommonWallet/Models/General/UserDefaultsKey.swift +++ b/CommonWallet/Models/UserDefaults/UserDefaultsKey.swift @@ -35,7 +35,6 @@ struct UserDefaultsKey { let userId = "userId" let userName = "userName" let shareNumber = "shareNumber" - let email = "email" let myIconPath = "myIconPath" let myIconData = "myIconData" let createdAt = "createdAt" diff --git a/CommonWallet/Models/General/UserDefaultsManager.swift b/CommonWallet/Models/UserDefaults/UserDefaultsManager.swift similarity index 77% rename from CommonWallet/Models/General/UserDefaultsManager.swift rename to CommonWallet/Models/UserDefaults/UserDefaultsManager.swift index 55a58f0..3142757 100644 --- a/CommonWallet/Models/General/UserDefaultsManager.swift +++ b/CommonWallet/Models/UserDefaults/UserDefaultsManager.swift @@ -11,39 +11,67 @@ struct UserDefaultsManager: UserDefaultsManaging { internal let userDefaultsKey = UserDefaultsKey() // MARK: - Setter - func setUser(user: User) { + func createUser(user: User) { UserDefaults.standard.set(user.id, forKey: userDefaultsKey.userId) UserDefaults.standard.set(user.name, forKey: userDefaultsKey.userName) - UserDefaults.standard.set(user.email, forKey: userDefaultsKey.email) UserDefaults.standard.set(user.iconPath, forKey: userDefaultsKey.myIconPath) + UserDefaults.standard.set(user.iconData, forKey: userDefaultsKey.myIconData) UserDefaults.standard.set(user.shareNumber, forKey: userDefaultsKey.shareNumber) + UserDefaults.standard.set(user.createdAt, forKey: userDefaultsKey.createdAt) + } - if let partnerUserId = user.partnerUserId { - UserDefaults.standard.set(partnerUserId, forKey: userDefaultsKey.partnerUserId) - } + func setUser(user: User) { + UserDefaults.standard.set(user.id, forKey: userDefaultsKey.userId) + UserDefaults.standard.set(user.name, forKey: userDefaultsKey.userName) + UserDefaults.standard.set(user.iconPath, forKey: userDefaultsKey.myIconPath) + + UserDefaults.standard.set(user.shareNumber, forKey: userDefaultsKey.shareNumber) - if let partnerName = user.partnerName { - UserDefaults.standard.set(partnerName, forKey: userDefaultsKey.partnerName) + if let iconData = user.iconData { + UserDefaults.standard.set(iconData, forKey: userDefaultsKey.myIconData) } if let createdAt = user.createdAt { UserDefaults.standard.set(createdAt, forKey: userDefaultsKey.createdAt) } - } - func setMyUserName(userName: String) { - UserDefaults.standard.set(userName, forKey: userDefaultsKey.userName) } - func setPartner(partner: Partner) { + func createPartner(partner: Partner) { UserDefaults.standard.set(partner.userId, forKey: userDefaultsKey.partnerUserId) - UserDefaults.standard.set(partner.userName, forKey: userDefaultsKey.partnerName) UserDefaults.standard.set(partner.userName, forKey: userDefaultsKey.partnerModifiedName) UserDefaults.standard.set(partner.iconPath, forKey: userDefaultsKey.partnerIconPath) UserDefaults.standard.set(partner.iconData, forKey: userDefaultsKey.partnerIconData) UserDefaults.standard.set(partner.shareNumber, forKey: userDefaultsKey.partnerShareNumber) } + func setMyUserName(userName: String) { + UserDefaults.standard.set(userName, forKey: userDefaultsKey.userName) + } + + func setPartner(partner: Partner) { + if let userId = partner.userId { + UserDefaults.standard.set(userId, forKey: userDefaultsKey.partnerUserId) + } + UserDefaults.standard.set(partner.userName, forKey: userDefaultsKey.partnerName) + + if let modifiedName = partner.modifiedName { + UserDefaults.standard.set(modifiedName, forKey: userDefaultsKey.partnerModifiedName) + } + if let shareNumber = partner.shareNumber { + UserDefaults.standard.set(shareNumber, forKey: userDefaultsKey.partnerShareNumber) + + } + if let iconPath = partner.iconPath { + UserDefaults.standard.set(iconPath, forKey: userDefaultsKey.partnerIconPath) + + } + if let iconData = partner.iconData { + UserDefaults.standard.set(partner.iconData, forKey: userDefaultsKey.partnerIconData) + + } + } + func setPartner(userId: String, name: String, modifiedName: String, iconPath: String, iconData: Data, shareNumber: String) { UserDefaults.standard.set(userId, forKey: userDefaultsKey.partnerUserId) UserDefaults.standard.set(name, forKey: userDefaultsKey.partnerName) @@ -101,7 +129,6 @@ struct UserDefaultsManager: UserDefaultsManaging { // MARK: - Getter func getUser() -> User? { guard let userName = UserDefaults.standard.string(forKey: userDefaultsKey.userName), - let email = UserDefaults.standard.string(forKey: userDefaultsKey.email), let userId = UserDefaults.standard.string(forKey: userDefaultsKey.userId), let myIconPath = UserDefaults.standard.string(forKey: userDefaultsKey.myIconPath), let shareNumber = UserDefaults.standard.string(forKey: userDefaultsKey.shareNumber) @@ -113,7 +140,7 @@ struct UserDefaultsManager: UserDefaultsManaging { let partnerName = UserDefaults.standard.string(forKey: userDefaultsKey.partnerName) let createdAt = UserDefaults.standard.object(forKey: userDefaultsKey.createdAt) as? Date - let user = User(id: userId, name: userName, email: email, shareNumber: shareNumber, iconPath: myIconPath, createdAt: createdAt, partnerUserId: partnerUserId, partnerName: partnerName) + let user = User(id: userId, name: userName, shareNumber: shareNumber, iconPath: myIconPath, createdAt: createdAt, partnerUserId: partnerUserId, partnerName: partnerName) return user } @@ -171,17 +198,22 @@ struct UserDefaultsManager: UserDefaultsManaging { // MARK: Delete func clearUser() { + // Myユーザー情報 UserDefaults.standard.set(nil, forKey: userDefaultsKey.userId) UserDefaults.standard.set(nil, forKey: userDefaultsKey.userName) - UserDefaults.standard.set(nil, forKey: userDefaultsKey.email) UserDefaults.standard.set(nil, forKey: userDefaultsKey.shareNumber) - UserDefaults.standard.set(nil, forKey: userDefaultsKey.partnerUserId) - UserDefaults.standard.set(nil, forKey: userDefaultsKey.partnerName) + UserDefaults.standard.set(nil, forKey: userDefaultsKey.myIconPath) + UserDefaults.standard.set(nil, forKey: userDefaultsKey.myIconData) + UserDefaults.standard.set(nil, forKey: userDefaultsKey.createdAt) + UserDefaults.standard.set(nil, forKey: userDefaultsKey.oldestResolvedDate) } - func deletePartner() { + func clearPartner() { UserDefaults.standard.set(nil, forKey: userDefaultsKey.partnerUserId) UserDefaults.standard.set(nil, forKey: userDefaultsKey.partnerName) + UserDefaults.standard.set(nil, forKey: userDefaultsKey.partnerIconPath) + UserDefaults.standard.set(nil, forKey: userDefaultsKey.partnerIconPath) + UserDefaults.standard.set(nil, forKey: userDefaultsKey.partnerModifiedName) UserDefaults.standard.set(nil, forKey: userDefaultsKey.partnerShareNumber) } diff --git a/CommonWallet/Sceans/Authentication/View/CreateUserView.swift b/CommonWallet/Sceans/Authentication/View/CreateUserView.swift index 291269d..8582774 100644 --- a/CommonWallet/Sceans/Authentication/View/CreateUserView.swift +++ b/CommonWallet/Sceans/Authentication/View/CreateUserView.swift @@ -5,49 +5,49 @@ import SwiftUI -struct CreateUserView: View { - - @ObservedObject var createUserViewModel = CreateUserViewModel() - - @State var name = "" - @State var mailAdress = "" - @State var password = "" - @State private var isSecondView: Bool = false - @Binding var isShow: Bool - - var body: some View { - VStack { - Text("アカウント登録") - TextField("名前", text: $name) - TextField("メールアドレス", text: $mailAdress) - TextField("パスワード", text: $password) - - Button(action: { - - Task { - await createUserViewModel.createUser(email: mailAdress, password: password, name: name, complition: { isSuccess, message in - isSecondView = isSuccess - print(isSuccess, message) - }) - } - - }) { - Text("アカウント登録").fontWeight(.bold).font(.largeTitle) - } - .fullScreenCover(isPresented: self.$isSecondView) { - // trueになれば下からふわっと表示 - MainTabView() - } - - Button { - isShow = false - } label: { - Text("ログインはこちら") - } - } - .padding() - } -} +//struct CreateUserView: View { +// +// @ObservedObject var createUserViewModel = CreateUserViewModel() +// +// @State var name = "" +// @State var mailAdress = "" +// @State var password = "" +// @State private var isSecondView: Bool = false +// @Binding var isShow: Bool +// +// var body: some View { +// VStack { +// Text("アカウント登録") +// TextField("名前", text: $name) +// TextField("メールアドレス", text: $mailAdress) +// TextField("パスワード", text: $password) +// +// Button(action: { +// +// Task { +// await createUserViewModel.createUser(email: mailAdress, password: password, name: name, complition: { isSuccess, message in +// isSecondView = isSuccess +// print(isSuccess, message) +// }) +// } +// +// }) { +// Text("アカウント登録").fontWeight(.bold).font(.largeTitle) +// } +// .fullScreenCover(isPresented: self.$isSecondView) { +// // trueになれば下からふわっと表示 +// MainTabView() +// } +// +// Button { +// isShow = false +// } label: { +// Text("ログインはこちら") +// } +// } +// .padding() +// } +//} //struct CreateUserView_Previews: PreviewProvider { // static var previews: some View { diff --git a/CommonWallet/Sceans/Authentication/View/SignInView.swift b/CommonWallet/Sceans/Authentication/View/SignInView.swift index dafdea7..68cf34f 100644 --- a/CommonWallet/Sceans/Authentication/View/SignInView.swift +++ b/CommonWallet/Sceans/Authentication/View/SignInView.swift @@ -3,53 +3,53 @@ // CommonWallet // -import SwiftUI -import FirebaseAuth - -struct SignInView: View { - - @ObservedObject var signInViewModel = SignInViewModel() - - @State var email = "" - @State var password = "" - @State private var isSecondView: Bool = false - @State private var isCreateUserView: Bool = false - - var body: some View { - VStack { - Text("ログイン") - TextField("メールアドレス", text: $email) - TextField("パスワード", text: $password) - - Button(action: { - Task { - await signInViewModel.signIn(email: email, password: password, complition:{ isSuccess, message in - print(isSuccess, message) - }) - } - }) { - Text("ログイン").fontWeight(.bold).font(.largeTitle) - } - .fullScreenCover(isPresented: self.$isSecondView) { - MainTabView() - } - - Button { - isCreateUserView.toggle() - } label: { - Text("アカウント登録はこちら") - } - .fullScreenCover(isPresented: $isCreateUserView) { - CreateUserView(isShow: $isCreateUserView) - } - } - .padding() - } - -} - -struct SignInView_Previews: PreviewProvider { - static var previews: some View { - SignInView() - } -} +//import SwiftUI +//import FirebaseAuth +// +//struct SignInView: View { +// +// @ObservedObject var signInViewModel = SignInViewModel() +// +// @State var email = "" +// @State var password = "" +// @State private var isSecondView: Bool = false +// @State private var isCreateUserView: Bool = false +// +// var body: some View { +// VStack { +// Text("ログイン") +// TextField("メールアドレス", text: $email) +// TextField("パスワード", text: $password) +// +// Button(action: { +// Task { +// await signInViewModel.signIn(email: email, password: password, complition:{ isSuccess, message in +// print(isSuccess, message) +// }) +// } +// }) { +// Text("ログイン").fontWeight(.bold).font(.largeTitle) +// } +// .fullScreenCover(isPresented: self.$isSecondView) { +// MainTabView() +// } +// +// Button { +// isCreateUserView.toggle() +// } label: { +// Text("アカウント登録はこちら") +// } +// .fullScreenCover(isPresented: $isCreateUserView) { +// //CreateUserView(isShow: $isCreateUserView) +// } +// } +// .padding() +// } +// +//} +// +//struct SignInView_Previews: PreviewProvider { +// static var previews: some View { +// SignInView() +// } +//} diff --git a/CommonWallet/Sceans/Authentication/ViewModels/CreateUserViewModel.swift b/CommonWallet/Sceans/Authentication/ViewModels/CreateUserViewModel.swift index d0e4970..c7bffea 100644 --- a/CommonWallet/Sceans/Authentication/ViewModels/CreateUserViewModel.swift +++ b/CommonWallet/Sceans/Authentication/ViewModels/CreateUserViewModel.swift @@ -5,31 +5,54 @@ import Foundation -class CreateUserViewModel: ObservableObject { - let authManager = AuthManager() - let errorMessageManegar = FirebaseErrorManager() - let shareNumberManager = ShareNumberManager() - - func createUser(email: String, password: String, name: String, complition: @escaping (Bool, String) -> Void) async { - - // ユーザーの共有番号を作る - var shareNumber = "" - do { - shareNumber = await shareNumberManager.createShareNumber() - } - - do { - try await authManager.createUser(email: email, password: password, name: name, shareNumber: shareNumber) - complition(true, "アカウント登録成功") - - } catch FirebaseErrorType.Auth(let error) { - let errorMessage = errorMessageManegar.getAuthErrorMessage(error) - complition(false, errorMessage) - } catch FirebaseErrorType.FireStore(let error) { - let errorMessage = errorMessageManegar.getFireStoreErrorMessage(error) - complition(false, errorMessage) - } catch { - complition(false, "不明なエラー") - } - } -} +//class CreateUserViewModel: ObservableObject { +// let authManager = AuthManager() +// let errorMessageManegar = FirebaseErrorManager() +// let shareNumberManager = ShareNumberManager() +// +// func createUser(email: String, password: String, name: String, complition: @escaping (Bool, String) -> Void) async { +// +// // ユーザーの共有番号を作る +// var shareNumber = "" +// do { +// shareNumber = await shareNumberManager.createShareNumber() +// } +// +// do { +// try await authManager.createUser(email: email, password: password, name: name, shareNumber: shareNumber) +// complition(true, "アカウント登録成功") +// +// } catch FirebaseErrorType.Auth(let error) { +// let errorMessage = errorMessageManegar.getAuthErrorMessage(error) +// complition(false, errorMessage) +// } catch FirebaseErrorType.FireStore(let error) { +// let errorMessage = errorMessageManegar.getFireStoreErrorMessage(error) +// complition(false, errorMessage) +// } catch { +// complition(false, "不明なエラー") +// } +// } +// +// func createUser() async { +// +// // ユーザーの共有番号を作る +// var shareNumber = "" +// do { +// shareNumber = await shareNumberManager.createShareNumber() +// } +// +// do { +// try await authManager.createUser(email: email, password: password, name: name, shareNumber: shareNumber) +// complition(true, "アカウント登録成功") +// +// } catch FirebaseErrorType.Auth(let error) { +// let errorMessage = errorMessageManegar.getAuthErrorMessage(error) +// complition(false, errorMessage) +// } catch FirebaseErrorType.FireStore(let error) { +// let errorMessage = errorMessageManegar.getFireStoreErrorMessage(error) +// complition(false, errorMessage) +// } catch { +// complition(false, "不明なエラー") +// } +// } +//} diff --git a/CommonWallet/Sceans/Authentication/ViewModels/SignInViewModel.swift b/CommonWallet/Sceans/Authentication/ViewModels/SignInViewModel.swift index 0d1e0a3..46b1708 100644 --- a/CommonWallet/Sceans/Authentication/ViewModels/SignInViewModel.swift +++ b/CommonWallet/Sceans/Authentication/ViewModels/SignInViewModel.swift @@ -3,22 +3,22 @@ // CommonWallet // -import Foundation - -class SignInViewModel: ObservableObject { - let authManager = AuthManager() - let errorMessageManegar = FirebaseErrorManager() - - func signIn(email: String, password: String, complition: @escaping (Bool, String) -> Void) async { - do { - try await authManager.signIn(email: email, password: password) - complition(true, "サインインの成功") - } catch FirebaseErrorType.Auth(let error){ - let errorMessage = errorMessageManegar.getAuthErrorMessage(error) - complition(false, errorMessage) - } catch { - complition(false, "不明なエラー") - } - } - -} +//import Foundation +// +//class SignInViewModel: ObservableObject { +// let authManager = AuthManager() +// let errorMessageManegar = FirebaseErrorManager() +// +// func signIn(email: String, password: String, complition: @escaping (Bool, String) -> Void) async { +// do { +// try await authManager.signIn(email: email, password: password) +// complition(true, "サインインの成功") +// } catch FirebaseErrorType.Auth(let error){ +// let errorMessage = errorMessageManegar.getAuthErrorMessage(error) +// complition(false, errorMessage) +// } catch { +// complition(false, "不明なエラー") +// } +// } +// +//} diff --git a/CommonWallet/Sceans/Launch/View/LaunchScreen.swift b/CommonWallet/Sceans/Launch/View/LaunchScreen.swift index 519935a..3bcf21f 100644 --- a/CommonWallet/Sceans/Launch/View/LaunchScreen.swift +++ b/CommonWallet/Sceans/Launch/View/LaunchScreen.swift @@ -22,10 +22,11 @@ struct LaunchScreen: View { @State private var fireStoreUserManager = FireStoreUserManager() @State private var fireStorePartnerManager = FireStorePartnerManager() - @ObservedObject var launchViewModel = LaunchViewModel() + @ObservedObject var viewModel = LaunchViewModel() var body: some View { + // 既に匿名ログインが済んでいる場合 if let _ = Auth.auth().currentUser?.uid { if isMainTabViewLoading { ZStack { @@ -34,10 +35,7 @@ struct LaunchScreen: View { Image("SampleLogo") } .onAppear { - Task { - await launchViewModel.fetchPartnerInfo() - await launchViewModel.fetchUserInfo() - } + print("アカウント作成済み") DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { withAnimation { isMainTabViewLoading = false @@ -48,18 +46,29 @@ struct LaunchScreen: View { MainTabView() } + // 匿名ログインが済んでいない場合 } else { - if isSignInViewLoading { ZStack { Color(.red) .ignoresSafeArea() // ステータスバーまで塗り潰すために必要 + Text("アカウント作成中...") Image("Sample1") .resizable() .aspectRatio(contentMode: .fit) .padding() } .onAppear { + // アカウント作成 + Task { + do { + try await viewModel.createUser(myUserName: "ユーザー", partnerUserName: "パートナー") + print("アカウント作成しました!") + } catch { + print(#function, error) + } + } + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { withAnimation { isSignInViewLoading = false @@ -67,7 +76,7 @@ struct LaunchScreen: View { } } } else { - SignInView() + MainTabView() } } } diff --git a/CommonWallet/Sceans/Launch/ViewModels/LaunchViewModel.swift b/CommonWallet/Sceans/Launch/ViewModels/LaunchViewModel.swift index d2efaea..eb7c17d 100644 --- a/CommonWallet/Sceans/Launch/ViewModels/LaunchViewModel.swift +++ b/CommonWallet/Sceans/Launch/ViewModels/LaunchViewModel.swift @@ -8,57 +8,34 @@ import FirebaseAuth class LaunchViewModel: ObservableObject { + private var authManager = AuthManager() + private var shareNumberManager = ShareNumberManager() private var fireStoreTransactionManager = FireStoreTransactionManager() private var fireStoreUserManager = FireStoreUserManager() private var fireStorePartnerManager = FireStorePartnerManager() + private var storageManager = StorageManager() private var userDefaultsManager = UserDefaultsManager() - // ここでUserInfoをfetchする - // addSnapListernerだから、更新されるたびに自動でUserDefaultsが更新される - func fetchUserInfo() async { - guard let userId = Auth.auth().currentUser?.uid else { - print("haven't Auth.auth().currentUser?.uid") - return - } - self.fireStoreUserManager.realtimeFetchInfo(userId: userId, completion: { user, error in - if error != nil { - print("error") - return - } - guard let user = user else { - print("haven't user") - return - } - self.userDefaultsManager.setUser(user: user) - }) - } - - func fetchPartnerInfo() async { - - guard let myUserId = userDefaultsManager.getUser()?.id else { - return - } - - fireStorePartnerManager.realtimeFetchInfo(myUserId: myUserId, completion: { partner, error in - if let error = error { - return - } - - guard let partner = partner else { - print("haven't partner") - return - } - - let partnerUserDefaultsName = self.userDefaultsManager.getPartnerName() ?? partner.userName - self.userDefaultsManager.setPartner( - userId: partner.userId, - name: partner.userName, - modifiedName: partnerUserDefaultsName, - iconPath: partner.iconPath, - iconData: partner.iconData, - shareNumber: partner.shareNumber - ) - }) + func createUser(myUserName: String, partnerUserName: String) async throws { + // アカウント作成 + let authResult = try await authManager.signInAnonymously() + + // 自分の情報定義 + let myUserId = authResult.user.uid + let sampleMyIconPath = "icon-sample-images/sample\(Int.random(in: 1...20)).jpeg" + let samplePartnerIconPath = "icon-sample-images/initial-partner-icon.jpeg" + let sampleMyIconData = try await storageManager.download(path: sampleMyIconPath) + let samplePartnerIconData = try await storageManager.download(path: samplePartnerIconPath) + let shareNumber = try await shareNumberManager.createShareNumber() + + // トランザクションにアカウント登録 + try await fireStoreUserManager.createUser(userId: myUserId, userName: myUserName, iconPath: sampleMyIconPath, shareNumber: shareNumber) + + // Userdefaultsに保存 + let user = User(id: myUserId, name: myUserName, shareNumber: shareNumber, iconPath: sampleMyIconPath, iconData: sampleMyIconData, createdAt: Date()) + let partner = Partner(userName: partnerUserName, iconPath: samplePartnerIconPath, iconData: samplePartnerIconData) + userDefaultsManager.createUser(user: user) + userDefaultsManager.createPartner(partner: partner) } } diff --git a/CommonWallet/Sceans/MainTab/View/MainTabView.swift b/CommonWallet/Sceans/MainTab/MainTabView.swift similarity index 79% rename from CommonWallet/Sceans/MainTab/View/MainTabView.swift rename to CommonWallet/Sceans/MainTab/MainTabView.swift index 457bf30..f50149b 100644 --- a/CommonWallet/Sceans/MainTab/View/MainTabView.swift +++ b/CommonWallet/Sceans/MainTab/MainTabView.swift @@ -7,7 +7,7 @@ import SwiftUI struct MainTabView: View { - @ObservedObject var mainTabViewModel = MainTabViewModel() + @ObservedObject var viewModel = MainTabViewModel() var body: some View { TabView { @@ -25,6 +25,11 @@ struct MainTabView: View { Text("履歴") } }.tag(2) + }.onAppear { + Task { + await viewModel.realtimeFetchPartnerInfo() + await viewModel.realtimeFetchUserInfo() + } } } diff --git a/CommonWallet/Sceans/MainTab/MainTabViewModel.swift b/CommonWallet/Sceans/MainTab/MainTabViewModel.swift new file mode 100644 index 0000000..6b0568c --- /dev/null +++ b/CommonWallet/Sceans/MainTab/MainTabViewModel.swift @@ -0,0 +1,50 @@ +// +// MainTabViewModel.swift +// CommonWallet +// + +import Foundation + +class MainTabViewModel: ObservableObject { + private var authManager = AuthManager() + private var shareNumberManager = ShareNumberManager() + private var fireStoreTransactionManager = FireStoreTransactionManager() + private var fireStoreUserManager = FireStoreUserManager() + private var fireStorePartnerManager = FireStorePartnerManager() + private var storageManager = StorageManager() + private var userDefaultsManager = UserDefaultsManager() + + // ここでUserInfoをfetchする + // addSnapListernerだから、更新されるたびに自動でUserDefaultsが更新される + func realtimeFetchUserInfo() async { + + guard let myUserId = userDefaultsManager.getUser()?.id else { return } + self.fireStoreUserManager.realtimeFetchInfo(userId: myUserId, completion: { [weak self] user, error in + + if let error = error { + print(error) + return + } + + guard let user = user else { return } + self?.userDefaultsManager.setUser(user: user) + }) + } + + func realtimeFetchPartnerInfo() async { + + guard let myUserId = userDefaultsManager.getUser()?.id else { return } + + fireStorePartnerManager.realtimeFetchInfo(myUserId: myUserId, completion: { [weak self] partner, error in + + if let error = error { + print(error) + return + } + + guard let partner = partner else { return } + self?.userDefaultsManager.setPartner(partner: partner) + }) + } + +} diff --git a/CommonWallet/Sceans/MainTab/ViewMdels/MainTabViewModel.swift b/CommonWallet/Sceans/MainTab/ViewMdels/MainTabViewModel.swift deleted file mode 100644 index d2fe6b8..0000000 --- a/CommonWallet/Sceans/MainTab/ViewMdels/MainTabViewModel.swift +++ /dev/null @@ -1,9 +0,0 @@ -// -// MainTabViewModel.swift -// CommonWallet -// - -import Foundation - -class MainTabViewModel: ObservableObject { -} diff --git a/CommonWallet/Sceans/Setting/View/AccountView.swift b/CommonWallet/Sceans/Setting/View/AccountView.swift index 9058dff..ce10f1d 100644 --- a/CommonWallet/Sceans/Setting/View/AccountView.swift +++ b/CommonWallet/Sceans/Setting/View/AccountView.swift @@ -8,6 +8,7 @@ import SwiftUI struct AccountView: View { @StateObject var viewModel: AccountViewModel + @EnvironmentObject var transactionData: TransactionData @AppStorage(UserDefaultsKey().userName) private var userName = String() @AppStorage(UserDefaultsKey().myIconData) private var myIconData = Data() @@ -63,7 +64,7 @@ struct AccountView: View { Button("リセット", role: .destructive){ Task { do { - try await authManager.deleteUser() + try await viewModel.clearAccount(transactions: transactionData.transactions) } catch { print("アカウント削除", error) } @@ -75,7 +76,6 @@ struct AccountView: View { } // MARK: - Section - /** アイコンを表示するView, タップでアイコン変更 - Returns: View(Section) @@ -169,6 +169,6 @@ struct AccountView: View { struct AccountView_Previews: PreviewProvider { static var previews: some View { - AccountView(viewModel: AccountViewModel(userDefaultsManager: UserDefaultsManager(), storageManager: StorageManager())) + AccountView(viewModel: AccountViewModel(fireStoreTransactionManager: FireStoreTransactionManager(), fireStoreUserManager: FireStoreUserManager(), userDefaultsManager: UserDefaultsManager(), storageManager: StorageManager(), authManager: AuthManager())) } } diff --git a/CommonWallet/Sceans/Setting/View/SettingView.swift b/CommonWallet/Sceans/Setting/View/SettingView.swift index bcd6e67..501fb88 100644 --- a/CommonWallet/Sceans/Setting/View/SettingView.swift +++ b/CommonWallet/Sceans/Setting/View/SettingView.swift @@ -64,7 +64,7 @@ struct SettingView: View { Section { // タップ後: AccountViewへNavigation遷移 - NavigationLink(destination: AccountView(viewModel: AccountViewModel(userDefaultsManager: UserDefaultsManager(), storageManager: StorageManager()))) { + NavigationLink(destination:AccountView(viewModel: AccountViewModel(fireStoreTransactionManager: FireStoreTransactionManager(), fireStoreUserManager: FireStoreUserManager(), userDefaultsManager: UserDefaultsManager(), storageManager: StorageManager(), authManager: AuthManager()))) { HStack { Image(uiImage: UIImage(data: myIconData) ?? UIImage(named: imageNameProperty.iconNotFound)!) .resizable() diff --git a/CommonWallet/Sceans/Setting/ViewModels/AccountViewModel.swift b/CommonWallet/Sceans/Setting/ViewModels/AccountViewModel.swift index 0e1cec7..f04e67a 100644 --- a/CommonWallet/Sceans/Setting/ViewModels/AccountViewModel.swift +++ b/CommonWallet/Sceans/Setting/ViewModels/AccountViewModel.swift @@ -4,16 +4,28 @@ // import Foundation +import FirebaseAuth import SwiftUI class AccountViewModel: ObservableObject { + private var fireStoreTransactionManager: FireStoreTransactionManaging + private var shareNumberManager = ShareNumberManager() + private var fireStoreUserManager: FireStoreUserManaging private var userDefaultsManager: UserDefaultsManaging private var storageManager: StorageManaging + private var authManager: AuthManaging - init(userDefaultsManager: UserDefaultsManaging, storageManager: StorageManaging) { + init(fireStoreTransactionManager: FireStoreTransactionManaging, + fireStoreUserManager: FireStoreUserManaging, + userDefaultsManager: UserDefaultsManaging, + storageManager: StorageManaging, + authManager: AuthManaging) { + self.fireStoreTransactionManager = fireStoreTransactionManager + self.fireStoreUserManager = fireStoreUserManager self.userDefaultsManager = userDefaultsManager self.storageManager = storageManager + self.authManager = authManager } /** @@ -50,4 +62,65 @@ class AccountViewModel: ObservableObject { } + /** + アカウントリセットを行う + - Description + - トランザクションの削除 + - fireStoreのUserを削除 + - authから削除 + - UserDefaultsのクリーン + - parameter transactions: 今持っている全てのトランザクション + */ + internal func clearAccount(transactions: [Transaction]) async throws { + + guard let myUserId = Auth.auth().currentUser?.uid else { return } + + // トランザクションの削除 + // パートナーが空の場合、そのトランザションは削除 + let userNullTransactionIds = transactions + .filter{ + ($0.debtorId == myUserId && $0.creditorId == "") || + ($0.debtorId == "" && $0.creditorId == myUserId) + } + .map { $0.id } + // creditorIdに自分のIdが含まれていて、パートナーが存在する場合は、そこをnullにしてアップデート + let myCreditorTransactionIds = transactions + .filter{ ($0.creditorId == myUserId && $0.debtorId != "") } + .map { $0.id } + // debtorIdに自分のIdが含まれていて、パートナーが存在する場合は、そこをnullにしてアップデート + let myDebtorTransactionIds = transactions + .filter{ ($0.debtorId == myUserId && $0.creditorId != "") } + .map { $0.id } + + // ここは非同期で並列処理。関数を抜けるまでには必ず処理される。 + async let _ = fireStoreTransactionManager.deleteTransactions(transactionIds: userNullTransactionIds) + async let _ = fireStoreTransactionManager.updateCreditorNullOnTransactionIds(transactionIds: myCreditorTransactionIds) + async let _ = fireStoreTransactionManager.updateDebtorNullOnTransactionIds(transactionIds: myDebtorTransactionIds) + + // IconImageの削除 + if let myIconPath = userDefaultsManager.getMyIconImagePath() { + storageManager.deleteImage(path: myIconPath) + } + + // 初期情報定義 + let myUserName = "ユーザー" + let partnerUserName = "パートナー" + let sampleMyIconPath = "icon-sample-images/sample\(Int.random(in: 1...20)).jpeg" + let samplePartnerIconPath = "icon-sample-images/initial-partner-icon.jpeg" + let sampleMyIconData = try await storageManager.download(path: sampleMyIconPath) + let samplePartnerIconData = try await storageManager.download(path: samplePartnerIconPath) + let shareNumber = try await shareNumberManager.createShareNumber() + + // トランザクションにアカウント登録 + try await fireStoreUserManager.createUser(userId: myUserId, userName: myUserName, iconPath: sampleMyIconPath, shareNumber: shareNumber) + + // Userdefaultsに保存 + userDefaultsManager.clearUser() + userDefaultsManager.clearPartner() + let user = User(id: myUserId, name: myUserName, shareNumber: shareNumber, iconPath: sampleMyIconPath, iconData: sampleMyIconData, createdAt: Date()) + let partner = Partner(userName: partnerUserName, iconPath: samplePartnerIconPath, iconData: samplePartnerIconData) + userDefaultsManager.createUser(user: user) + userDefaultsManager.createPartner(partner: partner) + } + } diff --git a/CommonWallet/Sceans/Setting/ViewModels/PartnerInfoViewModel.swift b/CommonWallet/Sceans/Setting/ViewModels/PartnerInfoViewModel.swift index fa84f11..bf1f7a5 100644 --- a/CommonWallet/Sceans/Setting/ViewModels/PartnerInfoViewModel.swift +++ b/CommonWallet/Sceans/Setting/ViewModels/PartnerInfoViewModel.swift @@ -27,7 +27,7 @@ class PartnerInfoViewModel: ObservableObject { throw UserDefaultsError.emptyMyUserId } try await fireStorePartnerManager.deletePartner(myUserId: myUserId, partnerUserId: partnerUserId) - userDefaultsManager.deletePartner() + userDefaultsManager.clearPartner() } } diff --git a/CommonWallet/Source/Flip.swift b/CommonWallet/ViewTools/Flip.swift similarity index 100% rename from CommonWallet/Source/Flip.swift rename to CommonWallet/ViewTools/Flip.swift diff --git a/CommonWallet/Source/ImagePicker.swift b/CommonWallet/ViewTools/ImagePicker.swift similarity index 100% rename from CommonWallet/Source/ImagePicker.swift rename to CommonWallet/ViewTools/ImagePicker.swift diff --git a/CommonWallet/Source/PKHUDView.swift b/CommonWallet/ViewTools/PKHUDView.swift similarity index 100% rename from CommonWallet/Source/PKHUDView.swift rename to CommonWallet/ViewTools/PKHUDView.swift diff --git a/CommonWallet/Source/WebView/WebView.swift b/CommonWallet/ViewTools/WebView/WebView.swift similarity index 100% rename from CommonWallet/Source/WebView/WebView.swift rename to CommonWallet/ViewTools/WebView/WebView.swift diff --git a/CommonWallet/Source/WebView/WebViewController.swift b/CommonWallet/ViewTools/WebView/WebViewController.swift similarity index 100% rename from CommonWallet/Source/WebView/WebViewController.swift rename to CommonWallet/ViewTools/WebView/WebViewController.swift diff --git a/CommonWallet/Source/WebView/WebViewController.xib b/CommonWallet/ViewTools/WebView/WebViewController.xib similarity index 100% rename from CommonWallet/Source/WebView/WebViewController.xib rename to CommonWallet/ViewTools/WebView/WebViewController.xib