diff --git a/macos/Onit/Accessibility/Notifications/AccessibilityNotificationsManager.swift b/macos/Onit/Accessibility/Notifications/AccessibilityNotificationsManager.swift index d5d09f3b..94dca9da 100644 --- a/macos/Onit/Accessibility/Notifications/AccessibilityNotificationsManager.swift +++ b/macos/Onit/Accessibility/Notifications/AccessibilityNotificationsManager.swift @@ -603,13 +603,19 @@ class AccessibilityNotificationsManager: ObservableObject { screenResult.userInteraction.selectedText = nil PanelStateCoordinator.shared.state.pendingInput = nil + PanelStateCoordinator.shared.state.trackedPendingInput = nil return } screenResult.userInteraction.selectedText = selectedText let input = Input(selectedText: selectedText, application: currentSource ?? "") - PanelStateCoordinator.shared.state.pendingInput = input + + if Defaults[.autoAddHighlightedTextToContext] { + PanelStateCoordinator.shared.state.pendingInput = input + } else { + PanelStateCoordinator.shared.state.trackedPendingInput = input + } } // MARK: Caret Position Handling diff --git a/macos/Onit/Data/Persistence/Defaults.swift b/macos/Onit/Data/Persistence/Defaults.swift index 9304b745..b5674740 100644 --- a/macos/Onit/Data/Persistence/Defaults.swift +++ b/macos/Onit/Data/Persistence/Defaults.swift @@ -114,7 +114,9 @@ extension Defaults.Keys { static let lineHeight = Key("lineHeight", default: 1.5) static let voiceSilenceThreshold = Key("voiceSilenceThreshold", default: -40) static let voiceSpeechPassThreshold = Key("voiceSpeechPassThreshold", default: 0.7) + /// Highlighted Text static let showHighlightedTextInput = Key("showHighlightedTextInput", default: true) + static let autoAddHighlightedTextToContext = Key("autoAddHighlightedTextToContext", default: true) // Local model advanced options static let localKeepAlive = Key("localKeepAlive", default: nil) diff --git a/macos/Onit/UI/Panels/State/OnitPanelState.swift b/macos/Onit/UI/Panels/State/OnitPanelState.swift index 49df4982..ece64a2f 100644 --- a/macos/Onit/UI/Panels/State/OnitPanelState.swift +++ b/macos/Onit/UI/Panels/State/OnitPanelState.swift @@ -130,6 +130,8 @@ class OnitPanelState: NSObject { } } + var trackedPendingInput: Input? = nil + var systemPromptId: String = SystemPrompt.outputOnly.id var imageUploads: [URL: UploadProgress] = [:] diff --git a/macos/Onit/UI/Prompt/Files/FileRow.swift b/macos/Onit/UI/Prompt/Files/FileRow.swift index 9fc4d934..a1c5e39e 100644 --- a/macos/Onit/UI/Prompt/Files/FileRow.swift +++ b/macos/Onit/UI/Prompt/Files/FileRow.swift @@ -14,6 +14,7 @@ struct FileRow: View { @ObservedObject private var debugManager = DebugManager.shared @Default(.autoContextFromCurrentWindow) var autoContextFromCurrentWindow + @Default(.autoAddHighlightedTextToContext) var autoAddHighlightedTextToContext @State private var ocrComparisonResult: OCRComparisonResult? = nil @State private var showOCRDetails = false @@ -119,7 +120,8 @@ struct FileRow: View { FlowLayout(spacing: 6) { PaperclipButton() - addForegroundWindowToContextButton + addHighlightedTextToContextButton + addWindowToContextButton pendingWindowContextItems highlightedTextContext addedWindowContextItems @@ -150,28 +152,70 @@ struct FileRow: View { // MARK: - Child Components extension FileRow { + private func ghostContextTag( + text: String, + iconBundleURL: URL? = nil, + iconView: (any View)? = nil, + tooltip: String, + action: @escaping () -> Void + ) -> some View { + ContextTag( + text: text, + textColor: .T_2, + hoverTextColor: .white, + background: contextTagBackground, + hoverBackground: contextTagHoverBackground, + hasHoverBorder: true, + shouldFadeIn: true, + iconBundleURL: iconBundleURL, + iconView: iconView, + tooltip: tooltip + ) { + action() + } + } + + @ViewBuilder + private var addHighlightedTextToContextButton: some View { + if accessibilityEnabled, + Defaults[.autoContextFromHighlights], + let windowState = windowState, + let trackedPendingInput = windowState.trackedPendingInput + { + ghostContextTag( + text: trackedPendingInput.selectedText, + iconView: Image(.text).addIconStyles(iconSize: 14), + tooltip: "Add Highlighted Text To Context" + ) { + windowState.pendingInput = trackedPendingInput + windowState.trackedPendingInput = nil + } + .onChange(of: autoAddHighlightedTextToContext) { _, autoAddHighlightedText in + if autoAddHighlightedText { + windowState.pendingInput = trackedPendingInput + windowState.trackedPendingInput = nil + } + } + } + } + @ViewBuilder - private var addForegroundWindowToContextButton: some View { + private var addWindowToContextButton: some View { if accessibilityEnabled, autoContextFromCurrentWindow, !(windowBeingAddedToContext || windowAlreadyInContext), - let foregroundWindow = windowState?.foregroundWindow + let windowState = windowState, + let foregroundWindow = windowState.foregroundWindow { let foregroundWindowName = WindowHelpers.getWindowName(window: foregroundWindow.element) let iconBundleURL = WindowHelpers.getWindowAppBundleUrl(window: foregroundWindow.element) - - ContextTag( + + ghostContextTag( text: contextTagText, - textColor: .T_2, - hoverTextColor: .white, - background: contextTagBackground, - hoverBackground: contextTagHoverBackground, - hasHoverBorder: true, - shouldFadeIn: true, iconBundleURL: iconBundleURL, tooltip: "Add \(foregroundWindowName) Context" ) { - windowState?.addWindowToContext(window: foregroundWindow.element) + windowState.addWindowToContext(window: foregroundWindow.element) } } } @@ -211,6 +255,8 @@ extension FileRow { iconView: Image(.text).addIconStyles(iconSize: 14) ) { Defaults[.showHighlightedTextInput] = true + } removeAction: { + windowState?.pendingInput = nil } } } diff --git a/macos/Onit/UI/Settings/GeneralTab.swift b/macos/Onit/UI/Settings/GeneralTab.swift index 7a28d74a..27c0d587 100644 --- a/macos/Onit/UI/Settings/GeneralTab.swift +++ b/macos/Onit/UI/Settings/GeneralTab.swift @@ -19,6 +19,7 @@ struct GeneralTab: View { @Default(.tetheredButtonHideAllApps) var tetheredButtonHideAllApps @Default(.tetheredButtonHideAllAppsTimerDate) var tetheredButtonHideAllAppsTimerDate @Default(.showHighlightedTextInput) var showHighlightedTextInput + @Default(.autoAddHighlightedTextToContext) var autoAddHighlightedTextToContext @State var isLaunchAtStartupEnabled: Bool = SMAppService.mainApp.status == .enabled @State var isAnalyticsEnabled: Bool = PostHogSDK.shared.isOptOut() == false @@ -434,6 +435,19 @@ struct GeneralTab: View { .controlSize(.small) } } + + VStack(alignment: .leading, spacing: 20) { + HStack { + Text("Auto-add highlighted text to context.") + .font(.system(size: 13)) + + Spacer() + + Toggle("", isOn: $autoAddHighlightedTextToContext) + .toggleStyle(.switch) + .controlSize(.small) + } + } } }