Changeset 0.20.0 (#85)
This commit is contained in:
@@ -37,12 +37,37 @@ const ChatInput = {
|
||||
return this._textarea;
|
||||
},
|
||||
|
||||
/** Get the visible input element (for positioning, getBoundingClientRect) */
|
||||
get el() {
|
||||
if (this._editor) return this._editor.getView().dom;
|
||||
return this._textarea;
|
||||
},
|
||||
|
||||
/** Get the wrapper DOM element (for resize, etc.) */
|
||||
getWrapDom() {
|
||||
if (this._editor) return this._editor.getView().dom;
|
||||
return this._textarea;
|
||||
},
|
||||
|
||||
/** Get cursor byte offset (for @mention autocomplete) */
|
||||
getCursorPos() {
|
||||
if (this._editor) {
|
||||
const view = this._editor.getView();
|
||||
return view.state.selection.main.head;
|
||||
}
|
||||
return this._textarea?.selectionStart || 0;
|
||||
},
|
||||
|
||||
/** Set cursor byte offset (for @mention autocomplete) */
|
||||
setCursorPos(pos) {
|
||||
if (this._editor) {
|
||||
const view = this._editor.getView();
|
||||
view.dispatch({ selection: { anchor: pos } });
|
||||
} else if (this._textarea) {
|
||||
this._textarea.selectionStart = this._textarea.selectionEnd = pos;
|
||||
}
|
||||
},
|
||||
|
||||
/** Initialize — try CM6, fall back to textarea */
|
||||
init() {
|
||||
this._textarea = document.getElementById('messageInput');
|
||||
@@ -54,20 +79,35 @@ const ChatInput = {
|
||||
this._editor = CM.chatInput(wrap, {
|
||||
placeholder: 'Send a message...',
|
||||
onSubmit: () => sendMessage(),
|
||||
onChange: () => updateInputTokens(),
|
||||
onChange: () => {
|
||||
updateInputTokens();
|
||||
// @mention autocomplete (v0.20.0)
|
||||
if (typeof ChannelModels !== 'undefined') ChannelModels.onInput(ChatInput);
|
||||
},
|
||||
maxHeight: 200,
|
||||
});
|
||||
// @mention autocomplete: intercept keys on CM6 contentDOM (v0.20.0)
|
||||
this._editor.getView().contentDOM.addEventListener('keydown', (e) => {
|
||||
if (typeof ChannelModels !== 'undefined' && ChannelModels.handleKey(e)) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
});
|
||||
DebugLog?.push?.('chat', '[CM6] Chat input initialized');
|
||||
} else {
|
||||
// Fallback: textarea with manual event handling
|
||||
DebugLog?.push?.('chat', '[CM6] Not available — using textarea fallback');
|
||||
this._textarea.addEventListener('keydown', (e) => {
|
||||
// @mention autocomplete intercepts arrow/enter/escape (v0.20.0)
|
||||
if (typeof ChannelModels !== 'undefined' && ChannelModels.handleKey(e)) return;
|
||||
if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); sendMessage(); }
|
||||
});
|
||||
this._textarea.addEventListener('input', function() {
|
||||
this.style.height = 'auto';
|
||||
this.style.height = Math.min(this.scrollHeight, 200) + 'px';
|
||||
updateInputTokens();
|
||||
// @mention autocomplete (v0.20.0)
|
||||
if (typeof ChannelModels !== 'undefined') ChannelModels.onInput(this);
|
||||
});
|
||||
}
|
||||
},
|
||||
@@ -202,6 +242,9 @@ async function selectChat(chatId) {
|
||||
// Restore the last-used model/preset for this chat
|
||||
_restoreChatModel(chatId, chat);
|
||||
|
||||
// Load multi-model roster for @mention routing (v0.20.0)
|
||||
if (typeof ChannelModels !== 'undefined') ChannelModels.load(chatId);
|
||||
|
||||
// Load attachments for message rendering (non-blocking, best-effort)
|
||||
await loadChannelAttachments(chatId);
|
||||
|
||||
@@ -827,6 +870,9 @@ function _initChatListeners() {
|
||||
// Input — CM6 or textarea fallback
|
||||
ChatInput.init();
|
||||
|
||||
// Multi-model channel roster (v0.20.0)
|
||||
if (typeof ChannelModels !== 'undefined') ChannelModels.init();
|
||||
|
||||
// Close modals on overlay click
|
||||
document.querySelectorAll('.modal-overlay').forEach(overlay => {
|
||||
overlay.addEventListener('click', (e) => {
|
||||
|
||||
Reference in New Issue
Block a user