Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions SupacodeSettingsFeature/Reducer/SettingsFeature.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ public struct SettingsFeature {
public var copyUntrackedOnWorktreeCreate: Bool
public var pullRequestMergeStrategy: PullRequestMergeStrategy
public var terminalThemeSyncEnabled: Bool
public var hideSingleTabBar: Bool
public var automatedActionPolicy: AutomatedActionPolicy
public var defaultWorktreeBaseDirectoryPath: String
public var autoDeleteArchivedWorktreesAfterDays: AutoDeletePeriod?
Expand Down Expand Up @@ -124,7 +123,6 @@ public struct SettingsFeature {
copyUntrackedOnWorktreeCreate = settings.copyUntrackedOnWorktreeCreate
pullRequestMergeStrategy = settings.pullRequestMergeStrategy
terminalThemeSyncEnabled = settings.terminalThemeSyncEnabled
hideSingleTabBar = settings.hideSingleTabBar
automatedActionPolicy = settings.automatedActionPolicy
autoDeleteArchivedWorktreesAfterDays = settings.autoDeleteArchivedWorktreesAfterDays
shortcutOverrides = settings.shortcutOverrides
Expand Down Expand Up @@ -166,7 +164,6 @@ public struct SettingsFeature {
copyUntrackedOnWorktreeCreate: copyUntrackedOnWorktreeCreate,
pullRequestMergeStrategy: pullRequestMergeStrategy,
terminalThemeSyncEnabled: terminalThemeSyncEnabled,
hideSingleTabBar: hideSingleTabBar,
automatedActionPolicy: automatedActionPolicy,
defaultWorktreeBaseDirectoryPath: SupacodePaths.normalizedWorktreeBaseDirectoryPath(
defaultWorktreeBaseDirectoryPath
Expand Down Expand Up @@ -308,7 +305,6 @@ public struct SettingsFeature {
state.copyUntrackedOnWorktreeCreate = normalizedSettings.copyUntrackedOnWorktreeCreate
state.pullRequestMergeStrategy = normalizedSettings.pullRequestMergeStrategy
state.terminalThemeSyncEnabled = normalizedSettings.terminalThemeSyncEnabled
state.hideSingleTabBar = normalizedSettings.hideSingleTabBar
state.automatedActionPolicy = normalizedSettings.automatedActionPolicy
state.autoDeleteArchivedWorktreesAfterDays = normalizedSettings.autoDeleteArchivedWorktreesAfterDays
state.shortcutOverrides = normalizedSettings.shortcutOverrides
Expand Down
118 changes: 60 additions & 58 deletions SupacodeSettingsFeature/Views/AppearanceSettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public struct AppearanceSettingsView: View {
let openActionOptions = store.installedOpenActions
Form {
Section {
LabeledContent("Appearance") {
LabeledContent {
HStack(spacing: 12) {
let appearanceMode = $store.appearanceMode
ForEach(AppearanceMode.allCases) { mode in
Expand All @@ -25,52 +25,83 @@ public struct AppearanceSettingsView: View {
}
}
}
// Keeps the wrapping subtitle from hugging the option cards.
.padding(.leading, 16)
} label: {
Text("Appearance")
Text("Follow the system appearance, or always use light or dark.")
}
Toggle(isOn: $store.terminalThemeSyncEnabled) {
Text("Supacode Terminal Theme")
Text("Supacode terminal theme")
Text("When off, honors your Ghostty config theme.")
}
}
Section {
Picker(selection: $store.confirmQuitMode) {
ForEach(ConfirmQuitMode.allCases, id: \.self) { mode in
Text(mode.label).tag(mode)
LabeledContent {
HStack(spacing: 12) {
ForEach(AppVisibility.allCases) { visibility in
AppVisibilityOptionCardView(
visibility: visibility,
isSelected: visibility == store.appVisibility
) {
store.send(.setAppVisibility(visibility))
}
}
}
// Keeps the wrapping subtitle from hugging the option cards.
.padding(.leading, 16)
} label: {
Text("Confirm before Quitting")
Text(store.confirmQuitMode.subtitle)
Text("Visibility")
Text("Show Supacode in the Dock, the menu bar, or both.")
}
}
Section("Persistence") {
Toggle(isOn: $store.terminateSessionsOnQuit) {
Text("Terminate Sessions on Quit")
Text("Terminate sessions on quit")
Text(
"""
Close all tabs and stop background shells when quitting.
Terminal persistence is powered by [zmx \u{2197}](https://github.com/neurosnap/zmx).
Terminal persistence is powered by [zmx\u{00A0}\u{2197}](https://github.com/neurosnap/zmx).
"""
)
}
Toggle(isOn: $store.remoteSessionPersistenceEnabled) {
Text("Persist Remote Sessions on Host")
Toggle(isOn: $store.terminalHibernationEnabled) {
HStack(spacing: 6) {
Text("Hibernate inactive terminals")
BetaBadge()
}
Text(
"""
Keeps SSH surfaces alive across disconnects when \
[zmx \u{2197}](https://github.com/neurosnap/zmx) is installed on the host.
"""
"Background terminal tabs release their renderer after a few minutes of inactivity "
+ "and reconnect instantly when viewed. Sessions and running agents are unaffected."
)
}
}
Section {
LabeledContent("Visibility") {
HStack(spacing: 12) {
ForEach(AppVisibility.allCases) { visibility in
AppVisibilityOptionCardView(
visibility: visibility,
isSelected: visibility == store.appVisibility
) {
store.send(.setAppVisibility(visibility))
}
}
Toggle(isOn: $store.confirmCloseSurface) {
Text("Confirm before closing terminals")
Text("Asks before closing a terminal with a running process or a persisted background session.")
}
Picker(selection: $store.confirmQuitMode) {
ForEach(ConfirmQuitMode.allCases, id: \.self) { mode in
Text(mode.label).tag(mode)
}
} label: {
Text("Confirm before quitting app")
Text(store.confirmQuitMode.subtitle)
}
}
Section {
Toggle(isOn: $store.remoteSessionPersistenceEnabled) {
HStack(spacing: 6) {
Text("Persist sessions on remote host")
BetaBadge()
}
Text(
"""
Keeps SSH sessions alive across disconnects. Ignored when \
[zmx\u{00A0}\u{2197}](https://github.com/neurosnap/zmx) is not installed on the host.
"""
)
}
}
Section("Editor") {
Expand All @@ -97,59 +128,30 @@ public struct AppearanceSettingsView: View {
.tag(action.settingsID)
}
} label: {
Text("Default Editor")
Text("Default editor")
Text("Applies to Worktrees without repository overrides.")
}
}
Section {
Toggle(isOn: $store.analyticsEnabled) {
Text("Share Analytics")
Text("Share analytics")
Text("Anonymous usage data helps improve Supacode.")
}
Toggle(isOn: $store.crashReportsEnabled) {
Text("Share Crash Reports")
Text("Share crash reports")
Text("Anonymous crash reports help improve stability.")
}
} header: {
Text("Analytics")
} footer: {
Text("Changes to Analytics require Supacode to restart before they take effect.")
}
Section("Advanced") {
Toggle(isOn: $store.hideSingleTabBar) {
Text("Hide Tab Bar for Single Tab")
Text("Automatically hides the tab bar when only one tab is open.")
}
Toggle(isOn: $store.confirmCloseSurface) {
Text("Confirm before Closing Terminals")
Text("Ask before closing a terminal that has a running process.")
}
Picker(selection: $store.automatedActionPolicy.sending(\.setAutomatedActionPolicy)) {
ForEach(AutomatedActionPolicy.allCases, id: \.self) { policy in
Text(policy.displayName).tag(policy)
}
} label: {
Text("Allow Arbitrary Actions")
Text("Skip the confirmation dialog for commands and destructive actions.")
}
Toggle(isOn: $store.terminalHibernationEnabled) {
HStack(spacing: 6) {
Text("Hibernate inactive terminals")
BetaBadge()
}
Text(
"Background terminal tabs release their renderer after a few minutes of inactivity "
+ "and reconnect instantly when viewed. Sessions and running agents are unaffected."
)
}
.help("Free memory by suspending the renderer of terminal tabs you are not viewing.")
}
}
.formStyle(.grouped)
.contentMargins(.trailing, 6, for: .scrollIndicators)
.padding(.top, -20)
.padding(.leading, -8)
.padding(.trailing, -6)

.navigationTitle("General")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ public struct GlobalScriptsSettingsView: View {
}
}
.formStyle(.grouped)
.contentMargins(.trailing, 6, for: .scrollIndicators)
.padding(.top, -20)
.padding(.leading, -8)
.padding(.trailing, -6)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ public struct NotificationsSettingsView: View {
) {
Text("System notifications")
}
.help("Show macOS system notifications")
Picker(selection: $store.notificationSound) {
Text(NotificationSound.never.displayName).tag(NotificationSound.never)
Divider()
Expand Down Expand Up @@ -68,10 +67,10 @@ public struct NotificationsSettingsView: View {
}
}
.formStyle(.grouped)
.contentMargins(.trailing, 6, for: .scrollIndicators)
.padding(.top, -20)
.padding(.leading, -8)
.padding(.trailing, -6)

.navigationTitle("Notifications")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ public struct RepositoryScriptsSettingsView: View {
}
.alert($store.scope(state: \.alert, action: \.alert))
.formStyle(.grouped)
.contentMargins(.trailing, 6, for: .scrollIndicators)
.padding(.top, -20)
.padding(.leading, -8)
.padding(.trailing, -6)
Expand Down
1 change: 1 addition & 0 deletions SupacodeSettingsFeature/Views/RepositorySettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ public struct RepositorySettingsView: View {
}
}
.formStyle(.grouped)
.contentMargins(.trailing, 6, for: .scrollIndicators)
.padding(.top, -20)
.padding(.leading, -8)
.padding(.trailing, -6)
Expand Down
1 change: 1 addition & 0 deletions SupacodeSettingsFeature/Views/WorktreeSettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ public struct WorktreeSettingsView: View {
}
}
.formStyle(.grouped)
.contentMargins(.trailing, 6, for: .scrollIndicators)
.padding(.top, -20)
.padding(.leading, -8)
.padding(.trailing, -6)
Expand Down
6 changes: 3 additions & 3 deletions SupacodeSettingsShared/Domain/AutomatedActionPolicy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ public enum AutomatedActionPolicy: String, Codable, Equatable, Sendable, CaseIte
/// Human-readable label for the settings picker.
public var displayName: String {
switch self {
case .always: "Always"
case .cliOnly: "CLI Only"
case .deeplinksOnly: "Deeplinks Only"
case .always: "CLI & deeplinks"
case .cliOnly: "CLI only"
case .deeplinksOnly: "Deeplinks only"
case .never: "Never"
}
}
Expand Down
7 changes: 0 additions & 7 deletions SupacodeSettingsShared/Models/GlobalSettings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ public nonisolated struct GlobalSettings: Codable, Equatable, Sendable {
public var copyUntrackedOnWorktreeCreate: Bool
public var pullRequestMergeStrategy: PullRequestMergeStrategy
public var terminalThemeSyncEnabled: Bool
public var hideSingleTabBar: Bool
public var automatedActionPolicy: AutomatedActionPolicy
public var autoDeleteArchivedWorktreesAfterDays: AutoDeletePeriod?
public var shortcutOverrides: [AppShortcutID: AppShortcutOverride]
Expand Down Expand Up @@ -134,7 +133,6 @@ public nonisolated struct GlobalSettings: Codable, Equatable, Sendable {
copyUntrackedOnWorktreeCreate: false,
pullRequestMergeStrategy: .merge,
terminalThemeSyncEnabled: true,
hideSingleTabBar: false,
automatedActionPolicy: .cliOnly,
defaultWorktreeBaseDirectoryPath: nil,
autoDeleteArchivedWorktreesAfterDays: nil,
Expand Down Expand Up @@ -173,7 +171,6 @@ public nonisolated struct GlobalSettings: Codable, Equatable, Sendable {
copyUntrackedOnWorktreeCreate: Bool = false,
pullRequestMergeStrategy: PullRequestMergeStrategy = .merge,
terminalThemeSyncEnabled: Bool = true,
hideSingleTabBar: Bool = false,
automatedActionPolicy: AutomatedActionPolicy = .cliOnly,
defaultWorktreeBaseDirectoryPath: String? = nil,
autoDeleteArchivedWorktreesAfterDays: AutoDeletePeriod? = nil,
Expand Down Expand Up @@ -211,7 +208,6 @@ public nonisolated struct GlobalSettings: Codable, Equatable, Sendable {
self.copyUntrackedOnWorktreeCreate = copyUntrackedOnWorktreeCreate
self.pullRequestMergeStrategy = pullRequestMergeStrategy
self.terminalThemeSyncEnabled = terminalThemeSyncEnabled
self.hideSingleTabBar = hideSingleTabBar
self.automatedActionPolicy = automatedActionPolicy
self.defaultWorktreeBaseDirectoryPath = defaultWorktreeBaseDirectoryPath
self.autoDeleteArchivedWorktreesAfterDays = autoDeleteArchivedWorktreesAfterDays
Expand Down Expand Up @@ -326,9 +322,6 @@ public nonisolated struct GlobalSettings: Codable, Equatable, Sendable {
terminalThemeSyncEnabled =
try container.decodeIfPresent(Bool.self, forKey: .terminalThemeSyncEnabled)
?? false
hideSingleTabBar =
try container.decodeIfPresent(Bool.self, forKey: .hideSingleTabBar)
?? Self.default.hideSingleTabBar
// Migrate from the old Bool `allowArbitraryDeeplinkInput` to the new enum.
if let policy = try container.decodeIfPresent(AutomatedActionPolicy.self, forKey: .automatedActionPolicy) {
automatedActionPolicy = policy
Expand Down
6 changes: 6 additions & 0 deletions scripts/build-ghostty.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ print_fingerprint() {
git ls-files --others --exclude-standard | LC_ALL=C sort | shasum -a 256
shasum -a 256 "${script_path}" | awk '{print $1}'
shasum -a 256 "${srcroot}/mise.toml" | awk '{print $1}'
# The patches are applied at build time, so an edited patch must bust the cache.
for patch in "${ghostty_patches_dir}"/*.patch; do
[ -e "${patch}" ] || continue
basename "${patch}"
shasum -a 256 "${patch}" | awk '{print $1}'
done | shasum -a 256
} | shasum -a 256 | awk '{print $1}'
)
}
Expand Down
2 changes: 1 addition & 1 deletion supacode/App/DeeplinkReferenceView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ struct DeeplinkReferenceView: View {
.foregroundStyle(.secondary)
Text(
"Deeplinks that run commands or perform destructive actions require confirmation"
+ " unless \"Allow Arbitrary Deeplink Actions\" is enabled in Settings."
+ " unless \"Allow dangerous actions\" permits them in Developer settings."
)
.foregroundStyle(.secondary)
} header: {
Expand Down
1 change: 0 additions & 1 deletion supacode/Clients/Terminal/TerminalClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ struct TerminalClient {
case setNotificationsEnabled(Bool)
case enforceNotificationRetentionLimit
case setSelectedWorktreeID(Worktree.ID?)
case refreshTabBarVisibility
/// Fans a hibernation Beta-flag flip into every worktree state: enabling
/// re-arms grace timers for hidden tabs, disabling cancels pending ones.
case setTerminalHibernationEnabled(Bool)
Expand Down
3 changes: 0 additions & 3 deletions supacode/Features/App/Reducer/AppFeature.swift
Original file line number Diff line number Diff line change
Expand Up @@ -680,9 +680,6 @@
.run { _ in
await terminalClient.send(.enforceNotificationRetentionLimit)
},
.run { _ in
await terminalClient.send(.refreshTabBarVisibility)
},
]
if let selectedWorktree = state.repositories.worktree(for: state.repositories.selectedWorktreeID) {
effects.append(
Expand Down Expand Up @@ -727,7 +724,7 @@
// refused policy switch would leave no surface at all. Fall back
// to the previous mode, which puts one of them back.
guard appLifecycleClient.applyVisibility(settings.appVisibility) else {
await send(.settings(.setAppVisibility(previousVisibility)))

Check warning on line 727 in supacode/Features/App/Reducer/AppFeature.swift

View workflow job for this annotation

GitHub Actions / build

no 'async' operations occur within 'await' expression
return
}
if dockIconReappeared {
Expand Down
14 changes: 13 additions & 1 deletion supacode/Features/Settings/Views/DeveloperSettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,22 @@ struct DeveloperSettingsView: View {
Text(
"Re-installs hooks for any agent reporting an outdated integration when Supacode comes to the foreground.")
}
.help("Silently re-applies the canonical hook layout to outdated agent integrations when Supacode activates.")
}
Section("Advanced") {
Picker(selection: $store.automatedActionPolicy.sending(\.setAutomatedActionPolicy)) {
ForEach(AutomatedActionPolicy.allCases, id: \.self) { policy in
Text(policy.displayName).tag(policy)
}
} label: {
Text("Allow dangerous actions")
Text(
"Skips the confirmation dialog when running commands or scripts, closing tabs or splits, "
+ "and archiving or deleting worktrees.")
}
}
}
.formStyle(.grouped)
.contentMargins(.trailing, 6, for: .scrollIndicators)
.padding(.top, -20)
.padding(.leading, -8)
.padding(.trailing, -6)
Expand Down
1 change: 1 addition & 0 deletions supacode/Features/Settings/Views/GithubSettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ struct GithubSettingsView: View {
}
}
.formStyle(.grouped)
.contentMargins(.trailing, 6, for: .scrollIndicators)
.padding(.top, -20)
.padding(.leading, -8)
.padding(.trailing, -6)
Expand Down
1 change: 1 addition & 0 deletions supacode/Features/Settings/Views/UpdatesSettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ struct UpdatesSettingsView: View {
}
}
.formStyle(.grouped)
.contentMargins(.trailing, 6, for: .scrollIndicators)
.padding(.top, -20)
.padding(.leading, -8)
.padding(.trailing, -6)
Expand Down
Loading
Loading