diff --git a/HappyAnding/HappyAnding.xcodeproj/project.pbxproj b/HappyAnding/HappyAnding.xcodeproj/project.pbxproj index d6a67e00..485b9c4f 100644 --- a/HappyAnding/HappyAnding.xcodeproj/project.pbxproj +++ b/HappyAnding/HappyAnding.xcodeproj/project.pbxproj @@ -12,11 +12,13 @@ 4D402E7B2979342800D9A825 /* RecentRegisteredView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D402E7A2979342800D9A825 /* RecentRegisteredView.swift */; }; 4D61A767291E1EE8000EF531 /* NavigationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D61A766291E1EE8000EF531 /* NavigationViewModel.swift */; }; 4D778A34290A53BA00C15AC4 /* Application+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D778A33290A53BA00C15AC4 /* Application+Extension.swift */; }; + 4D7D16072986BBD7008B3332 /* TextLiteral.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D7D16062986BBD7008B3332 /* TextLiteral.swift */; }; + 4D7D16082986BBDE008B3332 /* TextLiteral.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D7D16062986BBD7008B3332 /* TextLiteral.swift */; }; 4DAD635E292AB61700ABF8C1 /* UpdateShortcutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DAD635D292AB61700ABF8C1 /* UpdateShortcutView.swift */; }; 4DAD6370292BCB1000ABF8C1 /* CategoryCardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DAD636F292BCB1000ABF8C1 /* CategoryCardView.swift */; }; 87276C382933F6AB00C92F4C /* CustomTextEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87276C372933F6AB00C92F4C /* CustomTextEditor.swift */; }; 872A7D8F2918393B004A05B8 /* PrivacyPolicyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 872A7D8E2918393B004A05B8 /* PrivacyPolicyView.swift */; }; - 8788374A2920D549009B3F54 /* Binding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 878837492920D549009B3F54 /* Binding.swift */; }; + 8788374A2920D549009B3F54 /* Binding+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 878837492920D549009B3F54 /* Binding+Extension.swift */; }; 8792478D2918CE450040D5C3 /* UINavigationContoller+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8792478C2918CE450040D5C3 /* UINavigationContoller+Extension.swift */; }; 8792479B291BDF820040D5C3 /* SearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8792479A291BDF820040D5C3 /* SearchView.swift */; }; 8795A16E292AB841004B765F /* View+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8795A16D292AB841004B765F /* View+Extension.swift */; }; @@ -39,31 +41,23 @@ 87E99CA328FFF22E009B691F /* ExploreCurationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87E99CA228FFF22E009B691F /* ExploreCurationView.swift */; }; 87E99CA728FFF23E009B691F /* ListCurationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87E99CA628FFF23E009B691F /* ListCurationView.swift */; }; 87E99CA928FFF24F009B691F /* ExploreShortcutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87E99CA828FFF24F009B691F /* ExploreShortcutView.swift */; }; - 87E99CAB28FFF256009B691F /* ExploreCategoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87E99CAA28FFF256009B691F /* ExploreCategoryView.swift */; }; 87E99CAD28FFF261009B691F /* ReadShortcutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87E99CAC28FFF261009B691F /* ReadShortcutView.swift */; }; - 87E99CAF28FFF26A009B691F /* EditShortcutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87E99CAE28FFF26A009B691F /* EditShortcutView.swift */; }; 87E99CB128FFF273009B691F /* WriteCurationSetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87E99CB028FFF273009B691F /* WriteCurationSetView.swift */; }; 87E99CB528FFF282009B691F /* WriteCurationInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87E99CB428FFF282009B691F /* WriteCurationInfoView.swift */; }; - 87E99CB928FFF291009B691F /* WriteShortcutTitleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87E99CB828FFF291009B691F /* WriteShortcutTitleView.swift */; }; + 87E99CB928FFF291009B691F /* WriteShortcutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87E99CB828FFF291009B691F /* WriteShortcutView.swift */; }; 87E99CBB28FFF298009B691F /* IconModalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87E99CBA28FFF298009B691F /* IconModalView.swift */; }; - 87E99CBD28FFF2A1009B691F /* WriteShortcutdescriptionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87E99CBC28FFF2A1009B691F /* WriteShortcutdescriptionView.swift */; }; - 87E99CBF28FFF2AB009B691F /* WriteShortcutTagView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87E99CBE28FFF2AB009B691F /* WriteShortcutTagView.swift */; }; 87E99CC128FFF2B5009B691F /* CategoryModalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87E99CC028FFF2B5009B691F /* CategoryModalView.swift */; }; 87E99CC429014572009B691F /* Color+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87E99CC329014572009B691F /* Color+Extension.swift */; }; 87E99CC7290145AD009B691F /* ShortcutCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87E99CC6290145AD009B691F /* ShortcutCell.swift */; }; 87E99CC9290145B8009B691F /* ListShortcutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87E99CC8290145B8009B691F /* ListShortcutView.swift */; }; 87E99CCB290145C4009B691F /* UserCurationCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87E99CCA290145C4009B691F /* UserCurationCell.swift */; }; 87E99CCD290145CC009B691F /* AdminCurationCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87E99CCC290145CC009B691F /* AdminCurationCell.swift */; }; - 87E99CCF290145D5009B691F /* PaletteCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87E99CCE290145D5009B691F /* PaletteCell.swift */; }; - 87E99CD1290145DE009B691F /* PaletteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87E99CD0290145DE009B691F /* PaletteView.swift */; }; 87E99CD32901465F009B691F /* ValidationCheckTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87E99CD22901465F009B691F /* ValidationCheckTextField.swift */; }; 87E99CD929042536009B691F /* SectionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87E99CD829042536009B691F /* SectionType.swift */; }; 87E99CDB29042CCA009B691F /* Category.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87E99CDA29042CCA009B691F /* Category.swift */; }; 87E99CE82907C6E6009B691F /* Shortcuts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87E99CE72907C6E6009B691F /* Shortcuts.swift */; }; 87E99CEC29080C30009B691F /* Curation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87E99CEB29080C30009B691F /* Curation.swift */; }; 87E99CEE29080D33009B691F /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87E99CED29080D33009B691F /* User.swift */; }; - 87EDB96329082C7F009A750A /* ListCategoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87EDB96229082C7F009A750A /* ListCategoryView.swift */; }; - A04ACB0129027BDE004A85A6 /* TabRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = A04ACB0029027BDE004A85A6 /* TabRouter.swift */; }; A04ACB062903D0B2004A85A6 /* MyShortcutCardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A04ACB052903D0B2004A85A6 /* MyShortcutCardView.swift */; }; A04ACB082903DECC004A85A6 /* MyShortcutCardListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A04ACB072903DECC004A85A6 /* MyShortcutCardListView.swift */; }; A04ACB0A29041CD8004A85A6 /* DownloadRankView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A04ACB0929041CD8004A85A6 /* DownloadRankView.swift */; }; @@ -74,7 +68,7 @@ A09CBA7E2922B36C00D31F5F /* String+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A09CBA7D2922B36C00D31F5F /* String+Extension.swift */; }; A0DD085729276608008177BB /* URL+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0DD085629276608008177BB /* URL+Extension.swift */; }; A0F822AC2910B8F100AF4448 /* ShortcutsZipViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0F822AB2910B8F100AF4448 /* ShortcutsZipViewModel.swift */; }; - A0F822B729164D2300AF4448 /* ShortcutsListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0F822B629164D2300AF4448 /* ShortcutsListView.swift */; }; + A0F822B729164D2300AF4448 /* ListCategoryShortcutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0F822B629164D2300AF4448 /* ListCategoryShortcutView.swift */; }; A31F1844292A637300AF4A82 /* Date+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9CAEF822914855900224B0A /* Date+Extension.swift */; }; A31F1846292A638700AF4A82 /* (null) in Sources */ = {isa = PBXBuildFile; }; A31F1848292A64D700AF4A82 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 87E99C7128F94EA8009B691F /* Assets.xcassets */; }; @@ -90,7 +84,7 @@ A38115BA292B447D0043E8B8 /* ShortcutCardCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A38115B9292B447D0043E8B8 /* ShortcutCardCell.swift */; }; A3A6AD1E292763E2004C49DC /* ShareExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = A3A6AD14292763E2004C49DC /* ShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; A3B2636A2909DFD200829DE1 /* CurationListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3B263692909DFD200829DE1 /* CurationListView.swift */; }; - A3C5576C292BE084003907DC /* ShareExtensionWriteShortcutTitleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3C5576B292BE084003907DC /* ShareExtensionWriteShortcutTitleView.swift */; }; + A3C5576C292BE084003907DC /* ShareExtensionWriteShortcutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3C5576B292BE084003907DC /* ShareExtensionWriteShortcutView.swift */; }; A3FC4747292A61550058BF26 /* FirebaseAnalytics in Frameworks */ = {isa = PBXBuildFile; productRef = A3FC4746292A61550058BF26 /* FirebaseAnalytics */; }; A3FC4749292A61550058BF26 /* FirebaseAuth in Frameworks */ = {isa = PBXBuildFile; productRef = A3FC4748292A61550058BF26 /* FirebaseAuth */; }; A3FC474B292A61550058BF26 /* FirebaseDatabase in Frameworks */ = {isa = PBXBuildFile; productRef = A3FC474A292A61550058BF26 /* FirebaseDatabase */; }; @@ -115,11 +109,16 @@ F90DEA5129327E62002140E2 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3D41EE07290A4C18008BE986 /* Launch Screen.storyboard */; }; F9131B6B2922D38D00868A0E /* Keyword.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9131B6A2922D38D00868A0E /* Keyword.swift */; }; F9136EB6293612310034AAB2 /* ShortcutsZipView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9136EB5293612310034AAB2 /* ShortcutsZipView.swift */; }; + F91A72C1299915C500CA135A /* MoreCaptionTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F91A72C0299915C500CA135A /* MoreCaptionTextView.swift */; }; + F91A72C32999160E00CA135A /* Alerter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F91A72C22999160E00CA135A /* Alerter.swift */; }; F94B432E2907088400987819 /* UserCurationListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F94B432D2907088400987819 /* UserCurationListView.swift */; }; F94B435D2907B19A00987819 /* FirebaseAnalytics in Frameworks */ = {isa = PBXBuildFile; productRef = F94B435C2907B19A00987819 /* FirebaseAnalytics */; }; F94B435F2907B19A00987819 /* FirebaseAuth in Frameworks */ = {isa = PBXBuildFile; productRef = F94B435E2907B19A00987819 /* FirebaseAuth */; }; F94B43612907B19A00987819 /* FirebaseFirestore in Frameworks */ = {isa = PBXBuildFile; productRef = F94B43602907B19A00987819 /* FirebaseFirestore */; }; F94B43632907B19A00987819 /* FirebaseFirestoreCombine-Community in Frameworks */ = {isa = PBXBuildFile; productRef = F94B43622907B19A00987819 /* FirebaseFirestoreCombine-Community */; }; + F96D45B72980301F000C2441 /* SubtitleTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F96D45B62980301F000C2441 /* SubtitleTextView.swift */; }; + F96D45BB29804057000C2441 /* EnvironmentValues+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = F96D45BA29804057000C2441 /* EnvironmentValues+Extension.swift */; }; + F96D45BD29816578000C2441 /* StickyHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = F96D45BC29816578000C2441 /* StickyHeader.swift */; }; F9724BBF292755E400860F8A /* Comment.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9724BBE292755E400860F8A /* Comment.swift */; }; F976E82C29368E0D0088BBA1 /* Version.swift in Sources */ = {isa = PBXBuildFile; fileRef = F976E82B29368E0D0088BBA1 /* Version.swift */; }; F976E85129395B350088BBA1 /* ShareExtensionViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F976E85029395B350088BBA1 /* ShareExtensionViewModel.swift */; }; @@ -181,12 +180,13 @@ 4D402E7A2979342800D9A825 /* RecentRegisteredView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecentRegisteredView.swift; sourceTree = ""; }; 4D61A766291E1EE8000EF531 /* NavigationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationViewModel.swift; sourceTree = ""; }; 4D778A33290A53BA00C15AC4 /* Application+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Application+Extension.swift"; sourceTree = ""; }; + 4D7D16062986BBD7008B3332 /* TextLiteral.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TextLiteral.swift; path = HappyAnding/TextLiteral.swift; sourceTree = SOURCE_ROOT; }; 4DAD635D292AB61700ABF8C1 /* UpdateShortcutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdateShortcutView.swift; sourceTree = ""; }; 4DAD636F292BCB1000ABF8C1 /* CategoryCardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryCardView.swift; sourceTree = ""; }; 87276C372933F6AB00C92F4C /* CustomTextEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTextEditor.swift; sourceTree = ""; }; 872A7D8E2918393B004A05B8 /* PrivacyPolicyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacyPolicyView.swift; sourceTree = ""; }; 8764C0D6291F85DF00E1593B /* NavigationStackModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationStackModel.swift; sourceTree = ""; }; - 878837492920D549009B3F54 /* Binding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Binding.swift; sourceTree = ""; }; + 878837492920D549009B3F54 /* Binding+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Binding+Extension.swift"; sourceTree = ""; }; 8792478C2918CE450040D5C3 /* UINavigationContoller+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationContoller+Extension.swift"; sourceTree = ""; }; 8792479A291BDF820040D5C3 /* SearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchView.swift; sourceTree = ""; }; 8795A16D292AB841004B765F /* View+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Extension.swift"; sourceTree = ""; }; @@ -215,31 +215,23 @@ 87E99CA428FFF238009B691F /* ReadAdminCurationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadAdminCurationView.swift; sourceTree = ""; }; 87E99CA628FFF23E009B691F /* ListCurationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListCurationView.swift; sourceTree = ""; }; 87E99CA828FFF24F009B691F /* ExploreShortcutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExploreShortcutView.swift; sourceTree = ""; }; - 87E99CAA28FFF256009B691F /* ExploreCategoryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExploreCategoryView.swift; sourceTree = ""; }; 87E99CAC28FFF261009B691F /* ReadShortcutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadShortcutView.swift; sourceTree = ""; }; - 87E99CAE28FFF26A009B691F /* EditShortcutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditShortcutView.swift; sourceTree = ""; }; 87E99CB028FFF273009B691F /* WriteCurationSetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WriteCurationSetView.swift; sourceTree = ""; }; 87E99CB428FFF282009B691F /* WriteCurationInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WriteCurationInfoView.swift; sourceTree = ""; }; - 87E99CB828FFF291009B691F /* WriteShortcutTitleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WriteShortcutTitleView.swift; sourceTree = ""; }; + 87E99CB828FFF291009B691F /* WriteShortcutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WriteShortcutView.swift; sourceTree = ""; }; 87E99CBA28FFF298009B691F /* IconModalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconModalView.swift; sourceTree = ""; }; - 87E99CBC28FFF2A1009B691F /* WriteShortcutdescriptionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WriteShortcutdescriptionView.swift; sourceTree = ""; }; - 87E99CBE28FFF2AB009B691F /* WriteShortcutTagView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WriteShortcutTagView.swift; sourceTree = ""; }; 87E99CC028FFF2B5009B691F /* CategoryModalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryModalView.swift; sourceTree = ""; }; 87E99CC329014572009B691F /* Color+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Color+Extension.swift"; sourceTree = ""; }; 87E99CC6290145AD009B691F /* ShortcutCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShortcutCell.swift; sourceTree = ""; }; 87E99CC8290145B8009B691F /* ListShortcutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListShortcutView.swift; sourceTree = ""; }; 87E99CCA290145C4009B691F /* UserCurationCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserCurationCell.swift; sourceTree = ""; }; 87E99CCC290145CC009B691F /* AdminCurationCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdminCurationCell.swift; sourceTree = ""; }; - 87E99CCE290145D5009B691F /* PaletteCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaletteCell.swift; sourceTree = ""; }; - 87E99CD0290145DE009B691F /* PaletteView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaletteView.swift; sourceTree = ""; }; 87E99CD22901465F009B691F /* ValidationCheckTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValidationCheckTextField.swift; sourceTree = ""; }; 87E99CD829042536009B691F /* SectionType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionType.swift; sourceTree = ""; }; 87E99CDA29042CCA009B691F /* Category.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Category.swift; sourceTree = ""; }; 87E99CE72907C6E6009B691F /* Shortcuts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Shortcuts.swift; sourceTree = ""; }; 87E99CEB29080C30009B691F /* Curation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Curation.swift; sourceTree = ""; }; 87E99CED29080D33009B691F /* User.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = ""; }; - 87EDB96229082C7F009A750A /* ListCategoryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListCategoryView.swift; sourceTree = ""; }; - A04ACB0029027BDE004A85A6 /* TabRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabRouter.swift; sourceTree = ""; }; A04ACB052903D0B2004A85A6 /* MyShortcutCardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyShortcutCardView.swift; sourceTree = ""; }; A04ACB072903DECC004A85A6 /* MyShortcutCardListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyShortcutCardListView.swift; sourceTree = ""; }; A04ACB0929041CD8004A85A6 /* DownloadRankView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadRankView.swift; sourceTree = ""; }; @@ -250,7 +242,7 @@ A09CBA7D2922B36C00D31F5F /* String+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extension.swift"; sourceTree = ""; }; A0DD085629276608008177BB /* URL+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+Extension.swift"; sourceTree = ""; }; A0F822AB2910B8F100AF4448 /* ShortcutsZipViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShortcutsZipViewModel.swift; sourceTree = ""; }; - A0F822B629164D2300AF4448 /* ShortcutsListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShortcutsListView.swift; sourceTree = ""; }; + A0F822B629164D2300AF4448 /* ListCategoryShortcutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListCategoryShortcutView.swift; sourceTree = ""; }; A33F74AD2908D8C800B8D0D0 /* CheckBoxShortcutCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckBoxShortcutCell.swift; sourceTree = ""; }; A3439AFA2939B0E80043E273 /* UserDefaults+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserDefaults+Extension.swift"; sourceTree = ""; }; A35C39532936928200C4359F /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "../../../../Downloads/GoogleService-Info.plist"; sourceTree = ""; }; @@ -262,7 +254,7 @@ A3A6AD1B292763E2004C49DC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; A3A6AD232927BA06004C49DC /* ShareExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ShareExtension.entitlements; sourceTree = ""; }; A3B263692909DFD200829DE1 /* CurationListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurationListView.swift; sourceTree = ""; }; - A3C5576B292BE084003907DC /* ShareExtensionWriteShortcutTitleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareExtensionWriteShortcutTitleView.swift; sourceTree = ""; }; + A3C5576B292BE084003907DC /* ShareExtensionWriteShortcutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareExtensionWriteShortcutView.swift; sourceTree = ""; }; A3FF0182291648A300384211 /* MailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MailView.swift; sourceTree = ""; }; A3FF01852918552E00384211 /* AboutTeamView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutTeamView.swift; sourceTree = ""; }; A3FF01872918581E00384211 /* LicenseView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LicenseView.swift; sourceTree = ""; }; @@ -272,7 +264,12 @@ A3FF4F8D297A836800FA9EEE /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; F9131B6A2922D38D00868A0E /* Keyword.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Keyword.swift; sourceTree = ""; }; F9136EB5293612310034AAB2 /* ShortcutsZipView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShortcutsZipView.swift; sourceTree = ""; }; + F91A72C0299915C500CA135A /* MoreCaptionTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoreCaptionTextView.swift; sourceTree = ""; }; + F91A72C22999160E00CA135A /* Alerter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Alerter.swift; sourceTree = ""; }; F94B432D2907088400987819 /* UserCurationListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserCurationListView.swift; sourceTree = ""; }; + F96D45B62980301F000C2441 /* SubtitleTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubtitleTextView.swift; sourceTree = ""; }; + F96D45BA29804057000C2441 /* EnvironmentValues+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "EnvironmentValues+Extension.swift"; sourceTree = ""; }; + F96D45BC29816578000C2441 /* StickyHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StickyHeader.swift; sourceTree = ""; }; F9724BBE292755E400860F8A /* Comment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Comment.swift; sourceTree = ""; }; F976E82B29368E0D0088BBA1 /* Version.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Version.swift; sourceTree = ""; }; F976E85029395B350088BBA1 /* ShareExtensionViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareExtensionViewModel.swift; sourceTree = ""; }; @@ -373,6 +370,7 @@ 87E99C9828FFF1D2009B691F /* Views */, 87E99CD729042503009B691F /* Model */, A0F822AA2910B8B900AF4448 /* ViewModel */, + 4D7D16062986BBD7008B3332 /* TextLiteral.swift */, 87E99C7128F94EA8009B691F /* Assets.xcassets */, 87E99C7328F94EA8009B691F /* Preview Content */, ); @@ -407,9 +405,7 @@ 87E99C9728FFF1C0009B691F /* WriteShortcutViews */ = { isa = PBXGroup; children = ( - 87E99CB828FFF291009B691F /* WriteShortcutTitleView.swift */, - 87E99CBC28FFF2A1009B691F /* WriteShortcutdescriptionView.swift */, - 87E99CBE28FFF2AB009B691F /* WriteShortcutTagView.swift */, + 87E99CB828FFF291009B691F /* WriteShortcutView.swift */, 87E99CBA28FFF298009B691F /* IconModalView.swift */, 87E99CC028FFF2B5009B691F /* CategoryModalView.swift */, ); @@ -450,7 +446,6 @@ isa = PBXGroup; children = ( A04ACB3029068688004A85A6 /* ReadShortcutView */, - 87E99CAE28FFF26A009B691F /* EditShortcutView.swift */, 4DAD635D292AB61700ABF8C1 /* UpdateShortcutView.swift */, 4D3DBB952934E31A00DE8160 /* ShowProfileView.swift */, ); @@ -461,8 +456,7 @@ isa = PBXGroup; children = ( A04ACB0F29044E52004A85A6 /* ExploreShortcutView */, - 87E99CAA28FFF256009B691F /* ExploreCategoryView.swift */, - A0F822B629164D2300AF4448 /* ShortcutsListView.swift */, + A0F822B629164D2300AF4448 /* ListCategoryShortcutView.swift */, ); path = ExploreShortcutViews; sourceTree = ""; @@ -500,13 +494,14 @@ F9CAEF822914855900224B0A /* Date+Extension.swift */, 8792478C2918CE450040D5C3 /* UINavigationContoller+Extension.swift */, A09CBA7D2922B36C00D31F5F /* String+Extension.swift */, - 878837492920D549009B3F54 /* Binding.swift */, + 878837492920D549009B3F54 /* Binding+Extension.swift */, A0DD085629276608008177BB /* URL+Extension.swift */, 8795A16D292AB841004B765F /* View+Extension.swift */, 8795A16F292AB945004B765F /* UIScreen+Extension.swift */, F9AC2BB92935D34C00165820 /* Image+Extension.swift */, A3439AFA2939B0E80043E273 /* UserDefaults+Extension.swift */, A3FF4F822979C09000FA9EEE /* LineBreaking+Extension.swift */, + F96D45BA29804057000C2441 /* EnvironmentValues+Extension.swift */, ); path = Extensions; sourceTree = ""; @@ -521,13 +516,15 @@ 87E99CC8290145B8009B691F /* ListShortcutView.swift */, 87E99CCA290145C4009B691F /* UserCurationCell.swift */, 87E99CCC290145CC009B691F /* AdminCurationCell.swift */, - 87E99CCE290145D5009B691F /* PaletteCell.swift */, - 87E99CD0290145DE009B691F /* PaletteView.swift */, 87E99CD22901465F009B691F /* ValidationCheckTextField.swift */, F94B432D2907088400987819 /* UserCurationListView.swift */, A3B263692909DFD200829DE1 /* CurationListView.swift */, 87276C372933F6AB00C92F4C /* CustomTextEditor.swift */, 87CFD8482939187200F97B86 /* NicknameTextField.swift */, + F96D45B62980301F000C2441 /* SubtitleTextView.swift */, + F91A72C0299915C500CA135A /* MoreCaptionTextView.swift */, + F96D45BC29816578000C2441 /* StickyHeader.swift */, + F91A72C22999160E00CA135A /* Alerter.swift */, ); path = Components; sourceTree = ""; @@ -552,7 +549,6 @@ isa = PBXGroup; children = ( 87E99C6F28F94EA6009B691F /* ShortcutTabView.swift */, - A04ACB0029027BDE004A85A6 /* TabRouter.swift */, ); path = TabView; sourceTree = ""; @@ -565,7 +561,6 @@ A04ACB0B29041CEE004A85A6 /* LovedShortcutView.swift */, A04ACB0929041CD8004A85A6 /* DownloadRankView.swift */, A04ACB0D29041D61004A85A6 /* CategoryView.swift */, - 87EDB96229082C7F009A750A /* ListCategoryView.swift */, 4DAD636F292BCB1000ABF8C1 /* CategoryCardView.swift */, ); path = ExploreShortcutView; @@ -608,7 +603,7 @@ F976E85029395B350088BBA1 /* ShareExtensionViewModel.swift */, A35DB3362927E8EB0011A28B /* CustomShareViewController.swift */, A35DB3382927E9630011A28B /* CustomShareNavigationController.swift */, - A3C5576B292BE084003907DC /* ShareExtensionWriteShortcutTitleView.swift */, + A3C5576B292BE084003907DC /* ShareExtensionWriteShortcutView.swift */, F9DB8EB82939853D00516CE1 /* ShareExtensionValidationTextField.swift */, F9DB8EBC293987BD00516CE1 /* ShareExtensionCustomTextEditor.swift */, F9DB8ED2293B4C3200516CE1 /* ShareExtensionTagTextField.swift */, @@ -828,11 +823,9 @@ F9CAEF8429148CDD00224B0A /* ReadAdminCurationView.swift in Sources */, F9AC2BB62935201C00165820 /* CheckUpdateVersion.swift in Sources */, F9131B6B2922D38D00868A0E /* Keyword.swift in Sources */, - 87EDB96329082C7F009A750A /* ListCategoryView.swift in Sources */, F94B432E2907088400987819 /* UserCurationListView.swift in Sources */, A04ACB34290686C7004A85A6 /* ReadShortcutContentView.swift in Sources */, A3FF0183291648A300384211 /* MailView.swift in Sources */, - 87E99CAF28FFF26A009B691F /* EditShortcutView.swift in Sources */, A0F822AC2910B8F100AF4448 /* ShortcutsZipViewModel.swift in Sources */, 87276C382933F6AB00C92F4C /* CustomTextEditor.swift in Sources */, 87E99CC429014572009B691F /* Color+Extension.swift in Sources */, @@ -845,13 +838,12 @@ 8792479B291BDF820040D5C3 /* SearchView.swift in Sources */, A3FF018E291ACFA500384211 /* WithdrawalView.swift in Sources */, 4D778A34290A53BA00C15AC4 /* Application+Extension.swift in Sources */, - 87E99CBF28FFF2AB009B691F /* WriteShortcutTagView.swift in Sources */, A3766B232904330300708F83 /* ReadUserCurationView.swift in Sources */, 87E606B0291062F900C3DA13 /* AppleAuthCoordinator.swift in Sources */, 8795A170292AB945004B765F /* UIScreen+Extension.swift in Sources */, A04ACB0A29041CD8004A85A6 /* DownloadRankView.swift in Sources */, - 87E99CD1290145DE009B691F /* PaletteView.swift in Sources */, 4DAD6370292BCB1000ABF8C1 /* CategoryCardView.swift in Sources */, + F96D45B72980301F000C2441 /* SubtitleTextView.swift in Sources */, 4D402E7B2979342800D9A825 /* RecentRegisteredView.swift in Sources */, 87E99CDB29042CCA009B691F /* Category.swift in Sources */, 8795A16E292AB841004B765F /* View+Extension.swift in Sources */, @@ -861,23 +853,23 @@ 87E606B629114F7D00C3DA13 /* WriteNicknameView.swift in Sources */, F9F4D36A2906E0B000DC8546 /* Navigationbar+Extension.swift in Sources */, A3B2636A2909DFD200829DE1 /* CurationListView.swift in Sources */, + 4D7D16072986BBD7008B3332 /* TextLiteral.swift in Sources */, 87E99CC128FFF2B5009B691F /* CategoryModalView.swift in Sources */, 87E606B829114FB200C3DA13 /* UserAuth.swift in Sources */, + F91A72C1299915C500CA135A /* MoreCaptionTextView.swift in Sources */, 4DAD635E292AB61700ABF8C1 /* UpdateShortcutView.swift in Sources */, 87E99C9F28FFF21B009B691F /* SettingView.swift in Sources */, A04ACB32290686AA004A85A6 /* ReadShortcutHeaderView.swift in Sources */, 87E99CA928FFF24F009B691F /* ExploreShortcutView.swift in Sources */, A04ACB082903DECC004A85A6 /* MyShortcutCardListView.swift in Sources */, 87E99CA128FFF225009B691F /* MyPageView.swift in Sources */, - A04ACB0129027BDE004A85A6 /* TabRouter.swift in Sources */, 8792478D2918CE450040D5C3 /* UINavigationContoller+Extension.swift in Sources */, - 87E99CCF290145D5009B691F /* PaletteCell.swift in Sources */, 87E99CC7290145AD009B691F /* ShortcutCell.swift in Sources */, - 87E99CAB28FFF256009B691F /* ExploreCategoryView.swift in Sources */, 8795A172292ABFDE004B765F /* ReadShortcutVersionView.swift in Sources */, 87E99CBB28FFF298009B691F /* IconModalView.swift in Sources */, 87E99C7028F94EA6009B691F /* ShortcutTabView.swift in Sources */, F99569182901DC4D0060AAEF /* Font+Extension.swift in Sources */, + F91A72C32999160E00CA135A /* Alerter.swift in Sources */, 87E99CAD28FFF261009B691F /* ReadShortcutView.swift in Sources */, A33F74AE2908D8C800B8D0D0 /* CheckBoxShortcutCell.swift in Sources */, 87E606B22910649B00C3DA13 /* SignInWithAppleView.swift in Sources */, @@ -885,11 +877,11 @@ F9136EB6293612310034AAB2 /* ShortcutsZipView.swift in Sources */, 87E99CB128FFF273009B691F /* WriteCurationSetView.swift in Sources */, 4D61A767291E1EE8000EF531 /* NavigationViewModel.swift in Sources */, + F96D45BD29816578000C2441 /* StickyHeader.swift in Sources */, 87E99CEE29080D33009B691F /* User.swift in Sources */, F976E82C29368E0D0088BBA1 /* Version.swift in Sources */, - 87E99CB928FFF291009B691F /* WriteShortcutTitleView.swift in Sources */, + 87E99CB928FFF291009B691F /* WriteShortcutView.swift in Sources */, 87E99CCD290145CC009B691F /* AdminCurationCell.swift in Sources */, - 87E99CBD28FFF2A1009B691F /* WriteShortcutdescriptionView.swift in Sources */, A04ACB0E29041D61004A85A6 /* CategoryView.swift in Sources */, 87E99CC9290145B8009B691F /* ListShortcutView.swift in Sources */, A3FF01862918552E00384211 /* AboutTeamView.swift in Sources */, @@ -899,15 +891,16 @@ 8795A174292ACA50004B765F /* ReadShortcutCommentView.swift in Sources */, A04ACB0C29041CEE004A85A6 /* LovedShortcutView.swift in Sources */, A3439AFB2939B0E80043E273 /* UserDefaults+Extension.swift in Sources */, + F96D45BB29804057000C2441 /* EnvironmentValues+Extension.swift in Sources */, A09CBA7E2922B36C00D31F5F /* String+Extension.swift in Sources */, 87E99CB528FFF282009B691F /* WriteCurationInfoView.swift in Sources */, F9DB8EBB293986E100516CE1 /* ShareExtensionViewModel.swift in Sources */, - 8788374A2920D549009B3F54 /* Binding.swift in Sources */, + 8788374A2920D549009B3F54 /* Binding+Extension.swift in Sources */, 87E99CCB290145C4009B691F /* UserCurationCell.swift in Sources */, F9724BBF292755E400860F8A /* Comment.swift in Sources */, 87E99CA328FFF22E009B691F /* ExploreCurationView.swift in Sources */, A3FF4F832979C09000FA9EEE /* LineBreaking+Extension.swift in Sources */, - A0F822B729164D2300AF4448 /* ShortcutsListView.swift in Sources */, + A0F822B729164D2300AF4448 /* ListCategoryShortcutView.swift in Sources */, 4D3DBB88292E67E600DE8160 /* EditNicknameView.swift in Sources */, 87E99CE82907C6E6009B691F /* Shortcuts.swift in Sources */, ); @@ -938,7 +931,7 @@ A3439AF529395A100043E273 /* UserAuth.swift in Sources */, A31F1846292A638700AF4A82 /* (null) in Sources */, F9DB8EB92939853D00516CE1 /* ShareExtensionValidationTextField.swift in Sources */, - A3C5576C292BE084003907DC /* ShareExtensionWriteShortcutTitleView.swift in Sources */, + A3C5576C292BE084003907DC /* ShareExtensionWriteShortcutView.swift in Sources */, A35DB3392927E9630011A28B /* CustomShareNavigationController.swift in Sources */, A31F1844292A637300AF4A82 /* Date+Extension.swift in Sources */, A3FC4756292A61B60058BF26 /* CategoryModalView.swift in Sources */, @@ -951,6 +944,7 @@ F9DB8EBD293987BD00516CE1 /* ShareExtensionCustomTextEditor.swift in Sources */, F976E85129395B350088BBA1 /* ShareExtensionViewModel.swift in Sources */, A3FC4753292A61AE0058BF26 /* IconModalView.swift in Sources */, + 4D7D16082986BBDE008B3332 /* TextLiteral.swift in Sources */, A3FC474F292A616D0058BF26 /* Font+Extension.swift in Sources */, A3FC475B292A61CE0058BF26 /* Category.swift in Sources */, A35DB3372927E8EB0011A28B /* CustomShareViewController.swift in Sources */, @@ -1121,6 +1115,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 1.2.1; + MARKETING_VERSION = 1.0.0; PRODUCT_BUNDLE_IDENTIFIER = com.happyanding.HappyAnding; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1163,6 +1158,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 1.2.1; + MARKETING_VERSION = 1.0.0; PRODUCT_BUNDLE_IDENTIFIER = com.happyanding.HappyAnding; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/HappyAnding/HappyAnding/Assets.xcassets/Colors/SystemColors/Error.colorset/Contents.json b/HappyAnding/HappyAnding/Assets.xcassets/Colors/SystemColors/Error.colorset/Contents.json index f1423e1f..653f4b6b 100644 --- a/HappyAnding/HappyAnding/Assets.xcassets/Colors/SystemColors/Error.colorset/Contents.json +++ b/HappyAnding/HappyAnding/Assets.xcassets/Colors/SystemColors/Error.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "0.239", - "green" : "0.306", - "red" : "0.922" + "blue" : "0x3D", + "green" : "0x4E", + "red" : "0xEB" } }, "idiom" : "universal" @@ -23,9 +23,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "0.271", - "green" : "0.333", - "red" : "0.922" + "blue" : "0x45", + "green" : "0x54", + "red" : "0xEB" } }, "idiom" : "universal" diff --git a/HappyAnding/HappyAnding/Extensions/Binding.swift b/HappyAnding/HappyAnding/Extensions/Binding+Extension.swift similarity index 100% rename from HappyAnding/HappyAnding/Extensions/Binding.swift rename to HappyAnding/HappyAnding/Extensions/Binding+Extension.swift diff --git a/HappyAnding/HappyAnding/Extensions/Color+Extension.swift b/HappyAnding/HappyAnding/Extensions/Color+Extension.swift index b842d50b..a7ab619f 100644 --- a/HappyAnding/HappyAnding/Extensions/Color+Extension.swift +++ b/HappyAnding/HappyAnding/Extensions/Color+Extension.swift @@ -38,41 +38,41 @@ extension Color { extension Color { // Semantic Color - static let Background_plus = Color(light: .Gray1, dark: .White) - static let Background_tabbar = Color(light: .White, dark: Color("Grey005")) - static let Background_list = Color(light:.White, dark:.Background) - static let Background_list_border = Color(light:.Gray1, dark:.White) + static let backgroundPlus = Color(light: .gray1, dark: .shortcutsZipWhite) + static let backgroundTabbar = Color(light: .shortcutsZipWhite, dark: Color("Grey005")) + static let backgroudList = Color(light: .shortcutsZipWhite, dark: .shortcutsZipBackground) + static let backgroudListBorder = Color(light: .gray1, dark: .shortcutsZipWhite) - static let Text_curation = Color(light: .Gray5, dark: .Background) - static let Text_icon = Color(light: .White, dark: .Gray6) + static let textCuration = Color(light: .gray5, dark: .shortcutsZipBackground) + static let textIcon = Color(light: .shortcutsZipWhite, dark: .gray6) - static let Text_Button = Color(light: .Background, dark: .Gray6) - static let Text_Button_Disable = Color(light: .White .opacity(0.8), dark: .Gray2.opacity(0.8)) + static let textButton = Color(light: .shortcutsZipBackground, dark: .gray6) + static let textButtonDisable = Color(light: .shortcutsZipWhite .opacity(0.8), dark: .gray2.opacity(0.8)) - static let Category_Pick_Fill = Color(light:.White, dark:.Primary) - static let Category_Pick_Text = Color(light:.Primary, dark:.Gray6) + static let categoryPickFill = Color(light: .shortcutsZipWhite, dark: .shortcutsZipPrimary) + static let categoryPickText = Color(light: .shortcutsZipPrimary, dark: .gray6) - static let Tag_Pick_Background = Color(light: Color.clear, dark:.Primary) - static let Tag_Background = Color(light: .Background, dark: .Primary) - static let Tag_Text = Color(light: .Primary, dark: .white) + static let tagPickBackground = Color(light: Color.clear, dark: .shortcutsZipPrimary) + static let tagBackground = Color(light: .shortcutsZipBackground, dark: .shortcutsZipPrimary) + static let tagText = Color(light: .shortcutsZipPrimary, dark: .white) } extension Color { ///System Colors - static let Background = Color("Grey020") - static let White = Color("Grey010") - static let Primary = Color("Primary") - static let Error = Color("Error") - static let Danger = Color("Danger") - static let Success = Color("Success") + static let shortcutsZipBackground = Color("Grey020") + static let shortcutsZipWhite = Color("Grey010") + static let shortcutsZipPrimary = Color("Primary") + static let shortcutsZipError = Color("Error") + static let shortcutsZipDanger = Color("Danger") + static let shortcutsZipSuccess = Color("Success") ///Text Colors - static let Gray1 = Color("Grey030") - static let Gray2 = Color("Grey040") - static let Gray3 = Color("Grey050") - static let Gray4 = Color("Grey060") - static let Gray5 = Color("Grey070") - static let Gray6 = Color("Grey080") + static let gray1 = Color("Grey030") + static let gray2 = Color("Grey040") + static let gray3 = Color("Grey050") + static let gray4 = Color("Grey060") + static let gray5 = Color("Grey070") + static let gray6 = Color("Grey080") //gradient사용하는 곳에서 Color.fetchGradient(color: "Red")와 같이 사용해주세요 //컬러명은 숫자를 제외하고 UpperCamelCase로 입력해주세요 @@ -81,26 +81,29 @@ extension Color { return LinearGradient(colors: colors, startPoint: .topLeading, endPoint: .bottomTrailing) } + static func fetchDefualtGradient() -> LinearGradient { + LinearGradient(colors: [Color.gray1], startPoint: .topLeading, endPoint: .bottomTrailing) + } } extension UIColor { - static var Gray4: UIColor { + static var gray4: UIColor { guard let color = UIColor(named: "Grey060") else { return .label } return color } - static var Gray5: UIColor { + static var gray5: UIColor { guard let color = UIColor(named: "Grey070") else { return .label } return color } - static var Background: UIColor { + static var shortcutsZipBackground: UIColor { guard let color = UIColor(named: "Grey020") else { return .label } return color } - static var Primary: UIColor { + static var shortcutsZipPrimary: UIColor { guard let color = UIColor(named: "Primary") else { return .label } return color } - static var PrimaryOpacity: UIColor { + static var shortcutsZipPrimaryOpacity: UIColor { guard let color = UIColor(named: "Primary") else { return .label } return color.withAlphaComponent(0.3) } diff --git a/HappyAnding/HappyAnding/Extensions/EnvironmentValues+Extension.swift b/HappyAnding/HappyAnding/Extensions/EnvironmentValues+Extension.swift new file mode 100644 index 00000000..653f6fb6 --- /dev/null +++ b/HappyAnding/HappyAnding/Extensions/EnvironmentValues+Extension.swift @@ -0,0 +1,15 @@ +// +// Alert+Extension.swift +// HappyAnding +// +// Created by 전지민 on 2023/01/25. +// + +import SwiftUI + +extension EnvironmentValues { + var loginAlertKey: Alerter { + get { return self[LoginAlertKey.self] } + set { self[LoginAlertKey.self] = newValue } + } +} diff --git a/HappyAnding/HappyAnding/Extensions/Image+Extension.swift b/HappyAnding/HappyAnding/Extensions/Image+Extension.swift index 37b12911..63b6127a 100644 --- a/HappyAnding/HappyAnding/Extensions/Image+Extension.swift +++ b/HappyAnding/HappyAnding/Extensions/Image+Extension.swift @@ -10,7 +10,7 @@ import SwiftUI extension Image { func setCellIcon() -> some View { self - .foregroundColor(.Gray4) + .foregroundColor(.gray4) .font(.system(size: 24, weight: .medium)) .frame(height: 32) } diff --git a/HappyAnding/HappyAnding/Extensions/Navigationbar+Extension.swift b/HappyAnding/HappyAnding/Extensions/Navigationbar+Extension.swift index adca18da..a06979f1 100644 --- a/HappyAnding/HappyAnding/Extensions/Navigationbar+Extension.swift +++ b/HappyAnding/HappyAnding/Extensions/Navigationbar+Extension.swift @@ -22,7 +22,7 @@ struct NavigationBarColorModifier: ViewModifier where Background: Vi appearance.configureWithOpaqueBackground() appearance.backgroundColor = UIColor.clear appearance.shadowColor = .clear - appearance.largeTitleTextAttributes = [.font : UIFont.LargeTitle, .foregroundColor: UIColor(.Gray5)] + appearance.largeTitleTextAttributes = [.font : UIFont.LargeTitle, .foregroundColor: UIColor(.gray5)] //back button color 지정 let backItemAppearance = UIBarButtonItemAppearance() backItemAppearance.normal.titleTextAttributes = [ @@ -32,14 +32,14 @@ struct NavigationBarColorModifier: ViewModifier where Background: Vi //indicator color 지정 let image = UIImage(systemName: "chevron.backward")? - .withTintColor(UIColor(.Gray4), renderingMode: .alwaysOriginal) + .withTintColor(UIColor(.gray4), renderingMode: .alwaysOriginal) appearance.setBackIndicatorImage(image, transitionMaskImage: image) let scrollAppearance = UINavigationBarAppearance() scrollAppearance.configureWithDefaultBackground() - scrollAppearance.backgroundColor = UIColor(Color.White) + scrollAppearance.backgroundColor = UIColor(Color.shortcutsZipWhite) scrollAppearance.shadowColor = .clear - scrollAppearance.largeTitleTextAttributes = [.font : UIFont.LargeTitle, .foregroundColor: UIColor(.Gray5)] + scrollAppearance.largeTitleTextAttributes = [.font : UIFont.LargeTitle, .foregroundColor: UIColor(.gray5)] scrollAppearance.backButtonAppearance = backItemAppearance scrollAppearance.setBackIndicatorImage(image, transitionMaskImage: image) diff --git a/HappyAnding/HappyAnding/Extensions/View+Extension.swift b/HappyAnding/HappyAnding/Extensions/View+Extension.swift index a2d60bd0..ec4b0946 100644 --- a/HappyAnding/HappyAnding/Extensions/View+Extension.swift +++ b/HappyAnding/HappyAnding/Extensions/View+Extension.swift @@ -7,6 +7,7 @@ import SwiftUI +//MARK: - 제스쳐 extension View { func readSize(onChange: @escaping (CGSize) -> Void) -> some View { background( @@ -45,6 +46,7 @@ extension View { } } +//MARK: - 둥근 모서리 struct RoundedCorner: Shape { var radius: CGFloat = .infinity diff --git a/HappyAnding/HappyAnding/Model/Category.swift b/HappyAnding/HappyAnding/Model/Category.swift index 15cbf271..2cecc2a0 100644 --- a/HappyAnding/HappyAnding/Model/Category.swift +++ b/HappyAnding/HappyAnding/Model/Category.swift @@ -96,7 +96,7 @@ enum Category: String, CaseIterable { case .photo: return "사진 및 비디오" case .decoration: - return "데코레이션/꾸미기" + return "데코레이션" case .utility: return "유틸리티" case .sns: diff --git a/HappyAnding/HappyAnding/Model/Shortcuts.swift b/HappyAnding/HappyAnding/Model/Shortcuts.swift index 8489b46b..696163fd 100644 --- a/HappyAnding/HappyAnding/Model/Shortcuts.swift +++ b/HappyAnding/HappyAnding/Model/Shortcuts.swift @@ -27,14 +27,6 @@ struct Shortcuts: Identifiable, Codable, Equatable, Hashable { var curationIDs: [String] var updateDescription: [String] = [""] - enum CodingKeys: String, CodingKey { - case id, sfSymbol, color, title, subtitle - case description = "description" - case category, requiredApp, date, numberOfLike, numberOfDownload, author, shortcutRequirements, downloadLink - case curationIDs - case updateDescription - } - var dictionary: [String: Any] { let data = (try? JSONEncoder().encode(self)) ?? Data() return (try? JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any]) ?? [:] diff --git a/HappyAnding/HappyAnding/TextLiteral.swift b/HappyAnding/HappyAnding/TextLiteral.swift new file mode 100644 index 00000000..913fe1f8 --- /dev/null +++ b/HappyAnding/HappyAnding/TextLiteral.swift @@ -0,0 +1,228 @@ +// +// TextLiteral.swift +// HappyAnding +// +// Created by kimjimin on 2023/01/29. +// + +import Foundation + +enum TextLiteral { + + // MARK: - AnyWhere + static let more: String = "더보기" + static let loginTitle: String = "로그인을 먼저 진행해주세요" + static let loginMessage: String = "이 기능은 로그인 후 사용할 수 있는 기능이에요" + static let loginAction: String = "로그인하기" + static let cancel: String = "취소" + static let next: String = "다음" + static let upload: String = "업로드" + static let close: String = "닫기" + static let done: String = "완료" + static let edit: String = "편집" + static let update: String = "업데이트" + static let later: String = "나중에" + static let share: String = "공유" + static let delete: String = "삭제" + static let withdrawnUser: String = "탈퇴한 사용자" + static let defaultUser: String = "user" + + static let appStoreUrl: String = "itms-apps://itunes.apple.com/app/6444001181" + + // MARK: - ExploreShortcutView + static let exploreShortcutViewTitle: String = "단축어 둘러보기" + + // MARK: - RecentRegisteredView + static let recentRegisteredViewTitle: String = "최신 단축어" + + // MARK: - LovedShortcutView + static let lovedShortcutViewTitle: String = "사랑받는 단축어" + + // MARK: - DownloadRankView + static let downloadRankViewTitle: String = "다운로드 순위" + + // MARK: - CategoryView + static let categoryViewTitle: String = "카테고리 모아보기" + static let categoryViewUnfold: String = "펼치기" + static let categoryViewFold: String = "접기" + + // MARK: - MyShortcutCardListView + static let myShortcutCardListViewTitle: String = "내가 작성한 단축어" + + // MARK: - ValidationCheckTextField + static let validationCheckTextFieldInvalid: String = "단축어 링크가 아니에요" + static let validationCheckTextFieldExcess: String = "입력할 수 있는 문자 수를 초과했어요" + static let validationCheckTextFieldOption: String = "(선택입력)" + static let validationCheckTextFieldPrefix: String = "https://www.icloud.com/shortcuts/" + + // MARK: - UserCurationListView + static let userCurationListViewAdd: String = "추천 모음집 작성" + + // MARK: - NicknameTextField + static let nicknameTextFieldLength: String = "최대 8자까지 입력할 수 있어요" + static let nicknameTextFieldEmoticon: String = "사용할 수 없는 문자가 포함되어 있어요" + static let nicknameTextFieldSpace: String = "공백 없이 한글 ,숫자, 영문만 입력할 수 있어요" + static let nicknameTextFieldDuplicateTitle: String = "닉네임 중복 확인" + static let nicknameTextFieldDuplicateSuccessMessage: String = "사용할 수 있는 닉네임이에요" + static let nicknameTextFieldDuplicateFailMessage: String = "이미 사용 중인 닉네임이에요" + static let nicknameTextFieldDuplicateSuccessLabel: String = "확인" + static let nicknameTextFieldDuplicateFailLabel: String = "다시 입력하기" + static let nicknameTextFieldTitle: String = "닉네임 (최대 8글자)" + static let nicknameTextFieldDuplicateCheck: String = "중복확인" + + // MARK: - WriteShortcutTitleView + static let writeShortcutViewNameTitle: String = "단축어 이름" + static let writeShortcutViewNamePlaceholder: String = "단축어 이름을 입력하세요" + static let writeShortcutViewLinkTitle: String = "단축어 링크" + static let writeShortcutViewLinkPlaceholder: String = "단축어 링크를 입력하세요" + static let writeShortcutViewOneLineTitle: String = "한 줄 설명" + static let writeShortcutViewOneLinePlaceholder: String = "단축어의 핵심 기능을 입력하세요" + static let writeShortcutViewMultiLineTitle: String = "상세 설명" + static let writeShortcutViewMultiLinePlaceholder: String = "단축어 사용법, 필수적으로 요구되는 사항 등 단축어를 이용하기 위해 필요한 정보를 입력하세요" + static let writeShortcutViewEdit: String = "단축어 편집" + static let writeShortcutViewPost: String = "단축어 작성" + static let writeShortcutViewCategoryTitle: String = "카테고리" + static let writeShortcutViewCategoryDescription: String = "최대 3개" + static let writeShortcutViewCategoryCell: String = "카테고리 선택" + static let writeShortcutViewRequiredAppDescription: String = "선택" + static let writeShortcutViewRequiredAppsTitle: String = "단축어 사용에 필요한 앱" + static let writeShortcutViewRequiredAppInformation: String = "해당 단축어를 사용하기 위해 필수로 다운로드해야 하는 앱을 입력해주세요" + static let writeShortcutViewRequiredAppCell: String = "앱 추가" + + // MARK: - IconModalView + static let iconModalViewTitle: String = "아이콘" + static let iconModalViewColor: String = "색상" + static let iconModalViewIcon: String = "기호" + + // MARK: - CategoryModalView + static let categoryModalViewTitle: String = "카테고리" + + // MARK: - ReadShortcutView + static let readShortcutViewBasicTabTitle: String = "기본 정보" + static let readShortcutViewVersionTabTitle: String = "버전 정보" + static let readShortcutViewCommentTabTitle: String = "댓글" + static let readShortcutViewDeletionTitle: String = "단축어 삭제" + static let readShortcutViewDeletionMessage: String = "단축어를 삭제하시겠어요?" + static let readShortcutViewDeleteFixes: String = "수정사항을 삭제하시겠어요?" + static let readShortcutViewKeepFixes: String = "계속 작성" + static let readShortcutViewCommentDescriptionBeforeLogin: String = "로그인 후 댓글을 작성할 수 있어요" + static let readShortcutViewCommentDescription: String = "댓글을 입력하세요" + + // MARK: - ReadShortcutContentView + static let readShortcutContentViewDescription: String = "단축어 설명" + static let readShortcutContentViewCategory: String = "카테고리" + static let readShortcutContentViewRequiredApps: String = "단축어 사용에 필요한 앱" + static let readShortcutContentViewRequirements: String = "단축어 사용을 위한 요구사항" + + // MARK: - ReadShortcutVersionView + static let readShortcutVersionViewNoUpdates: String = "업데이트된 버전이 없어요" + static let readShortcutVersionViewUpdateContent: String = "업데이트 내용" + static let readShortcutVersionViewDownloadPreviousVersion: String = "이전 버전 다운로드" + + // MARK: - ReadShortcutCommentView + static let readShortcutCommentViewNoComments: String = "등록된 댓글이 없어요" + static let readShortcutCommentViewDeletionTitle: String = "댓글 삭제" + static let readShortcutCommentViewDeletionMessage: String = "답글도 함께 삭제돼요. 댓글을 삭제하시겠어요?" + static let readShortcutCommentViewReply: String = "답글" + static let readShortcutCommentViewEdit: String = "수정" + + // MARK: - UpdateShortcutView + static let updateShortcutViewLinkTitle: String = "업데이트된 단축어 링크" + static let updateShortcutViewLinkPlaceholder: String = "업데이트된 단축어 링크를 입력하세요" + static let updateShortcutViewDescriptionTitle: String = "업데이트 설명" + static let updateShortcutViewDescriptionPlaceholder: String = "업데이트된 내용을 입력하세요" + + // MARK: - ShowProfileView + static let showProfileViewShortcutTabTitle: String = "작성한 단축어" + static let showProfileViewCurationTabTitle: String = "작성한 추천 모음집" + static let showProfileViewNoShortcuts: String = "아직 단축어를 작성하지 않았어요" + static let showProfileViewNoCurations: String = "아직 추천 모음집을 작성하지 않았어요" + + // MARK: - ExploreCurationView + static let exploreCurationViewTitle: String = "추천 모음집 둘러보기" + static let exploreCurationViewAdminCurations: String = "숏컷집 추천 모음집" + static let exploreCurationViewUserCurations: String = "사용자 추천 모음집" + + // MARK: - ReadUserCurationView + static let readUserCurationViewDeletionTitle: String = "추천 모음집 삭제" + static let readUserCurationViewDeletionMessage: String = "추천 모음집을 삭제하시겠어요?" + + // MARK: - WriteCurationSetView + static let writeCurationSetViewNoShortcuts: String = "아직 선택할 수 있는 단축어가 없어요\n단축어를 업로드하거나 좋아요를 눌러주세요" + static let writeCurationSetViewEdit: String = "추천 모음집 편집" + static let writeCurationSetViewPost: String = "추천 모음집 작성" + static let writeCurationSetViewSelectionTitle: String = "단축어 선택" + static let writeCurationSetViewSelectionDescription: String = "최대 10개" + static let writeCurationSetViewSelectionInformation: String = "추천 모음집을 위한 단축어 목록은 '내가 업로드한 단축어'와 '좋아요를 누른 단축어'로 구성되어 있어요." + + // MARK: - WriteCurationInfoView + static let writeCurationInfoViewNameTitle: String = "추천 모음집 이름" + static let writeCurationInfoViewNamePlaceholder: String = "추천 모음집의 이름을 입력하세요" + static let writeCurationInfoViewDescriptionTitle: String = "추천 모음집 설명" + static let writeCurationInfoViewDescriptionPlaceholder: String = "추천 모음집에 대한 설명을 입력하세요" + static let writeCurationInfoViewEdit: String = "추천 모음집 편집" + static let wrietCurationInfoViewPost: String = "추천 모음집 작성" + + // MARK: - WithdrawalView + static let withdrawalViewTitle: String = "탈퇴하기" + static let withdrawalViewDeleteTitle: String = "탈퇴 시 삭제되는 항목" + static let withdrawalViewDeleteContent: String = "로그인 정보 / 닉네임 / 좋아요한 단축어 목록 / 다운로드한 단축어 목록" + static let withdrawalViewNoDeleteTitle: String = "탈퇴 시 삭제되지 않는 항목" + static let withdrawalViewNoDeleteContent: String = "작성한 단축어 / 작성한 추천 모음집" + static let withdrawalViewHeadline: String = "ShortcutsZip에서 탈퇴 시 다음과 같이 사용자 데이터가 처리됩니다." + static let withdrawalViewAgree: String = "위의 데이터 처리방법에 동의합니다." + static let withdrawalViewButton: String = "사용자 재인증 후 탈퇴하기" + static let withdrawalViewAlertTitle: String = "탈퇴하기" + static let withdrawalViewAlertMessage: String = "ShortcutsZip에서 탈퇴하시겠습니까?" + static let withdrawalViewAlertAction: String = "탈퇴" + + // MARK: - SettingView + static let settingViewVersion: String = "버전 정보" + static let settingViewVersionNumber: String = "1.1.0" + static let settingViewOpensourceLicense: String = "오픈소스 라이선스" + static let settingViewPrivacyPolicy: String = "개인정보 처리방침" + static let settingViewPrivacyPolicyURL: String = "https://noble-satellite-574.notion.site/60d8fa2f417c40cca35e9c784f74b7fd" + static let settingViewContact: String = "개발자에게 메일 보내기" + static let settingViewContactMessage: String = "문의사항은 shortcutszip@gmail.com 으로 메일 보내주세요" + static let settingViewLogin: String = "로그인" + static let settingViewLogout: String = "로그아웃" + static let settingViewLogoutMessage: String = "로그아웃 하시겠습니까?" + static let settingViewWithdrawal: String = "탈퇴하기" + + // MARK: - SignInWithAppleView + static let signInWithAppleViewTitle: String = "ShortcutsZip" + static let signInWithAppleViewSubTitle: String = "편리한 단축어 공유 플랫폼" + static let signInWithAppleViewSignInWithApple: String = "Apple로 로그인" + static let signInWithAppleViewUseWithoutSignIn: String = "로그인 없이 둘러보기" + + // MARK: - MyPageView + static let myPageViewTitle: String = "프로필" + static let myPageViewMyCuration: String = "내가 작성한 추천 모음집" + static let myPageViewLikedShortcuts: String = "좋아요한 단축어" + static let myPageViewDownloadedShortcuts: String = "다운로드한 단축어" + + // MARK: - MailView + static let mailViewReceiver: String = "shortcutszip@gmail.com" + static let mailViewSubject: String = "🎤 ShortcutsZip 개발자에게 문의드립니다" + + // MARK: - EditNicknameView + static let editNicknameViewTitle: String = "닉네임 수정" + static let editNicknameViewHeadline: String = "닉네임을 수정해주세요" + + // MARK: - WriteNicknameView + static let writeNicknameViewHeadline: String = "닉네임을 입력해주세요" + static let writeNicknameViewStart: String = "시작하기" + + // MARK: - SearchView + static let searchViewPrompt: String = "제목 또는 관련앱으로 검색하세요" + static let searchViewRecommendedKeyword: String = "추천 검색어" + static let searchViewProposal: String = "단축어 제안하기" + static let searchViewProposalURL: String = "https://docs.google.com/forms/d/e/1FAIpQLScQc3KeYjDGCE-C2YRU-Hwy2XNy5bt89KVX1OMUzRiySaMX1Q/viewform" + + //MARK: - CustomShareViewController + static let customShareViewControllerSignInAlertTitle: String = "로그인을 먼저 진행해주세요" + static let customShareViewControllerSignInAlertMessage: String = "이 기능은 로그인 후 사용할 수 있는 기능이에요" + static let customShareViewControllerLinkVaildAlertTitle: String = "잘못된 접근이에요" + static let customShareViewControllerLinkVaildAlertMessage: String = "해당 링크는 ShortcutsZip으로 공유할 수 없어요" + static let customShareViewControllerCheck: String = "확인" +} diff --git a/HappyAnding/HappyAnding/ViewModel/ShortcutsZipViewModel.swift b/HappyAnding/HappyAnding/ViewModel/ShortcutsZipViewModel.swift index a3132f6b..a06aa063 100644 --- a/HappyAnding/HappyAnding/ViewModel/ShortcutsZipViewModel.swift +++ b/HappyAnding/HappyAnding/ViewModel/ShortcutsZipViewModel.swift @@ -17,7 +17,7 @@ import FirebaseAuth */ class ShortcutsZipViewModel: ObservableObject { - var userAuth = UserAuth.shared + @AppStorage("signInStatus") var signInStatus = false @Published var userInfo: User? // 유저정보 @@ -27,9 +27,8 @@ class ShortcutsZipViewModel: ObservableObject { @Published var shortcutsMadeByUser: [Shortcuts] = [] // 유저가 만든 숏컷배열 @Published var sortedShortcutsByDownload: [Shortcuts] = [] // 다운로드 수에 의해 정렬된 숏컷 @Published var sortedShortcutsByLike: [Shortcuts] = [] // 다운로드 수에 의해 정렬된 숏컷 + @Published var shortcutsInCategory: [[Shortcuts]] = [[Shortcuts]].init(repeating: [], count: Category.allCases.count) // Category에서 사용할 숏컷 배열 - @Published var isFirstFetchInCategory = [Bool] (repeating: true, count: Category.allCases.count) //카테고리를 리스트 첫 fetch여부 - @Published var isLastFetchInCategory = [Bool] (repeating: false, count: Category.allCases.count) //카테고리를 리스트 마지막 fetch여부 @Published var curationsMadeByUser: [Curation] = [] // 유저가 만든 큐레이션배열 @Published var userCurations: [Curation] = [] @@ -42,11 +41,12 @@ class ShortcutsZipViewModel: ObservableObject { static let share = ShortcutsZipViewModel() private let db = Firestore.firestore() + var allShortcuts: [Shortcuts] = [] + var userAuth = UserAuth.shared + let numberOfPageLimit = 10 let minimumOfLike = 5 - var allShortcuts: [Shortcuts] = [] - init() { fetchUser(userID: self.currentUser(), isCurrentUser: true) { user in self.userInfo = user @@ -107,7 +107,7 @@ class ShortcutsZipViewModel: ObservableObject { } -//MARK: - 데이터를 받아오는 함수들 + //MARK: - 데이터를 받아오는 함수들 //MARK: - 단축어 @@ -404,11 +404,10 @@ class ShortcutsZipViewModel: ObservableObject { } return Array(relatedCurations) } - - +} //MARK: - 저장, 편집 관련 함수 - +extension ShortcutsZipViewModel { //TODO: Error 처리 필요 func setData(model: Any) { @@ -426,6 +425,34 @@ class ShortcutsZipViewModel: ObservableObject { } } + //MARK: 단축어 수정 시 단축어 업데이트하는 함수 + func updateShortcut(existingCategory: [String], newCategory: [String], shortcut: Shortcuts) { + var newCategory = newCategory + existingCategory.forEach { category in + if !shortcut.category.contains(category) { + newCategory.removeAll(where: { $0 == category }) + self.shortcutsInCategory[Category(rawValue: category)!.index].removeAll(where: { $0.id == shortcut.id }) + } else { + newCategory.removeAll(where: { $0 == category }) + if let index = self.shortcutsInCategory[Category(rawValue: category)!.index].firstIndex(where: { $0.id == shortcut.id}) { + self.shortcutsInCategory[Category(rawValue: category)!.index][index] = shortcut + } + } + } + + //TODO: 셀정보에 변경사항이 있을 경우에만 함수를 호출하도록 변경 필요 + self.updateShortcutInCuration( + shortcutCell: ShortcutCellModel( + id: shortcut.id, + sfSymbol: shortcut.sfSymbol, + color: shortcut.color, + title: shortcut.title, + subtitle: shortcut.subtitle, + downloadLink: shortcut.downloadLink.last! + ), + curationIDs: shortcut.curationIDs + ) + } //MARK: 단축어 수정 시 해당 단축어가 포함된 큐레이션 서버 데이터를 업데이트하는 함수 -> 단축어 정보 업데이트 func updateShortcutInCuration(shortcutCell: ShortcutCellModel, curationIDs: [String]) { @@ -546,9 +573,34 @@ class ShortcutsZipViewModel: ObservableObject { } } + //MARK: 새로운 큐레이션 추가하는 함수 + func addCuration(curation: Curation, isEdit: Bool, deletedShortcutCells: [ShortcutCellModel]) { + var curation = curation + var deletedShortcutCells = deletedShortcutCells + + if isEdit { + curation.shortcuts.forEach { shortcutCell in + deletedShortcutCells.removeAll(where: { $0.id == shortcutCell.id }) + } + } + + curation.shortcuts = curation.shortcuts.sorted { $0.title < $1.title } + curation.author = currentUser() + setData(model: curation) + updateShortcutCurationID( + shortcutCells: curation.shortcuts, + curationID: curation.id, + isEdit: isEdit, + deletedShortcutCells: deletedShortcutCells + ) + if let index = userCurations.firstIndex(where: { $0.id == curation.id }) { + userCurations[index] = curation + } + } +} //MARK: - 삭제 관련 함수 - +extension ShortcutsZipViewModel { //TODO: Error 처리 필요 func deleteData(model: Any) { @@ -620,8 +672,10 @@ class ShortcutsZipViewModel: ObservableObject { } } - +} + //MARK: - 유저 관련 함수 +extension ShortcutsZipViewModel { //MARK: 로그인 정보 제거 @@ -718,99 +772,101 @@ class ShortcutsZipViewModel: ObservableObject { } } } - +} + // MARK: - 검색 관련 함수 +extension ShortcutsZipViewModel { + + //MARK: 연관 앱으로 단축어 검색 + func searchShortcutByRequiredApp(word: String, completionHandler: @escaping ([Shortcuts]) -> ()) { + var shortcuts: [Shortcuts] = [] - //MARK: 연관 앱으로 단축어 검색 - func searchShortcutByRequiredApp(word: String, completionHandler: @escaping ([Shortcuts]) -> ()) { - var shortcuts: [Shortcuts] = [] - - var query: Query! - - query = db.collection("Shortcut") - .whereField("requiredApp", arrayContains: word) - .order(by: "requiredApp", descending: true) - - query.getDocuments { (querySnapshot, error) in - if let error { - print("Error getting documents: \(error)") - } else { - guard let documents = querySnapshot?.documents else { return } - let decoder = JSONDecoder() - - for document in documents { - do { - let data = document.data() - let jsonData = try JSONSerialization.data(withJSONObject: data) - let shortcut = try decoder.decode(Shortcuts.self, from: jsonData) - shortcuts.append(shortcut) - } catch let error { - print("error: \(error)") - } + var query: Query! + + query = db.collection("Shortcut") + .whereField("requiredApp", arrayContains: word) + .order(by: "requiredApp", descending: true) + + query.getDocuments { (querySnapshot, error) in + if let error { + print("Error getting documents: \(error)") + } else { + guard let documents = querySnapshot?.documents else { return } + let decoder = JSONDecoder() + + for document in documents { + do { + let data = document.data() + let jsonData = try JSONSerialization.data(withJSONObject: data) + let shortcut = try decoder.decode(Shortcuts.self, from: jsonData) + shortcuts.append(shortcut) + } catch let error { + print("error: \(error)") } - completionHandler(shortcuts) } + completionHandler(shortcuts) } } + } + + //MARK: 제목으로 단축어 검색 + ///prefix기준으로만 검색이 가능 + func searchShortcutByTitlePrefix(keyword: String, completionHandler: @escaping ([Shortcuts]) -> ()) { + var shortcuts: [Shortcuts] = [] - //MARK: 제목으로 단축어 검색 - ///prefix기준으로만 검색이 가능 - func searchShortcutByTitlePrefix(keyword: String, completionHandler: @escaping ([Shortcuts]) -> ()) { - var shortcuts: [Shortcuts] = [] - - var query: Query! - - query = db.collection("Shortcut") - .whereField("title", isGreaterThanOrEqualTo: keyword) - .whereField("title", isLessThanOrEqualTo: keyword + "\u{f8ff}") - - query.getDocuments { (querySnapshot, error) in - if let error { - print("Error getting documents: \(error)") - } else { - guard let documents = querySnapshot?.documents else { return } - let decoder = JSONDecoder() - - for document in documents { - do { - let data = document.data() - let jsonData = try JSONSerialization.data(withJSONObject: data) - let shortcut = try decoder.decode(Shortcuts.self, from: jsonData) - shortcuts.append(shortcut) - } catch let error { - print("error: \(error)") - } + var query: Query! + + query = db.collection("Shortcut") + .whereField("title", isGreaterThanOrEqualTo: keyword) + .whereField("title", isLessThanOrEqualTo: keyword + "\u{f8ff}") + + query.getDocuments { (querySnapshot, error) in + if let error { + print("Error getting documents: \(error)") + } else { + guard let documents = querySnapshot?.documents else { return } + let decoder = JSONDecoder() + + for document in documents { + do { + let data = document.data() + let jsonData = try JSONSerialization.data(withJSONObject: data) + let shortcut = try decoder.decode(Shortcuts.self, from: jsonData) + shortcuts.append(shortcut) + } catch let error { + print("error: \(error)") } - completionHandler(shortcuts) } + completionHandler(shortcuts) } } + } //MARK: 키워드 받아오는 함수 - func fetchKeyword(completionHandler: @escaping (Keyword)->()) { - var _: [String] = [] - db.collection("Keyword").getDocuments { querySnapshot, error in - if let error { - print("Error getting documents: \(error)") - } else { - guard let documents = querySnapshot?.documents else { return } - let decoder = JSONDecoder() - for document in documents { - do { - let data = document.data() - let jsonData = try JSONSerialization.data(withJSONObject: data) - let keyword = try decoder.decode(Keyword.self, from: jsonData) - completionHandler(keyword) - } catch let error { - print("error: \(error)") - } + func fetchKeyword(completionHandler: @escaping (Keyword)->()) { + db.collection("Keyword").getDocuments { querySnapshot, error in + if let error { + print("Error getting documents: \(error)") + } else { + guard let documents = querySnapshot?.documents else { return } + let decoder = JSONDecoder() + for document in documents { + do { + let data = document.data() + let jsonData = try JSONSerialization.data(withJSONObject: data) + let keyword = try decoder.decode(Keyword.self, from: jsonData) + completionHandler(keyword) + } catch let error { + print("error: \(error)") } } } } - + } +} + //MARK: - 댓글 관련 함수 - +extension ShortcutsZipViewModel { //MARK: 모든 댓글을 가져오는 함수 func fetchCommentAll(completionHandler: @escaping ([Comments]) -> ()) { diff --git a/HappyAnding/HappyAnding/Views/Components/AdminCurationCell.swift b/HappyAnding/HappyAnding/Views/Components/AdminCurationCell.swift index 5a222818..0a5f5dfd 100644 --- a/HappyAnding/HappyAnding/Views/Components/AdminCurationCell.swift +++ b/HappyAnding/HappyAnding/Views/Components/AdminCurationCell.swift @@ -41,11 +41,11 @@ struct AdminCurationCell: View { VStack(alignment: .leading, spacing: 4) { Text(adminCuration.title) .Title1() - .foregroundColor(.Text_curation) + .foregroundColor(.textCuration) .lineLimit(1) Text(adminCuration.subtitle.replacingOccurrences(of: "\\n", with: "\n")) .Body2() - .foregroundColor(.Text_curation) + .foregroundColor(.textCuration) .lineLimit(2) .multilineTextAlignment(.leading) } diff --git a/HappyAnding/HappyAnding/Views/Components/Alerter.swift b/HappyAnding/HappyAnding/Views/Components/Alerter.swift new file mode 100644 index 00000000..c885313e --- /dev/null +++ b/HappyAnding/HappyAnding/Views/Components/Alerter.swift @@ -0,0 +1,17 @@ +// +// SwiftUIView.swift +// HappyAnding +// +// Created by 전지민 on 2023/02/12. +// + +import SwiftUI + +class Alerter: ObservableObject { + @Published var isPresented = false +} + +struct LoginAlertKey: EnvironmentKey { + static let defaultValue = Alerter() +} + diff --git a/HappyAnding/HappyAnding/Views/Components/CurationListView.swift b/HappyAnding/HappyAnding/Views/Components/CurationListView.swift index 36b9ea3c..481c14d4 100644 --- a/HappyAnding/HappyAnding/Views/Components/CurationListView.swift +++ b/HappyAnding/HappyAnding/Views/Components/CurationListView.swift @@ -10,6 +10,7 @@ import SwiftUI struct CurationListView: View { @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel + @State var data: NavigationListCurationType var body: some View { @@ -21,12 +22,12 @@ struct CurationListView: View { navigationParentView: self.data.navigationParentView) NavigationLink(value: data) { UserCurationCell(curation: curation, - navigationParentView: self.data.navigationParentView, - lineLimit: 2) + lineLimit: 2, + navigationParentView: self.data.navigationParentView) } } } - .background(Color.Background.ignoresSafeArea(.all, edges: .all)) + .background(Color.shortcutsZipBackground.ignoresSafeArea(.all, edges: .all)) .onAppear { if self.data.type == .personalCuration { self.data.curation = shortcutsZipViewModel.personalCurations @@ -40,22 +41,16 @@ struct CurationListView: View { var listHeader: some View { HStack(alignment: .bottom) { if data.type == .personalCuration { - Text("\(shortcutsZipViewModel.userInfo?.nickname ?? "")\(data.type.rawValue)") - .Title2() - .foregroundColor(.Gray5) + SubtitleTextView(text: "\(shortcutsZipViewModel.userInfo?.nickname ?? "")\(data.type.rawValue)") .onTapGesture { } } else { - Text(data.title ?? "") - .Title2() - .foregroundColor(.Gray5) + SubtitleTextView(text: data.title ?? "") .onTapGesture { } } Spacer() NavigationLink(value: data) { - Text("더보기") - .Footnote() - .foregroundColor(.Gray4) + MoreCaptionTextView(text: TextLiteral.more) } } .padding(.bottom, 12) diff --git a/HappyAnding/HappyAnding/Views/Components/CustomTextEditor.swift b/HappyAnding/HappyAnding/Views/Components/CustomTextEditor.swift index 1dbfcef4..10f07eb5 100644 --- a/HappyAnding/HappyAnding/Views/Components/CustomTextEditor.swift +++ b/HappyAnding/HappyAnding/Views/Components/CustomTextEditor.swift @@ -8,16 +8,17 @@ import SwiftUI struct CustomTextEditor: UIViewRepresentable { + @FocusState var isFocused: Bool + @Binding var text: String @Binding var inputHeight: CGFloat - @FocusState var isFocused: Bool func makeUIView(context: UIViewRepresentableContext) -> UITextView { let textView = UITextView(frame: .zero) textView.delegate = context.coordinator textView.font = .Body2 textView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) - textView.backgroundColor = UIColor(.Background) + textView.backgroundColor = UIColor(.shortcutsZipBackground) return textView } @@ -30,9 +31,10 @@ struct CustomTextEditor: UIViewRepresentable { } class Coordinator: NSObject, UITextViewDelegate { + @FocusState var isFocused: Bool + @Binding var text: String @Binding var inputHeight: CGFloat - @FocusState var isFocused: Bool let maxHeight: CGFloat = 272 diff --git a/HappyAnding/HappyAnding/Views/Components/ListShortcutView.swift b/HappyAnding/HappyAnding/Views/Components/ListShortcutView.swift index 922ab21b..157ea1a1 100644 --- a/HappyAnding/HappyAnding/Views/Components/ListShortcutView.swift +++ b/HappyAnding/HappyAnding/Views/Components/ListShortcutView.swift @@ -19,12 +19,12 @@ struct ListShortcutView: View { var body: some View { if let shortcuts = data.shortcuts { if shortcuts.count == 0 { - Text("\(data.sectionType.rawValue)가 없습니다.") + Text("아직 \(data.sectionType.rawValue)가 없어요") .Body2() - .foregroundColor(Color.Gray4) + .foregroundColor(Color.gray4) .frame(maxWidth: .infinity, maxHeight: .infinity) - .background(Color.Background.ignoresSafeArea(.all, edges: .all)) + .background(Color.shortcutsZipBackground.ignoresSafeArea(.all, edges: .all)) .navigationTitle(data.sectionType.rawValue) .navigationBarTitleDisplayMode(.inline) } else { @@ -47,19 +47,19 @@ struct ListShortcutView: View { makeShortcutCellList(shortcutsZipViewModel.shortcutsMadeByUser) } Rectangle() - .fill(Color.Background) + .fill(Color.shortcutsZipBackground) .frame(height: 44) .listRowInsets(EdgeInsets()) .listRowSeparator(.hidden) } } - .listRowBackground(Color.Background) + .listRowBackground(Color.shortcutsZipBackground) .listStyle(.plain) - .background(Color.Background.ignoresSafeArea(.all, edges: .all)) + .background(Color.shortcutsZipBackground.ignoresSafeArea(.all, edges: .all)) .scrollContentBackground(.hidden) .navigationTitle(data.sectionType.rawValue) .navigationBarTitleDisplayMode(.inline) - .navigationBarBackground ({ Color.Background }) + .navigationBarBackground ({ Color.shortcutsZipBackground }) } } } @@ -73,8 +73,8 @@ struct ListShortcutView: View { NavigationLink(value: navigationData) { ShortcutCell(shortcut: shortcut, - navigationParentView: data.navigationParentView, - sectionType: data.sectionType) + sectionType: data.sectionType, + navigationParentView: data.navigationParentView) .listRowInsets(EdgeInsets()) .listRowSeparator(.hidden) } diff --git a/HappyAnding/HappyAnding/Views/Components/MoreCaptionTextView.swift b/HappyAnding/HappyAnding/Views/Components/MoreCaptionTextView.swift new file mode 100644 index 00000000..ec897bf0 --- /dev/null +++ b/HappyAnding/HappyAnding/Views/Components/MoreCaptionTextView.swift @@ -0,0 +1,19 @@ +// +// MoreCaptionTextView.swift +// HappyAnding +// +// Created by 전지민 on 2023/02/12. +// + +import SwiftUI + +struct MoreCaptionTextView: View { + + var text: String + + var body: some View { + Text(text) + .Footnote() + .foregroundColor(Color.gray4) + } +} diff --git a/HappyAnding/HappyAnding/Views/Components/MyShortcutCardListView.swift b/HappyAnding/HappyAnding/Views/Components/MyShortcutCardListView.swift index 8f3598e0..742def46 100644 --- a/HappyAnding/HappyAnding/Views/Components/MyShortcutCardListView.swift +++ b/HappyAnding/HappyAnding/Views/Components/MyShortcutCardListView.swift @@ -9,11 +9,12 @@ import SwiftUI struct MyShortcutCardListView: View { + @Environment(\.loginAlertKey) var loginAlerter @StateObject var writeNavigation = WriteShortcutNavigation() + @AppStorage("useWithoutSignIn") var useWithoutSignIn: Bool = false @State var isWriting = false - @State private var tryWriteWithoutSignIn: Bool = false var shortcuts: [Shortcuts]? var data: NavigationListShortcutType { @@ -27,21 +28,15 @@ struct MyShortcutCardListView: View { var body: some View { VStack { HStack { - Text("내가 작성한 단축어") - .Title2() - .foregroundColor(Color.Gray5) - .frame(maxWidth: .infinity, alignment: .leading) + SubtitleTextView(text: TextLiteral.myShortcutCardListViewTitle) Spacer() NavigationLink(value: data) { - Text("더보기") - .Footnote() - .foregroundColor(Color.Gray4) - .padding(.trailing, 16) + MoreCaptionTextView(text: TextLiteral.more) } } - .padding(.leading, 16) + .padding(.horizontal, 16) ScrollView(.horizontal, showsIndicators: false) { HStack { @@ -49,7 +44,7 @@ struct MyShortcutCardListView: View { if !useWithoutSignIn { self.isWriting = true } else { - self.tryWriteWithoutSignIn = true + loginAlerter.isPresented = true } } label: { AddMyShortcutCardView() @@ -73,26 +68,10 @@ struct MyShortcutCardListView: View { .padding(.horizontal, 16) } } - .alert("로그인을 진행해주세요", isPresented: $tryWriteWithoutSignIn) { - Button(role: .cancel) { - tryWriteWithoutSignIn = false - } label: { - Text("취소") - } - Button { - useWithoutSignIn = false - tryWriteWithoutSignIn = false - } label: { - Text("로그인하기") - } - } message: { - Text("이 기능은 로그인 후 사용할 수 있어요") - } .navigationBarTitleDisplayMode(.automatic) .fullScreenCover(isPresented: $isWriting) { NavigationStack(path: $writeNavigation.navigationPath) { - WriteShortcutTitleView(isWriting: $isWriting, - isEdit: false) + WriteShortcutView(isWriting: $isWriting, isEdit: false) } .environmentObject(writeNavigation) } diff --git a/HappyAnding/HappyAnding/Views/Components/MyShortcutCardView.swift b/HappyAnding/HappyAnding/Views/Components/MyShortcutCardView.swift index 3fb4b7d7..e9b5e167 100644 --- a/HappyAnding/HappyAnding/Views/Components/MyShortcutCardView.swift +++ b/HappyAnding/HappyAnding/Views/Components/MyShortcutCardView.swift @@ -18,11 +18,11 @@ struct MyShortcutCardView: View { Image(systemName: myShortcutIcon) .frame(width: 30.0, height: 30.0) .font(.title2) - .foregroundColor(Color.Text_icon) + .foregroundColor(Color.textIcon) Text(myShortcutName) .Subtitle() .multilineTextAlignment(.leading) - .foregroundColor(Color.Text_icon) + .foregroundColor(Color.textIcon) .lineLimit(3) Spacer() } @@ -39,11 +39,11 @@ struct AddMyShortcutCardView: View { VStack { Image(systemName: "plus") .font(.title2) - .foregroundColor(Color.Gray4) + .foregroundColor(Color.gray4) } .padding() .frame(width: 107, height: 144) - .background(Color.Background_plus) + .background(Color.backgroundPlus) .cornerRadius(12) } } diff --git a/HappyAnding/HappyAnding/Views/Components/NicknameTextField.swift b/HappyAnding/HappyAnding/Views/Components/NicknameTextField.swift index 0bc3a97b..79800ebc 100644 --- a/HappyAnding/HappyAnding/Views/Components/NicknameTextField.swift +++ b/HappyAnding/HappyAnding/Views/Components/NicknameTextField.swift @@ -31,11 +31,11 @@ struct NicknameTextField: View { var color: Color { switch self { case .focus: - return .Primary + return .shortcutsZipPrimary case .focusError: - return .red + return .shortcutsZipError case .notfocus: - return .Gray2 + return .gray2 } } @@ -48,9 +48,9 @@ struct NicknameTextField: View { var message: String { switch self { case .length: - return "*닉네임은 최대 8글자까지 입력가능합니다." + return TextLiteral.nicknameTextFieldLength case .emoticon: - return "사용할 수 없는 문자가 포함되어 있습니다." + return TextLiteral.nicknameTextFieldEmoticon } } } @@ -60,12 +60,12 @@ struct NicknameTextField: View { @FocusState var isFocused: Bool @Binding var nickname: String + @Binding var isValid: Bool @State var nicknameState = NicknameState.none @State var nicknameFocus = NicknameFocus.notfocus @State var nicknameError = NicknameError.length @State var isCheckedDuplicated = false - @Binding var isValid: Bool var initName = "" @@ -79,11 +79,11 @@ struct NicknameTextField: View { if nicknameFocus == .focusError { Text(nicknameError.message) .Footnote() - .foregroundColor(.red) + .foregroundColor(.shortcutsZipError) } else { - Text("* 공백 없이 한글 ,숫자, 영문만 입력 가능") + Text(TextLiteral.nicknameTextFieldSpace) .Footnote() - .foregroundColor(.Gray3) + .foregroundColor(.gray3) } } .onChange(of: nickname) { _ in @@ -98,13 +98,13 @@ struct NicknameTextField: View { .onChange(of: nicknameState) { newValue in self.isValid = newValue == .success } - .alert("닉네임 중복 확인", isPresented: $isCheckedDuplicated) { + .alert(TextLiteral.nicknameTextFieldDuplicateTitle, isPresented: $isCheckedDuplicated) { Button { } label: { - Text(nicknameState == .success ? "확인" : "다시 입력하기") + Text(nicknameState == .success ? TextLiteral.nicknameTextFieldDuplicateSuccessLabel : TextLiteral.nicknameTextFieldDuplicateFailLabel) } } message: { - Text(nicknameState == .success ? "사용 가능한 닉네임입니다" : "이미 사용 중인 닉네임입니다") + Text(nicknameState == .success ? TextLiteral.nicknameTextFieldDuplicateSuccessMessage : TextLiteral.nicknameTextFieldDuplicateFailMessage) } } @@ -112,13 +112,13 @@ struct NicknameTextField: View { HStack (spacing: 12) { HStack { - TextField("닉네임 (최대 8글자)", text: $nickname) + TextField(TextLiteral.nicknameTextFieldTitle, text: $nickname) .disableAutocorrection(true) .textInputAutocapitalization(.never) .focused($isFocused) .frame(height: 52) .Body2() - .foregroundColor(.Gray5) + .foregroundColor(.gray5) .padding(.horizontal, 16) .onAppear { UIApplication.shared.hideKeyboard() } @@ -147,12 +147,12 @@ struct NicknameTextField: View { ZStack { RoundedRectangle(cornerRadius: 12) - .foregroundColor(nicknameState != .none || nickname.isEmpty || initName == nickname ? .Primary.opacity(0.13) : .Primary) + .foregroundColor(nicknameState != .none || nickname.isEmpty || initName == nickname ? .shortcutsZipPrimary.opacity(0.13) : .shortcutsZipPrimary) .frame(width: 80, height: 52) - Text("중복확인") + Text(TextLiteral.nicknameTextFieldDuplicateCheck) .Body1() - .foregroundColor(nicknameState != .none || nickname.isEmpty || initName == nickname ? .Text_Button_Disable : .Text_icon) + .foregroundColor(nicknameState != .none || nickname.isEmpty || initName == nickname ? .textButtonDisable : .textIcon) } } .disabled(nicknameState != .none || nickname.isEmpty || initName == nickname) @@ -167,18 +167,18 @@ struct NicknameTextField: View { } label: { Image(systemName: "xmark.circle.fill") .Body2() - .foregroundColor(.Gray5) + .foregroundColor(.gray5) } } else { if nicknameState == .fail { Image(systemName: "exclamationmark.circle.fill") .Body2() - .foregroundColor(.red) + .foregroundColor(.shortcutsZipError) .onTapGesture { } } else if nicknameState == .success { Image(systemName: "checkmark.circle.fill") .Body2() - .foregroundColor(.Success) + .foregroundColor(.shortcutsZipSuccess) .onTapGesture { } } } diff --git a/HappyAnding/HappyAnding/Views/Components/PaletteCell.swift b/HappyAnding/HappyAnding/Views/Components/PaletteCell.swift deleted file mode 100644 index 2c58e48c..00000000 --- a/HappyAnding/HappyAnding/Views/Components/PaletteCell.swift +++ /dev/null @@ -1,20 +0,0 @@ -// -// PaletteCell.swift -// HappyAnding -// -// Created by 이지원 on 2022/10/20. -// - -import SwiftUI - -struct PaletteCell: View { - var body: some View { - Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) - } -} - -struct PaletteCell_Previews: PreviewProvider { - static var previews: some View { - PaletteCell() - } -} diff --git a/HappyAnding/HappyAnding/Views/Components/PaletteView.swift b/HappyAnding/HappyAnding/Views/Components/PaletteView.swift deleted file mode 100644 index 2ced5732..00000000 --- a/HappyAnding/HappyAnding/Views/Components/PaletteView.swift +++ /dev/null @@ -1,20 +0,0 @@ -// -// PaletteView.swift -// HappyAnding -// -// Created by 이지원 on 2022/10/20. -// - -import SwiftUI - -struct PaletteView: View { - var body: some View { - Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) - } -} - -struct PaletteView_Previews: PreviewProvider { - static var previews: some View { - PaletteView() - } -} diff --git a/HappyAnding/HappyAnding/Views/Components/ShortcutCardCell.swift b/HappyAnding/HappyAnding/Views/Components/ShortcutCardCell.swift index 98dabd4f..c5ab985e 100644 --- a/HappyAnding/HappyAnding/Views/Components/ShortcutCardCell.swift +++ b/HappyAnding/HappyAnding/Views/Components/ShortcutCardCell.swift @@ -8,6 +8,7 @@ import SwiftUI struct ShortcutCardCell: View { + let categoryShortcutIcon: String let categoryShortcutName: String let categoryShortcutColor: String @@ -15,12 +16,12 @@ struct ShortcutCardCell: View { var body: some View { VStack(alignment: .leading, spacing: 4) { Image(systemName: categoryShortcutIcon) - .foregroundColor(Color.Text_icon) + .foregroundColor(Color.textIcon) Text(categoryShortcutName) .multilineTextAlignment(.leading) .lineLimit(2) .Headline() - .foregroundColor(Color.Text_icon) + .foregroundColor(Color.textIcon) Spacer() } .padding(12) diff --git a/HappyAnding/HappyAnding/Views/Components/ShortcutCell.swift b/HappyAnding/HappyAnding/Views/Components/ShortcutCell.swift index d7cad593..56ac79d2 100644 --- a/HappyAnding/HappyAnding/Views/Components/ShortcutCell.swift +++ b/HappyAnding/HappyAnding/Views/Components/ShortcutCell.swift @@ -31,9 +31,12 @@ import SwiftUI struct ShortcutCell: View { + @Environment(\.loginAlertKey) var loginAlerter @Environment(\.openURL) private var openURL @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel + @AppStorage("useWithoutSignIn") var useWithoutSignIn: Bool = false + @State var shortcutCell = ShortcutCellModel( id: "", sfSymbol: "", @@ -42,13 +45,11 @@ struct ShortcutCell: View { subtitle: "", downloadLink: "" ) + var shortcut: Shortcuts? var rankNumber: Int = -1 - let navigationParentView: NavigationParentView var sectionType: SectionType? - - @AppStorage("useWithoutSignIn") var useWithoutSignIn: Bool = false - @State private var tryActionWithoutSignIn: Bool = false + let navigationParentView: NavigationParentView var body: some View { @@ -67,7 +68,7 @@ struct ShortcutCell: View { } } } else { - tryActionWithoutSignIn = true + loginAlerter.isPresented = true } } } @@ -75,23 +76,8 @@ struct ShortcutCell: View { .background( background ) .padding(.horizontal, 20) } - .alert("로그인을 진행해주세요", isPresented: $tryActionWithoutSignIn) { - Button(role: .cancel) { - tryActionWithoutSignIn = false - } label: { - Text("취소") - } - Button { - useWithoutSignIn = false - tryActionWithoutSignIn = false - } label: { - Text("로그인하기") - } - } message: { - Text("이 기능은 로그인 후 사용할 수 있어요") - } .padding(.bottom, 12) - .background(Color.Background) + .background(Color.shortcutsZipBackground) .onAppear() { if let shortcut { self.shortcutCell = ShortcutCellModel( @@ -115,7 +101,7 @@ struct ShortcutCell: View { .frame(width: 52, height: 52) Image(systemName: shortcutCell.sfSymbol) - .foregroundColor(.Text_icon) + .foregroundColor(.textIcon) } .padding(.leading, 20) } @@ -126,16 +112,16 @@ struct ShortcutCell: View { if rankNumber != -1 { Text("\(rankNumber)") .Subtitle() - .foregroundColor(.Gray4) + .foregroundColor(.gray4) .padding(0) } Text(shortcutCell.title) .Headline() - .foregroundColor(.Gray5) + .foregroundColor(.gray5) .lineLimit(1) Text(shortcutCell.subtitle.lineBreaking) .Footnote() - .foregroundColor(.Gray3) + .foregroundColor(.gray3) .multilineTextAlignment(.leading) .lineLimit(2) } @@ -168,10 +154,10 @@ struct ShortcutCell: View { var background: some View { RoundedRectangle(cornerRadius: 12) - .fill(Color.Background_list) + .fill(Color.backgroudList) .overlay( RoundedRectangle(cornerRadius: 12) - .strokeBorder(Color.Background_list_border) + .strokeBorder(Color.backgroudListBorder) ) } } diff --git a/HappyAnding/HappyAnding/Views/Components/StickyHeader.swift b/HappyAnding/HappyAnding/Views/Components/StickyHeader.swift new file mode 100644 index 00000000..4d6f4e54 --- /dev/null +++ b/HappyAnding/HappyAnding/Views/Components/StickyHeader.swift @@ -0,0 +1,46 @@ +// +// StickyHeader.swift +// HappyAnding +// +// Created by 전지민 on 2023/01/25. +// + +import SwiftUI + +/** + 어드민 큐레이션 썸네일입니다. + + #parameters + - height: 배경의 높이 값 + - image: 이미지 파일명 + + #description + - sticky header가 필요한 곳에서 사용할 수 있습니다. + - 이미지가 적용되어야 할 경우에만 이미지 파일명을 넣어주시면 됩니다. + */ + +struct StickyHeader: View { + + var height: CGFloat + var image: String? + + var body: some View { + GeometryReader { geo in + let yOffset = geo.frame(in: .global).minY + + if let image = image { + Image(image) + .resizable() + .aspectRatio(contentMode: .fill) + .frame(width: geo.size.width, height: height + (yOffset > 0 ? yOffset : 0)) + .clipped() + .offset(y: yOffset > 0 ? -yOffset : 0) + } else { + Color.shortcutsZipWhite + .frame(width: geo.size.width, height: height + (yOffset > 0 ? yOffset : 0)) + .offset(y: yOffset > 0 ? -yOffset : 0) + } + } + .frame(minHeight: height) + } +} diff --git a/HappyAnding/HappyAnding/Views/Components/SubtitleTextView.swift b/HappyAnding/HappyAnding/Views/Components/SubtitleTextView.swift new file mode 100644 index 00000000..69d765a9 --- /dev/null +++ b/HappyAnding/HappyAnding/Views/Components/SubtitleTextView.swift @@ -0,0 +1,20 @@ +// +// SubtitleTextView.swift +// HappyAnding +// +// Created by 전지민 on 2023/01/25. +// + +import SwiftUI + +struct SubtitleTextView: View { + + var text: String + + var body: some View { + Text(text) + .Title2() + .foregroundColor(Color.gray5) + .frame(maxWidth: .infinity, alignment: .leading) + } +} diff --git a/HappyAnding/HappyAnding/Views/Components/UserCurationCell.swift b/HappyAnding/HappyAnding/Views/Components/UserCurationCell.swift index 9d519349..5644e695 100644 --- a/HappyAnding/HappyAnding/Views/Components/UserCurationCell.swift +++ b/HappyAnding/HappyAnding/Views/Components/UserCurationCell.swift @@ -12,15 +12,15 @@ import SwiftUI struct UserCurationCell: View { @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel + @State var curation: Curation @State var index = 0 - let navigationParentView: NavigationParentView + var lineLimit: Int? + let navigationParentView: NavigationParentView var body: some View { ZStack { - //TODO: userCuration 모델에 nickname 파라미터 통합 필요 - VStack (alignment: .leading, spacing: 0) { //MARK: - 단축어 아이콘 배열 @@ -28,13 +28,11 @@ struct UserCurationCell: View { ForEach(shortcutsZipViewModel.userCurations[index].shortcuts.prefix(4), id: \.self) { shortcut in ZStack { Rectangle() - .fill(Color.fetchGradient( - color: shortcut.color) - ) + .fill(Color.fetchGradient(color: shortcut.color)) .cornerRadius(8) .frame(width: 36, height: 36) Image(systemName: shortcut.sfSymbol) - .foregroundColor(Color.Text_icon) + .foregroundColor(Color.textIcon) .font(.system(size: 15)) } } @@ -43,14 +41,14 @@ struct UserCurationCell: View { if shortcutsZipViewModel.userCurations[index].shortcuts.count > 4 { ZStack(alignment: .center) { Rectangle() - .fill(Color.Gray2) + .fill(Color.gray2) .cornerRadius(8) .frame(width: 36, height: 36) HStack(spacing: 0) { Image(systemName: "plus") Text("\(shortcutsZipViewModel.userCurations[index].shortcuts.count-4)") } - .foregroundColor(.Gray5) + .foregroundColor(.gray5) .Footnote() } } @@ -62,13 +60,13 @@ struct UserCurationCell: View { Text(shortcutsZipViewModel.userCurations[index].title) .Headline() - .foregroundColor(Color.Gray5) + .foregroundColor(Color.gray5) .frame(maxWidth: .infinity, alignment: .leading) Text(shortcutsZipViewModel.userCurations[index].subtitle.lineBreaking) .Body2() .multilineTextAlignment(.leading) .lineLimit(lineLimit) - .foregroundColor(Color.Gray5) + .foregroundColor(Color.gray5) .padding(.bottom, 20) .fixedSize(horizontal: false, vertical: true) } @@ -78,10 +76,10 @@ struct UserCurationCell: View { } } .padding(.horizontal, 24) - .background(Color.Background_list) + .background(Color.backgroudList) .overlay( RoundedRectangle(cornerRadius: 12) - .strokeBorder(Color.Background_list_border, lineWidth: 1) + .strokeBorder(Color.backgroudListBorder, lineWidth: 1) ) .frame(maxWidth: .infinity) .cornerRadius(12) diff --git a/HappyAnding/HappyAnding/Views/Components/UserCurationListView.swift b/HappyAnding/HappyAnding/Views/Components/UserCurationListView.swift index 7dcecd4c..92830ce3 100644 --- a/HappyAnding/HappyAnding/Views/Components/UserCurationListView.swift +++ b/HappyAnding/HappyAnding/Views/Components/UserCurationListView.swift @@ -8,101 +8,72 @@ import SwiftUI struct UserCurationListView: View { + @Environment(\.loginAlertKey) var loginAlert @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel + @StateObject var writeCurationNavigation = WriteCurationNavigation() + @AppStorage("useWithoutSignIn") var useWithoutSignIn: Bool = false @State var isWriting = false @State var data: NavigationListCurationType - @State var curations = [Curation]() - @State private var tryWriteWithoutSignIn: Bool = false - var body: some View { VStack(spacing: 0) { - listHeader - .padding(.bottom, 12) - .padding(.horizontal, 16) + HStack(alignment: .bottom) { + SubtitleTextView(text: data.title ?? "") + .onTapGesture { } + Spacer() + + NavigationLink(value: data) { + MoreCaptionTextView(text: TextLiteral.more) + } + } + .padding(.bottom, 12) + .padding(.horizontal, 16) Button { if !useWithoutSignIn { self.isWriting = true } else { - self.tryWriteWithoutSignIn = true + loginAlert.isPresented = true } } label: { HStack(spacing: 7) { Image(systemName: "plus") - Text("추천 모음집 작성") + Text(TextLiteral.userCurationListViewAdd) } .Headline() - .foregroundColor(.Gray4) + .foregroundColor(.gray4) .frame(maxWidth: .infinity) .frame(height: 64) - .background(Color.Background_plus) + .background(Color.backgroundPlus) .cornerRadius(12) .padding(.bottom, 12) .padding(.horizontal, 16) } - ForEach(curations.prefix(2), id: \.self) { curation in - - let data = NavigationReadUserCurationType(userCuration: curation, - navigationParentView: self.data.navigationParentView) - NavigationLink(value: data) { - UserCurationCell(curation: curation, - navigationParentView: self.data.navigationParentView, - lineLimit: 2) + ForEach(Array(shortcutsZipViewModel.curationsMadeByUser.enumerated()), id: \.offset) { index, curation in + + if index < 2 { + let data = NavigationReadUserCurationType(userCuration: curation, + navigationParentView: self.data.navigationParentView) + NavigationLink(value: data) { + UserCurationCell(curation: curation, + lineLimit: 2, + navigationParentView: self.data.navigationParentView) + } } } } - .alert("로그인을 진행해주세요", isPresented: $tryWriteWithoutSignIn) { - Button(role: .cancel) { - tryWriteWithoutSignIn = false - } label: { - Text("취소") - } - Button { - useWithoutSignIn = false - tryWriteWithoutSignIn = false - } label: { - Text("로그인하기") - } - } message: { - Text("이 기능은 로그인 후 사용할 수 있어요") - } - .background(Color.Background.ignoresSafeArea(.all, edges: .all)) + .background(Color.shortcutsZipBackground.ignoresSafeArea(.all, edges: .all)) .fullScreenCover(isPresented: $isWriting) { NavigationStack(path: $writeCurationNavigation.navigationPath) { WriteCurationSetView(isWriting: $isWriting, isEdit: false) } .environmentObject(writeCurationNavigation) } - .onAppear { - self.data.curation = shortcutsZipViewModel.curationsMadeByUser - self.curations = shortcutsZipViewModel.curationsMadeByUser - } - .onChange(of: shortcutsZipViewModel.curationsMadeByUser) { data in - self.data.curation = data - self.curations = data - } - } - - var listHeader: some View { - HStack(alignment: .bottom) { - Text(data.title ?? "") - .Title2() - .foregroundColor(.Gray5) - .onTapGesture { } - Spacer() - - NavigationLink(value: data) { - Text("더보기") - .Footnote() - .foregroundColor(.Gray4) - } - } } } diff --git a/HappyAnding/HappyAnding/Views/Components/ValidationCheckTextField.swift b/HappyAnding/HappyAnding/Views/Components/ValidationCheckTextField.swift index 8e11f73e..e370aa69 100644 --- a/HappyAnding/HappyAnding/Views/Components/ValidationCheckTextField.swift +++ b/HappyAnding/HappyAnding/Views/Components/ValidationCheckTextField.swift @@ -31,15 +31,15 @@ enum TextFieldState { var color: Color { switch self { case .notStatus: - return Color.Gray2 + return Color.gray2 case .inProgressSuccess: - return Color.Primary + return Color.shortcutsZipPrimary case .inProgressFail: - return Color.red + return Color.shortcutsZipError case .doneSuccess: - return Color.Gray4 + return Color.gray4 case .doneFail: - return Color.red + return Color.shortcutsZipError } } } @@ -51,9 +51,9 @@ enum TextFieldError { var message: String { switch self { case .invalidLink: - return "유효하지 않은 링크입니다." + return TextLiteral.validationCheckTextFieldInvalid case .excessLimitLenth: - return "입력할 수 있는 문자 수를 초과했습니다." + return TextLiteral.validationCheckTextFieldExcess } } } @@ -70,7 +70,7 @@ struct ValidationCheckTextField: View { @Binding var content: String @Binding var isValid: Bool - @State private var strokeColor = Color.Gray2 + @State private var strokeColor = Color.gray2 @State private var isExceeded = false @State private var textFieldState = TextFieldState.notStatus @State private var textFieldError = TextFieldError.invalidLink @@ -89,7 +89,7 @@ struct ValidationCheckTextField: View { if let lengthLimit { Text("\(content.count)/\(lengthLimit)") .Body2() - .foregroundColor(.Gray4) + .foregroundColor(.gray4) .padding(.trailing, 16) } } @@ -115,7 +115,7 @@ struct ValidationCheckTextField: View { if isExceeded { Text(textFieldError.message) .Body2() - .foregroundColor(.Error) + .foregroundColor(.shortcutsZipError) .padding(.leading) } @@ -132,13 +132,13 @@ struct ValidationCheckTextField: View { HStack { Text(title) .Headline() - .foregroundColor(.Gray5) + .foregroundColor(.gray5) .padding(.leading, 16) if textType.isOptional { - Text("(선택입력)") + Text(TextLiteral.validationCheckTextFieldOption) .Footnote() - .foregroundColor(.Gray3) + .foregroundColor(.gray3) } } .frame(maxWidth: .infinity, alignment: .leading) @@ -170,9 +170,9 @@ struct ValidationCheckTextField: View { ZStack(alignment: .topLeading) { - CustomTextEditor(text: $content, - inputHeight: $inputHeight, - isFocused: _isFocused) + CustomTextEditor(isFocused: _isFocused, + text: $content, + inputHeight: $inputHeight) .focused($isFocused) .frame(height: inputHeight) .padding(16) @@ -183,7 +183,7 @@ struct ValidationCheckTextField: View { .frame(maxWidth: .infinity, alignment: .leading) .multilineTextAlignment(.leading) .padding(16) - .foregroundColor(.Gray2) + .foregroundColor(.gray2) .onTapGesture { isFocused = true } @@ -210,19 +210,19 @@ struct ValidationCheckTextField: View { case .doneSuccess: Image(systemName: "checkmark.circle.fill") .Body2() - .foregroundColor(.Success) + .foregroundColor(.shortcutsZipSuccess) .onTapGesture { } case .doneFail: Image(systemName: "exclamationmark.circle.fill") .Body2() - .foregroundColor(.red) + .foregroundColor(.shortcutsZipError) case .inProgressSuccess: Button { content.removeAll() } label: { Image(systemName: "xmark.circle.fill") .Body2() - .foregroundColor(.Gray5) + .foregroundColor(.gray5) } case .inProgressFail: Button { @@ -230,7 +230,7 @@ struct ValidationCheckTextField: View { } label: { Image(systemName: "xmark.circle.fill") .Body2() - .foregroundColor(.Gray5) + .foregroundColor(.gray5) } } } @@ -248,7 +248,7 @@ extension ValidationCheckTextField { self.textFieldState = .inProgressSuccess } else if content.count <= lengthLimit ?? 999 { if isDownloadLinkTextField { - if content.hasPrefix("https://www.icloud.com/shortcuts/") { + if content.hasPrefix(TextLiteral.validationCheckTextFieldPrefix) { isValid = true isExceeded = false self.textFieldState = .inProgressSuccess diff --git a/HappyAnding/HappyAnding/Views/ExploreCurationViews/ExploreCurationView.swift b/HappyAnding/HappyAnding/Views/ExploreCurationViews/ExploreCurationView.swift index 8ca2a51b..7fc41cc6 100644 --- a/HappyAnding/HappyAnding/Views/ExploreCurationViews/ExploreCurationView.swift +++ b/HappyAnding/HappyAnding/Views/ExploreCurationViews/ExploreCurationView.swift @@ -10,16 +10,16 @@ import SwiftUI struct ExploreCurationView: View { @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel + @AppStorage("useWithoutSignIn") var useWithoutSignIn = false var body: some View { ScrollView { - VStack(spacing: 0) { + VStack(spacing: 32) { //앱 큐레이션 - adminCurationsFrameiew(adminCurations: shortcutsZipViewModel.adminCurations) + adminCurationsFrameView(adminCurations: shortcutsZipViewModel.adminCurations) .padding(.top, 20) - .padding(.bottom, 32) //사용자를 위한 모음집 if !useWithoutSignIn { @@ -28,38 +28,36 @@ struct ExploreCurationView: View { isAllUser: false, navigationParentView: .curations, curation: shortcutsZipViewModel.personalCurations)) - .padding(.bottom, 32) } //추천 유저 큐레이션 CurationListView(data: NavigationListCurationType(type: .userCuration, - title: "사용자 추천 모음집", + title: TextLiteral.exploreCurationViewUserCurations, isAllUser: true, navigationParentView: .curations, curation: shortcutsZipViewModel.userCurations)) } - .padding(.bottom, 32) + .padding(.top, 20) + .padding(.bottom, 44) .onChange(of: shortcutsZipViewModel.userCurations) { _ in shortcutsZipViewModel.refreshPersonalCurations() } } - .navigationBarTitle(Text("추천 모음집 둘러보기")) + .navigationBarTitle(Text(TextLiteral.exploreCurationViewTitle)) .navigationBarTitleDisplayMode(.large) .scrollIndicators(.hidden) - .background(Color.Background) + .background(Color.shortcutsZipBackground) } } -struct adminCurationsFrameiew: View { +struct adminCurationsFrameView: View { let adminCurations: [Curation] var body: some View { VStack(alignment: .leading, spacing: 12) { HStack(alignment: .bottom) { - Text("숏컷집 추천 모음집") - .Title2() - .foregroundColor(.Gray5) + SubtitleTextView(text: TextLiteral.exploreCurationViewAdminCurations) .id(222) Spacer() @@ -67,7 +65,7 @@ struct adminCurationsFrameiew: View { // NavigationLink(destination: 더보기 눌렀을 때 뷰이름 입력) { // Text("더보기") // .Footnote() - // .foregroundColor(.Gray4) + // .foregroundColor(.gray4) // } } .padding(.horizontal, 16) diff --git a/HappyAnding/HappyAnding/Views/ExploreCurationViews/ListCurationView.swift b/HappyAnding/HappyAnding/Views/ExploreCurationViews/ListCurationView.swift index d09152a1..8bad91bf 100644 --- a/HappyAnding/HappyAnding/Views/ExploreCurationViews/ListCurationView.swift +++ b/HappyAnding/HappyAnding/Views/ExploreCurationViews/ListCurationView.swift @@ -22,23 +22,24 @@ enum CurationType: String { struct ListCurationView: View { @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel + @State var data: NavigationListCurationType var body: some View { let titleString = data.type == .personalCuration ? (shortcutsZipViewModel.userInfo?.nickname ?? "") : "" if data.curation.count == 0 { - Text("\(titleString)\(data.type.rawValue)이(가) 없습니다.") + Text("아직 \(titleString)\(data.type.rawValue)이(가) 없어요") .Body2() - .foregroundColor(Color.Gray4) + .foregroundColor(Color.gray4) .frame(maxWidth: .infinity, maxHeight: .infinity) - .background(Color.Background.ignoresSafeArea(.all, edges: .all)) + .background(Color.shortcutsZipBackground.ignoresSafeArea(.all, edges: .all)) .navigationBarTitle("\(titleString)\(data.type.rawValue)") .navigationBarTitleDisplayMode(.inline) } else { ScrollView { LazyVStack(spacing: 0) { Rectangle() - .fill(Color.Background) + .fill(Color.shortcutsZipBackground) .frame(height: 20) switch data.type { case .personalCuration: @@ -49,14 +50,14 @@ struct ListCurationView: View { makeCurationCellList(shortcutsZipViewModel.curationsMadeByUser) } Rectangle() - .fill(Color.Background) + .fill(Color.shortcutsZipBackground) .frame(height: 32) } } .scrollIndicators(.hidden) .listStyle(.plain) - .background(Color.Background.ignoresSafeArea(.all, edges: .all)) - .navigationBarBackground ({ Color.Background }) + .background(Color.shortcutsZipBackground.ignoresSafeArea(.all, edges: .all)) + .navigationBarBackground ({ Color.shortcutsZipBackground }) .scrollContentBackground(.hidden) .navigationBarTitleDisplayMode(.inline) .navigationTitle(data.title ?? "") @@ -65,18 +66,18 @@ struct ListCurationView: View { @ViewBuilder private func makeCurationCellList(_ curations: [Curation]) -> some View { - ForEach(curations, id: \.self) { curation in + ForEach(Array(curations.enumerated()), id: \.offset) { index, curation in let data = NavigationReadUserCurationType(userCuration: curation, navigationParentView: self.data.navigationParentView) NavigationLink(value: data) { UserCurationCell(curation: curation, - navigationParentView: self.data.navigationParentView, - lineLimit: 2) + lineLimit: 2, + navigationParentView: self.data.navigationParentView) .listRowInsets(EdgeInsets()) .listRowSeparator(.hidden) - .listRowBackground(Color.Background) + .listRowBackground(Color.shortcutsZipBackground) } } } diff --git a/HappyAnding/HappyAnding/Views/ExploreCurationViews/ReadAdminCurationView.swift b/HappyAnding/HappyAnding/Views/ExploreCurationViews/ReadAdminCurationView.swift index 3c084986..76fc9aa8 100644 --- a/HappyAnding/HappyAnding/Views/ExploreCurationViews/ReadAdminCurationView.swift +++ b/HappyAnding/HappyAnding/Views/ExploreCurationViews/ReadAdminCurationView.swift @@ -21,24 +21,15 @@ import SwiftUI */ struct ReadAdminCurationView: View { - @Environment(\.presentationMode) var presentationMode: Binding + let curation: Curation var body: some View { ScrollView(showsIndicators: false) { - GeometryReader { geo in - let yOffset = geo.frame(in: .global).minY - - Image(curation.background) - .resizable() - .aspectRatio(contentMode: .fill) - .frame(width: geo.size.width, height: 304 + (yOffset > 0 ? yOffset : 0)) - .clipped() - .offset(y: yOffset > 0 ? -yOffset : 0) - } - .frame(minHeight: 304) - .padding(.bottom, 20) + + StickyHeader(height: 304, image: curation.background) + .padding(.bottom, 20) titleAndSubtitle .padding(.bottom, 8) @@ -59,7 +50,7 @@ struct ReadAdminCurationView: View { } .navigationBarTitleDisplayMode(.inline) .edgesIgnoringSafeArea(.top) - .background(Color.Background) + .background(Color.shortcutsZipBackground) //TODO: 추후 공유 기능 추가 시 사용할 코드 // .toolbar { @@ -69,7 +60,7 @@ struct ReadAdminCurationView: View { // //TODO: Share 버튼 눌렀을 때 Curation공유 링크 생성 및 actionSheet 나타내기 // }) { // Image(systemName: "square.and.arrow.up") - // .foregroundColor(.Gray4) + // .foregroundColor(.gray4) // } // } // } @@ -86,12 +77,10 @@ struct ReadAdminCurationView: View { var titleAndSubtitle: some View { HStack { VStack(alignment: .leading, spacing: 4) { - Text(curation.title) - .Title2() - .foregroundColor(.Gray5) + SubtitleTextView(text: curation.title) Text(curation.subtitle.replacingOccurrences(of: "\\n", with: "\n")) .Body2() - .foregroundColor(.Gray4) + .foregroundColor(.gray4) } Spacer() } diff --git a/HappyAnding/HappyAnding/Views/ExploreCurationViews/ReadUserCurationView.swift b/HappyAnding/HappyAnding/Views/ExploreCurationViews/ReadUserCurationView.swift index bae481e2..d6a726d0 100644 --- a/HappyAnding/HappyAnding/Views/ExploreCurationViews/ReadUserCurationView.swift +++ b/HappyAnding/HappyAnding/Views/ExploreCurationViews/ReadUserCurationView.swift @@ -8,17 +8,18 @@ import SwiftUI struct ReadUserCurationView: View { - @Environment(\.presentationMode) var presentation: Binding @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel @StateObject var writeCurationNavigation = WriteCurationNavigation() + @State var authorInformation: User? = nil @State var isWriting = false @State var isTappedEditButton = false @State var isTappedShareButton = false @State var isTappedDeleteButton = false + @State var data: NavigationReadUserCurationType @State var index = 0 @@ -26,14 +27,7 @@ struct ReadUserCurationView: View { ScrollView(showsIndicators: false) { ZStack(alignment: .bottom) { - GeometryReader { geo in - let yOffset = geo.frame(in: .global).minY - - Color.White - .frame(width: geo.size.width, height: 371 + (yOffset > 0 ? yOffset : 0)) - .offset(y: yOffset > 0 ? -yOffset : 0) - } - .frame(minHeight: 371) + StickyHeader(height: 371) VStack { userInformation @@ -43,7 +37,8 @@ struct ReadUserCurationView: View { UserCurationCell(curation: data.userCuration, navigationParentView: data.navigationParentView) } } - .background(Color.White) + .padding(.bottom, 8) + .background(Color.shortcutsZipWhite) .padding(.bottom, 12) VStack(spacing: 0){ @@ -60,7 +55,7 @@ struct ReadUserCurationView: View { .padding(.bottom, 44) } - .background(Color.Background.ignoresSafeArea(.all, edges: .all)) + .background(Color.shortcutsZipBackground.ignoresSafeArea(.all, edges: .all)) .scrollContentBackground(.hidden) .edgesIgnoringSafeArea([.top]) .navigationBarTitleDisplayMode(.inline) @@ -73,11 +68,11 @@ struct ReadUserCurationView: View { } .environmentObject(writeCurationNavigation) } - .alert("글 삭제", isPresented: $isTappedDeleteButton) { + .alert(TextLiteral.readUserCurationViewDeletionTitle, isPresented: $isTappedDeleteButton) { Button(role: .cancel) { self.isTappedDeleteButton.toggle() } label: { - Text("닫기") + Text(TextLiteral.cancel) } Button(role: .destructive) { @@ -85,10 +80,10 @@ struct ReadUserCurationView: View { shortcutsZipViewModel.curationsMadeByUser = shortcutsZipViewModel.curationsMadeByUser.filter { $0.id != self.data.userCuration.id } presentation.wrappedValue.dismiss() } label: { - Text("삭제") + Text(TextLiteral.delete) } } message: { - Text("글을 삭제하시겠습니까?") + Text(TextLiteral.readUserCurationViewDeletionMessage) } } @@ -100,11 +95,11 @@ struct ReadUserCurationView: View { Image(systemName: "person.crop.circle.fill") .font(.system(size: 28, weight: .medium)) .frame(width: 28, height: 28) - .foregroundColor(.Gray3) + .foregroundColor(.gray3) - Text(authorInformation?.nickname ?? "탈퇴한 사용자") + Text(authorInformation?.nickname ?? TextLiteral.withdrawnUser) .Headline() - .foregroundColor(.Gray4) + .foregroundColor(.gray4) Spacer() } } @@ -113,7 +108,7 @@ struct ReadUserCurationView: View { .background( RoundedRectangle(cornerRadius: 12) .frame(height: 48) - .foregroundColor(.Gray1) + .foregroundColor(.gray1) .padding(.horizontal, 16) ) } @@ -151,7 +146,7 @@ extension ReadUserCurationView { } }, label: { Image(systemName: "ellipsis") - .foregroundColor(.Gray4) + .foregroundColor(.gray4) }) } @@ -159,7 +154,7 @@ extension ReadUserCurationView { Button { self.isWriting.toggle() } label: { - Label("편집", systemImage: "square.and.pencil") + Label(TextLiteral.edit, systemImage: "square.and.pencil") } } @@ -167,8 +162,8 @@ extension ReadUserCurationView { Button(action: { shareCuration() }) { - Label("공유", systemImage: "square.and.arrow.up") - .foregroundColor(.Gray4) + Label(TextLiteral.share, systemImage: "square.and.arrow.up") + .foregroundColor(.gray4) .fontWeight(.medium) } } @@ -177,7 +172,7 @@ extension ReadUserCurationView { Button(role: .destructive, action: { isTappedDeleteButton.toggle() }) { - Label("삭제", systemImage: "trash.fill") + Label(TextLiteral.delete, systemImage: "trash.fill") } } diff --git a/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreCategoryView.swift b/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreCategoryView.swift deleted file mode 100644 index c0aab9a5..00000000 --- a/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreCategoryView.swift +++ /dev/null @@ -1,130 +0,0 @@ -// -// ExploreCategoryView.swift -// HappyAnding -// -// Created by 이지원 on 2022/10/19. -// - -import SwiftUI - -/** - ExploreCategoryView - #parameters - - lovedShortcuts: 사랑받는 단축어 목록 - - rankingShortcuts: 다운로드 순위 단축어 목록 - - 카테고리 선택할 때 이 뷰에 넘겨줘야하는 카테고리 이름입니다. - - categoryDescriptions: 카테고리 설명글 - - #description - - ShortcutTestModel 파일에서 생성한 Shortcut모델을 기준으로 데이터를 받아옵니다. - */ -/* -<<<<<<< HEAD -======= - ->>>>>>> 921d9600b92f12b0832275415f08118fb711463f -struct ExploreCategoryView: View { - - //TODO: 단축어 목록 받아오기 -// let lovedShortcuts = Shortcut.fetchData(number: 10) -// let rankingShortcuts = Shortcut.fetchData(number: 10) - - @State var lovedShortcuts: [Shortcuts] = [] - @State var rankingShortcuts: [Shortcuts] = [] - - let firebase = FirebaseService() - - let category: Category - let shortcuts:[Shortcuts]? - - var body: some View { - VStack { - List { - Text(category.fetchDescription()) - .foregroundColor(.Gray5) - .Body2() - .padding(16) - .frame(maxWidth: .infinity, alignment: .leading) - .background( - Rectangle() - .foregroundColor(Color.Gray1) - .cornerRadius(12) - ) - .listRowInsets( - EdgeInsets( - top: 20, - leading: 16, - bottom: 0, - trailing: 16 - ) - ) - .listRowSeparator(.hidden) - .listRowBackground(Color.Background) - Section() { - CategoryListHeader(type: .download, category: category, shortcuts: rankingShortcuts) - .padding(.top, 20) - .listRowBackground(Color.Background) - if let rankingShortcuts { - ForEach(Array(rankingShortcuts.enumerated()), id: \.offset) { index, shortcut in - if index < 3 { - ShortcutCell(shortcut: shortcut) - } - } - .listRowInsets(EdgeInsets()) - .listRowSeparator(.hidden) - } - - } - Section() { - CategoryListHeader(type: .popular, shortcuts: lovedShortcuts) - .padding(.top, 20) - .listRowBackground(Color.Background) - if let lovedShortcuts { - ForEach(Array(lovedShortcuts.enumerated()), id: \.offset) { index, shortcut in - if index < 3 { - ShortcutCell(shortcut: shortcut) - } - } - .listRowInsets(EdgeInsets()) - .listRowSeparator(.hidden) - } - - } - } - .listStyle(.plain) - .background(Color.Background.ignoresSafeArea(.all, edges: .all)) - .scrollContentBackground(.hidden) - } - .navigationBarTitle(category.translateName()) - .onAppear() { - firebase.fetchCategoryOrderedShortcut(category: category.rawValue, orderBy: "numberOfLike") { shortcuts in - lovedShortcuts = shortcuts - } - firebase.fetchCategoryOrderedShortcut(category: category.rawValue, orderBy: "numberOfDownload") { shortcuts in - rankingShortcuts = shortcuts - } - } - } -} - -struct CategoryListHeader: View { - var type: SectionType - var category: Category? - var shortcuts: [Shortcuts]? - var body: some View { - HStack(alignment: .bottom) { - Text(type.rawValue) - .Title2() - .foregroundColor(.Gray5) - Spacer() - ZStack { - Text("더보기") - .Footnote() - .foregroundColor(.Gray4) - .frame(maxWidth: .infinity, alignment: .trailing) - NavigationLink(destination: ListShortcutView(shortcuts: shortcuts, categoryName: category, sectionType: type)){}.opacity(0) - } - } - } -} -*/ diff --git a/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView/CategoryCardView.swift b/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView/CategoryCardView.swift index 505da885..6dd643af 100644 --- a/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView/CategoryCardView.swift +++ b/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView/CategoryCardView.swift @@ -10,28 +10,24 @@ import SwiftUI struct CategoryCardView: View { @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel + @Binding var shortcuts: [Shortcuts] + let categoryName: Category let navigationParentView: NavigationParentView var body: some View { VStack(spacing: 0) { HStack { - Text(categoryName.translateName()) - .Title2() - .foregroundColor(Color.Gray5) - .frame(maxWidth: .infinity, alignment: .leading) + SubtitleTextView(text: categoryName.translateName()) Spacer() NavigationLink(value: categoryName) { - Text("더보기") - .Footnote() - .foregroundColor(Color.Gray4) - .padding(.trailing, 16) + MoreCaptionTextView(text: TextLiteral.more) } } - .padding(.leading, 16) + .padding(.horizontal, 16) .padding(.bottom, 12) ScrollView(.horizontal, showsIndicators: false) { @@ -39,13 +35,15 @@ struct CategoryCardView: View { if let shortcuts { ForEach(Array((shortcuts.enumerated())), id: \.offset) { index, shortcut in if index < 7 { - let data = NavigationReadShortcutType(shortcutID: shortcut.id, - navigationParentView: self.navigationParentView) + let data = NavigationReadShortcutType( + shortcutID: shortcut.id, + navigationParentView: self.navigationParentView) NavigationLink(value: data) { - ShortcutCardCell(categoryShortcutIcon: shortcut.sfSymbol, - categoryShortcutName: shortcut.title, - categoryShortcutColor: shortcut.color) + ShortcutCardCell( + categoryShortcutIcon: shortcut.sfSymbol, + categoryShortcutName: shortcut.title, + categoryShortcutColor: shortcut.color) } } } diff --git a/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView/CategoryView.swift b/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView/CategoryView.swift index fcef3915..07a201e7 100644 --- a/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView/CategoryView.swift +++ b/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView/CategoryView.swift @@ -10,32 +10,27 @@ import SwiftUI struct CategoryView: View { @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel - @State var categoryIndex = 6 + @Binding var isFolded: Bool + @State var categoryIndex = 6 var body: some View { VStack { HStack { - Text("카테고리 모아보기") - .Title2() - .foregroundColor(Color.Gray5) - .frame(maxWidth: .infinity, alignment: .leading) + SubtitleTextView(text: TextLiteral.categoryViewTitle) Spacer() Button(action: { self.isFolded.toggle() }, label: { - Text(isFolded ? "펼치기" : "접기") - .Footnote() - .foregroundColor(Color.Gray4) - .padding(.trailing, 16) + MoreCaptionTextView(text: isFolded ? TextLiteral.categoryViewUnfold : TextLiteral.categoryViewFold) }) .onChange(of: isFolded) { _ in categoryIndex = isFolded ? 6 : 12 } } - .padding(.leading, 16) + .padding(.horizontal, 16) LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible())]) { ForEach(Array(Category.allCases.enumerated()), id: \.offset) { index, value in @@ -59,14 +54,14 @@ struct CategoryCellView: View { var body: some View { RoundedRectangle(cornerSize: CGSize(width: 12, height: 12)) - .strokeBorder(Color.Gray1, lineWidth: 1) - .background(Color.White) + .strokeBorder(Color.gray1, lineWidth: 1) + .background(Color.shortcutsZipWhite) .cornerRadius(12) .frame(maxWidth: .infinity, minHeight:48, maxHeight: 48) .overlay { Text(categoryName) .Body2() - .foregroundColor(Color.Gray5) + .foregroundColor(Color.gray5) } } } diff --git a/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView/DownloadRankView.swift b/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView/DownloadRankView.swift index 02516278..5d79e8fa 100644 --- a/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView/DownloadRankView.swift +++ b/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView/DownloadRankView.swift @@ -16,23 +16,17 @@ struct DownloadRankView: View { var body: some View { VStack(spacing: 0) { HStack { - Text("다운로드 순위") - .Title2() - .foregroundColor(Color.Gray5) - .frame(maxWidth: .infinity, alignment: .leading) + SubtitleTextView(text: TextLiteral.downloadRankViewTitle) Spacer() NavigationLink(value: NavigationListShortcutType(sectionType: .download, shortcuts: shortcuts, navigationParentView: .shortcuts)) { - Text("더보기") - .Footnote() - .foregroundColor(Color.Gray4) - .padding(.trailing, 16) + MoreCaptionTextView(text: TextLiteral.more) } } - .padding(.leading, 16) + .padding(.horizontal, 16) .padding(.bottom, 12) ForEach(Array(shortcuts.enumerated()), id:\.offset) { index, shortcut in @@ -46,7 +40,7 @@ struct DownloadRankView: View { } } } - .background(Color.Background) + .background(Color.shortcutsZipBackground) } } } diff --git a/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView/ExploreShortcutView.swift b/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView/ExploreShortcutView.swift index 9599e9e0..5b182ae8 100644 --- a/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView/ExploreShortcutView.swift +++ b/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView/ExploreShortcutView.swift @@ -10,56 +10,55 @@ import SwiftUI struct ExploreShortcutView: View { @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel - let randomCategories: [Category] + @Binding var isFolded: Bool + let randomCategories: [Category] + var body: some View { ScrollView { - RecentRegisteredView(shortcuts: $shortcutsZipViewModel.allShortcuts, + VStack(spacing: 32){ + RecentRegisteredView(shortcuts: $shortcutsZipViewModel.allShortcuts, + navigationParentView: .shortcuts) + + CategoryCardView(shortcuts: $shortcutsZipViewModel.shortcutsInCategory[randomCategories[0].index], + categoryName: randomCategories[0], navigationParentView: .shortcuts) - .padding(.top, 20) - .padding(.bottom, 24) - - CategoryCardView(shortcuts: $shortcutsZipViewModel.shortcutsInCategory[randomCategories[0].index], - categoryName: randomCategories[0], - navigationParentView: .shortcuts) - .padding(.bottom, 24) - DownloadRankView(shortcuts: $shortcutsZipViewModel.sortedShortcutsByDownload, - navigationParentView: .shortcuts) - .padding(.bottom, 24) - - CategoryCardView(shortcuts: $shortcutsZipViewModel.shortcutsInCategory[randomCategories[1].index], - categoryName: randomCategories[1], - navigationParentView: .shortcuts) - .padding(.bottom, 24) - - LovedShortcutView(shortcuts: $shortcutsZipViewModel.sortedShortcutsByLike) - .padding(.bottom, 24) - - CategoryView(isFolded: $isFolded) - .padding(.bottom, 44) + DownloadRankView(shortcuts: $shortcutsZipViewModel.sortedShortcutsByDownload, + navigationParentView: .shortcuts) + + CategoryCardView(shortcuts: $shortcutsZipViewModel.shortcutsInCategory[randomCategories[1].index], + categoryName: randomCategories[1], + navigationParentView: .shortcuts) + + LovedShortcutView(shortcuts: $shortcutsZipViewModel.sortedShortcutsByLike) + + CategoryView(isFolded: $isFolded) + } + .padding(.top, 20) + .padding(.bottom, 44) } .scrollIndicators(.hidden) - .navigationBarTitle(Text("단축어 둘러보기")) + .navigationBarTitle(TextLiteral.exploreShortcutViewTitle) .navigationBarTitleDisplayMode(.large) - .background(Color.Background) + .background(Color.shortcutsZipBackground) .toolbar { ToolbarItem { NavigationLink(value: NavigationSearch.first) { Image(systemName: "magnifyingglass") .Headline() - .foregroundColor(.Gray5) + .foregroundColor(.gray5) } } } - .navigationBarBackground ({ Color.Background }) + .navigationBarBackground ({ Color.shortcutsZipBackground }) } } struct ExploreShortcutView_Previews: PreviewProvider { static var previews: some View { - ExploreShortcutView(randomCategories: [Category.lifestyle, Category.utility], isFolded: .constant(true)) + ExploreShortcutView(isFolded: .constant(true), randomCategories: [Category.lifestyle, Category.utility]) } } diff --git a/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView/ListCategoryView.swift b/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView/ListCategoryView.swift deleted file mode 100644 index 593b70ad..00000000 --- a/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView/ListCategoryView.swift +++ /dev/null @@ -1,52 +0,0 @@ -// -// ListCategoryView.swift -// HappyAnding -// -// Created by 이지원 on 2022/10/25. -// - -import SwiftUI - -struct ListCategoryView: View { - - @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel - private let gridLayout = [GridItem(.flexible()), GridItem(.flexible())] - - var body: some View { - - ZStack(alignment: .top) { - Color.Background - .ignoresSafeArea() - - VStack { - LazyVGrid(columns: gridLayout, spacing: 0) { - ForEach(Category.allCases, id: \.self) { item in - NavigationLink(destination: ShortcutsListView(shortcuts: $shortcutsZipViewModel.shortcutsInCategory[item.index], - categoryName: item, - navigationParentView: .shortcuts)) { - RoundedRectangle(cornerSize: CGSize(width: 12, height: 12)) - .strokeBorder(Color.Gray1, lineWidth: 1) - .background(Color.White) - .cornerRadius(12) - .frame(maxWidth: .infinity, minHeight:48, maxHeight: 48) - .overlay { - Text(item.translateName()) - .Body2() - .foregroundColor(Color.Gray5) - } - .padding(.horizontal, 6) - .padding(.vertical, 7) - } - } - } - .padding(.horizontal, 16) - .padding(.top, 32) - Spacer().frame(maxWidth: .infinity) - } - } - .frame(maxHeight: .infinity) - .navigationBarTitleDisplayMode(.inline) - .navigationTitle("카테고리") - } -} - diff --git a/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView/LovedShortcutView.swift b/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView/LovedShortcutView.swift index 4ce2a9a4..c2b2d724 100644 --- a/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView/LovedShortcutView.swift +++ b/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView/LovedShortcutView.swift @@ -14,23 +14,17 @@ struct LovedShortcutView: View { var body: some View { VStack(spacing: 0) { HStack { - Text("사랑받는 단축어") - .Title2() - .foregroundColor(Color.Gray5) - .frame(maxWidth: .infinity, alignment: .leading) + SubtitleTextView(text: TextLiteral.lovedShortcutViewTitle) Spacer() NavigationLink(value: NavigationListShortcutType(sectionType: .popular, shortcuts: shortcuts, navigationParentView: .shortcuts)) { - Text("더보기") - .Footnote() - .foregroundColor(Color.Gray4) - .padding(.trailing, 16) + MoreCaptionTextView(text: TextLiteral.more) } } - .padding(.leading, 16) + .padding(.horizontal, 16) .padding(.bottom, 12) if let shortcuts { @@ -48,7 +42,7 @@ struct LovedShortcutView: View { } } - .background(Color.Background) + .background(Color.shortcutsZipBackground) } } diff --git a/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView/RecentRegisteredView.swift b/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView/RecentRegisteredView.swift index b489d5c1..2d0251d8 100644 --- a/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView/RecentRegisteredView.swift +++ b/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ExploreShortcutView/RecentRegisteredView.swift @@ -16,10 +16,7 @@ struct RecentRegisteredView: View { var body: some View { VStack(spacing: 0) { HStack { - Text("최신 단축어") - .Title2() - .foregroundColor(Color.Gray5) - .frame(maxWidth: .infinity, alignment: .leading) + SubtitleTextView(text: TextLiteral.recentRegisteredViewTitle) .id(111) Spacer() @@ -27,13 +24,10 @@ struct RecentRegisteredView: View { NavigationLink(value: NavigationListShortcutType(sectionType: .recent, shortcuts: shortcuts, navigationParentView: .shortcuts)) { - Text("더보기") - .Footnote() - .foregroundColor(Color.Gray4) - .padding(.trailing, 16) + MoreCaptionTextView(text: TextLiteral.more) } } - .padding(.leading, 16) + .padding(.horizontal, 16) .padding(.bottom, 12) ForEach(Array(shortcuts.enumerated()), id:\.offset) { index, shortcut in @@ -46,7 +40,7 @@ struct RecentRegisteredView: View { } } } - .background(Color.Background) + .background(Color.shortcutsZipBackground) } } } diff --git a/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ShortcutsListView.swift b/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ListCategoryShortcutView.swift similarity index 79% rename from HappyAnding/HappyAnding/Views/ExploreShortcutViews/ShortcutsListView.swift rename to HappyAnding/HappyAnding/Views/ExploreShortcutViews/ListCategoryShortcutView.swift index 84a20d10..aa7bb613 100644 --- a/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ShortcutsListView.swift +++ b/HappyAnding/HappyAnding/Views/ExploreShortcutViews/ListCategoryShortcutView.swift @@ -7,12 +7,13 @@ import SwiftUI -struct ShortcutsListView: View { +struct ListCategoryShortcutView: View { @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel + @Binding var shortcuts:[Shortcuts] - @State var navigationTitle = "" + @State var navigationTitle = "" @State var isLastShortcut: Bool = false var categoryName: Category @@ -36,18 +37,13 @@ struct ShortcutsListView: View { .listRowSeparator(.hidden) } } - - Rectangle() - .fill(Color.Background) - .frame(height: 44) - .listRowInsets(EdgeInsets()) - .listRowSeparator(.hidden) } + .padding(.bottom, 44) } .navigationBarTitle(categoryName.translateName()) .navigationBarTitleDisplayMode(.inline) - .background(Color.Background) - .navigationBarBackground ({ Color.Background }) + .background(Color.shortcutsZipBackground) + .navigationBarBackground ({ Color.shortcutsZipBackground }) .onAppear { self.shortcuts = shortcutsZipViewModel.shortcutsInCategory[categoryName.index] } @@ -55,15 +51,15 @@ struct ShortcutsListView: View { var scrollHeader: some View { VStack { - Text(categoryName.fetchDescription()) + Text(categoryName.fetchDescription().lineBreaking) } - .foregroundColor(.Gray5) + .foregroundColor(.gray5) .Body2() .padding(16) .frame(maxWidth: .infinity, alignment: .leading) .background( Rectangle() - .foregroundColor(Color.Gray1) + .foregroundColor(Color.gray1) .cornerRadius(12) ) .padding(.vertical, 20) diff --git a/HappyAnding/HappyAnding/Views/HappyAndingApp.swift b/HappyAnding/HappyAnding/Views/HappyAndingApp.swift index 423ec92b..c3aa4ea5 100644 --- a/HappyAnding/HappyAnding/Views/HappyAndingApp.swift +++ b/HappyAnding/HappyAnding/Views/HappyAndingApp.swift @@ -17,13 +17,14 @@ struct HappyAndingApp: App { @Environment(\.openURL) private var openURL @StateObject var shortcutsZipViewModel = ShortcutsZipViewModel() + @StateObject var loginAlerter = Alerter() + + @AppStorage("useWithoutSignIn") var useWithoutSignIn: Bool = false @State var isNeededUpdate = false @State var isShowingLaunchScreen = true @State var version = Version(latestVersion: "", minimumVersion: "", description: "", title: "") - let appID = "6444001181" - init() { FirebaseApp.configure() } @@ -32,7 +33,7 @@ struct HappyAndingApp: App { WindowGroup { if isShowingLaunchScreen { ZStack { - Color.Primary.ignoresSafeArea() + Color.shortcutsZipPrimary.ignoresSafeArea() Text("ShortcutsZip") .foregroundColor(Color.white) .font(.system(size: 26, weight: .bold)) @@ -43,16 +44,16 @@ struct HappyAndingApp: App { Button(role: .cancel) { isShowingLaunchScreen = false } label: { - Text("나중에") + Text(TextLiteral.later) } Button() { - let url = "itms-apps://itunes.apple.com/app/" + self.appID + let url = TextLiteral.appStoreUrl if let url = URL(string: url){ UIApplication.shared.open(url) } isShowingLaunchScreen = false } label: { - Text("업데이트") + Text(TextLiteral.update) } } message: { Text(version.description) @@ -60,6 +61,20 @@ struct HappyAndingApp: App { } else { ShortcutsZipView() .environmentObject(shortcutsZipViewModel) + .environment(\.loginAlertKey, loginAlerter) + .alert(TextLiteral.loginTitle, isPresented: $loginAlerter.isPresented) { + Button(role: .cancel) { + } label: { + Text(TextLiteral.cancel) + } + Button { + useWithoutSignIn = false + } label: { + Text(TextLiteral.loginAction) + } + } message: { + Text(TextLiteral.loginMessage) + } } } .onChange(of: scenePhase) { (newScenePhase) in diff --git a/HappyAnding/HappyAnding/Views/MyPageViews/EditNicknameView.swift b/HappyAnding/HappyAnding/Views/MyPageViews/EditNicknameView.swift index cc6d3830..e4dfe92c 100644 --- a/HappyAnding/HappyAnding/Views/MyPageViews/EditNicknameView.swift +++ b/HappyAnding/HappyAnding/Views/MyPageViews/EditNicknameView.swift @@ -17,26 +17,22 @@ struct EditNicknameView: View { var body: some View { VStack(alignment: .leading) { - Text("닉네임을 수정해주세요") + Text(TextLiteral.editNicknameViewHeadline) .Title1() - .foregroundColor(.Gray5) + .foregroundColor(.gray5) .padding(.top, 40) NicknameTextField(nickname: $nickname, isValid: $isValid, initName: self.user?.nickname ?? "") - .padding(.top, 16) - + .padding(.top, 16) + Spacer() doneButton } .onAppear { nickname = shortcutszipViewModel.userInfo?.nickname ?? "" -//<<<<<<< HEAD shortcutszipViewModel.fetchUser(userID: shortcutszipViewModel.currentUser(), isCurrentUser: true) { user in -//======= -// shortcutszipViewModel.fetchUser(userID: shortcutszipViewModel.currentUser()) { user in -//>>>>>>> develop self.user = user } } @@ -48,8 +44,8 @@ struct EditNicknameView: View { } .padding(.horizontal, 16) .padding(.bottom, 44) - .background(Color.Background) - .navigationTitle("닉네임 수정") + .background(Color.shortcutsZipBackground) + .navigationTitle(TextLiteral.editNicknameViewTitle) .navigationBarTitleDisplayMode(.inline) } @@ -64,10 +60,10 @@ struct EditNicknameView: View { }, label: { ZStack { RoundedRectangle(cornerRadius: 12) - .foregroundColor(isValid ? .Primary : .Primary .opacity(0.13)) + .foregroundColor(isValid ? .shortcutsZipPrimary : .shortcutsZipPrimary .opacity(0.13)) .frame(height: 52) - Text("완료") - .foregroundColor(isValid ? .Text_icon : .Text_Button_Disable) + Text(TextLiteral.done) + .foregroundColor(isValid ? .textIcon : .textButtonDisable) .Body1() } }) diff --git a/HappyAnding/HappyAnding/Views/MyPageViews/MailView.swift b/HappyAnding/HappyAnding/Views/MyPageViews/MailView.swift index 42eb8835..5cb069eb 100644 --- a/HappyAnding/HappyAnding/Views/MyPageViews/MailView.swift +++ b/HappyAnding/HappyAnding/Views/MyPageViews/MailView.swift @@ -49,8 +49,8 @@ struct MailView: UIViewControllerRepresentable { vc.mailComposeDelegate = context.coordinator //이메일 수신자 및 제목 설정. - vc.setToRecipients(["shortcutszip@gmail.com"]) - vc.setSubject("🎤 ShortcutsZip 개발자에게 문의드립니다") + vc.setToRecipients([TextLiteral.mailViewReceiver]) + vc.setSubject(TextLiteral.mailViewSubject) return vc } diff --git a/HappyAnding/HappyAnding/Views/MyPageViews/MyPageView.swift b/HappyAnding/HappyAnding/Views/MyPageViews/MyPageView.swift index dc5be035..eebcd51c 100644 --- a/HappyAnding/HappyAnding/Views/MyPageViews/MyPageView.swift +++ b/HappyAnding/HappyAnding/Views/MyPageViews/MyPageView.swift @@ -10,6 +10,7 @@ import SwiftUI struct MyPageView: View { @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel + @AppStorage("useWithoutSignIn") var useWithoutSignIn: Bool = false enum NavigationSettingView: Hashable, Equatable { @@ -31,19 +32,19 @@ struct MyPageView: View { Image(systemName: "person.crop.circle.fill") .font(.system(size: 60, weight: .medium)) .frame(width: 60, height: 60) - .foregroundColor(.Gray3) + .foregroundColor(.gray3) .id(333) HStack { - Text(shortcutsZipViewModel.userInfo?.nickname ?? "사용자") + Text(shortcutsZipViewModel.userInfo?.nickname ?? TextLiteral.defaultUser) .Title1() - .foregroundColor(.Gray5) + .foregroundColor(.gray5) if !useWithoutSignIn { NavigationLink(value: NavigationNicknameView.first) { Image(systemName: "square.and.pencil") .Title2() - .foregroundColor(.Gray4) + .foregroundColor(.gray4) } } } @@ -63,7 +64,7 @@ struct MyPageView: View { // MARK: - 내가 작성한 큐레이션 UserCurationListView(data: NavigationListCurationType(type: .myCuration, - title: "내가 작성한 추천 모음집", + title: TextLiteral.myPageViewMyCuration, isAllUser: false, navigationParentView: .myPage, curation: shortcutsZipViewModel.curationsMadeByUser)) @@ -79,19 +80,19 @@ struct MyPageView: View { .padding(.bottom, 44) } } - .navigationBarTitle("프로필") + .navigationBarTitle(TextLiteral.myPageViewTitle) .navigationBarTitleDisplayMode(.large) .toolbar { ToolbarItem { NavigationLink(value: NavigationSettingView.first) { Image(systemName: "gearshape.fill") .Headline() - .foregroundColor(.Gray5) + .foregroundColor(.gray5) } } } .scrollIndicators(.hidden) - .background(Color.Background) + .background(Color.shortcutsZipBackground) .navigationDestination(for: NavigationNicknameView.self) { _ in EditNicknameView() } @@ -113,25 +114,25 @@ struct MyPageShortcutListCell: View { var body: some View { NavigationLink(value: data) { HStack() { - Text(type == .myLovingShortcut ? "좋아요한 단축어" : "다운로드한 단축어") + Text(type == .myLovingShortcut ? TextLiteral.myPageViewLikedShortcuts : TextLiteral.myPageViewDownloadedShortcuts) .Title2() - .foregroundColor(.Gray5) + .foregroundColor(.gray5) .padding(.trailing, 9) Text("\(shortcuts.count)개") .Body2() - .foregroundColor(Color.Tag_Text) + .foregroundColor(Color.tagText) .padding(.horizontal, 12) .padding(.vertical, 4) .background( RoundedRectangle(cornerRadius: 16) - .fill( Color.Tag_Background ) + .fill( Color.tagBackground ) .overlay( RoundedRectangle(cornerRadius: 16) - .strokeBorder(Color.Primary, lineWidth: 1)) + .strokeBorder(Color.shortcutsZipPrimary, lineWidth: 1)) ) Spacer() Image(systemName: "chevron.forward") - .foregroundColor(.Gray5) + .foregroundColor(.gray5) .font(Font(UIFont.systemFont(ofSize: 20, weight: .medium))) } diff --git a/HappyAnding/HappyAnding/Views/MyPageViews/SettingView.swift b/HappyAnding/HappyAnding/Views/MyPageViews/SettingView.swift index adced25f..8ee39ebc 100644 --- a/HappyAnding/HappyAnding/Views/MyPageViews/SettingView.swift +++ b/HappyAnding/HappyAnding/Views/MyPageViews/SettingView.swift @@ -11,12 +11,13 @@ import SwiftUI import FirebaseAuth struct SettingView: View { + @EnvironmentObject var userAuth: UserAuth + @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel + + @ObservedObject var webViewModel = WebViewModel() @AppStorage("signInStatus") var signInStatus = false @AppStorage("useWithoutSignIn") var useWithoutSignIn = false - @EnvironmentObject var userAuth: UserAuth - @ObservedObject var webViewModel = WebViewModel() - @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel @State var result: Result? = nil @State var isShowingMailView = false @@ -48,13 +49,13 @@ struct SettingView: View { */ // MARK: - 버전 정보 - SettingCell(title: "버전정보", version: "1.2.0") + SettingCell(title: TextLiteral.settingViewVersion, version: TextLiteral.settingViewVersionNumber) // MARK: - 오픈소스 라이선스 NavigationLink(value: NavigationLisence.first) { - SettingCell(title: "오픈소스 라이선스") + SettingCell(title: TextLiteral.settingViewOpensourceLicense) } @@ -63,7 +64,7 @@ struct SettingView: View { Button { self.isTappedPrivacyButton.toggle() } label: { - SettingCell(title: "개인정보처리방침") + SettingCell(title: TextLiteral.settingViewPrivacyPolicy) } @@ -81,11 +82,11 @@ struct SettingView: View { } }) { if MFMailComposeViewController.canSendMail() { - SettingCell(title: "개발자에게 연락하기") + SettingCell(title: TextLiteral.settingViewContact) } //못 보내는 기기일 때 뜨는 것. 아예 지워도 될 것 같긴 한데 어떻게할까요. 못 보내는 기기의 기준이 확실치 않아서 일단 이렇게 둠. else { - SettingCell(title: "문의사항은 shortcutszip@gmail.com 으로 메일 주세요") + SettingCell(title: TextLiteral.settingViewContactMessage) .multilineTextAlignment(.leading) } } @@ -96,7 +97,7 @@ struct SettingView: View { Button { useWithoutSignIn = false } label: { - SettingCell(title: "로그인") + SettingCell(title: TextLiteral.settingViewLogin) } } else { @@ -104,27 +105,27 @@ struct SettingView: View { Button { self.isTappedLogOutButton.toggle() } label: { - SettingCell(title: "로그아웃") + SettingCell(title: TextLiteral.settingViewLogout) } - .alert("로그아웃", isPresented: $isTappedLogOutButton) { + .alert(TextLiteral.settingViewLogout, isPresented: $isTappedLogOutButton) { Button(role: .cancel) { } label: { - Text("닫기") + Text(TextLiteral.cancel) } Button(role: .destructive) { logOut() } label: { - Text("로그아웃") + Text(TextLiteral.settingViewLogout) } } message: { - Text("로그아웃 하시겠습니까?") + Text(TextLiteral.settingViewLogoutMessage) } // MARK: - 회원탈퇴 버튼 NavigationLink(value: NavigationWithdrawal.first) { - SettingCell(title: "탈퇴하기") + SettingCell(title: TextLiteral.settingViewWithdrawal) } } @@ -138,7 +139,7 @@ struct SettingView: View { ZStack { PrivacyPolicyView(viewModel: webViewModel, isTappedPrivacyButton: $isTappedPrivacyButton, - url: "https://noble-satellite-574.notion.site/60d8fa2f417c40cca35e9c784f74b7fd") + url: TextLiteral.settingViewPrivacyPolicyURL) .environmentObject(webViewModel) .presentationDetents([.large]) .presentationDragIndicator(.visible) @@ -157,7 +158,7 @@ struct SettingView: View { } .padding(.horizontal, 16) - .background(Color.Background) + .background(Color.shortcutsZipBackground) .navigationBarTitleDisplayMode(.inline) } @@ -169,6 +170,7 @@ struct SettingView: View { userAuth.signOut() self.signInStatus = false shortcutsZipViewModel.resetUser() + UserDefaults.shared.set(false, forKey: "isSignInForShareExtension") } catch { print(error.localizedDescription) } @@ -184,7 +186,7 @@ struct SettingCell: View { if let version {Text(version)} } .Body1() - .foregroundColor(.Gray4) + .foregroundColor(.gray4) .padding(.horizontal, 12) .padding(.vertical, 16) } diff --git a/HappyAnding/HappyAnding/Views/MyPageViews/SettingViews/AboutTeamView.swift b/HappyAnding/HappyAnding/Views/MyPageViews/SettingViews/AboutTeamView.swift index 72e953da..0e345276 100644 --- a/HappyAnding/HappyAnding/Views/MyPageViews/SettingViews/AboutTeamView.swift +++ b/HappyAnding/HappyAnding/Views/MyPageViews/SettingViews/AboutTeamView.swift @@ -14,12 +14,12 @@ struct AboutTeamView: View { VStack { Text("Team Happy ANDing") .Title1() - .foregroundColor(Color.Gray5) + .foregroundColor(Color.gray5) .multilineTextAlignment(.leading) .padding(.horizontal, 16) Text("안녕하세요. ShortcutsZip의 개발팀 Team Happy ANDing입니다. ") .Body2() - .foregroundColor(Color.Gray3) + .foregroundColor(Color.gray3) .multilineTextAlignment(.leading) .padding(.bottom, 16) } @@ -33,7 +33,7 @@ struct AboutTeamView: View { .padding(.top, 12) } .frame(maxWidth: .infinity, maxHeight: . infinity) - .background(Color.Background) + .background(Color.shortcutsZipBackground) .scrollIndicators(.hidden) .navigationTitle("개발팀에 관하여") } @@ -42,7 +42,7 @@ struct AboutTeamView: View { ZStack { RoundedRectangle(cornerRadius: 12) .frame(height: 200) - .foregroundColor(Color.Gray2) + .foregroundColor(Color.gray2) .contextMenu{ Button { // Add this item to a list of favorites. diff --git a/HappyAnding/HappyAnding/Views/MyPageViews/SettingViews/LicenseView.swift b/HappyAnding/HappyAnding/Views/MyPageViews/SettingViews/LicenseView.swift index 80421352..2ae5a598 100644 --- a/HappyAnding/HappyAnding/Views/MyPageViews/SettingViews/LicenseView.swift +++ b/HappyAnding/HappyAnding/Views/MyPageViews/SettingViews/LicenseView.swift @@ -14,7 +14,7 @@ struct LicenseView: View { LicenseCell(title: "[Firebase](https://github.com/firebase)", text: "License\nThe contents of this repository are licensed under the Apache License, version 2.0.\nYour use of Firebase is governed by the Terms of Service for Firebase Services.") LicenseCell(title: "Apache License 2.0", text: readTextFile("apache.txt")) } - .background(Color.Background) + .background(Color.shortcutsZipBackground) } } @@ -23,6 +23,7 @@ struct LicenseCell: View { @ObservedObject var webViewModel = WebViewModel() @State private var isTappedFirebaseButton = false + var title: String var text: String @@ -30,14 +31,14 @@ struct LicenseCell: View { VStack(alignment: .leading) { Text(.init(title)) .Title2() - .foregroundColor(Color.Gray5) + .foregroundColor(Color.gray5) .multilineTextAlignment(.leading) .padding(.top, 36) - .tint(.Gray5) + .tint(.gray5) Text(text) .Body2() - .foregroundColor(Color.Gray4) + .foregroundColor(Color.gray4) .multilineTextAlignment(.leading) Spacer() } diff --git a/HappyAnding/HappyAnding/Views/MyPageViews/SettingViews/WithdrawalView.swift b/HappyAnding/HappyAnding/Views/MyPageViews/SettingViews/WithdrawalView.swift index 5097eca1..16d7897a 100644 --- a/HappyAnding/HappyAnding/Views/MyPageViews/SettingViews/WithdrawalView.swift +++ b/HappyAnding/HappyAnding/Views/MyPageViews/SettingViews/WithdrawalView.swift @@ -10,42 +10,39 @@ import SwiftUI import FirebaseAuth struct WithdrawalView: View { + @Environment(\.window) var window: UIWindow? + @EnvironmentObject var userAuth: UserAuth + @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel @AppStorage("signInStatus") var signInStatus = false @AppStorage("isReauthenticated") var isReauthenticated = false @AppStorage("isTappedSignOutButton") var isTappedSignOutButton = false - @EnvironmentObject var userAuth: UserAuth - @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel - @State private var appleLoginCoordinator: AppleAuthCoordinator? - @Environment(\.window) var window: UIWindow? - @State var isTappedCheckToggle = false - private let signOutTitle = ["탈퇴 시 삭제되는 항목", - "탈퇴 시 삭제되지 않는 항목"] - private let signOutDescription = ["로그인 정보 / 닉네임 / 좋아요한 단축어 목록 /\n 다운로드 한 단축어 목록", - "작성한 단축어 / 작성한 추천 모음집"] + private let signOutTitle = [TextLiteral.withdrawalViewDeleteTitle, + TextLiteral.withdrawalViewNoDeleteTitle] + private let signOutDescription = [TextLiteral.withdrawalViewDeleteContent, TextLiteral.withdrawalViewNoDeleteContent] var body: some View { VStack(alignment: .leading) { - Text("ShortcutsZip에서 탈퇴 시 다음과 같이 사용자 데이터가 처리됩니다.") + Text(TextLiteral.withdrawalViewHeadline) .Title2() - .foregroundColor(.Gray5) + .foregroundColor(.gray5) .multilineTextAlignment(.leading) .padding(.vertical, 32) ForEach(0.. String { - switch categoryName { - case "education": - return "교육" - case "finance": - return "금융" - case "business": - return "비즈니스" - case "health": - return "건강 및 피트니스" - case "lifestyle": - return "라이프스타일" - case "weather": - return "날씨" - case "photo": - return "사진 및 비디오" - case "decoration": - return "데코레이션/꾸미기" - case "utility": - return "유틸리티" - case "sns": - return "소셜 네트워킹" - case "entertainment": - return "엔터테인먼트" - case "trip": - return "여행" - default: - return "" - } - } } private struct ReusableTextView: View { @@ -96,11 +63,11 @@ private struct ReusableTextView: View { VStack(alignment: .leading) { Text(title) .Body2() - .foregroundColor(Color.Gray4) + .foregroundColor(Color.gray4) if let contents { Text(contents) .Body2() - .foregroundColor(Color.Gray5) + .foregroundColor(Color.gray5) .lineLimit(nil) } if let contentsArray { @@ -108,7 +75,7 @@ private struct ReusableTextView: View { content in Text(content) .Body2() - .foregroundColor(Color.Gray5) + .foregroundColor(Color.gray5) .lineLimit(nil) } } diff --git a/HappyAnding/HappyAnding/Views/ShortcutDetailViews/ReadShortcutView/ReadShortcutHeaderView.swift b/HappyAnding/HappyAnding/Views/ShortcutDetailViews/ReadShortcutView/ReadShortcutHeaderView.swift index c4cae882..671cd28c 100644 --- a/HappyAnding/HappyAnding/Views/ShortcutDetailViews/ReadShortcutView/ReadShortcutHeaderView.swift +++ b/HappyAnding/HappyAnding/Views/ShortcutDetailViews/ReadShortcutView/ReadShortcutHeaderView.swift @@ -8,17 +8,17 @@ import SwiftUI struct ReadShortcutHeaderView: View { - + @Environment(\.loginAlertKey) var loginAlerter @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel + @AppStorage("useWithoutSignIn") var useWithoutSignIn: Bool = false + @Binding var shortcut: Shortcuts @Binding var isMyLike: Bool + @State var userInformation: User? = nil @State var numberOfLike = 0 - @AppStorage("useWithoutSignIn") var useWithoutSignIn: Bool = false - @State private var tryActionWithoutSignIn: Bool = false - var body: some View { VStack(alignment: .leading, spacing: 16) { HStack { @@ -33,31 +33,16 @@ struct ReadShortcutHeaderView: View { VStack(alignment: .leading, spacing: 4) { Text("\(shortcut.title)") .Title1() - .foregroundColor(Color.Gray5) + .foregroundColor(Color.gray5) .fixedSize(horizontal: false, vertical: true) Text("\(shortcut.subtitle)") .Body1() - .foregroundColor(Color.Gray3) + .foregroundColor(Color.gray3) .fixedSize(horizontal: false, vertical: true) } userInfo } - .alert("로그인을 진행해주세요", isPresented: $tryActionWithoutSignIn) { - Button(role: .cancel) { - tryActionWithoutSignIn = false - } label: { - Text("취소") - } - Button { - useWithoutSignIn = false - tryActionWithoutSignIn = false - } label: { - Text("로그인하기") - } - } message: { - Text("이 기능은 로그인 후 사용할 수 있어요") - } .frame(maxWidth: .infinity, alignment: .leading) .padding(.horizontal, 16) .onAppear() { @@ -75,7 +60,7 @@ struct ReadShortcutHeaderView: View { VStack { Image(systemName: shortcut.sfSymbol) .Title2() - .foregroundColor(Color.Text_icon) + .foregroundColor(Color.textIcon) } .frame(width: 52, height: 52) .background(Color.fetchGradient(color: shortcut.color)) @@ -87,8 +72,8 @@ struct ReadShortcutHeaderView: View { Text("\(isMyLike ? Image(systemName: "heart.fill") : Image(systemName: "heart")) \(numberOfLike)") .Body2() .padding(10) - .foregroundColor(isMyLike ? Color.Text_icon : Color.Gray4) - .background(isMyLike ? Color.Primary : Color.Gray1) + .foregroundColor(isMyLike ? Color.textIcon : Color.gray4) + .background(isMyLike ? Color.shortcutsZipPrimary : Color.gray1) .cornerRadius(12) .onTapGesture { if !useWithoutSignIn { @@ -96,7 +81,7 @@ struct ReadShortcutHeaderView: View { //화면 상의 좋아요 추가, 취소 기능 동작 numberOfLike += isMyLike ? 1 : -1 } else { - tryActionWithoutSignIn = true + loginAlerter.isPresented = true } } } @@ -111,12 +96,12 @@ struct ReadShortcutHeaderView: View { Image(systemName: "person.crop.circle.fill") .font(.system(size: 24, weight: .medium)) .frame(width: 24, height: 24) - .foregroundColor(.Gray3) + .foregroundColor(.gray3) .padding(.leading, 16) - Text(userInformation?.nickname ?? "탈퇴한 사용자") + Text(userInformation?.nickname ?? TextLiteral.withdrawnUser) .Body2() - .foregroundColor(.Gray4) + .foregroundColor(.gray4) Spacer() .frame(maxWidth: .infinity) @@ -127,7 +112,7 @@ struct ReadShortcutHeaderView: View { /* Image(systemName: "light.beacon.max.fill") .Headline() - .foregroundColor(.Gray5) + .foregroundColor(.gray5) .padding(.trailing, 16) .onTapGesture { print("Tapped!") @@ -141,7 +126,7 @@ struct ReadShortcutHeaderView: View { .frame(maxWidth: .infinity, maxHeight: 44) .overlay { RoundedRectangle(cornerRadius: 12) - .stroke(Color.Gray1, lineWidth: 1) + .stroke(Color.gray1, lineWidth: 1) } } } diff --git a/HappyAnding/HappyAnding/Views/ShortcutDetailViews/ReadShortcutView/ReadShortcutVersionView.swift b/HappyAnding/HappyAnding/Views/ShortcutDetailViews/ReadShortcutView/ReadShortcutVersionView.swift index 51ccb19f..d3623dde 100644 --- a/HappyAnding/HappyAnding/Views/ShortcutDetailViews/ReadShortcutView/ReadShortcutVersionView.swift +++ b/HappyAnding/HappyAnding/Views/ShortcutDetailViews/ReadShortcutView/ReadShortcutVersionView.swift @@ -8,47 +8,47 @@ import SwiftUI struct ReadShortcutVersionView: View { - - @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel @Environment(\.openURL) var openURL + @Environment(\.loginAlertKey) var loginAlerter + @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel + + @AppStorage("useWithoutSignIn") var useWithoutSignIn: Bool = false @Binding var shortcut: Shortcuts @Binding var isUpdating: Bool - @AppStorage("useWithoutSignIn") var useWithoutSignIn: Bool = false - @State private var tryActionWithoutSignIn: Bool = false - var body: some View { VStack(alignment: .leading, spacing: 16) { if shortcut.updateDescription.count == 1 { - Text("아직 업데이트된 버전이 없습니다.") + Text(TextLiteral.readShortcutVersionViewNoUpdates) .Body2() - .foregroundColor(.Gray4) + .foregroundColor(.gray4) .padding(.top, 16) Spacer() .frame(maxHeight: .infinity) } else { - Text("업데이트 내용") + Text(TextLiteral.readShortcutVersionViewUpdateContent) .Body2() - .foregroundColor(.Gray4) + .foregroundColor(.gray4) + ForEach(Array(zip(shortcut.updateDescription, shortcut.updateDescription.indices)), id: \.0) { data, index in VStack(alignment: .leading, spacing: 12) { HStack { Text("Ver \(shortcut.updateDescription.count - index).0") .Body2() - .foregroundColor(.Gray5) + .foregroundColor(.gray5) Spacer() Text(shortcut.date[index].getVersionUpdateDateFormat()) .Body2() - .foregroundColor(.Gray3) + .foregroundColor(.gray3) } if data != "" { Text(data) .Body2() - .foregroundColor(.Gray5) + .foregroundColor(.gray5) } if index != 0 { Button { @@ -61,16 +61,16 @@ struct ReadShortcutVersionView: View { openURL(url) } } else { - self.tryActionWithoutSignIn = true + loginAlerter.isPresented = true } } label: { - Text("이전 버전 다운로드") + Text(TextLiteral.readShortcutVersionViewDownloadPreviousVersion) .Body2() - .foregroundColor(.Primary) + .foregroundColor(.shortcutsZipPrimary) } } Divider() - .foregroundColor(.Gray1) + .foregroundColor(.gray1) } } @@ -78,21 +78,6 @@ struct ReadShortcutVersionView: View { .frame(maxHeight: .infinity) } } - .alert("로그인을 진행해주세요", isPresented: $tryActionWithoutSignIn) { - Button(role: .cancel) { - tryActionWithoutSignIn = false - } label: { - Text("취소") - } - Button { - useWithoutSignIn = false - tryActionWithoutSignIn = false - } label: { - Text("로그인하기") - } - } message: { - Text("이 기능은 로그인 후 사용할 수 있어요") - } .padding(.top, 16) } } diff --git a/HappyAnding/HappyAnding/Views/ShortcutDetailViews/ReadShortcutView/ReadShortcutView.swift b/HappyAnding/HappyAnding/Views/ShortcutDetailViews/ReadShortcutView/ReadShortcutView.swift index 5695fa20..1f6c78e2 100644 --- a/HappyAnding/HappyAnding/Views/ShortcutDetailViews/ReadShortcutView/ReadShortcutView.swift +++ b/HappyAnding/HappyAnding/Views/ShortcutDetailViews/ReadShortcutView/ReadShortcutView.swift @@ -8,6 +8,10 @@ import SwiftUI struct ReadShortcutView: View { + @Environment(\.presentationMode) var presentationMode: Binding + @Environment(\.presentationMode) var presentation: Binding + @Environment(\.openURL) private var openURL + @Environment(\.loginAlertKey) var loginAlerter @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel @EnvironmentObject var shortcutNavigation: ShortcutNavigation @@ -16,11 +20,8 @@ struct ReadShortcutView: View { @EnvironmentObject var writeCurationNavigation: WriteCurationNavigation @EnvironmentObject var profileNavigation: ProfileNavigation - @Environment(\.presentationMode) var presentationMode: Binding - @Environment(\.presentationMode) var presentation: Binding - @Environment(\.openURL) private var openURL - @StateObject var writeNavigation = WriteShortcutNavigation() + @State var isTappedDeleteButton = false @State var isEdit = false @State var isUpdating = false @@ -36,44 +37,35 @@ struct ReadShortcutView: View { @State var currentTab: Int = 0 @State var commentText = "" - @FocusState private var isFocused: Bool - @Namespace var namespace - @State var isClickCorrection = false //댓글 수정버튼 클릭했는지? @State var isCancledCorrection = false //댓글 수정 중 텍스트필드를 제외한 부분을 터치했는지? @AppStorage("useWithoutSignIn") var useWithoutSignIn: Bool = false - @State private var tryActionWithoutSignIn: Bool = false + @FocusState private var isFocused: Bool + @Namespace var namespace - private let tabItems = ["기본 정보", "버전 정보", "댓글"] + private let tabItems = [TextLiteral.readShortcutViewBasicTabTitle, TextLiteral.readShortcutViewVersionTabTitle, TextLiteral.readShortcutViewCommentTabTitle] var body: some View { ZStack { ScrollView { VStack(spacing: 0) { if data.shortcut != nil { - GeometryReader { geo in - let yOffset = geo.frame(in: .global).minY - - Color.White - .frame(width: geo.size.width, height: 40 + (yOffset > 0 ? yOffset : 0)) - .offset(y: yOffset > 0 ? -yOffset : 0) - } - .frame(minHeight: 40) + StickyHeader(height: 40) // MARK: - 단축어 타이틀 ReadShortcutHeaderView(shortcut: $data.shortcut.unwrap()!, isMyLike: $isMyLike) .frame(minHeight: 160) .padding(.bottom, 33) - .background(Color.White) + .background(Color.shortcutsZipWhite) // MARK: - 탭뷰 (기본 정보, 버전 정보, 댓글) LazyVStack(pinnedViews: [.sectionHeaders]) { Section(header: tabBarView - .background(Color.White) + .background(Color.shortcutsZipWhite) ) { detailInformationView .padding(.top, 4) @@ -83,24 +75,9 @@ struct ReadShortcutView: View { } } } - .alert("로그인을 진행해주세요", isPresented: $tryActionWithoutSignIn) { - Button(role: .cancel) { - tryActionWithoutSignIn = false - } label: { - Text("취소") - } - Button { - useWithoutSignIn = false - tryActionWithoutSignIn = false - } label: { - Text("로그인하기") - } - } message: { - Text("이 기능은 로그인 후 사용할 수 있어요") - } .scrollDisabled(isClickCorrection) - .navigationBarBackground ({ Color.White }) - .background(Color.Background) + .navigationBarBackground ({ Color.shortcutsZipWhite }) + .background(Color.shortcutsZipBackground) .safeAreaInset(edge: .bottom, spacing: 0) { VStack { @@ -121,15 +98,15 @@ struct ReadShortcutView: View { } shortcutsZipViewModel.updateNumberOfDownload(shortcut: shortcut, downloadlinkIndex: 0) } else { - self.tryActionWithoutSignIn = true + loginAlerter.isPresented = true } } label: { Text("다운로드 | \(Image(systemName: "arrow.down.app.fill")) \(shortcut.numberOfDownload)") .Body1() - .foregroundColor(Color.Text_icon) + .foregroundColor(Color.textIcon) .padding() .frame(maxWidth: .infinity) - .background(Color.Primary) + .background(Color.shortcutsZipPrimary) } } } @@ -161,10 +138,10 @@ struct ReadShortcutView: View { } .navigationBarTitleDisplayMode(NavigationBarItem.TitleDisplayMode.inline) .navigationBarItems(trailing: readShortcutViewButtonByUser()) - .alert("글 삭제", isPresented: $isTappedDeleteButton) { + .alert(TextLiteral.readShortcutViewDeletionTitle, isPresented: $isTappedDeleteButton) { Button(role: .cancel) { } label: { - Text("닫기") + Text(TextLiteral.cancel) } Button(role: .destructive) { @@ -176,15 +153,15 @@ struct ReadShortcutView: View { self.presentation.wrappedValue.dismiss() } } label: { - Text("삭제") + Text(TextLiteral.delete) } } message: { - Text("글을 삭제하시겠습니까?") + Text(TextLiteral.readShortcutViewDeletionMessage) } .fullScreenCover(isPresented: $isEdit) { NavigationStack(path: $writeNavigation.navigationPath) { if let shortcut = data.shortcut { - WriteShortcutTitleView(isWriting: $isEdit, + WriteShortcutView(isWriting: $isEdit, shortcut: shortcut, isEdit: true) } @@ -216,11 +193,11 @@ struct ReadShortcutView: View { isFocused.toggle() isCancledCorrection.toggle() } - .alert("글 삭제", isPresented: $isCancledCorrection) { + .alert(TextLiteral.readShortcutViewDeletionTitle, isPresented: $isCancledCorrection) { Button(role: .cancel) { isFocused.toggle() } label: { - Text("계속 작성") + Text(TextLiteral.readShortcutViewKeepFixes) } Button(role: .destructive) { @@ -230,10 +207,10 @@ struct ReadShortcutView: View { commentText = "" } } label: { - Text("삭제") + Text(TextLiteral.delete) } } message: { - Text("수정사항을 삭제하시겠습니까?") + Text(TextLiteral.readShortcutViewDeleteFixes) } } @@ -252,9 +229,9 @@ extension ReadShortcutView { HStack { if comment.depth == 1 && !isClickCorrection { Image(systemName: "arrow.turn.down.right") - .foregroundColor(.Gray4) + .foregroundColor(.gray4) } - TextField(useWithoutSignIn ? "로그인 후 댓글을 작성할 수 있어요" : "댓글을 입력하세요", text: $commentText, axis: .vertical) + TextField(useWithoutSignIn ? TextLiteral.readShortcutViewCommentDescriptionBeforeLogin : TextLiteral.readShortcutViewCommentDescription, text: $commentText, axis: .vertical) .disabled(useWithoutSignIn == true) .disableAutocorrection(true) .textInputAutocapitalization(.never) @@ -282,7 +259,7 @@ extension ReadShortcutView { isFocused.toggle() } label: { Image(systemName: "paperplane.fill") - .foregroundColor(commentText == "" ? Color.Gray2 : Color.Gray5) + .foregroundColor(commentText == "" ? Color.gray2 : Color.gray5) } .disabled(commentText == "" ? true : false) } @@ -290,7 +267,7 @@ extension ReadShortcutView { .padding(.horizontal, 16) .background( Rectangle() - .fill(Color.Gray1) + .fill(Color.gray1) .cornerRadius(12 ,corners: (comment.depth == 1) && (!isClickCorrection) ? [.bottomLeft, .bottomRight] : .allCorners) ) .padding(.horizontal, 16) @@ -301,7 +278,7 @@ extension ReadShortcutView { HStack { Text("@ \(nestedCommentInfoText)") .Footnote() - .foregroundColor(.Gray5) + .foregroundColor(.gray5) Spacer() Button { comment.bundle_id = "\(Date().getDate())_\(UUID().uuidString)" @@ -309,14 +286,14 @@ extension ReadShortcutView { } label: { Image(systemName: "xmark") .font(Font(UIFont.systemFont(ofSize: 17, weight: .medium))) - .foregroundColor(.Gray5) + .foregroundColor(.gray5) } } .padding(.horizontal, 16) .padding(.vertical, 11) .background( Rectangle() - .fill(Color.Gray2) + .fill(Color.gray2) .cornerRadius(12 ,corners: [.topLeft, .topRight]) ) .padding(.horizontal, 16) @@ -341,7 +318,7 @@ extension ReadShortcutView { } }, label: { Image(systemName: "ellipsis") - .foregroundColor(.Gray4) + .foregroundColor(.gray4) }) } @@ -349,7 +326,7 @@ extension ReadShortcutView { Button { isEdit.toggle() } label: { - Label("편집", systemImage: "square.and.pencil") + Label(TextLiteral.edit, systemImage: "square.and.pencil") } } @@ -357,7 +334,7 @@ extension ReadShortcutView { Button { isUpdating.toggle() } label: { - Label("업데이트", systemImage: "clock.arrow.circlepath") + Label(TextLiteral.update, systemImage: "clock.arrow.circlepath") } } @@ -365,8 +342,8 @@ extension ReadShortcutView { Button(action: { shareShortcut() }) { - Label("공유", systemImage: "square.and.arrow.up") - .foregroundColor(.Gray4) + Label(TextLiteral.share, systemImage: "square.and.arrow.up") + .foregroundColor(.gray4) .fontWeight(.medium) } } @@ -377,7 +354,7 @@ extension ReadShortcutView { // TODO: firebase delete function }) { - Label("삭제", systemImage: "trash.fill") + Label(TextLiteral.delete, systemImage: "trash.fill") } } @@ -413,11 +390,11 @@ extension ReadShortcutView { case 1: ReadShortcutVersionView(shortcut: $data.shortcut.unwrap()!, isUpdating: $isUpdating) case 2: - ReadShortcutCommentView(addedComment: $comment, + ReadShortcutCommentView(isFocused: _isFocused, + addedComment: $comment, comments: $comments, nestedCommentInfoText: $nestedCommentInfoText, isClickCorrenction: $isClickCorrection, - isFocused: _isFocused, shortcutID: data.shortcutID) default: EmptyView() @@ -466,15 +443,15 @@ extension ReadShortcutView { if self.currentTab == tab { Text(string) .Headline() - .foregroundColor(.Gray5) - Color.Gray5 + .foregroundColor(.gray5) + Color.gray5 .frame(height: 2) .matchedGeometryEffect(id: "underline", in: namespace, properties: .frame) } else { Text(string) .Body1() - .foregroundColor(.Gray3) + .foregroundColor(.gray3) Color.clear.frame(height: 2) } } diff --git a/HappyAnding/HappyAnding/Views/ShortcutDetailViews/ShowProfileView.swift b/HappyAnding/HappyAnding/Views/ShortcutDetailViews/ShowProfileView.swift index d5e6f58a..8b3235f3 100644 --- a/HappyAnding/HappyAnding/Views/ShortcutDetailViews/ShowProfileView.swift +++ b/HappyAnding/HappyAnding/Views/ShortcutDetailViews/ShowProfileView.swift @@ -15,34 +15,31 @@ struct ShowProfileView: View { @State var shortcuts: [Shortcuts] = [] @State var curations: [Curation] = [] - @Namespace var namespace @State var currentTab: Int = 0 - private let tabItems = ["작성한 단축어", "작성한 추천 모음집"] + + @Namespace var namespace + + private let tabItems = [TextLiteral.showProfileViewShortcutTabTitle, TextLiteral.showProfileViewCurationTabTitle] var body: some View { ScrollView { VStack(spacing: 0) { - GeometryReader { geo in - let yOffset = geo.frame(in: .global).minY - - Color.White - .frame(width: geo.size.width, height: 40 + (yOffset > 0 ? yOffset : 0)) - .offset(y: yOffset > 0 ? -yOffset : 0) - } + + StickyHeader(height: 40) //MARK: 프로필이미지 및 닉네임 VStack { Image(systemName: "person.crop.circle.fill") .font(.system(size: 72, weight: .medium)) .frame(width: 72, height: 72) - .foregroundColor(.Gray3) - Text(data.userInfo?.nickname ?? "user") + .foregroundColor(.gray3) + Text(data.userInfo?.nickname ?? TextLiteral.defaultUser) .Title1() - .foregroundColor(.Gray5) + .foregroundColor(.gray5) } .frame(maxWidth: .infinity) .frame(height: 160) - .background(Color.White) + .background(Color.shortcutsZipWhite) //MARK: 탭바 및 탭 내부 컨텐츠 LazyVStack(pinnedViews: [.sectionHeaders]) { @@ -53,8 +50,8 @@ struct ShowProfileView: View { } } } - .navigationBarBackground { Color.White } - .background(Color.Background) + .navigationBarBackground { Color.shortcutsZipWhite } + .background(Color.shortcutsZipBackground) .toolbar(.visible, for: .tabBar) .onAppear { shortcuts = shortcutsZipViewModel.allShortcuts.filter { $0.author == self.data.userInfo?.id } @@ -74,7 +71,7 @@ extension ShowProfileView { } .padding(.horizontal, 16) .frame(height: 36) - .background(Color.White) + .background(Color.shortcutsZipWhite) } private func tabBarItem(string: String, tab: Int) -> some View { @@ -85,15 +82,15 @@ extension ShowProfileView { if self.currentTab == tab { Text(string) .Headline() - .foregroundColor(.Gray5) - Color.Gray5 + .foregroundColor(.gray5) + Color.gray5 .frame(height: 2) .matchedGeometryEffect(id: "underline", in: namespace, properties: .frame) } else { Text(string) .Body1() - .foregroundColor(.Gray3) + .foregroundColor(.gray3) Color.clear .frame(height: 2) } @@ -118,10 +115,10 @@ extension ShowProfileView { case 0: if shortcuts.isEmpty { VStack { - Text("작성한 단축어가 없습니다.") + Text(TextLiteral.showProfileViewNoShortcuts) .padding(.top, 16) .Body2() - .foregroundColor(.Gray4) + .foregroundColor(.gray4) Spacer() } } @@ -143,10 +140,10 @@ extension ShowProfileView { case 1: if curations.isEmpty { VStack{ - Text("작성한 추천 모음집이 없습니다.") + Text(TextLiteral.showProfileViewNoCurations) .padding(.top, 16) .Body2() - .foregroundColor(.Gray4) + .foregroundColor(.gray4) Spacer() } } @@ -157,8 +154,8 @@ extension ShowProfileView { navigationParentView: .shortcuts) NavigationLink(value: data) { UserCurationCell(curation: curation, - navigationParentView: data.navigationParentView, - lineLimit: 2) + lineLimit: 2, + navigationParentView: data.navigationParentView) } } diff --git a/HappyAnding/HappyAnding/Views/ShortcutDetailViews/UpdateShortcutView.swift b/HappyAnding/HappyAnding/Views/ShortcutDetailViews/UpdateShortcutView.swift index dcdc7450..ea544adb 100644 --- a/HappyAnding/HappyAnding/Views/ShortcutDetailViews/UpdateShortcutView.swift +++ b/HappyAnding/HappyAnding/Views/ShortcutDetailViews/UpdateShortcutView.swift @@ -8,7 +8,6 @@ import SwiftUI struct UpdateShortcutView: View { - @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel @Binding var isUpdating: Bool @@ -25,12 +24,12 @@ struct UpdateShortcutView: View { Button(action: { isUpdating.toggle() }, label: { - Text("취소") - .foregroundColor(.Gray5) + Text(TextLiteral.cancel) + .foregroundColor(.gray5) }) .frame(maxWidth: .infinity, alignment: .leading) - Text("업데이트") + Text(TextLiteral.update) .font(.headline) .frame(maxWidth: .infinity, alignment: .center) @@ -41,8 +40,8 @@ struct UpdateShortcutView: View { .padding(.horizontal, 16) ValidationCheckTextField(textType: .mandatory, isMultipleLines: false, - title: "업데이트된 단축어 링크", - placeholder: "업데이트된 단축어 링크를 추가하세요", + title: TextLiteral.updateShortcutViewLinkTitle, + placeholder: TextLiteral.updateShortcutViewLinkPlaceholder, lengthLimit: 100, isDownloadLinkTextField: true, content: $updatedLink, @@ -53,8 +52,8 @@ struct UpdateShortcutView: View { ValidationCheckTextField(textType: .mandatory, isMultipleLines: false, - title: "업데이트 설명", - placeholder: "업데이트된 내용을 입력해주세요", + title: TextLiteral.updateShortcutViewDescriptionTitle, + placeholder: TextLiteral.updateShortcutViewDescriptionPlaceholder, lengthLimit: 50, isDownloadLinkTextField: false, content: $updateDescription, @@ -71,11 +70,10 @@ struct UpdateShortcutView: View { }, label: { ZStack { RoundedRectangle(cornerRadius: 12) - .foregroundColor(isLinkValid && isDescriptionValid ? .Primary : .Primary.opacity(0.13)) + .foregroundColor(isLinkValid && isDescriptionValid ? .shortcutsZipPrimary : .shortcutsZipPrimary.opacity(0.13)) .frame(maxWidth: .infinity, maxHeight: 52) - - Text("업데이트") - .foregroundColor(isLinkValid && isDescriptionValid ? .Text_Button : .Text_Button_Disable) + Text(TextLiteral.update) + .foregroundColor(isLinkValid && isDescriptionValid ? .textButton : .textButtonDisable) .Body1() } }) @@ -83,6 +81,6 @@ struct UpdateShortcutView: View { .padding(.horizontal, 16) .padding(.bottom, 24) } - .background(Color.Background) + .background(Color.shortcutsZipBackground) } } diff --git a/HappyAnding/HappyAnding/Views/ShortcutsZipView.swift b/HappyAnding/HappyAnding/Views/ShortcutsZipView.swift index ff55bf19..0bcbe18a 100644 --- a/HappyAnding/HappyAnding/Views/ShortcutsZipView.swift +++ b/HappyAnding/HappyAnding/Views/ShortcutsZipView.swift @@ -23,7 +23,6 @@ struct ShortcutsZipView: View { } else { if useWithoutSignIn { ShortcutTabView() -// .environmentObject(userAuth) } else { if userAuth.isLoggedIn { WriteNicknameView() diff --git a/HappyAnding/HappyAnding/Views/SignInViews/AppleAuthCoordinator.swift b/HappyAnding/HappyAnding/Views/SignInViews/AppleAuthCoordinator.swift index 3238c4ff..ec1cba81 100644 --- a/HappyAnding/HappyAnding/Views/SignInViews/AppleAuthCoordinator.swift +++ b/HappyAnding/HappyAnding/Views/SignInViews/AppleAuthCoordinator.swift @@ -21,6 +21,7 @@ class AppleAuthCoordinator: NSObject { var userAuth = UserAuth.shared var currentNonce: String? + let window: UIWindow? let shortcutZipViewModel = ShortcutsZipViewModel() let isTappedSignInButton: Bool diff --git a/HappyAnding/HappyAnding/Views/SignInViews/PrivacyPolicyView.swift b/HappyAnding/HappyAnding/Views/SignInViews/PrivacyPolicyView.swift index 0d29e730..c468cd36 100644 --- a/HappyAnding/HappyAnding/Views/SignInViews/PrivacyPolicyView.swift +++ b/HappyAnding/HappyAnding/Views/SignInViews/PrivacyPolicyView.swift @@ -30,13 +30,13 @@ struct PrivacyPolicyView: View { Button { self.isTappedPrivacyButton = false } label: { - Text("닫기") - .foregroundColor(.Gray5) + Text(TextLiteral.close) + .foregroundColor(.gray5) .frame(maxWidth: .infinity, alignment: .leading) .padding(.leading, 16) } - Text("개인정보처리방침") + Text(TextLiteral.settingViewPrivacyPolicy) .Headline() .frame(maxWidth: .infinity) @@ -79,6 +79,7 @@ struct PrivacyPolicyContentView: UIViewRepresentable { extension PrivacyPolicyContentView { class Coordinator: NSObject, WKNavigationDelegate { + @ObservedObject private var webViewModel: WebViewModel private let parent: PrivacyPolicyContentView diff --git a/HappyAnding/HappyAnding/Views/SignInViews/SignInWithAppleView.swift b/HappyAnding/HappyAnding/Views/SignInViews/SignInWithAppleView.swift index d2fcc5b4..c08a5bf4 100644 --- a/HappyAnding/HappyAnding/Views/SignInViews/SignInWithAppleView.swift +++ b/HappyAnding/HappyAnding/Views/SignInViews/SignInWithAppleView.swift @@ -6,16 +6,19 @@ // import SwiftUI +import FirebaseAuth struct SignInWithAppleView: View { + @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel + @Environment(\.window) var window: UIWindow? @EnvironmentObject var userAuth: UserAuth - - @State private var appleLoginCoordinator: AppleAuthCoordinator? @AppStorage("useWithoutSignIn") var useWithoutSignIn = false + @State private var appleLoginCoordinator: AppleAuthCoordinator? + var body: some View { VStack { @@ -25,13 +28,13 @@ struct SignInWithAppleView: View { Image("logo") .padding(.bottom, 28) - Text("ShortcutsZip") + Text(TextLiteral.signInWithAppleViewTitle) .LargeTitle() - .foregroundColor(.Primary) + .foregroundColor(.shortcutsZipPrimary) - Text("단축어 생활의 시작") + Text(TextLiteral.signInWithAppleViewSubTitle) .Body2() - .foregroundColor(.Gray3) + .foregroundColor(.gray3) Spacer() @@ -42,30 +45,44 @@ struct SignInWithAppleView: View { RoundedRectangle(cornerRadius: 12) .padding(.horizontal, 16) .frame(height: 52) - .foregroundColor(.Gray5) + .foregroundColor(.gray5) - Text("\(Image(systemName: "applelogo")) Apple로 로그인") - .foregroundColor(.White) + Label(TextLiteral.signInWithAppleViewSignInWithApple, systemImage: "applelogo") + .foregroundColor(.shortcutsZipWhite) } .padding(.bottom, 8) }) Button(action: { + setDefaultUserSetting() useWithoutSignIn = true }, label: { - Text("로그인 없이 둘러보기") + Text(TextLiteral.signInWithAppleViewUseWithoutSignIn) .Body2() - .foregroundColor(.Gray5) + .foregroundColor(.gray5) }) .padding(.bottom, 12) } - .background(Color.Background) + .background(Color.shortcutsZipBackground) } func appleLogin() { appleLoginCoordinator = AppleAuthCoordinator(window: window, isTappedSignInButton: true) appleLoginCoordinator?.startSignInWithAppleFlow() + UserDefaults.shared.set(true, forKey: "isSignInForShareExtension") } + + private func setDefaultUserSetting() { + let firebaseAuth = Auth.auth() + do { + try firebaseAuth.signOut() + shortcutsZipViewModel.resetUser() + UserDefaults.shared.set(false, forKey: "isFirstLaunch") + } catch { + print(error.localizedDescription) + } + } + } struct SignUpView_Previews: PreviewProvider { diff --git a/HappyAnding/HappyAnding/Views/SignInViews/WriteNicknameView.swift b/HappyAnding/HappyAnding/Views/SignInViews/WriteNicknameView.swift index 240f579b..be38ed76 100644 --- a/HappyAnding/HappyAnding/Views/SignInViews/WriteNicknameView.swift +++ b/HappyAnding/HappyAnding/Views/SignInViews/WriteNicknameView.swift @@ -22,12 +22,13 @@ import FirebaseAuth */ struct WriteNicknameView: View { - - @AppStorage("signInStatus") var signInStatus = false @EnvironmentObject var userAuth: UserAuth - @ObservedObject var webViewModel = WebViewModel() @EnvironmentObject var shortcutszipViewModel: ShortcutsZipViewModel + @ObservedObject var webViewModel = WebViewModel() + + @AppStorage("signInStatus") var signInStatus = false + @State var nickname: String = "" @State private var isTappedPrivacyButton = false @State var isValid = false @@ -37,18 +38,18 @@ struct WriteNicknameView: View { var body: some View { VStack(alignment: .leading) { - Text("닉네임을 입력해주세요") + Text(TextLiteral.writeNicknameViewHeadline) .Title1() - .foregroundColor(.Gray5) + .foregroundColor(.gray5) .padding(.top, 40) NicknameTextField(nickname: $nickname, isValid: $isValid) Spacer() - Text("개인정보처리방침") + Text(TextLiteral.settingViewPrivacyPolicy) .Body2() - .foregroundColor(Color.Gray3) + .foregroundColor(Color.gray3) .padding(.bottom, 12) .frame(maxWidth: .infinity) .onTapGesture { @@ -59,12 +60,12 @@ struct WriteNicknameView: View { } .padding(.horizontal, 16) .padding(.bottom, 44) - .background(Color.Background) + .background(Color.shortcutsZipBackground) .sheet(isPresented: self.$isTappedPrivacyButton) { ZStack { PrivacyPolicyView(viewModel: webViewModel, isTappedPrivacyButton: $isTappedPrivacyButton, - url: "https://noble-satellite-574.notion.site/60d8fa2f417c40cca35e9c784f74b7fd") + url: TextLiteral.settingViewPrivacyPolicyURL) .presentationDetents([.large]) .presentationDragIndicator(.visible) if webViewModel.isLoading { @@ -86,10 +87,10 @@ struct WriteNicknameView: View { }, label: { ZStack { RoundedRectangle(cornerRadius: 12) - .foregroundColor(isValid ? .Primary : .Primary .opacity(0.13)) + .foregroundColor(isValid ? .shortcutsZipPrimary : .shortcutsZipPrimary .opacity(0.13)) .frame(height: 52) - Text("시작하기") - .foregroundColor(isValid ? .Text_icon : .Text_Button_Disable) + Text(TextLiteral.writeNicknameViewStart) + .foregroundColor(isValid ? .textIcon : .textButtonDisable) .Body1() } }) diff --git a/HappyAnding/HappyAnding/Views/TabView/ShortcutTabView.swift b/HappyAnding/HappyAnding/Views/TabView/ShortcutTabView.swift index c97867db..9326fa74 100644 --- a/HappyAnding/HappyAnding/Views/TabView/ShortcutTabView.swift +++ b/HappyAnding/HappyAnding/Views/TabView/ShortcutTabView.swift @@ -9,34 +9,34 @@ import SwiftUI import BackgroundTasks struct ShortcutTabView: View { - // TODO: StateObject로 선언할 수 있는 다른 로직 구현해보기 @Environment(\.scenePhase) private var phase @EnvironmentObject var userAuth: UserAuth @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel - @State private var randomCategories = Category.allCases.shuffled().prefix(2) - @State var isFolded = true + @StateObject var shortcutNavigation = ShortcutNavigation() + @StateObject var curationNavigation = CurationNavigation() + @StateObject var profileNavigation = ProfileNavigation() @AppStorage("signInStatus") var signInStatus = false + @AppStorage("selectedTab") var selectedTab = 1 + @State private var isShortcutDeeplink = false @State private var isCurationDeeplink = false @State private var tempShortcutId = "" @State private var tempCurationId = "" - @StateObject var shortcutNavigation = ShortcutNavigation() - @StateObject var curationNavigation = CurationNavigation() - @StateObject var profileNavigation = ProfileNavigation() - @AppStorage("selectedTab") var selectedTab = 1 + @State private var randomCategories = Category.allCases.shuffled().prefix(2) + @State var isFolded = true @State private var tappedTwice = false init() { let transparentAppearence = UITabBarAppearance() transparentAppearence.configureWithTransparentBackground() UITabBar.appearance().standardAppearance = transparentAppearence - UITabBar.appearance().barTintColor = UIColor(Color.White) - UITabBar.appearance().backgroundColor = UIColor(Color.White) - UITabBar.appearance().unselectedItemTintColor = UIColor(Color.Gray2) + UITabBar.appearance().barTintColor = UIColor(Color.shortcutsZipWhite) + UITabBar.appearance().backgroundColor = UIColor(Color.shortcutsZipWhite) + UITabBar.appearance().unselectedItemTintColor = UIColor(Color.gray2) UITabBar.appearance().layer.borderColor = UIColor(Color.clear).cgColor UITabBar.appearance().clipsToBounds = true } @@ -55,7 +55,7 @@ struct ShortcutTabView: View { ScrollViewReader { proxy in TabView(selection: handler) { NavigationStack(path: $shortcutNavigation.navigationPath) { - ExploreShortcutView(randomCategories: Array(randomCategories), isFolded: $isFolded) + ExploreShortcutView(isFolded: $isFolded, randomCategories: Array(randomCategories)) .onChange(of: tappedTwice, perform: { tappedTwice in guard tappedTwice else { return } if shortcutNavigation.navigationPath.count > 0 { @@ -85,7 +85,7 @@ struct ShortcutTabView: View { ReadShortcutView(data: data) } .navigationDestination(for: Category.self) { category in - ShortcutsListView(shortcuts: $shortcutsZipViewModel.shortcutsInCategory[category.index], + ListCategoryShortcutView(shortcuts: $shortcutsZipViewModel.shortcutsInCategory[category.index], categoryName: category, navigationParentView: .shortcuts) } @@ -112,7 +112,7 @@ struct ShortcutTabView: View { } self.tappedTwice = false }) - .navigationBarBackground ({ Color.Background }) + .navigationBarBackground ({ Color.shortcutsZipBackground }) .navigationDestination(for: NavigationProfile.self) { data in ShowProfileView(data: data) } @@ -149,7 +149,7 @@ struct ShortcutTabView: View { } self.tappedTwice = false }) - .navigationBarBackground ({ Color.Background }) + .navigationBarBackground ({ Color.shortcutsZipBackground }) .navigationDestination(for: NavigationProfile.self) { data in ShowProfileView(data: data) } @@ -172,17 +172,6 @@ struct ShortcutTabView: View { } .tag(3) } - .sheet(isPresented: self.$isShortcutDeeplink) { - let data = NavigationReadShortcutType(shortcutID: self.tempShortcutId, - navigationParentView: .myPage) - ReadShortcutView(data: data) - } - .sheet(isPresented: self.$isCurationDeeplink) { - if let curation = shortcutsZipViewModel.fetchCurationDetail(curationID: tempCurationId) { - let data = NavigationReadUserCurationType(userCuration: curation, navigationParentView: .myPage) - ReadUserCurationView(data: data) - } - } .onChange(of: phase) { newPhase in switch newPhase { case .background: isShortcutDeeplink = false; isCurationDeeplink = false @@ -212,6 +201,10 @@ struct ShortcutTabView: View { tempShortcutId = shortcutIDfromURL isShortcutDeeplink = true + + let data = NavigationReadShortcutType(shortcutID: self.tempShortcutId, + navigationParentView: .myPage) + navigateLink(data: data) } private func fetchCurationIdFromUrl(urlString: String) { @@ -228,10 +221,28 @@ struct ShortcutTabView: View { guard let curationIDfromURL = dictionaryData["curationID"] else { return } - print("curationIDfromURL = \(curationIDfromURL)") - tempCurationId = curationIDfromURL isCurationDeeplink = true + + if let curation = shortcutsZipViewModel.fetchCurationDetail(curationID: tempCurationId) { + let data = NavigationReadUserCurationType(userCuration: curation, + navigationParentView: .myPage) + navigateLink(data: data) + } + } + + private func navigateLink (data: T) { + + switch selectedTab { + case 1: + shortcutNavigation.navigationPath.append(data) + case 2: + curationNavigation.navigationPath.append(data) + case 3: + profileNavigation.navigationPath.append(data) + default: + break + } } } diff --git a/HappyAnding/HappyAnding/Views/TabView/TabRouter.swift b/HappyAnding/HappyAnding/Views/TabView/TabRouter.swift deleted file mode 100644 index c8489926..00000000 --- a/HappyAnding/HappyAnding/Views/TabView/TabRouter.swift +++ /dev/null @@ -1,38 +0,0 @@ -// -// TabRouter.swift -// HappyAnding -// -// Created by KiWoong Hong on 2022/10/21. -// -//import SwiftUI -// -//enum Tab: CaseIterable { -// case exploreShortcut -// case collect -// case myPage -// -// var tabName: String { -// switch self { -// case .exploreShortcut : return "단축어" -// case .collect: return "큐레이션" -// case .myPage: return "프로필" -// } -// } -// -// var systemImage: String { -// switch self { -// case .exploreShortcut : return "square.stack.3d.up.fill" -// case .collect: return "folder.fill" -// case .myPage: return "person.crop.circle.fill" -// } -// } -// -// @ViewBuilder -// var view: some View { -// switch self { -// case .exploreShortcut : ExploreShortcutView() -// case .collect: ExploreCurationView() -// case .myPage: MyPageView() -// } -// } -//} diff --git a/HappyAnding/HappyAnding/Views/WriteCurationViews/CheckBoxShortcutCell.swift b/HappyAnding/HappyAnding/Views/WriteCurationViews/CheckBoxShortcutCell.swift index 64a94249..9328acd4 100644 --- a/HappyAnding/HappyAnding/Views/WriteCurationViews/CheckBoxShortcutCell.swift +++ b/HappyAnding/HappyAnding/Views/WriteCurationViews/CheckBoxShortcutCell.swift @@ -9,16 +9,16 @@ import SwiftUI struct CheckBoxShortcutCell: View { - @State var isShortcutTapped: Bool = false - @Binding var selectedShortcutCells: [ShortcutCellModel] + @State var isShortcutTapped: Bool = false + let shortcutCell: ShortcutCellModel var body: some View { ZStack { - Color.Background + Color.shortcutsZipBackground HStack { toggle @@ -48,12 +48,12 @@ struct CheckBoxShortcutCell: View { } } .padding(.top, 0) - .background(Color.Background) + .background(Color.shortcutsZipBackground) } var toggle: some View { Image(systemName: isShortcutTapped ? "checkmark.square.fill" : "square") - .foregroundColor(isShortcutTapped ? .Primary : .Gray3) + .foregroundColor(isShortcutTapped ? .shortcutsZipPrimary : .gray3) .padding(.leading, 20) } @@ -76,11 +76,11 @@ struct CheckBoxShortcutCell: View { VStack(alignment: .leading, spacing: 4) { Text(shortcutCell.title) .Headline() - .foregroundColor(.Gray5) + .foregroundColor(.gray5) .lineLimit(1) Text(shortcutCell.subtitle) .Footnote() - .foregroundColor(.Gray3) + .foregroundColor(.gray3) .lineLimit(2) } .padding(.leading, 12) @@ -90,10 +90,10 @@ struct CheckBoxShortcutCell: View { var background: some View { RoundedRectangle(cornerRadius: 12) - .fill(isShortcutTapped ? Color.White : Color.Background_list) + .fill(isShortcutTapped ? Color.shortcutsZipWhite : Color.backgroudList) .overlay( RoundedRectangle(cornerRadius: 12) - .strokeBorder(isShortcutTapped ? Color.Primary : Color.Background_list_border) + .strokeBorder(isShortcutTapped ? Color.shortcutsZipPrimary : Color.backgroudListBorder) ) }} diff --git a/HappyAnding/HappyAnding/Views/WriteCurationViews/WriteCurationInfoView.swift b/HappyAnding/HappyAnding/Views/WriteCurationViews/WriteCurationInfoView.swift index bc6471a6..3fae9b4d 100644 --- a/HappyAnding/HappyAnding/Views/WriteCurationViews/WriteCurationInfoView.swift +++ b/HappyAnding/HappyAnding/Views/WriteCurationViews/WriteCurationInfoView.swift @@ -12,27 +12,27 @@ struct WriteCurationInfoView: View { @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel @EnvironmentObject var writeCurationNavigation: WriteCurationNavigation - @State var isValidTitle = false - @State var isValidDescription = false - @Binding var curation: Curation @Binding var isWriting: Bool - - let isEdit: Bool @Binding var deletedShortcutCells: [ShortcutCellModel] + @State var isValidTitle = false + @State var isValidDescription = false + private var isIncomplete: Bool { !(isValidTitle && isValidDescription) } + let isEdit: Bool + var body: some View { VStack(spacing: 24) { ProgressView(value: 2, total: 2) ValidationCheckTextField(textType: .mandatory, isMultipleLines: false, - title: "추천 모음집 이름", - placeholder: "추천 모음집의 이름을 입력하세요", + title: TextLiteral.writeCurationInfoViewNameTitle, + placeholder: TextLiteral.writeCurationInfoViewNamePlaceholder, lengthLimit: 20, isDownloadLinkTextField: false, content: $curation.title, @@ -41,8 +41,8 @@ struct WriteCurationInfoView: View { ValidationCheckTextField(textType: .mandatory, isMultipleLines: true, - title: "추천 모음집 설명", - placeholder: "추천 모음집에 대한 설명을 작성해주세요", + title: TextLiteral.writeCurationInfoViewDescriptionTitle, + placeholder: TextLiteral.writeCurationInfoViewDescriptionPlaceholder, lengthLimit: 40, isDownloadLinkTextField: false, inputHeight: 72, @@ -56,43 +56,21 @@ struct WriteCurationInfoView: View { .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button { - if isEdit { - curation.shortcuts.forEach { shortcutCell in - deletedShortcutCells.removeAll(where: { $0.id == shortcutCell.id }) - } - } - curation.shortcuts = curation.shortcuts.sorted { $0.title < $1.title } - curation.author = shortcutsZipViewModel.currentUser() - shortcutsZipViewModel.setData(model: curation) - shortcutsZipViewModel.updateShortcutCurationID( - shortcutCells: curation.shortcuts, - curationID: curation.id, - isEdit: isEdit, - deletedShortcutCells: deletedShortcutCells - ) - if let index = shortcutsZipViewModel.userCurations.firstIndex(where: { $0.id == curation.id }) { - shortcutsZipViewModel.userCurations[index] = curation - } + + shortcutsZipViewModel.addCuration(curation: curation, isEdit: isEdit, deletedShortcutCells: deletedShortcutCells) self.isWriting.toggle() writeCurationNavigation.navigationPath = .init() } label: { - Text("업로드") + Text(TextLiteral.upload) .Headline() - .foregroundColor(isIncomplete ? .Primary.opacity(0.3) : .Primary) + .foregroundColor(isIncomplete ? .shortcutsZipPrimary.opacity(0.3) : .shortcutsZipPrimary) } .disabled(isIncomplete) } } - .background(Color.Background) - .navigationBarTitle(isEdit ? "추천 모음집 편집" : "추천 모음집 작성") + .background(Color.shortcutsZipBackground) + .navigationBarTitle(isEdit ? TextLiteral.writeCurationInfoViewEdit : TextLiteral.wrietCurationInfoViewPost) .onAppear(perform : UIApplication.shared.hideKeyboard) } } - -//struct WriteCurationInfoView_Previews: PreviewProvider { -// static var previews: some View { -// WriteCurationInfoView(isWriting: .constant(true), -// isEdit: false, navigationParentView: .curations) -// } -//} diff --git a/HappyAnding/HappyAnding/Views/WriteCurationViews/WriteCurationSetView.swift b/HappyAnding/HappyAnding/Views/WriteCurationViews/WriteCurationSetView.swift index 32599d9d..26a9de4f 100644 --- a/HappyAnding/HappyAnding/Views/WriteCurationViews/WriteCurationSetView.swift +++ b/HappyAnding/HappyAnding/Views/WriteCurationViews/WriteCurationSetView.swift @@ -35,9 +35,9 @@ struct WriteCurationSetView: View { infomation if shortcutCells.isEmpty { Spacer() - Text("아직 선택할 수 있는 단축어가 없어요.\n단축어를 업로드하거나 좋아요를 눌러주세요:)") + Text(TextLiteral.writeCurationSetViewNoShortcuts) .Body2() - .foregroundColor(.Gray4) + .foregroundColor(.gray4) .multilineTextAlignment(.center) Spacer() @@ -45,8 +45,8 @@ struct WriteCurationSetView: View { shortcutList } } - .background(Color.Background) - .navigationTitle(isEdit ? "추천 모음집 편집" : "추천 모음집 작성") + .background(Color.shortcutsZipBackground) + .navigationTitle(isEdit ? TextLiteral.writeCurationSetViewEdit : TextLiteral.writeCurationSetViewPost) .navigationBarTitleDisplayMode(.inline) .onAppear { self.shortcutCells = shortcutsZipViewModel.fetchShortcutMakeCuration().sorted { $0.title < $1.title } @@ -59,17 +59,17 @@ struct WriteCurationSetView: View { Button { self.isWriting.toggle() } label: { - Text("취소") + Text(TextLiteral.cancel) .Body1() - .foregroundColor(.Gray4) + .foregroundColor(.gray4) } } ToolbarItem(placement: .navigationBarTrailing) { NavigationLink(value: Float(0.0)) { - Text("다음") + Text(TextLiteral.next) .Headline() - .foregroundColor(curation.shortcuts.isEmpty ? .Primary.opacity(0.3) : .Primary) + .foregroundColor(curation.shortcuts.isEmpty ? .shortcutsZipPrimary.opacity(0.3) : .shortcutsZipPrimary) } .disabled(curation.shortcuts.isEmpty) } @@ -77,24 +77,24 @@ struct WriteCurationSetView: View { .navigationDestination(for: Float.self) { isEdit in WriteCurationInfoView(curation: $curation, isWriting: self.$isWriting, - isEdit: self.isEdit, - deletedShortcutCells: $deletedShortcutCells) + deletedShortcutCells: $deletedShortcutCells, + isEdit: self.isEdit) } } ///단축어 선택 텍스트 및 카운터 var listHeader: some View { HStack(alignment: .bottom, spacing: 8) { - Text("단축어 선택") + Text(TextLiteral.writeCurationSetViewSelectionTitle) .Sb() - .foregroundColor(.Gray5) - Text("최대 10개") + .foregroundColor(.gray5) + Text(TextLiteral.writeCurationSetViewSelectionDescription) .Footnote() - .foregroundColor(.Gray3) + .foregroundColor(.gray3) Spacer() Text("\(curation.shortcuts.count)개") .Body2() - .foregroundColor(.Primary) + .foregroundColor(.shortcutsZipPrimary) } .padding(.horizontal, 16) } @@ -103,13 +103,9 @@ struct WriteCurationSetView: View { var shortcutList: some View { ScrollView { - - - ForEach(Array(shortcutCells)) { shortcut in CheckBoxShortcutCell( - isShortcutTapped: curation.shortcuts.contains(shortcut), - selectedShortcutCells: $curation.shortcuts, + selectedShortcutCells: $curation.shortcuts, isShortcutTapped: curation.shortcuts.contains(shortcut), shortcutCell: shortcut ) } @@ -120,14 +116,14 @@ struct WriteCurationSetView: View { // MARK: - 안내문구 var infomation: some View { - Text("추천 모음집을 위한 단축어 목록은 ‘내가 업로드한 단축어'와 ‘좋아요를 누른 단축어'로 구성되어 있습니다.") + Text(TextLiteral.writeCurationSetViewSelectionInformation) .frame(maxWidth: .infinity, alignment: .leading) .Body2() - .foregroundColor(.Gray5) + .foregroundColor(.gray5) .padding(.all, 16) .background( RoundedRectangle(cornerRadius: 12) - .foregroundColor(.Gray1) + .foregroundColor(.gray1) ) .padding(.horizontal, 16) .padding(.bottom, 20) diff --git a/HappyAnding/HappyAnding/Views/WriteShortcutViews/CategoryModalView.swift b/HappyAnding/HappyAnding/Views/WriteShortcutViews/CategoryModalView.swift index 54c8d1d9..674f9f7b 100644 --- a/HappyAnding/HappyAnding/Views/WriteShortcutViews/CategoryModalView.swift +++ b/HappyAnding/HappyAnding/Views/WriteShortcutViews/CategoryModalView.swift @@ -8,28 +8,31 @@ import SwiftUI struct CategoryModalView: View { + @Binding var isShowingCategoryModal: Bool @Binding var selectedCategories: [String] + var screenHeight = UIScreen.main.bounds.size.height + private let gridLayout = [GridItem(.flexible()), GridItem(.flexible())] var body: some View { ZStack { - Color.Background + Color.shortcutsZipBackground .ignoresSafeArea() VStack { HStack(spacing: 0) { Button { self.isShowingCategoryModal = false } label: { - Text("닫기") - .foregroundColor(.Gray5) + Text(TextLiteral.close) + .foregroundColor(.gray5) .frame(maxWidth: .infinity, alignment: .leading) .padding(.leading, 16) } - Text("카테고리") - .font(.headline) + Text(TextLiteral.categoryModalViewTitle) + .Headline() .frame(maxWidth: .infinity) Spacer() @@ -37,7 +40,7 @@ struct CategoryModalView: View { } Spacer() - .frame(height: UIScreen.main.bounds.size.height * 0.7 * 0.04) + .frame(height: screenHeight * 0.7 * 0.04) LazyVGrid(columns: gridLayout, spacing: 12) { ForEach(Category.allCases, id: \.self) { item in @@ -47,18 +50,18 @@ struct CategoryModalView: View { .padding(.horizontal, 16) Spacer() - .frame(height: UIScreen.main.bounds.size.height * 0.7 * 0.04) + .frame(height: screenHeight * 0.7 * 0.04) Button(action: { isShowingCategoryModal = false }, label: { ZStack { RoundedRectangle(cornerRadius: 12) - .foregroundColor(!selectedCategories.isEmpty ? .Primary : .Primary .opacity(0.13) ) + .foregroundColor(!selectedCategories.isEmpty ? .shortcutsZipPrimary : .shortcutsZipPrimary.opacity(0.13) ) .frame(maxWidth: .infinity, maxHeight: 52) - Text("완료") - .foregroundColor(!selectedCategories.isEmpty ? .Text_icon : .Text_Button_Disable) + Text(TextLiteral.done) + .foregroundColor(!selectedCategories.isEmpty ? .textIcon : .textButtonDisable) .Body1() } }) @@ -85,14 +88,14 @@ struct CategoryModalView: View { Text(item.translateName()) .Body2() .tag(item.category) - .foregroundColor(items.contains(item.category) ? Color.Category_Pick_Text : Color.Gray3) + .foregroundColor(items.contains(item.category) ? Color.categoryPickText : Color.gray3) .frame(maxWidth: .infinity, minHeight: UIScreen.main.bounds.size.height * 0.7 * 0.08) .background( RoundedRectangle(cornerRadius: 12) - .fill(items.contains(item.category) ? Color.Category_Pick_Fill : .clear) + .fill(items.contains(item.category) ? Color.categoryPickFill : .clear) .overlay( RoundedRectangle(cornerRadius: 12) - .strokeBorder(items.contains(item.category) ? Color.Primary : Color.Gray3, lineWidth: 1) + .strokeBorder(items.contains(item.category) ? Color.shortcutsZipPrimary : Color.gray3, lineWidth: 1) ) ) diff --git a/HappyAnding/HappyAnding/Views/WriteShortcutViews/IconModalView.swift b/HappyAnding/HappyAnding/Views/WriteShortcutViews/IconModalView.swift index 24b5fad6..00f2cec0 100644 --- a/HappyAnding/HappyAnding/Views/WriteShortcutViews/IconModalView.swift +++ b/HappyAnding/HappyAnding/Views/WriteShortcutViews/IconModalView.swift @@ -8,6 +8,7 @@ import SwiftUI struct IconModalView: View { + @Binding var isShowingIconModal: Bool @Binding var iconColor: String @Binding var iconSymbol: String @@ -62,13 +63,13 @@ struct IconModalView: View { Button { self.isShowingIconModal = false } label: { - Text("닫기") - .foregroundColor(.Gray5) + Text(TextLiteral.close) + .foregroundColor(.gray5) .frame(maxWidth: .infinity, alignment: .leading) .padding(.leading, 16) } - Text("아이콘") + Text(TextLiteral.iconModalViewTitle) .Headline() .frame(maxWidth: .infinity) @@ -80,7 +81,7 @@ struct IconModalView: View { ZStack(alignment: .center) { Rectangle() - .fill(Color.Gray1) + .fill(Color.gray1) .cornerRadius(UIScreen.main.bounds.size.height > 700 ? 20 : 12.35) .frame(width: UIScreen.main.bounds.size.height > 700 ? 136 : 84, height: UIScreen.main.bounds.size.height > 700 ? 136 : 84) @@ -92,31 +93,31 @@ struct IconModalView: View { Image(systemName: iconSymbol) .font(.system(size: UIScreen.main.bounds.size.height > 700 ? 48 : 32)) .frame(width: UIScreen.main.bounds.size.height > 700 ? 136 : 84, height: UIScreen.main.bounds.size.height > 700 ? 136 : 84) - .foregroundColor(.Text_icon) + .foregroundColor(.textIcon) } .padding(.bottom, 24) - Text("색상") + Text(TextLiteral.iconModalViewColor) .Subtitle() .padding(.leading, 16) - .foregroundColor(.Gray4) + .foregroundColor(.gray4) .frame(maxWidth: .infinity, alignment: .leading) LazyVGrid(columns: gridLayout, spacing: 12) { ForEach(colors, id: \.self) { item in - ColorCell(paletteColor: item, iconColor: $iconColor) + ColorCell(iconColor: $iconColor, paletteColor: item) } } .padding(.horizontal, 16) .padding(.bottom, 24) - Text("기호") + Text(TextLiteral.iconModalViewIcon) .Subtitle() .padding(.leading, 16) - .foregroundColor(.Gray4) + .foregroundColor(.gray4) .frame(maxWidth: .infinity, alignment: .leading) LazyVGrid(columns: gridLayout, spacing: 12) { ForEach(symbols, id: \.self) { item in - SymbolCell(paletteSymbol: item, iconSymbol: $iconSymbol) + SymbolCell(iconSymbol: $iconSymbol, paletteSymbol: item) } } .padding(.horizontal, 16) @@ -128,11 +129,11 @@ struct IconModalView: View { }, label: { ZStack { RoundedRectangle(cornerRadius: 12) - .foregroundColor(!iconColor.isEmpty && !iconSymbol.isEmpty ? .Primary : .Primary .opacity(0.13) ) + .foregroundColor(!iconColor.isEmpty && !iconSymbol.isEmpty ? .shortcutsZipPrimary : .shortcutsZipPrimary.opacity(0.13) ) .frame(maxWidth: .infinity, maxHeight: 52) - Text("완료") - .foregroundColor(!iconColor.isEmpty && !iconSymbol.isEmpty ? .Text_Button : .Text_Button_Disable ) + Text(TextLiteral.done) + .foregroundColor(!iconColor.isEmpty && !iconSymbol.isEmpty ? .textButton : .textButtonDisable ) .Body1() } }) @@ -140,13 +141,14 @@ struct IconModalView: View { .padding(.horizontal, 16) .padding(.bottom, 24) } - .background(Color.Background) + .background(Color.shortcutsZipBackground) } struct ColorCell: View { - let paletteColor: String @Binding var iconColor: String + let paletteColor: String + var body: some View { Button(action: { iconColor = paletteColor @@ -159,7 +161,7 @@ struct IconModalView: View { if paletteColor == iconColor { Image(systemName: "checkmark") - .foregroundColor(.Text_icon) + .foregroundColor(.textIcon) } } }) @@ -167,21 +169,22 @@ struct IconModalView: View { } struct SymbolCell: View { - let paletteSymbol: String @Binding var iconSymbol: String + let paletteSymbol: String + var body: some View { Button(action: { iconSymbol = paletteSymbol }, label: { ZStack(alignment: .center) { Rectangle() - .fill(paletteSymbol == iconSymbol ? Color.Gray1 : Color.clear) + .fill(paletteSymbol == iconSymbol ? Color.gray1 : Color.clear) .cornerRadius(8) .frame(width: 36, height: 36) Image(systemName: paletteSymbol) - .foregroundColor(paletteSymbol == iconSymbol ? Color.Gray5 : Color.Gray3) + .foregroundColor(paletteSymbol == iconSymbol ? Color.gray5 : Color.gray3) } }) } diff --git a/HappyAnding/HappyAnding/Views/WriteShortcutViews/WriteShortcutTagView.swift b/HappyAnding/HappyAnding/Views/WriteShortcutViews/WriteShortcutTagView.swift deleted file mode 100644 index cc0de612..00000000 --- a/HappyAnding/HappyAnding/Views/WriteShortcutViews/WriteShortcutTagView.swift +++ /dev/null @@ -1,318 +0,0 @@ -// -// WriteShortcutTagView.swift -// HappyAnding -// -// Created by 이지원 on 2022/10/19. -// - -import SwiftUI - -struct WriteShortcutTagView: View { - - @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel - @EnvironmentObject var writeShortcutNavigation: WriteShortcutNavigation - - @Binding var isWriting: Bool - @Binding var shortcut: Shortcuts - - @State var isShowingCategoryModal = false - @State var isRequirementValid = false - - @State var existingCategory: [String] = [] - @State var newCategory: [String] = [] - - let isEdit: Bool - - var body: some View { - VStack { - ProgressView(value: 1, total: 1) - .padding(.bottom, 36) - - HStack { - Text("카테고리") - .Headline() - .padding(.leading, 16) - .foregroundColor(.Gray5) - Text("최대 3개 선택") - .Footnote() - .foregroundColor(.Gray3) - } - .frame(maxWidth: .infinity, alignment: .leading) - - categoryList(isShowingCategoryModal: $isShowingCategoryModal, selectedCategories: $shortcut.category) - .padding(.bottom, 32) - - HStack { - Text("단축어 사용에 필요한 앱") - .Headline() - .padding(.leading, 16) - .foregroundColor(.Gray5) - Text("(선택입력)") - .Footnote() - .foregroundColor(.Gray3) - } - .frame(maxWidth: .infinity, alignment: .leading) - - relatedAppList(relatedApps: $shortcut.requiredApp) - .padding(.bottom, 32) - - ValidationCheckTextField(textType: .optional, - isMultipleLines: true, - title: "단축어 사용을 위한 요구사항", - placeholder: "단축어를 사용하기 위해서 필수적으로 요구되는 내용이 있다면, 작성해주세요", - lengthLimit: 100, - isDownloadLinkTextField: false, - content: $shortcut.shortcutRequirements, - isValid: $isRequirementValid - ) - - Spacer() - - Button(action: { - if let index = shortcutsZipViewModel.allShortcuts.firstIndex(where: {$0.id == shortcut.id}) { - shortcutsZipViewModel.allShortcuts[index] = shortcut - } - - shortcut.author = shortcutsZipViewModel.currentUser() - if isEdit { - //뷰모델의 카테고리별 단축어 목록에서 정보 수정 - newCategory = shortcut.category - existingCategory.forEach { category in - if !shortcut.category.contains(category) { - newCategory.removeAll(where: { $0 == category }) - shortcutsZipViewModel.shortcutsInCategory[Category(rawValue: category)!.index].removeAll(where: { $0.id == shortcut.id }) - } else { - newCategory.removeAll(where: { $0 == category }) - if let index = shortcutsZipViewModel.shortcutsInCategory[Category(rawValue: category)!.index].firstIndex(where: { $0.id == shortcut.id}) { - shortcutsZipViewModel.shortcutsInCategory[Category(rawValue: category)!.index][index] = shortcut - } - } - } - newCategory.forEach { category in - if !shortcutsZipViewModel.isFirstFetchInCategory[Category(rawValue: category)!.index] { - shortcutsZipViewModel.shortcutsInCategory[Category(rawValue: category)!.index].insert(shortcut, at: 0) - } - } - - //서버 데이터 변경 - shortcutsZipViewModel.setData(model: shortcut) - //TODO: 셀정보에 변경사항이 있을 경우에만 함수를 호출하도록 변경 필요 - shortcutsZipViewModel.updateShortcutInCuration( - shortcutCell: ShortcutCellModel( - id: shortcut.id, - sfSymbol: shortcut.sfSymbol, - color: shortcut.color, - title: shortcut.title, - subtitle: shortcut.subtitle, - downloadLink: shortcut.downloadLink.last! - ), - curationIDs: shortcut.curationIDs - ) - } else { - //새로운 단축어 생성 및 저장 - // 뷰모델에 추가 - shortcutsZipViewModel.shortcutsMadeByUser.insert(shortcut, at: 0) - - // 서버에 추가 - shortcutsZipViewModel.setData(model: shortcut) - } - - - isWriting.toggle() - - writeShortcutNavigation.navigationPath = .init() - - }, label: { - ZStack { - RoundedRectangle(cornerRadius: 12) - .foregroundColor(!shortcut.category.isEmpty && isRequirementValid ? .Primary : .Primary .opacity(0.13) ) - .frame(maxWidth: .infinity, maxHeight: 52) - - Text("완료") - .foregroundColor(!shortcut.category.isEmpty && isRequirementValid ? .Text_Button : .Text_Button_Disable ) - .Body1() - } - }) - .disabled(shortcut.category.isEmpty || !isRequirementValid) - .padding(.horizontal, 16) - .padding(.bottom, 24) - } - .onAppear() { - existingCategory = shortcut.category - } - .navigationTitle(isEdit ? "단축어 편집" :"단축어 등록") - .ignoresSafeArea(.keyboard) - .background(Color.Background) - } - - struct categoryList: View { - @Binding var isShowingCategoryModal: Bool - @Binding var selectedCategories: [String] - - var body: some View { - ScrollView(.horizontal) { - HStack(spacing: 8) { - ForEach(selectedCategories, id:\.self) { item in - CategoryTag(item: item, items: $selectedCategories) - } - - Button(action: { - isShowingCategoryModal = true - }, label: { - HStack { - Image(systemName: "plus") - Text("카테고리 추가") - } - }) - .modifier(CellModifier(foregroundColor: Color.Gray3)) - .sheet(isPresented: $isShowingCategoryModal) { - CategoryModalView(isShowingCategoryModal: $isShowingCategoryModal, selectedCategories: $selectedCategories) - .presentationDetents([.fraction(0.7)]) - .presentationDragIndicator(.visible) - } - } - } - .padding(.leading, 16) - } - } - - struct relatedAppList: View { - @Binding var relatedApps: [String] - - @FocusState private var isFocused: Bool - @State var isTextFieldShowing = false - @State var relatedApp = "" - - var body: some View { - ScrollView(.horizontal) { - HStack(spacing: 8) { - ForEach(relatedApps, id:\.self) { item in - RelatedAppTag(item: item, items: $relatedApps) - } - - if isTextFieldShowing { - TextField("", text: $relatedApp) - .disableAutocorrection(true) - .textInputAutocapitalization(.never) - .modifier(ClearButton(text: $relatedApp)) - .focused($isFocused) - .onAppear { - isFocused = true - } - .onChange(of: isFocused) { _ in - if !isFocused { - if !relatedApp.isEmpty { - relatedApps.append(relatedApp) - relatedApp = "" - } - isTextFieldShowing = false - } - } - .modifier(CellModifier(foregroundColor: Color.Gray4)) - } - - Button(action: { - isTextFieldShowing = true - isFocused = true - }, label: { - HStack { - Image(systemName: "plus") - Text("앱 추가") - } - }) - .modifier(CellModifier(foregroundColor: Color.Gray3)) - } - } - .padding(.leading, 16) - } - } - - struct CategoryTag: View { - var item: String - @Binding var items: [String] - - var body: some View { - HStack { - Text(Category.withLabel(item)!.translateName()) - - Button(action: { - items.removeAll { $0 == item } - }, label: { - Image(systemName: "xmark") - }) - } - .modifier(CellModifier(foregroundColor: Color.Category_Pick_Text, - backgroundColor: Color.Tag_Pick_Background, - strokeColor: Color.Primary)) - } - } - - struct RelatedAppTag: View { - var item: String - @Binding var items: [String] - - var body: some View { - HStack { - Button(action: { - //TODO: 탭 되었을 때 수정 로직 추가 - }, label: { - Text(item) - }) - - Button(action: { - items.removeAll { $0 == item } - }, label: { - Image(systemName: "xmark") - }) - } - .modifier(CellModifier(foregroundColor: Color.Category_Pick_Text, - backgroundColor: Color.Tag_Pick_Background, - strokeColor: Color.Primary)) - } - } - - struct CellModifier: ViewModifier { - @State var foregroundColor: Color - @State var backgroundColor = Color.clear - @State var strokeColor = Color.Gray4 - - public func body(content: Content) -> some View { - content - .Body2() - .foregroundColor(foregroundColor) - .frame(height: 46) - .padding(.horizontal) - .background( - RoundedRectangle(cornerRadius: 12) - .fill( backgroundColor ) - .overlay( - RoundedRectangle(cornerRadius: 12) - .strokeBorder(strokeColor, lineWidth: 1)) - ) - } - } - - struct ClearButton: ViewModifier { - @Binding var text: String - - public func body(content: Content) -> some View { - HStack { - content - Button(action: { - self.text = "" - }) { - Image(systemName: "xmark.circle.fill") - .Body2() - .foregroundColor(.Gray4) - } - } - } - } -} -/* -struct WriteShortcutTagView_Previews: PreviewProvider { - static var previews: some View { - WriteShortcutTagView(isWriting: .constant(true), isEdit: false) - } -} -*/ diff --git a/HappyAnding/HappyAnding/Views/WriteShortcutViews/WriteShortcutTitleView.swift b/HappyAnding/HappyAnding/Views/WriteShortcutViews/WriteShortcutView.swift similarity index 63% rename from HappyAnding/HappyAnding/Views/WriteShortcutViews/WriteShortcutTitleView.swift rename to HappyAnding/HappyAnding/Views/WriteShortcutViews/WriteShortcutView.swift index 62fa76cb..0d2b0d62 100644 --- a/HappyAnding/HappyAnding/Views/WriteShortcutViews/WriteShortcutTitleView.swift +++ b/HappyAnding/HappyAnding/Views/WriteShortcutViews/WriteShortcutView.swift @@ -7,14 +7,16 @@ import SwiftUI -struct WriteShortcutTitleView: View { +struct WriteShortcutView: View { + @Environment(\.presentationMode) var presentationMode @EnvironmentObject var shortcutsZipViewModel: ShortcutsZipViewModel @EnvironmentObject var writeShortcutNavigation: WriteShortcutNavigation - @Environment(\.presentationMode) var presentationMode @Binding var isWriting: Bool + @State var isInfoButtonTouched = false + @State var isShowingIconModal = false @State var isNameValid = false @State var isLinkValid = false @@ -42,8 +44,6 @@ struct WriteShortcutTitleView: View { let isEdit: Bool - @State var isInfoButtonTouched: Bool = false - var body: some View { ScrollView(showsIndicators: false) { VStack(spacing: 32){ @@ -56,23 +56,17 @@ struct WriteShortcutTitleView: View { shortcutsRequiredApp } } - // .ignoresSafeArea(edges: .bottom) - .background(Color.Background) - .navigationTitle(isEdit ? "단축어 편집" : "단축어 등록") + .background(Color.shortcutsZipBackground) + .navigationTitle(isEdit ? TextLiteral.writeShortcutViewEdit : TextLiteral.writeShortcutViewPost) .navigationBarTitleDisplayMode(.inline) - .navigationDestination(for: Int.self) { value in - WriteShortcutdescriptionView(shortcut: $shortcut, - isWriting: $isWriting, - isEdit: isEdit) - } .toolbar { ToolbarItem(placement: .navigationBarLeading) { Button { self.presentationMode.wrappedValue.dismiss() } label: { - Text("취소") + Text(TextLiteral.cancel) .Body1() - .foregroundColor(.Gray5) + .foregroundColor(.gray5) } } @@ -85,114 +79,61 @@ struct WriteShortcutTitleView: View { shortcut.author = shortcutsZipViewModel.currentUser() if isEdit { - //뷰모델의 카테고리별 단축어 목록에서 정보 수정 - newCategory = shortcut.category - existingCategory.forEach { category in - if !shortcut.category.contains(category) { - newCategory.removeAll(where: { $0 == category }) - shortcutsZipViewModel.shortcutsInCategory[Category(rawValue: category)!.index].removeAll(where: { $0.id == shortcut.id }) - } else { - newCategory.removeAll(where: { $0 == category }) - if let index = shortcutsZipViewModel.shortcutsInCategory[Category(rawValue: category)!.index].firstIndex(where: { $0.id == shortcut.id}) { - shortcutsZipViewModel.shortcutsInCategory[Category(rawValue: category)!.index][index] = shortcut - } - } - } - newCategory.forEach { category in - if !shortcutsZipViewModel.isFirstFetchInCategory[Category(rawValue: category)!.index] { - shortcutsZipViewModel.shortcutsInCategory[Category(rawValue: category)!.index].insert(shortcut, at: 0) - } - } + //단축어 수정 + //뷰모델의 카테고리별 단축어 목록에서 정보 수정 및 해당 단축어가 포함된 큐레이션 수정 + shortcutsZipViewModel.updateShortcut(existingCategory: existingCategory, newCategory: shortcut.category, shortcut: shortcut) - //서버 데이터 변경 - shortcutsZipViewModel.setData(model: shortcut) - //TODO: 셀정보에 변경사항이 있을 경우에만 함수를 호출하도록 변경 필요 - shortcutsZipViewModel.updateShortcutInCuration( - shortcutCell: ShortcutCellModel( - id: shortcut.id, - sfSymbol: shortcut.sfSymbol, - color: shortcut.color, - title: shortcut.title, - subtitle: shortcut.subtitle, - downloadLink: shortcut.downloadLink.last! - ), - curationIDs: shortcut.curationIDs - ) } else { //새로운 단축어 생성 및 저장 // 뷰모델에 추가 shortcutsZipViewModel.shortcutsMadeByUser.insert(shortcut, at: 0) - // 서버에 추가 - shortcutsZipViewModel.setData(model: shortcut) } + // 서버에 추가 또는 수정 + shortcutsZipViewModel.setData(model: shortcut) isWriting.toggle() writeShortcutNavigation.navigationPath = .init() }, label: { - Text("업로드") + Text(TextLiteral.upload) .Headline() - .foregroundColor(.Primary) - .opacity(shortcut.color.isEmpty || - shortcut.sfSymbol.isEmpty || - shortcut.title.isEmpty || - !isNameValid || - shortcut.downloadLink.isEmpty || - !isLinkValid || - shortcut.subtitle.isEmpty || - !isOneLineValid || - shortcut.description.isEmpty || - !isMultiLineValid || - shortcut.category.isEmpty ? 0.3 : 1) + .foregroundColor(.shortcutsZipPrimary) + .opacity(isUnavailableUploadButton() ? 0.3 : 1) }) - .disabled(shortcut.color.isEmpty || - shortcut.sfSymbol.isEmpty || - shortcut.title.isEmpty || - !isNameValid || - shortcut.downloadLink.isEmpty || - !isLinkValid || - shortcut.subtitle.isEmpty || - !isOneLineValid || - shortcut.description.isEmpty || - !isMultiLineValid || - shortcut.category.isEmpty - ) + .disabled(isUnavailableUploadButton()) } } } + private func isUnavailableUploadButton() -> Bool { + shortcut.color.isEmpty || + shortcut.sfSymbol.isEmpty || + shortcut.title.isEmpty || + !isNameValid || + shortcut.downloadLink.isEmpty || + !isLinkValid || + shortcut.subtitle.isEmpty || + !isOneLineValid || + shortcut.description.isEmpty || + !isMultiLineValid || shortcut.category.isEmpty + } + //MARK: -아이콘 모달 버튼 private var iconModalView: some View { Button(action: { isShowingIconModal = true }, label: { - if shortcut.sfSymbol.isEmpty { - ZStack(alignment: .center) { - Rectangle() - .fill(Color.Gray1) - .cornerRadius(12.35) - .frame(width: 84, height: 84) - - Image(systemName: "plus") - .font(.system(size: 24)) - .frame(width: 84, height: 84) - .foregroundColor(.Gray5) - } - - } else { - ZStack(alignment: .center) { - Rectangle() - .fill(Color.fetchGradient(color: shortcut.color)) - .cornerRadius(12.35) - .frame(width: 84, height: 84) - - Image(systemName: shortcut.sfSymbol) - .font(.system(size: 32)) - .frame(width: 84, height: 84) - .foregroundColor(.Text_icon) - } + ZStack(alignment: .center) { + Rectangle() + .fill(!shortcut.sfSymbol.isEmpty ? Color.fetchGradient(color: shortcut.color) : Color.fetchDefualtGradient()) + .cornerRadius(12.35) + .frame(width: 84, height: 84) + Image(systemName: !shortcut.sfSymbol.isEmpty ? shortcut.sfSymbol : "plus") + .font(.system(size: 24)) + .frame(width: 84, height: 84) + .foregroundColor(!shortcut.sfSymbol.isEmpty ? .textIcon : .gray5) } }) .sheet(isPresented: $isShowingIconModal) { @@ -210,8 +151,8 @@ struct WriteShortcutTitleView: View { private var shortcutTitleText: some View { ValidationCheckTextField(textType: .mandatory, isMultipleLines: false, - title: "단축어 이름", - placeholder: "단축어 이름을 입력하세요", + title: TextLiteral.writeShortcutViewNameTitle, + placeholder: TextLiteral.writeShortcutViewNamePlaceholder, lengthLimit: 20, isDownloadLinkTextField: false, content: $shortcut.title, @@ -224,8 +165,8 @@ struct WriteShortcutTitleView: View { private var shortcutLinkText: some View { ValidationCheckTextField(textType: .mandatory, isMultipleLines: false, - title: "단축어 링크", - placeholder: "단축어 링크를 추가하세요", + title: TextLiteral.writeShortcutViewLinkTitle, + placeholder: TextLiteral.writeShortcutViewLinkPlaceholder, lengthLimit: nil, isDownloadLinkTextField: true, content: $shortcut.downloadLink[0], @@ -237,8 +178,8 @@ struct WriteShortcutTitleView: View { private var shortcutSubtitleText: some View { ValidationCheckTextField(textType: .mandatory, isMultipleLines: false, - title: "한줄 설명", - placeholder: "해당 단축어의 핵심 기능을 작성해주세요", + title: TextLiteral.writeShortcutViewOneLineTitle, + placeholder: TextLiteral.writeShortcutViewOneLinePlaceholder, lengthLimit: 20, isDownloadLinkTextField: false, content: $shortcut.subtitle, @@ -250,8 +191,8 @@ struct WriteShortcutTitleView: View { private var shortcutDescriptionText: some View { ValidationCheckTextField(textType: .mandatory, isMultipleLines: true, - title: "상세 설명", - placeholder: "단축어 사용법, 필수적으로 요구되는 사항 등 단축어를 이용하기 위해 필요한 정보를 입력해주세요", + title: TextLiteral.writeShortcutViewMultiLineTitle, + placeholder: TextLiteral.writeShortcutViewMultiLinePlaceholder, lengthLimit: 300, isDownloadLinkTextField: false, content: $shortcut.description, @@ -263,12 +204,12 @@ struct WriteShortcutTitleView: View { private var shortcutCategory: some View { VStack { HStack(alignment: .bottom) { - Text("카테고리") + Text(TextLiteral.writeShortcutViewCategoryTitle) .Headline() - .foregroundColor(.Gray5) - Text("최대 3개") + .foregroundColor(.gray5) + Text(TextLiteral.writeShortcutViewCategoryDescription) .Footnote() - .foregroundColor(.Gray3) + .foregroundColor(.gray3) Spacer() } .padding(.horizontal, 16) @@ -288,23 +229,23 @@ struct WriteShortcutTitleView: View { }, label: { HStack { if selectedCategories.isEmpty { - Text("카테고리 선택") - .foregroundColor(.Gray2) + Text(TextLiteral.writeShortcutViewCategoryCell) + .foregroundColor(.gray2) .Body2() } else { Text(selectedCategories.map { Category(rawValue: $0)!.translateName() }.joined(separator: ", ")) - .foregroundColor(.Gray4) + .foregroundColor(.gray4) .Body2() .multilineTextAlignment(.leading) } Spacer() Image(systemName: "chevron.forward") - .foregroundColor(selectedCategories.isEmpty ? .Gray2 : .Gray4) + .foregroundColor(selectedCategories.isEmpty ? .gray2 : .gray4) } .padding(.all, 16) .overlay( RoundedRectangle(cornerRadius: 12) - .strokeBorder(selectedCategories.isEmpty ? Color.Gray2 : Color.Gray4, lineWidth: 1) + .strokeBorder(selectedCategories.isEmpty ? Color.gray2 : Color.gray4, lineWidth: 1) ) }) .sheet(isPresented: $isShowingCategoryModal) { @@ -322,16 +263,16 @@ struct WriteShortcutTitleView: View { private var shortcutsRequiredApp: some View { VStack { HStack(alignment: .bottom) { - Text("단축어 사용을 위해 필요한 앱") + Text(TextLiteral.writeShortcutViewRequiredAppsTitle) .Headline() - .foregroundColor(.Gray5) - Text("(선택)") + .foregroundColor(.gray5) + Text(TextLiteral.writeShortcutViewRequiredAppDescription) .Footnote() - .foregroundColor(.Gray3) + .foregroundColor(.gray3) Spacer() Image(systemName: "info.circle.fill") .frame(width: 20, height: 20) - .foregroundColor(.Gray4) + .foregroundColor(.gray4) .onTapGesture { isInfoButtonTouched.toggle() } @@ -344,16 +285,16 @@ struct WriteShortcutTitleView: View { ZStack(alignment: .center) { RoundedRectangle(cornerRadius: 12) .frame(maxWidth: .infinity, maxHeight: 68) - .foregroundColor(.Gray5) + .foregroundColor(.gray5) HStack(alignment: .top) { - Text("해당 단축어를 사용하기 위해 필수로 다운로드해야 하는 앱을 작성해 주세요") + Text(TextLiteral.writeShortcutViewRequiredAppInformation) .Footnote() - .foregroundColor(.Gray1) + .foregroundColor(.gray1) .multilineTextAlignment(.leading) Spacer() Image(systemName: "xmark") .frame(width: 16, height: 16) - .foregroundColor(.Gray1) + .foregroundColor(.gray1) .onTapGesture { isInfoButtonTouched = false } @@ -366,9 +307,10 @@ struct WriteShortcutTitleView: View { } } struct relatedAppList: View { + @FocusState private var isFocused: Bool + @Binding var relatedApps: [String] - @FocusState private var isFocused: Bool @State var isTextFieldShowing = false @State var relatedApp = "" @@ -376,7 +318,7 @@ struct WriteShortcutTitleView: View { ScrollView(.horizontal) { HStack(spacing: 8) { ForEach(relatedApps, id:\.self) { item in - RelatedAppTag(item: item, items: $relatedApps) + RelatedAppTag(items: $relatedApps, item: item) } if isTextFieldShowing { @@ -395,7 +337,7 @@ struct WriteShortcutTitleView: View { isTextFieldShowing = false } } - .modifier(CellModifier(foregroundColor: Color.Gray4, strokeColor: Color.Primary)) + .modifier(CellModifier(foregroundColor: Color.gray4, strokeColor: Color.shortcutsZipPrimary)) } Button(action: { @@ -404,10 +346,10 @@ struct WriteShortcutTitleView: View { }, label: { HStack { Image(systemName: "plus") - Text("앱 추가") + Text(TextLiteral.writeShortcutViewRequiredAppCell) } }) - .modifier(CellModifier(foregroundColor: Color.Gray2, strokeColor: Color.Gray2)) + .modifier(CellModifier(foregroundColor: Color.gray2, strokeColor: Color.gray2)) } .padding(.leading, 16) } @@ -415,9 +357,10 @@ struct WriteShortcutTitleView: View { } } struct RelatedAppTag: View { - var item: String @Binding var items: [String] + var item: String + var body: some View { HStack { Text(item) @@ -428,9 +371,9 @@ struct WriteShortcutTitleView: View { Image(systemName: "xmark") }) } - .modifier(CellModifier(foregroundColor: Color.Gray4, - backgroundColor: Color.Background, - strokeColor: Color.Gray4)) + .modifier(CellModifier(foregroundColor: Color.gray4, + backgroundColor: Color.shortcutsZipBackground, + strokeColor: Color.gray4)) } } struct CellModifier: ViewModifier { @@ -464,7 +407,7 @@ struct WriteShortcutTitleView: View { }) { Image(systemName: "xmark.circle.fill") .Body2() - .foregroundColor(.Gray4) + .foregroundColor(.gray4) } } } diff --git a/HappyAnding/HappyAnding/Views/WriteShortcutViews/WriteShortcutdescriptionView.swift b/HappyAnding/HappyAnding/Views/WriteShortcutViews/WriteShortcutdescriptionView.swift deleted file mode 100644 index 92c4c403..00000000 --- a/HappyAnding/HappyAnding/Views/WriteShortcutViews/WriteShortcutdescriptionView.swift +++ /dev/null @@ -1,83 +0,0 @@ -// -// WriteShortcutdescriptionView.swift -// HappyAnding -// -// Created by 이지원 on 2022/10/19. -// - -import SwiftUI - -struct WriteShortcutdescriptionView: View { - - @Binding var shortcut: Shortcuts - @Binding var isWriting: Bool - - @State var isOneLineValid = false - @State var isMultiLineValid = false - - let isEdit: Bool - - enum NavigationWriteTagView: Hashable, Equatable { - case first - } - - var body: some View { - VStack { - ProgressView(value: 0.66, total: 1) - .padding(.bottom, 36) - - ValidationCheckTextField(textType: .mandatory, - isMultipleLines: false, - title: "한줄 설명", - placeholder: "간단하게 설명을 작성해주세요", - lengthLimit: 35, - isDownloadLinkTextField: false, - content: $shortcut.subtitle, - isValid: $isOneLineValid - ) - - ValidationCheckTextField(textType: .mandatory, - isMultipleLines: true, - title: "설명", - placeholder: "단축어에 대한 설명을 작성해주세요\n\n예시)\n- 이럴때 사용하면 좋아요\n- 이 단축어는 이렇게 사용해요", - lengthLimit: 500, - isDownloadLinkTextField: false, - content: $shortcut.description, - isValid: $isMultiLineValid - ) - - Spacer() - - NavigationLink(value: NavigationWriteTagView.first) { - ZStack { - RoundedRectangle(cornerRadius: 12) - .foregroundColor(isOneLineValid && isMultiLineValid ? .Primary : .Primary .opacity(0.13) ) - .frame(maxWidth: .infinity, maxHeight: 52) - - Text("다음") - .foregroundColor(isOneLineValid && isMultiLineValid ? .Text_icon : .Text_Button_Disable ) - .Body1() - } - } - - .disabled(!isOneLineValid || !isMultiLineValid) - .padding(.horizontal, 16) - .padding(.bottom, 24) - } - .navigationDestination(for: NavigationWriteTagView.self) { value in - WriteShortcutTagView(isWriting: $isWriting, - shortcut: $shortcut, - isEdit: isEdit) - } - .navigationTitle(isEdit ? "단축어 편집" : "단축어 등록") - .ignoresSafeArea(.keyboard) - .background(Color.Background) - } -} -/* -struct WriteShortcutdescriptionView_Previews: PreviewProvider { - static var previews: some View { - WriteShortcutdescriptionView(isWriting: .constant(true), isEdit: false) - } -} -*/ diff --git a/HappyAnding/ShareExtension/CustomShareViewController.swift b/HappyAnding/ShareExtension/CustomShareViewController.swift index 88511a9b..d5f6d994 100644 --- a/HappyAnding/ShareExtension/CustomShareViewController.swift +++ b/HappyAnding/ShareExtension/CustomShareViewController.swift @@ -29,10 +29,10 @@ class CustomShareViewController: UIViewController { NotificationCenter.default.addObserver(self, selector: #selector(inEnabledDoneButton), name: NSNotification.Name(rawValue: "inEnabledDoneButton"), object: nil) //로그인 정보 empty 일 때 - if UserDefaults.shared.string(forKey: "ShareUserInfo") == nil { - let alert = UIAlertController(title: "로그인을 먼저 진행해주세요", message: - "이 기능은 로그인 후 사용할 수 있는 기능이에요", preferredStyle: .alert) - let action = UIAlertAction(title: "확인", style: .default) { _ in + if UserDefaults.shared.string(forKey: "ShareUserInfo") == nil || UserDefaults.shared.bool(forKey: "isSignInForShareExtension") == false { + let alert = UIAlertController(title: TextLiteral.customShareViewControllerSignInAlertTitle, message: + TextLiteral.customShareViewControllerSignInAlertMessage, preferredStyle: .alert) + let action = UIAlertAction(title: TextLiteral.customShareViewControllerCheck, style: .default) { _ in self.extensionContext?.completeRequest(returningItems: [], completionHandler: nil) } alert.addAction(action) @@ -43,8 +43,8 @@ class CustomShareViewController: UIViewController { //링크가 적절하지 않을 때 if !self.shareExtensionViewModel.isLinkValid(content: "\(url)") { - let alert = UIAlertController(title: "잘못된 접근이에요", message:"해당 링크는 ShortcutsZip으로 공유할 수 없어요", preferredStyle: .alert) - let action = UIAlertAction(title: "확인", style: .default) { action in + let alert = UIAlertController(title: TextLiteral.customShareViewControllerLinkVaildAlertTitle, message: TextLiteral.customShareViewControllerLinkVaildAlertMessage, preferredStyle: .alert) + let action = UIAlertAction(title: TextLiteral.customShareViewControllerCheck, style: .default) { action in self.extensionContext?.completeRequest(returningItems: [], completionHandler: nil) } alert.addAction(action) @@ -53,7 +53,7 @@ class CustomShareViewController: UIViewController { //익스텐션 뷰 뜸 self.shareExtensionViewModel.shortcut.downloadLink.append("\(url)") - let extShortcutsView = UIHostingController(rootView: ShareExtensionWriteShortcutTitleView(shareExtensionViewModel: self.shareExtensionViewModel)) + let extShortcutsView = UIHostingController(rootView: ShareExtensionWriteShortcutView(shareExtensionViewModel: self.shareExtensionViewModel)) self.view.addSubview(extShortcutsView.view) extShortcutsView.view.translatesAutoresizingMaskIntoConstraints = false extShortcutsView.view.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true @@ -62,7 +62,7 @@ class CustomShareViewController: UIViewController { extShortcutsView.view.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true } setupNavBar() - self.view.backgroundColor = UIColor.Background + self.view.backgroundColor = UIColor.shortcutsZipBackground } override func viewDidDisappear(_ animated: Bool) { @@ -108,12 +108,12 @@ class CustomShareViewController: UIViewController { navigationController!.navigationBar.compactScrollEdgeAppearance = newNavBarAppearance } - self.navigationItem.title = "단축어 작성" + self.navigationItem.title = TextLiteral.writeShortcutViewPost let cancelButton: UIButton = { let button = UIButton() - button.setTitle("취소", for: .normal) - button.setTitleColor(UIColor.Gray4, for: .normal) + button.setTitle(TextLiteral.cancel, for: .normal) + button.setTitleColor(UIColor.gray4, for: .normal) button.titleLabel?.font = UIFont.Body1 button.addTarget(self, action: #selector(cancelAction), for: .touchUpInside) @@ -122,7 +122,7 @@ class CustomShareViewController: UIViewController { itemCancel = UIBarButtonItem(customView: cancelButton) self.navigationItem.setLeftBarButton(itemCancel, animated: false) - itemDone = UIBarButtonItem(title: "업로드", style: .plain, target: self, action: #selector(doneAction)) + itemDone = UIBarButtonItem(title: TextLiteral.upload, style: .plain, target: self, action: #selector(doneAction)) self.navigationItem.setRightBarButton(itemDone, animated: false) itemDone.isEnabled = false @@ -147,17 +147,17 @@ class CustomShareViewController: UIViewController { let customNavBarAppearance = UINavigationBarAppearance() customNavBarAppearance.configureWithOpaqueBackground() - customNavBarAppearance.backgroundColor = UIColor.Background + customNavBarAppearance.backgroundColor = UIColor.shortcutsZipBackground customNavBarAppearance.shadowColor = .clear - customNavBarAppearance.titleTextAttributes = [.foregroundColor: UIColor.Gray5] - customNavBarAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.Gray5] + customNavBarAppearance.titleTextAttributes = [.foregroundColor: UIColor.gray5] + customNavBarAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.gray5] let barButtonItemAppearance = UIBarButtonItemAppearance(style: .plain) - barButtonItemAppearance.normal.titleTextAttributes = [.foregroundColor: UIColor.Primary, .font: UIFont.Headline] - barButtonItemAppearance.disabled.titleTextAttributes = [.foregroundColor: UIColor.PrimaryOpacity] + barButtonItemAppearance.normal.titleTextAttributes = [.foregroundColor: UIColor.shortcutsZipPrimary, .font: UIFont.Headline] + barButtonItemAppearance.disabled.titleTextAttributes = [.foregroundColor: UIColor.shortcutsZipPrimaryOpacity] barButtonItemAppearance.highlighted.titleTextAttributes = [.foregroundColor: UIColor.label] - barButtonItemAppearance.focused.titleTextAttributes = [.foregroundColor: UIColor.Gray5] + barButtonItemAppearance.focused.titleTextAttributes = [.foregroundColor: UIColor.gray5] customNavBarAppearance.buttonAppearance = barButtonItemAppearance customNavBarAppearance.backButtonAppearance = barButtonItemAppearance customNavBarAppearance.doneButtonAppearance = barButtonItemAppearance diff --git a/HappyAnding/ShareExtension/ShareExtensionCustomTextEditor.swift b/HappyAnding/ShareExtension/ShareExtensionCustomTextEditor.swift index 3b9b906c..cb1139a1 100644 --- a/HappyAnding/ShareExtension/ShareExtensionCustomTextEditor.swift +++ b/HappyAnding/ShareExtension/ShareExtensionCustomTextEditor.swift @@ -19,7 +19,7 @@ struct ShareExtensionCustomTextEditor: UIViewRepresentable { textView.delegate = context.coordinator textView.font = .Body2 textView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) - textView.backgroundColor = UIColor(.Background) + textView.backgroundColor = UIColor(.shortcutsZipBackground) return textView } diff --git a/HappyAnding/ShareExtension/ShareExtensionTagTextField.swift b/HappyAnding/ShareExtension/ShareExtensionTagTextField.swift index 668a87a8..e6507463 100644 --- a/HappyAnding/ShareExtension/ShareExtensionTagTextField.swift +++ b/HappyAnding/ShareExtension/ShareExtensionTagTextField.swift @@ -22,7 +22,7 @@ struct ShareExtensionTagTextField: UIViewRepresentable { public func makeUIView(context: Context) -> UITextField { let view = UITextField() view.font = .Body2 - view.textColor = UIColor.Gray4 + view.textColor = UIColor.gray4 view.addTarget(context.coordinator, action: #selector(Coordinator.textViewDidChange), for: .editingChanged) view.delegate = context.coordinator return view diff --git a/HappyAnding/ShareExtension/ShareExtensionValidationTextField.swift b/HappyAnding/ShareExtension/ShareExtensionValidationTextField.swift index fd4f1ad9..71c8f564 100644 --- a/HappyAnding/ShareExtension/ShareExtensionValidationTextField.swift +++ b/HappyAnding/ShareExtension/ShareExtensionValidationTextField.swift @@ -31,15 +31,15 @@ enum TextFieldState { var color: Color { switch self { case .notStatus: - return Color.Gray2 + return Color.gray2 case .inProgressSuccess: - return Color.Primary + return Color.shortcutsZipPrimary case .inProgressFail: - return Color.red + return Color.shortcutsZipError case .doneSuccess: - return Color.Gray4 + return Color.gray4 case .doneFail: - return Color.red + return Color.shortcutsZipError } } } @@ -51,9 +51,9 @@ enum TextFieldError { var message: String { switch self { case .invalidLink: - return "유효하지 않은 링크입니다." + return TextLiteral.validationCheckTextFieldInvalid case .excessLimitLenth: - return "입력할 수 있는 문자 수를 초과했습니다." + return TextLiteral.validationCheckTextFieldExcess } } } @@ -70,7 +70,7 @@ struct ShareExtensionValidationCheckTextField: View { @Binding var content: String @Binding var isValid: Bool - @State private var strokeColor = Color.Gray2 + @State private var strokeColor = Color.gray2 @State private var isExceeded = false @State private var textFieldState = TextFieldState.notStatus @State private var textFieldError = TextFieldError.invalidLink @@ -91,7 +91,7 @@ struct ShareExtensionValidationCheckTextField: View { if let lengthLimit { Text("\(content.count)/\(lengthLimit)") .Body2() - .foregroundColor(.Gray4) + .foregroundColor(.gray4) .padding(.trailing, 16) } } @@ -117,7 +117,7 @@ struct ShareExtensionValidationCheckTextField: View { if isExceeded { Text(textFieldError.message) .Body2() - .foregroundColor(.Error) + .foregroundColor(.shortcutsZipError) .padding(.leading) } @@ -134,13 +134,13 @@ struct ShareExtensionValidationCheckTextField: View { HStack { Text(title) .Headline() - .foregroundColor(.Gray5) + .foregroundColor(.gray5) .padding(.leading, 16) if textType.isOptional { - Text("(선택입력)") + Text(TextLiteral.validationCheckTextFieldOption) .Footnote() - .foregroundColor(.Gray3) + .foregroundColor(.gray3) } } .frame(maxWidth: .infinity, alignment: .leading) @@ -188,7 +188,7 @@ struct ShareExtensionValidationCheckTextField: View { .frame(maxWidth: .infinity, alignment: .leading) .multilineTextAlignment(.leading) .padding(16) - .foregroundColor(.Gray2) + .foregroundColor(.gray2) .allowsHitTesting(false) } } @@ -213,19 +213,19 @@ struct ShareExtensionValidationCheckTextField: View { case .doneSuccess: Image(systemName: "checkmark.circle.fill") .Body2() - .foregroundColor(.Success) + .foregroundColor(.shortcutsZipSuccess) .onTapGesture { } case .doneFail: Image(systemName: "exclamationmark.circle.fill") .Body2() - .foregroundColor(.red) + .foregroundColor(.shortcutsZipError) case .inProgressSuccess: Button { content.removeAll() } label: { Image(systemName: "xmark.circle.fill") .Body2() - .foregroundColor(.Gray5) + .foregroundColor(.gray5) } case .inProgressFail: Button { @@ -233,7 +233,7 @@ struct ShareExtensionValidationCheckTextField: View { } label: { Image(systemName: "xmark.circle.fill") .Body2() - .foregroundColor(.Gray5) + .foregroundColor(.gray5) } } } @@ -251,7 +251,7 @@ extension ShareExtensionValidationCheckTextField { self.textFieldState = .inProgressSuccess } else if content.count <= lengthLimit ?? 999 { if isDownloadLinkTextField { - if content.hasPrefix("https://www.icloud.com/shortcuts/") { + if content.hasPrefix(TextLiteral.validationCheckTextFieldPrefix) { isValid = true isExceeded = false self.textFieldState = .inProgressSuccess diff --git a/HappyAnding/ShareExtension/ShareExtensionViewModel.swift b/HappyAnding/ShareExtension/ShareExtensionViewModel.swift index d2f98a0d..4ad97de6 100644 --- a/HappyAnding/ShareExtension/ShareExtensionViewModel.swift +++ b/HappyAnding/ShareExtension/ShareExtensionViewModel.swift @@ -41,6 +41,6 @@ class ShareExtensionViewModel: ObservableObject { } func isLinkValid(content: String) -> Bool { - content.hasPrefix("https://www.icloud.com/shortcuts/") + content.hasPrefix(TextLiteral.validationCheckTextFieldPrefix) } } diff --git a/HappyAnding/ShareExtension/ShareExtensionWriteShortcutTitleView.swift b/HappyAnding/ShareExtension/ShareExtensionWriteShortcutView.swift similarity index 83% rename from HappyAnding/ShareExtension/ShareExtensionWriteShortcutTitleView.swift rename to HappyAnding/ShareExtension/ShareExtensionWriteShortcutView.swift index 4e13a4f5..1cf9792a 100644 --- a/HappyAnding/ShareExtension/ShareExtensionWriteShortcutTitleView.swift +++ b/HappyAnding/ShareExtension/ShareExtensionWriteShortcutView.swift @@ -1,5 +1,5 @@ // -// ShareExtensionWriteShortcutTitleView.swift +// ShareExtensionWriteShortcutView.swift // ShareExtension // // Created by HanGyeongjun on 2022/11/22. @@ -7,9 +7,7 @@ import SwiftUI - - -struct ShareExtensionWriteShortcutTitleView: View { +struct ShareExtensionWriteShortcutView: View { enum TextFieldType { case shortcutTitleText @@ -28,7 +26,6 @@ struct ShareExtensionWriteShortcutTitleView: View { @State var isMultiLineValid = false @State var isShowingCategoryModal = false @State var isInfoButtonTouched: Bool = false - @State var isTextFocused = [Bool](repeating: false, count: 5) var body: some View { @@ -43,7 +40,7 @@ struct ShareExtensionWriteShortcutTitleView: View { shortcutsRequiredApp } } - .background(Color.Background) + .background(Color.shortcutsZipBackground) .onChange(of: shareExtensionViewModel.shortcut) { _ in let isDoneValid = shareExtensionViewModel.isDoneValid() @@ -66,14 +63,14 @@ struct ShareExtensionWriteShortcutTitleView: View { if shareExtensionViewModel.shortcut.sfSymbol.isEmpty { ZStack(alignment: .center) { Rectangle() - .fill(Color.Gray1) + .fill(Color.gray1) .cornerRadius(12.35) .frame(width: 84, height: 84) Image(systemName: "plus") .font(.system(size: 24)) .frame(width: 84, height: 84) - .foregroundColor(.Gray5) + .foregroundColor(.gray5) } } else { @@ -86,7 +83,7 @@ struct ShareExtensionWriteShortcutTitleView: View { Image(systemName: shareExtensionViewModel.shortcut.sfSymbol) .font(.system(size: 32)) .frame(width: 84, height: 84) - .foregroundColor(.Text_icon) + .foregroundColor(.textIcon) } } }) @@ -105,8 +102,8 @@ struct ShareExtensionWriteShortcutTitleView: View { private var shortcutTitleText: some View { ShareExtensionValidationCheckTextField(textType: .mandatory, isMultipleLines: false, - title: "단축어 이름", - placeholder: "단축어 이름을 입력하세요", + title: TextLiteral.writeShortcutViewNameTitle, + placeholder: TextLiteral.writeShortcutViewNamePlaceholder, lengthLimit: 20, isDownloadLinkTextField: false, content: $shareExtensionViewModel.shortcut.title, @@ -119,8 +116,8 @@ struct ShareExtensionWriteShortcutTitleView: View { private var shortcutLinkText: some View { ShareExtensionValidationCheckTextField(textType: .mandatory, isMultipleLines: false, - title: "단축어 링크", - placeholder: "단축어 링크를 추가하세요", + title: TextLiteral.writeShortcutViewLinkTitle, + placeholder: TextLiteral.writeShortcutViewLinkPlaceholder, lengthLimit: nil, isDownloadLinkTextField: true, content: $shareExtensionViewModel.shortcut.downloadLink[0], @@ -134,8 +131,8 @@ struct ShareExtensionWriteShortcutTitleView: View { private var shortcutSubtitleText: some View { ShareExtensionValidationCheckTextField(textType: .mandatory, isMultipleLines: false, - title: "한줄 설명", - placeholder: "해당 단축어의 핵심 기능을 작성해주세요", + title: TextLiteral.writeShortcutViewOneLineTitle, + placeholder: TextLiteral.writeShortcutViewOneLinePlaceholder, lengthLimit: 20, isDownloadLinkTextField: false, content: $shareExtensionViewModel.shortcut.subtitle, @@ -149,8 +146,8 @@ struct ShareExtensionWriteShortcutTitleView: View { private var shortcutDescriptionText: some View { ShareExtensionValidationCheckTextField(textType: .mandatory, isMultipleLines: true, - title: "상세 설명", - placeholder: "단축어 사용법, 필수적으로 요구되는 사항 등 단축어를 이용하기 위해 필요한 정보를 입력해주세요", + title: TextLiteral.writeShortcutViewMultiLineTitle, + placeholder: TextLiteral.writeShortcutViewMultiLinePlaceholder, lengthLimit: 300, isDownloadLinkTextField: false, content: $shareExtensionViewModel.shortcut.description, @@ -163,12 +160,12 @@ struct ShareExtensionWriteShortcutTitleView: View { private var shortcutCategory: some View { VStack { HStack(alignment: .bottom) { - Text("카테고리") + Text(TextLiteral.writeShortcutViewCategoryTitle) .Headline() - .foregroundColor(.Gray5) - Text("최대 3개") + .foregroundColor(.gray5) + Text(TextLiteral.writeShortcutViewCategoryDescription) .Footnote() - .foregroundColor(.Gray3) + .foregroundColor(.gray3) Spacer() } .padding(.horizontal, 16) @@ -188,23 +185,23 @@ struct ShareExtensionWriteShortcutTitleView: View { }, label: { HStack { if selectedCategories.isEmpty { - Text("카테고리 선택") - .foregroundColor(.Gray2) + Text(TextLiteral.writeShortcutViewCategoryCell) + .foregroundColor(.gray2) .Body2() } else { Text(selectedCategories.map { String( Category(rawValue: $0)!.translateName()) }.joined(separator: ", ")) - .foregroundColor(.Gray4) + .foregroundColor(.gray4) .Body2() .multilineTextAlignment(.leading) } Spacer() Image(systemName: "chevron.forward") - .foregroundColor(selectedCategories.isEmpty ? .Gray2 : .Gray4) + .foregroundColor(selectedCategories.isEmpty ? .gray2 : .gray4) } .padding(.all, 16) .overlay( RoundedRectangle(cornerRadius: 12) - .strokeBorder(selectedCategories.isEmpty ? Color.Gray2 : Color.Gray4, lineWidth: 1) + .strokeBorder(selectedCategories.isEmpty ? Color.gray2 : Color.gray4, lineWidth: 1) ) }) .sheet(isPresented: $isShowingCategoryModal) { @@ -222,16 +219,16 @@ struct ShareExtensionWriteShortcutTitleView: View { private var shortcutsRequiredApp: some View { VStack { HStack(alignment: .bottom) { - Text("단축어 사용을 위해 필요한 앱") + Text(TextLiteral.writeShortcutViewRequiredAppsTitle) .Headline() - .foregroundColor(.Gray5) - Text("(선택)") + .foregroundColor(.gray5) + Text(TextLiteral.writeShortcutViewRequiredAppDescription) .Footnote() - .foregroundColor(.Gray3) + .foregroundColor(.gray3) Spacer() Image(systemName: "info.circle.fill") .frame(width: 20, height: 20) - .foregroundColor(.Gray4) + .foregroundColor(.gray4) .onTapGesture { isInfoButtonTouched.toggle() } @@ -244,16 +241,16 @@ struct ShareExtensionWriteShortcutTitleView: View { ZStack(alignment: .center) { RoundedRectangle(cornerRadius: 12) .frame(maxWidth: .infinity, maxHeight: 68) - .foregroundColor(.Gray5) + .foregroundColor(.gray5) HStack(alignment: .top) { - Text("해당 단축어를 사용하기 위해 필수로 다운로드해야 하는 앱을 작성해 주세요") + Text(TextLiteral.writeShortcutViewRequiredAppInformation) .Footnote() - .foregroundColor(.Gray1) + .foregroundColor(.gray1) .multilineTextAlignment(.leading) Spacer() Image(systemName: "xmark") .frame(width: 16, height: 16) - .foregroundColor(.Gray1) + .foregroundColor(.gray1) .onTapGesture { isInfoButtonTouched = false } @@ -275,7 +272,7 @@ struct ShareExtensionWriteShortcutTitleView: View { ScrollView(.horizontal) { HStack(spacing: 8) { ForEach(relatedApps, id:\.self) { item in - RelatedAppTag(item: item, items: $relatedApps) + RelatedAppTag(items: $relatedApps, item: item) } if isTextFieldShowing { @@ -296,7 +293,7 @@ struct ShareExtensionWriteShortcutTitleView: View { .onSubmit { isTextFocused[4] = false } - .modifier(CellModifier(foregroundColor: Color.Gray4, strokeColor: Color.Primary)) + .modifier(CellModifier(foregroundColor: Color.gray4, strokeColor: Color.shortcutsZipPrimary)) } Button(action: { @@ -305,10 +302,10 @@ struct ShareExtensionWriteShortcutTitleView: View { }, label: { HStack { Image(systemName: "plus") - Text("앱 추가") + Text(TextLiteral.writeShortcutViewRequiredAppCell) } }) - .modifier(CellModifier(foregroundColor: Color.Gray2, strokeColor: Color.Gray2)) + .modifier(CellModifier(foregroundColor: Color.gray2, strokeColor: Color.gray2)) } .padding(.leading, 16) } @@ -316,8 +313,8 @@ struct ShareExtensionWriteShortcutTitleView: View { } } struct RelatedAppTag: View { - var item: String @Binding var items: [String] + var item: String var body: some View { HStack { @@ -333,9 +330,9 @@ struct ShareExtensionWriteShortcutTitleView: View { Image(systemName: "xmark") }) } - .modifier(CellModifier(foregroundColor: Color.Gray4, - backgroundColor: Color.Background, - strokeColor: Color.Gray4)) + .modifier(CellModifier(foregroundColor: Color.gray4, + backgroundColor: Color.shortcutsZipBackground, + strokeColor: Color.gray4)) } } struct CellModifier: ViewModifier { @@ -369,7 +366,7 @@ struct ShareExtensionWriteShortcutTitleView: View { }) { Image(systemName: "xmark.circle.fill") .Body2() - .foregroundColor(.Gray4) + .foregroundColor(.gray4) } } } diff --git a/README.md b/README.md index f371c3ff..41a7a8db 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

- +

@@ -78,7 +78,7 @@ ## Contributors -[@Elie](https://www.github.com/JMM00) | [@Green](https://www.github.com/jim4020key) | [@Halogen](https://www.github.com/HanGyengjun) | [@HongKi](https://www.github.com/otoolz) | [@Romi](https://www.github.com/mxnxxii ) | [@Soi](https://www.github.com/JIWON1923) | +[@Elie](https://www.github.com/JMM00) | [@Green](https://www.github.com/jim4020key) | [@Halogen](https://www.github.com/HanGyeongjun) | [@HongKi](https://www.github.com/otoolz) | [@Romi](https://www.github.com/mxnxxii ) | [@Soi](https://www.github.com/JIWON1923) | :---|:---|:---|:---|:---|:--- |![elie](https://user-images.githubusercontent.com/68676844/205005538-38658595-9627-4df2-80a5-bdcb6c93b18c.png)|![green](https://user-images.githubusercontent.com/68676844/205005410-a773b326-9c49-47ea-8313-24dc9822f6d6.png)|![halogen](https://user-images.githubusercontent.com/68676844/205005492-210bffd4-4a52-44c2-89ad-65c7c8b838c4.png)|![hongki](https://user-images.githubusercontent.com/68676844/205005435-fd4ccbea-41aa-434f-9889-84f93f988093.png)|![romi](https://user-images.githubusercontent.com/68676844/205005382-74f5b3a6-93a8-4f48-b70e-339f6867ddab.png)|![soi](https://user-images.githubusercontent.com/68676844/205079322-77590700-1f9c-4363-8c7e-33cb2eafa22e.png)