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(