Skip to content

Conversation

@lk340
Copy link
Collaborator

@lk340 lk340 commented Jul 17, 2025

Summary

This PR tackles the "pinned" portion of the new text highlight experience.

Parts (Pin 1 and Pin 2 have been closed)

  1. Text Highlight: Update Highlighted Text Behavior #339
  2. Text Highlight: Auto-add To Context #340
  3. Text Highlight (Pin - 1): Update to Data Files and OnitPanelState #342 (Pin 1)
  4. Text Highlight (Pin - 2): Update to Managers and UI #343 (Pin 2)
  5. YOU ARE HERE (Pin 3)

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Greptile Summary

This PR updates the FileRow component to support pinned text highlighting functionality. The key changes include:

  • Splitting highlighted text items into separate unpinned and pinned sections
  • Adding state management for transitions between pinned/unpinned states
  • Implementing morphing behavior between ghost tags and context tags
  • Adding proper cleanup for UI elements when removing highlighted text items

This is part 3 of a larger feature implementation, focusing specifically on the FileRow component updates. The changes maintain backward compatibility while adding new pinning capabilities.

Confidence score: 4/5

  1. This PR appears safe to merge as it's a well-isolated component update with clear state management
  2. The high score is due to the focused scope and clear separation of concerns in the implementation
  3. Key files to review:
    • macos/Onit/UI/Prompt/Files/FileRow.swift - Verify the state transitions between pinned/unpinned items

1 file reviewed, no comments
Edit PR Review Bot Settings | Greptile

@lk340 lk340 changed the base branch from feature/text-highlight/accessibility-and-shortcuts-managers to feature/text-highlight/auto-add-to-context July 17, 2025 21:46
@lk340 lk340 changed the base branch from feature/text-highlight/auto-add-to-context to feature/text-highlight/updated-input-view-behavior July 18, 2025 12:59
@lk340 lk340 changed the title Text Highlight (Pin - 3): FileRow Update Text Highlight: Pin Jul 18, 2025
lk340 added 5 commits July 18, 2025 12:02
… with pinned text highlight updates.

* `AccessibliityNotificationsManager` now properly handles removing `InputView` from the UI when it matches the current highlighted text, and the current highlighted text is about to be removed.
* `AccessibliityNotificationsManager` also now handles setting the unpinned highlighted context and showing it in the UI.
* `KeyboardShortcutsManager` now clears all states related to highlighted text.
* Add pin icon.
* ContextTag can now handle the pin action and shows pinned corner icon when pinned.
* ExternalTetheredButton now accounts for both auto-highlighted and tracked highlighted text.
* InputView `smallRemove` button now clears the unpinned highlighted text context tag when it matches the removed InputView text.
* Update FinalContextView to now show full array of input (highlighted text) contexts.
* Update PromptCore to properly show the selected highlighted text context.
@lk340 lk340 force-pushed the feature/text-highlight/file-row-updates branch from abd8a3a to 916f84b Compare July 18, 2025 16:12
Copy link
Contributor

@timlenardo timlenardo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @lk340 - thanks for getting this up! Unfortunately, I am unable to run it due to a crash that occurs when I try to instantiate the data container, now that the SwiftData has changed.

Fixing this is going to be a big task, and it feels like a niche product. How many people will really want to pin lots of highlighted text? It doesn't seem like a major user behavior, so I think we should set this aside for now and revisit it after we've addressed some more pressing matters.

Regardless, I left some comments so you can understand the issues.

let pendingInputs = inputs[index]

if let input = inputs[index], !input.selectedText.isEmpty {
message += "\n\nUse the following selected text as context. When present, selected text should take priority over other context."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also update this to respect the ordering of the selected text. For example, if there's 4 highlighted text sections pinned and they send a prompt like "rephrase this", I think they're probably referring to the most recently added highlight.

So this prompt should be modified to say like "the selected text should be given priority in the order they appear", and then we need to make sure that the most recent highlighted text is added first (which probably isn't the default, since we most likely use 'append').

} else if state.pendingInput != nil {
state.pendingInput = nil
} else if state.hasHighlightedText {
state.clearHighlightedTextStates()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting. I wonder if this should only clear out the most recent, instead of all of them. It seems like it might be irritating if you hit Escape by accident and it clears your entire context window.

Without really playing with it, my intuition is that we should:

  1. Only do this if the user is in the mode where highlights get auto-added.
  2. Only do it for the automatically added highlight, not any that they've pinned.

private let borderColor: Color?
private let iconBundleURL: URL?
private let iconView: (any View)?
private let iconViewCornerIcon: ImageResource?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'd probably call this the 'leftIcon' and 'rightIcon' instead of 'iconView' and 'iconViewCornerIcon'. That's what this new field is, right? It's a new right-aligned icon?

tooltip: String? = nil,
errorDotColor: Color? = nil,
action: (() -> Void)? = nil,
pinAction: (() -> Void)? = nil,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling this 'pinAction' makes it specific to pinning, which defeats the purpose of a general name like 'iconViewCornerIcon'. If we're only supporting a pin action, there's no need to pass in the CornerIcon; it can just be hardcoded. Alternatively, if we want to make this general, we should give both new fields corresponding generic names, like "rightIcon" and "rightIconAction." Either approach works for me since we have no immediate plans for anything other than pinning, but it should be one or the other.

var instruction: String
var timestamp: Date
var input: Input?
var inputs: [Input]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Were you able to get this code to run on your computer? It's insta-crashing for me. We can't change anything in any of the SwiftData model objects (Prompt, Chat, SystemPrompt, etc - search for the @model decorator) without writing a migration. In this case, transitioning from an optional Input to a non-optional input array results in a fatal error. Many of my old chats have a value of 'nil' for the 'input', which can't be converted into a non-optional array.

To reproduce the issue, checkout an older version of the app and send a prompt with no Input. Then, check out this branch and run it. You'll get a fatal error.

You can see some examples of migrations I've written in the past ('maybeUpdatePromptPriorInstructions' and 'maybeCleanupHangingPromptReferences') in SwiftDataContainer. It's a pain in the ass, but you have to do it if you want to change anything in Swift Data.

Comment on lines +119 to +128
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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From reading the code, I can't tell the difference between this icon and the hoverActionButton added below. Do we need both?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants