diff --git a/macos/Onit/Accessibility/Notifications/AccessibilityNotificationsManager.swift b/macos/Onit/Accessibility/Notifications/AccessibilityNotificationsManager.swift
index a0aa90f3..902387b9 100644
--- a/macos/Onit/Accessibility/Notifications/AccessibilityNotificationsManager.swift
+++ b/macos/Onit/Accessibility/Notifications/AccessibilityNotificationsManager.swift
@@ -421,11 +421,9 @@ class AccessibilityNotificationsManager: ObservableObject {
let selectedElement = element,
!selectedText.isEmpty
else {
-
selectedSource = nil
model?.pendingInput = nil
HighlightHintWindowController.shared.hide()
-
return
}
screenResult.userInteraction.selectedText = selectedText
diff --git a/macos/Onit/Assets.xcassets/Icons/incog-off.imageset/Contents.json b/macos/Onit/Assets.xcassets/Icons/incog-off.imageset/Contents.json
new file mode 100644
index 00000000..846c0fd7
--- /dev/null
+++ b/macos/Onit/Assets.xcassets/Icons/incog-off.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+ "images" : [
+ {
+ "filename" : "incog-off.svg",
+ "idiom" : "universal",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/macos/Onit/Assets.xcassets/Icons/incog-off.imageset/incog-off.svg b/macos/Onit/Assets.xcassets/Icons/incog-off.imageset/incog-off.svg
new file mode 100644
index 00000000..0dcb6f12
--- /dev/null
+++ b/macos/Onit/Assets.xcassets/Icons/incog-off.imageset/incog-off.svg
@@ -0,0 +1,3 @@
+
diff --git a/macos/Onit/Assets.xcassets/Icons/incog-on.imageset/Contents.json b/macos/Onit/Assets.xcassets/Icons/incog-on.imageset/Contents.json
new file mode 100644
index 00000000..3bd7d2e0
--- /dev/null
+++ b/macos/Onit/Assets.xcassets/Icons/incog-on.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+ "images" : [
+ {
+ "filename" : "incog-on.svg",
+ "idiom" : "universal",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/macos/Onit/Assets.xcassets/Icons/incog-on.imageset/incog-on.svg b/macos/Onit/Assets.xcassets/Icons/incog-on.imageset/incog-on.svg
new file mode 100644
index 00000000..6407225a
--- /dev/null
+++ b/macos/Onit/Assets.xcassets/Icons/incog-on.imageset/incog-on.svg
@@ -0,0 +1,3 @@
+
diff --git a/macos/Onit/Data/Model/Model+Chat.swift b/macos/Onit/Data/Model/Model+Chat.swift
index fab096d8..facc5710 100644
--- a/macos/Onit/Data/Model/Model+Chat.swift
+++ b/macos/Onit/Data/Model/Model+Chat.swift
@@ -35,7 +35,8 @@ extension OnitModel {
currentPrompts = []
SystemPromptState.shared.shouldShowSystemPrompt = false
let modelContext = container.mainContext
- modelContext.insert(currentChat!)
+
+ if !Defaults[.incognitoModeEnabled] { modelContext.insert(currentChat!) }
finishPromptCreation(prompt)
}
diff --git a/macos/Onit/Data/Persistence/Defaults.swift b/macos/Onit/Data/Persistence/Defaults.swift
index 4654f9ec..25e6bf30 100644
--- a/macos/Onit/Data/Persistence/Defaults.swift
+++ b/macos/Onit/Data/Persistence/Defaults.swift
@@ -65,6 +65,7 @@ extension Defaults.Keys {
static let availableRemoteModels = Key<[AIModel]>("availableRemoteModels", default: [])
static let availableCustomProviders = Key<[CustomProvider]>(
"availableCustomProvider", default: [])
+ static let incognitoModeEnabled = Key("incognitoModeEnabled", default: false)
// Stores unique model identifiers in the format "provider-id" or "customProviderName-id" for custom providers
static let visibleModelIds = Key>("visibleModelIds", default: Set([]))
diff --git a/macos/Onit/KeyboardShortcuts/KeyboardShortcutsManager.swift b/macos/Onit/KeyboardShortcuts/KeyboardShortcutsManager.swift
index a63e6f4a..3d48abde 100644
--- a/macos/Onit/KeyboardShortcuts/KeyboardShortcutsManager.swift
+++ b/macos/Onit/KeyboardShortcuts/KeyboardShortcutsManager.swift
@@ -91,6 +91,7 @@ struct KeyboardShortcutsManager {
PostHogSDK.shared.capture(
"shortcut_launch_with_auto_context", properties: eventProperties)
model.addAutoContext()
+
if (model.panel == nil) {
model.launchPanel()
}
diff --git a/macos/Onit/UI/Chat/ChatView.swift b/macos/Onit/UI/Chat/ChatView.swift
index fd6b76f7..3c453c22 100644
--- a/macos/Onit/UI/Chat/ChatView.swift
+++ b/macos/Onit/UI/Chat/ChatView.swift
@@ -8,6 +8,7 @@ struct ChatView: View {
var body: some View {
VStack(alignment: .leading, spacing: 0) {
+ IncognitoDismissable()
SetUpDialogs()
if let systemPrompt = model.currentChat?.systemPrompt {
ChatSystemPromptView(systemPrompt: systemPrompt)
diff --git a/macos/Onit/UI/Dismissables/IncognitoDismissable.swift b/macos/Onit/UI/Dismissables/IncognitoDismissable.swift
new file mode 100644
index 00000000..1bd297b2
--- /dev/null
+++ b/macos/Onit/UI/Dismissables/IncognitoDismissable.swift
@@ -0,0 +1,67 @@
+//
+// IncognitoDismissable.swift
+// Onit
+//
+// Created by Loyd Kim on 4/7/25.
+//
+
+import Defaults
+import SwiftUI
+
+struct IncognitoDismissable: View {
+ @AppStorage("closedIncognitoDismissable") private var closedIncognitoDismissable = false
+ @Default(.incognitoModeEnabled) var incognitoModeEnabled
+
+ @State var closeHovered: Bool = false
+
+ var body: some View {
+ if incognitoModeEnabled && !closedIncognitoDismissable {
+ VStack(alignment: .leading, spacing: 6) {
+ title
+ text
+ }
+ .padding(14)
+ .background(.gray900)
+ .overlay(
+ RoundedRectangle(cornerRadius: 16)
+ .inset(by: 0.5)
+ .stroke(Color(red: 0.28, green: 0.29, blue: 0.31), lineWidth: 1)
+ )
+ .cornerRadius(16)
+ .padding(.vertical, 8)
+ .padding(.horizontal, 14)
+ }
+ }
+}
+
+
+/// Child Components
+extension IncognitoDismissable {
+ var title: some View {
+ HStack {
+ Text("Incognito Mode")
+ .foregroundColor(.white)
+ .font(.system(size: 14, weight: .semibold))
+
+ Spacer()
+
+ Button {
+ closedIncognitoDismissable = true
+ } label: {
+ Image(.smallCross)
+ .renderingMode(.template)
+ .foregroundStyle(.white)
+ .frame(width: 10, height: 10)
+ }
+ .opacity(closeHovered ? 0.5 : 1)
+ .animation(.easeInOut(duration: 0.15), value: closeHovered)
+ .onHover{ isHovering in closeHovered = isHovering}
+ }
+ }
+
+ var text: some View {
+ Text("When on, Onit won’t store your chats in history.")
+ .foregroundColor(.gray100)
+ .font(.system(size: 13, weight: .medium))
+ }
+}
diff --git a/macos/Onit/UI/History/HistoryRowView.swift b/macos/Onit/UI/History/HistoryRowView.swift
index 1f328f2b..272b0e0c 100644
--- a/macos/Onit/UI/History/HistoryRowView.swift
+++ b/macos/Onit/UI/History/HistoryRowView.swift
@@ -5,9 +5,12 @@
// Created by Benjamin Sage on 11/4/24.
//
+import Defaults
import SwiftUI
struct HistoryRowView: View {
+ @Default(.incognitoModeEnabled) var incognitoModeEnabled
+
@Environment(\.model) var model
@State private var showDelete: Bool = false
@@ -17,6 +20,7 @@ struct HistoryRowView: View {
var body: some View {
Button {
+ incognitoModeEnabled = false
model.setChat(chat: chat, index: index)
} label: {
HStack {
diff --git a/macos/Onit/UI/OS/ContextPickerView.swift b/macos/Onit/UI/OS/ContextPickerView.swift
index d70cbc45..584a9de4 100644
--- a/macos/Onit/UI/OS/ContextPickerView.swift
+++ b/macos/Onit/UI/OS/ContextPickerView.swift
@@ -27,7 +27,10 @@ struct ContextPickerView: View {
model.addAutoContext()
}) {
ContextPickerItemView(
- imageRes: .stars, title: "Auto-context", subtitle: "Current window activity")
+ imageRes: .stars,
+ title: "Auto-context",
+ subtitle: "Current window activity"
+ )
}
.buttonStyle(.plain)
.foregroundColor(.gray200)
diff --git a/macos/Onit/UI/Prompt/Toolbar.swift b/macos/Onit/UI/Prompt/Toolbar.swift
index 5821c964..16c35e44 100644
--- a/macos/Onit/UI/Prompt/Toolbar.swift
+++ b/macos/Onit/UI/Prompt/Toolbar.swift
@@ -20,6 +20,7 @@ struct Toolbar: View {
@Default(.localModel) var localModel
@Default(.isRegularApp) var isRegularApp
@Default(.fitActiveWindow) var fitActiveWindow
+ @Default(.incognitoModeEnabled) var incognitoModeEnabled
private var isAccessibilityFlagsEnabled: Bool {
featureFlagsManager.accessibility && featureFlagsManager.accessibilityAutoContext
@@ -59,6 +60,7 @@ struct Toolbar: View {
fitActiveWindowButton
}
localMode
+ incognitoMode
history
settings
@@ -242,6 +244,19 @@ struct Toolbar: View {
}
.tooltip(prompt: "Local Mode", shortcut: .keyboardShortcuts(.toggleLocalMode))
}
+
+ var incognitoMode: some View {
+ Button {
+ incognitoModeEnabled.toggle()
+ model.newChat()
+ } label: {
+ Image(incognitoModeEnabled ? .incogOn : .incogOff)
+ .renderingMode(.template)
+ .padding(4)
+ .foregroundColor(incognitoModeEnabled ? .blue400 : .gray200)
+ }
+ .tooltip(prompt: "Incognito mode (auto-context off)")
+ }
var showHistoryBinding: Binding {
Binding(