From 01edc09385b017af45c0453fe9cfb0636afe1645 Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Wed, 21 Oct 2026 10:57:08 -0700 Subject: [PATCH] Share the composer and attention reply editor --- mac/Sources/Byre/Attention.swift | 30 +------------ mac/Sources/Byre/Composer.swift | 75 ++++++++++++++++++++------------ 2 files changed, 49 insertions(+), 56 deletions(-) diff --git a/mac/Sources/Byre/Attention.swift b/mac/Sources/Byre/Attention.swift index a76ce30..2ea80ab 100644 --- a/mac/Sources/Byre/Attention.swift +++ b/mac/Sources/Byre/Attention.swift @@ -78,35 +78,9 @@ private struct OtherEntry: View { if otherOpen(store, key) { VStack(alignment: .leading, spacing: 6) { Thumbnails(key: key) - TextEditor(text: $text) - .font(Fonts.font(13)) - .scrollContentBackground(.hidden) - .writingToolsBehavior(.disabled) - .focused($editing) + AgentEditor(text: $text, placeholder: placeholder, key: key, height: 66, + focus: $editing, border: editing ? Palette.accent : Palette.border, send: send) .disabled(busy) - .onKeyPress(.return, phases: .down) { press in - let marked = (NSApp.keyWindow?.firstResponder as? NSTextView)?.hasMarkedText() ?? false - if press.modifiers.contains(.shift) || marked { - return .ignored - } - send() - return .handled - } - .padding(.horizontal, 5) - .padding(.vertical, 6) - .frame(height: 66) - .background(Palette.raised, in: RoundedRectangle(cornerRadius: 6)) - .overlay(alignment: .topLeading) { - if text.isEmpty { - Text(placeholder) - .foregroundStyle(Palette.muted) - .padding(.horizontal, 10) - .padding(.vertical, 6) - .allowsHitTesting(false) - } - } - .overlay(RoundedRectangle(cornerRadius: 6).stroke(editing ? Palette.accent : Palette.border)) - .imageInput(key) } .onChange(of: editing) { if !editing { diff --git a/mac/Sources/Byre/Composer.swift b/mac/Sources/Byre/Composer.swift index c9ec4cd..e2ea79b 100644 --- a/mac/Sources/Byre/Composer.swift +++ b/mac/Sources/Byre/Composer.swift @@ -309,6 +309,48 @@ private struct ThumbRemove: View { } } +struct AgentEditor: View { + @Binding var text: String + let placeholder: String + let key: String + let height: CGFloat + var focus: FocusState.Binding + let border: Color + var borderWidth: CGFloat = 1 + let send: () -> Void + + var body: some View { + TextEditor(text: $text) + .font(Fonts.font(13)) + .scrollContentBackground(.hidden) + .writingToolsBehavior(.disabled) + .focused(focus) + .onKeyPress(.return, phases: .down) { press in + let marked = (NSApp.keyWindow?.firstResponder as? NSTextView)?.hasMarkedText() ?? false + if press.modifiers.contains(.shift) || marked { + return .ignored + } + send() + return .handled + } + .padding(.horizontal, 5) + .padding(.vertical, 6) + .frame(height: height) + .background(Palette.raised, in: RoundedRectangle(cornerRadius: 6)) + .overlay(alignment: .topLeading) { + if text.isEmpty { + Text(placeholder) + .foregroundStyle(Palette.muted) + .padding(.horizontal, 10) + .padding(.vertical, 6) + .allowsHitTesting(false) + } + } + .overlay(RoundedRectangle(cornerRadius: 6).stroke(border, lineWidth: borderWidth)) + .imageInput(key) + } +} + struct ComposerView: View { let chat: ChatModel let key: String @@ -497,34 +539,11 @@ struct ComposerView: View { } private var editor: some View { - TextEditor(text: $text) - .font(Fonts.font(13)) - .scrollContentBackground(.hidden) - .writingToolsBehavior(.disabled) - .focused($focused) - .onKeyPress(.return, phases: .down) { press in - let marked = (NSApp.keyWindow?.firstResponder as? NSTextView)?.hasMarkedText() ?? false - if press.modifiers.contains(.shift) || marked { - return .ignored - } - submit(modelState()) - return .handled - } - .padding(.horizontal, 5) - .padding(.vertical, 6) - .frame(height: 104) - .background(Palette.raised, in: RoundedRectangle(cornerRadius: 6)) - .overlay(alignment: .topLeading) { - if text.isEmpty { - Text(chat.placeholder) - .foregroundStyle(Palette.muted) - .padding(.horizontal, 10) - .padding(.vertical, 6) - .allowsHitTesting(false) - } - } - .overlay(RoundedRectangle(cornerRadius: 6).stroke(inRightPane ? accent : focused ? Palette.accent : Palette.border, lineWidth: inRightPane && focused ? 2 : 1)) - .imageInput(draftKey) + AgentEditor(text: $text, placeholder: chat.placeholder, key: draftKey, height: 104, + focus: $focused, border: inRightPane ? accent : focused ? Palette.accent : Palette.border, + borderWidth: inRightPane && focused ? 2 : 1) { + submit(modelState()) + } } private func reportDraft() {