diff --git a/ui/app/pages/console.vue b/ui/app/pages/console.vue index a7b16ee3..dcaaae5a 100644 --- a/ui/app/pages/console.vue +++ b/ui/app/pages/console.vue @@ -2,6 +2,15 @@ .terminal { padding-left: 10px; } + +.history-item { + cursor: pointer; + transition: background-color 0.2s; +} + +.history-item:hover { + background-color: #f5f5f5; +} @@ -68,11 +119,13 @@ import { useStorage } from '@vueuse/core' import { disableOpacity, enableOpacity } from '~/utils' import InputAutocomplete from '~/components/InputAutocomplete.vue' import TextareaAutocomplete from '~/components/TextareaAutocomplete.vue' +import { useDialog } from '~/composables/useDialog' import type { AutoCompleteOptions } from '~/types/autocomplete' const config = useConfigStore() const socket = useSocketStore() const toast = useNotification() +const dialog = useDialog() const terminal = ref() const terminalFit = ref() @@ -82,6 +135,9 @@ const commandInput = ref | null>(null) const commandTextarea = ref | null>(null) const isLoading = ref(false) const storedCommand = useStorage('console_command', '') +const commandHistory = useStorage('console_command_history', []) +const isHistoryCollapsed = useStorage('console_history_collapsed', false) +const MAX_HISTORY_ITEMS = 50 const ytDlpOptions = computed(() => config.ytdlp_options.flatMap(opt => opt.flags .map(flag => ({ value: flag, description: opt.description || '' })) @@ -94,6 +150,9 @@ watch(() => isLoading.value, async value => { if (value) { return } + if (command.value.trim()) { + addToHistory(command.value.trim()) + } command.value = '' await nextTick(); focusInput() @@ -256,6 +315,33 @@ const focusInput = async () => { elm?.focus() } +const addToHistory = (cmd: string) => { + commandHistory.value = [cmd, ...commandHistory.value.filter(h => h !== cmd)].slice(0, MAX_HISTORY_ITEMS) +} + +const loadCommand = async (cmd: string) => { + command.value = cmd + await nextTick() + focusInput() +} + +const clearHistory = async () => { + if (commandHistory.value.length === 0) { + return + } + const { status } = await dialog.confirmDialog({ + title: 'Confirm Action', + message: `Clear commands history?`, + confirmColor: 'is-danger', + }) + if (!status) { + return + } + commandHistory.value = [] +} + +const removeFromHistory = (index: number) => commandHistory.value = commandHistory.value.filter((_, i) => i !== index) + const writer = (s: string) => { if (!terminal.value) { return