Skip to content

Commit 4624ede

Browse files
authored
Performance improvements for settings (#1250)
* Added fix, partially applied it Signed-off-by: Wouter01 <[email protected]> * Further conversion Signed-off-by: Wouter01 <[email protected]> * Further conversion Signed-off-by: Wouter01 <[email protected]> * Further conversion Signed-off-by: Wouter01 <[email protected]> * Fixed warning Signed-off-by: Wouter01 <[email protected]> * Added throttling to json saver Signed-off-by: Wouter01 <[email protected]> --------- Signed-off-by: Wouter01 <[email protected]>
1 parent e39baba commit 4624ede

File tree

47 files changed

+302
-242
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+302
-242
lines changed

CodeEdit.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@
297297
6CB9144B29BEC7F100BC47F2 /* (null) in Sources */ = {isa = PBXBuildFile; };
298298
6CBD1BC62978DE53006639D5 /* Font+Caption3.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CBD1BC52978DE53006639D5 /* Font+Caption3.swift */; };
299299
6CC9E4B229B5669900C97388 /* Environment+ActiveTabGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC9E4B129B5669900C97388 /* Environment+ActiveTabGroup.swift */; };
300+
6CD03B6A29FC773F001BD1D0 /* SettingsInjector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD03B6929FC773F001BD1D0 /* SettingsInjector.swift */; };
300301
6CDA84AD284C1BA000C1CC3A /* TabBarContextMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CDA84AC284C1BA000C1CC3A /* TabBarContextMenu.swift */; };
301302
6CDEFC9629E22C2700B7C684 /* Introspect in Frameworks */ = {isa = PBXBuildFile; productRef = 6CDEFC9529E22C2700B7C684 /* Introspect */; };
302303
6CFF967429BEBCC300182D6F /* FindCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CFF967329BEBCC300182D6F /* FindCommands.swift */; };
@@ -697,6 +698,7 @@
697698
6CABB1A029C5593800340467 /* OverlayView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OverlayView.swift; sourceTree = "<group>"; };
698699
6CBD1BC52978DE53006639D5 /* Font+Caption3.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Font+Caption3.swift"; sourceTree = "<group>"; };
699700
6CC9E4B129B5669900C97388 /* Environment+ActiveTabGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Environment+ActiveTabGroup.swift"; sourceTree = "<group>"; };
701+
6CD03B6929FC773F001BD1D0 /* SettingsInjector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsInjector.swift; sourceTree = "<group>"; };
700702
6CDA84AC284C1BA000C1CC3A /* TabBarContextMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarContextMenu.swift; sourceTree = "<group>"; };
701703
6CFF967329BEBCC300182D6F /* FindCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FindCommands.swift; sourceTree = "<group>"; };
702704
6CFF967529BEBCD900182D6F /* FileCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileCommands.swift; sourceTree = "<group>"; };
@@ -2041,6 +2043,7 @@
20412043
58F2EADB292FB2B0004A9BDE /* SettingsData.swift */,
20422044
58F2EAD2292FB2B0004A9BDE /* Settings.swift */,
20432045
6C5FDF7929E6160000BC08C0 /* AppSettings.swift */,
2046+
6CD03B6929FC773F001BD1D0 /* SettingsInjector.swift */,
20442047
6C0D0C6729E861B000AE4D3F /* SettingsSidebarFix.swift */,
20452048
850C631129D6B03400E1444C /* SettingsPage.swift */,
20462049
);
@@ -2814,6 +2817,7 @@
28142817
5878DAB2291D627C00DD95A3 /* PathBarView.swift in Sources */,
28152818
043C321627E3201F006AE443 /* WorkspaceDocument.swift in Sources */,
28162819
58F2EAEC292FB2B0004A9BDE /* IgnoredFiles.swift in Sources */,
2820+
6CD03B6A29FC773F001BD1D0 /* SettingsInjector.swift in Sources */,
28172821
58798236292E30B90085B254 /* FeedbackType.swift in Sources */,
28182822
587B9E6D29301D8F00AC7927 /* GitLabEventNote.swift in Sources */,
28192823
587B9E9129301D8F00AC7927 /* BitBucketOAuthRouter.swift in Sources */,

