@@ -115,6 +115,7 @@ export function addCopyButtons() {
115115
116116export function useChatPrompt ( ctx ) {
117117 const messageText = ref ( '' )
118+ const promptHistory = ref ( [ ] )
118119 const attachedFiles = ref ( [ ] )
119120 const hasImage = ( ) => attachedFiles . value . some ( f => imageExts . includes ( lastRightPart ( f . name , '.' ) ) )
120121 const hasAudio = ( ) => attachedFiles . value . some ( f => audioExts . includes ( lastRightPart ( f . name , '.' ) ) )
@@ -363,6 +364,7 @@ export function useChatPrompt(ctx) {
363364 createContent,
364365 createRequest,
365366 applySettings,
367+ promptHistory,
366368 messageText,
367369 attachedFiles,
368370 editingMessage,
@@ -420,6 +422,7 @@ const ChatPrompt = {
420422 <textarea
421423 ref="refMessage"
422424 v-model="messageText"
425+ @keydown="onKeyDown"
423426 @keydown.enter.exact.prevent="sendMessage"
424427 @keydown.enter.shift.exact="addNewLine"
425428 @paste="onPaste"
@@ -491,6 +494,7 @@ const ChatPrompt = {
491494 const config = ctx . state . config
492495 const {
493496 messageText,
497+ promptHistory,
494498 hasImage,
495499 hasAudio,
496500 hasFile,
@@ -500,6 +504,8 @@ const ChatPrompt = {
500504 const fileInput = ref ( null )
501505 const refMessage = ref ( null )
502506 const showSettings = ref ( false )
507+ const historyIndex = ref ( - 1 )
508+ const isNavigatingHistory = ref ( false )
503509
504510 // File attachments (+) handlers
505511 const triggerFilePicker = ( ) => {
@@ -639,6 +645,14 @@ const ChatPrompt = {
639645 // 1. Construct Structured Content (Text + Attachments)
640646 let text = messageText . value . trim ( )
641647
648+ if ( text ) {
649+ const idx = promptHistory . value . indexOf ( text )
650+ if ( idx !== - 1 ) {
651+ promptHistory . value . splice ( idx , 1 )
652+ }
653+ promptHistory . value . push ( text )
654+ }
655+
642656 messageText . value = ''
643657 let content = ctx . chat . createContent ( { text, files : ctx . chat . attachedFiles . value } )
644658
@@ -742,6 +756,49 @@ const ChatPrompt = {
742756 //messageText.value += '\n'
743757 }
744758
759+ const onKeyDown = ( e ) => {
760+ if ( e . key === 'ArrowUp' ) {
761+ if ( refMessage . value . selectionStart === 0 && refMessage . value . selectionEnd === 0 ) {
762+ if ( promptHistory . value . length > 0 ) {
763+ e . preventDefault ( )
764+ if ( historyIndex . value === - 1 ) {
765+ historyIndex . value = promptHistory . value . length - 1
766+ } else {
767+ historyIndex . value = Math . max ( 0 , historyIndex . value - 1 )
768+ }
769+ isNavigatingHistory . value = true
770+ messageText . value = promptHistory . value [ historyIndex . value ]
771+ nextTick ( ( ) => {
772+ refMessage . value . setSelectionRange ( 0 , 0 )
773+ } )
774+ }
775+ }
776+ } else if ( e . key === 'ArrowDown' ) {
777+ if ( historyIndex . value !== - 1 ) {
778+ e . preventDefault ( )
779+ if ( historyIndex . value < promptHistory . value . length - 1 ) {
780+ historyIndex . value ++
781+ isNavigatingHistory . value = true
782+ messageText . value = promptHistory . value [ historyIndex . value ]
783+ } else {
784+ historyIndex . value = - 1
785+ isNavigatingHistory . value = true
786+ messageText . value = ''
787+ }
788+ nextTick ( ( ) => {
789+ refMessage . value . setSelectionRange ( 0 , 0 )
790+ } )
791+ }
792+ }
793+ }
794+
795+ watch ( messageText , ( newValue ) => {
796+ if ( ! isNavigatingHistory . value ) {
797+ historyIndex . value = - 1
798+ }
799+ isNavigatingHistory . value = false
800+ } )
801+
745802 watch ( ( ) => ctx . state . selectedAspectRatio , newValue => {
746803 ctx . setPrefs ( { aspectRatio : newValue } )
747804 } )
@@ -769,6 +826,7 @@ const ChatPrompt = {
769826 removeAttachment,
770827 sendMessage,
771828 addNewLine,
829+ onKeyDown,
772830 imageAspectRatios,
773831 }
774832 }
0 commit comments