Skip to content

Commit 4d9a5d4

Browse files
Navigation style setting and file history navigation improvements (#1603)
* Added navigation style setting * Added navigation style setting * If one editors tab bar should be shown, all tab bars should be shown across other editors * Removed complete TODO comment * When there is only one tab in an editor and the navigation style changes to open in place, we change the tab to be termporary so that tab bar will hide * Invalidating flattenedEditors cache when editors change. * New editors open first tab as a temporary tab. * History improvements - if going back or forward in history to a file for a teb that was previously closed, we now open it as a temporary tab * Update CodeEditSourceEditor dependency version * Invalidating flattenedEditors cache when closing an editor * Removing last change * Fixed PR issue.
1 parent 7c773f9 commit 4d9a5d4

17 files changed

Lines changed: 259 additions & 58 deletions

File tree

CodeEdit.xcodeproj/project.pbxproj

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,8 @@
422422
B65B10FE2B08B07D002852CF /* SourceControlNavigatorChangesList.swift in Sources */ = {isa = PBXBuildFile; fileRef = B65B10FD2B08B07D002852CF /* SourceControlNavigatorChangesList.swift */; };
423423
B65B11012B09D5D4002852CF /* GitClient+Pull.swift in Sources */ = {isa = PBXBuildFile; fileRef = B65B11002B09D5D4002852CF /* GitClient+Pull.swift */; };
424424
B65B11042B09DB1C002852CF /* GitClient+Fetch.swift in Sources */ = {isa = PBXBuildFile; fileRef = B65B11032B09DB1C002852CF /* GitClient+Fetch.swift */; };
425+
B664C3B02B965F6C00816B4E /* NavigationSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = B664C3AF2B965F6C00816B4E /* NavigationSettings.swift */; };
426+
B664C3B32B96634F00816B4E /* NavigationSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B664C3B22B96634F00816B4E /* NavigationSettingsView.swift */; };
425427
B66A4E4529C8E86D004573B4 /* CommandsFixes.swift in Sources */ = {isa = PBXBuildFile; fileRef = B66A4E4429C8E86D004573B4 /* CommandsFixes.swift */; };
426428
B66A4E4C29C9179B004573B4 /* CodeEditApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = B66A4E4B29C9179B004573B4 /* CodeEditApp.swift */; };
427429
B66A4E4F29C917B8004573B4 /* WelcomeWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = B66A4E4E29C917B8004573B4 /* WelcomeWindow.swift */; };
@@ -953,6 +955,8 @@
953955
B65B10FD2B08B07D002852CF /* SourceControlNavigatorChangesList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceControlNavigatorChangesList.swift; sourceTree = "<group>"; };
954956
B65B11002B09D5D4002852CF /* GitClient+Pull.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "GitClient+Pull.swift"; sourceTree = "<group>"; };
955957
B65B11032B09DB1C002852CF /* GitClient+Fetch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "GitClient+Fetch.swift"; sourceTree = "<group>"; };
958+
B664C3AF2B965F6C00816B4E /* NavigationSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationSettings.swift; sourceTree = "<group>"; };
959+
B664C3B22B96634F00816B4E /* NavigationSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationSettingsView.swift; sourceTree = "<group>"; };
956960
B66A4E4429C8E86D004573B4 /* CommandsFixes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommandsFixes.swift; sourceTree = "<group>"; };
957961
B66A4E4B29C9179B004573B4 /* CodeEditApp.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CodeEditApp.swift; sourceTree = "<group>"; };
958962
B66A4E4E29C917B8004573B4 /* WelcomeWindow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WelcomeWindow.swift; sourceTree = "<group>"; };
@@ -1218,13 +1222,13 @@
12181222
287776EA27E350A100D46668 /* NavigatorArea */ = {
12191223
isa = PBXGroup;
12201224
children = (
1221-
307AC4CB2ABABD9800163376 /* ViewModels */,
12221225
D7012EE627E757660001E1EF /* FindNavigator */,
12231226
581550CB29FBD30400684881 /* OutlineView */,
12241227
286471AC27ED52950039369D /* ProjectNavigator */,
12251228
201169D52837B29600F92B46 /* SourceControlNavigator */,
12261229
B67660682AA972D400CD56B0 /* Models */,
12271230
B67660692AA972DC00CD56B0 /* Views */,
1231+
307AC4CB2ABABD9800163376 /* ViewModels */,
12281232
);
12291233
path = NavigatorArea;
12301234
sourceTree = "<group>";
@@ -2494,16 +2498,17 @@
24942498
B61DA9DD29D929BF00BF4A43 /* Pages */ = {
24952499
isa = PBXGroup;
24962500
children = (
2501+
B664C3AD2B965F4500816B4E /* NavigationSettings */,
2502+
B61DA9E129D929F900BF4A43 /* GeneralSettings */,
2503+
B6E41C6E29DD15540088F9F4 /* AccountsSettings */,
2504+
58F2EAAE292FB2B0004A9BDE /* ThemeSettings */,
2505+
B6EA1FF329DA37D3001BF195 /* TextEditingSettings */,
24972506
5B698A082B262F8400DE9392 /* SearchSettings */,
24982507
6C5BE51A2A3D5419002DA0FC /* FeatureFlags */,
24992508
B6CF632629E5417C0085880A /* Keybindings */,
2500-
B6E41C6E29DD15540088F9F4 /* AccountsSettings */,
2501-
B6EA1FF329DA37D3001BF195 /* TextEditingSettings */,
25022509
B6F0516E29D9E35300D72287 /* LocationsSettings */,
25032510
B6F0516D29D9E34200D72287 /* SourceControlSettings */,
25042511
B6F0516C29D9E32700D72287 /* TerminalSettings */,
2505-
58F2EAAE292FB2B0004A9BDE /* ThemeSettings */,
2506-
B61DA9E129D929F900BF4A43 /* GeneralSettings */,
25072512
);
25082513
path = Pages;
25092514
sourceTree = "<group>";
@@ -2604,6 +2609,23 @@
26042609
path = "Preview Content";
26052610
sourceTree = "<group>";
26062611
};
2612+
B664C3AD2B965F4500816B4E /* NavigationSettings */ = {
2613+
isa = PBXGroup;
2614+
children = (
2615+
B664C3AE2B965F5500816B4E /* Models */,
2616+
B664C3B22B96634F00816B4E /* NavigationSettingsView.swift */,
2617+
);
2618+
path = NavigationSettings;
2619+
sourceTree = "<group>";
2620+
};
2621+
B664C3AE2B965F5500816B4E /* Models */ = {
2622+
isa = PBXGroup;
2623+
children = (
2624+
B664C3AF2B965F6C00816B4E /* NavigationSettings.swift */,
2625+
);
2626+
path = Models;
2627+
sourceTree = "<group>";
2628+
};
26072629
B66DD19E2B3C0E0C0004FFEC /* History */ = {
26082630
isa = PBXGroup;
26092631
children = (
@@ -3215,6 +3237,7 @@
32153237
587B9E9229301D8F00AC7927 /* BitBucketAccount.swift in Sources */,
32163238
DE513F52281B672D002260B9 /* EditorTabBarAccessory.swift in Sources */,
32173239
2813F93927ECC4C300E305E4 /* NavigatorAreaView.swift in Sources */,
3240+
B664C3B02B965F6C00816B4E /* NavigationSettings.swift in Sources */,
32183241
5B698A0F2B2636A700DE9392 /* SearchSettingsIgnoreGlobPatternItemView.swift in Sources */,
32193242
587B9E8A29301D8F00AC7927 /* GitHubIssue.swift in Sources */,
32203243
EC0870F72A455F6400EB8692 /* ProjectNavigatorViewController+NSMenuDelegate.swift in Sources */,
@@ -3263,6 +3286,7 @@
32633286
611192042B08CCED00D4459B /* SearchIndexer+ProgressiveSearch.swift in Sources */,
32643287
611192022B08CCDC00D4459B /* SearchIndexer+Search.swift in Sources */,
32653288
04BA7C272AE2E9F100584E1C /* GitClient+Push.swift in Sources */,
3289+
B664C3B32B96634F00816B4E /* NavigationSettingsView.swift in Sources */,
32663290
2B7A583527E4BA0100D25D4E /* AppDelegate.swift in Sources */,
32673291
D7012EE827E757850001E1EF /* FindNavigatorView.swift in Sources */,
32683292
58A5DF8029325B5A00D1BD5D /* GitClient.swift in Sources */,
@@ -4593,7 +4617,7 @@
45934617
repositoryURL = "https://github.com/CodeEditApp/CodeEditSourceEditor";
45944618
requirement = {
45954619
kind = upToNextMajorVersion;
4596-
minimumVersion = 0.7.1;
4620+
minimumVersion = 0.7.2;
45974621
};
45984622
};
45994623
6CDEFC9429E22C2700B7C684 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */ = {

CodeEdit.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

CodeEdit/Features/CodeEditUI/Views/SegmentedControl.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ struct SegmentedControl: View {
3131
}
3232

3333
var body: some View {
34-
HStack(spacing: 8) {
34+
HStack(spacing: 4) {
3535
ForEach(options.indices, id: \.self) { index in
3636
SegmentedControlItem(
3737
label: options[index],

CodeEdit/Features/Editor/Models/Editor.swift

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@ final class Editor: ObservableObject, Identifiable {
4040
let tab = history[historyOffset]
4141

4242
if !tabs.contains(tab) {
43-
if let selectedTab {
44-
openTab(file: tab.file, at: tabs.firstIndex(of: selectedTab), fromHistory: true)
45-
} else {
46-
openTab(file: tab.file, fromHistory: true)
43+
if let temporaryTab, tabs.contains(temporaryTab) {
44+
closeTab(file: temporaryTab.file, fromHistory: true)
4745
}
46+
temporaryTab = tab
47+
openTab(file: tab.file, fromHistory: true)
4848
}
4949
selectedTab = tab
5050
}
@@ -64,29 +64,34 @@ final class Editor: ObservableObject, Identifiable {
6464

6565
init() {
6666
self.tabs = []
67+
self.temporaryTab = nil
6768
self.parent = nil
6869
}
6970

7071
init(
7172
files: OrderedSet<CEWorkspaceFile> = [],
7273
selectedTab: Tab? = nil,
74+
temporaryTab: Tab? = nil,
7375
parent: SplitViewData? = nil
7476
) {
7577
self.tabs = []
7678
self.parent = parent
7779
files.forEach { openTab(file: $0) }
7880
self.selectedTab = selectedTab ?? (files.isEmpty ? nil : Tab(file: files.first!))
81+
self.temporaryTab = temporaryTab
7982
}
8083

8184
init(
8285
files: OrderedSet<Tab> = [],
8386
selectedTab: Tab? = nil,
87+
temporaryTab: Tab? = nil,
8488
parent: SplitViewData? = nil
8589
) {
8690
self.tabs = []
8791
self.parent = parent
8892
files.forEach { openTab(file: $0.file) }
8993
self.selectedTab = selectedTab ?? tabs.first
94+
self.temporaryTab = temporaryTab
9095
}
9196

9297
/// Closes the editor.
@@ -102,14 +107,15 @@ final class Editor: ObservableObject, Identifiable {
102107
/// Closes a tab in the editor.
103108
/// This will also write any changes to the file on disk and will add the tab to the tab history.
104109
/// - Parameter item: the tab to close.
105-
func closeTab(file: CEWorkspaceFile) {
110+
func closeTab(file: CEWorkspaceFile, fromHistory: Bool = false) {
106111
guard canCloseTab(file: file) else { return }
107112

108113
if temporaryTab?.file == file {
109114
temporaryTab = nil
110115
}
111-
112-
historyOffset = 0
116+
if !fromHistory {
117+
historyOffset = 0
118+
}
113119
if file != selectedTab?.file {
114120
history.prepend(EditorInstance(file: file))
115121
}
@@ -149,7 +155,9 @@ final class Editor: ObservableObject, Identifiable {
149155
switch (temporaryTab, asTemporary) {
150156
case (.some(let tab), true):
151157
if let index = tabs.firstIndex(of: tab) {
158+
history.removeFirst(historyOffset)
152159
history.prepend(item)
160+
historyOffset = 0
153161
tabs.remove(tab)
154162
tabs.insert(item, at: index)
155163
self.selectedTab = item

CodeEdit/Features/Editor/Models/EditorLayout.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,24 @@ enum EditorLayout: Equatable {
8989
}
9090
}
9191

92+
/// Gets flattened splitviews.
93+
func getFlattened(parent: SplitViewData) -> [Editor] {
94+
switch self {
95+
case .one(let editor):
96+
return [editor]
97+
case .horizontal(let data), .vertical(let data):
98+
if data.editorLayouts.count == 1 {
99+
let one = data.editorLayouts[0]
100+
if case .one(let editor) = one {
101+
return [editor]
102+
}
103+
return []
104+
} else {
105+
return data.getFlattened()
106+
}
107+
}
108+
}
109+
92110
var isEmpty: Bool {
93111
switch self {
94112
case .one:

CodeEdit/Features/Editor/Models/EditorManager.swift

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,17 @@ class EditorManager: ObservableObject {
3636
var tabBarTabIdSubject = PassthroughSubject<String?, Never>()
3737
var cancellable: AnyCancellable?
3838

39+
// This caching mechanism is a temporary solution and is not optimized
40+
@Published var updateCachedFlattenedEditors: Bool = true
41+
var cachedFlettenedEditors: [Editor] = []
42+
var flattenedEditors: [Editor] {
43+
if updateCachedFlattenedEditors {
44+
cachedFlettenedEditors = self.getFlattened()
45+
updateCachedFlattenedEditors = false
46+
}
47+
return cachedFlettenedEditors
48+
}
49+
3950
// MARK: - Init
4051

4152
init() {
@@ -61,10 +72,21 @@ class EditorManager: ObservableObject {
6172

6273
/// Flattens the splitviews.
6374
func flatten() {
64-
if case .horizontal(let data) = editorLayout {
65-
data.flatten()
66-
} else if case .vertical(let data) = editorLayout {
75+
switch editorLayout {
76+
case .horizontal(let data), .vertical(let data):
6777
data.flatten()
78+
default:
79+
break
80+
}
81+
}
82+
83+
/// Returns and array of flattened splitviews.
84+
func getFlattened() -> [Editor] {
85+
switch editorLayout {
86+
case .horizontal(let data), .vertical(let data):
87+
return data.getFlattened()
88+
default:
89+
return []
6890
}
6991
}
7092

@@ -99,6 +121,7 @@ class EditorManager: ObservableObject {
99121

100122
flatten()
101123
objectWillChange.send()
124+
updateCachedFlattenedEditors = true
102125
}
103126

104127
/// Set a new active editor.

CodeEdit/Features/Editor/PathBar/Views/EditorPathBarView.swift

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import SwiftUI
99

1010
struct EditorPathBarView: View {
1111
private let file: CEWorkspaceFile?
12+
private let shouldShowTabBar: Bool
1213
private let tappedOpenFile: (CEWorkspaceFile) -> Void
1314

1415
@Environment(\.colorScheme)
@@ -20,13 +21,15 @@ struct EditorPathBarView: View {
2021
@Environment(\.controlActiveState)
2122
private var activeState
2223

23-
static let height = 27.0
24+
static let height = 28.0
2425

2526
init(
2627
file: CEWorkspaceFile?,
28+
shouldShowTabBar: Bool,
2729
tappedOpenFile: @escaping (CEWorkspaceFile) -> Void
2830
) {
2931
self.file = file ?? nil
32+
self.shouldShowTabBar = shouldShowTabBar
3033
self.tappedOpenFile = tappedOpenFile
3134
}
3235

@@ -63,7 +66,17 @@ struct EditorPathBarView: View {
6366
}
6467
}
6568
}
66-
.padding(.horizontal, 10)
69+
}
70+
.padding(.horizontal, shouldShowTabBar ? (file == nil ? 10 : 4) : 0)
71+
.safeAreaInset(edge: .leading, spacing: 0) {
72+
if !shouldShowTabBar {
73+
EditorTabBarLeadingAccessories()
74+
}
75+
}
76+
.safeAreaInset(edge: .trailing, spacing: 0) {
77+
if !shouldShowTabBar {
78+
EditorTabBarTrailingAccessories()
79+
}
6780
}
6881
.frame(height: Self.height, alignment: .center)
6982
.opacity(activeState == .inactive ? 0.8 : 1.0)

CodeEdit/Features/Editor/TabBar/Views/EditorTabBarLeadingAccessories.swift

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,9 @@ struct EditorTabBarLeadingAccessories: View {
7474
}
7575
} label: {
7676
Image(systemName: "chevron.left")
77-
.controlSize(.regular)
78-
.opacity(
79-
editor.historyOffset == editor.history.count-1 || editor.history.isEmpty
80-
? 0.5 : 1.0
81-
)
77+
.opacity(editor.historyOffset == editor.history.count-1 || editor.history.isEmpty ? 0.5 : 1)
78+
.frame(height: EditorTabBarView.height - 2)
79+
.padding(.horizontal, 4)
8280
} primaryAction: {
8381
editorManager.activeEditor = editor
8482
editor.goBackInHistory()
@@ -103,20 +101,19 @@ struct EditorTabBarLeadingAccessories: View {
103101
}
104102
} label: {
105103
Image(systemName: "chevron.right")
106-
.controlSize(.regular)
107-
.opacity(editor.historyOffset == 0 ? 0.5 : 1.0)
104+
.opacity(editor.historyOffset == 0 ? 0.5 : 1)
105+
.frame(height: EditorTabBarView.height - 2)
106+
.padding(.horizontal, 4)
108107
} primaryAction: {
109108
editorManager.activeEditor = editor
110109
editor.goForwardInHistory()
111110
}
112111
.disabled(editor.historyOffset == 0)
113112
.help("Navigate forward")
114113
}
114+
.buttonStyle(.icon)
115115
.controlSize(.small)
116116
.font(EditorTabBarAccessoryIcon.iconFont)
117-
.frame(height: EditorTabBarView.height - 2)
118-
.padding(.horizontal, 4)
119-
.contentShape(Rectangle())
120117
}
121118
.foregroundColor(.secondary)
122119
.buttonStyle(.plain)
@@ -136,9 +133,3 @@ struct EditorTabBarLeadingAccessories: View {
136133
}
137134
}
138135
}
139-
140-
struct TabBarLeadingAccessories_Previews: PreviewProvider {
141-
static var previews: some View {
142-
EditorTabBarLeadingAccessories()
143-
}
144-
}

CodeEdit/Features/Editor/TabBar/Views/EditorTabBarTrailingAccessories.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,12 @@ struct EditorTabBarTrailingAccessories: View {
6969
func split(edge: Edge) {
7070
let newEditor: Editor
7171
if let tab = editor.selectedTab {
72-
newEditor = .init(files: [tab])
72+
newEditor = .init(files: [tab], temporaryTab: tab)
7373
} else {
7474
newEditor = .init()
7575
}
7676
splitEditor(edge, newEditor)
77+
editorManager.updateCachedFlattenedEditors = true
7778
editorManager.activeEditor = newEditor
7879
}
7980
}

0 commit comments

Comments
 (0)