CodeEdit/Features/CodeFile/CodeFile.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,9 @@ final class CodeFileDocument: NSDocument, ObservableObject, QLPreviewItem {
8080
let windowController = NSWindowController(window: window)
8181
addWindowController(windowController)
8282

83-
window.contentView = NSHostingView(rootView: WindowCodeFileView(codeFile: self))
83+
window.contentView = NSHostingView(rootView: SettingsInjector {
84+
WindowCodeFileView(codeFile: self)
85+
})
8486

8587
window.makeKeyAndOrderFront(nil)
8688
window.center()

CodeEdit/Features/CodeFile/CodeFileView.swift

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@ struct CodeFileView: View {
1616
@ObservedObject
1717
private var codeFile: CodeFileDocument
1818

19-
@AppSettings var settings
19+
@AppSettings(\.textEditing.defaultTabWidth) var defaultTabWidth
20+
@AppSettings(\.textEditing.lineHeightMultiple) var lineHeightMultiple
21+
@AppSettings(\.textEditing.wrapLinesToEditorWidth) var wrapLinesToEditorWidth
22+
@AppSettings(\.textEditing.font) var settingsFont
23+
@AppSettings(\.theme.useThemeBackground) var useThemeBackground
24+
@AppSettings(\.theme.matchAppearance) var matchAppearance
2025

2126
@Environment(\.colorScheme)
2227
private var colorScheme
@@ -56,7 +61,7 @@ struct CodeFileView: View {
5661

5762
@State
5863
private var font: NSFont = {
59-
return Settings.shared.preferences.textEditing.font.current()
64+
return Settings[\.textEditing].font.current()
6065
}()
6166

6267
@Environment(\.edgeInsets)
@@ -71,11 +76,11 @@ struct CodeFileView: View {
7176
language: getLanguage(),
7277
theme: $selectedTheme.editor.editorTheme,
7378
font: $font,
74-
tabWidth: $settings.textEditing.defaultTabWidth,
75-
lineHeight: $settings.textEditing.lineHeightMultiple,
76-
wrapLines: $settings.textEditing.wrapLinesToEditorWidth,
79+
tabWidth: $defaultTabWidth,
80+
lineHeight: $lineHeightMultiple,
81+
wrapLines: $wrapLinesToEditorWidth,
7782
cursorPosition: $codeFile.cursorPosition,
78-
useThemeBackground: settings.theme.useThemeBackground,
83+
useThemeBackground: useThemeBackground,
7984
contentInsets: edgeInsets.nsEdgeInsets,
8085
isEditable: isEditable
8186
)
@@ -99,13 +104,13 @@ struct CodeFileView: View {
99104
self.selectedTheme = theme
100105
}
101106
.onChange(of: colorScheme) { newValue in
102-
if settings.theme.matchAppearance {
107+
if matchAppearance {
103108
ThemeModel.shared.selectedTheme = newValue == .dark
104109
? ThemeModel.shared.selectedDarkTheme!
105110
: ThemeModel.shared.selectedLightTheme!
106111
}
107112
}
108-
.onChange(of: settings.textEditing.font) { _ in
113+
.onChange(of: settingsFont) { _ in
109114
font = Settings.shared.preferences.textEditing.font.current()
110115
}
111116
}

CodeEdit/Features/Documents/Controllers/CodeEditWindowController.swift

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,11 @@ final class CodeEditWindowController: NSWindowController, NSToolbarDelegate, Obs
8686
let feedbackPerformer = NSHapticFeedbackManager.defaultPerformer
8787
let splitVC = CodeEditSplitViewController(workspace: workspace, feedbackPerformer: feedbackPerformer)
8888

89-
let navigatorView = NavigatorSidebarView(workspace: workspace)
90-
.environmentObject(workspace)
91-
.environmentObject(workspace.tabManager)
89+
let navigatorView = SettingsInjector {
90+
NavigatorSidebarView(workspace: workspace)
91+
.environmentObject(workspace)
92+
.environmentObject(workspace.tabManager)
93+
}
9294

9395
let navigator = NSSplitViewItem(
9496
sidebarWithViewController: NSHostingController(rootView: navigatorView)
@@ -98,10 +100,12 @@ final class CodeEditWindowController: NSWindowController, NSToolbarDelegate, Obs
98100
navigator.collapseBehavior = .useConstraints
99101
splitVC.addSplitViewItem(navigator)
100102

101-
let workspaceView = WindowObserver(window: window!) {
102-
WorkspaceView()
103-
.environmentObject(workspace)
104-
.environmentObject(workspace.tabManager)
103+
let workspaceView = SettingsInjector {
104+
WindowObserver(window: window!) {
105+
WorkspaceView()
106+
.environmentObject(workspace)
107+
.environmentObject(workspace.tabManager)
108+
}
105109
}
106110

107111
let mainContent = NSSplitViewItem(
@@ -110,9 +114,11 @@ final class CodeEditWindowController: NSWindowController, NSToolbarDelegate, Obs
110114
mainContent.titlebarSeparatorStyle = .line
111115
splitVC.addSplitViewItem(mainContent)
112116

113-
let inspectorView = InspectorSidebarView(workspace: workspace)
114-
.environmentObject(workspace)
115-
.environmentObject(workspace.tabManager)
117+
let inspectorView = SettingsInjector {
118+
InspectorSidebarView(workspace: workspace)
119+
.environmentObject(workspace)
120+
.environmentObject(workspace.tabManager)
121+
}
116122

117123
let inspector = NSSplitViewItem(
118124
viewController: NSHostingController(rootView: inspectorView)
@@ -220,9 +226,9 @@ final class CodeEditWindowController: NSWindowController, NSToolbarDelegate, Obs
220226
let toolbarItem = NSToolbarItem(itemIdentifier: .branchPicker)
221227
let view = NSHostingView(
222228
rootView: ToolbarBranchPicker(
223-
shellClient: currentWorld.shellClient,
224-
workspace: workspace?.workspaceClient
225-
)
229+
shellClient: currentWorld.shellClient,
230+
workspace: workspace?.workspaceClient
231+
)
226232
)
227233
toolbarItem.view = view
228234

@@ -261,7 +267,7 @@ final class CodeEditWindowController: NSWindowController, NSToolbarDelegate, Obs
261267
let panel = OverlayPanel()
262268
self.commandPalettePanel = panel
263269
let contentView = CommandPaletteView(state: state, closePalette: panel.close)
264-
panel.contentView = NSHostingView(rootView: contentView)
270+
panel.contentView = NSHostingView(rootView: SettingsInjector { contentView })
265271
window?.addChildWindow(panel, ordered: .above)
266272
panel.makeKeyAndOrderFront(self)
267273
}
@@ -288,7 +294,7 @@ final class CodeEditWindowController: NSWindowController, NSToolbarDelegate, Obs
288294
workspace.tabManager.openTab(item: file)
289295
}
290296

291-
panel.contentView = NSHostingView(rootView: contentView)
297+
panel.contentView = NSHostingView(rootView: SettingsInjector { contentView })
292298
window?.addChildWindow(panel, ordered: .above)
293299
panel.makeKeyAndOrderFront(self)
294300
}

CodeEdit/Features/Documents/Views/WorkspaceCodeFileView.swift

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,6 @@ import UniformTypeIdentifiers
1111
struct WorkspaceCodeFileView: View {
1212
var file: WorkspaceClient.FileItem
1313

14-
@StateObject
15-
private var prefs: Settings = .shared
16-
1714
@ViewBuilder
1815
var codeView: some View {
1916
if let document = file.fileDocument {

CodeEdit/Features/Feedback/Controllers/FeedbackWindowController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import SwiftUI
99

1010
final class FeedbackWindowController: NSWindowController, NSToolbarDelegate {
1111
convenience init<T: View>(view: T, size: NSSize) {
12-
let hostingController = NSHostingController(rootView: view)
12+
let hostingController = NSHostingController(rootView: SettingsInjector { view })
1313
let window = NSWindow(contentViewController: hostingController)
1414
self.init(window: window)
1515
window.title = "Feedback for CodeEdit"

CodeEdit/Features/Feedback/FeedbackView.swift

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,6 @@ struct FeedbackView: View {
1111
@ObservedObject
1212
private var feedbackModel: FeedbackModel = .shared
1313

14-
@StateObject
15-
var prefs: Settings = .shared
16-
1714
@State
1815
var showsAlert: Bool = false
1916

CodeEdit/Features/Keybindings/KeybindingManager.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ final class KeybindingManager {
6060
}
6161

6262
/// Wrapper for KeyboardShortcut. It contains name, keybindings.
63-
struct KeyboardShortcutWrapper: Codable {
63+
struct KeyboardShortcutWrapper: Codable, Hashable {
6464
var keyboardShortcut: KeyboardShortcut {
6565
return KeyboardShortcut.init(.init(Character(keybinding)), modifiers: parsedModifier)
6666
}

CodeEdit/Features/NavigatorSidebar/FindNavigator/FindNavigatorResultList/FindNavigatorResultList.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@ struct FindNavigatorResultList: NSViewControllerRepresentable {
1313
@EnvironmentObject
1414
var workspace: WorkspaceDocument
1515

16-
@AppSettings var settings
16+
@AppSettings(\.general.projectNavigatorSize) var projectNavigatorSize
1717

1818
typealias NSViewControllerType = FindNavigatorListViewController
1919

2020
func makeNSViewController(context: Context) -> FindNavigatorListViewController {
2121
let controller = FindNavigatorListViewController(workspace: workspace)
2222
controller.setSearchResults(workspace.searchState?.searchResult ?? [])
23-
controller.rowHeight = settings.general.projectNavigatorSize.rowHeight
23+
controller.rowHeight = projectNavigatorSize.rowHeight
2424
context.coordinator.controller = controller
2525
return controller
2626
}
@@ -30,8 +30,8 @@ struct FindNavigatorResultList: NSViewControllerRepresentable {
3030
workspace.searchState?.searchResult ?? [],
3131
searchId: workspace.searchState?.searchId
3232
)
33-
if nsViewController.rowHeight != settings.general.projectNavigatorSize.rowHeight {
34-
nsViewController.rowHeight = settings.general.projectNavigatorSize.rowHeight
33+
if nsViewController.rowHeight != projectNavigatorSize.rowHeight {
34+
nsViewController.rowHeight = projectNavigatorSize.rowHeight
3535
}
3636
return
3737
}

CodeEdit/Features/NavigatorSidebar/ProjectNavigator/OutlineView/OutlineTableViewCell.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ protocol OutlineTableViewCellDelegate: AnyObject {
1515
/// A `NSTableCellView` showing an ``icon`` and a ``label``
1616
final class OutlineTableViewCell: NSTableCellView {
1717

18-
@AppSettings var settings
19-
2018
var label: NSTextField!
2119
var icon: NSImageView!
2220
private var fileItem: WorkspaceClient.FileItem!

CodeEdit/Features/NavigatorSidebar/ProjectNavigator/OutlineView/OutlineView.swift

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ struct OutlineView: NSViewControllerRepresentable {
1414
@EnvironmentObject
1515
var workspace: WorkspaceDocument
1616

17-
@AppSettings var settings
18-
1917
// This is mainly just used to trigger a view update.
2018
@Binding
2119
var selection: WorkspaceClient.FileItem?
@@ -25,19 +23,19 @@ struct OutlineView: NSViewControllerRepresentable {
2523
func makeNSViewController(context: Context) -> OutlineViewController {
2624
let controller = OutlineViewController()
2725
controller.workspace = workspace
28-
controller.iconColor = settings.general.fileIconStyle
26+
controller.iconColor = Settings[\.general].fileIconStyle
2927

3028
context.coordinator.controller = controller
3129

3230
return controller
3331
}
3432

3533
func updateNSViewController(_ nsViewController: OutlineViewController, context: Context) {
36-
nsViewController.iconColor = settings.general.fileIconStyle
37-
nsViewController.rowHeight = settings.general.projectNavigatorSize.rowHeight
38-
nsViewController.fileExtensionsVisibility = settings.general.fileExtensionsVisibility
39-
nsViewController.shownFileExtensions = settings.general.shownFileExtensions
40-
nsViewController.hiddenFileExtensions = settings.general.hiddenFileExtensions
34+
nsViewController.iconColor = Settings[\.general].fileIconStyle
35+
nsViewController.rowHeight = Settings[\.general].projectNavigatorSize.rowHeight
36+
nsViewController.fileExtensionsVisibility = Settings[\.general].fileExtensionsVisibility
37+
nsViewController.shownFileExtensions = Settings[\.general].shownFileExtensions
38+
nsViewController.hiddenFileExtensions = Settings[\.general].hiddenFileExtensions
4139
nsViewController.updateSelection()
4240
return
4341
}

CodeEdit/Features/PathBar/Views/PathBarComponent.swift

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@ struct PathBarComponent: View {
1919
@Environment(\.controlActiveState)
2020
private var activeState
2121

22-
@StateObject
23-
private var prefs: Settings = .shared
24-
2522
@State
2623
var position: NSPoint?
2724

CodeEdit/Features/Settings/Models/AppSettings.swift

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,54 @@ import Foundation
99
import SwiftUI
1010

1111
@propertyWrapper
12-
struct AppSettings: DynamicProperty {
13-
@ObservedObject
14-
private var prefs: Settings
12+
struct AppSettings<T>: DynamicProperty where T: Equatable {
1513

16-
init(_ prefs: Settings = .shared) {
17-
self.prefs = prefs
14+
var settings: Environment<T>
15+
16+
let keyPath: WritableKeyPath<SettingsData, T>
17+
18+
@available(*,
19+
deprecated,
20+
message: """
21+
Use init(_ keyPath:) instead, otherwise the view will be reevaluated on every settings change.
22+
"""
23+
)
24+
init() where T == SettingsData {
25+
self.keyPath = \.self
26+
self.settings = .init(\.settings)
1827
}
1928

20-
var wrappedValue: SettingsData {
29+
init(_ keyPath: WritableKeyPath<SettingsData, T>) {
30+
self.keyPath = keyPath
31+
let newKeyPath = (\EnvironmentValues.settings).appending(path: keyPath)
32+
self.settings = .init(newKeyPath)
33+
}
34+
35+
var wrappedValue: T {
2136
get {
22-
prefs.preferences
37+
settings.wrappedValue
2338
}
2439
nonmutating set {
25-
prefs.preferences = newValue
40+
Settings.shared.preferences[keyPath: keyPath] = newValue
41+
}
42+
}
43+
44+
var projectedValue: Binding<T> {
45+
.init {
46+
settings.wrappedValue
47+
} set: {
48+
Settings.shared.preferences[keyPath: keyPath] = $0
2649
}
2750
}
51+
}
52+
53+
struct SettingsDataEnvironmentKey: EnvironmentKey {
54+
static var defaultValue: SettingsData = .init()
55+
}
2856

29-
var projectedValue: Binding<SettingsData> {
30-
$prefs.preferences
57+
extension EnvironmentValues {
58+
var settings: SettingsDataEnvironmentKey.Value {
59+
get { self[SettingsDataEnvironmentKey.self] }
60+
set { self[SettingsDataEnvironmentKey.self] = newValue }
3161
}
3262
}

0 commit comments

Comments
 (0)