Skip to content

Commit 2981547

Browse files
Source Control Filter (#2024)
### Description Adding the ability to filter the project navigator by items that have a source control status. <!--- REQUIRED: Describe what changed in detail --> <!--- REQUIRED: Tag all related issues (e.g. * #123) --> <!--- If this PR resolves the issue please specify (e.g. * closes #123) --> <!--- If this PR addresses multiple issues, these issues must be related to one other --> <!--- * #ISSUE_NUMBER --> ### Checklist <!--- Add things that are not yet implemented above --> - [x] I read and understood the [contributing guide](https://github.com/CodeEditApp/CodeEdit/blob/main/CONTRIBUTING.md) as well as the [code of conduct](https://github.com/CodeEditApp/CodeEdit/blob/main/CODE_OF_CONDUCT.md) - [x] The issues this PR addresses are related to each other - [x] My changes generate no new warnings - [x] My code builds and runs on my machine - [x] My changes are all related to the related issue above - [x] I documented my code ### Screenshots https://github.com/user-attachments/assets/2a5cb5a9-d4f0-42ff-9f61-2a7b3260ee5a
1 parent e45d7f2 commit 2981547

File tree

5 files changed

+33
-13
lines changed

5 files changed

+33
-13
lines changed

CodeEdit/Features/Documents/WorkspaceDocument/WorkspaceDocument.swift

+2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ final class WorkspaceDocument: NSDocument, ObservableObject, NSToolbarDelegate {
1616
@Published var sortFoldersOnTop: Bool = true
1717
/// A string used to filter the displayed files and folders in the project navigator area based on user input.
1818
@Published var navigatorFilter: String = ""
19+
/// Whether the workspace only shows files with changes.
20+
@Published var sourceControlFilter = false
1921

2022
private var workspaceState: [String: Any] {
2123
get {

CodeEdit/Features/NavigatorArea/ProjectNavigator/OutlineView/ProjectNavigatorOutlineView.swift

+4
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ struct ProjectNavigatorOutlineView: NSViewControllerRepresentable {
6767
.throttle(for: 0.1, scheduler: RunLoop.main, latest: true)
6868
.sink { [weak self] _ in self?.controller?.handleFilterChange() }
6969
.store(in: &cancellables)
70+
workspace.$sourceControlFilter
71+
.throttle(for: 0.1, scheduler: RunLoop.main, latest: true)
72+
.sink { [weak self] _ in self?.controller?.handleFilterChange() }
73+
.store(in: &cancellables)
7074
}
7175

7276
var cancellables: Set<AnyCancellable> = []

CodeEdit/Features/NavigatorArea/ProjectNavigator/OutlineView/ProjectNavigatorViewController+NSOutlineViewDataSource.swift

+5-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@ extension ProjectNavigatorViewController: NSOutlineViewDataSource {
1515
}
1616

1717
if let children = workspace?.workspaceFileManager?.childrenOfFile(item) {
18-
if let filter = workspace?.navigatorFilter, !filter.isEmpty {
19-
let filteredChildren = children.filter { fileSearchMatches(filter, for: $0) }
18+
if let filter = workspace?.navigatorFilter, let sourceControlFilter = workspace?.sourceControlFilter,
19+
!filter.isEmpty || sourceControlFilter {
20+
let filteredChildren = children.filter {
21+
fileSearchMatches(filter, for: $0, sourceControlFilter: sourceControlFilter)
22+
}
2023
filteredContentChildren[item] = filteredChildren
2124
return filteredChildren
2225
}

CodeEdit/Features/NavigatorArea/ProjectNavigator/OutlineView/ProjectNavigatorViewController.swift

+20-8
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ final class ProjectNavigatorViewController: NSViewController {
6464
/// to open the file a second time.
6565
var shouldSendSelectionUpdate: Bool = true
6666

67+
var filterIsEmpty: Bool {
68+
workspace?.navigatorFilter.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == true
69+
}
70+
6771
/// Setup the ``scrollView`` and ``outlineView``
6872
override func loadView() {
6973
self.scrollView = NSScrollView()
@@ -193,13 +197,13 @@ final class ProjectNavigatorViewController: NSViewController {
193197
guard let workspace else { return }
194198

195199
/// If the filter is empty, show all items and restore the expanded state.
196-
if workspace.navigatorFilter.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
197-
restoreExpandedState()
198-
outlineView.autosaveExpandedItems = true
199-
} else {
200+
if workspace.sourceControlFilter || !filterIsEmpty {
200201
outlineView.autosaveExpandedItems = false
201202
/// Expand all items for search.
202203
outlineView.expandItem(outlineView.item(atRow: 0), expandChildren: true)
204+
} else {
205+
restoreExpandedState()
206+
outlineView.autosaveExpandedItems = true
203207
}
204208

205209
if let root = content.first(where: { $0.isRoot }), let children = filteredContentChildren[root] {
@@ -213,16 +217,24 @@ final class ProjectNavigatorViewController: NSViewController {
213217
}
214218

215219
/// Checks if the given filter matches the name of the item or any of its children.
216-
func fileSearchMatches(_ filter: String, for item: CEWorkspaceFile) -> Bool {
217-
guard !filter.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else { return true }
220+
func fileSearchMatches(_ filter: String, for item: CEWorkspaceFile, sourceControlFilter: Bool) -> Bool {
221+
guard !filterIsEmpty || sourceControlFilter else {
222+
return true
223+
}
218224

219-
if item.name.localizedLowercase.contains(filter.localizedLowercase) {
225+
if sourceControlFilter {
226+
if item.gitStatus != nil && item.gitStatus != GitStatus.none &&
227+
(filterIsEmpty || item.name.localizedCaseInsensitiveContains(filter)) {
228+
saveAllContentChildren(for: item)
229+
return true
230+
}
231+
} else if item.name.localizedCaseInsensitiveContains(filter) {
220232
saveAllContentChildren(for: item)
221233
return true
222234
}
223235

224236
if let children = workspace?.workspaceFileManager?.childrenOfFile(item) {
225-
return children.contains { fileSearchMatches(filter, for: $0) }
237+
return children.contains { fileSearchMatches(filter, for: $0, sourceControlFilter: sourceControlFilter) }
226238
}
227239

228240
return false

CodeEdit/Features/NavigatorArea/ProjectNavigator/ProjectNavigatorToolbarBottom.swift

+2-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ struct ProjectNavigatorToolbarBottom: View {
1818
@EnvironmentObject var editorManager: EditorManager
1919

2020
@State var recentsFilter: Bool = false
21-
@State var sourceControlFilter: Bool = false
2221

2322
var body: some View {
2423
HStack(spacing: 5) {
@@ -48,7 +47,7 @@ struct ProjectNavigatorToolbarBottom: View {
4847
Image(systemName: "clock")
4948
}
5049
.help("Show only recent files")
51-
Toggle(isOn: $sourceControlFilter) {
50+
Toggle(isOn: $workspace.sourceControlFilter) {
5251
Image(systemName: "plusminus.circle")
5352
}
5453
.help("Show only files with source-control status")
@@ -57,7 +56,7 @@ struct ProjectNavigatorToolbarBottom: View {
5756
.padding(.trailing, 2.5)
5857
},
5958
clearable: true,
60-
hasValue: !workspace.navigatorFilter.isEmpty || recentsFilter || sourceControlFilter
59+
hasValue: !workspace.navigatorFilter.isEmpty || recentsFilter || workspace.sourceControlFilter
6160
)
6261
}
6362
.padding(.horizontal, 5)

0 commit comments

Comments
 (0)