Skip to content
Closed
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 @@ -595,15 +595,32 @@ class AccessibilityNotificationsManager: ObservableObject {

showDebug()
}

private func clearPendingInputsOnInvalidSelectedText() {
let currentHighlightedTextIsInView = PanelStateCoordinator.shared.state.selectedPendingInput == PanelStateCoordinator.shared.state.unpinnedPendingInput


/// Clearing `InputView` when it's showing the current highlighted text that's about to be cleared.
if currentHighlightedTextIsInView {
PanelStateCoordinator.shared.state.selectedPendingInput = nil
}

PanelStateCoordinator.shared.state.unpinnedPendingInput = nil
PanelStateCoordinator.shared.state.trackedPendingInput = nil
}

private func addSelectedTextToContextAndShowInView(_ input: Input) {
PanelStateCoordinator.shared.state.selectedPendingInput = input
PanelStateCoordinator.shared.state.unpinnedPendingInput = input
}

private func processSelectedText(_ text: String?) {
guard Defaults[.autoContextFromHighlights],
let selectedText = text,
HighlightedTextValidator.isValid(text: selectedText) else {

screenResult.userInteraction.selectedText = nil
PanelStateCoordinator.shared.state.pendingInput = nil
PanelStateCoordinator.shared.state.trackedPendingInput = nil
clearPendingInputsOnInvalidSelectedText()
return
}

Expand All @@ -612,7 +629,7 @@ class AccessibilityNotificationsManager: ObservableObject {
let input = Input(selectedText: selectedText, application: currentSource ?? "")

if Defaults[.autoAddHighlightedTextToContext] {
PanelStateCoordinator.shared.state.pendingInput = input
addSelectedTextToContextAndShowInView(input)
} else {
PanelStateCoordinator.shared.state.trackedPendingInput = input
}
Expand Down
15 changes: 15 additions & 0 deletions macos/Onit/Assets.xcassets/Icons/pin.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "pin.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}
3 changes: 3 additions & 0 deletions macos/Onit/Assets.xcassets/Icons/pin.imageset/pin.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion macos/Onit/Data/Structures/Input.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import Foundation

struct Input: Codable, Equatable {
struct Input: Codable, Equatable, Hashable {
var selectedText: String
var application: String?
}
Expand Down
4 changes: 2 additions & 2 deletions macos/Onit/KeyboardShortcuts/KeyboardShortcutsManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ struct KeyboardShortcutsManager {
if state.panel != nil {
if state.showContextMenuBrowserTabs {
state.showContextMenuBrowserTabs = false
} else if state.pendingInput != nil {
state.pendingInput = nil
} else if state.hasHighlightedText {
state.clearHighlightedTextStates()
} else {
PanelStateCoordinator.shared.closePanel()
}
Expand Down
71 changes: 54 additions & 17 deletions macos/Onit/UI/Components/ContextTag.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@ struct ContextTag: View {
private let shouldFadeIn: Bool
private let iconBundleURL: URL?
private let iconView: (any View)?
private let iconViewCornerIcon: ImageResource?
private let caption: String?
private let tooltip: String?
private let errorDotColor: Color?
private let action: (() -> Void)?
private let pinAction: (() -> Void)?
private let removeAction: (() -> Void)?

init(
Expand All @@ -37,10 +39,12 @@ struct ContextTag: View {
shouldFadeIn: Bool = false,
iconBundleURL: URL? = nil,
iconView: (any View)? = nil,
iconViewCornerIcon: ImageResource? = nil,
caption: String? = nil,
tooltip: String? = nil,
errorDotColor: Color? = nil,
action: (() -> Void)? = nil,
pinAction: (() -> Void)? = nil,
removeAction: (() -> Void)? = nil
) {
self.text = text
Expand All @@ -54,16 +58,18 @@ struct ContextTag: View {
self.shouldFadeIn = shouldFadeIn
self.iconBundleURL = iconBundleURL
self.iconView = iconView
self.iconViewCornerIcon = iconViewCornerIcon
self.caption = caption
self.tooltip = tooltip
self.errorDotColor = errorDotColor
self.action = action
self.pinAction = pinAction
self.removeAction = removeAction
}

@State private var isHoveredBody: Bool = false
@State private var isPressedBody: Bool = false
@State private var isHoveredRemove: Bool = false
@State private var isHoveredAction: Bool = false

private let height: CGFloat = 24

Expand All @@ -72,6 +78,10 @@ struct ContextTag: View {
return NSWorkspace.shared.icon(forFile: bundleUrl.path)
}

private var hasHoverActions: Bool {
pinAction != nil || removeAction != nil
}

var body: some View {
ZStack(alignment: .leading) {
HStack(alignment: .center, spacing: 6) {
Expand All @@ -97,7 +107,21 @@ struct ContextTag: View {
}

if let iconView = iconView {
AnyView(iconView)
ZStack(alignment: .bottomTrailing) {
AnyView(iconView)

if let cornerIcon = iconViewCornerIcon {
ZStack(alignment: .center) {
Circle()
.fill(isHoveredBody ? hoverBackground : background)
.frame(width: 13, height: 13)

Image(cornerIcon)
.addIconStyles(iconSize: 7.45)
}
.offset(x: 4, y: 4)
}
}
}

if isLoading { textView.shimmering() }
Expand All @@ -114,16 +138,29 @@ struct ContextTag: View {
}
}

HStack(spacing: 0) {
Spacer()

if let removeAction = removeAction {
if hasHoverActions {
HStack(spacing: 0) {
Spacer()
FadeHorizontal(color: hoverBackground)
removeButton(removeAction)

HStack(spacing: 6) {
if let pinAction = pinAction {
hoverActionButton(icon: .pin) {
pinAction()
}
}

if let removeAction = removeAction {
hoverActionButton(icon: .cross) {
removeAction()
}
}
}
}
.frame(height: height)
.opacity(isHoveredBody ? 1 : 0)
}
.frame(height: height)
.opacity(isHoveredBody ? 1 : 0)
}
.padding(.leading, 4)
.padding(.trailing, 6)
Expand Down Expand Up @@ -173,26 +210,26 @@ extension ContextTag {
Text(text)
.styleText(
size: 12,
color: isHoveredRemove ? .T_3 : isHoveredBody ? hoverTextColor : textColor
color: isHoveredAction ? .T_3 : isHoveredBody ? hoverTextColor : textColor
)
.truncateText()
.addAnimation(dependency: [isHoveredBody, isHoveredRemove])
.addAnimation(dependency: [isHoveredBody, isHoveredAction])
}

private func removeButton(_ removeAction: @escaping () -> Void) -> some View {
private func hoverActionButton(icon: ImageResource, hoverAction: @escaping () -> Void) -> some View {
Button {
removeAction()
hoverAction()
} label: {
Image(.cross)
Image(icon)
.addIconStyles(
foregroundColor: isHoveredRemove ? .white : .gray100,
foregroundColor: isHoveredAction ? Color.primary : .gray100,
iconSize: 9
)
.addAnimation(dependency: isHoveredRemove)
.addAnimation(dependency: isHoveredAction)
}
.background(hoverBackground)
.onHover { isHovering in
isHoveredRemove = isHovering
isHoveredAction = isHovering
}
}
}
2 changes: 1 addition & 1 deletion macos/Onit/UI/Content/ExternalTetheredButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ struct ExternalTetheredButton: View {
}

private var capturedHighlightedText: Bool {
return windowState?.pendingInput != nil
return windowState?.unpinnedPendingInput != nil || windowState?.trackedPendingInput != nil
}

private var foregroundWindowIcon: NSImage? {
Expand Down
4 changes: 4 additions & 0 deletions macos/Onit/UI/Panels/State/OnitPanelState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ class OnitPanelState: NSObject {
}

var pinnedPendingInputs: [Input] = []

var hasHighlightedText: Bool {
selectedPendingInput != nil || trackedPendingInput != nil || unpinnedPendingInput != nil || !pinnedPendingInputs.isEmpty
}

func clearHighlightedTextStates() {
selectedPendingInput = nil
Expand Down
8 changes: 5 additions & 3 deletions macos/Onit/UI/Prompt/FinalContextView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ struct FinalContextView: View {
let prompt: Prompt

var usingContextOrInput: Bool {
usingContext || prompt.input != nil
usingContext || !prompt.inputs.isEmpty
}

var usingContext: Bool {
Expand Down Expand Up @@ -164,8 +164,10 @@ struct FinalContextView: View {
.buttonStyle(.plain)

if isExpanded {
if let input = prompt.input {
InputView(input: input, isEditing: false)
if !prompt.inputs.isEmpty {
ForEach(prompt.inputs, id: \.self) { input in
InputView(input: input, isEditing: false)
}
}

if usingContext {
Expand Down
2 changes: 1 addition & 1 deletion macos/Onit/UI/Prompt/Generated/GeneratedView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ struct GeneratedView: View {
#if DEBUG
#Preview {
var prompt = Prompt.sample
prompt.input = Input(selectedText: "blablabla", application: "Xcode")
prompt.inputs = [Input(selectedText: "blablabla", application: "Xcode")]

return GeneratedView(prompt: prompt)
}
Expand Down
14 changes: 12 additions & 2 deletions macos/Onit/UI/Prompt/Input/InputButtons.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ struct InputButtons: View {

var body: some View {
Group {
if let state = state, input == state.pendingInput {
if let state = state, input == state.selectedPendingInput {
Button {
state.pendingInput = nil
clearHighlightedText(state: state)

state.selectedPendingInput = nil
} label: {
Image(.smallRemove)
.renderingMode(.template)
Expand Down Expand Up @@ -57,6 +59,14 @@ struct InputButtons: View {
Defaults[.showHighlightedTextInput] = false
}
}

// MARK: - Private Functions

private func clearHighlightedText(state: OnitPanelState) {
if state.selectedPendingInput == state.unpinnedPendingInput {
state.unpinnedPendingInput = nil
}
}
}

#if DEBUG
Expand Down
4 changes: 2 additions & 2 deletions macos/Onit/UI/Prompt/PromptCore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ struct PromptCore: View {

var body: some View {
VStack(spacing: 0) {
if let windowState = windowState, let pendingInput = windowState.pendingInput {
InputView(input: pendingInput)
if let windowState = windowState, let selectedPendingInput = windowState.selectedPendingInput {
InputView(input: selectedPendingInput)
}

VStack(spacing: 6) {
Expand Down