generated from nhcarrigan/template
feat: input history (both text and commands)
This commit is contained in:
@@ -23,6 +23,9 @@
|
|||||||
type SlashCommand,
|
type SlashCommand,
|
||||||
} from "$lib/commands/slashCommands";
|
} from "$lib/commands/slashCommands";
|
||||||
|
|
||||||
|
const INPUT_HISTORY_KEY = "hikari-input-history";
|
||||||
|
const MAX_HISTORY_SIZE = 100;
|
||||||
|
|
||||||
let inputValue = $state("");
|
let inputValue = $state("");
|
||||||
let isSubmitting = $state(false);
|
let isSubmitting = $state(false);
|
||||||
let isConnected = $state(false);
|
let isConnected = $state(false);
|
||||||
@@ -31,6 +34,44 @@
|
|||||||
let matchingCommands = $state<SlashCommand[]>([]);
|
let matchingCommands = $state<SlashCommand[]>([]);
|
||||||
let selectedCommandIndex = $state(0);
|
let selectedCommandIndex = $state(0);
|
||||||
|
|
||||||
|
// Input history state
|
||||||
|
let inputHistory = $state<string[]>([]);
|
||||||
|
let historyIndex = $state(-1);
|
||||||
|
let tempInput = $state("");
|
||||||
|
|
||||||
|
// Load history from localStorage on init
|
||||||
|
function loadHistory(): string[] {
|
||||||
|
try {
|
||||||
|
const stored = localStorage.getItem(INPUT_HISTORY_KEY);
|
||||||
|
return stored ? JSON.parse(stored) : [];
|
||||||
|
} catch {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveHistory(history: string[]) {
|
||||||
|
try {
|
||||||
|
localStorage.setItem(INPUT_HISTORY_KEY, JSON.stringify(history));
|
||||||
|
} catch {
|
||||||
|
// Ignore storage errors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addToHistory(input: string) {
|
||||||
|
const trimmed = input.trim();
|
||||||
|
if (!trimmed) return;
|
||||||
|
|
||||||
|
// Don't add duplicates of the most recent entry
|
||||||
|
if (inputHistory.length > 0 && inputHistory[0] === trimmed) return;
|
||||||
|
|
||||||
|
// Add to front of history
|
||||||
|
inputHistory = [trimmed, ...inputHistory.slice(0, MAX_HISTORY_SIZE - 1)];
|
||||||
|
saveHistory(inputHistory);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize history on mount
|
||||||
|
inputHistory = loadHistory();
|
||||||
|
|
||||||
claudeStore.connectionStatus.subscribe((status) => {
|
claudeStore.connectionStatus.subscribe((status) => {
|
||||||
isConnected = status === "connected";
|
isConnected = status === "connected";
|
||||||
});
|
});
|
||||||
@@ -40,6 +81,10 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
function handleInputChange() {
|
function handleInputChange() {
|
||||||
|
// Reset history navigation when user types
|
||||||
|
historyIndex = -1;
|
||||||
|
tempInput = "";
|
||||||
|
|
||||||
if (isSlashCommand(inputValue)) {
|
if (isSlashCommand(inputValue)) {
|
||||||
matchingCommands = getMatchingCommands(inputValue);
|
matchingCommands = getMatchingCommands(inputValue);
|
||||||
showCommandMenu = matchingCommands.length > 0;
|
showCommandMenu = matchingCommands.length > 0;
|
||||||
@@ -76,6 +121,11 @@
|
|||||||
|
|
||||||
// Check for slash commands first (these work even when disconnected)
|
// Check for slash commands first (these work even when disconnected)
|
||||||
if (isSlashCommand(message)) {
|
if (isSlashCommand(message)) {
|
||||||
|
// Add slash commands to history too
|
||||||
|
addToHistory(message);
|
||||||
|
historyIndex = -1;
|
||||||
|
tempInput = "";
|
||||||
|
|
||||||
const wasCommand = await executeSlashCommand();
|
const wasCommand = await executeSlashCommand();
|
||||||
if (wasCommand) return;
|
if (wasCommand) return;
|
||||||
// If it started with / but wasn't a valid command, show error
|
// If it started with / but wasn't a valid command, show error
|
||||||
@@ -90,6 +140,11 @@
|
|||||||
// Regular messages require connection
|
// Regular messages require connection
|
||||||
if (!isConnected) return;
|
if (!isConnected) return;
|
||||||
|
|
||||||
|
// Add to history before clearing
|
||||||
|
addToHistory(message);
|
||||||
|
historyIndex = -1;
|
||||||
|
tempInput = "";
|
||||||
|
|
||||||
isSubmitting = true;
|
isSubmitting = true;
|
||||||
inputValue = "";
|
inputValue = "";
|
||||||
|
|
||||||
@@ -222,6 +277,32 @@ User: ${formattedMessage}`;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle input history navigation (when command menu is closed)
|
||||||
|
if (event.key === "ArrowUp" && inputHistory.length > 0) {
|
||||||
|
event.preventDefault();
|
||||||
|
if (historyIndex === -1) {
|
||||||
|
// Save current input before navigating history
|
||||||
|
tempInput = inputValue;
|
||||||
|
}
|
||||||
|
if (historyIndex < inputHistory.length - 1) {
|
||||||
|
historyIndex++;
|
||||||
|
inputValue = inputHistory[historyIndex];
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.key === "ArrowDown" && historyIndex >= 0) {
|
||||||
|
event.preventDefault();
|
||||||
|
historyIndex--;
|
||||||
|
if (historyIndex === -1) {
|
||||||
|
// Restore the temp input when going back to current
|
||||||
|
inputValue = tempInput;
|
||||||
|
} else {
|
||||||
|
inputValue = inputHistory[historyIndex];
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (event.key === "Enter" && !event.shiftKey) {
|
if (event.key === "Enter" && !event.shiftKey) {
|
||||||
handleSubmit(event);
|
handleSubmit(event);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user