From c912b89da25fd27e4085d0a18be3a0e0d3d8f1e4 Mon Sep 17 00:00:00 2001 From: Egzon Arifi Date: Tue, 28 Nov 2023 16:28:05 +0100 Subject: [PATCH] Add section filtering --- .../Lingua/Lingua.xcodeproj/project.pbxproj | 4 ++ Lingua-App/Lingua/Lingua/Model/Project.swift | 14 ++++- .../ProjectFormView/ProjectFormView.swift | 14 +++++ .../Components/UI/SectionsInputView.swift | 53 +++++++++++++++++++ .../Utils/Manager/LocalizationManager.swift | 3 +- .../LinguaLib/Domain/Entities/Config.swift | 10 +++- .../Generator/LocalizedFilesGenerator.swift | 4 ++ 7 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 Lingua-App/Lingua/Lingua/Utils/Components/UI/SectionsInputView.swift diff --git a/Lingua-App/Lingua/Lingua.xcodeproj/project.pbxproj b/Lingua-App/Lingua/Lingua.xcodeproj/project.pbxproj index 1022f13..8d8b0eb 100644 --- a/Lingua-App/Lingua/Lingua.xcodeproj/project.pbxproj +++ b/Lingua-App/Lingua/Lingua.xcodeproj/project.pbxproj @@ -11,6 +11,7 @@ 774A1A462A8E588500789A04 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 774A1A452A8E588500789A04 /* ContentView.swift */; }; 774A1A482A8E588800789A04 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 774A1A472A8E588800789A04 /* Assets.xcassets */; }; 774A1A562A8E588800789A04 /* LinguaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 774A1A552A8E588800789A04 /* LinguaTests.swift */; }; + 777814B02B13D5C700A1B678 /* SectionsInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 777814AF2B13D5C700A1B678 /* SectionsInputView.swift */; }; 777BC5E12A93617000C74D72 /* ValidatingTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 777BC5E02A93617000C74D72 /* ValidatingTextField.swift */; }; 777BC5E42A9361E200C74D72 /* ValidationRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 777BC5E32A9361E200C74D72 /* ValidationRule.swift */; }; 777BC5E62A9361F000C74D72 /* RequiredRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 777BC5E52A9361F000C74D72 /* RequiredRule.swift */; }; @@ -65,6 +66,7 @@ 774A1A4C2A8E588800789A04 /* Lingua.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Lingua.entitlements; sourceTree = ""; }; 774A1A512A8E588800789A04 /* LinguaTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LinguaTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 774A1A552A8E588800789A04 /* LinguaTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinguaTests.swift; sourceTree = ""; }; + 777814AF2B13D5C700A1B678 /* SectionsInputView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionsInputView.swift; sourceTree = ""; }; 777BC5E02A93617000C74D72 /* ValidatingTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValidatingTextField.swift; sourceTree = ""; }; 777BC5E32A9361E200C74D72 /* ValidationRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValidationRule.swift; sourceTree = ""; }; 777BC5E52A9361F000C74D72 /* RequiredRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequiredRule.swift; sourceTree = ""; }; @@ -205,6 +207,7 @@ 777BC62E2A94B2A000C74D72 /* ProgressOverlay.swift */, 779F91F82A978AC8009C77D5 /* InformationHolderView.swift */, 77F89A472A98DF3A009EE7B1 /* CustomSearchBar.swift */, + 777814AF2B13D5C700A1B678 /* SectionsInputView.swift */, ); path = UI; sourceTree = ""; @@ -441,6 +444,7 @@ 777BC5EF2A938B8400C74D72 /* ProjectFormView.swift in Sources */, 774A1A442A8E588500789A04 /* LinguaApp.swift in Sources */, 777BC5E82A93639E00C74D72 /* DirectoryInputField.swift in Sources */, + 777814B02B13D5C700A1B678 /* SectionsInputView.swift in Sources */, 970D1F802B10EC3F00F6CD8E /* Window.swift in Sources */, 777BC62F2A94B2A000C74D72 /* ProgressOverlay.swift in Sources */, 777BC5E42A9361E200C74D72 /* ValidationRule.swift in Sources */, diff --git a/Lingua-App/Lingua/Lingua/Model/Project.swift b/Lingua-App/Lingua/Lingua/Model/Project.swift index c0fd4de..83063d0 100644 --- a/Lingua-App/Lingua/Lingua/Model/Project.swift +++ b/Lingua-App/Lingua/Lingua/Model/Project.swift @@ -16,9 +16,11 @@ struct Project: Identifiable, Hashable, Equatable, Codable { var directoryPath: String var title: String var swiftCode: SwiftCode - var swiftCodeEnabled: Bool = true + var swiftCodeEnabled: Bool var createdAt: Date var lastLocalizedAt: Date? + var filterSectionsEnabled: Bool + var allowedSections: [String] init(id: UUID, type: LocalizationPlatform, @@ -27,8 +29,11 @@ struct Project: Identifiable, Hashable, Equatable, Codable { directoryPath: String = "", title: String = "", swiftCode: SwiftCode = .init(stringsDirectory: "", outputSwiftCodeFileDirectory: ""), + swiftCodeEnabled: Bool = true, createdAt: Date = .init(), - lastLocalizedAt: Date? = nil) { + lastLocalizedAt: Date? = nil, + filterSectionsEnabled: Bool = false, + allowedSections: [String] = []) { self.id = id self.type = type self.apiKey = apiKey @@ -36,8 +41,11 @@ struct Project: Identifiable, Hashable, Equatable, Codable { self.directoryPath = directoryPath self.title = title self.swiftCode = swiftCode + self.swiftCodeEnabled = swiftCodeEnabled self.createdAt = createdAt self.lastLocalizedAt = lastLocalizedAt + self.filterSectionsEnabled = filterSectionsEnabled + self.allowedSections = allowedSections } /// Custom initializer for decoding [Project] from persisted storage. @@ -57,6 +65,8 @@ struct Project: Identifiable, Hashable, Equatable, Codable { swiftCodeEnabled = try container.decode(Bool.self, forKey: .swiftCodeEnabled) createdAt = try container.decodeIfPresent(Date.self, forKey: .createdAt) ?? Date() lastLocalizedAt = try container.decodeIfPresent(Date.self, forKey: .lastLocalizedAt) + filterSectionsEnabled = try container.decodeIfPresent(Bool.self, forKey: .filterSectionsEnabled) ?? false + allowedSections = try container.decodeIfPresent([String].self, forKey: .allowedSections) ?? [] } } diff --git a/Lingua-App/Lingua/Lingua/Scenes/ProjectFormView/ProjectFormView.swift b/Lingua-App/Lingua/Lingua/Scenes/ProjectFormView/ProjectFormView.swift index b9602f3..bcb7bc4 100644 --- a/Lingua-App/Lingua/Lingua/Scenes/ProjectFormView/ProjectFormView.swift +++ b/Lingua-App/Lingua/Lingua/Scenes/ProjectFormView/ProjectFormView.swift @@ -28,6 +28,7 @@ struct ProjectFormView: View { Form { basicConfigurationFormSection() swiftCodeFormSection() + filterSectionsFormSection() iOSInfoFormSection() } .toolbar { @@ -157,6 +158,19 @@ private extension ProjectFormView { } } + @ViewBuilder + func filterSectionsFormSection() -> some View { + Section { + Toggle(isOn: $viewModel.project.filterSectionsEnabled) { + Text("Enable sections filtering...") + .bold() + if viewModel.project.filterSectionsEnabled { + SectionsInputView(sections: $viewModel.project.allowedSections) + } + } + } + } + @ViewBuilder func iOSInfoFormSection() -> some View { if viewModel.project.type == .ios { diff --git a/Lingua-App/Lingua/Lingua/Utils/Components/UI/SectionsInputView.swift b/Lingua-App/Lingua/Lingua/Utils/Components/UI/SectionsInputView.swift new file mode 100644 index 0000000..e7417ab --- /dev/null +++ b/Lingua-App/Lingua/Lingua/Utils/Components/UI/SectionsInputView.swift @@ -0,0 +1,53 @@ +// +// TagInputView.swift +// Lingua +// +// Created by Egzon Arifi on 26/11/2023. +// + +import SwiftUI + +struct SectionsInputView: View { + @State var currentInput: String = "" + @Binding var sections: [String] + + var body: some View { + VStack(alignment: .leading) { + HStack { + TextField("Enter a section", text: $currentInput, onCommit: addSection) + .textFieldStyle(RoundedBorderTextFieldStyle()) + .padding() + + Button(action: addSection) { + Text("Add section") + } + } + + Divider() + + HStack { + ForEach(sections, id: \.self) { tag in + Button(action: { + removeSection(tag) + }, label: { + Text(tag) + .padding(.vertical, 4) + + Image(systemName: "xmark") + }) + } + } + } + } + + private func addSection() { + if !currentInput.isEmpty { + sections.append(currentInput) + currentInput = "" + } + } + + private func removeSection(_ tag: String) { + sections.removeAll { $0 == tag } + } +} diff --git a/Lingua-App/Lingua/Lingua/Utils/Manager/LocalizationManager.swift b/Lingua-App/Lingua/Lingua/Utils/Manager/LocalizationManager.swift index 4a36062..a8b2862 100644 --- a/Lingua-App/Lingua/Lingua/Utils/Manager/LocalizationManager.swift +++ b/Lingua-App/Lingua/Lingua/Utils/Manager/LocalizationManager.swift @@ -32,7 +32,8 @@ struct LocalizationManager { let config = Config.Localization(apiKey: project.apiKey, sheetId: project.sheetId, outputDirectory: project.directoryPath, - localizedSwiftCode: localizedSwiftCode) + localizedSwiftCode: localizedSwiftCode, + allowedSections: project.filterSectionsEnabled ? project.allowedSections : .none) let module = LocalizationModuleFactory.make(config: config) try await module.localize(for: project.type) diff --git a/Sources/LinguaLib/Domain/Entities/Config.swift b/Sources/LinguaLib/Domain/Entities/Config.swift index 81fc789..ca58c61 100644 --- a/Sources/LinguaLib/Domain/Entities/Config.swift +++ b/Sources/LinguaLib/Domain/Entities/Config.swift @@ -10,12 +10,20 @@ public extension Config { let sheetId: String let outputDirectory: String let localizedSwiftCode: LocalizedSwiftCode? + let allowedSections: [String]? - public init(apiKey: String, sheetId: String, outputDirectory: String, localizedSwiftCode: LocalizedSwiftCode?) { + public init( + apiKey: String, + sheetId: String, + outputDirectory: String, + localizedSwiftCode: LocalizedSwiftCode?, + allowedSections: [String]? = nil + ) { self.apiKey = apiKey self.sheetId = sheetId self.outputDirectory = outputDirectory self.localizedSwiftCode = localizedSwiftCode + self.allowedSections = allowedSections } } diff --git a/Sources/LinguaLib/Infrastructure/LocalizationGenerator/Generator/LocalizedFilesGenerator.swift b/Sources/LinguaLib/Infrastructure/LocalizationGenerator/Generator/LocalizedFilesGenerator.swift index 1f18069..5fb536e 100644 --- a/Sources/LinguaLib/Infrastructure/LocalizationGenerator/Generator/LocalizedFilesGenerator.swift +++ b/Sources/LinguaLib/Infrastructure/LocalizationGenerator/Generator/LocalizedFilesGenerator.swift @@ -27,6 +27,10 @@ extension LocalizedFilesGenerator: LocalizedFilesGenerating { let sections = Dictionary(grouping: sheet.entries, by: { $0.section }) for (sectionName, sectionEntries) in sections { + if let allowedSections = config.allowedSections, + !allowedSections.contains(where: { $0.lowercased() == sectionName.lowercased() }) { + continue + } try filesGenerator.createPlatformFiles(for: sectionEntries, sectionName: sectionName.formatSheetSection(), outputFolder: outputFolder,