diff --git a/frontend/index.html b/frontend/index.html index cc11671..cfc5ecf 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -144,7 +144,18 @@ - + @@ -258,8 +269,24 @@
主机密钥--
- - + +
@@ -295,9 +322,12 @@ aria-controls="file-manager-panel" aria-expanded="false" tabindex="0" + aria-label="文件管理" + data-i18n-aria-label-zh="文件管理" + data-i18n-aria-label-en="Files" > - 文件管理 + 文件管理
diff --git a/frontend/src/main.ts b/frontend/src/main.ts index e515a9d..ec759e5 100644 --- a/frontend/src/main.ts +++ b/frontend/src/main.ts @@ -7,6 +7,7 @@ import { decryptPasswordResult, encryptPassword, isEncryptedPassword } from './p import { resolveConnectionControl, resolveConnectionPanel } from './ui-state'; import { classifyHostKey, SSH_FINGERPRINT_RE, type HostKeyPrompt } from './host-key'; import { FileManager, collectFileManagerElements } from './file-manager'; +import { resetTerminalForConnection } from './terminal-session'; import './style.css'; type AuthMethod = 'password' | 'publickey'; @@ -312,7 +313,7 @@ const ui = { function updateRevealPasswordButton(): void { const revealed = ui.password.type === 'text'; - ui.revealPassword.textContent = revealed ? bilingual('隐藏', 'Hide') : bilingual('显示', 'Show'); + ui.revealPassword.setAttribute('aria-pressed', revealed ? 'true' : 'false'); ui.revealPassword.setAttribute('aria-label', revealed ? bilingual('隐藏密码', 'Hide password') : bilingual('显示密码', 'Show password')); @@ -1467,7 +1468,7 @@ async function connect(): Promise { authorizationAbort = abortController; setState('connecting'); ui.terminalEmpty.hidden = true; - terminal.clear(); + resetTerminalForConnection(terminal); fitTerminal(false); const host = normalizeHost(ui.host.value); diff --git a/frontend/src/style.css b/frontend/src/style.css index ca49110..6e2721d 100644 --- a/frontend/src/style.css +++ b/frontend/src/style.css @@ -715,7 +715,7 @@ button:disabled { } .input-action-wrap input { - padding-right: 82px; + padding-right: 44px; } .input-action { @@ -723,6 +723,9 @@ button:disabled { top: 5px; right: 5px; bottom: 5px; + display: grid; + width: 34px; + place-items: center; border: 0; border-radius: 5px; background: var(--surface-2); @@ -732,6 +735,32 @@ button:disabled { text-transform: uppercase; } +.input-action:hover { + color: var(--text); +} + +.reveal-icon { + width: 16px; + height: 16px; + fill: none; + stroke: currentColor; + stroke-linecap: round; + stroke-linejoin: round; + stroke-width: 1.8; +} + +.reveal-icon-eye-off { + display: none; +} + +.input-action[aria-pressed='true'] .reveal-icon-eye { + display: none; +} + +.input-action[aria-pressed='true'] .reveal-icon-eye-off { + display: block; +} + .key-field { display: grid; gap: 9px; @@ -1014,6 +1043,10 @@ button:disabled { } .terminal-actions .toolbar-button { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 5px; padding: 5px 7px; border-color: #263642; background: #151f28; @@ -1168,6 +1201,17 @@ button:disabled { stroke-width: 1.7; } +.toolbar-button-icon { + width: 13px; + height: 13px; + flex: 0 0 auto; + fill: none; + stroke: currentColor; + stroke-linecap: round; + stroke-linejoin: round; + stroke-width: 1.8; +} + .dock-tab:hover { background: var(--surface-3); color: var(--text); @@ -1816,6 +1860,15 @@ button:disabled { .file-table th:nth-child(2) { width: 16%; } .file-table th:nth-child(3) { width: 16%; } .file-table th:nth-child(4) { width: 28%; } + + .button-label { + display: none; + } + + .dock-tab { + min-width: 0; + padding: 0 13px; + } } @media (max-width: 480px) { diff --git a/frontend/src/terminal-session.ts b/frontend/src/terminal-session.ts new file mode 100644 index 0000000..71b8a39 --- /dev/null +++ b/frontend/src/terminal-session.ts @@ -0,0 +1,10 @@ +const TERMINAL_RESET_SEQUENCE = '\x1bc'; + +interface WritableTerminal { + write(data: string): void; +} + +export function resetTerminalForConnection(terminal: WritableTerminal): void { + // Queue RIS behind pending SSH output so stale writes cannot land after the reset. + terminal.write(TERMINAL_RESET_SEQUENCE); +}