diff --git a/Smeem-iOS/Smeem-iOS.xcodeproj/project.pbxproj b/Smeem-iOS/Smeem-iOS.xcodeproj/project.pbxproj index 472cf9f6..c9863adb 100644 --- a/Smeem-iOS/Smeem-iOS.xcodeproj/project.pbxproj +++ b/Smeem-iOS/Smeem-iOS.xcodeproj/project.pbxproj @@ -8,6 +8,15 @@ /* Begin PBXBuildFile section */ 37035CF92AF2ADD2008EE521 /* DiaryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37035CF82AF2ADD2008EE521 /* DiaryViewModel.swift */; }; + 370BD0AD2CFB65BE009560DB /* DatePickerFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 370BD0A52CFB65BE009560DB /* DatePickerFooterView.swift */; }; + 370BD0AE2CFB65BE009560DB /* AlarmCollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 370BD0A22CFB65BE009560DB /* AlarmCollectionView.swift */; }; + 370BD0AF2CFB65BE009560DB /* SeparationLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 370BD0AB2CFB65BE009560DB /* SeparationLine.swift */; }; + 370BD0B02CFB65BE009560DB /* DiaryBottomView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 370BD0A72CFB65BE009560DB /* DiaryBottomView.swift */; }; + 370BD0B12CFB65BE009560DB /* DiaryDetailRandomSubjectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 370BD0A82CFB65BE009560DB /* DiaryDetailRandomSubjectView.swift */; }; + 370BD0B22CFB65BE009560DB /* DiaryScrollerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 370BD0A92CFB65BE009560DB /* DiaryScrollerView.swift */; }; + 370BD0B32CFB65BE009560DB /* RandomTopicView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 370BD0AA2CFB65BE009560DB /* RandomTopicView.swift */; }; + 370BD0B42CFB65BE009560DB /* AlarmCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 370BD0A32CFB65BE009560DB /* AlarmCollectionViewCell.swift */; }; + 370BD0B52CFB65BE009560DB /* AlarmDefaultModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 370BD0A42CFB65BE009560DB /* AlarmDefaultModel.swift */; }; 371107DA2AC99099007A4AC2 /* KeyboardFollowingLayoutHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371107D92AC99099007A4AC2 /* KeyboardFollowingLayoutHandler.swift */; }; 371107DD2ACAB571007A4AC2 /* BaseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371107DC2ACAB571007A4AC2 /* BaseView.swift */; }; 371107DF2ACAB709007A4AC2 /* BaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371107DE2ACAB709007A4AC2 /* BaseViewController.swift */; }; @@ -23,15 +32,14 @@ 3728B8D52A2CFF2C00EF4CF8 /* StepOneKoreanDiaryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3728B8D42A2CFF2C00EF4CF8 /* StepOneKoreanDiaryViewController.swift */; }; 3728B8D72A2CFF3A00EF4CF8 /* StepTwoKoreanDiaryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3728B8D62A2CFF3A00EF4CF8 /* StepTwoKoreanDiaryViewController.swift */; }; 373D29932CBFE17B00A559A3 /* View+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 373D29922CBFE17B00A559A3 /* View+.swift */; }; - 373E38592A2F889500DF96F0 /* DiaryDetailRandomSubjectView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 373E38582A2F889500DF96F0 /* DiaryDetailRandomSubjectView.swift */; }; 374F828C2AC327A200C128B9 /* SmeemTextViewHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374F828B2AC327A200C128B9 /* SmeemTextViewHandler.swift */; }; - 374F828E2AC5DFFE00C128B9 /* DiaryBottomView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374F828D2AC5DFFE00C128B9 /* DiaryBottomView.swift */; }; 374FAF812A2CACCF00237A1A /* DiaryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 374FAF802A2CACCF00237A1A /* DiaryViewController.swift */; }; 375B62872C590D0D00DA8E30 /* FirebaseAnalytics in Frameworks */ = {isa = PBXBuildFile; productRef = 375B62862C590D0D00DA8E30 /* FirebaseAnalytics */; }; 375B62892C590D0D00DA8E30 /* FirebaseCrashlytics in Frameworks */ = {isa = PBXBuildFile; productRef = 375B62882C590D0D00DA8E30 /* FirebaseCrashlytics */; }; 375B628B2C590D0D00DA8E30 /* FirebaseMessaging in Frameworks */ = {isa = PBXBuildFile; productRef = 375B628A2C590D0D00DA8E30 /* FirebaseMessaging */; }; 375B628D2C590D0D00DA8E30 /* FirebaseRemoteConfig in Frameworks */ = {isa = PBXBuildFile; productRef = 375B628C2C590D0D00DA8E30 /* FirebaseRemoteConfig */; }; 3761116C2A278D0E0095EC5A /* String+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3761116B2A278D0E0095EC5A /* String+.swift */; }; + 377B3BF02CF613710086E0BC /* HighlightModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 377B3BEF2CF613710086E0BC /* HighlightModifier.swift */; }; 3785072F2BD1480C004CC922 /* SharedDiaryDataService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37499E3C2BD0C3A100BA6FAF /* SharedDiaryDataService.swift */; }; 378B20EE2BA0A01600604935 /* ForeignDiaryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 378B20ED2BA0A01600604935 /* ForeignDiaryViewModel.swift */; }; 378B20F02BA0A02400604935 /* StepOneKoreanDiaryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 378B20EF2BA0A02400604935 /* StepOneKoreanDiaryViewModel.swift */; }; @@ -56,8 +64,7 @@ 37A574DA29FF9FFF00312453 /* Pretendard-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 37A574D629FF9FFF00312453 /* Pretendard-Regular.otf */; }; 37A574DB29FF9FFF00312453 /* Pretendard-Medium.otf in Resources */ = {isa = PBXBuildFile; fileRef = 37A574D729FF9FFF00312453 /* Pretendard-Medium.otf */; }; 37A574DC29FF9FFF00312453 /* Pretendard-Bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 37A574D829FF9FFF00312453 /* Pretendard-Bold.otf */; }; - 37A574E02A00CDCD00312453 /* SeparationLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37A574DF2A00CDCD00312453 /* SeparationLine.swift */; }; - 37A574E82A02424F00312453 /* RandomTopicView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37A574E72A02424F00312453 /* RandomTopicView.swift */; }; + 37B123B62CEEE58E00ED973A /* DetailDiaryCoachedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37B123B52CEEE58E00ED973A /* DetailDiaryCoachedView.swift */; }; 37BCADF22BC3FFBF006EF960 /* DetailDiaryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BCADF12BC3FFBF006EF960 /* DetailDiaryViewModel.swift */; }; 37BDC9872C4FEA940075F68A /* SendFeedbackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37BDC9862C4FEA940075F68A /* SendFeedbackView.swift */; }; 37DCA6572A47574300FF8F90 /* RandomTopicAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37DCA6562A47574300FF8F90 /* RandomTopicAPI.swift */; }; @@ -96,9 +103,6 @@ 4A3373F52A45BF6600EFE6C4 /* OnboardingEndPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A3373F42A45BF6600EFE6C4 /* OnboardingEndPoint.swift */; }; 4A3373F82A461ABC00EFE6C4 /* OnboardingService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A3373F72A461ABC00EFE6C4 /* OnboardingService.swift */; }; 4A3774842A42E6EA00357DD1 /* ConfigConstant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A3774832A42E6EA00357DD1 /* ConfigConstant.swift */; }; - 4A3F2E972A0ABBAA00F6AC60 /* AlarmCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A3F2E962A0ABBAA00F6AC60 /* AlarmCollectionViewCell.swift */; }; - 4A3F2E9C2A0B4C7100F6AC60 /* AlarmCollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A3F2E9B2A0B4C7100F6AC60 /* AlarmCollectionView.swift */; }; - 4A3F2EA02A0C18B600F6AC60 /* DatePickerFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A3F2E9F2A0C18B600F6AC60 /* DatePickerFooterView.swift */; }; 4A454A832B6666FF0079D48D /* TrainingGoalViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A454A822B6666FF0079D48D /* TrainingGoalViewModel.swift */; }; 4A454A852B6667180079D48D /* ViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A454A842B6667180079D48D /* ViewModel.swift */; }; 4A4FEB012B721956001BBDF3 /* Combine+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A4FEB002B721956001BBDF3 /* Combine+.swift */; }; @@ -187,12 +191,10 @@ 4AC705AE2BECF0D4003C5310 /* EditPlanViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AC705AD2BECF0D4003C5310 /* EditPlanViewModel.swift */; }; 4AC707A82B73893200B1D791 /* AlarmTimeAppData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AC707A72B73893200B1D791 /* AlarmTimeAppData.swift */; }; 4AC707AB2B738A5B00B1D791 /* TrainingAlarmViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AC707AA2B738A5B00B1D791 /* TrainingAlarmViewModel.swift */; }; - 4AC707B02B73CFFA00B1D791 /* AlarmDefaultModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AC707AF2B73CFFA00B1D791 /* AlarmDefaultModel.swift */; }; 4AC707B42B73D2D400B1D791 /* UserNicknameViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AC707B32B73D2D400B1D791 /* UserNicknameViewModel.swift */; }; 4AC707B92B74D5CD00B1D791 /* ServiceAcceptViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AC707B82B74D5CD00B1D791 /* ServiceAcceptViewModel.swift */; }; 4AC707BB2B74DE3E00B1D791 /* ServiceAcceptCollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AC707BA2B74DE3E00B1D791 /* ServiceAcceptCollectionView.swift */; }; 4AC9489829ED800800489C2B /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 4AC9489729ED800800489C2B /* GoogleService-Info.plist */; }; - 4AD04B3B2A1905BB004B7A58 /* DiaryScrollerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AD04B3A2A1905BB004B7A58 /* DiaryScrollerView.swift */; }; 4AD04B3D2A190E9A004B7A58 /* UITextView+.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AD04B3C2A190E9A004B7A58 /* UITextView+.swift */; }; 4AD04B402A1921AE004B7A58 /* CorrectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AD04B3F2A1921AE004B7A58 /* CorrectionViewController.swift */; }; 4ADA41772A556209001C0285 /* LoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4ADA41762A556209001C0285 /* LoadingView.swift */; }; @@ -233,6 +235,15 @@ /* Begin PBXFileReference section */ 37035CF82AF2ADD2008EE521 /* DiaryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryViewModel.swift; sourceTree = ""; }; + 370BD0A22CFB65BE009560DB /* AlarmCollectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlarmCollectionView.swift; sourceTree = ""; }; + 370BD0A32CFB65BE009560DB /* AlarmCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlarmCollectionViewCell.swift; sourceTree = ""; }; + 370BD0A42CFB65BE009560DB /* AlarmDefaultModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlarmDefaultModel.swift; sourceTree = ""; }; + 370BD0A52CFB65BE009560DB /* DatePickerFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatePickerFooterView.swift; sourceTree = ""; }; + 370BD0A72CFB65BE009560DB /* DiaryBottomView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryBottomView.swift; sourceTree = ""; }; + 370BD0A82CFB65BE009560DB /* DiaryDetailRandomSubjectView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryDetailRandomSubjectView.swift; sourceTree = ""; }; + 370BD0A92CFB65BE009560DB /* DiaryScrollerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryScrollerView.swift; sourceTree = ""; }; + 370BD0AA2CFB65BE009560DB /* RandomTopicView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RandomTopicView.swift; sourceTree = ""; }; + 370BD0AB2CFB65BE009560DB /* SeparationLine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparationLine.swift; sourceTree = ""; }; 371107D92AC99099007A4AC2 /* KeyboardFollowingLayoutHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardFollowingLayoutHandler.swift; sourceTree = ""; }; 371107DC2ACAB571007A4AC2 /* BaseView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseView.swift; sourceTree = ""; }; 371107DE2ACAB709007A4AC2 /* BaseViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseViewController.swift; sourceTree = ""; }; @@ -248,12 +259,11 @@ 3728B8D42A2CFF2C00EF4CF8 /* StepOneKoreanDiaryViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StepOneKoreanDiaryViewController.swift; sourceTree = ""; }; 3728B8D62A2CFF3A00EF4CF8 /* StepTwoKoreanDiaryViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StepTwoKoreanDiaryViewController.swift; sourceTree = ""; }; 373D29922CBFE17B00A559A3 /* View+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+.swift"; sourceTree = ""; }; - 373E38582A2F889500DF96F0 /* DiaryDetailRandomSubjectView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryDetailRandomSubjectView.swift; sourceTree = ""; }; 37499E3C2BD0C3A100BA6FAF /* SharedDiaryDataService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharedDiaryDataService.swift; sourceTree = ""; }; 374F828B2AC327A200C128B9 /* SmeemTextViewHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SmeemTextViewHandler.swift; sourceTree = ""; }; - 374F828D2AC5DFFE00C128B9 /* DiaryBottomView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryBottomView.swift; sourceTree = ""; }; 374FAF802A2CACCF00237A1A /* DiaryViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryViewController.swift; sourceTree = ""; }; 3761116B2A278D0E0095EC5A /* String+.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+.swift"; sourceTree = ""; }; + 377B3BEF2CF613710086E0BC /* HighlightModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HighlightModifier.swift; sourceTree = ""; }; 378B20ED2BA0A01600604935 /* ForeignDiaryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForeignDiaryViewModel.swift; sourceTree = ""; }; 378B20EF2BA0A02400604935 /* StepOneKoreanDiaryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StepOneKoreanDiaryViewModel.swift; sourceTree = ""; }; 378B20F12BA0A03000604935 /* StepTwoKoreanDiaryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StepTwoKoreanDiaryViewModel.swift; sourceTree = ""; }; @@ -277,8 +287,7 @@ 37A574D629FF9FFF00312453 /* Pretendard-Regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-Regular.otf"; sourceTree = ""; }; 37A574D729FF9FFF00312453 /* Pretendard-Medium.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-Medium.otf"; sourceTree = ""; }; 37A574D829FF9FFF00312453 /* Pretendard-Bold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-Bold.otf"; sourceTree = ""; }; - 37A574DF2A00CDCD00312453 /* SeparationLine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparationLine.swift; sourceTree = ""; }; - 37A574E72A02424F00312453 /* RandomTopicView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RandomTopicView.swift; sourceTree = ""; }; + 37B123B52CEEE58E00ED973A /* DetailDiaryCoachedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailDiaryCoachedView.swift; sourceTree = ""; }; 37BCADF12BC3FFBF006EF960 /* DetailDiaryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailDiaryViewModel.swift; sourceTree = ""; }; 37BDC9862C4FEA940075F68A /* SendFeedbackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendFeedbackView.swift; sourceTree = ""; }; 37DCA6562A47574300FF8F90 /* RandomTopicAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RandomTopicAPI.swift; sourceTree = ""; }; @@ -320,9 +329,6 @@ 4A3373F42A45BF6600EFE6C4 /* OnboardingEndPoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingEndPoint.swift; sourceTree = ""; }; 4A3373F72A461ABC00EFE6C4 /* OnboardingService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingService.swift; sourceTree = ""; }; 4A3774832A42E6EA00357DD1 /* ConfigConstant.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigConstant.swift; sourceTree = ""; }; - 4A3F2E962A0ABBAA00F6AC60 /* AlarmCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlarmCollectionViewCell.swift; sourceTree = ""; }; - 4A3F2E9B2A0B4C7100F6AC60 /* AlarmCollectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlarmCollectionView.swift; sourceTree = ""; }; - 4A3F2E9F2A0C18B600F6AC60 /* DatePickerFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatePickerFooterView.swift; sourceTree = ""; }; 4A454A822B6666FF0079D48D /* TrainingGoalViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrainingGoalViewModel.swift; sourceTree = ""; }; 4A454A842B6667180079D48D /* ViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewModel.swift; sourceTree = ""; }; 4A4E21EE29D9B02500BF8747 /* Smeem-iOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Smeem-iOS.entitlements"; sourceTree = ""; }; @@ -411,13 +417,11 @@ 4AC705AD2BECF0D4003C5310 /* EditPlanViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditPlanViewModel.swift; sourceTree = ""; }; 4AC707A72B73893200B1D791 /* AlarmTimeAppData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlarmTimeAppData.swift; sourceTree = ""; }; 4AC707AA2B738A5B00B1D791 /* TrainingAlarmViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrainingAlarmViewModel.swift; sourceTree = ""; }; - 4AC707AF2B73CFFA00B1D791 /* AlarmDefaultModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlarmDefaultModel.swift; sourceTree = ""; }; 4AC707B32B73D2D400B1D791 /* UserNicknameViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserNicknameViewModel.swift; sourceTree = ""; }; 4AC707B82B74D5CD00B1D791 /* ServiceAcceptViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServiceAcceptViewModel.swift; sourceTree = ""; }; 4AC707BA2B74DE3E00B1D791 /* ServiceAcceptCollectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServiceAcceptCollectionView.swift; sourceTree = ""; }; 4AC9489729ED800800489C2B /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; 4AD04B382A190020004B7A58 /* UITextField+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITextField+.swift"; sourceTree = ""; }; - 4AD04B3A2A1905BB004B7A58 /* DiaryScrollerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryScrollerView.swift; sourceTree = ""; }; 4AD04B3C2A190E9A004B7A58 /* UITextView+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITextView+.swift"; sourceTree = ""; }; 4AD04B3F2A1921AE004B7A58 /* CorrectionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CorrectionViewController.swift; sourceTree = ""; }; 4AD923E62A0650B600FF5E27 /* SmeemStartViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SmeemStartViewController.swift; sourceTree = ""; }; @@ -442,8 +446,23 @@ A3D7ECB62A26566A009857D6 /* EditNicknameViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditNicknameViewController.swift; sourceTree = ""; }; /* End PBXFileReference section */ +/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ + 370BD0B62CFB660C009560DB /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + CoachingComparisonView.swift, + CoachingCompletedView.swift, + CoachingExplanationView.swift, + CustomSegmentedControl.swift, + SwiftUINavigationView.swift, + ); + target = 4A8FFA4B29C9E1FD00FB76C0 /* Smeem-iOS */; + }; +/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ + /* Begin PBXFileSystemSynchronizedRootGroup section */ - 4AB3494D2CF229D10047C484 /* UIViewConponent */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = UIViewConponent; sourceTree = ""; }; + 377B3BF12CF618B90086E0BC /* SwiftUI */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = SwiftUI; sourceTree = ""; }; + 4AB3494D2CF229D10047C484 /* UIViewConponent */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (370BD0B62CFB660C009560DB /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = UIViewConponent; sourceTree = ""; }; 4AB3494E2CF22A070047C484 /* Global */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = Global; sourceTree = ""; }; 4AB3494F2CF22A250047C484 /* Button */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = Button; sourceTree = ""; }; 4AB349502CF22A2E0047C484 /* TextView */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = TextView; sourceTree = ""; }; @@ -489,6 +508,29 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 370BD0A62CFB65BE009560DB /* Alarm */ = { + isa = PBXGroup; + children = ( + 370BD0A22CFB65BE009560DB /* AlarmCollectionView.swift */, + 370BD0A32CFB65BE009560DB /* AlarmCollectionViewCell.swift */, + 370BD0A42CFB65BE009560DB /* AlarmDefaultModel.swift */, + 370BD0A52CFB65BE009560DB /* DatePickerFooterView.swift */, + ); + path = Alarm; + sourceTree = ""; + }; + 370BD0AC2CFB65BE009560DB /* Diary */ = { + isa = PBXGroup; + children = ( + 370BD0A72CFB65BE009560DB /* DiaryBottomView.swift */, + 370BD0A82CFB65BE009560DB /* DiaryDetailRandomSubjectView.swift */, + 370BD0A92CFB65BE009560DB /* DiaryScrollerView.swift */, + 370BD0AA2CFB65BE009560DB /* RandomTopicView.swift */, + 370BD0AB2CFB65BE009560DB /* SeparationLine.swift */, + ); + path = Diary; + sourceTree = ""; + }; 371107D82AC9905B007A4AC2 /* Utilities */ = { isa = PBXGroup; children = ( @@ -576,6 +618,7 @@ 37A574B929FE209F00312453 /* Resources */, 4AC4B82B2A2F9F5300E147AA /* Constants */, 37EB69E42A4B3B6B00075E4E /* Protocols */, + 377B3BEF2CF613710086E0BC /* HighlightModifier.swift */, ); path = Global; sourceTree = ""; @@ -630,6 +673,7 @@ 37A574B729FE208A00312453 /* UIComponents */ = { isa = PBXGroup; children = ( + 377B3BF12CF618B90086E0BC /* SwiftUI */, 4AB3494D2CF229D10047C484 /* UIViewConponent */, 371107DB2ACAB4E3007A4AC2 /* Base */, 4A1EE9552A4DFB86007BFEF3 /* SmeemComponent */, @@ -744,6 +788,7 @@ children = ( 37DCA65F2A48033400FF8F90 /* DetailDiaryViewController.swift */, 37BCADF12BC3FFBF006EF960 /* DetailDiaryViewModel.swift */, + 37B123B52CEEE58E00ED973A /* DetailDiaryCoachedView.swift */, ); path = DetailDiary; sourceTree = ""; @@ -970,28 +1015,16 @@ path = Nickname; sourceTree = ""; }; - 4A1EE9532A4DFB42007BFEF3 /* Diary */ = { - isa = PBXGroup; - children = ( - 4AD04B3A2A1905BB004B7A58 /* DiaryScrollerView.swift */, - 37A574E72A02424F00312453 /* RandomTopicView.swift */, - 373E38582A2F889500DF96F0 /* DiaryDetailRandomSubjectView.swift */, - 37A574DF2A00CDCD00312453 /* SeparationLine.swift */, - 374F828D2AC5DFFE00C128B9 /* DiaryBottomView.swift */, - ); - path = Diary; - sourceTree = ""; - }; 4A1EE9552A4DFB86007BFEF3 /* SmeemComponent */ = { isa = PBXGroup; children = ( 4AB349502CF22A2E0047C484 /* TextView */, 4AB3494F2CF22A250047C484 /* Button */, 4AB3494E2CF22A070047C484 /* Global */, - 4A3F2E952A0ABB9C00F6AC60 /* Alarm */, 379789012AAB9B1900C61EF4 /* NavigationBar */, - 4A1EE9532A4DFB42007BFEF3 /* Diary */, 4A81C2942ACDAAF80056E815 /* PlanGoal */, + 370BD0A62CFB65BE009560DB /* Alarm */, + 370BD0AC2CFB65BE009560DB /* Diary */, ); path = SmeemComponent; sourceTree = ""; @@ -1006,17 +1039,6 @@ path = Onboarding; sourceTree = ""; }; - 4A3F2E952A0ABB9C00F6AC60 /* Alarm */ = { - isa = PBXGroup; - children = ( - 4A3F2E9B2A0B4C7100F6AC60 /* AlarmCollectionView.swift */, - 4A3F2E962A0ABBAA00F6AC60 /* AlarmCollectionViewCell.swift */, - 4A3F2E9F2A0C18B600F6AC60 /* DatePickerFooterView.swift */, - 4AC707AF2B73CFFA00B1D791 /* AlarmDefaultModel.swift */, - ); - path = Alarm; - sourceTree = ""; - }; 4A4FEAF82B7105B4001BBDF3 /* ViewModel */ = { isa = PBXGroup; children = ( @@ -1729,6 +1751,7 @@ dependencies = ( ); fileSystemSynchronizedGroups = ( + 377B3BF12CF618B90086E0BC /* SwiftUI */, 4AB3494D2CF229D10047C484 /* UIViewConponent */, 4AB3494E2CF22A070047C484 /* Global */, 4AB3494F2CF22A250047C484 /* Button */, @@ -1869,7 +1892,6 @@ 4ABCBCE72BE25E51003138A8 /* TrainingPlanResponse.swift in Sources */, 4AC705832BE8BA60003C5310 /* MyBadgeCollectionViewDatasource.swift in Sources */, 4A9FAB472A4C3D1200C40D5A /* BadgeListTableViewCell.swift in Sources */, - 373E38592A2F889500DF96F0 /* DiaryDetailRandomSubjectView.swift in Sources */, 4AC705AE2BECF0D4003C5310 /* EditPlanViewModel.swift in Sources */, 4AF7C22F2BFB797600E8C6CD /* LockBadgeCollectionViewCell.swift in Sources */, 6F294A3E2A26177B00856CC8 /* TrainingGoalViewController.swift in Sources */, @@ -1887,6 +1909,15 @@ 4AC707B42B73D2D400B1D791 /* UserNicknameViewModel.swift in Sources */, 4AEB82952A4CB4F200C1114B /* BadgePopupViewController.swift in Sources */, 3785072F2BD1480C004CC922 /* SharedDiaryDataService.swift in Sources */, + 370BD0AD2CFB65BE009560DB /* DatePickerFooterView.swift in Sources */, + 370BD0AE2CFB65BE009560DB /* AlarmCollectionView.swift in Sources */, + 370BD0AF2CFB65BE009560DB /* SeparationLine.swift in Sources */, + 370BD0B02CFB65BE009560DB /* DiaryBottomView.swift in Sources */, + 370BD0B12CFB65BE009560DB /* DiaryDetailRandomSubjectView.swift in Sources */, + 370BD0B22CFB65BE009560DB /* DiaryScrollerView.swift in Sources */, + 370BD0B32CFB65BE009560DB /* RandomTopicView.swift in Sources */, + 370BD0B42CFB65BE009560DB /* AlarmCollectionViewCell.swift in Sources */, + 370BD0B52CFB65BE009560DB /* AlarmDefaultModel.swift in Sources */, 4AB7C9302B78B44500845733 /* LoginBottomSheetViewController.swift in Sources */, 4A08480E2B555FD0008327C7 /* AmplitudeConstant.swift in Sources */, 4A3774842A42E6EA00357DD1 /* ConfigConstant.swift in Sources */, @@ -1904,6 +1935,7 @@ 37DCA65D2A475B5100FF8F90 /* RandomTopicResponse.swift in Sources */, 4ABCBCCC2BDE8E44003138A8 /* MySummaryService.swift in Sources */, 371107DA2AC99099007A4AC2 /* KeyboardFollowingLayoutHandler.swift in Sources */, + 37B123B62CEEE58E00ED973A /* DetailDiaryCoachedView.swift in Sources */, 4A9FAB452A4C3D1200C40D5A /* BadgeListViewController.swift in Sources */, 4ABCBCE52BE25D82003138A8 /* TrainingPlanViewController.swift in Sources */, 4AB7C9192B75F9B500845733 /* GesturePublisher+.swift in Sources */, @@ -1911,22 +1943,20 @@ 4ABCBCEA2BE26079003138A8 /* TrainingPlanViewModel.swift in Sources */, 4A9E10E42A43468600295D07 /* BaseTargetType.swift in Sources */, 37A574C329FF6E9C00312453 /* Constant.swift in Sources */, + 377B3BF02CF613710086E0BC /* HighlightModifier.swift in Sources */, 4AC1D6832B4ED38200D39A98 /* OnboardingModel.swift in Sources */, 4AC705932BEA1E52003C5310 /* LanguageContainerView.swift in Sources */, 4A004D602B4EE2BD003C8936 /* MyPageAPI.swift in Sources */, 4AE35E9E2A7FE8CE00465FD5 /* UICollectionViewCell+.swift in Sources */, 4A10A3A82AB8AA5800C145E9 /* System.swift in Sources */, 4AC705A02BEA2AAA003C5310 /* SettingServiceProtocol.swift in Sources */, - 4A3F2EA02A0C18B600F6AC60 /* DatePickerFooterView.swift in Sources */, 6FE1298C2A498338005536C4 /* HomeService.swift in Sources */, 4AD04B3D2A190E9A004B7A58 /* UITextView+.swift in Sources */, 4ABCBCC72BDD3983003138A8 /* MySummaryServiceProtocol.swift in Sources */, 6F31802F2A24D1DB00089870 /* CalendarCell.swift in Sources */, 6FE1298A2A4982DA005536C4 /* HomeAPI.swift in Sources */, - 374F828E2AC5DFFE00C128B9 /* DiaryBottomView.swift in Sources */, 4A86D6602C591409002C0617 /* AuthServiceProtocol.swift in Sources */, 4AC707B92B74D5CD00B1D791 /* ServiceAcceptViewModel.swift in Sources */, - 4A3F2E972A0ABBAA00F6AC60 /* AlarmCollectionViewCell.swift in Sources */, 379789032AAC705B00C61EF4 /* NavigationBarActionDelegate.swift in Sources */, 37DCA6572A47574300FF8F90 /* RandomTopicAPI.swift in Sources */, 4ABCBCD22BDFB037003138A8 /* TotalMySummaryResponse.swift in Sources */, @@ -1934,7 +1964,6 @@ A3D7ECB72A26566A009857D6 /* EditNicknameViewController.swift in Sources */, 6FE129902A49A5A6005536C4 /* Date+.swift in Sources */, 6F62668C2A04EA3B000365CD /* HomeViewController.swift in Sources */, - 4AD04B3B2A1905BB004B7A58 /* DiaryScrollerView.swift in Sources */, 4ABCBCBE2BD784A0003138A8 /* MySmeemCollectionViewCell.swift in Sources */, 4AC705952BEA1E58003C5310 /* AlarmContainerView.swift in Sources */, 4AC705A62BEA58EA003C5310 /* SettingAppData.swift in Sources */, @@ -1944,7 +1973,6 @@ 4A454A852B6667180079D48D /* ViewModel.swift in Sources */, 4A3373F52A45BF6600EFE6C4 /* OnboardingEndPoint.swift in Sources */, 4A6630362A51B0AD00D19CC9 /* EditDiaryViewController.swift in Sources */, - 4A3F2E9C2A0B4C7100F6AC60 /* AlarmCollectionView.swift in Sources */, 4A004D512B4ED783003C8936 /* TrainingWayResponse.swift in Sources */, 37DCA6602A48033400FF8F90 /* DetailDiaryViewController.swift in Sources */, 4ABCBCC02BD7C521003138A8 /* MyPlanActiveCollectionViewCell.swift in Sources */, @@ -1981,7 +2009,6 @@ 37DCA6652A48052200FF8F90 /* DetailDiaryResponse.swift in Sources */, 4ABCBCD82BE2230F003138A8 /* MyPlanCollectionViewDataSource.swift in Sources */, 4AC4B82D2A2F9FE200E147AA /* UserDefaultsManager.swift in Sources */, - 37A574E02A00CDCD00312453 /* SeparationLine.swift in Sources */, 4ABCBCDC2BE2484B003138A8 /* MyPlanAppData.swift in Sources */, 3728B8D72A2CFF3A00EF4CF8 /* StepTwoKoreanDiaryViewController.swift in Sources */, 4A07F8A82B7B3E5E004185F2 /* SignupBottomSheetViewController.swift in Sources */, @@ -2032,12 +2059,10 @@ 4A3373F82A461ABC00EFE6C4 /* OnboardingService.swift in Sources */, 4A9731D72BAAB6E100DEC0C8 /* SplashServiceProtocol.swift in Sources */, 4AA5E4B42BF2355300F308C8 /* MySummaryViewModel2.swift in Sources */, - 37A574E82A02424F00312453 /* RandomTopicView.swift in Sources */, 4ABCBCCA2BDD3E3D003138A8 /* MySummaryResponse.swift in Sources */, 4AC7059D2BEA2A8E003C5310 /* SettingEndPoint.swift in Sources */, 371107DD2ACAB571007A4AC2 /* BaseView.swift in Sources */, 371C69D32BE112AD000D745D /* BottomSheetPresentable.swift in Sources */, - 4AC707B02B73CFFA00B1D791 /* AlarmDefaultModel.swift in Sources */, 4AC705912BEA1E49003C5310 /* PlanContainerView.swift in Sources */, 4AC705A92BECE064003C5310 /* EditPlanViewController.swift in Sources */, 378E461A2B5516E200D2A473 /* DeepLAPI.swift in Sources */, diff --git a/Smeem-iOS/Smeem-iOS/Global/HighlightModifier.swift b/Smeem-iOS/Smeem-iOS/Global/HighlightModifier.swift new file mode 100644 index 00000000..f34727fe --- /dev/null +++ b/Smeem-iOS/Smeem-iOS/Global/HighlightModifier.swift @@ -0,0 +1,45 @@ +// +// HighlightModifier.swift +// Smeem-iOS +// +// Created by Joon Baek on 11/26/24. +// + +import SwiftUI + +/* +# 사용법 + - `diaryText`: 강조 표시를 적용할 전체 텍스트 (String) + - `corrections`: 강조할 문장의 목록 (CoachingResponse 배열) + - `highlightIndex`: 강조할 문장의 인덱스 (Int) + + `Text` 뷰에 `.modifier(HighlightModifier(...))`로 적용 + +# 예제 코드 + +Text(diaryText) + .modifier(HighlightModifier( + diaryText: diaryText, + corrections: coachingResponse.corrections, + highlightIndex: currentIndex + )) +*/ + +struct HighlightModifier: ViewModifier { + let diaryText: String + let corrections: [CoachingResponse] + let highlightIndex: Int + + func body(content: Content) -> some View { + var attributedText = AttributedString(diaryText) + + for (index, correction) in corrections.enumerated() { + if index == highlightIndex, let range = attributedText.range(of: correction.original_sentence) { + attributedText[range].backgroundColor = Color(UIColor.point) + attributedText[range].foregroundColor = Color(UIColor.smeemWhite) + } + } + + return Text(attributedText) + } +} diff --git a/Smeem-iOS/Smeem-iOS/Global/UIComponents/SwiftUI/CoachingComparisonView.swift b/Smeem-iOS/Smeem-iOS/Global/UIComponents/SwiftUI/CoachingComparisonView.swift new file mode 100644 index 00000000..60d3c91d --- /dev/null +++ b/Smeem-iOS/Smeem-iOS/Global/UIComponents/SwiftUI/CoachingComparisonView.swift @@ -0,0 +1,72 @@ +// +// CoachingComparisonView.swift +// Smeem-iOS +// +// Created by 황찬미 on 11/1/24. +// + +import SwiftUI + +struct CoachingComparisonView: View { + @Binding var coachingResponse: CoachingResponse + @State private var textHeight: CGFloat = 0 // Text의 높이를 저장할 변수 + + var body: some View { + VStack(spacing: 20) { + VStack(alignment: .leading, spacing: 8) { + HStack { + Rectangle() + .frame(width: 2, height: textHeight) + .foregroundStyle(Color(UIColor.black)) + + Text("나의 일기") + .font(Font.custom("Pretendard", size: 16).weight(.medium)) + .foregroundColor(Color(UIColor.black)) + .background(GeometryReader { geometry in + Color.clear + .preference(key: TextHeightPreferenceKey.self, value: geometry.size.height) + }) + } + .onPreferenceChange(TextHeightPreferenceKey.self) { value in + textHeight = value + } + + Text(coachingResponse.original_sentence) + .font(Font.custom("Pretendard", size: 14)).fontWeight(.regular) + .frame(maxWidth: .infinity, alignment: .topLeading) + } + .padding(.leading, 18) + .padding(.trailing, 18) + + VStack(alignment: .leading, spacing: 8) { + HStack { + Rectangle() + .frame(width: 2, height: textHeight) + .foregroundStyle(Color(UIColor.point)) + + Text("고친 문장") + .font(Font.custom("Pretendard", size: 16).weight(.medium)) + .foregroundColor(Color(UIColor.point)) + } + + Text(coachingResponse.corrected_sentence) + .font(Font.custom("Pretendard", size: 14)).fontWeight(.medium) + .foregroundColor(Color(UIColor.point)) + .frame(maxWidth: .infinity, alignment: .topLeading) + } + .padding(.leading, 18) + .padding(.trailing, 18) + } + } +} + +struct TextHeightPreferenceKey: PreferenceKey { + static var defaultValue: CGFloat = 0 + static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) { + value = nextValue() + } +} + +//#Preview { +// CoachingComparisonView() +//} diff --git a/Smeem-iOS/Smeem-iOS/Global/UIComponents/SwiftUI/CoachingCompletedView.swift b/Smeem-iOS/Smeem-iOS/Global/UIComponents/SwiftUI/CoachingCompletedView.swift new file mode 100644 index 00000000..55199b66 --- /dev/null +++ b/Smeem-iOS/Smeem-iOS/Global/UIComponents/SwiftUI/CoachingCompletedView.swift @@ -0,0 +1,38 @@ +// +// CoachingTextView.swift +// Smeem-iOS +// +// Created by Joon Baek on 2024/10/16. +// + +import SwiftUI + +struct CoachingTextView: View { + @Binding var coachingText: String + + var body: some View { + + VStack(spacing: 16) { + Text("일기를 잘 작성하셨어요! \n내용이 명확하고 흥미로웠습니다.\n이제 몇 가지 문법적 오류를 수정해 볼까요?") + .font(Font.custom("Pretendard", size: 16)) + // Colors 상수 등록 필요 + .foregroundColor(Color(UIColor.smeemBlack)) + .frame(maxWidth: .infinity, alignment: .leading) + + ScrollView { + Text(coachingText) + .font(Font.custom("Pretendard", size: 16)) + .foregroundColor(Color(UIColor.gray400)) + .lineSpacing(0.375) + } + + Spacer() + } + .padding(.horizontal, screenWidth * 0.048) + } +} +// +//@available (iOS 17, *) +//#Preview { +// CoachingTextView(coachingText: "") +//} diff --git a/Smeem-iOS/Smeem-iOS/Global/UIComponents/SwiftUI/CoachingContentView.swift b/Smeem-iOS/Smeem-iOS/Global/UIComponents/SwiftUI/CoachingContentView.swift new file mode 100644 index 00000000..ca8d4667 --- /dev/null +++ b/Smeem-iOS/Smeem-iOS/Global/UIComponents/SwiftUI/CoachingContentView.swift @@ -0,0 +1,45 @@ +// +// CoachingContentView.swift +// Smeem-iOS +// +// Created by Joon Baek on 11/21/24. +// + +import SwiftUI + +struct CoachingContentView: View { + @Binding var currentIndex: Int + @Binding var coachingResponse: CoachingsResponse + + var body: some View { + VStack(spacing: screenHeight * (20 / screenHeight)) { + Rectangle() + .frame(height: screenHeight * (8 / screenHeight)) + .foregroundStyle(Color(UIColor.gray100)) + + TabView(selection: $currentIndex) { + ForEach(coachingResponse.corrections.indices, id: \.self) { item in + ScrollView { + VStack(spacing: screenWidth * (8 / screenWidth)) { + CoachingComparisonView(coachingResponse: $coachingResponse.corrections[item]) + + CoachingExplanationView(coachingResponse: $coachingResponse.corrections[item]) + } + } + } + } + .frame(width: screenWidth, height: screenHeight * (286 / screenHeight), alignment: .top) + .tabViewStyle(.page(indexDisplayMode: .never)) + .padding(.horizontal, screenWidth * (16 / screenWidth)) + + PageControl(currentPage: $currentIndex, + coachingResponse: $coachingResponse) + } + } +} + +#Preview { + @State var defaultIndex: Int = 0 + @State var coachingResponse = CoachingsResponse.empty + CoachingContentView(currentIndex: $defaultIndex, coachingResponse: $coachingResponse) +} diff --git a/Smeem-iOS/Smeem-iOS/Global/UIComponents/SwiftUI/CoachingExplanationView.swift b/Smeem-iOS/Smeem-iOS/Global/UIComponents/SwiftUI/CoachingExplanationView.swift new file mode 100644 index 00000000..8686a472 --- /dev/null +++ b/Smeem-iOS/Smeem-iOS/Global/UIComponents/SwiftUI/CoachingExplanationView.swift @@ -0,0 +1,38 @@ +// +// CoachingExplanationView.swift +// Smeem-iOS +// +// Created by 황찬미 on 11/16/24. +// + +import SwiftUI + +struct CoachingExplanationView: View { + @Binding var coachingResponse: CoachingResponse + + var body: some View { + HStack() { + + ZStack(alignment: .leading) { + GeometryReader { geomerty in + Rectangle() + .fill(Color(UIColor.gray100)) + .frame(height: geomerty.size.height) + .cornerRadius(3) + } + + Text(coachingResponse.reason) + .font(Font.custom("Pretendard", size: 14).weight(.regular)) + .foregroundStyle(.black) + .padding(12) + } + .fixedSize(horizontal: false, vertical: true) + .padding(.leading, 18) + .padding(.trailing, 18) + } + } +} + +//#Preview { +// CoachingExplanationView() +//} diff --git a/Smeem-iOS/Smeem-iOS/Global/UIComponents/SwiftUI/CustomSegmentedControl.swift b/Smeem-iOS/Smeem-iOS/Global/UIComponents/SwiftUI/CustomSegmentedControl.swift new file mode 100644 index 00000000..9576441a --- /dev/null +++ b/Smeem-iOS/Smeem-iOS/Global/UIComponents/SwiftUI/CustomSegmentedControl.swift @@ -0,0 +1,74 @@ +// +// CustomSegmentedControl.swift +// Smeem-iOS +// +// Created by Joon Baek on 2024/10/22. +// + +import SwiftUI + +struct CustomSegmentedControl: View { + @Binding var selectedIndex: Int + let options: [String] + + var body: some View { + HStack(spacing: 0) { + ForEach(options.indices, id: \.self) { index in + SegmentButton( + title: options[index], + isSelected: selectedIndex == index, + action: { selectedIndex = index } + ) + } + } + .background(Color.gray.opacity(0.2)) + .cornerRadius(8) + } +} + +struct SegmentButton: View { + let title: String + let isSelected: Bool + let action: () -> Void + + var body: some View { + Button(action: action) { + Text(title) + .padding(.vertical, 8) + .padding(.horizontal, 11) + .frame(maxWidth: .infinity) + .background(backgroundColor) + .foregroundColor(foregroundColor) + .font(Font(UIFont.c5)) + } + } + + private var backgroundColor: Color { + isSelected ? (isCoachingOn ? Color(UIColor.point) : Color(UIColor.gray200)) : Color(UIColor.gray100) + } + + private var foregroundColor: Color { + isSelected ? .white : Color(UIColor.gray500) + } + + private var isCoachingOn: Bool { + title == "코칭 ON" + } +} + +struct PreviewWrapper: View { + @State private var selectedIndex = 0 + let options = ["코칭 OFF", "코칭 ON"] + + var body: some View { + CustomSegmentedControl(selectedIndex: $selectedIndex, options: options) + .frame(height: 40) + .padding(117) + } +} + +@available(iOS 17.0, *) +#Preview { + PreviewWrapper() +} + diff --git a/Smeem-iOS/Smeem-iOS/Global/UIComponents/SwiftUI/FloatingButtonsSwiftUIView.swift b/Smeem-iOS/Smeem-iOS/Global/UIComponents/SwiftUI/FloatingButtonsSwiftUIView.swift new file mode 100644 index 00000000..c2290fa4 --- /dev/null +++ b/Smeem-iOS/Smeem-iOS/Global/UIComponents/SwiftUI/FloatingButtonsSwiftUIView.swift @@ -0,0 +1,82 @@ +// +// FloatingButtonsSwiftUIView.swift +// Smeem-iOS +// +// Created by Joon Baek on 11/26/24. +// + +import SwiftUI + +struct FloatingButtonsSwiftUIView: View { + @Environment(\.dismiss) var dismiss + @State private var showAlert = false + + var body: some View { + ZStack { + Color.black.opacity(0.3) + .ignoresSafeArea() + .onTapGesture { + dismiss() + } + + VStack { + Spacer() + + VStack(spacing: 0) { + Button(action: { + showAlert = true + }) { + Text("수정하기") + .font(.headline) + .frame(maxWidth: .infinity) + .padding() + .foregroundColor(.blue) + } + .alert("수정시 모든 코칭 내용이 사라집니다. 그래도 수정하시겠습니까?", + isPresented: $showAlert) { + Button("취소", role: .cancel) { dismiss() } + Button("확인", role: .destructive) { + print("수정 확인 버튼 액션") + } + } + + Divider() + .frame(height: 1) + .background(Color.gray.opacity(0.5)) + + Button(action: { + print("삭제하기 버튼 액션") + }) { + Text("삭제하기") + .font(.headline) + .frame(maxWidth: .infinity) + .padding() + .foregroundColor(.red) + } + } + .background(Color.white) + .cornerRadius(14) + + Button(action: { + dismiss() + }) { + Text("취소") + .font(.headline) + .frame(maxWidth: .infinity) + .padding() + .background(.white) + .foregroundColor(.blue) + .cornerRadius(14) + } + .padding(.top, 10) + + Spacer().frame(height: 20) + } + .padding(.horizontal, 20) + } + } +} + +#Preview { + FloatingButtonsSwiftUIView() +} diff --git a/Smeem-iOS/Smeem-iOS/Global/UIComponents/SwiftUI/ScrollableDiaryView.swift b/Smeem-iOS/Smeem-iOS/Global/UIComponents/SwiftUI/ScrollableDiaryView.swift new file mode 100644 index 00000000..e334c2d3 --- /dev/null +++ b/Smeem-iOS/Smeem-iOS/Global/UIComponents/SwiftUI/ScrollableDiaryView.swift @@ -0,0 +1,62 @@ +// +// ScrollableDiaryView.swift +// Smeem-iOS +// +// Created by Joon Baek on 11/26/24. +// + +import SwiftUI + +struct ScrollableDiaryView: View { + let diaryText: String + let corrections: [CoachingResponse] + let currentIndex: Int + let selectedIndex: Int + let dateText: String + let authorText: String + + @State private var contentHeight: CGFloat = 0 + + var body: some View { + VStack(spacing: 0) { + // 본문 내용 + ScrollView { + VStack(alignment: .leading, spacing: screenWidth * 0.02) { + // 텍스트 내용 + Text(diaryText) + .modifier(HighlightModifier( + diaryText: diaryText, + corrections: corrections, + highlightIndex: selectedIndex != 0 ? currentIndex : -1 + )) + .padding(.horizontal, screenHeight * (18 / screenHeight)) + .padding(.bottom, screenHeight * (16 / screenHeight)) + .foregroundColor(Color(UIColor.gray400)) + .background( // 콘텐츠 크기를 측정하기 위한 백그라운드 + GeometryReader { geometry in + Color.clear + .onAppear { + contentHeight = geometry.size.height + } + } + ) + + // Footer (작성 날짜, 작성자) + HStack { + Spacer() + VStack(alignment: .trailing, spacing: screenWidth * (4 / screenWidth)) { + Text(dateText) + Text(authorText) + } + .font(Font(UIFont.c3)) + .foregroundColor(Color(UIColor.gray400)) + } + .padding(.horizontal, screenWidth * (18 / screenWidth)) + } + .padding(.bottom, screenHeight * (16 / screenHeight)) + } + .frame(maxHeight: contentHeight + screenHeight * (100 / screenHeight)) // 텍스트 높이에 따른 동적 변경 + } + } +} + diff --git a/Smeem-iOS/Smeem-iOS/Global/UIComponents/SwiftUI/SwiftUINavigationView.swift b/Smeem-iOS/Smeem-iOS/Global/UIComponents/SwiftUI/SwiftUINavigationView.swift new file mode 100644 index 00000000..95d30984 --- /dev/null +++ b/Smeem-iOS/Smeem-iOS/Global/UIComponents/SwiftUI/SwiftUINavigationView.swift @@ -0,0 +1,75 @@ +// +// SwiftUINavigationView.swift +// Smeem-iOS +// +// Created by Joon Baek on 2024/10/18. +// + +import SwiftUI + +enum NavigationbarType { + case coachingCompleted + case diaryDetails +} + +struct SwiftUINavigationView: View { + let navigationbarType: NavigationbarType + @State private var showFloatingView = false + @Binding var selectedIndex: Int + + let options = ["코칭 OFF", "코칭 ON"] + + var body: some View { + HStack { + // 뒤로가기 버튼 + if navigationbarType == .diaryDetails { + Button(action: { + // 뒤로가기 액션 + }, label: { + Image("icnBack") + .imageScale(.large) + }) + .padding(.leading, 10 / screenWidth) + } else { + Spacer().frame(width: 30 / screenWidth) + } + + // 중앙 콘텐츠 (CustomSegmentedControl) + if navigationbarType == .diaryDetails { + CustomSegmentedControl(selectedIndex: $selectedIndex, options: options) + .frame(height: 32 / screenHeight) + .padding(65) + } + + Spacer() + + // 오른쪽 버튼 + if navigationbarType == .diaryDetails { + Button(action: { + showFloatingView = true + }, label: { + Image("icnMore") + }) + .padding(.trailing, 18 / screenWidth) + .fullScreenCover(isPresented: $showFloatingView) { + FloatingButtonsSwiftUIView() + } + } else { + Button(action: { + // 다른 버튼 액션 + }, label: { + Text("닫기") + .tint(.black) + }) + .padding(.trailing, 18 / screenWidth) + } + } + .frame(height: screenHeight * (66 / screenHeight)) + } +} + +#Preview { + @State var defaultIndex = 0 + + SwiftUINavigationView(navigationbarType: .diaryDetails, selectedIndex: $defaultIndex) +} diff --git a/Smeem-iOS/Smeem-iOS/Network/NetworkDataModel/Coaching/CoachingResponse.swift b/Smeem-iOS/Smeem-iOS/Network/NetworkDataModel/Coaching/CoachingResponse.swift index 428552d3..b455c245 100644 --- a/Smeem-iOS/Smeem-iOS/Network/NetworkDataModel/Coaching/CoachingResponse.swift +++ b/Smeem-iOS/Smeem-iOS/Network/NetworkDataModel/Coaching/CoachingResponse.swift @@ -16,10 +16,32 @@ extension CoachingsResponse { corrected_sentence: "I went to the park yesterdayI went to the park yesterdayI went to the park yesterdayI went to the park yesterdayI went to the park yesterday", reason: "현재완료 시제인 have went는 과거 시제인 went로 바꾸는 것이 맞습니다. yesterday와 함께 사용할 때는 단순 과거 시제를 사용해야 합니다.", is_corrected: true), - CoachingResponse(original_sentence: "I have went to the park yesterdayI have went to the park yesterdayI have went럼뉴름ㄴ람ㄴㄹ 마넝롬나ㅣㅓㅇㄹ ㅗㅁ나ㅓㅇ롬나어롬나어롬나러ㅗㅁ나러 ㅗㄴ마러ㅁ너ㅏ롬 ㄴ라ㅓ ㅗㄴㅁ라 왜 갑자 I have went to the park yesterdayI have went to the park yesterdayI have went to the park yesterdayI have went to the park yesterdayI have went to the park yesterday", - corrected_sentence: "I went to the park yesterdayI went to the park yesterdayI went to the park yesterday", - reason: "이러 이러한 이유로 이건 맞습니다", - is_corrected: true)]) + CoachingResponse(original_sentence: "I have went to the park yesterdayI have went to the park yesterdayI have went럼뉴름ㄴ람ㄴㄹ 마넝롬나ㅣㅓㅇㄹ ㅗㅁ나ㅓㅇ롬나어롬나어롬나러ㅗㅁ나러 ㅗㄴ마러ㅗㅁ너ㅏ롬 ㄴ라ㅓ ㅗㄴㅁ라 왜 갑자 I have went to the park yesterdayI have went to the park yesterdayI have went to the park yesterdayI have went to the park yesterdayI have went to the park yesterday", + corrected_sentence: "I went to the park yesterdayI went to the park yesterdayI went to the park yesterday", + reason: "이러 이러한 이유로 이건 맞습니다", + is_corrected: true)]) + static let sample = CoachingsResponse( + corrections: [ + CoachingResponse( + original_sentence: "I should have skimmed the previous season - Avatar1..", + corrected_sentence: "I should have skimmed the previous season - Avatar 1.", + reason: "Avatar1은 'Avatar 1'으로 띄어쓰기해야 하며, 중복된 마침표 하나를 제거해야 합니다.", + is_corrected: true + ), + CoachingResponse( + original_sentence: "I think 두팔 who is my boyfriend should study before wathcing….", + corrected_sentence: "I think 두팔, who is my boyfriend, should study before watching.", + reason: "'wathcing'을 'watching'으로 수정하고, 불필요한 점을 제거했습니다. 또한 쉼표를 추가하여 문장을 읽기 쉽게 만들었습니다.", + is_corrected: true + ), + CoachingResponse( + original_sentence: "In my personal opinion, the jjin main character of Avatar2 is not Sully, but his son.", + corrected_sentence: "In my personal opinion, the real main character of Avatar 2 is not Sully, but his son.", + reason: "'jjin'은 'real'로 대체하였고, 'Avatar2'를 'Avatar 2'로 띄어쓰기 처리하였습니다.", + is_corrected: true + ) + ] + ) } struct CoachingResponse: Codable { diff --git a/Smeem-iOS/Smeem-iOS/Presentation/DetailDiary/DetailDiaryCoachedView.swift b/Smeem-iOS/Smeem-iOS/Presentation/DetailDiary/DetailDiaryCoachedView.swift new file mode 100644 index 00000000..7dca18fb --- /dev/null +++ b/Smeem-iOS/Smeem-iOS/Presentation/DetailDiary/DetailDiaryCoachedView.swift @@ -0,0 +1,50 @@ +// +// DetailDiaryCoachedView.swift +// Smeem-iOS +// +// Created by Joon Baek on 11/21/24. +// + +import SwiftUI + +struct DetailDiaryCoachedView: View { + + @Binding var diaryText: String + @Binding var coachingResponse: CoachingsResponse + @State var currentIndex = 0 + @State private var selectedIndex = 0 + + var body: some View { + VStack(spacing: screenWidth * (16 / screenWidth)) { + SwiftUINavigationView(navigationbarType: .diaryDetails, + selectedIndex: $selectedIndex) + + ScrollableDiaryView( + diaryText: diaryText, + corrections: coachingResponse.corrections, + currentIndex: currentIndex, + selectedIndex: selectedIndex, + dateText: "2023년 3월 27일 4:18PM", + authorText: "유진이" + ) + + // "코칭 ON"일 때만 표시 + if selectedIndex == 1 { + Spacer() + CoachingContentView(currentIndex: $currentIndex, + coachingResponse: $coachingResponse) + } else { + Spacer(minLength: screenHeight * (342 / screenHeight)) + } + } + } +} + +@available(iOS 17, *) +#Preview { + @State var diaryText = "I watched Avatar with my boyfriend at Hongdae CGV. I should have skimmed the previous season - Avatar1.. I really couldn’t get what they weere saying and the universe(??). What I was annoyed then was 두팔 didn’t know that as me. I think 두팔 who is my boyfriend should study before wathcing…. but Avatar2 is amazing movie I think. In my personal opinion, the jjin main character of Avatar2 is not Sully, but his son." + + @State var coachingResponse = CoachingsResponse.sample + + DetailDiaryCoachedView(diaryText: $diaryText, coachingResponse: $coachingResponse) +}