From bef202513d8555a618308329e3ec7fbe0aa6151b Mon Sep 17 00:00:00 2001 From: Esteban Borai Date: Sun, 10 Dec 2023 15:05:50 -0300 Subject: [PATCH 01/15] feat: setup search section in app settings --- CodeEdit.xcodeproj/project.pbxproj | 24 +++++++++++++++ .../xcshareddata/swiftpm/Package.resolved | 4 +-- .../Settings/Models/SettingsData.swift | 6 ++++ .../Settings/Models/SettingsPage.swift | 1 + .../Models/SearchSettings.swift | 24 +++++++++++++++ .../SearchSettings/SearchSettingsView.swift | 29 +++++++++++++++++++ CodeEdit/Features/Settings/SettingsView.swift | 9 ++++++ 7 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettings.swift create mode 100644 CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift diff --git a/CodeEdit.xcodeproj/project.pbxproj b/CodeEdit.xcodeproj/project.pbxproj index 5654a4cd0f..a3df72fec3 100644 --- a/CodeEdit.xcodeproj/project.pbxproj +++ b/CodeEdit.xcodeproj/project.pbxproj @@ -247,6 +247,8 @@ 58F2EB1E292FB954004A9BDE /* Sparkle in Frameworks */ = {isa = PBXBuildFile; productRef = 58F2EB1D292FB954004A9BDE /* Sparkle */; }; 58FD7608291EA1CB0051D6E4 /* CommandPaletteViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58FD7605291EA1CB0051D6E4 /* CommandPaletteViewModel.swift */; }; 58FD7609291EA1CB0051D6E4 /* CommandPaletteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58FD7607291EA1CB0051D6E4 /* CommandPaletteView.swift */; }; + 5B698A0A2B262FA000DE9392 /* SearchSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B698A092B262FA000DE9392 /* SearchSettingsView.swift */; }; + 5B698A0D2B26327800DE9392 /* SearchSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B698A0C2B26327800DE9392 /* SearchSettings.swift */; }; 5C4BB1E128212B1E00A92FB2 /* World.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C4BB1E028212B1E00A92FB2 /* World.swift */; }; 610C0FDA2B44438F00A01CA7 /* WorkspaceDocument+FindAndReplace.swift in Sources */ = {isa = PBXBuildFile; fileRef = 610C0FD92B44438F00A01CA7 /* WorkspaceDocument+FindAndReplace.swift */; }; 611191FA2B08CC9000D4459B /* SearchIndexer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 611191F92B08CC9000D4459B /* SearchIndexer.swift */; }; @@ -797,6 +799,8 @@ 58F2EAE1292FB2B0004A9BDE /* SoftwareUpdater.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SoftwareUpdater.swift; sourceTree = ""; }; 58FD7605291EA1CB0051D6E4 /* CommandPaletteViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommandPaletteViewModel.swift; sourceTree = ""; }; 58FD7607291EA1CB0051D6E4 /* CommandPaletteView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommandPaletteView.swift; sourceTree = ""; }; + 5B698A092B262FA000DE9392 /* SearchSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchSettingsView.swift; sourceTree = ""; }; + 5B698A0C2B26327800DE9392 /* SearchSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchSettings.swift; sourceTree = ""; }; 5C4BB1E028212B1E00A92FB2 /* World.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = World.swift; sourceTree = ""; }; 610C0FD92B44438F00A01CA7 /* WorkspaceDocument+FindAndReplace.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WorkspaceDocument+FindAndReplace.swift"; sourceTree = ""; }; 611191F92B08CC9000D4459B /* SearchIndexer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchIndexer.swift; sourceTree = ""; }; @@ -2256,6 +2260,23 @@ path = Views; sourceTree = ""; }; + 5B698A082B262F8400DE9392 /* SearchSettings */ = { + isa = PBXGroup; + children = ( + 5B698A0B2B26326000DE9392 /* Models */, + 5B698A092B262FA000DE9392 /* SearchSettingsView.swift */, + ); + path = SearchSettings; + sourceTree = ""; + }; + 5B698A0B2B26326000DE9392 /* Models */ = { + isa = PBXGroup; + children = ( + 5B698A0C2B26327800DE9392 /* SearchSettings.swift */, + ); + path = Models; + sourceTree = ""; + }; 5C403B8D27E20F8000788241 /* Frameworks */ = { isa = PBXGroup; children = ( @@ -2482,6 +2503,7 @@ B61DA9DD29D929BF00BF4A43 /* Pages */ = { isa = PBXGroup; children = ( + 5B698A082B262F8400DE9392 /* SearchSettings */, 6C5BE51A2A3D5419002DA0FC /* FeatureFlags */, B6CF632629E5417C0085880A /* Keybindings */, B6E41C6E29DD15540088F9F4 /* AccountsSettings */, @@ -3204,6 +3226,7 @@ 587B9E8429301D8F00AC7927 /* GitHubUser.swift in Sources */, 04BA7C1C2AE2D84100584E1C /* GitClient+Commit.swift in Sources */, B65B10EC2B073913002852CF /* CEContentUnavailableView.swift in Sources */, + 5B698A0A2B262FA000DE9392 /* SearchSettingsView.swift in Sources */, B65B10FB2B08B054002852CF /* Divided.swift in Sources */, B65B11012B09D5D4002852CF /* GitClient+Pull.swift in Sources */, 2072FA13280D74ED00C7F8D4 /* HistoryInspectorModel.swift in Sources */, @@ -3478,6 +3501,7 @@ 6CFF967629BEBCD900182D6F /* FileCommands.swift in Sources */, B60718462B17DC15009CDAB4 /* RepoOutlineGroupItem.swift in Sources */, B697937A29FF5668002027EC /* AccountsSettingsAccountLink.swift in Sources */, + 5B698A0D2B26327800DE9392 /* SearchSettings.swift in Sources */, B685DE7929CC9CCD002860C8 /* StatusBarIcon.swift in Sources */, 587B9DA629300ABD00AC7927 /* ToolbarBranchPicker.swift in Sources */, 6C6BD6F629CD145F00235D17 /* ExtensionInfo.swift in Sources */, diff --git a/CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 325d174f18..4966272a3b 100644 --- a/CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -203,8 +203,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-syntax.git", "state" : { - "revision" : "43c802fb7f96e090dde015344a94b5e85779eff1", - "version" : "509.1.0" + "revision" : "6ad4ea24b01559dde0773e3d091f1b9e36175036", + "version" : "509.0.2" } }, { diff --git a/CodeEdit/Features/Settings/Models/SettingsData.swift b/CodeEdit/Features/Settings/Models/SettingsData.swift index 011b48ed45..05c48c719d 100644 --- a/CodeEdit/Features/Settings/Models/SettingsData.swift +++ b/CodeEdit/Features/Settings/Models/SettingsData.swift @@ -47,6 +47,9 @@ struct SettingsData: Codable, Hashable { /// Feature Flags settings var featureFlags: FeatureFlagsSettings = .init() + /// Searh Settings + var search: SearchSettings = .init() + /// Default initializer init() {} @@ -58,6 +61,7 @@ struct SettingsData: Codable, Hashable { self.theme = try container.decodeIfPresent(ThemeSettings.self, forKey: .theme) ?? .init() self.terminal = try container.decodeIfPresent(TerminalSettings.self, forKey: .terminal) ?? .init() self.textEditing = try container.decodeIfPresent(TextEditingSettings.self, forKey: .textEditing) ?? .init() + self.search = try container.decodeIfPresent(SearchSettings.self, forKey: .search) ?? .init() self.sourceControl = try container.decodeIfPresent( SourceControlSettings.self, forKey: .sourceControl @@ -84,6 +88,8 @@ struct SettingsData: Codable, Hashable { textEditing.searchKeys.forEach { settings.append(.init(name, isSetting: true, settingName: $0)) } case .terminal: terminal.searchKeys.forEach { settings.append(.init(name, isSetting: true, settingName: $0)) } + case .search: + search.searchKeys.forEach { settings.append(.init(name, isSetting: true, settingName: $0)) } case .sourceControl: sourceControl.searchKeys.forEach { settings.append(.init(name, isSetting: true, settingName: $0)) } case .location: diff --git a/CodeEdit/Features/Settings/Models/SettingsPage.swift b/CodeEdit/Features/Settings/Models/SettingsPage.swift index e8903fb181..54d9b0a970 100644 --- a/CodeEdit/Features/Settings/Models/SettingsPage.swift +++ b/CodeEdit/Features/Settings/Models/SettingsPage.swift @@ -26,6 +26,7 @@ struct SettingsPage: Hashable, Equatable, Identifiable { case theme = "Themes" case textEditing = "Text Editing" case terminal = "Terminal" + case search = "Search" case keybindings = "Key Bindings" case sourceControl = "Source Control" case components = "Components" diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettings.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettings.swift new file mode 100644 index 0000000000..0cc456acb2 --- /dev/null +++ b/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettings.swift @@ -0,0 +1,24 @@ +// +// SearchSettings.swift +// CodeEdit +// +// Created by Esteban on 12/10/23. +// + +import Foundation + +extension SettingsData { + + struct SearchSettings: Codable, Hashable, SearchableSettingsPage { + + /// The search keys + var searchKeys: [String] { + [ + "Ignore Glob Patterns" + ] + .map { NSLocalizedString($0, comment: "") } + } + + var ignoreGlobPatterns: Array = [] + } +} diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift new file mode 100644 index 0000000000..2dd5ec558a --- /dev/null +++ b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift @@ -0,0 +1,29 @@ +// +// SearchSettingsView.swift +// CodeEdit +// +// Created by Esteban on 12/10/23. +// + +import SwiftUI + +struct SearchSettingsView: View { + + @AppSettings(\.search.ignoreGlobPatterns) + var ignoreGlobPatterns + + var body: some View { + SettingsForm { + Section { + Text("No accounts") + .foregroundColor(.secondary) + .frame(maxWidth: .infinity, alignment: .center) + } footer: { + HStack { + Spacer() + } + .padding(.top, 10) + } + } + } +} diff --git a/CodeEdit/Features/Settings/SettingsView.swift b/CodeEdit/Features/Settings/SettingsView.swift index bacf5e2bf3..faddda296f 100644 --- a/CodeEdit/Features/Settings/SettingsView.swift +++ b/CodeEdit/Features/Settings/SettingsView.swift @@ -57,6 +57,13 @@ struct SettingsView: View { icon: .system("terminal.fill") ) ), + .init( + SettingsPage( + .search, + baseColor: .blue, + icon: .system("magnifyingglass") + ) + ), .init( SettingsPage( .sourceControl, @@ -151,6 +158,8 @@ struct SettingsView: View { TextEditingSettingsView() case .terminal: TerminalSettingsView() + case .search: + SearchSettingsView() case .sourceControl: SourceControlSettingsView() case .location: From 36283dc1fae3e869fd1d4fc2bee2e4d8aff732fa Mon Sep 17 00:00:00 2001 From: Esteban Borai Date: Sun, 10 Dec 2023 15:14:24 -0300 Subject: [PATCH 02/15] feat: list for ignore glob patterns --- CodeEdit.xcodeproj/project.pbxproj | 4 ++++ .../SearchSettings/SearchIgnoreGlobPattern.swift | 16 ++++++++++++++++ .../SearchSettings/SearchSettingsView.swift | 12 +++++++++--- 3 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 CodeEdit/Features/Settings/Pages/SearchSettings/SearchIgnoreGlobPattern.swift diff --git a/CodeEdit.xcodeproj/project.pbxproj b/CodeEdit.xcodeproj/project.pbxproj index a3df72fec3..73d12f3ce8 100644 --- a/CodeEdit.xcodeproj/project.pbxproj +++ b/CodeEdit.xcodeproj/project.pbxproj @@ -249,6 +249,7 @@ 58FD7609291EA1CB0051D6E4 /* CommandPaletteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58FD7607291EA1CB0051D6E4 /* CommandPaletteView.swift */; }; 5B698A0A2B262FA000DE9392 /* SearchSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B698A092B262FA000DE9392 /* SearchSettingsView.swift */; }; 5B698A0D2B26327800DE9392 /* SearchSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B698A0C2B26327800DE9392 /* SearchSettings.swift */; }; + 5B698A0F2B2636A700DE9392 /* SearchIgnoreGlobPattern.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B698A0E2B2636A700DE9392 /* SearchIgnoreGlobPattern.swift */; }; 5C4BB1E128212B1E00A92FB2 /* World.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C4BB1E028212B1E00A92FB2 /* World.swift */; }; 610C0FDA2B44438F00A01CA7 /* WorkspaceDocument+FindAndReplace.swift in Sources */ = {isa = PBXBuildFile; fileRef = 610C0FD92B44438F00A01CA7 /* WorkspaceDocument+FindAndReplace.swift */; }; 611191FA2B08CC9000D4459B /* SearchIndexer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 611191F92B08CC9000D4459B /* SearchIndexer.swift */; }; @@ -801,6 +802,7 @@ 58FD7607291EA1CB0051D6E4 /* CommandPaletteView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommandPaletteView.swift; sourceTree = ""; }; 5B698A092B262FA000DE9392 /* SearchSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchSettingsView.swift; sourceTree = ""; }; 5B698A0C2B26327800DE9392 /* SearchSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchSettings.swift; sourceTree = ""; }; + 5B698A0E2B2636A700DE9392 /* SearchIgnoreGlobPattern.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchIgnoreGlobPattern.swift; sourceTree = ""; }; 5C4BB1E028212B1E00A92FB2 /* World.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = World.swift; sourceTree = ""; }; 610C0FD92B44438F00A01CA7 /* WorkspaceDocument+FindAndReplace.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WorkspaceDocument+FindAndReplace.swift"; sourceTree = ""; }; 611191F92B08CC9000D4459B /* SearchIndexer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchIndexer.swift; sourceTree = ""; }; @@ -2265,6 +2267,7 @@ children = ( 5B698A0B2B26326000DE9392 /* Models */, 5B698A092B262FA000DE9392 /* SearchSettingsView.swift */, + 5B698A0E2B2636A700DE9392 /* SearchIgnoreGlobPattern.swift */, ); path = SearchSettings; sourceTree = ""; @@ -3240,6 +3243,7 @@ 587B9E9229301D8F00AC7927 /* BitBucketAccount.swift in Sources */, DE513F52281B672D002260B9 /* EditorTabBarAccessory.swift in Sources */, 2813F93927ECC4C300E305E4 /* NavigatorAreaView.swift in Sources */, + 5B698A0F2B2636A700DE9392 /* SearchIgnoreGlobPattern.swift in Sources */, 587B9E8A29301D8F00AC7927 /* GitHubIssue.swift in Sources */, EC0870F72A455F6400EB8692 /* ProjectNavigatorViewController+NSMenuDelegate.swift in Sources */, B60718202B0C6CE7009CDAB4 /* GitStashEntry.swift in Sources */, diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchIgnoreGlobPattern.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchIgnoreGlobPattern.swift new file mode 100644 index 0000000000..e074d0a37e --- /dev/null +++ b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchIgnoreGlobPattern.swift @@ -0,0 +1,16 @@ +// +// SearchIgnoreGlobPattern.swift +// CodeEdit +// +// Created by Esteban on 12/10/23. +// + +import SwiftUI + +struct SearchIgnoreGlobPattern: View { + @Binding var globPattern: String + + var body: some View { + Text(globPattern) + } +} diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift index 2dd5ec558a..4290fc3447 100644 --- a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift +++ b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift @@ -15,9 +15,15 @@ struct SearchSettingsView: View { var body: some View { SettingsForm { Section { - Text("No accounts") - .foregroundColor(.secondary) - .frame(maxWidth: .infinity, alignment: .center) + if $ignoreGlobPatterns.isEmpty { + Text("No ignore patterns") + .foregroundColor(.secondary) + .frame(maxWidth: .infinity, alignment: .center) + } else { + ForEach($ignoreGlobPatterns, id: \.self) { pattern in + SearchIgnoreGlobPattern(globPattern: pattern) + } + } } footer: { HStack { Spacer() From d0c1b6234d18cc6226f7987d1190e01200bcdbe6 Mon Sep 17 00:00:00 2001 From: Esteban Borai Date: Sun, 10 Dec 2023 15:29:00 -0300 Subject: [PATCH 03/15] feat: open/close modal for add glob pattern --- CodeEdit.xcodeproj/project.pbxproj | 12 ++++-- .../Models/SearchSettings.swift | 6 ++- ...archSettingsIgnoreGlobPatternAddView.swift | 41 +++++++++++++++++++ ...chSettingsIgnoreGlobPatternItemView.swift} | 4 +- .../SearchSettings/SearchSettingsView.swift | 8 +++- 5 files changed, 63 insertions(+), 8 deletions(-) create mode 100644 CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsIgnoreGlobPatternAddView.swift rename CodeEdit/Features/Settings/Pages/SearchSettings/{SearchIgnoreGlobPattern.swift => SearchSettingsIgnoreGlobPatternItemView.swift} (62%) diff --git a/CodeEdit.xcodeproj/project.pbxproj b/CodeEdit.xcodeproj/project.pbxproj index 73d12f3ce8..c9eca367e5 100644 --- a/CodeEdit.xcodeproj/project.pbxproj +++ b/CodeEdit.xcodeproj/project.pbxproj @@ -249,7 +249,8 @@ 58FD7609291EA1CB0051D6E4 /* CommandPaletteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58FD7607291EA1CB0051D6E4 /* CommandPaletteView.swift */; }; 5B698A0A2B262FA000DE9392 /* SearchSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B698A092B262FA000DE9392 /* SearchSettingsView.swift */; }; 5B698A0D2B26327800DE9392 /* SearchSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B698A0C2B26327800DE9392 /* SearchSettings.swift */; }; - 5B698A0F2B2636A700DE9392 /* SearchIgnoreGlobPattern.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B698A0E2B2636A700DE9392 /* SearchIgnoreGlobPattern.swift */; }; + 5B698A0F2B2636A700DE9392 /* SearchSettingsIgnoreGlobPatternItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B698A0E2B2636A700DE9392 /* SearchSettingsIgnoreGlobPatternItemView.swift */; }; + 5B698A132B2638ED00DE9392 /* SearchSettingsIgnoreGlobPatternAddView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B698A122B2638ED00DE9392 /* SearchSettingsIgnoreGlobPatternAddView.swift */; }; 5C4BB1E128212B1E00A92FB2 /* World.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C4BB1E028212B1E00A92FB2 /* World.swift */; }; 610C0FDA2B44438F00A01CA7 /* WorkspaceDocument+FindAndReplace.swift in Sources */ = {isa = PBXBuildFile; fileRef = 610C0FD92B44438F00A01CA7 /* WorkspaceDocument+FindAndReplace.swift */; }; 611191FA2B08CC9000D4459B /* SearchIndexer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 611191F92B08CC9000D4459B /* SearchIndexer.swift */; }; @@ -802,7 +803,8 @@ 58FD7607291EA1CB0051D6E4 /* CommandPaletteView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommandPaletteView.swift; sourceTree = ""; }; 5B698A092B262FA000DE9392 /* SearchSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchSettingsView.swift; sourceTree = ""; }; 5B698A0C2B26327800DE9392 /* SearchSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchSettings.swift; sourceTree = ""; }; - 5B698A0E2B2636A700DE9392 /* SearchIgnoreGlobPattern.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchIgnoreGlobPattern.swift; sourceTree = ""; }; + 5B698A0E2B2636A700DE9392 /* SearchSettingsIgnoreGlobPatternItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchSettingsIgnoreGlobPatternItemView.swift; sourceTree = ""; }; + 5B698A122B2638ED00DE9392 /* SearchSettingsIgnoreGlobPatternAddView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchSettingsIgnoreGlobPatternAddView.swift; sourceTree = ""; }; 5C4BB1E028212B1E00A92FB2 /* World.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = World.swift; sourceTree = ""; }; 610C0FD92B44438F00A01CA7 /* WorkspaceDocument+FindAndReplace.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WorkspaceDocument+FindAndReplace.swift"; sourceTree = ""; }; 611191F92B08CC9000D4459B /* SearchIndexer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchIndexer.swift; sourceTree = ""; }; @@ -2267,7 +2269,8 @@ children = ( 5B698A0B2B26326000DE9392 /* Models */, 5B698A092B262FA000DE9392 /* SearchSettingsView.swift */, - 5B698A0E2B2636A700DE9392 /* SearchIgnoreGlobPattern.swift */, + 5B698A0E2B2636A700DE9392 /* SearchSettingsIgnoreGlobPatternItemView.swift */, + 5B698A122B2638ED00DE9392 /* SearchSettingsIgnoreGlobPatternAddView.swift */, ); path = SearchSettings; sourceTree = ""; @@ -3243,7 +3246,8 @@ 587B9E9229301D8F00AC7927 /* BitBucketAccount.swift in Sources */, DE513F52281B672D002260B9 /* EditorTabBarAccessory.swift in Sources */, 2813F93927ECC4C300E305E4 /* NavigatorAreaView.swift in Sources */, - 5B698A0F2B2636A700DE9392 /* SearchIgnoreGlobPattern.swift in Sources */, + 5B698A132B2638ED00DE9392 /* SearchSettingsIgnoreGlobPatternAddView.swift in Sources */, + 5B698A0F2B2636A700DE9392 /* SearchSettingsIgnoreGlobPatternItemView.swift in Sources */, 587B9E8A29301D8F00AC7927 /* GitHubIssue.swift in Sources */, EC0870F72A455F6400EB8692 /* ProjectNavigatorViewController+NSMenuDelegate.swift in Sources */, B60718202B0C6CE7009CDAB4 /* GitStashEntry.swift in Sources */, diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettings.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettings.swift index 0cc456acb2..b48f04e2d3 100644 --- a/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettings.swift +++ b/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettings.swift @@ -19,6 +19,10 @@ extension SettingsData { .map { NSLocalizedString($0, comment: "") } } - var ignoreGlobPatterns: Array = [] + var ignoreGlobPatterns: Array = [ + "**/node_modules", + "**/bower_components", + "**/*.code-search" + ] } } diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsIgnoreGlobPatternAddView.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsIgnoreGlobPatternAddView.swift new file mode 100644 index 0000000000..7c498e5d94 --- /dev/null +++ b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsIgnoreGlobPatternAddView.swift @@ -0,0 +1,41 @@ +// +// SearchSettingsIgnoreGlobPatternAddView.swift +// CodeEdit +// +// Created by Esteban on 12/10/23. +// + +import SwiftUI + +struct SearchSettingsIgnoreGlobPatternAddView: View { + @Environment(\.dismiss) + var dismiss + + var body: some View { + VStack(spacing: 0) { + Form { + Section { + VStack(alignment: .leading, spacing: 0) { + Text("Add here!") + } + } footer: { + HStack { + Spacer() + Button { + dismiss() + } label: { + Text("Cancel") + .padding(.horizontal) + } + .buttonStyle(.borderedProminent) + .controlSize(.large) + } + .padding(.top, 10) + } + } + .formStyle(.grouped) + .scrollDisabled(true) + } + .frame(width: 300) + } +} diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchIgnoreGlobPattern.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsIgnoreGlobPatternItemView.swift similarity index 62% rename from CodeEdit/Features/Settings/Pages/SearchSettings/SearchIgnoreGlobPattern.swift rename to CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsIgnoreGlobPatternItemView.swift index e074d0a37e..b29c33c361 100644 --- a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchIgnoreGlobPattern.swift +++ b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsIgnoreGlobPatternItemView.swift @@ -1,5 +1,5 @@ // -// SearchIgnoreGlobPattern.swift +// SearchSettingsIgnoreGlobPatternItemView.swift // CodeEdit // // Created by Esteban on 12/10/23. @@ -7,7 +7,7 @@ import SwiftUI -struct SearchIgnoreGlobPattern: View { +struct SearchSettingsIgnoreGlobPatternItemView: View { @Binding var globPattern: String var body: some View { diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift index 4290fc3447..e6596d9494 100644 --- a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift +++ b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift @@ -11,6 +11,8 @@ struct SearchSettingsView: View { @AppSettings(\.search.ignoreGlobPatterns) var ignoreGlobPatterns + + @State private var addIgnoreGlobPatternPresented: Bool = false var body: some View { SettingsForm { @@ -21,12 +23,16 @@ struct SearchSettingsView: View { .frame(maxWidth: .infinity, alignment: .center) } else { ForEach($ignoreGlobPatterns, id: \.self) { pattern in - SearchIgnoreGlobPattern(globPattern: pattern) + SearchSettingsIgnoreGlobPatternItemView(globPattern: pattern) } } } footer: { HStack { Spacer() + Button("Add ignore glob pattern...") { addIgnoreGlobPatternPresented.toggle() } + .sheet(isPresented: $addIgnoreGlobPatternPresented, content: { + SearchSettingsIgnoreGlobPatternAddView() + }) } .padding(.top, 10) } From dd7550a271148eb3311da1186abff9278c46b018 Mon Sep 17 00:00:00 2001 From: Esteban Borai Date: Sun, 10 Dec 2023 15:44:31 -0300 Subject: [PATCH 04/15] feat: introduce view model for search settings glob pattern --- CodeEdit.xcodeproj/project.pbxproj | 4 ++ .../Models/SearchSettings.swift | 6 +- .../Models/SearchSettingsModel.swift | 59 +++++++++++++++++++ ...archSettingsIgnoreGlobPatternAddView.swift | 12 +++- .../SearchSettings/SearchSettingsView.swift | 2 +- 5 files changed, 76 insertions(+), 7 deletions(-) create mode 100644 CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettingsModel.swift diff --git a/CodeEdit.xcodeproj/project.pbxproj b/CodeEdit.xcodeproj/project.pbxproj index c9eca367e5..841c6c005d 100644 --- a/CodeEdit.xcodeproj/project.pbxproj +++ b/CodeEdit.xcodeproj/project.pbxproj @@ -251,6 +251,7 @@ 5B698A0D2B26327800DE9392 /* SearchSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B698A0C2B26327800DE9392 /* SearchSettings.swift */; }; 5B698A0F2B2636A700DE9392 /* SearchSettingsIgnoreGlobPatternItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B698A0E2B2636A700DE9392 /* SearchSettingsIgnoreGlobPatternItemView.swift */; }; 5B698A132B2638ED00DE9392 /* SearchSettingsIgnoreGlobPatternAddView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B698A122B2638ED00DE9392 /* SearchSettingsIgnoreGlobPatternAddView.swift */; }; + 5B698A162B263BCE00DE9392 /* SearchSettingsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B698A152B263BCE00DE9392 /* SearchSettingsModel.swift */; }; 5C4BB1E128212B1E00A92FB2 /* World.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C4BB1E028212B1E00A92FB2 /* World.swift */; }; 610C0FDA2B44438F00A01CA7 /* WorkspaceDocument+FindAndReplace.swift in Sources */ = {isa = PBXBuildFile; fileRef = 610C0FD92B44438F00A01CA7 /* WorkspaceDocument+FindAndReplace.swift */; }; 611191FA2B08CC9000D4459B /* SearchIndexer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 611191F92B08CC9000D4459B /* SearchIndexer.swift */; }; @@ -805,6 +806,7 @@ 5B698A0C2B26327800DE9392 /* SearchSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchSettings.swift; sourceTree = ""; }; 5B698A0E2B2636A700DE9392 /* SearchSettingsIgnoreGlobPatternItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchSettingsIgnoreGlobPatternItemView.swift; sourceTree = ""; }; 5B698A122B2638ED00DE9392 /* SearchSettingsIgnoreGlobPatternAddView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchSettingsIgnoreGlobPatternAddView.swift; sourceTree = ""; }; + 5B698A152B263BCE00DE9392 /* SearchSettingsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchSettingsModel.swift; sourceTree = ""; }; 5C4BB1E028212B1E00A92FB2 /* World.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = World.swift; sourceTree = ""; }; 610C0FD92B44438F00A01CA7 /* WorkspaceDocument+FindAndReplace.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WorkspaceDocument+FindAndReplace.swift"; sourceTree = ""; }; 611191F92B08CC9000D4459B /* SearchIndexer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchIndexer.swift; sourceTree = ""; }; @@ -2279,6 +2281,7 @@ isa = PBXGroup; children = ( 5B698A0C2B26327800DE9392 /* SearchSettings.swift */, + 5B698A152B263BCE00DE9392 /* SearchSettingsModel.swift */, ); path = Models; sourceTree = ""; @@ -3491,6 +3494,7 @@ B607184C2B17E037009CDAB4 /* SourceControlStashChangesView.swift in Sources */, 6C14CEB32877A68F001468FE /* FindNavigatorMatchListCell.swift in Sources */, 20EBB501280C325D00F3A5DA /* FileInspectorView.swift in Sources */, + 5B698A162B263BCE00DE9392 /* SearchSettingsModel.swift in Sources */, 58822531292C280D00E83CDE /* View+isHovering.swift in Sources */, 587B9E9929301D8F00AC7927 /* GitChangedFile.swift in Sources */, 6C147C4B29A32A7B0089B630 /* Environment+SplitEditor.swift in Sources */, diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettings.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettings.swift index b48f04e2d3..0cc456acb2 100644 --- a/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettings.swift +++ b/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettings.swift @@ -19,10 +19,6 @@ extension SettingsData { .map { NSLocalizedString($0, comment: "") } } - var ignoreGlobPatterns: Array = [ - "**/node_modules", - "**/bower_components", - "**/*.code-search" - ] + var ignoreGlobPatterns: Array = [] } } diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettingsModel.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettingsModel.swift new file mode 100644 index 0000000000..38cc739a03 --- /dev/null +++ b/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettingsModel.swift @@ -0,0 +1,59 @@ +// +// SearchSettingsModel.swift +// CodeEdit +// +// Created by Esteban on 12/10/23. +// + +import SwiftUI + +/// The Search Settings View Model. Accessible via the singleton "``SearchSettings/shared``". +/// +/// **Usage:** +/// ```swift +/// @StateObject +/// private var searchSettigs: SearchSettingsModel = .shared +/// ``` +final class SearchSettingsModel: ObservableObject { + static let shared: SearchSettingsModel = .init() + + /// Default instance of the `FileManager` + private let filemanager = FileManager.default + + /// The base folder url `~/Library/Application Support/CodeEdit/` + private var baseURL: URL { + filemanager.homeDirectoryForCurrentUser.appendingPathComponent("Library/Application Support/CodeEdit") + } + + /// The URL of the `search` folder + internal var themesURL: URL { + baseURL.appendingPathComponent("search", isDirectory: true) + } + + /// The URL of the `Extensions` folder + internal var extensionsURL: URL { + baseURL.appendingPathComponent("Extensions", isDirectory: true) + } + + /// The URL of the `settings.json` file + internal var settingsURL: URL { + baseURL.appendingPathComponent("settings.json", isDirectory: true) + } + + /// The currently existent Search Ignore Glob Patterns. + @Published var ignoreGlobPatterns: Array { + didSet { + DispatchQueue.main.async { + Settings[\.search].ignoreGlobPatterns = self.ignoreGlobPatterns + } + } + } + + private init() { + self.ignoreGlobPatterns = [ + "**/node_modules", + "**/bower_components", + "**/*.code-search" + ] + } +} diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsIgnoreGlobPatternAddView.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsIgnoreGlobPatternAddView.swift index 7c498e5d94..ba5818bd21 100644 --- a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsIgnoreGlobPatternAddView.swift +++ b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsIgnoreGlobPatternAddView.swift @@ -11,12 +11,22 @@ struct SearchSettingsIgnoreGlobPatternAddView: View { @Environment(\.dismiss) var dismiss + @State private var globPattern: String = "" + @FocusState private var globPatternIsFocused: Bool + var body: some View { VStack(spacing: 0) { Form { Section { VStack(alignment: .leading, spacing: 0) { - Text("Add here!") + TextField( + "Glob Pattern", + text: $globPattern + ) + .focused($globPatternIsFocused) + .onSubmit { + print($globPattern) + } } } footer: { HStack { diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift index e6596d9494..d031e5eee3 100644 --- a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift +++ b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift @@ -11,7 +11,7 @@ struct SearchSettingsView: View { @AppSettings(\.search.ignoreGlobPatterns) var ignoreGlobPatterns - + @State private var addIgnoreGlobPatternPresented: Bool = false var body: some View { From 173ac215df5e647884ad8c8ab97631d7eb722a1b Mon Sep 17 00:00:00 2001 From: Esteban Borai Date: Sun, 10 Dec 2023 15:49:15 -0300 Subject: [PATCH 05/15] fix: method name --- .../Pages/SearchSettings/Models/SearchSettingsModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettingsModel.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettingsModel.swift index 38cc739a03..b811d371ac 100644 --- a/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettingsModel.swift +++ b/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettingsModel.swift @@ -26,7 +26,7 @@ final class SearchSettingsModel: ObservableObject { } /// The URL of the `search` folder - internal var themesURL: URL { + internal var searchURL: URL { baseURL.appendingPathComponent("search", isDirectory: true) } From 8ccc7ccd5760dcc8b338bf55aaff3e8d191d6c84 Mon Sep 17 00:00:00 2001 From: Esteban Borai Date: Wed, 13 Dec 2023 19:31:21 -0300 Subject: [PATCH 06/15] feat: use list to render values --- .../Models/SearchSettings.swift | 8 +- .../Models/SearchSettingsModel.swift | 8 +- .../SearchSettings/SearchSettingsView.swift | 78 +++++++++++++++---- 3 files changed, 70 insertions(+), 24 deletions(-) diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettings.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettings.swift index 0cc456acb2..fc0688bd7e 100644 --- a/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettings.swift +++ b/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettings.swift @@ -14,11 +14,15 @@ extension SettingsData { /// The search keys var searchKeys: [String] { [ - "Ignore Glob Patterns" + "Ignore Glob Patterns", + "Ignore Patterns" ] .map { NSLocalizedString($0, comment: "") } } - var ignoreGlobPatterns: Array = [] + /// List of Glob Patterns that determine which files or directories to ignore + var ignoreGlobPatterns: [String] = [ + "Testing" + ] } } diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettingsModel.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettingsModel.swift index b811d371ac..dc19a6140e 100644 --- a/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettingsModel.swift +++ b/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettingsModel.swift @@ -41,7 +41,7 @@ final class SearchSettingsModel: ObservableObject { } /// The currently existent Search Ignore Glob Patterns. - @Published var ignoreGlobPatterns: Array { + @Published var ignoreGlobPatterns: [String] { didSet { DispatchQueue.main.async { Settings[\.search].ignoreGlobPatterns = self.ignoreGlobPatterns @@ -50,10 +50,6 @@ final class SearchSettingsModel: ObservableObject { } private init() { - self.ignoreGlobPatterns = [ - "**/node_modules", - "**/bower_components", - "**/*.code-search" - ] + self.ignoreGlobPatterns = [] } } diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift index d031e5eee3..ab0bfa8a10 100644 --- a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift +++ b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift @@ -7,34 +7,80 @@ import SwiftUI +struct GlobPattern: Identifiable, Hashable { + /// Ephimeral UUID used to track its representation in the UI + let id = UUID() + + /// The Glob Pattern to render + var value: String +} + struct SearchSettingsView: View { @AppSettings(\.search.ignoreGlobPatterns) var ignoreGlobPatterns - @State private var addIgnoreGlobPatternPresented: Bool = false + @FocusState private var focusedField: String? + @State private var selection: Set = [] + + @State var globPatterns: [GlobPattern] = [] + + init() { + globPatterns = ignoreGlobPatterns.map { + GlobPattern(value: $0) + } + } + + func addIgnoreGlobPattern() { + globPatterns.append(.init(value: "")) + } var body: some View { SettingsForm { Section { - if $ignoreGlobPatterns.isEmpty { - Text("No ignore patterns") - .foregroundColor(.secondary) - .frame(maxWidth: .infinity, alignment: .center) - } else { - ForEach($ignoreGlobPatterns, id: \.self) { pattern in - SearchSettingsIgnoreGlobPatternItemView(globPattern: pattern) - } + List($globPatterns, id: \.self, selection: $selection) { $globPattern in + TextField("", text: $globPattern.value) + .focused($focusedField, equals: globPattern.id.uuidString) + .labelsHidden() + .onAppear { + if globPatterns.isEmpty { + addIgnoreGlobPattern() + } + } + .onSubmit { + if globPattern.value.isEmpty { + print("Remove \(globPattern)") + } else { + if globPattern == globPatterns.last { + addIgnoreGlobPattern() + } + } + } } - } footer: { - HStack { + .actionBar { + Button { + addIgnoreGlobPattern() + } label: { + Image(systemName: "plus") + } + Divider() + Button { + print("Remove") + } label: { + Image(systemName: "minus") + } + .disabled(ignoreGlobPatterns.isEmpty) Spacer() - Button("Add ignore glob pattern...") { addIgnoreGlobPatternPresented.toggle() } - .sheet(isPresented: $addIgnoreGlobPatternPresented, content: { - SearchSettingsIgnoreGlobPatternAddView() - }) + Button { + print("More") + } label: { + Image(systemName: "ellipsis.circle") + .font(.system(size: 13, weight: .medium)) + } + } + .onDeleteCommand { + print("Remove selection") } - .padding(.top, 10) } } } From b620b7f43ed19fe7ecfdd334c84771ed78707f8b Mon Sep 17 00:00:00 2001 From: Esteban Borai Date: Tue, 19 Dec 2023 22:06:17 -0300 Subject: [PATCH 07/15] feat: writing to sottings json --- .../Models/SearchSettings.swift | 18 +++++++-- .../Models/SearchSettingsModel.swift | 10 ++++- .../SearchSettings/SearchSettingsView.swift | 39 ++++++------------- 3 files changed, 36 insertions(+), 31 deletions(-) diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettings.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettings.swift index fc0688bd7e..b8f3935ed7 100644 --- a/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettings.swift +++ b/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettings.swift @@ -21,8 +21,20 @@ extension SettingsData { } /// List of Glob Patterns that determine which files or directories to ignore - var ignoreGlobPatterns: [String] = [ - "Testing" - ] + var ignoreGlobPatterns: [GlobPattern] = .init() + + /// Default initializer + init() {} + + /// Explicit decoder init for setting default values when key is not present in `JSON` + init(from decoder: Decoder) throws { + print("From decoder") + let container = try decoder.container(keyedBy: CodingKeys.self) + + self.ignoreGlobPatterns = try container.decodeIfPresent( + [GlobPattern].self, + forKey: .ignoreGlobPatterns + ) ?? [] + } } } diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettingsModel.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettingsModel.swift index dc19a6140e..dbbcff4e56 100644 --- a/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettingsModel.swift +++ b/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettingsModel.swift @@ -7,6 +7,14 @@ import SwiftUI +struct GlobPattern: Identifiable, Hashable, Decodable, Encodable { + /// Ephimeral UUID used to track its representation in the UI + var id = UUID() + + /// The Glob Pattern to render + var value: String +} + /// The Search Settings View Model. Accessible via the singleton "``SearchSettings/shared``". /// /// **Usage:** @@ -41,7 +49,7 @@ final class SearchSettingsModel: ObservableObject { } /// The currently existent Search Ignore Glob Patterns. - @Published var ignoreGlobPatterns: [String] { + @Published var ignoreGlobPatterns: [GlobPattern] { didSet { DispatchQueue.main.async { Settings[\.search].ignoreGlobPatterns = self.ignoreGlobPatterns diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift index ab0bfa8a10..45550b51f5 100644 --- a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift +++ b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift @@ -7,51 +7,36 @@ import SwiftUI -struct GlobPattern: Identifiable, Hashable { - /// Ephimeral UUID used to track its representation in the UI - let id = UUID() - - /// The Glob Pattern to render - var value: String -} - struct SearchSettingsView: View { - @AppSettings(\.search.ignoreGlobPatterns) - var ignoreGlobPatterns + @ObservedObject private var searchSettingsModel: SearchSettingsModel = .shared @FocusState private var focusedField: String? @State private var selection: Set = [] - @State var globPatterns: [GlobPattern] = [] - - init() { - globPatterns = ignoreGlobPatterns.map { - GlobPattern(value: $0) - } - } - func addIgnoreGlobPattern() { - globPatterns.append(.init(value: "")) + searchSettingsModel.ignoreGlobPatterns.append(GlobPattern(value: "")) } var body: some View { SettingsForm { Section { - List($globPatterns, id: \.self, selection: $selection) { $globPattern in - TextField("", text: $globPattern.value) - .focused($focusedField, equals: globPattern.id.uuidString) + List($searchSettingsModel.ignoreGlobPatterns, selection: $selection) { ignorePattern in + TextField("", text: ignorePattern.value) + .disableAutocorrection(true) + .autocorrectionDisabled() + .focused($focusedField, equals: ignorePattern.id.uuidString) .labelsHidden() .onAppear { - if globPatterns.isEmpty { + if $searchSettingsModel.ignoreGlobPatterns.isEmpty { addIgnoreGlobPattern() } } .onSubmit { - if globPattern.value.isEmpty { - print("Remove \(globPattern)") + if $searchSettingsModel.ignoreGlobPatterns.isEmpty { + print("Remove \(ignorePattern)") } else { - if globPattern == globPatterns.last { + if ignorePattern.id == $searchSettingsModel.ignoreGlobPatterns.last?.id { addIgnoreGlobPattern() } } @@ -69,7 +54,7 @@ struct SearchSettingsView: View { } label: { Image(systemName: "minus") } - .disabled(ignoreGlobPatterns.isEmpty) + .disabled($searchSettingsModel.ignoreGlobPatterns.isEmpty) Spacer() Button { print("More") From 9f4ea450f3cce30b19b37f9f82123888a4b1f389 Mon Sep 17 00:00:00 2001 From: Esteban Borai Date: Fri, 22 Dec 2023 19:53:20 -0300 Subject: [PATCH 08/15] feat: persist settings and load from settings --- .../Pages/SearchSettings/Models/SearchSettings.swift | 1 - .../Pages/SearchSettings/Models/SearchSettingsModel.swift | 8 ++++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettings.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettings.swift index b8f3935ed7..87da440f28 100644 --- a/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettings.swift +++ b/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettings.swift @@ -28,7 +28,6 @@ extension SettingsData { /// Explicit decoder init for setting default values when key is not present in `JSON` init(from decoder: Decoder) throws { - print("From decoder") let container = try decoder.container(keyedBy: CodingKeys.self) self.ignoreGlobPatterns = try container.decodeIfPresent( diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettingsModel.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettingsModel.swift index dbbcff4e56..05f52df179 100644 --- a/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettingsModel.swift +++ b/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettingsModel.swift @@ -48,7 +48,8 @@ final class SearchSettingsModel: ObservableObject { baseURL.appendingPathComponent("settings.json", isDirectory: true) } - /// The currently existent Search Ignore Glob Patterns. + /// Stores the new values from the Search Settings Model into the settings.json whenever + /// `ignoreGlobPatterns` is updated @Published var ignoreGlobPatterns: [GlobPattern] { didSet { DispatchQueue.main.async { @@ -57,7 +58,10 @@ final class SearchSettingsModel: ObservableObject { } } + /// Reads settings file for Search Settings and updates the values in this model + /// correspondingly private init() { - self.ignoreGlobPatterns = [] + let value = Settings[\.search].ignoreGlobPatterns + self.ignoreGlobPatterns = value } } From 1e7d1bd18f5bad97f808ab7a78ede73131ebc8a0 Mon Sep 17 00:00:00 2001 From: Esteban Borai Date: Sun, 24 Dec 2023 16:00:53 -0300 Subject: [PATCH 09/15] feat: capability to remove selection --- .../Pages/SearchSettings/SearchSettingsView.swift | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift index 45550b51f5..de72c16094 100644 --- a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift +++ b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift @@ -12,12 +12,18 @@ struct SearchSettingsView: View { @ObservedObject private var searchSettingsModel: SearchSettingsModel = .shared @FocusState private var focusedField: String? - @State private var selection: Set = [] + @State private var selection: Set = [] func addIgnoreGlobPattern() { searchSettingsModel.ignoreGlobPatterns.append(GlobPattern(value: "")) } + func removeSelection(_ selection: Set) { + searchSettingsModel.ignoreGlobPatterns.removeAll { + selection.contains($0) + } + } + var body: some View { SettingsForm { Section { @@ -50,7 +56,7 @@ struct SearchSettingsView: View { } Divider() Button { - print("Remove") + removeSelection(selection) } label: { Image(systemName: "minus") } @@ -64,7 +70,7 @@ struct SearchSettingsView: View { } } .onDeleteCommand { - print("Remove selection") + removeSelection(selection) } } } From d598ce5e8e290889b27e35e0c0bde88bf4322b0d Mon Sep 17 00:00:00 2001 From: Esteban Borai Date: Sat, 13 Jan 2024 11:33:59 -0300 Subject: [PATCH 10/15] fix: editable table lines --- .../SearchSettings/SearchSettingsView.swift | 201 ++++++++++++++---- 1 file changed, 156 insertions(+), 45 deletions(-) diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift index de72c16094..95830dabfc 100644 --- a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift +++ b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift @@ -8,71 +8,182 @@ import SwiftUI struct SearchSettingsView: View { + var body: some View { + SettingsForm { + Section { + ExcludedGlobPatternList() + } header: { + Text("Exclude") + Text( + "Add glob patterns to exclude matching files and folders from searches and open quickly. " + + "This will inherit glob patterns from the Exclude from Project setting." + ) + } + } + } +} +struct ExcludedGlobPatternList: View { @ObservedObject private var searchSettingsModel: SearchSettingsModel = .shared @FocusState private var focusedField: String? - @State private var selection: Set = [] - func addIgnoreGlobPattern() { + @State private var selection: GlobPattern? + + func addPattern() { searchSettingsModel.ignoreGlobPatterns.append(GlobPattern(value: "")) } - func removeSelection(_ selection: Set) { + func removePattern(_ pattern: GlobPattern?) { + let selectedIndex = searchSettingsModel.ignoreGlobPatterns.firstIndex { + $0 == selection + } + + let removeIndex = searchSettingsModel.ignoreGlobPatterns.firstIndex { + $0 == selection + } + searchSettingsModel.ignoreGlobPatterns.removeAll { - selection.contains($0) + pattern == $0 + } + + if selectedIndex == removeIndex && !searchSettingsModel.ignoreGlobPatterns.isEmpty && selectedIndex != nil { + selection = searchSettingsModel.ignoreGlobPatterns[ + selectedIndex == 0 ? 0 : (selectedIndex ?? 1) - 1 + ] } } var body: some View { - SettingsForm { - Section { - List($searchSettingsModel.ignoreGlobPatterns, selection: $selection) { ignorePattern in - TextField("", text: ignorePattern.value) - .disableAutocorrection(true) - .autocorrectionDisabled() - .focused($focusedField, equals: ignorePattern.id.uuidString) - .labelsHidden() - .onAppear { - if $searchSettingsModel.ignoreGlobPatterns.isEmpty { - addIgnoreGlobPattern() - } - } - .onSubmit { - if $searchSettingsModel.ignoreGlobPatterns.isEmpty { - print("Remove \(ignorePattern)") - } else { - if ignorePattern.id == $searchSettingsModel.ignoreGlobPatterns.last?.id { - addIgnoreGlobPattern() - } - } - } + List(selection: $selection) { + ForEach( + Array(searchSettingsModel.ignoreGlobPatterns.enumerated()), + id: \.element + ) { index, ignorePattern in + IgnorePatternListItem( + pattern: $searchSettingsModel.ignoreGlobPatterns[index], + selectedPattern: $selection, + addPattern: addPattern, + removePattern: removePattern, + focusedField: $focusedField, + isLast: searchSettingsModel.ignoreGlobPatterns.count == index+1 + ) + .onAppear { + if ignorePattern.value.isEmpty { + focusedField = ignorePattern.id.uuidString + } } - .actionBar { - Button { - addIgnoreGlobPattern() - } label: { - Image(systemName: "plus") + + } + .onMove { fromOffsets, toOffset in + searchSettingsModel.ignoreGlobPatterns.move(fromOffsets: fromOffsets, toOffset: toOffset) + } + } + .frame(minHeight: 96) + + .contextMenu( + forSelectionType: GlobPattern.self, + menu: { selection in + if let pattern = selection.first { + Button("Edit") { + focusedField = pattern.id.uuidString } - Divider() - Button { - removeSelection(selection) - } label: { - Image(systemName: "minus") + Button("Add") { + addPattern() } - .disabled($searchSettingsModel.ignoreGlobPatterns.isEmpty) - Spacer() - Button { - print("More") - } label: { - Image(systemName: "ellipsis.circle") - .font(.system(size: 13, weight: .medium)) + Divider() + Button("Remove") { + removePattern(pattern) } } - .onDeleteCommand { - removeSelection(selection) + }, + primaryAction: { selection in + if let pattern = selection.first { + focusedField = pattern.id.uuidString + } + } + ) + .overlay { + if searchSettingsModel.ignoreGlobPatterns.isEmpty { + Text("No excluded glob patterns") + .foregroundStyle(Color(.secondaryLabelColor)) + } + } + .actionBar { + Button { + addPattern() + } label: { + Image(systemName: "plus") + } + Divider() + Button { + if let pattern = selection { + removePattern(pattern) } + } label: { + Image(systemName: "minus") } + .disabled(selection == nil) } + .onDeleteCommand { + removePattern(selection) + } + } +} + +struct IgnorePatternListItem: View { + @Binding var pattern: GlobPattern + @Binding var selectedPattern: GlobPattern? + var addPattern: () -> Void + var removePattern: (GlobPattern) -> Void + var focusedField: FocusState.Binding + var isLast: Bool + + @State var value: String + + @FocusState private var isFocused: Bool + + init( + pattern: Binding, + selectedPattern: Binding, + addPattern: @escaping () -> Void, + removePattern: @escaping (GlobPattern) -> Void, + focusedField: FocusState.Binding, + isLast: Bool + ) { + self._pattern = pattern + self._selectedPattern = selectedPattern + self.addPattern = addPattern + self.removePattern = removePattern + self.focusedField = focusedField + self.isLast = isLast + self._value = State(initialValue: pattern.wrappedValue.value) + } + + var body: some View { + TextField("", text: $value) + .focused(focusedField, equals: pattern.id.uuidString) + .focused($isFocused) + .disableAutocorrection(true) + .autocorrectionDisabled() + .labelsHidden() + .onSubmit { + if !value.isEmpty && isLast { + addPattern() + } + } + .onChange(of: isFocused) { newIsFocused in + if newIsFocused { + if selectedPattern != pattern { + selectedPattern = pattern + } + } else { + if value.isEmpty { + removePattern(pattern) + } else { + pattern.value = value + } + } + } } } From 4a7ac2454cd57b0fc5107f63cbbc5ed250eb8c72 Mon Sep 17 00:00:00 2001 From: Esteban Borai Date: Sat, 13 Jan 2024 11:36:03 -0300 Subject: [PATCH 11/15] fix: fmt --- .../Settings/Pages/SearchSettings/SearchSettingsView.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift index 95830dabfc..e05e1bec91 100644 --- a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift +++ b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift @@ -73,7 +73,6 @@ struct ExcludedGlobPatternList: View { focusedField = ignorePattern.id.uuidString } } - } .onMove { fromOffsets, toOffset in searchSettingsModel.ignoreGlobPatterns.move(fromOffsets: fromOffsets, toOffset: toOffset) From f7933b6d324269fed4cb5037177c4e272304d5e1 Mon Sep 17 00:00:00 2001 From: Esteban Borai Date: Tue, 30 Jan 2024 23:02:26 -0300 Subject: [PATCH 12/15] feat: check list size before removing --- .../Settings/Pages/SearchSettings/SearchSettingsView.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift index e05e1bec91..2042ebeb39 100644 --- a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift +++ b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift @@ -92,7 +92,9 @@ struct ExcludedGlobPatternList: View { } Divider() Button("Remove") { - removePattern(pattern) + if !searchSettingsModel.ignoreGlobPatterns.isEmpty { + removePattern(pattern) + } } } }, From 10fdc181853f6c8f8b0c856dbb39554ee5986879 Mon Sep 17 00:00:00 2001 From: Esteban Borai Date: Fri, 2 Feb 2024 23:25:02 -0300 Subject: [PATCH 13/15] Update CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettings.swift Co-authored-by: Tom Ludwig --- .../Settings/Pages/SearchSettings/Models/SearchSettings.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettings.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettings.swift index 87da440f28..6510d418c0 100644 --- a/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettings.swift +++ b/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettings.swift @@ -8,7 +8,6 @@ import Foundation extension SettingsData { - struct SearchSettings: Codable, Hashable, SearchableSettingsPage { /// The search keys From c8b37b195e7d06b33852ef9e83cc65cbf85b186d Mon Sep 17 00:00:00 2001 From: Esteban Borai Date: Fri, 2 Feb 2024 23:34:46 -0300 Subject: [PATCH 14/15] fix: pr review items --- CodeEdit.xcodeproj/project.pbxproj | 8 +- .../IgnorePatternListItemView.swift | 65 +++++++++++++ .../Models/SearchSettingsModel.swift | 14 +-- ...archSettingsIgnoreGlobPatternAddView.swift | 51 ---------- .../SearchSettings/SearchSettingsView.swift | 93 ++++--------------- 5 files changed, 94 insertions(+), 137 deletions(-) create mode 100644 CodeEdit/Features/Settings/Pages/SearchSettings/IgnorePatternListItemView.swift delete mode 100644 CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsIgnoreGlobPatternAddView.swift diff --git a/CodeEdit.xcodeproj/project.pbxproj b/CodeEdit.xcodeproj/project.pbxproj index 841c6c005d..a8935fa35c 100644 --- a/CodeEdit.xcodeproj/project.pbxproj +++ b/CodeEdit.xcodeproj/project.pbxproj @@ -247,10 +247,10 @@ 58F2EB1E292FB954004A9BDE /* Sparkle in Frameworks */ = {isa = PBXBuildFile; productRef = 58F2EB1D292FB954004A9BDE /* Sparkle */; }; 58FD7608291EA1CB0051D6E4 /* CommandPaletteViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58FD7605291EA1CB0051D6E4 /* CommandPaletteViewModel.swift */; }; 58FD7609291EA1CB0051D6E4 /* CommandPaletteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58FD7607291EA1CB0051D6E4 /* CommandPaletteView.swift */; }; + 5B241BF32B6DDBFF0016E616 /* IgnorePatternListItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B241BF22B6DDBFF0016E616 /* IgnorePatternListItemView.swift */; }; 5B698A0A2B262FA000DE9392 /* SearchSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B698A092B262FA000DE9392 /* SearchSettingsView.swift */; }; 5B698A0D2B26327800DE9392 /* SearchSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B698A0C2B26327800DE9392 /* SearchSettings.swift */; }; 5B698A0F2B2636A700DE9392 /* SearchSettingsIgnoreGlobPatternItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B698A0E2B2636A700DE9392 /* SearchSettingsIgnoreGlobPatternItemView.swift */; }; - 5B698A132B2638ED00DE9392 /* SearchSettingsIgnoreGlobPatternAddView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B698A122B2638ED00DE9392 /* SearchSettingsIgnoreGlobPatternAddView.swift */; }; 5B698A162B263BCE00DE9392 /* SearchSettingsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B698A152B263BCE00DE9392 /* SearchSettingsModel.swift */; }; 5C4BB1E128212B1E00A92FB2 /* World.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C4BB1E028212B1E00A92FB2 /* World.swift */; }; 610C0FDA2B44438F00A01CA7 /* WorkspaceDocument+FindAndReplace.swift in Sources */ = {isa = PBXBuildFile; fileRef = 610C0FD92B44438F00A01CA7 /* WorkspaceDocument+FindAndReplace.swift */; }; @@ -802,10 +802,10 @@ 58F2EAE1292FB2B0004A9BDE /* SoftwareUpdater.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SoftwareUpdater.swift; sourceTree = ""; }; 58FD7605291EA1CB0051D6E4 /* CommandPaletteViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommandPaletteViewModel.swift; sourceTree = ""; }; 58FD7607291EA1CB0051D6E4 /* CommandPaletteView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommandPaletteView.swift; sourceTree = ""; }; + 5B241BF22B6DDBFF0016E616 /* IgnorePatternListItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IgnorePatternListItemView.swift; sourceTree = ""; }; 5B698A092B262FA000DE9392 /* SearchSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchSettingsView.swift; sourceTree = ""; }; 5B698A0C2B26327800DE9392 /* SearchSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchSettings.swift; sourceTree = ""; }; 5B698A0E2B2636A700DE9392 /* SearchSettingsIgnoreGlobPatternItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchSettingsIgnoreGlobPatternItemView.swift; sourceTree = ""; }; - 5B698A122B2638ED00DE9392 /* SearchSettingsIgnoreGlobPatternAddView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchSettingsIgnoreGlobPatternAddView.swift; sourceTree = ""; }; 5B698A152B263BCE00DE9392 /* SearchSettingsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchSettingsModel.swift; sourceTree = ""; }; 5C4BB1E028212B1E00A92FB2 /* World.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = World.swift; sourceTree = ""; }; 610C0FD92B44438F00A01CA7 /* WorkspaceDocument+FindAndReplace.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WorkspaceDocument+FindAndReplace.swift"; sourceTree = ""; }; @@ -2271,8 +2271,8 @@ children = ( 5B698A0B2B26326000DE9392 /* Models */, 5B698A092B262FA000DE9392 /* SearchSettingsView.swift */, + 5B241BF22B6DDBFF0016E616 /* IgnorePatternListItemView.swift */, 5B698A0E2B2636A700DE9392 /* SearchSettingsIgnoreGlobPatternItemView.swift */, - 5B698A122B2638ED00DE9392 /* SearchSettingsIgnoreGlobPatternAddView.swift */, ); path = SearchSettings; sourceTree = ""; @@ -3249,7 +3249,6 @@ 587B9E9229301D8F00AC7927 /* BitBucketAccount.swift in Sources */, DE513F52281B672D002260B9 /* EditorTabBarAccessory.swift in Sources */, 2813F93927ECC4C300E305E4 /* NavigatorAreaView.swift in Sources */, - 5B698A132B2638ED00DE9392 /* SearchSettingsIgnoreGlobPatternAddView.swift in Sources */, 5B698A0F2B2636A700DE9392 /* SearchSettingsIgnoreGlobPatternItemView.swift in Sources */, 587B9E8A29301D8F00AC7927 /* GitHubIssue.swift in Sources */, EC0870F72A455F6400EB8692 /* ProjectNavigatorViewController+NSMenuDelegate.swift in Sources */, @@ -3627,6 +3626,7 @@ 611192002B08CCD700D4459B /* SearchIndexer+Memory.swift in Sources */, 587B9E8129301D8F00AC7927 /* PublicKey.swift in Sources */, 611191FE2B08CCD200D4459B /* SearchIndexer+File.swift in Sources */, + 5B241BF32B6DDBFF0016E616 /* IgnorePatternListItemView.swift in Sources */, 6CB52DC92AC8DC3E002E75B3 /* CEWorkspaceFileManager+FileManagement.swift in Sources */, 58F2EB0B292FB2B0004A9BDE /* AccountsSettings.swift in Sources */, 5882252A292C280D00E83CDE /* StatusBarToggleUtilityAreaButton.swift in Sources */, diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/IgnorePatternListItemView.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/IgnorePatternListItemView.swift new file mode 100644 index 0000000000..0ba3f4ffdc --- /dev/null +++ b/CodeEdit/Features/Settings/Pages/SearchSettings/IgnorePatternListItemView.swift @@ -0,0 +1,65 @@ +// +// IgnorePatternListItemView.swift +// CodeEdit +// +// Created by Esteban on 2/2/24. +// + +import SwiftUI + +struct IgnorePatternListItem: View { + @Binding var pattern: GlobPattern + @Binding var selectedPattern: GlobPattern? + var addPattern: () -> Void + var removePattern: (GlobPattern) -> Void + var focusedField: FocusState.Binding + var isLast: Bool + + @State var value: String + + @FocusState private var isFocused: Bool + + init( + pattern: Binding, + selectedPattern: Binding, + addPattern: @escaping () -> Void, + removePattern: @escaping (GlobPattern) -> Void, + focusedField: FocusState.Binding, + isLast: Bool + ) { + self._pattern = pattern + self._selectedPattern = selectedPattern + self.addPattern = addPattern + self.removePattern = removePattern + self.focusedField = focusedField + self.isLast = isLast + self._value = State(initialValue: pattern.wrappedValue.value) + } + + var body: some View { + TextField("", text: $value) + .focused(focusedField, equals: pattern.id.uuidString) + .focused($isFocused) + .disableAutocorrection(true) + .autocorrectionDisabled() + .labelsHidden() + .onSubmit { + if !value.isEmpty && isLast { + addPattern() + } + } + .onChange(of: isFocused) { newIsFocused in + if newIsFocused { + if selectedPattern != pattern { + selectedPattern = pattern + } + } else { + if value.isEmpty { + removePattern(pattern) + } else { + pattern.value = value + } + } + } + } +} diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettingsModel.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettingsModel.swift index 05f52df179..9bd6cd8311 100644 --- a/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettingsModel.swift +++ b/CodeEdit/Features/Settings/Pages/SearchSettings/Models/SearchSettingsModel.swift @@ -23,6 +23,13 @@ struct GlobPattern: Identifiable, Hashable, Decodable, Encodable { /// private var searchSettigs: SearchSettingsModel = .shared /// ``` final class SearchSettingsModel: ObservableObject { + /// Reads settings file for Search Settings and updates the values in this model + /// correspondingly + private init() { + let value = Settings[\.search].ignoreGlobPatterns + self.ignoreGlobPatterns = value + } + static let shared: SearchSettingsModel = .init() /// Default instance of the `FileManager` @@ -57,11 +64,4 @@ final class SearchSettingsModel: ObservableObject { } } } - - /// Reads settings file for Search Settings and updates the values in this model - /// correspondingly - private init() { - let value = Settings[\.search].ignoreGlobPatterns - self.ignoreGlobPatterns = value - } } diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsIgnoreGlobPatternAddView.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsIgnoreGlobPatternAddView.swift deleted file mode 100644 index ba5818bd21..0000000000 --- a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsIgnoreGlobPatternAddView.swift +++ /dev/null @@ -1,51 +0,0 @@ -// -// SearchSettingsIgnoreGlobPatternAddView.swift -// CodeEdit -// -// Created by Esteban on 12/10/23. -// - -import SwiftUI - -struct SearchSettingsIgnoreGlobPatternAddView: View { - @Environment(\.dismiss) - var dismiss - - @State private var globPattern: String = "" - @FocusState private var globPatternIsFocused: Bool - - var body: some View { - VStack(spacing: 0) { - Form { - Section { - VStack(alignment: .leading, spacing: 0) { - TextField( - "Glob Pattern", - text: $globPattern - ) - .focused($globPatternIsFocused) - .onSubmit { - print($globPattern) - } - } - } footer: { - HStack { - Spacer() - Button { - dismiss() - } label: { - Text("Cancel") - .padding(.horizontal) - } - .buttonStyle(.borderedProminent) - .controlSize(.large) - } - .padding(.top, 10) - } - } - .formStyle(.grouped) - .scrollDisabled(true) - } - .frame(width: 300) - } -} diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift index 2042ebeb39..d721fa86e1 100644 --- a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift +++ b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift @@ -30,30 +30,6 @@ struct ExcludedGlobPatternList: View { @State private var selection: GlobPattern? - func addPattern() { - searchSettingsModel.ignoreGlobPatterns.append(GlobPattern(value: "")) - } - - func removePattern(_ pattern: GlobPattern?) { - let selectedIndex = searchSettingsModel.ignoreGlobPatterns.firstIndex { - $0 == selection - } - - let removeIndex = searchSettingsModel.ignoreGlobPatterns.firstIndex { - $0 == selection - } - - searchSettingsModel.ignoreGlobPatterns.removeAll { - pattern == $0 - } - - if selectedIndex == removeIndex && !searchSettingsModel.ignoreGlobPatterns.isEmpty && selectedIndex != nil { - selection = searchSettingsModel.ignoreGlobPatterns[ - selectedIndex == 0 ? 0 : (selectedIndex ?? 1) - 1 - ] - } - } - var body: some View { List(selection: $selection) { ForEach( @@ -130,61 +106,28 @@ struct ExcludedGlobPatternList: View { removePattern(selection) } } -} -struct IgnorePatternListItem: View { - @Binding var pattern: GlobPattern - @Binding var selectedPattern: GlobPattern? - var addPattern: () -> Void - var removePattern: (GlobPattern) -> Void - var focusedField: FocusState.Binding - var isLast: Bool + func addPattern() { + searchSettingsModel.ignoreGlobPatterns.append(GlobPattern(value: "")) + } - @State var value: String + func removePattern(_ pattern: GlobPattern?) { + let selectedIndex = searchSettingsModel.ignoreGlobPatterns.firstIndex { + $0 == selection + } - @FocusState private var isFocused: Bool + let removeIndex = searchSettingsModel.ignoreGlobPatterns.firstIndex { + $0 == selection + } - init( - pattern: Binding, - selectedPattern: Binding, - addPattern: @escaping () -> Void, - removePattern: @escaping (GlobPattern) -> Void, - focusedField: FocusState.Binding, - isLast: Bool - ) { - self._pattern = pattern - self._selectedPattern = selectedPattern - self.addPattern = addPattern - self.removePattern = removePattern - self.focusedField = focusedField - self.isLast = isLast - self._value = State(initialValue: pattern.wrappedValue.value) - } + searchSettingsModel.ignoreGlobPatterns.removeAll { + pattern == $0 + } - var body: some View { - TextField("", text: $value) - .focused(focusedField, equals: pattern.id.uuidString) - .focused($isFocused) - .disableAutocorrection(true) - .autocorrectionDisabled() - .labelsHidden() - .onSubmit { - if !value.isEmpty && isLast { - addPattern() - } - } - .onChange(of: isFocused) { newIsFocused in - if newIsFocused { - if selectedPattern != pattern { - selectedPattern = pattern - } - } else { - if value.isEmpty { - removePattern(pattern) - } else { - pattern.value = value - } - } - } + if selectedIndex == removeIndex && !searchSettingsModel.ignoreGlobPatterns.isEmpty && selectedIndex != nil { + selection = searchSettingsModel.ignoreGlobPatterns[ + selectedIndex == 0 ? 0 : (selectedIndex ?? 1) - 1 + ] + } } } From d5391e96fdafac7bae996d4de0c2a3421036edc9 Mon Sep 17 00:00:00 2001 From: Esteban Borai Date: Fri, 2 Feb 2024 23:35:31 -0300 Subject: [PATCH 15/15] Update CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift Co-authored-by: Tom Ludwig --- .../Settings/Pages/SearchSettings/SearchSettingsView.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift index d721fa86e1..cebc9f65c2 100644 --- a/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift +++ b/CodeEdit/Features/Settings/Pages/SearchSettings/SearchSettingsView.swift @@ -55,7 +55,6 @@ struct ExcludedGlobPatternList: View { } } .frame(minHeight: 96) - .contextMenu( forSelectionType: GlobPattern.self, menu: { selection in