diff --git a/CHANGELOG.md b/CHANGELOG.md index d5febe2bf..df2403eec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added a tip to the Feed to welcome first-time users and explain how the Feed works. [#1602](https://github.com/planetary-social/nos/issues/1602) - Added a tag to published contact lists to help us detect the source of lost contact lists. [cleanstr#51](https://github.com/planetary-social/cleanstr/issues/51) - Removed integration with Universal Name Space [#1636](https://github.com/planetary-social/nos/issues/1636) +- Remove most usage of xcstringstool-generated strings to improve performance. [#1458](https://github.com/planetary-social/nos/issues/1458) ### Internal Changes - Migrate ObservableObject to @Observable where possible [#1458](https://github.com/planetary-social/nos/issues/1458) diff --git a/Nos/Controller/ContentWarningController.swift b/Nos/Controller/ContentWarningController.swift index 705d0af15..1513a5b03 100644 --- a/Nos/Controller/ContentWarningController.swift +++ b/Nos/Controller/ContentWarningController.swift @@ -47,7 +47,7 @@ enum ContentWarningType { /// The name of the first author in the list of reports private var firstAuthorSafeName: String { - authorNames.first ?? String(localized: .localizable.unknownAuthor) + authorNames.first ?? String(localized: "unknownAuthor") } /// The string explaining the reason(s) for the reports. @@ -57,7 +57,7 @@ enum ContentWarningType { .sorted() .joined(separator: ", ") if reasons.isEmpty { - return String(localized: .localizable.error) + return String(localized: "error") } else { return reasons } diff --git a/Nos/Controller/RawEventController.swift b/Nos/Controller/RawEventController.swift index 376c018d4..42209c034 100644 --- a/Nos/Controller/RawEventController.swift +++ b/Nos/Controller/RawEventController.swift @@ -51,7 +51,7 @@ protocol RawEventViewModel { } private func loadRawMessage() { - loadingMessage = String(localized: .localizable.loading) + loadingMessage = String(localized: "loading") let rawMessage: String do { diff --git a/Nos/Extensions/Date+Elapsed.swift b/Nos/Extensions/Date+Elapsed.swift index 72e2093a1..e91a503b3 100644 --- a/Nos/Extensions/Date+Elapsed.swift +++ b/Nos/Extensions/Date+Elapsed.swift @@ -76,7 +76,7 @@ extension Date { return formattedDate } } else { - return String(localized: .localizable.now) + return String(localized: "now") } } diff --git a/Nos/Models/AppDestination.swift b/Nos/Models/AppDestination.swift index 1cce177e0..4483d8f43 100644 --- a/Nos/Models/AppDestination.swift +++ b/Nos/Models/AppDestination.swift @@ -12,15 +12,15 @@ enum AppDestination: Hashable, Equatable { var destinationString: String { switch self { case .home: - return String(localized: .localizable.homeFeed) + return String(localized: "homeFeed") case .discover: - return String(localized: .localizable.discover) + return String(localized: "discover") case .notifications: - return String(localized: .localizable.notifications) + return String(localized: "notifications") case .noteComposer: - return String(localized: .localizable.newNote) + return String(localized: "newNote") case .profile: - return String(localized: .localizable.profileTitle) + return String(localized: "profileTitle") } } diff --git a/Nos/Models/ExpirationTimeOption.swift b/Nos/Models/ExpirationTimeOption.swift index 9b4cf58e6..f891d66aa 100644 --- a/Nos/Models/ExpirationTimeOption.swift +++ b/Nos/Models/ExpirationTimeOption.swift @@ -31,13 +31,13 @@ enum ExpirationTimeOption: Double, Identifiable, CaseIterable { var unit: String { switch self { case .oneHour: - return String(localized: .localizable.hourAbbreviated) + return String(localized: "hourAbbreviated") case .oneDay: - return String(localized: .localizable.hoursAbbreviated) + return String(localized: "hoursAbbreviated") case .sevenDays: - return String(localized: .localizable.daysAbbreviated) + return String(localized: "daysAbbreviated") case .oneYear: - return String(localized: .localizable.daysAbbreviated) + return String(localized: "daysAbbreviated") } } diff --git a/Nos/Models/FlagOption.swift b/Nos/Models/FlagOption.swift index 29656c003..78f449155 100644 --- a/Nos/Models/FlagOption.swift +++ b/Nos/Models/FlagOption.swift @@ -37,17 +37,17 @@ struct FlagOption: Identifiable, Equatable { /// `FlagOption` instances representing different categories of how a content can can be flagged. static let flagContentSendOptions: [FlagOption] = [ FlagOption( - title: String(localized: .localizable.flagSendToNosTitle), - description: String(localized: .localizable.flagSendToNosDescription), + title: String(localized: "flagSendToNosTitle"), + description: String(localized: "flagSendToNosDescription"), info: { selectedTitle in guard let selectedTitle = selectedTitle else { return nil } - return String(localized: .localizable.flagUserSendToNosInfo(selectedTitle)) + return String.localizedStringWithFormat(String(localized: "flagUserSendToNosInfo"), selectedTitle) }, category: .privacy(.sendToNos) ), FlagOption( - title: String(localized: .localizable.flagPubliclyTitle), - description: String(localized: .localizable.flagPubliclyDescription), + title: String(localized: "flagPubliclyTitle"), + description: String(localized: "flagPubliclyDescription"), info: nil, category: .privacy(.publicly) ) @@ -56,17 +56,17 @@ struct FlagOption: Identifiable, Equatable { /// `FlagOption` instances representing different categories of how a user can be flagged. static let flagUserSendOptions: [FlagOption] = [ FlagOption( - title: String(localized: .localizable.flagSendToNosTitle), - description: String(localized: .localizable.flagSendToNosDescription), + title: String(localized: "flagSendToNosTitle"), + description: String(localized: "flagSendToNosDescription"), info: { selectedTitle in guard let selectedTitle = selectedTitle else { return nil } - return String(localized: .localizable.flagUserSendToNosInfo(selectedTitle)) + return String.localizedStringWithFormat(String(localized: "flagUserSendToNosInfo"), selectedTitle) }, category: .privacy(.sendToNos) ), FlagOption( - title: String(localized: .localizable.flagPubliclyTitle), - description: String(localized: .localizable.flagPubliclyDescription), + title: String(localized: "flagPubliclyTitle"), + description: String(localized: "flagPubliclyDescription"), info: nil, category: .privacy(.publicly) ) @@ -75,14 +75,14 @@ struct FlagOption: Identifiable, Equatable { /// `FlagOption` instances representing different categories of the visibility of a flagged user. static let flagUserVisibilityOptions: [FlagOption] = [ FlagOption( - title: String(localized: .localizable.flagUserMuteTitle), - description: String(localized: .localizable.flagUserMuteDescription), + title: String(localized: "flagUserMuteTitle"), + description: String(localized: "flagUserMuteDescription"), info: nil, category: .visibility(.mute) ), FlagOption( - title: String(localized: .localizable.flagUserDontMuteTitle), - description: String(localized: .localizable.flagUserDontMuteDescription), + title: String(localized: "flagUserDontMuteTitle"), + description: String(localized: "flagUserDontMuteDescription"), info: nil, category: .visibility(.dontMute) ) @@ -95,43 +95,43 @@ struct FlagOption: Identifiable, Equatable { extension FlagOption { static let spam = FlagOption( - title: String(localized: .localizable.flagContentSpamTitle), + title: String(localized: "flagContentSpamTitle"), description: nil, info: nil, category: .report(ReportCategory.spam) ) static let harassment = FlagOption( - title: String(localized: .localizable.flagContentHarassmentTitle), - description: String(localized: .localizable.flagContentHarassmentDescription), + title: String(localized: "flagContentHarassmentTitle"), + description: String(localized: "flagContentHarassmentDescription"), info: nil, category: .report(ReportCategory.harassment) ) static let nsfw = FlagOption( title: "NSFW", - description: String(localized: .localizable.flagContentNudityDescription), + description: String(localized: "flagContentNudityDescription"), info: nil, category: .report(ReportCategory.nsfw) ) static let illegal = FlagOption( - title: String(localized: .localizable.flagContentIllegalTitle), - description: String(localized: .localizable.flagContentIllegalDescription), + title: String(localized: "flagContentIllegalTitle"), + description: String(localized: "flagContentIllegalDescription"), info: nil, category: .report(ReportCategory.illegal) ) static let impersonation = FlagOption( - title: String(localized: .localizable.flagUserImpersonationTitle), - description: String(localized: .localizable.flagUserImpersonationDescription), + title: String(localized: "flagUserImpersonationTitle"), + description: String(localized: "flagUserImpersonationDescription"), info: nil, category: .report(ReportCategory.other) ) static let other = FlagOption( - title: String(localized: .localizable.flagContentOtherTitle), - description: String(localized: .localizable.flagContentOtherDescription), + title: String(localized: "flagContentOtherTitle"), + description: String(localized: "flagContentOtherDescription"), info: nil, category: .report(ReportCategory.other) ) diff --git a/Nos/Models/ReportCategory.swift b/Nos/Models/ReportCategory.swift index deec8e163..fc68b4d87 100644 --- a/Nos/Models/ReportCategory.swift +++ b/Nos/Models/ReportCategory.swift @@ -4,11 +4,7 @@ import Foundation /// Vocabulary from [NIP-56] and [NIP-69](https://github.com/nostr-protocol/nips/pull/457). struct ReportCategory: Identifiable, Equatable { /// A localized human readable description of the reason/category. Should be short enough to fit in an action menu. - var displayName: String { - String(localized: name) - } - - var name: LocalizedStringResource + var displayName: String /// The machine-readable code corresponding to this category. var code: String @@ -47,31 +43,31 @@ enum NIP56Code: String { extension ReportCategory { static let coarseLanguage = ReportCategory( - name: .moderation.coarseLanguage, + displayName: String(localized: "coarseLanguage", table: "Moderation"), code: "CL", nip56Code: .profanity ) static let likelyToCauseHarm = ReportCategory( - name: .moderation.likelyToCauseHarm, + displayName: String(localized: "likelyToCauseHarm", table: "Moderation"), code: "HC", nip56Code: .other ) static let harassment = ReportCategory( - name: .moderation.harassment, + displayName: String(localized: "harassment", table: "Moderation"), code: "IL-har", nip56Code: .profanity ) static let intoleranceAndHate = ReportCategory( - name: .moderation.intoleranceAndHate, + displayName: String(localized: "intoleranceAndHate", table: "Moderation"), code: "IH", nip56Code: .other ) static let illegal = ReportCategory( - name: .moderation.illegal, + displayName: String(localized: "illegal", table: "Moderation"), code: "IL", nip56Code: .illegal, subCategories: [ @@ -87,19 +83,19 @@ extension ReportCategory { ) static let nsfw = ReportCategory( - name: .moderation.nsfw, + displayName: String(localized: "nsfw", table: "Moderation"), code: "NW", nip56Code: .nudity ) static let impersonation = ReportCategory( - name: .moderation.impersonation, + displayName: String(localized: "impersonation", table: "Moderation"), code: "IM", nip56Code: .impersonation ) static let nudity = ReportCategory( - name: .moderation.nudityAndSex, + displayName: String(localized: "nudityAndSex", table: "Moderation"), code: "NS", nip56Code: .nudity, subCategories: [ @@ -110,7 +106,7 @@ extension ReportCategory { ) static let pornography = ReportCategory( - name: .moderation.pornography, + displayName: String(localized: "pornography", table: "Moderation"), code: "PN", nip56Code: .nudity, subCategories: [ @@ -123,10 +119,14 @@ extension ReportCategory { ] ) - static let spam = ReportCategory(name: .moderation.spam, code: "SP", nip56Code: .spam) + static let spam = ReportCategory( + displayName: String(localized: "spam", table: "Moderation"), + code: "SP", + nip56Code: .spam + ) static let violence = ReportCategory( - name: .moderation.violence, + displayName: String(localized: "violence", table: "Moderation"), code: "VI", nip56Code: .other, subCategories: [ @@ -135,7 +135,11 @@ extension ReportCategory { ] ) - static let other = ReportCategory(name: .moderation.other, code: "NA", nip56Code: .other) + static let other = ReportCategory( + displayName: String(localized: "other", table: "Moderation"), + code: "NA", + nip56Code: .other + ) } extension ReportCategory { @@ -174,115 +178,115 @@ extension ReportCategory { enum ReportSubCategoryType { static let copyrightViolation = ReportCategory( - name: .moderation.copyrightViolation, + displayName: String(localized: "copyrightViolation", table: "Moderation"), code: "IL-cop", nip56Code: .illegal ) static let childSexualAbuse = ReportCategory( - name: .moderation.childSexualAbuse, + displayName: String(localized: "childSexualAbuse", table: "Moderation"), code: "IL-csa", nip56Code: .illegal ) static let drugRelatedCrime = ReportCategory( - name: .moderation.drugRelatedCrime, + displayName: String(localized: "drugRelatedCrime", table: "Moderation"), code: "IL-drg", nip56Code: .illegal ) static let fraudAndScams = ReportCategory( - name: .moderation.fraudAndScams, + displayName: String(localized: "fraudAndScams", table: "Moderation"), code: "IL-frd", nip56Code: .illegal ) static let harassmentStalkingOrDoxxing = ReportCategory( - name: .moderation.harassmentStalkingOrDoxxing, + displayName: String(localized: "harassmentStalkingOrDoxxing", table: "Moderation"), code: "IL-har", nip56Code: .illegal ) static let prostitution = ReportCategory( - name: .moderation.prostitution, + displayName: String(localized: "prostitution", table: "Moderation"), code: "IL-swk", nip56Code: .illegal ) static let impersonation = ReportCategory( - name: .moderation.impersonation, + displayName: String(localized: "impersonation", table: "Moderation"), code: "IL-idt", nip56Code: .illegal ) static let malware = ReportCategory( - name: .moderation.malware, + displayName: String(localized: "malware", table: "Moderation"), code: "IL-mal", nip56Code: .illegal ) static let casualNudity = ReportCategory( - name: .moderation.casualNudity, + displayName: String(localized: "casualNudity", table: "Moderation"), code: "NS-nud", nip56Code: .nudity ) static let erotica = ReportCategory( - name: .moderation.erotica, + displayName: String(localized: "erotica", table: "Moderation"), code: "NS-ero", nip56Code: .nudity ) // swiftlint:disable:next identifier_name static let sex = ReportCategory( - name: .moderation.sex, + displayName: String(localized: "sex", table: "Moderation"), code: "NS-sex", nip56Code: .nudity ) static let heterosexualPorn = ReportCategory( - name: .moderation.heterosexualPorn, + displayName: String(localized: "heterosexualPorn", table: "Moderation"), code: "PN-het", nip56Code: .nudity ) static let gayMalePorn = ReportCategory( - name: .moderation.gayMalePorn, + displayName: String(localized: "gayMalePorn", table: "Moderation"), code: "PN-gay", nip56Code: .nudity ) static let lesbianPorn = ReportCategory( - name: .moderation.lesbianPorn, + displayName: String(localized: "lesbianPorn", table: "Moderation"), code: "PN-les", nip56Code: .nudity ) static let bisexualPorn = ReportCategory( - name: .moderation.bisexualPorn, + displayName: String(localized: "bisexualPorn", table: "Moderation"), code: "PN-bis", nip56Code: .nudity ) static let transsexualPorn = ReportCategory( - name: .moderation.transsexualPorn, + displayName: String(localized: "transsexualPorn", table: "Moderation"), code: "PN-trn", nip56Code: .nudity ) static let genderFluidNonBinaryPorn = ReportCategory( - name: .moderation.genderFluidNonBinaryPorn, + displayName: String(localized: "genderFluidNonBinaryPorn", table: "Moderation"), code: "PN-fnb", nip56Code: .nudity ) static let violenceTowardsAHumanBeing = ReportCategory( - name: .moderation.violenceTowardsAHumanBeing, + displayName: String(localized: "violenceTowardsAHumanBeing", table: "Moderation"), code: "VI-hum", nip56Code: .other ) static let violenceTowardsASentientAnimal = ReportCategory( - name: .moderation.violenceTowardsASentientAnimal, + displayName: String(localized: "violenceTowardsASentientAnimal", table: "Moderation"), code: "VI-ani", nip56Code: .other ) diff --git a/Nos/Service/NamesAPI.swift b/Nos/Service/NamesAPI.swift index 77d1a001b..f4653b912 100644 --- a/Nos/Service/NamesAPI.swift +++ b/Nos/Service/NamesAPI.swift @@ -40,7 +40,7 @@ class NamesAPI { case .unexpected: return "Unexpected" case .usernameNotAvailable: - return String(localized: .localizable.usernameAlreadyClaimed) + return String(localized: "usernameAlreadyClaimed") } } } diff --git a/Nos/Service/ReportPublisher.swift b/Nos/Service/ReportPublisher.swift index 478609284..09a430bb5 100644 --- a/Nos/Service/ReportPublisher.swift +++ b/Nos/Service/ReportPublisher.swift @@ -84,7 +84,7 @@ class ReportPublisher { pubKey: pubKey, kind: .report, tags: [], - content: String(localized: .localizable.reportEventContent(category.displayName)) + content: String.localizedStringWithFormat(String(localized: "reportEventContent"), category.displayName) ) let nip56Reason = category.nip56Code.rawValue diff --git a/Nos/Views/AppView.swift b/Nos/Views/AppView.swift index fcdd2d0a6..b57e5bf20 100644 --- a/Nos/Views/AppView.swift +++ b/Nos/Views/AppView.swift @@ -54,7 +54,7 @@ struct AppView: View { HomeTab(user: author) .tabItem { VStack { - let text = Text(.localizable.homeFeed) + let text = Text("homeFeed") if $router.selectedTab.wrappedValue == .home { Image.tabIconHomeSelected text @@ -83,7 +83,7 @@ struct AppView: View { DiscoverTab() .tabItem { VStack { - let text = Text(.localizable.discover) + let text = Text("discover") if $router.selectedTab.wrappedValue == .discover { Image.tabIconEveryoneSelected text.foregroundColor(.primaryTxt) @@ -101,7 +101,7 @@ struct AppView: View { .tabItem { VStack { Image.newPostButton - Text(.localizable.post) + Text("post") } } .tag(AppDestination.noteComposer(nil)) @@ -109,7 +109,7 @@ struct AppView: View { NotificationsView(user: currentUser.author) .tabItem { VStack { - let text = Text(.localizable.notifications) + let text = Text("notifications") if $router.selectedTab.wrappedValue == .notifications { Image.tabIconNotificationsSelected text.foregroundColor(.primaryTxt) @@ -128,7 +128,7 @@ struct AppView: View { ProfileTab(author: author, path: $router.profilePath) .tabItem { VStack { - let text = Text(.localizable.profileTitle) + let text = Text("profileTitle") if $router.selectedTab.wrappedValue == .profile { Image.tabProfileSelected text.foregroundColor(.primaryTxt) diff --git a/Nos/Views/Components/ActionBanner.swift b/Nos/Views/Components/ActionBanner.swift index aa5718298..cbf3a076b 100644 --- a/Nos/Views/Components/ActionBanner.swift +++ b/Nos/Views/Components/ActionBanner.swift @@ -3,9 +3,9 @@ import SwiftUI /// A large colorful banner with a message and action button. struct ActionBanner: View { - var messageText: LocalizedStringResource + var messageText: LocalizedStringKey var messageImage: Image? - var buttonText: LocalizedStringResource + var buttonText: LocalizedStringKey var buttonImage: Image? var shouldButtonFillHorizontalSpace: Bool var action: (() -> Void)? @@ -37,7 +37,7 @@ struct ActionBanner: View { } HStack { ActionButton( - title: buttonText, + buttonText, font: .clarity(.semibold, textStyle: .subheadline), image: buttonImage, textColor: .actionBannerButtonTxt, @@ -101,9 +101,9 @@ struct ActionBanner_Previews: PreviewProvider { static var previews: some View { VStack { ActionBanner( - messageText: .localizable.completeProfileMessage, + messageText: "completeProfileMessage", messageImage: Image.atSymbol, - buttonText: .localizable.completeProfileButton, + buttonText: "completeProfileButton", shouldButtonFillHorizontalSpace: true ) .padding(20) diff --git a/Nos/Views/Components/Author/AuthorCard.swift b/Nos/Views/Components/Author/AuthorCard.swift index 992956ce7..22c1c94ae 100644 --- a/Nos/Views/Components/Author/AuthorCard.swift +++ b/Nos/Views/Components/Author/AuthorCard.swift @@ -55,7 +55,7 @@ struct AuthorCard: View { Spacer() if author.muted { - Text(.localizable.muted) + Text("muted") .font(.subheadline) .foregroundColor(Color.secondaryTxt) } diff --git a/Nos/Views/Components/Author/AuthorLabel.swift b/Nos/Views/Components/Author/AuthorLabel.swift index 27a9aa145..001f23158 100644 --- a/Nos/Views/Components/Author/AuthorLabel.swift +++ b/Nos/Views/Components/Author/AuthorLabel.swift @@ -10,7 +10,7 @@ struct AuthorLabel: View { authorName.foregroundColor = .primaryTxt authorName.font = .clarity(.semibold) if let note { - let postedOrRepliedString = String(localized: note.isReply ? .reply.replied : .reply.posted) + let postedOrRepliedString = String(localized: note.isReply ? "replied" : "posted", table: "Reply") var postedOrReplied = AttributedString(" " + postedOrRepliedString) postedOrReplied.foregroundColor = .secondaryTxt diff --git a/Nos/Views/Components/Author/AuthorListView.swift b/Nos/Views/Components/Author/AuthorListView.swift index a4734c4c3..dbd389e2c 100644 --- a/Nos/Views/Components/Author/AuthorListView.swift +++ b/Nos/Views/Components/Author/AuthorListView.swift @@ -33,7 +33,7 @@ struct AuthorListView: View { } } .background(Color.appBg) - .nosNavigationBar(title: .localizable.mention) + .nosNavigationBar("mention") .onAppear { isSearching = true } @@ -43,7 +43,7 @@ struct AuthorListView: View { Button(action: { isPresented = false }, label: { - Text(.localizable.cancel) + Text("cancel") .foregroundColor(.primaryTxt) }) } diff --git a/Nos/Views/Components/Author/AuthorObservationView.swift b/Nos/Views/Components/Author/AuthorObservationView.swift index 5fe5e553b..80d8afd44 100644 --- a/Nos/Views/Components/Author/AuthorObservationView.swift +++ b/Nos/Views/Components/Author/AuthorObservationView.swift @@ -23,7 +23,7 @@ struct AuthorObservationView: View { if let author = authors.first { contentBuilder(author) } else { - Text(.localizable.error) + Text("error") } } } diff --git a/Nos/Views/Components/Author/NIP05View.swift b/Nos/Views/Components/Author/NIP05View.swift index 7cb42c7d3..e636dfff0 100644 --- a/Nos/Views/Components/Author/NIP05View.swift +++ b/Nos/Views/Components/Author/NIP05View.swift @@ -27,7 +27,7 @@ struct NIP05View: View { Button { UIPasteboard.general.string = nip05 } label: { - Text(.localizable.copy) + Text("copy") } } preview: { Text(nip05) diff --git a/Nos/Views/Components/BioView.swift b/Nos/Views/Components/BioView.swift index 09dc55fd7..1caff8689 100644 --- a/Nos/Views/Components/BioView.swift +++ b/Nos/Views/Components/BioView.swift @@ -89,7 +89,8 @@ struct BioView: View { } if shouldShowReadMore { ZStack(alignment: .center) { - Text(String(localized: .localizable.readMore).uppercased()) + Text("readMore") + .textCase(.uppercase) .font(.clarityRegular(.caption)) .foregroundColor(.secondaryTxt) .padding(EdgeInsets(top: 4, leading: 6, bottom: 4, trailing: 6)) diff --git a/Nos/Views/Components/Button/ActionButton.swift b/Nos/Views/Components/Button/ActionButton.swift index 2dac4c741..3cf8ce9d2 100644 --- a/Nos/Views/Components/Button/ActionButton.swift +++ b/Nos/Views/Components/Button/ActionButton.swift @@ -8,21 +8,14 @@ struct ActionButton: View { case right } - var title: LocalizedStringResource + let titleText: Text var font: Font = .clarity(.bold) var image: Image? var imageAlignment: ImageAlignment = .left var padding = EdgeInsets(top: 8, leading: 13, bottom: 8, trailing: 13) var textColor = Color.white var depthEffectColor = Color.actionPrimaryDepthEffect - var backgroundGradient = LinearGradient( - colors: [ - Color.actionPrimaryGradientTop, - Color.actionPrimaryGradientBottom - ], - startPoint: .bottomLeading, - endPoint: .topTrailing - ) + var backgroundGradient = LinearGradient.diagonalAccent2 var textShadow = true /// A flag used to fill the available horizontal space (centering the /// contents) or to fit the horizontal space to the contents of the action @@ -31,6 +24,62 @@ struct ActionButton: View { var action: (() async -> Void)? @State var disabled = false + init( + title: String, + font: Font = .clarity(.bold), + image: Image? = nil, + imageAlignment: ImageAlignment = .left, + padding: EdgeInsets = EdgeInsets(top: 8, leading: 13, bottom: 8, trailing: 13), + textColor: SwiftUI.Color = Color.white, + depthEffectColor: Color = Color.actionPrimaryDepthEffect, + backgroundGradient: LinearGradient = LinearGradient.diagonalAccent2, + textShadow: Bool = true, + shouldFillHorizontalSpace: Bool = false, + action: (() async -> Void)? = nil, + disabled: Bool = false + ) { + self.titleText = Text(title) + self.font = font + self.image = image + self.imageAlignment = imageAlignment + self.padding = padding + self.textColor = textColor + self.depthEffectColor = depthEffectColor + self.backgroundGradient = backgroundGradient + self.textShadow = textShadow + self.shouldFillHorizontalSpace = shouldFillHorizontalSpace + self.action = action + self.disabled = disabled + } + + init( + _ titleKey: LocalizedStringKey, + font: Font = .clarity(.bold), + image: Image? = nil, + imageAlignment: ImageAlignment = .left, + padding: EdgeInsets = EdgeInsets(top: 8, leading: 13, bottom: 8, trailing: 13), + textColor: Color = Color.white, + depthEffectColor: Color = Color.actionPrimaryDepthEffect, + backgroundGradient: LinearGradient = LinearGradient.diagonalAccent2, + textShadow: Bool = true, + shouldFillHorizontalSpace: Bool = false, + action: (() async -> Void)? = nil, + disabled: Bool = false + ) { + self.titleText = Text(titleKey) + self.font = font + self.image = image + self.imageAlignment = imageAlignment + self.padding = padding + self.textColor = textColor + self.depthEffectColor = depthEffectColor + self.backgroundGradient = backgroundGradient + self.textShadow = textShadow + self.shouldFillHorizontalSpace = shouldFillHorizontalSpace + self.action = action + self.disabled = disabled + } + var body: some View { Button(action: { disabled = true @@ -48,7 +97,7 @@ struct ActionButton: View { if imageAlignment == .left { image } - Text(title) + titleText .font(font) .transition(.opacity) .font(.headline) @@ -77,19 +126,28 @@ struct ActionButton: View { } struct SecondaryActionButton: View { - var title: LocalizedStringResource - var font: Font = .clarity(.bold) - - var image: Image? - var imageAlignment: ActionButton.ImageAlignment = .left - /// A flag used to fill the available horizontal space (centering the + + private let button: ActionButton + + /// Initializes a ``SecondaryActionButton``. + /// - Parameters: + /// - title: The title for the button. + /// - font: The font to use. + /// - image: An image for the button. Optional. + /// - imageAlignment: The side of the button the image should appear on. + /// - shouldFillHorizontalSpace: A flag used to fill the available horizontal space (centering the /// contents) or to fit the horizontal space to the contents of the action /// button. - var shouldFillHorizontalSpace = false - var action: (() async -> Void)? - - var body: some View { - ActionButton( + /// - action: The action to perform when the button is tapped. + init( + title: String, + font: Font = .clarity(.bold), + image: Image? = nil, + imageAlignment: ActionButton.ImageAlignment = .left, + shouldFillHorizontalSpace: Bool = false, + action: (() -> Void)? = nil + ) { + button = ActionButton( title: title, font: font, image: image, @@ -100,11 +158,35 @@ struct SecondaryActionButton: View { action: action ) } + + init( + _ titleKey: LocalizedStringKey, + font: Font = .clarity(.bold), + image: Image? = nil, + imageAlignment: ActionButton.ImageAlignment = .left, + shouldFillHorizontalSpace: Bool = false, + action: (() async -> Void)? = nil + ) { + button = ActionButton( + titleKey, + font: font, + image: image, + imageAlignment: imageAlignment, + depthEffectColor: .actionSecondaryDepthEffect, + backgroundGradient: .verticalAccentSecondary, + shouldFillHorizontalSpace: shouldFillHorizontalSpace, + action: action + ) + } + + var body: some View { + button + } } struct ActionButtonStyle: ButtonStyle { - @SwiftUI.Environment(\.isEnabled) private var isEnabled + @Environment(\.isEnabled) private var isEnabled let cornerRadius: CGFloat = 17 let depthEffectColor: Color @@ -161,13 +243,13 @@ struct ActionButtonStyle: ButtonStyle { struct ActionButton_Previews: PreviewProvider { static var previews: some View { VStack(spacing: 20) { - ActionButton(title: .localizable.done, action: {}) + ActionButton("done") - ActionButton(title: .localizable.done, action: {}) + ActionButton("done") .disabled(true) ActionButton( - title: .localizable.edit, + "edit", font: .clarity(.medium), image: Image.editProfile, textColor: Color.actionBannerButtonTxt, @@ -180,15 +262,16 @@ struct ActionButton_Previews: PreviewProvider { startPoint: .leading, endPoint: .trailing ), - textShadow: false, - action: {} + textShadow: false ) - SecondaryActionButton(title: .localizable.edit, action: {}) + SecondaryActionButton("edit") // Something that should wrap at larger text sizes - SecondaryActionButton(title: .localizable.reportNoteSendToNosConfirmation("harassment"), action: {}) - .disabled(true) + SecondaryActionButton( + title: "The Nos moderation team will analyze the note for harassment content and may publish a report from our own account, concealing your identity." // swiftlint:disable:this line_length + ) + .disabled(true) } } } diff --git a/Nos/Views/Components/Button/BigActionButton.swift b/Nos/Views/Components/Button/BigActionButton.swift index 81b91fe0c..17a82971e 100644 --- a/Nos/Views/Components/Button/BigActionButton.swift +++ b/Nos/Views/Components/Button/BigActionButton.swift @@ -3,11 +3,23 @@ import SwiftUI /// A big bright button that is used as the primary call-to-action on a screen. struct BigActionButton: View { - var title: LocalizedStringResource + var title: LocalizedStringKey var backgroundGradient: LinearGradient = .bigAction var action: () async -> Void @State var disabled = false + init( + _ title: LocalizedStringKey, + backgroundGradient: LinearGradient = .bigAction, + action: @escaping () async -> Void, + disabled: Bool = false + ) { + self.title = title + self.backgroundGradient = backgroundGradient + self.action = action + self.disabled = disabled + } + var body: some View { Button(action: { disabled = true @@ -102,10 +114,10 @@ struct BigActionButtonStyle: ButtonStyle { #Preview { VStack(spacing: 20) { - BigActionButton(title: .localizable.accept, action: {}) + BigActionButton("accept", action: {}) .frame(width: 268) - BigActionButton(title: .localizable.accept, action: {}) + BigActionButton("accept", action: {}) .disabled(true) .frame(width: 268) } diff --git a/Nos/Views/Components/Button/FollowButton.swift b/Nos/Views/Components/Button/FollowButton.swift index a194a840d..e13e9e17e 100644 --- a/Nos/Views/Components/Button/FollowButton.swift +++ b/Nos/Views/Components/Button/FollowButton.swift @@ -27,7 +27,7 @@ struct FollowButton: View { var body: some View { let following = currentUser.isFollowing(author: author) ActionButton( - title: following ? .localizable.unfollow : .localizable.follow, + following ? "unfollow" : "follow", font: .clarity(.bold, textStyle: .subheadline), image: image(for: following), shouldFillHorizontalSpace: shouldFillHorizontalSpace diff --git a/Nos/Views/Components/Button/NewNotesButton.swift b/Nos/Views/Components/Button/NewNotesButton.swift index 7a125e647..d69985df3 100644 --- a/Nos/Views/Components/Button/NewNotesButton.swift +++ b/Nos/Views/Components/Button/NewNotesButton.swift @@ -22,7 +22,7 @@ struct NewNotesButton: View { } else { VStack { SecondaryActionButton( - title: .localizable.newNotesAvailable, + "newNotesAvailable", font: .clarity(.semibold, textStyle: .footnote), action: action ) diff --git a/Nos/Views/Components/Button/RelayPickerToolbarButton.swift b/Nos/Views/Components/Button/RelayPickerToolbarButton.swift index 8ae103a40..dce818b23 100644 --- a/Nos/Views/Components/Button/RelayPickerToolbarButton.swift +++ b/Nos/Views/Components/Button/RelayPickerToolbarButton.swift @@ -4,16 +4,15 @@ struct RelayPickerToolbarButton: ToolbarContent { @Binding var selectedRelay: Relay? @Binding var isPresenting: Bool - var defaultSelection: LocalizedStringResource var action: () -> Void @Environment(\.horizontalSizeClass) private var horizontalSizeClass var title: String { if let selectedRelay { - return selectedRelay.host ?? String(localized: .localizable.error) + return selectedRelay.host ?? String(localized: "error") } else { - return String(localized: defaultSelection) + return String(localized: "allMyRelays") } } @@ -79,22 +78,21 @@ struct RelayPickerToolbarButton_Previews: PreviewProvider { ToolbarItem(placement: .navigationBarLeading) { Button {} label: { - Text(.localizable.cancel) + Text("cancel") .foregroundColor(.secondaryTxt) } } RelayPickerToolbarButton( selectedRelay: selectedRelay, - isPresenting: isPresented, - defaultSelection: .localizable.allMyRelays + isPresenting: isPresented ) {} ToolbarItem(placement: .navigationBarTrailing) { - ActionButton(title: .localizable.post, action: {}) + ActionButton("post") .frame(height: 22) .padding(.bottom, 3) } } - .navigationBarTitle(String(localized: .localizable.discover), displayMode: .inline) + .navigationBarTitle("discover", displayMode: .inline) .toolbarBackground(.visible, for: .navigationBar) .toolbarBackground(Color.cardBgBottom, for: .navigationBar) } diff --git a/Nos/Views/Components/Button/RepostButton.swift b/Nos/Views/Components/Button/RepostButton.swift index 88c41596b..701a492b3 100644 --- a/Nos/Views/Components/Button/RepostButton.swift +++ b/Nos/Views/Components/Button/RepostButton.swift @@ -59,19 +59,19 @@ struct RepostButton: View { .padding(.vertical, 12) } .disabled(tapped) - .confirmationDialog(String(localized: .localizable.repost), isPresented: $shouldConfirmRepost) { - Button(String(localized: .localizable.repost)) { + .confirmationDialog("repost", isPresented: $shouldConfirmRepost) { + Button("repost") { Task { await repostNote() } } - Button(String(localized: .localizable.quote)) { + Button("quote") { showQuotedNoteComposer = true } - Button(String(localized: .localizable.cancel), role: .cancel) { + Button("cancel", role: .cancel) { tapped = false } } - .confirmationDialog(String(localized: .localizable.deleteRepost), isPresented: $shouldConfirmDelete) { - Button(String(localized: .localizable.deleteRepost), role: .destructive) { + .confirmationDialog("deleteRepost", isPresented: $shouldConfirmDelete) { + Button("deleteRepost", role: .destructive) { Task { await deleteReposts() } } } diff --git a/Nos/Views/Components/Event/EventObservationView.swift b/Nos/Views/Components/Event/EventObservationView.swift index f2ea86adc..77b5d5e67 100644 --- a/Nos/Views/Components/Event/EventObservationView.swift +++ b/Nos/Views/Components/Event/EventObservationView.swift @@ -33,7 +33,7 @@ struct EventObservationView: View { if let event = events.first { contentBuilder(event) } else { - Text(.localizable.error) + Text("error") } } } diff --git a/Nos/Views/Components/Event/RawEventView.swift b/Nos/Views/Components/Event/RawEventView.swift index 1873ada55..e17a0198d 100644 --- a/Nos/Views/Components/Event/RawEventView.swift +++ b/Nos/Views/Components/Event/RawEventView.swift @@ -70,12 +70,12 @@ struct RawEventView: View where ViewModel: RawEventViewModel { } } } - .nosNavigationBar(title: .localizable.eventSource) + .nosNavigationBar("eventSource") .disabled(showProgress) .overlay(loadingIndicator) .alert(isPresented: showAlert) { Alert( - title: Text(.localizable.error), + title: Text("error"), message: Text(viewModel.errorMessage ?? "") ) } diff --git a/Nos/Views/Components/Form/NosForm.swift b/Nos/Views/Components/Form/NosForm.swift index 898551d20..a54e077ef 100644 --- a/Nos/Views/Components/Form/NosForm.swift +++ b/Nos/Views/Components/Form/NosForm.swift @@ -25,9 +25,9 @@ struct NosForm: View { struct NosForm_Previews: PreviewProvider { static var previews: some View { NosForm { - NosFormSection(label: .localizable.profilePicture) { + NosFormSection("profilePicture") { WithState(initialValue: "Alice") { text in - NosTextField(label: .localizable.url, text: text) + NosTextField("url", text: text) } } } diff --git a/Nos/Views/Components/Form/NosFormField.swift b/Nos/Views/Components/Form/NosFormField.swift index c33a7241b..89f39dc3d 100644 --- a/Nos/Views/Components/Form/NosFormField.swift +++ b/Nos/Views/Components/Form/NosFormField.swift @@ -4,11 +4,11 @@ import SwiftUINavigation struct NosFormField: View { let control: Control - let label: LocalizedStringResource + let label: LocalizedStringKey @FocusState private var focus: Bool init( - label: LocalizedStringResource, + _ label: LocalizedStringKey, @ViewBuilder builder: () -> Control ) { self.label = label @@ -25,7 +25,7 @@ struct NosFormField: View { } control - .accessibilityLabel(String(localized: label)) + .accessibilityLabel(label) .focused($focus) } .padding(16) @@ -39,9 +39,9 @@ struct NosFormField: View { struct NosFormField_Previews: PreviewProvider { static var previews: some View { NosForm { - NosFormSection(label: .localizable.profileTitle) { + NosFormSection("profileTitle") { WithState(initialValue: "") { text in - NosFormField(label: .localizable.about) { + NosFormField("about") { TextField("", text: text) .textInputAutocapitalization(.none) .foregroundColor(.primaryTxt) diff --git a/Nos/Views/Components/Form/NosFormSection.swift b/Nos/Views/Components/Form/NosFormSection.swift index 8567b2168..0b57ef2c5 100644 --- a/Nos/Views/Components/Form/NosFormSection.swift +++ b/Nos/Views/Components/Form/NosFormSection.swift @@ -3,10 +3,10 @@ import SwiftUINavigation struct NosFormSection: View { - var label: LocalizedStringResource? + var label: LocalizedStringKey? let content: Content - init(label: LocalizedStringResource? = nil, @ViewBuilder builder: () -> Content) { + init(_ label: LocalizedStringKey? = nil, @ViewBuilder builder: () -> Content) { self.label = label self.content = builder() } @@ -52,9 +52,9 @@ struct NosFormSection: View { struct NosFormSection_Previews: PreviewProvider { static var previews: some View { NosForm { - NosFormSection(label: .localizable.profilePicture) { + NosFormSection("profilePicture") { WithState(initialValue: "Alice") { text in - NosTextField(label: .localizable.url, text: text) + NosTextField("url", text: text) } } } diff --git a/Nos/Views/Components/Form/NosTextEditor.swift b/Nos/Views/Components/Form/NosTextEditor.swift index f9778ccef..5098c6a46 100644 --- a/Nos/Views/Components/Form/NosTextEditor.swift +++ b/Nos/Views/Components/Form/NosTextEditor.swift @@ -3,11 +3,16 @@ import SwiftUINavigation struct NosTextEditor: View { - var label: LocalizedStringResource + var label: LocalizedStringKey @Binding var text: String + init(_ label: LocalizedStringKey, text: Binding) { + self.label = label + self._text = text + } + var body: some View { - NosFormField(label: label) { + NosFormField(label) { TextEditor(text: $text) .textInputAutocapitalization(.none) .foregroundColor(.primaryTxt) @@ -20,11 +25,11 @@ struct NosTextEditor: View { struct NosTextEditor_Previews: PreviewProvider { static var previews: some View { NosForm { - NosFormSection(label: .localizable.profilePicture) { + NosFormSection("profilePicture") { WithState(initialValue: "Alice") { text in - NosTextEditor(label: .localizable.bio, text: text) + NosTextEditor("bio", text: text) .frame(maxHeight: 200) - } + } } } } diff --git a/Nos/Views/Components/Form/NosTextField.swift b/Nos/Views/Components/Form/NosTextField.swift index e9b8f0cee..25988ac63 100644 --- a/Nos/Views/Components/Form/NosTextField.swift +++ b/Nos/Views/Components/Form/NosTextField.swift @@ -3,11 +3,16 @@ import SwiftUINavigation struct NosTextField: View { - var label: LocalizedStringResource + var label: LocalizedStringKey @Binding var text: String + init(_ label: LocalizedStringKey, text: Binding) { + self.label = label + self._text = text + } + var body: some View { - NosFormField(label: label) { + NosFormField(label) { TextField("", text: $text) .textInputAutocapitalization(.none) .foregroundColor(.primaryTxt) @@ -19,10 +24,10 @@ struct NosTextField: View { struct NosTextField_Previews: PreviewProvider { static var previews: some View { NosForm { - NosFormSection(label: .localizable.profilePicture) { + NosFormSection("profilePicture") { WithState(initialValue: "Alice") { text in - NosTextField(label: .localizable.url, text: text) - } + NosTextField("url", text: text) + } } } } diff --git a/Nos/Views/Components/FullscreenProgressView.swift b/Nos/Views/Components/FullscreenProgressView.swift index bbb2af6c0..593d56fac 100644 --- a/Nos/Views/Components/FullscreenProgressView.swift +++ b/Nos/Views/Components/FullscreenProgressView.swift @@ -45,6 +45,6 @@ struct FullscreenProgressView: View { #Preview("Long text") { FullscreenProgressView( isPresented: .constant(true), - text: String(localized: .localizable.notFindingResults) + text: String(localized: "notFindingResults") ) } diff --git a/Nos/Views/Components/KnownFollowersView.swift b/Nos/Views/Components/KnownFollowersView.swift index 1804b8cf0..b10a9f778 100644 --- a/Nos/Views/Components/KnownFollowersView.swift +++ b/Nos/Views/Components/KnownFollowersView.swift @@ -25,7 +25,7 @@ struct KnownFollowersView: View { /// The text that will be displayed alongside the avatars listing some of the displayedAuthor's names var followText: Text { - let stringResource: LocalizedStringResource + let followString: String let authors = self.displayedAuthors switch authors.count { case 0: @@ -34,24 +34,24 @@ struct KnownFollowersView: View { guard let name = authors[safe: 0]?.safeName else { return Text("") } - stringResource = LocalizedStringResource.localizable.followedByOne(name) + followString = String.localizedStringWithFormat(String(localized: "followedByOne"), name) case 2: guard let firstName = authors[safe: 0]?.safeName, let secondName = authors[safe: 1]?.safeName else { return Text("") } - stringResource = LocalizedStringResource.localizable.followedByTwo(firstName, secondName) + followString = String.localizedStringWithFormat(String(localized: "followedByTwo"), firstName, secondName) default: guard let firstName = authors[safe: 0]?.safeName, let secondName = authors[safe: 1]?.safeName else { return Text("") } - stringResource = LocalizedStringResource.localizable.followedByTwoAndMore( - firstName, secondName, knownFollowers.count - 2 + followString = String.localizedStringWithFormat( + String(localized: "followedByTwoAndMore"), firstName, secondName, knownFollowers.count - 2 ) } - let attributedString = AttributedString(localized: stringResource) + let attributedString = (try? AttributedString(markdown: followString)) ?? AttributedString(followString) .replacingAttributes( AttributeContainer( [.inlinePresentationIntent: InlinePresentationIntent.stronglyEmphasized.rawValue] diff --git a/Nos/Views/Components/Media/ImageButton.swift b/Nos/Views/Components/Media/ImageButton.swift index 202b63463..6537b7827 100644 --- a/Nos/Views/Components/Media/ImageButton.swift +++ b/Nos/Views/Components/Media/ImageButton.swift @@ -59,7 +59,7 @@ struct ImageButton: View { ZStack { Color.clear - Text(.localizable.gifButton) + Text("gifButton") .font(.title) .foregroundStyle(Color.primaryTxt) .padding() diff --git a/Nos/Views/Components/NosNavigationBar.swift b/Nos/Views/Components/NosNavigationBar.swift index fb37ffa01..48b4f222a 100644 --- a/Nos/Views/Components/NosNavigationBar.swift +++ b/Nos/Views/Components/NosNavigationBar.swift @@ -1,9 +1,34 @@ import SwiftUI -struct NosNavigationBarModifier: ViewModifier { +fileprivate struct NosNavigationBarModifier: ViewModifier { - var title: AttributedString + let titleKey: LocalizedStringKey + + init(_ titleKey: LocalizedStringKey) { + self.titleKey = titleKey + } + func body(content: Content) -> some View { + content + .navigationBarTitle(titleKey, displayMode: .inline) + .toolbar { + ToolbarItem(placement: .principal) { + Text(titleKey) + .font(.title3) + .fontWeight(.bold) + .foregroundColor(.primaryTxt) + .tint(.primaryTxt) + .allowsHitTesting(false) + } + } + .toolbarBackground(.visible, for: .navigationBar) + .toolbarBackground(Color.cardBgBottom, for: .navigationBar) + } +} + +fileprivate struct AttributedNavigationBarModifier: ViewModifier { + let title: AttributedString + func body(content: Content) -> some View { content .navigationBarTitle(String(title.characters), displayMode: .inline) @@ -23,11 +48,11 @@ struct NosNavigationBarModifier: ViewModifier { } extension View { - func nosNavigationBar(title: LocalizedStringResource) -> some View { - self.modifier(NosNavigationBarModifier(title: AttributedString(localized: title))) + func nosNavigationBar(_ title: LocalizedStringKey) -> some View { + self.modifier(NosNavigationBarModifier(title)) } func nosNavigationBar(title: AttributedString) -> some View { - self.modifier(NosNavigationBarModifier(title: title)) + self.modifier(AttributedNavigationBarModifier(title: title)) } } @@ -40,7 +65,7 @@ extension View { } .frame(maxWidth: .infinity) .background(Color.appBg) - .nosNavigationBar(title: .localizable.homeFeed) + .nosNavigationBar("homeFeed") } } @@ -53,6 +78,6 @@ extension View { } .frame(maxWidth: .infinity) .background(Color.appBg) - .nosNavigationBar(title: LocalizedStringResource(stringLiteral: "me@nos.social")) + .nosNavigationBar(LocalizedStringKey(stringLiteral: "me@nos.social")) } } diff --git a/Nos/Views/Components/NosToggle.swift b/Nos/Views/Components/NosToggle.swift index 6bb4d05e5..71c1b5c9c 100644 --- a/Nos/Views/Components/NosToggle.swift +++ b/Nos/Views/Components/NosToggle.swift @@ -1,13 +1,20 @@ import SwiftUI + /// A toggle with the tint color set to green. struct NosToggle: View { - @Binding var isOn: Bool /// A string that shows up beside the toggle. Optional. - var labelText: LocalizedStringResource? + var labelText: LocalizedStringKey? + + @Binding var isOn: Bool + init(_ labelText: LocalizedStringKey? = nil, isOn: Binding) { + self.labelText = labelText + self._isOn = isOn + } + var body: some View { Toggle(isOn: $isOn) { - if let labelText = labelText { + if let labelText { Text(labelText) .foregroundColor(.primaryTxt) } @@ -20,7 +27,7 @@ struct NosToggle: View { @State var isOn = true return NosToggle( - isOn: $isOn, - labelText: .localizable.useReportsFromFollows + "useReportsFromFollows", + isOn: $isOn ) } diff --git a/Nos/Views/Components/NoteTextEditor.swift b/Nos/Views/Components/NoteTextEditor.swift index 1469250df..2d3bb34e0 100644 --- a/Nos/Views/Components/NoteTextEditor.swift +++ b/Nos/Views/Components/NoteTextEditor.swift @@ -10,12 +10,9 @@ struct NoteTextEditor: View { /// The smallest size of EditableNoteText var minHeight: CGFloat - var placeholder: LocalizedStringResource - - init(controller: Binding, minHeight: CGFloat, placeholder: LocalizedStringResource) { + init(controller: Binding, minHeight: CGFloat) { self._controller = controller self.minHeight = minHeight - self.placeholder = placeholder } var body: some View { @@ -45,13 +42,11 @@ struct NoteTextEditor: View { var previewData = PreviewData() @State var controller = NoteEditorController() - let placeholder: LocalizedStringResource = .localizable.newNotePlaceholder return NavigationStack { NoteTextEditor( controller: $controller, - minHeight: 500, - placeholder: placeholder + minHeight: 500 ) Spacer() } diff --git a/Nos/Views/Components/RelayPicker.swift b/Nos/Views/Components/RelayPicker.swift index 40c06be9e..f24b7e413 100644 --- a/Nos/Views/Components/RelayPicker.swift +++ b/Nos/Views/Components/RelayPicker.swift @@ -88,9 +88,9 @@ struct RelayPickerRow: View { var title: String { if let relay { - return relay.host ?? String(localized: .localizable.error) + return relay.host ?? String(localized: "error") } else { - return defaultSelection ?? String(localized: .localizable.error) + return defaultSelection ?? String(localized: "error") } } @@ -161,7 +161,7 @@ struct RelayPickerRow: View { return RelayPicker( selectedRelay: $selectedRelay, - defaultSelection: String(localized: .localizable.allMyRelays), + defaultSelection: String(localized: "allMyRelays"), author: previewData.alice, isPresented: .constant(true) ) @@ -187,7 +187,7 @@ struct RelayPickerRow: View { return RelayPicker( selectedRelay: $selectedRelay, - defaultSelection: String(localized: .localizable.allMyRelays), + defaultSelection: String(localized: "allMyRelays"), author: previewData.alice, isPresented: .constant(true) ) diff --git a/Nos/Views/Components/RepliesLabel.swift b/Nos/Views/Components/RepliesLabel.swift index fe34cea60..330ab50fa 100644 --- a/Nos/Views/Components/RepliesLabel.swift +++ b/Nos/Views/Components/RepliesLabel.swift @@ -64,17 +64,17 @@ struct RepliesLabel: View { case .discussion: if avatars.isEmpty { return AttributedString( - String(localized: .reply.joinTheDiscussion), + String(localized: "joinTheDiscussion", table: "Reply"), attributes: AttributeContainer( [NSAttributedString.Key.foregroundColor: UIColor.primaryTxt] ) ) } else { - return AttributedString(String(localized: .reply.inDiscussion)) + return AttributedString(localized: "inDiscussion", table: "Reply") } case .count: let count = replies.count - let string = String(localized: .reply.replies(count)) + let string = String.localizedStringWithFormat(String(localized: "replies", table: "Reply"), count) do { var attributed = try AttributedString(markdown: string) if let range = attributed.range(of: "\(count)") { diff --git a/Nos/Views/Components/SearchBar.swift b/Nos/Views/Components/SearchBar.swift index 276ec69e3..37d0245ac 100644 --- a/Nos/Views/Components/SearchBar.swift +++ b/Nos/Views/Components/SearchBar.swift @@ -30,7 +30,7 @@ struct SearchBar: View { text = "" // Clear the search text isSearching.wrappedValue = false // Remove focus from the search bar }, label: { - Text(.localizable.clear) + Text("clear") .foregroundLinearGradient(.horizontalAccent) }) .transition(.move(edge: .trailing)) diff --git a/Nos/Views/Components/WarningView.swift b/Nos/Views/Components/WarningView.swift index 26ce33fcc..408750076 100644 --- a/Nos/Views/Components/WarningView.swift +++ b/Nos/Views/Components/WarningView.swift @@ -45,20 +45,20 @@ struct OutOfNetworkView: View { Spacer() // pushes content to the center if self.isOverlayHelpTextBoxShown { - Text(.localizable.outsideNetworkExplanation) + Text("outsideNetworkExplanation") .font(.body) .foregroundColor(.primaryTxt) .padding(.horizontal, 24) .fixedSize(horizontal: false, vertical: true) } else { - Text(.localizable.outsideNetwork) + Text("outsideNetwork") .font(.body) .foregroundColor(.primaryTxt) .padding(.horizontal, 24) .fixedSize(horizontal: false, vertical: true) } - SecondaryActionButton(title: .localizable.viewThisPostAnyway) { + SecondaryActionButton("viewThisPostAnyway") { withAnimation { controller.userHidWarning = true } @@ -104,7 +104,7 @@ struct OverlayContentReportView: View { // TextBox or Image based on isTextBoxShown if self.isOverlayHelpTextBoxShown { - Text(.localizable.contentWarningExplanation) + Text("contentWarningExplanation") .font(.body) .foregroundColor(.secondaryTxt) .padding(.horizontal, 24) @@ -123,7 +123,7 @@ struct OverlayContentReportView: View { ContentWarningMessage(reports: controller.authorReports, type: .author) } } - SecondaryActionButton(title: .localizable.viewThisPostAnyway) { + SecondaryActionButton("viewThisPostAnyway") { withAnimation { controller.userHidWarning = true } diff --git a/Nos/Views/Components/Wizard/WizardSheetBadgeText.swift b/Nos/Views/Components/Wizard/WizardSheetBadgeText.swift index 38be6bed3..2ffceb449 100644 --- a/Nos/Views/Components/Wizard/WizardSheetBadgeText.swift +++ b/Nos/Views/Components/Wizard/WizardSheetBadgeText.swift @@ -6,14 +6,15 @@ import SwiftUI /// This Text was implemented to be re-used in the wizards that set-up and delete usernames in EditProfile screen. struct WizardSheetBadgeText: View { - private var localizedStringResource: LocalizedStringResource + private var localizedStringKey: LocalizedStringKey - init(_ localizedStringResource: LocalizedStringResource) { - self.localizedStringResource = localizedStringResource + init(_ localizedStringKey: LocalizedStringKey) { + self.localizedStringKey = localizedStringKey } var body: some View { - Text(String(localized: localizedStringResource).uppercased()) + Text(localizedStringKey) + .textCase(.uppercase) .padding(.horizontal, 6) .padding(.vertical, 5) .font(.clarity(.bold, textStyle: .footnote)) @@ -26,5 +27,5 @@ struct WizardSheetBadgeText: View { } #Preview { - WizardSheetBadgeText(LocalizedStringResource(stringLiteral: "Hello")) + WizardSheetBadgeText("Hello") } diff --git a/Nos/Views/Components/Wizard/WizardSheetDescriptionText.swift b/Nos/Views/Components/Wizard/WizardSheetDescriptionText.swift index 6a7bce00b..4ba952345 100644 --- a/Nos/Views/Components/Wizard/WizardSheetDescriptionText.swift +++ b/Nos/Views/Components/Wizard/WizardSheetDescriptionText.swift @@ -39,11 +39,11 @@ struct WizardSheetDescriptionText: View { } init( - markdown localizedStringResource: LocalizedStringResource, + markdown: AttributedString, tint: Color = .primaryTxt ) { self.init( - AttributedString(localized: localizedStringResource), + markdown, tint: tint ) } @@ -60,6 +60,6 @@ struct WizardSheetDescriptionText: View { VStack(spacing: 10) { WizardSheetDescriptionText(LocalizedStringResource(stringLiteral: "Hello")) WizardSheetDescriptionText(LocalizedStringResource(stringLiteral: "Hello **Martin**")) - WizardSheetDescriptionText(markdown: LocalizedStringResource(stringLiteral: "Hello **Martin**")) + WizardSheetDescriptionText(markdown: AttributedString("Hello **Martin**")) } } diff --git a/Nos/Views/Components/Wizard/WizardSheetTitleText.swift b/Nos/Views/Components/Wizard/WizardSheetTitleText.swift index ec6aafe4b..98cadc053 100644 --- a/Nos/Views/Components/Wizard/WizardSheetTitleText.swift +++ b/Nos/Views/Components/Wizard/WizardSheetTitleText.swift @@ -6,14 +6,14 @@ import SwiftUI /// This View was implemented to be re-used in the wizards that set-up and delete usernames in EditProfile screen. struct WizardSheetTitleText: View { - private var localizedStringResource: LocalizedStringResource + private var localizedStringKey: LocalizedStringKey - init(_ localizedStringResource: LocalizedStringResource) { - self.localizedStringResource = localizedStringResource + init(_ localizedStringKey: LocalizedStringKey) { + self.localizedStringKey = localizedStringKey } var body: some View { - Text(localizedStringResource) + Text(localizedStringKey) .font(.clarityBold(.title)) .foregroundStyle(Color.primaryTxt) } @@ -21,6 +21,6 @@ struct WizardSheetTitleText: View { #Preview { VStack(spacing: 10) { - WizardSheetTitleText(LocalizedStringResource(stringLiteral: "Hello")) + WizardSheetTitleText("Hello") } } diff --git a/Nos/Views/Discover/DiscoverContentsView.swift b/Nos/Views/Discover/DiscoverContentsView.swift index 6fe912772..f45f84101 100644 --- a/Nos/Views/Discover/DiscoverContentsView.swift +++ b/Nos/Views/Discover/DiscoverContentsView.swift @@ -44,7 +44,7 @@ struct DiscoverContentsView: View { FullscreenProgressView( isPresented: .constant(true), text: searchController.state == .stillLoading ? - String(localized: .localizable.notFindingResults) : nil + String(localized: "notFindingResults") : nil ) case .results: ScrollView { diff --git a/Nos/Views/Discover/DiscoverTab.swift b/Nos/Views/Discover/DiscoverTab.swift index f7f2f814e..71fa3694b 100644 --- a/Nos/Views/Discover/DiscoverTab.swift +++ b/Nos/Views/Discover/DiscoverTab.swift @@ -47,7 +47,7 @@ struct DiscoverTab: View { .searchable( text: $searchController.query, placement: .toolbar, - prompt: Text(.localizable.searchBar) + prompt: Text("searchBar") ) .autocorrectionDisabled() .onSubmit(of: .search) { @@ -68,7 +68,7 @@ struct DiscoverTab: View { analytics.showedDiscover() } } - .nosNavigationBar(title: .localizable.discover) + .nosNavigationBar("discover") .toolbarBackground(.visible, for: .navigationBar) .toolbarBackground(Color.cardBgBottom, for: .navigationBar) .navigationBarItems(leading: SideMenuButton()) diff --git a/Nos/Views/Discover/FeaturedAuthorCategory.swift b/Nos/Views/Discover/FeaturedAuthorCategory.swift index 30eca9ffc..139a185bd 100644 --- a/Nos/Views/Discover/FeaturedAuthorCategory.swift +++ b/Nos/Views/Discover/FeaturedAuthorCategory.swift @@ -1,4 +1,5 @@ import Foundation +import SwiftUI /// Categories of featured authors on the Discover tab. /// - Note: The order of cases in this enum determines the order in which categories are displayed @@ -17,18 +18,18 @@ enum FeaturedAuthorCategory: CaseIterable { case gaming case sports - var text: LocalizedStringResource { + var text: LocalizedStringKey { switch self { - case .all: LocalizedStringResource.localizable.featuredAuthorCategoryAll - case .new: LocalizedStringResource.localizable.featuredAuthorCategoryNew - case .music: LocalizedStringResource.localizable.featuredAuthorCategoryMusic - case .news: LocalizedStringResource.localizable.featuredAuthorCategoryNews - case .art: LocalizedStringResource.localizable.featuredAuthorCategoryArt - case .activists: LocalizedStringResource.localizable.featuredAuthorCategoryActivists - case .gaming: LocalizedStringResource.localizable.featuredAuthorCategoryGaming - case .sports: LocalizedStringResource.localizable.featuredAuthorCategorySports - case .tech: LocalizedStringResource.localizable.featuredAuthorCategoryTech - case .health: LocalizedStringResource.localizable.featuredAuthorCategoryHealth + case .all: "featuredAuthorCategoryAll" + case .new: "featuredAuthorCategoryNew" + case .music: "featuredAuthorCategoryMusic" + case .news: "featuredAuthorCategoryNews" + case .art: "featuredAuthorCategoryArt" + case .activists: "featuredAuthorCategoryActivists" + case .gaming: "featuredAuthorCategoryGaming" + case .sports: "featuredAuthorCategorySports" + case .tech: "featuredAuthorCategoryTech" + case .health: "featuredAuthorCategoryHealth" } } diff --git a/Nos/Views/Home/HomeFeedView.swift b/Nos/Views/Home/HomeFeedView.swift index fd501a3fa..80d374e1d 100644 --- a/Nos/Views/Home/HomeFeedView.swift +++ b/Nos/Views/Home/HomeFeedView.swift @@ -57,11 +57,11 @@ struct HomeFeedView: View { return filter } - var navigationBarTitle: LocalizedStringResource { + var navigationBarTitle: LocalizedStringKey { if let relayName = selectedRelay?.host { - LocalizedStringResource(stringLiteral: relayName) + LocalizedStringKey(stringLiteral: relayName) } else { - .localizable.accountsIFollow + "accountsIFollow" } } @@ -87,7 +87,7 @@ struct HomeFeedView: View { }, emptyPlaceholder: { VStack { - Text(.localizable.noEvents) + Text("noEvents") .padding() } .frame(minHeight: 300) @@ -110,7 +110,7 @@ struct HomeFeedView: View { if showRelayPicker { RelayPicker( selectedRelay: $selectedRelay, - defaultSelection: String(localized: .localizable.accountsIFollow), + defaultSelection: String(localized: "accountsIFollow"), author: user, isPresented: $showRelayPicker ) @@ -145,13 +145,13 @@ struct HomeFeedView: View { } label: { Image(systemName: "line.3.horizontal.decrease.circle") .foregroundStyle(Color.secondaryTxt) - .accessibilityLabel(Text(.localizable.filter)) + .accessibilityLabel(Text("filter")) } .frame(minWidth: 40, minHeight: 40) } } .padding(.top, 1) - .nosNavigationBar(title: navigationBarTitle) + .nosNavigationBar(navigationBarTitle) .onAppear { if router.selectedTab == .home { isVisible = true diff --git a/Nos/Views/Moderation/ContentFlagView.swift b/Nos/Views/Moderation/ContentFlagView.swift index 964e8750c..e8b2caa29 100644 --- a/Nos/Views/Moderation/ContentFlagView.swift +++ b/Nos/Views/Moderation/ContentFlagView.swift @@ -34,14 +34,14 @@ struct ContentFlagView: View { categoryView } } - .nosNavigationBar(title: .localizable.flagContent) + .nosNavigationBar("flagContent") .toolbar { ToolbarItem(placement: .navigationBarLeading) { Button { dismiss() resetSelections() } label: { - Text(.localizable.cancel) + Text("cancel") .foregroundColor(.primaryTxt) } .opacity(showSuccessView ? 0 : 1) @@ -49,7 +49,7 @@ struct ContentFlagView: View { } ToolbarItem(placement: .navigationBarTrailing) { ActionButton( - title: showSuccessView ? .localizable.done : .localizable.send, + showSuccessView ? "done" : "send", action: { if showSuccessView { dismiss() @@ -84,8 +84,8 @@ struct ContentFlagView: View { previousSelection: .constant(nil), currentSelection: $selectedFlagOptionCategory, options: flagCategories, - title: String(localized: .localizable.flagContentCategoryTitle), - subtitle: String(localized: .localizable.flagContentCategoryDescription) + title: String(localized: "flagContentCategoryTitle"), + subtitle: String(localized: "flagContentCategoryDescription") ) if selectedFlagOptionCategory != nil { @@ -93,7 +93,7 @@ struct ContentFlagView: View { previousSelection: $selectedFlagOptionCategory, currentSelection: $selectedSendOptionCategory, options: FlagOption.flagContentSendOptions, - title: String(localized: .localizable.flagSendTitle), + title: String(localized: "flagSendTitle"), subtitle: nil ) .id(sendSectionID) diff --git a/Nos/Views/Moderation/FlagSuccessView.swift b/Nos/Views/Moderation/FlagSuccessView.swift index ba7d70b81..ad2344b63 100644 --- a/Nos/Views/Moderation/FlagSuccessView.swift +++ b/Nos/Views/Moderation/FlagSuccessView.swift @@ -9,12 +9,12 @@ struct FlagSuccessView: View { .aspectRatio(contentMode: .fit) .frame(height: 116) - Text(String(localized: .localizable.thanksForTag)) + Text("thanksForTag") .foregroundColor(.primaryTxt) .font(.title2) .padding(.horizontal, 25) - Text(String(localized: .localizable.keepOnHelpingUs)) + Text("keepOnHelpingUs") .padding(.horizontal, 25) .foregroundColor(.secondaryTxt) .multilineTextAlignment(.center) diff --git a/Nos/Views/Moderation/UserFlagView.swift b/Nos/Views/Moderation/UserFlagView.swift index d89959245..09eaaa8a5 100644 --- a/Nos/Views/Moderation/UserFlagView.swift +++ b/Nos/Views/Moderation/UserFlagView.swift @@ -58,14 +58,14 @@ struct UserFlagView: View { categoryView } } - .nosNavigationBar(title: .localizable.flagUserTitle) + .nosNavigationBar("flagUserTitle") .toolbar { ToolbarItem(placement: .navigationBarLeading) { Button { dismiss() resetSelections() } label: { - Text(.localizable.cancel) + Text("cancel") .foregroundColor(.primaryTxt) } .opacity(showSuccessView ? 0 : 1) @@ -73,7 +73,7 @@ struct UserFlagView: View { } ToolbarItem(placement: .navigationBarTrailing) { ActionButton( - title: showSuccessView ? .localizable.done : .localizable.send, + showSuccessView ? "done" : "send", action: { if showSuccessView { dismiss() @@ -110,8 +110,8 @@ struct UserFlagView: View { previousSelection: .constant(nil), currentSelection: $selectedFlagOption, options: flagCategories, - title: String(localized: .localizable.flagUserCategoryTitle), - subtitle: String(localized: .localizable.flagUserCategoryDescription) + title: String(localized: "flagUserCategoryTitle"), + subtitle: String(localized: "flagUserCategoryDescription") ) if selectedFlagOption != nil { @@ -119,7 +119,7 @@ struct UserFlagView: View { previousSelection: $selectedFlagOption, currentSelection: $selectedSendOption, options: FlagOption.flagUserSendOptions, - title: String(localized: .localizable.flagSendTitle), + title: String(localized: "flagSendTitle"), subtitle: nil ) .id(sendSectionID) @@ -131,7 +131,7 @@ struct UserFlagView: View { previousSelection: .constant(nil), currentSelection: $selectedVisibilityOption, options: FlagOption.flagUserVisibilityOptions, - title: String(localized: .localizable.flagUserMuteCategoryTitle), + title: String(localized: "flagUserMuteCategoryTitle"), subtitle: nil ) .id(visibilitySectionID) diff --git a/Nos/Views/Modifiers/ReportMenuModifier.swift b/Nos/Views/Modifiers/ReportMenuModifier.swift index 6839a30b9..7b4145bfd 100644 --- a/Nos/Views/Modifiers/ReportMenuModifier.swift +++ b/Nos/Views/Modifiers/ReportMenuModifier.swift @@ -86,17 +86,17 @@ struct ReportMenuModifier: ViewModifier { // ReportCategory menu .confirmationDialog(unwrapping: $confirmationDialogState, action: processUserSelection) .alert( - String(localized: .localizable.confirmFlag), + String(localized: "confirmFlag"), isPresented: $confirmReport, actions: { - Button(String(localized: .localizable.confirm)) { + Button("confirm") { publishReport(userSelection) if let author = reportedObject.author, !author.muted { showMuteDialog = true } } - Button(String(localized: .localizable.cancel), role: .cancel) { + Button("cancel", role: .cancel) { userSelection = nil } }, @@ -107,37 +107,37 @@ struct ReportMenuModifier: ViewModifier { ) // Mute user menu .alert( - String(localized: .localizable.muteUser), + "muteUser", isPresented: $showMuteDialog, actions: { if let author = reportedObject.author { - Button(String(localized: .localizable.yes)) { + Button("yes") { Task { await mute(author: author) } } - Button(String(localized: .localizable.no)) {} + Button("no") {} } }, message: { if let author = reportedObject.author { - Text(.localizable.mutePrompt(author.safeName)) + Text(String.localizedStringWithFormat(String(localized: "mutePrompt"), author.safeName)) } else { - Text(.localizable.error) + Text("error") } } ) .onChange(of: isPresented) { _, shouldPresent in if shouldPresent { - let message: LocalizedStringResource + let message: String if case .noteCategorySelected = userSelection { - message = .localizable.reportContentMessage + message = String(localized: "reportContentMessage") } else { - message = .localizable.flagUserMessage + message = String(localized: "flagUserMessage") } confirmationDialogState = ConfirmationDialogState( - title: TextState(String(localized: .localizable.reportContent)), - message: TextState(String(localized: message)), + title: TextState(String(localized: "reportContent")), + message: TextState(message), buttons: topLevelButtons() ) } @@ -161,8 +161,12 @@ struct ReportMenuModifier: ViewModifier { case .noteCategorySelected(let category): Task { confirmationDialogState = ConfirmationDialogState( - title: TextState(String(localized: .localizable.reportActionTitle(category.displayName))), - message: TextState(String(localized: .localizable.reportActionTitle(category.displayName))), + title: TextState( + String.localizedStringWithFormat(String(localized: "reportActionTitle"), category.displayName) + ), + message: TextState( + String.localizedStringWithFormat(String(localized: "reportActionTitle"), category.displayName) + ), buttons: [ ButtonState(action: .send(.sendToNos(category))) { TextState("Send to Nos") @@ -177,8 +181,12 @@ struct ReportMenuModifier: ViewModifier { case .authorCategorySelected(let category): Task { confirmationDialogState = ConfirmationDialogState( - title: TextState(String(localized: .localizable.reportActionTitle(category.displayName))), - message: TextState(String(localized: .localizable.reportActionTitle(category.displayName))), + title: TextState( + String.localizedStringWithFormat(String(localized: "reportActionTitle"), category.displayName) + ), + message: TextState( + String.localizedStringWithFormat(String(localized: "reportActionTitle"), category.displayName) + ), buttons: [ ButtonState(action: .send(.sendToNos(category))) { TextState("Send to Nos") @@ -228,17 +236,23 @@ struct ReportMenuModifier: ViewModifier { case .sendToNos(let category): switch reportedObject { case .note: - return String(localized: .localizable.reportNoteSendToNosConfirmation(category.displayName)) + return String.localizedStringWithFormat( + String(localized: "reportNoteSendToNosConfirmation"), category.displayName + ) case .author: - return String(localized: .localizable.reportAuthorSendToNosConfirmation) + return String(localized: "reportAuthorSendToNosConfirmation") } case .flagPublicly(let category): - return String(localized: .localizable.reportFlagPubliclyConfirmation(category.displayName)) + return String.localizedStringWithFormat( + String(localized: "reportFlagPubliclyConfirmation"), category.displayName + ) case .noteCategorySelected(let category), .authorCategorySelected(let category): - return String(localized: .localizable.reportFlagPubliclyConfirmation(category.displayName)) + return String.localizedStringWithFormat( + String(localized: "reportFlagPubliclyConfirmation"), category.displayName + ) } } } @@ -325,7 +339,7 @@ struct ReportMenuModifier: ViewModifier { } func getAlertMessage(for userSelection: UserSelection?, with reportedObject: ReportTarget) -> String { - userSelection?.confirmationAlertMessage(for: reportedObject) ?? String(localized: .localizable.error) + userSelection?.confirmationAlertMessage(for: reportedObject) ?? String(localized: "error") } } diff --git a/Nos/Views/Note/CompactNoteView.swift b/Nos/Views/Note/CompactNoteView.swift index a480a71fe..cd9ee06f8 100644 --- a/Nos/Views/Note/CompactNoteView.swift +++ b/Nos/Views/Note/CompactNoteView.swift @@ -142,7 +142,8 @@ struct CompactNoteView: View { isTextTruncated = false } } label: { - Text(String(localized: .localizable.readMore).uppercased()) + Text("readMore") + .textCase(.uppercase) .font(.caption) .foregroundColor(.secondaryTxt) .padding(EdgeInsets(top: 4, leading: 6, bottom: 4, trailing: 6)) diff --git a/Nos/Views/Note/NoteView.swift b/Nos/Views/Note/NoteView.swift index 535e5124a..a62a26c34 100644 --- a/Nos/Views/Note/NoteView.swift +++ b/Nos/Views/Note/NoteView.swift @@ -121,7 +121,7 @@ struct NoteView: View { } .frame(maxWidth: .infinity, maxHeight: .infinity) .padding(.top, 1) - .nosNavigationBar(title: .localizable.thread) + .nosNavigationBar("thread") .onAppear { subscribeToReplies() } @@ -150,7 +150,7 @@ struct NoteView: View { Button(action: { focusTextView = false }, label: { - Text(.localizable.cancel) + Text("cancel") .foregroundColor(.primaryTxt) }) } diff --git a/Nos/Views/NoteComposer/ComposerActionBar.swift b/Nos/Views/NoteComposer/ComposerActionBar.swift index fa63a89d5..c2cc9820e 100644 --- a/Nos/Views/NoteComposer/ComposerActionBar.swift +++ b/Nos/Views/NoteComposer/ComposerActionBar.swift @@ -51,7 +51,7 @@ struct ComposerActionBar: View { backArrow ScrollView(.horizontal) { HStack { - Text(.localizable.noteDisappearsIn) + Text("noteDisappearsIn") .font(.clarityRegular(.caption)) .foregroundColor(.secondaryTxt) .transition(.move(edge: .trailing)) @@ -119,7 +119,7 @@ struct ComposerActionBar: View { .frame(minWidth: 44, minHeight: 44) } .padding(.leading, 8) - .accessibilityLabel(Text(.localizable.attachMedia)) + .accessibilityLabel(Text("attachMedia")) } /// Expiration Time @@ -135,7 +135,7 @@ struct ComposerActionBar: View { self.expirationTime = $0 ? option.timeInterval : nil }) ) - .accessibilityLabel(Text(.localizable.expirationDate)) + .accessibilityLabel(Text("expirationDate")) .padding(12) } else { Button { @@ -152,7 +152,7 @@ struct ComposerActionBar: View { /// Preview Toggle private var previewToggle: some View { Group { - Text(.localizable.preview) + Text("preview") .padding(.horizontal, 10) .foregroundColor(Color.secondaryTxt) NosToggle(isOn: $showPreview) @@ -202,31 +202,37 @@ struct ComposerActionBar: View { private func createAlert( for error: Error ) -> AlertState { - var title = String(localized: .imagePicker.errorUploadingFile) + var title = String(localized: "errorUploadingFile", table: "ImagePicker") var message: String var buttons: [ButtonState] = [ .default( - TextState(String(localized: .localizable.ok)), + TextState(String(localized: "ok")), action: .send(.cancel) ) ] if case let FileStorageAPIClientError.fileTooBig(errorMessage) = error, let errorMessage { - title = String(localized: .imagePicker.errorUploadingFileExceedsSizeLimit) - message = String(localized: .imagePicker.errorUploadingFileExceedsLimit(errorMessage)) + title = String(localized: "errorUploadingFileExceedsSizeLimit", table: "ImagePicker") + message = String.localizedStringWithFormat( + String(localized: "errorUploadingFileExceedsLimit", table: "ImagePicker"), + errorMessage + ) buttons = [ .cancel( - TextState(String(localized: .localizable.cancel)), action: .send(.cancel) + TextState(String(localized: "cancel")), action: .send(.cancel) ), .default( - TextState(String(localized: .imagePicker.getAccount)), + TextState(String(localized: "getAccount", table: "ImagePicker")), action: .send(.getAccount) ) ] } else if case let FileStorageAPIClientError.uploadFailed(errorMessage) = error, let errorMessage { - message = String(localized: .imagePicker.errorUploadingFileWithMessage(errorMessage)) + message = String.localizedStringWithFormat( + String(localized: "errorUploadingFileWithMessage", table: "ImagePicker"), + errorMessage + ) } else { - message = String(localized: .imagePicker.errorUploadingFileMessage) + message = String(localized: "errorUploadingFileMessage", table: "ImagePicker") } return AlertState( diff --git a/Nos/Views/NoteComposer/ImagePickerButton.swift b/Nos/Views/NoteComposer/ImagePickerButton.swift index c062acb7a..f0c816bea 100644 --- a/Nos/Views/NoteComposer/ImagePickerButton.swift +++ b/Nos/Views/NoteComposer/ImagePickerButton.swift @@ -36,11 +36,8 @@ struct ImagePickerButton