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
4 changes: 3 additions & 1 deletion packages/app/src/components/prompt-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
let scrollRef!: HTMLDivElement
let slashPopoverRef!: HTMLDivElement
let restoreEndOnFocus = true
let savedCursor: number | null = null

const mirror = { input: false }
const inset = 56
Expand Down Expand Up @@ -590,7 +591,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {

const restoreFocus = () => {
requestAnimationFrame(() => {
const cursor = prompt.cursor() ?? promptLength(prompt.current())
const cursor = savedCursor ?? prompt.cursor() ?? promptLength(prompt.current())
editorRef.focus()
setCursorPosition(editorRef, cursor)
queueScroll()
Expand Down Expand Up @@ -627,6 +628,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
const isImeComposing = (event: KeyboardEvent) => event.isComposing || composing() || event.keyCode === 229

const handleBlur = () => {
savedCursor = currentCursor()
closePopover()
setComposing(false)
}
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/components/settings-v2/settings-v2.css
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@
overflow: hidden;
font-size: 13px;
font-weight: 440;
line-height: 1;
line-height: 16px;
text-overflow: ellipsis;
white-space: nowrap;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/components/titlebar-tab-popover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { createSignal, Show, type JSXElement } from "solid-js"
import "./titlebar-tab-popover.css"

// Initial hover delay before the preview appears, per design.
const OPEN_DELAY = 200
const OPEN_DELAY = 400
// Mouse-out delay: begin closing immediately (a brief exit animation plays).
const CLOSE_DELAY = 0
// After a preview closes, hovering a neighbouring tab within this window skips
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1393,14 +1393,14 @@ export function MessageTimeline(props: {
<button
type="button"
data-slot="session-title-parent"
class="min-w-0 max-w-[40%] truncate px-2 text-[13px] font-[530] leading-4 tracking-[-0.04px] text-v2-text-text-faint transition-colors hover:text-v2-text-text-muted"
class="min-w-0 max-w-[40%] truncate pl-2 text-[13px] font-[530] leading-4 tracking-[-0.04px] text-v2-text-text-faint transition-colors hover:text-v2-text-text-muted"
onClick={navigateParent}
>
{parentTitle()}
</button>
<span
data-slot="session-title-separator"
class="-translate-y-[0.5px] px-1 text-[11px] font-medium text-v2-text-text-faint"
class="-translate-y-[0.5px] pl-2 pr-1 text-[11px] font-medium text-v2-text-text-faint"
aria-hidden="true"
>
/
Expand Down
17 changes: 16 additions & 1 deletion packages/app/src/pages/session/use-composer-commands.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useLanguage } from "@/context/language"
import { useLocal } from "@/context/local"
import { useSettings } from "@/context/settings"
import { useDialog } from "@opencode-ai/ui/context/dialog"
import { getCursorPosition, setCursorPosition } from "@/components/prompt-input/editor-dom"
import { useSessionLayout } from "./session-layout"
import { createSessionOwnership } from "./session-ownership"

Expand All @@ -26,9 +27,23 @@ export const useComposerCommands = () => {

const chooseModel = async () => {
const owner = sessionOwnership.capture()
const editor = document.querySelector<HTMLElement>('[data-component="prompt-input"]')
const selection = window.getSelection()
const cursor =
editor && selection?.rangeCount && editor.contains(selection.anchorNode) ? getCursorPosition(editor) : null
const restoreComposer = () => {
// Kobalte restores focus during its teardown effect; defer past it so the
// composer keeps focus and the caret returns to where the user left it.
requestAnimationFrame(() => {
const editor = document.querySelector<HTMLElement>('[data-component="prompt-input"]')
if (!editor) return
editor.focus()
if (cursor !== null) setCursorPosition(editor, cursor)
})
}
const { DialogSelectModel } = await import("@/components/dialog-select-model")
owner.run(() => {
void dialog.show(() => <DialogSelectModel model={local.model} />)
void dialog.show(() => <DialogSelectModel model={local.model} />, restoreComposer)
})
}

Expand Down
Loading