|
34 | 34 |
|
35 | 35 | $: inactive = $sessionState === "closed" || $sessionState === "readonly"; |
36 | 36 |
|
| 37 | + const MAX_COMMAND_LENGTH = 128; |
| 38 | + const COUNTER_THRESHOLD = Math.floor(MAX_COMMAND_LENGTH * 0.8); |
| 39 | + let commandValue = ""; |
| 40 | + $: remaining = MAX_COMMAND_LENGTH - commandValue.length; |
| 41 | + $: showCounter = commandValue.length >= COUNTER_THRESHOLD; |
| 42 | + $: counterColor = |
| 43 | + remaining <= 10 ? "text-red-400" : |
| 44 | + remaining <= 20 ? "text-yellow-400" : |
| 45 | + "text-gray-500"; |
| 46 | +
|
37 | 47 | let cleanClose = false; |
38 | 48 | let virtualConsole: VirtualConsole; |
39 | 49 | let reconnection: ReconnectionController; |
|
156 | 166 | } |
157 | 167 |
|
158 | 168 | function handleKeydown(e: KeyboardEvent) { |
159 | | - if (e.key === "Enter" && commandInput.value.trim() !== "") { |
160 | | - const commandText = commandInput.value.trim(); |
| 169 | + if (e.key === "Enter" && commandValue.trim() !== "") { |
| 170 | + const commandText = commandValue.trim(); |
161 | 171 | sendCommand(commandText); |
162 | 172 | commandHistory.unshift(commandText); |
163 | 173 | if (commandHistory.length > 50) commandHistory.pop(); |
164 | 174 | localStorage.setItem(HISTORY_KEY, JSON.stringify(commandHistory)); |
165 | 175 | historyIndex = -1; |
166 | | - commandInput.value = ""; |
| 176 | + commandValue = ""; |
167 | 177 | e.preventDefault(); |
168 | 178 | } else if (e.key === "ArrowUp") { |
169 | 179 | if (historyIndex < commandHistory.length - 1) { |
170 | 180 | historyIndex++; |
171 | | - commandInput.value = commandHistory[historyIndex]; |
| 181 | + commandValue = commandHistory[historyIndex]; |
172 | 182 | } |
173 | 183 | e.preventDefault(); |
174 | 184 | } else if (e.key === "ArrowDown") { |
175 | 185 | if (historyIndex >= 0) { |
176 | 186 | historyIndex--; |
177 | | - commandInput.value = historyIndex >= 0 ? commandHistory[historyIndex] : ""; |
| 187 | + commandValue = historyIndex >= 0 ? commandHistory[historyIndex] : ""; |
178 | 188 | } |
179 | 189 | e.preventDefault(); |
180 | 190 | } |
|
189 | 199 | <div class="flex items-center border-t border-gray-700 pt-3"> |
190 | 200 | <span class="{inactive ? 'text-gray-600' : 'text-green-400'} mr-2 shrink-0">></span> |
191 | 201 | <!-- svelte-ignore a11y-autofocus --> |
192 | | - <input type="text" bind:this={commandInput} on:keydown={handleKeydown} class="w-full bg-transparent border-none focus:ring-0 focus:outline-none {inactive ? 'text-gray-600 placeholder-gray-600 cursor-not-allowed' : 'text-gray-200 placeholder-gray-500'}" placeholder="{inactive ? 'Session ended' : 'Enter command...'}" autocomplete="off" autofocus disabled> |
| 202 | + <input type="text" bind:this={commandInput} bind:value={commandValue} maxlength={MAX_COMMAND_LENGTH} on:keydown={handleKeydown} class="w-full bg-transparent border-none focus:ring-0 focus:outline-none {inactive ? 'text-gray-600 placeholder-gray-600 cursor-not-allowed' : 'text-gray-200 placeholder-gray-500'}" placeholder="{inactive ? 'Session ended' : 'Enter command...'}" autocomplete="off" autofocus disabled> |
| 203 | + {#if showCounter} |
| 204 | + <span class="ml-2 text-xs font-mono tabular-nums shrink-0 {counterColor}">{remaining}</span> |
| 205 | + {/if} |
193 | 206 | </div> |
194 | 207 | </div> |
195 | 208 | </div> |
0 commit comments