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
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions macos/Onit/Data/Persistence/Defaults.swift
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ extension Defaults.Keys {
static let lineHeight = Key<Double>("lineHeight", default: 1.5)
static let voiceSilenceThreshold = Key<Float>("voiceSilenceThreshold", default: -40)
static let voiceSpeechPassThreshold = Key<Double>("voiceSpeechPassThreshold", default: 0.7)
/// Highlighted Text
static let showHighlightedTextInput = Key<Bool>("showHighlightedTextInput", default: true)
static let autoAddHighlightedTextToContext = Key<Bool>("autoAddHighlightedTextToContext", default: true)

// Local model advanced options
static let localKeepAlive = Key<String?>("localKeepAlive", default: nil)
Expand Down
14 changes: 14 additions & 0 deletions macos/Onit/Helpers/StringHelpers.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// StringHelpers.swift
// Onit
//
// Created by Loyd Kim on 7/18/25.
//

struct StringHelpers {
static func removeWhiteSpaceAndNewLines(_ str: String) -> String {
return str.replacingOccurrences(of: "\\r?\\n", with: " ", options: .regularExpression)
.replacingOccurrences(of: " +", with: " ", options: .regularExpression)
.trimmingCharacters(in: .whitespacesAndNewlines)
}
}
10 changes: 8 additions & 2 deletions macos/Onit/UI/Components/ContextTag.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ struct ContextTag: View {
private let background: Color
private let hoverBackground: Color
private let hasHoverBorder: Bool
private let hasDottedBorder: Bool
private let maxWidth: CGFloat
private let isLoading: Bool
private let shouldFadeIn: Bool
private let borderColor: Color?
private let iconBundleURL: URL?
private let iconView: (any View)?
private let caption: String?
Expand All @@ -32,9 +34,11 @@ struct ContextTag: View {
background: Color = .gray500,
hoverBackground: Color = .gray400,
hasHoverBorder: Bool = false,
hasDottedBorder: Bool = false,
maxWidth: CGFloat = 155,
isLoading: Bool = false,
shouldFadeIn: Bool = false,
borderColor: Color? = nil,
iconBundleURL: URL? = nil,
iconView: (any View)? = nil,
caption: String? = nil,
Expand All @@ -49,9 +53,11 @@ struct ContextTag: View {
self.background = background
self.hoverBackground = hoverBackground
self.hasHoverBorder = hasHoverBorder
self.hasDottedBorder = hasDottedBorder
self.maxWidth = maxWidth
self.isLoading = isLoading
self.shouldFadeIn = shouldFadeIn
self.borderColor = borderColor
self.iconBundleURL = iconBundleURL
self.iconView = iconView
self.caption = caption
Expand Down Expand Up @@ -151,8 +157,8 @@ struct ContextTag: View {
.addAnimation(dependency: isHoveredBody)
.addBorder(
cornerRadius: 4,
stroke: hasHoverBorder && isHoveredBody ? .T_4 : .clear,
dotted: true
stroke: hasHoverBorder && isHoveredBody ? .T_4 : borderColor ?? .clear,
dotted: hasDottedBorder
)
.addButtonEffects(
background: background,
Expand Down
2 changes: 2 additions & 0 deletions macos/Onit/UI/Panels/State/OnitPanelState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ class OnitPanelState: NSObject {
}
}

var trackedPendingInput: Input? = nil

var systemPromptId: String = SystemPrompt.outputOnly.id

var imageUploads: [URL: UploadProgress] = [:]
Expand Down
87 changes: 75 additions & 12 deletions macos/Onit/UI/Prompt/Files/FileRow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ struct FileRow: View {
@ObservedObject private var debugManager = DebugManager.shared

@Default(.autoContextFromCurrentWindow) var autoContextFromCurrentWindow
@Default(.autoAddHighlightedTextToContext) var autoAddHighlightedTextToContext
@Default(.autoContextFromHighlights) var autoContextFromHighlights
@Default(.showHighlightedTextInput) var showHighlightedTextInput

@State private var ocrComparisonResult: OCRComparisonResult? = nil
@State private var showOCRDetails = false
Expand Down Expand Up @@ -119,9 +122,11 @@ struct FileRow: View {
FlowLayout(spacing: 6) {
PaperclipButton()

addForegroundWindowToContextButton
addWindowToContextButton
addHighlightedTextToContextButton
pendingWindowContextItems
addedWindowContextItems
highlightedTextContext
}

ocrDetailsLink
Expand Down Expand Up @@ -149,28 +154,71 @@ 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,
hasDottedBorder: true,
shouldFadeIn: true,
iconBundleURL: iconBundleURL,
iconView: iconView,
tooltip: tooltip
) {
action()
}
}

@ViewBuilder
private var addForegroundWindowToContextButton: some View {
private var addHighlightedTextToContextButton: some View {
if accessibilityEnabled,
autoContextFromHighlights,
let windowState = windowState,
let trackedPendingInput = windowState.trackedPendingInput
{
ghostContextTag(
text: StringHelpers.removeWhiteSpaceAndNewLines(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 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)
}
}
}
Expand Down Expand Up @@ -202,6 +250,21 @@ extension FileRow {
}
}

@ViewBuilder
private var highlightedTextContext: some View {
if let pendingInput = windowState?.pendingInput {
ContextTag(
text: StringHelpers.removeWhiteSpaceAndNewLines(pendingInput.selectedText),
borderColor: showHighlightedTextInput ? .gray400 : .clear,
iconView: Image(.text).addIconStyles(iconSize: 14)
) {
showHighlightedTextInput = true
} removeAction: {
windowState?.pendingInput = nil
}
}
}

@ViewBuilder
private var addedWindowContextItems: some View {
if !contextList.isEmpty {
Expand Down
2 changes: 1 addition & 1 deletion macos/Onit/UI/Prompt/Input/InputBody.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ struct InputBody: View {
}

var height: CGFloat {
min(textHeight, 73)
min(textHeight, 222)
}

var body: some View {
Expand Down
15 changes: 9 additions & 6 deletions macos/Onit/UI/Prompt/Input/InputButtons.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// Created by Benjamin Sage on 10/8/24.
//

import Defaults
import SwiftUI

struct InputButtons: View {
Expand All @@ -13,6 +14,7 @@ struct InputButtons: View {
@Binding var inputExpanded: Bool

var input: Input
var isEditing: Bool

var body: some View {
Group {
Expand All @@ -26,18 +28,19 @@ struct InputButtons: View {
.buttonStyle(DarkerButtonStyle())
}

CopyButton(text: input.selectedText)
.frame(width: 20, height: 20)

Button {
inputExpanded.toggle()
if isEditing {
Defaults[.showHighlightedTextInput] = false
} else {
inputExpanded.toggle()
}
} label: {
Color.clear
.frame(width: 20, height: 20)
.overlay {
Image(.smallChevRight)
.renderingMode(.template)
.rotationEffect(inputExpanded ? .degrees(90) : .zero)
.rotationEffect(isEditing ? .degrees(90) : inputExpanded ? .degrees(-90) : .degrees(90))
}
}
}
Expand All @@ -47,6 +50,6 @@ struct InputButtons: View {

#if DEBUG
#Preview {
InputButtons(inputExpanded: .constant(true), input: .sample)
InputButtons(inputExpanded: .constant(true), input: .sample, isEditing: true)
}
#endif
15 changes: 8 additions & 7 deletions macos/Onit/UI/Prompt/Input/InputTitle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,31 @@ import SwiftUI
struct InputTitle: View {
@Binding var inputExpanded: Bool
var input: Input
var isEditing: Bool

var sourceString: String {
guard let sourceText = input.application else { return "" }
return " - \(sourceText)"
return " [\(sourceText)]"
}

var inputString: String {
"Input\(sourceString)"
"From\(sourceString)"
}

var body: some View {
HStack(spacing: 8) {
HStack(alignment: .center, spacing: 8) {
Text(inputString)
.appFont(.medium13)
.appFont(.medium12)
.textSelection(.enabled)
Spacer()
InputButtons(inputExpanded: $inputExpanded, input: input)
InputButtons(inputExpanded: $inputExpanded, input: input, isEditing: isEditing)
}
.foregroundStyle(.gray100)
.padding(.horizontal, 12)
.padding(.vertical, 8)
.padding(.vertical, 4)
}
}

#Preview {
InputTitle(inputExpanded: .constant(true), input: .sample)
InputTitle(inputExpanded: .constant(true), input: .sample, isEditing: true)
}
19 changes: 10 additions & 9 deletions macos/Onit/UI/Prompt/Input/InputView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,32 @@
// Created by Benjamin Sage on 10/3/24.
//

import Defaults
import SwiftUI

struct InputView: View {

@State var inputExpanded: Bool = true

var input: Input
var isEditing: Bool = true

@State var inputExpanded: Bool = false

var body: some View {
VStack(spacing: 0) {
InputTitle(inputExpanded: $inputExpanded, input: input)
InputTitle(inputExpanded: $inputExpanded, input: input, isEditing: isEditing)
divider
InputBody(inputExpanded: $inputExpanded, input: input)
}
.background {
RoundedRectangle(cornerRadius: 10)
.fill(.gray800)
.strokeBorder(.gray600)
RoundedRectangle(cornerRadius: 6)
.fill(.gray500)
.strokeBorder(.gray400)
}
.padding([.horizontal, .top], isEditing ? 12 : 0)
.padding(.top, isEditing ? 6 : 0)
.padding([.horizontal], isEditing ? 8 : 0)
}

var divider: some View {
Color.gray600
Color.gray400
.frame(height: 1)
.opacity(inputExpanded ? 1 : 0)
}
Expand Down
Loading