diff --git a/DDooing/DDooing.xcodeproj/project.pbxproj b/DDooing/DDooing.xcodeproj/project.pbxproj index b13e2a7..976f3ab 100644 --- a/DDooing/DDooing.xcodeproj/project.pbxproj +++ b/DDooing/DDooing.xcodeproj/project.pbxproj @@ -45,6 +45,27 @@ 4F3F81422BFE10AE008C920C /* HomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FF515932BF33F810056531C /* HomeView.swift */; }; 4F3F81542BFE63CA008C920C /* AppModelContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F3F81532BFE63CA008C920C /* AppModelContainer.swift */; }; 4F3F81552BFE63CA008C920C /* AppModelContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F3F81532BFE63CA008C920C /* AppModelContainer.swift */; }; + 4F6D48982C00BDF9008B2A7F /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FF293F22BFA2779004BDDB3 /* ContentView.swift */; }; + 4F6D489A2C00BEE4008B2A7F /* AppViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FF293F42BFA27AF004BDDB3 /* AppViewModel.swift */; }; + 4F6D489B2C00BEEB008B2A7F /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FF5158B2BF33EAB0056531C /* LoginView.swift */; }; + 4F6D489C2C00BEF9008B2A7F /* RandomCodeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FF5158F2BF33F430056531C /* RandomCodeView.swift */; }; + 4F6D489D2C00BEFC008B2A7F /* PartnerNameView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FF515912BF33F680056531C /* PartnerNameView.swift */; }; + 4F6D489E2C00BF09008B2A7F /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FAD25B12BF3339A00EBD37A /* MainView.swift */; }; + 4F6D489F2C00BF1A008B2A7F /* TextEditView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FF515952BF33FB40056531C /* TextEditView.swift */; }; + 4F6D48A02C00BF1D008B2A7F /* ShowMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FF515972BF33FD70056531C /* ShowMessageView.swift */; }; + 4F6D48A12C00BF50008B2A7F /* FontManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F1A59582BF8894600C3EF2C /* FontManager.swift */; }; + 4F6D48A22C00BF54008B2A7F /* Pretendard-Black.otf in Resources */ = {isa = PBXBuildFile; fileRef = 4F1A593A2BF8892000C3EF2C /* Pretendard-Black.otf */; }; + 4F6D48A32C00BF57008B2A7F /* Pretendard-Bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 4F1A59382BF8892000C3EF2C /* Pretendard-Bold.otf */; }; + 4F6D48A42C00BF58008B2A7F /* Pretendard-ExtraBold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 4F1A59342BF8892000C3EF2C /* Pretendard-ExtraBold.otf */; }; + 4F6D48A52C00BF5A008B2A7F /* Pretendard-ExtraLight.otf in Resources */ = {isa = PBXBuildFile; fileRef = 4F1A59352BF8892000C3EF2C /* Pretendard-ExtraLight.otf */; }; + 4F6D48A62C00BF5D008B2A7F /* Pretendard-Light.otf in Resources */ = {isa = PBXBuildFile; fileRef = 4F1A59372BF8892000C3EF2C /* Pretendard-Light.otf */; }; + 4F6D48A72C00BF60008B2A7F /* Pretendard-Medium.otf in Resources */ = {isa = PBXBuildFile; fileRef = 4F1A593B2BF8892000C3EF2C /* Pretendard-Medium.otf */; }; + 4F6D48A82C00BF62008B2A7F /* Pretendard-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 4F1A59362BF8892000C3EF2C /* Pretendard-Regular.otf */; }; + 4F6D48A92C00BF65008B2A7F /* Pretendard-SemiBold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 4F1A593C2BF8892000C3EF2C /* Pretendard-SemiBold.otf */; }; + 4F6D48AA2C00BF67008B2A7F /* Pretendard-Thin.otf in Resources */ = {isa = PBXBuildFile; fileRef = 4F1A59392BF8892000C3EF2C /* Pretendard-Thin.otf */; }; + 4F6D48AB2C00BF88008B2A7F /* UserStatusViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FF293E82BF8EF33004BDDB3 /* UserStatusViewModel.swift */; }; + 4F6D48AC2C00BF8A008B2A7F /* LoginViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FD812D82BF87BA800F16ED0 /* LoginViewModel.swift */; }; + 4F6D48AD2C00BF8D008B2A7F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4FAD25B32BF3339B00EBD37A /* Assets.xcassets */; }; 4F8D878D2BFF864F006BEF4A /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 4F8D878C2BFF84DF006BEF4A /* GoogleService-Info.plist */; }; 4F8D878E2BFF8650006BEF4A /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 4F8D878C2BFF84DF006BEF4A /* GoogleService-Info.plist */; }; 4FAD25B02BF3339A00EBD37A /* DDooingApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FAD25AF2BF3339A00EBD37A /* DDooingApp.swift */; }; @@ -616,7 +637,17 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 4F6D48A52C00BF5A008B2A7F /* Pretendard-ExtraLight.otf in Resources */, 4F3F813F2BFDDEDC008C920C /* Assets.xcassets in Resources */, + 4F6D48A32C00BF57008B2A7F /* Pretendard-Bold.otf in Resources */, + 4F6D48A72C00BF60008B2A7F /* Pretendard-Medium.otf in Resources */, + 4F6D48A82C00BF62008B2A7F /* Pretendard-Regular.otf in Resources */, + 4F6D48A42C00BF58008B2A7F /* Pretendard-ExtraBold.otf in Resources */, + 4F6D48A62C00BF5D008B2A7F /* Pretendard-Light.otf in Resources */, + 4F6D48A92C00BF65008B2A7F /* Pretendard-SemiBold.otf in Resources */, + 4F6D48A22C00BF54008B2A7F /* Pretendard-Black.otf in Resources */, + 4F6D48AA2C00BF67008B2A7F /* Pretendard-Thin.otf in Resources */, + 4F6D48AD2C00BF8D008B2A7F /* Assets.xcassets in Resources */, 4F8D878E2BFF8650006BEF4A /* GoogleService-Info.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -671,14 +702,25 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 4F6D489A2C00BEE4008B2A7F /* AppViewModel.swift in Sources */, + 4F6D48A12C00BF50008B2A7F /* FontManager.swift in Sources */, + 4F6D48A02C00BF1D008B2A7F /* ShowMessageView.swift in Sources */, + 4F6D489E2C00BF09008B2A7F /* MainView.swift in Sources */, 4FBE64BA2BFDC940008363A0 /* DDooingWidgetBundle.swift in Sources */, + 4F6D489C2C00BEF9008B2A7F /* RandomCodeView.swift in Sources */, 4F3F81412BFE0F7B008C920C /* MessageModel.swift in Sources */, 4FBE64C02BFDC940008363A0 /* AppIntent.swift in Sources */, 4FBE64BE2BFDC940008363A0 /* DDooingWidget.swift in Sources */, 4F3F81422BFE10AE008C920C /* HomeView.swift in Sources */, + 4F6D48982C00BDF9008B2A7F /* ContentView.swift in Sources */, 4FBE64BC2BFDC940008363A0 /* DDooingWidgetLiveActivity.swift in Sources */, + 4F6D489B2C00BEEB008B2A7F /* LoginView.swift in Sources */, 4F3F81402BFDE116008C920C /* WidgetColor.swift in Sources */, 4F3F81552BFE63CA008C920C /* AppModelContainer.swift in Sources */, + 4F6D48AB2C00BF88008B2A7F /* UserStatusViewModel.swift in Sources */, + 4F6D489D2C00BEFC008B2A7F /* PartnerNameView.swift in Sources */, + 4F6D48AC2C00BF8A008B2A7F /* LoginViewModel.swift in Sources */, + 4F6D489F2C00BF1A008B2A7F /* TextEditView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/DDooing/DDooing/Views/Auth/LoginView.swift b/DDooing/DDooing/Views/Auth/LoginView.swift index ad55dd5..256191c 100644 --- a/DDooing/DDooing/Views/Auth/LoginView.swift +++ b/DDooing/DDooing/Views/Auth/LoginView.swift @@ -45,17 +45,17 @@ struct LoginView: View { } .signInWithAppleButtonStyle(.black) .frame(width: 345, height: 54) - - NavigationLink( - destination: RandomCodeView(), - isActive: $loginData.isAuthenticated, //여기서 사용자 로그인이 잘 됐으면 화면 전환 - label: { - EmptyView() - }) } .padding(.horizontal, 16) .padding(.top,165) Spacer() + + NavigationLink( + destination: RandomCodeView(), + isActive: $loginData.isAuthenticated, //여기서 사용자 로그인이 잘 됐으면 화면 전환 + label: { + EmptyView() + }) } } } diff --git a/DDooing/DDooing/Views/Auth/RandomCodeView.swift b/DDooing/DDooing/Views/Auth/RandomCodeView.swift index 683abdd..f4dbe88 100644 --- a/DDooing/DDooing/Views/Auth/RandomCodeView.swift +++ b/DDooing/DDooing/Views/Auth/RandomCodeView.swift @@ -45,7 +45,7 @@ struct RandomCodeView: View { } else{ TextField("Code", text: $code) - .keyboardType(.namePhonePad).autocapitalization(.none) + .keyboardType(.asciiCapable) .font(.pretendardBold32) .padding(.leading, 32) .padding(.trailing, 32) diff --git a/DDooing/DDooing/Views/ContentView.swift b/DDooing/DDooing/Views/ContentView.swift index cd63d12..9d83b31 100644 --- a/DDooing/DDooing/Views/ContentView.swift +++ b/DDooing/DDooing/Views/ContentView.swift @@ -6,6 +6,9 @@ // import SwiftUI +import Firebase +import AppIntents +import WidgetKit struct ContentView: View { @EnvironmentObject var viewModel: AppViewModel @@ -25,3 +28,85 @@ struct ContentView: View { #Preview { ContentView() } + +class MessagingService { + static var partnerUID: String = "" + static var currentUserUID: String = "" + static var randomMessages: String = "" + + static func sendMessage(partnerUID : String, currentUserUID: String, messageText: String, isStarred: Bool) { + let db = Firestore.firestore() + print("db init") + +// let currentUid = "fXnIoNjeH9VbF8cFkMGRkjgv4GQ2" //여기가 문제 +// guard let currentUid = Auth.auth().currentUser?.uid else { return } + print(currentUserUID) + + + let currentUserRef = db.collection("Received-Messages") + .document(currentUserUID).collection(partnerUID).document() + + let partnerRef = db.collection("Received-Messages") + .document(partnerUID).collection(currentUserUID) + + let recentPartnerRef = db.collection("Received-Messages") + .document(partnerUID).collection("recent-messages") + .document(currentUserUID) + + let messageId = currentUserRef.documentID + + let messageData: [String: Any] = [ + "fromId": currentUserUID, + "toId": partnerUID, + "messageText": messageText, + "timeStamp": Timestamp(date: Date()), + "isStarred": isStarred, + "messageId": messageId + ] + + // 메시지 데이터를 Firestore에 저장 + partnerRef.document(messageId).setData(messageData) + recentPartnerRef.setData(messageData) + } +} + +// Intent에서 사용 +struct SendMessageIntent: AppIntent { + + static var title: LocalizedStringResource = .init(stringLiteral: "DDooing Send Message") + + @Parameter(title : "Random Message") + var randomMessage : String + + @Parameter(title : "PartnerUID") + var partnerUID : String + + @Parameter(title : "CurrentUserUID") + var currentUserUID : String + + init(randomMessage: String, partnerUID: String, currentUserUID: String) { + self.randomMessage = randomMessage + self.partnerUID = partnerUID + self.currentUserUID = currentUserUID + } + + init() { + //empty + } + + func perform() async throws -> some IntentResult { + print("앱이 꺼져있어도 실행이 됩니다.") + + // 랜덤 메시지 설정 + MessagingService.randomMessages = randomMessage + MessagingService.partnerUID = partnerUID + MessagingService.currentUserUID = currentUserUID + // 메시지 보내기 + MessagingService.sendMessage(partnerUID : MessagingService.partnerUID, currentUserUID: MessagingService.currentUserUID, messageText: MessagingService.randomMessages, isStarred: false) + +// print(MessagingService.randomMessages) +// print(MessagingService.partnerUID) + + return .result() + } +} diff --git a/DDooing/DDooing/Views/MainView.swift b/DDooing/DDooing/Views/MainView.swift index 1d18337..dab901e 100644 --- a/DDooing/DDooing/Views/MainView.swift +++ b/DDooing/DDooing/Views/MainView.swift @@ -50,6 +50,13 @@ struct MainView: View { let filteredDocuments = querySnapshot?.documents.filter { $0.documentID != currentUserUID } if let partnerDocument = filteredDocuments?.first { self.partnerUID = partnerDocument.documentID + let defaults = UserDefaults(suiteName: "group.com.Seodongwon.DDooing")! + + defaults.set(partnerUID,forKey: "partnerUID") + defaults.set(currentUserUID,forKey: "currentUserUID") + + print(defaults.string(forKey: "partnerUID")) + print(defaults.string(forKey: "currentUserUID")) } print("파트너 uid : \(String(describing: partnerUID))") } diff --git a/DDooing/DDooingWidget/DDooingWidget.swift b/DDooing/DDooingWidget/DDooingWidget.swift index 32586a5..65530c8 100644 --- a/DDooing/DDooingWidget/DDooingWidget.swift +++ b/DDooing/DDooingWidget/DDooingWidget.swift @@ -16,7 +16,7 @@ struct Provider : TimelineProvider { // 본격적으로 위젯에 표시될 placeholder // 데이터를 불러오기 전(getSnapshot)에 보여줄 placeholder @MainActor func placeholder(in context: Context) -> SimpleEntry { - SimpleEntry(date: Date(), message: getMessage()) + SimpleEntry(date: Date(), message: getMessage(), partnerUID: getPartnerUID(), currentUserUID: getCurrentUserUID()) } // 데이터를 가져와서 표출해주는 getSnapshot @@ -24,7 +24,7 @@ struct Provider : TimelineProvider { // API를 통해서 데이터를 fetch하여 보여줄때 딜레이가 있는 경우 여기서 샘플 데이터를 하드코딩해서 보여주는 작업도 가능 // context.isPreview가 true인 경우 위젯 갤러리에 위젯이 표출되는 상태 @MainActor func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> Void) { - let entry = SimpleEntry(date: Date(), message: getMessage()) + let entry = SimpleEntry(date: Date(), message: getMessage(), partnerUID: getPartnerUID(), currentUserUID: getCurrentUserUID()) completion(entry) } @@ -33,12 +33,13 @@ struct Provider : TimelineProvider { // 홈화면에 있는 위젯을 언제 업데이트 시킬것인지 구현하는 부분 @MainActor func getTimeline(in context: Context, completion: @escaping (Timeline) -> ()) { var entries: [SimpleEntry] = [] - let entry = SimpleEntry(date: .now, message: getMessage()) + let entry = SimpleEntry(date: .now, message: getMessage(), partnerUID: getPartnerUID(), currentUserUID: getCurrentUserUID()) entries.append(entry) // .atEnd: 마지막 date가 끝난 후 타임라인 reloading // .after: 다음 data가 지난 후 타임라인 reloading // .never: 즉시 타임라인 reloading let timeline = Timeline(entries: entries, policy: .after(.now.advanced(by: 60 * 5))) +// let timeline = Timeline(entries: entries, policy: .atEnd) completion(timeline) } @@ -59,13 +60,37 @@ struct Provider : TimelineProvider { } + @MainActor + private func getPartnerUID() -> String { + let defaults = UserDefaults(suiteName: "group.com.Seodongwon.DDooing") + guard let partnerUID = defaults?.string(forKey: "partnerUID") else { + return "" + } + + return partnerUID + + } + + @MainActor + private func getCurrentUserUID() -> String { + let defaults = UserDefaults(suiteName: "group.com.Seodongwon.DDooing") + guard let currentUserUID = defaults?.string(forKey: "currentUserUID") else { + return "" + } + + return currentUserUID + + } + } // TimelineEntry를 준수하는 구조체 // 위젯을 표시할 Date를 정하고, 그 Date에 표시할 데이터를 나타냄 struct SimpleEntry: TimelineEntry { let date: Date - let message : String + let message: String + let partnerUID: String + let currentUserUID: String } struct DDooingWidget: Widget { @@ -99,7 +124,7 @@ struct DDooingWidgetEntryView : View { switch widgetFamily { case .systemSmall: VStack { - Button(intent: SendMessageIntent(randomMessage: entry.message)){ + Button(intent: SendMessageIntent(randomMessage: entry.message, partnerUID: entry.partnerUID, currentUserUID: entry.currentUserUID)){ Image("WidgetButton") .resizable() .frame(width: 130,height: 118) @@ -109,7 +134,7 @@ struct DDooingWidgetEntryView : View { .containerBackground((LinearGradient(gradient: Gradient(colors: [Color.widgetTopColor, Color.widgetBottomColor]), startPoint: .top, endPoint: .bottom)), for: .widget) case .systemLarge: VStack { - Button(intent: SendMessageIntent(randomMessage: entry.message)){ + Button(intent: SendMessageIntent(randomMessage: entry.message, partnerUID: entry.partnerUID, currentUserUID: entry.currentUserUID)){ Image("WidgetButton") .resizable() .frame(width: 260,height: 236) @@ -119,7 +144,7 @@ struct DDooingWidgetEntryView : View { .containerBackground((LinearGradient(gradient: Gradient(colors: [Color.widgetTopColor, Color.widgetBottomColor]), startPoint: .top, endPoint: .bottom)), for: .widget) default: VStack { - Button(intent: SendMessageIntent(randomMessage: entry.message)){ + Button(intent: SendMessageIntent(randomMessage: entry.message, partnerUID: entry.partnerUID, currentUserUID: entry.currentUserUID)){ Image("WidgetButton") .resizable() .frame(width: 130,height: 118) @@ -131,111 +156,3 @@ struct DDooingWidgetEntryView : View { } } - -class MessagingService { - - var partnerUID: String? = nil - var randomMessages: String = "" - - init(partnerUID: String?) { - self.partnerUID = partnerUID - } - - - // 비동기적으로 partnerUID를 가져오는 메소드 - func fetchPartnerUIDAsync() async throws -> String { - guard let currentUser = Auth.auth().currentUser else { throw NSError() } - let currentUserUID = currentUser.uid - - let db = Firestore.firestore() - - let document = try await db.collection("Users").document(currentUserUID).getDocument() - if document.exists { - if let code = document.data()?["code"] as? String { - let querySnapshot = try await db.collection("Users").whereField("code", isEqualTo: code).getDocuments() - let filteredDocuments = querySnapshot.documents.filter { $0.documentID != currentUserUID } - if let partnerDocument = filteredDocuments.first { - self.partnerUID = partnerDocument.documentID - return partnerDocument.documentID - } - } - } - throw NSError() - } - - - func saveRandomMessage() { - guard let partnerUID = partnerUID else { return } - sendMessage(messageText: randomMessages, isStarred: false) - } - - func sendMessage(messageText: String, isStarred: Bool) { - let db = Firestore.firestore() - - guard let currentUid = Auth.auth().currentUser?.uid else { return } - - let currentUserRef = db.collection("Received-Messages") - .document(currentUid).collection(partnerUID ?? "").document() - - let partnerRef = db.collection("Received-Messages") - .document(partnerUID ?? "").collection(currentUid) - - let recentPartnerRef = db.collection("Received-Messages") - .document(partnerUID ?? "").collection("recent-messages") - .document(currentUid) - - let messageId = currentUserRef.documentID - - let messageData: [String: Any] = [ - "fromId": currentUid, - "toId": partnerUID ?? "", - "messageText": messageText, - "timeStamp": Timestamp(date: Date()), - "isStarred": isStarred, - "messageId": messageId - ] - - // 메시지 데이터를 Firestore에 저장 - partnerRef.document(messageId).setData(messageData) - recentPartnerRef.setData(messageData) - } -} - -// Intent에서 사용 -struct SendMessageIntent: AppIntent { - - static var title: LocalizedStringResource = .init(stringLiteral: "DDooing Send Message") - - @Parameter(title : "Random Message") - var randomMessage : String - - init(randomMessage: String) { - self.randomMessage = randomMessage - } - - init() { - //empty - } - - func perform() async throws -> some IntentResult { - - // MessagingService의 인스턴스 생성 - let messagingService = MessagingService(partnerUID: nil) - - // 비동기적으로 partnerUID를 설정 - do { - _ = try await messagingService.fetchPartnerUIDAsync() - - // 랜덤 메시지 설정 - messagingService.randomMessages = randomMessage - // 메시지 보내기 - messagingService.sendMessage(messageText: messagingService.randomMessages, isStarred: false) - - } catch { - // 오류 처리 - print("Partner UID를 가져오는 데 실패했습니다.") - } - - return .result() - } -}