Skip to content

Commit 52877b4

Browse files
committed
feat: Add workspace visibility settings for reflog, PRs, and Git LFS
Expose toggles in a new WorkspaceVisibilityPopover and persist them through AppState, settings snapshots, and Firestore cloud sync.
1 parent ea02799 commit 52877b4

10 files changed

Lines changed: 231 additions & 7 deletions

‎macgit/App/AppState.swift‎

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ final class AppState: ObservableObject {
2323
private static let appearanceKey = "appearance"
2424
private static let showToolbarButtonTextKey = "showToolbarButtonText"
2525
private static let showGitFlowKey = "showGitFlow"
26+
private static let showWorkspaceReflogKey = "showWorkspaceReflog"
27+
private static let showWorkspacePullRequestsKey = "showWorkspacePullRequests"
28+
private static let showWorkspaceGitLFSKey = "showWorkspaceGitLFS"
2629
private static let showSubmodulesKey = "showSubmodules"
2730
private static let showSubtreesKey = "showSubtrees"
2831
private static let showHeaderBranchButtonKey = "showHeaderBranchButton"
@@ -72,6 +75,30 @@ final class AppState: ObservableObject {
7275
}
7376
}
7477
}
78+
@Published var showWorkspaceReflog: Bool {
79+
didSet {
80+
userDefaults.set(showWorkspaceReflog, forKey: Self.showWorkspaceReflogKey)
81+
if !isApplyingSnapshot {
82+
currentSettingsSnapshot = snapshot
83+
}
84+
}
85+
}
86+
@Published var showWorkspacePullRequests: Bool {
87+
didSet {
88+
userDefaults.set(showWorkspacePullRequests, forKey: Self.showWorkspacePullRequestsKey)
89+
if !isApplyingSnapshot {
90+
currentSettingsSnapshot = snapshot
91+
}
92+
}
93+
}
94+
@Published var showWorkspaceGitLFS: Bool {
95+
didSet {
96+
userDefaults.set(showWorkspaceGitLFS, forKey: Self.showWorkspaceGitLFSKey)
97+
if !isApplyingSnapshot {
98+
currentSettingsSnapshot = snapshot
99+
}
100+
}
101+
}
75102
@Published var showSubmodules: Bool {
76103
didSet {
77104
userDefaults.set(showSubmodules, forKey: Self.showSubmodulesKey)
@@ -232,6 +259,9 @@ final class AppState: ObservableObject {
232259
.flatMap(AppAppearance.init(rawValue:)) ?? .system
233260
let showToolbarButtonText = userDefaults.object(forKey: Self.showToolbarButtonTextKey) as? Bool ?? true
234261
let showGitFlow = userDefaults.object(forKey: Self.showGitFlowKey) as? Bool ?? true
262+
let showWorkspaceReflog = userDefaults.object(forKey: Self.showWorkspaceReflogKey) as? Bool ?? true
263+
let showWorkspacePullRequests = userDefaults.object(forKey: Self.showWorkspacePullRequestsKey) as? Bool ?? true
264+
let showWorkspaceGitLFS = userDefaults.object(forKey: Self.showWorkspaceGitLFSKey) as? Bool ?? true
235265
let showSubmodules = userDefaults.object(forKey: Self.showSubmodulesKey) as? Bool ?? false
236266
let showSubtrees = userDefaults.object(forKey: Self.showSubtreesKey) as? Bool ?? false
237267
let showHeaderBranchButton = userDefaults.object(forKey: Self.showHeaderBranchButtonKey) as? Bool ?? true
@@ -261,6 +291,9 @@ final class AppState: ObservableObject {
261291
appearance: appearance,
262292
showToolbarButtonText: showToolbarButtonText,
263293
showGitFlow: showGitFlow,
294+
showWorkspaceReflog: showWorkspaceReflog,
295+
showWorkspacePullRequests: showWorkspacePullRequests,
296+
showWorkspaceGitLFS: showWorkspaceGitLFS,
264297
showSubmodules: showSubmodules,
265298
showSubtrees: showSubtrees,
266299
showHeaderBranchButton: showHeaderBranchButton,
@@ -281,6 +314,9 @@ final class AppState: ObservableObject {
281314
self.appearance = appearance
282315
self.showToolbarButtonText = showToolbarButtonText
283316
self.showGitFlow = showGitFlow
317+
self.showWorkspaceReflog = showWorkspaceReflog
318+
self.showWorkspacePullRequests = showWorkspacePullRequests
319+
self.showWorkspaceGitLFS = showWorkspaceGitLFS
284320
self.showSubmodules = showSubmodules
285321
self.showSubtrees = showSubtrees
286322
self.showHeaderBranchButton = showHeaderBranchButton
@@ -308,6 +344,9 @@ final class AppState: ObservableObject {
308344
appearance: appearance,
309345
showToolbarButtonText: showToolbarButtonText,
310346
showGitFlow: showGitFlow,
347+
showWorkspaceReflog: showWorkspaceReflog,
348+
showWorkspacePullRequests: showWorkspacePullRequests,
349+
showWorkspaceGitLFS: showWorkspaceGitLFS,
311350
showSubmodules: showSubmodules,
312351
showSubtrees: showSubtrees,
313352
showHeaderBranchButton: showHeaderBranchButton,
@@ -333,6 +372,9 @@ final class AppState: ObservableObject {
333372
appearance = snapshot.appearance
334373
showToolbarButtonText = snapshot.showToolbarButtonText
335374
showGitFlow = snapshot.showGitFlow
375+
showWorkspaceReflog = snapshot.showWorkspaceReflog
376+
showWorkspacePullRequests = snapshot.showWorkspacePullRequests
377+
showWorkspaceGitLFS = snapshot.showWorkspaceGitLFS
336378
showSubmodules = snapshot.showSubmodules
337379
showSubtrees = snapshot.showSubtrees
338380
showHeaderBranchButton = snapshot.showHeaderBranchButton

‎macgit/Models/AppSettingsSnapshot.swift‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ struct AppSettingsSnapshot: Codable, Equatable, Sendable {
2323
var appearance: AppAppearance
2424
var showToolbarButtonText: Bool
2525
var showGitFlow: Bool
26+
var showWorkspaceReflog: Bool
27+
var showWorkspacePullRequests: Bool
28+
var showWorkspaceGitLFS: Bool
2629
var showSubmodules: Bool
2730
var showSubtrees: Bool
2831
var showHeaderBranchButton: Bool
@@ -43,6 +46,9 @@ struct AppSettingsSnapshot: Codable, Equatable, Sendable {
4346
appearance: AppAppearance = .system,
4447
showToolbarButtonText: Bool,
4548
showGitFlow: Bool = true,
49+
showWorkspaceReflog: Bool = true,
50+
showWorkspacePullRequests: Bool = true,
51+
showWorkspaceGitLFS: Bool = true,
4652
showSubmodules: Bool,
4753
showSubtrees: Bool,
4854
showHeaderBranchButton: Bool = true,
@@ -63,6 +69,9 @@ struct AppSettingsSnapshot: Codable, Equatable, Sendable {
6369
self.appearance = appearance
6470
self.showToolbarButtonText = showToolbarButtonText
6571
self.showGitFlow = showGitFlow
72+
self.showWorkspaceReflog = showWorkspaceReflog
73+
self.showWorkspacePullRequests = showWorkspacePullRequests
74+
self.showWorkspaceGitLFS = showWorkspaceGitLFS
6675
self.showSubmodules = showSubmodules
6776
self.showSubtrees = showSubtrees
6877
self.showHeaderBranchButton = showHeaderBranchButton
@@ -86,6 +95,9 @@ struct AppSettingsSnapshot: Codable, Equatable, Sendable {
8695
appearance = try container.decode(AppAppearance.self, forKey: .appearance)
8796
showToolbarButtonText = try container.decode(Bool.self, forKey: .showToolbarButtonText)
8897
showGitFlow = try container.decodeIfPresent(Bool.self, forKey: .showGitFlow) ?? true
98+
showWorkspaceReflog = try container.decodeIfPresent(Bool.self, forKey: .showWorkspaceReflog) ?? true
99+
showWorkspacePullRequests = try container.decodeIfPresent(Bool.self, forKey: .showWorkspacePullRequests) ?? true
100+
showWorkspaceGitLFS = try container.decodeIfPresent(Bool.self, forKey: .showWorkspaceGitLFS) ?? true
89101
showSubmodules = try container.decode(Bool.self, forKey: .showSubmodules)
90102
showSubtrees = try container.decode(Bool.self, forKey: .showSubtrees)
91103
showHeaderBranchButton = try container.decode(Bool.self, forKey: .showHeaderBranchButton)

‎macgit/Services/FirestoreSettingsStore.swift‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ enum CloudSettingsDocument {
2929
"appearance": snapshot.appearance.rawValue,
3030
"showToolbarButtonText": snapshot.showToolbarButtonText,
3131
"showGitFlow": snapshot.showGitFlow,
32+
"showWorkspaceReflog": snapshot.showWorkspaceReflog,
33+
"showWorkspacePullRequests": snapshot.showWorkspacePullRequests,
34+
"showWorkspaceGitLFS": snapshot.showWorkspaceGitLFS,
3235
"showSubmodules": snapshot.showSubmodules,
3336
"showSubtrees": snapshot.showSubtrees,
3437
"showHeaderBranchButton": snapshot.showHeaderBranchButton,
@@ -75,6 +78,9 @@ enum CloudSettingsDocument {
7578
appearance: appearance,
7679
showToolbarButtonText: showToolbarButtonText,
7780
showGitFlow: data["showGitFlow"] as? Bool ?? true,
81+
showWorkspaceReflog: data["showWorkspaceReflog"] as? Bool ?? true,
82+
showWorkspacePullRequests: data["showWorkspacePullRequests"] as? Bool ?? true,
83+
showWorkspaceGitLFS: data["showWorkspaceGitLFS"] as? Bool ?? true,
7884
showSubmodules: showSubmodules,
7985
showSubtrees: showSubtrees,
8086
showHeaderBranchButton: data["showHeaderBranchButton"] as? Bool ?? true,

‎macgit/Views/Account/ManageAccountSheet.swift‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,10 @@ struct SettingsSyncConflictSheet: View {
217217
Grid(alignment: .leading, horizontalSpacing: 16, verticalSpacing: 8) {
218218
settingValueRow("Appearance", value: snapshot.appearance.title)
219219
settingRow("Toolbar button text", enabled: snapshot.showToolbarButtonText)
220-
settingRow("Git Flow", enabled: snapshot.showGitFlow)
220+
settingRow("Workspace: Reflog", enabled: snapshot.showWorkspaceReflog)
221+
settingRow("Workspace: Pull Requests", enabled: snapshot.showWorkspacePullRequests)
222+
settingRow("Workspace: Git LFS", enabled: snapshot.showWorkspaceGitLFS)
223+
settingRow("Workspace: Git Flow", enabled: snapshot.showGitFlow)
221224
settingRow("Submodules", enabled: snapshot.showSubmodules)
222225
settingRow("Subtrees", enabled: snapshot.showSubtrees)
223226
settingRow("Header: Branch", enabled: snapshot.showHeaderBranchButton)

‎macgit/Views/Common/GeneralSettingsView.swift‎

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,28 @@ struct GeneralSettingsView: View {
3636
Section {
3737
SettingsToggleRow(
3838
title: "Show Git Flow",
39-
detail: "Include Git Flow workflow actions as a dedicated repository sidebar section.",
39+
detail: "Include Git Flow in the Workspace section of the repository sidebar.",
4040
isOn: $appState.showGitFlow
4141
)
4242

43+
SettingsToggleRow(
44+
title: "Show Reflog",
45+
detail: "Include Reflog in the Workspace section of the repository sidebar.",
46+
isOn: $appState.showWorkspaceReflog
47+
)
48+
49+
SettingsToggleRow(
50+
title: "Show Pull Requests",
51+
detail: "Include Pull Requests in the Workspace section of the repository sidebar.",
52+
isOn: $appState.showWorkspacePullRequests
53+
)
54+
55+
SettingsToggleRow(
56+
title: "Show Git LFS",
57+
detail: "Include Git LFS in the Workspace section of the repository sidebar.",
58+
isOn: $appState.showWorkspaceGitLFS
59+
)
60+
4361
SettingsToggleRow(
4462
title: "Show submodules",
4563
detail: "Include Git submodules as a dedicated section in the repository sidebar.",
@@ -107,6 +125,9 @@ struct GeneralSettingsView: View {
107125
private func restoreDefaults() {
108126
appState.fitRepositoryWindowsToScreen = false
109127
appState.showGitFlow = true
128+
appState.showWorkspaceReflog = true
129+
appState.showWorkspacePullRequests = true
130+
appState.showWorkspaceGitLFS = true
110131
appState.showSubmodules = false
111132
appState.showSubtrees = false
112133
appState.historyIncludeRemotes = false

‎macgit/Views/MainWindow/Sidebar/SidebarWorkspaceSection.swift‎

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,12 @@
1919
import SwiftUI
2020

2121
struct SidebarWorkspaceSection: View {
22+
@ObservedObject var appState: AppState
2223
let onRequestSearch: () -> Void
2324
let onRequestCreatePullRequest: () -> Void
24-
let showGitFlow: Bool
2525
let gitFlowCommandState: GitFlowCommandState
2626
let onGitFlowAction: (GitFlowMenuAction) -> Void
27+
@State private var isShowingVisibilityPopover = false
2728

2829
var body: some View {
2930
Section {
@@ -41,12 +42,25 @@ struct SidebarWorkspaceSection: View {
4142
.accessibilityElement(children: .combine)
4243

4344
Spacer()
45+
46+
Button("Customize Workspace", systemImage: "line.3.horizontal.decrease.circle") {
47+
isShowingVisibilityPopover.toggle()
48+
}
49+
.labelStyle(.iconOnly)
50+
.buttonStyle(.plain)
51+
.foregroundStyle(.secondary)
52+
.padding(.trailing, 8)
53+
.help("Choose which Workspace items are shown")
54+
.sidebarPointingHandCursor()
55+
.popover(isPresented: $isShowingVisibilityPopover, arrowEdge: .trailing) {
56+
WorkspaceVisibilityPopover(appState: appState)
57+
}
4458
}
4559
.padding(.vertical, 2)
4660
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
4761

4862
ForEach(SidebarSection.workspace.items) { item in
49-
if item == .search {
63+
if isVisible(item), item == .search {
5064
Label(item.rawValue, systemImage: item.icon)
5165
.padding(.leading, 6)
5266
.frame(maxWidth: .infinity, alignment: .leading)
@@ -55,7 +69,7 @@ struct SidebarWorkspaceSection: View {
5569
onRequestSearch()
5670
}
5771
.sidebarPointingHandCursor()
58-
} else {
72+
} else if isVisible(item) {
5973
Label(item.rawValue, systemImage: item.icon)
6074
.padding(.leading, 6)
6175
.tag(SidebarSelection.item(item))
@@ -68,7 +82,7 @@ struct SidebarWorkspaceSection: View {
6882
}
6983
}
7084

71-
if showGitFlow {
85+
if appState.showGitFlow {
7286
Label(SidebarItem.gitFlow.rawValue, systemImage: SidebarItem.gitFlow.icon)
7387
.padding(.leading, 6)
7488
.tag(SidebarSelection.item(.gitFlow))
@@ -86,4 +100,17 @@ struct SidebarWorkspaceSection: View {
86100
}
87101
}
88102
}
103+
104+
private func isVisible(_ item: SidebarItem) -> Bool {
105+
switch item {
106+
case .reflog:
107+
appState.showWorkspaceReflog
108+
case .pullRequests:
109+
appState.showWorkspacePullRequests
110+
case .gitLFS:
111+
appState.showWorkspaceGitLFS
112+
case .fileStatus, .history, .search, .gitFlow:
113+
true
114+
}
115+
}
89116
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//
2+
// macgit (Commit+) - a macOS Git client built with Swift and SwiftUI.
3+
// Copyright (C) 2026 Thanh Tran <trantienthanh2412@gmail.com>
4+
//
5+
// This program is free software: you can redistribute it and/or modify
6+
// it under the terms of the GNU Affero General Public License as published by
7+
// the Free Software Foundation, either version 3 of the License, or
8+
// (at your option) any later version.
9+
//
10+
// This program is distributed in the hope that it will be useful,
11+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
// GNU Affero General Public License for more details.
14+
//
15+
// You should have received a copy of the GNU Affero General Public License
16+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
//
18+
19+
import SwiftUI
20+
21+
struct WorkspaceVisibilityPopover: View {
22+
@ObservedObject var appState: AppState
23+
24+
var body: some View {
25+
VStack(alignment: .leading, spacing: 10) {
26+
Text("Show in Workspace")
27+
.font(.headline)
28+
29+
Toggle("Reflog", isOn: $appState.showWorkspaceReflog)
30+
Toggle("Pull Requests", isOn: $appState.showWorkspacePullRequests)
31+
Toggle("Git LFS", isOn: $appState.showWorkspaceGitLFS)
32+
Toggle("Git Flow", isOn: $appState.showGitFlow)
33+
}
34+
.padding()
35+
.frame(minWidth: 190, alignment: .leading)
36+
}
37+
}

‎macgit/Views/MainWindow/SidebarView.swift‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -767,9 +767,9 @@ struct SidebarView: View {
767767
@ViewBuilder
768768
private var sidebarRows: some View {
769769
SidebarWorkspaceSection(
770+
appState: appState,
770771
onRequestSearch: onRequestSearch,
771772
onRequestCreatePullRequest: onRequestCreatePullRequestFromWorkspace,
772-
showGitFlow: appState.showGitFlow,
773773
gitFlowCommandState: gitFlowCommandState,
774774
onGitFlowAction: performGitFlowAction
775775
)

0 commit comments

Comments
 (0)