fix: WKWebView cursor/selection focus, theme restore on startup, status bar
All checks were successful
Build & Sign Wraith / Build Windows + Sign (push) Successful in 3m45s
All checks were successful
Build & Sign Wraith / Build Windows + Sign (push) Successful in 3m45s
Cursor blink + selection (ROOT CAUSE FOUND): - xterm.js v6 uses DOM renderer, not canvas. Cursor blink and selection both require CSS focus classes set by the hidden textarea's focus event. - WKWebView doesn't focus elements with opacity:0, width:0, height:0, left:-9999em — the textarea never receives focus, classes never toggle. - Fix: Override .xterm-helper-textarea to left:0, top:0, width:1px, height:1px, opacity:0.01 — within viewport, non-zero, focusable. Theme restoration on startup: - sessionStore.activeTheme started as null on every launch - ThemePicker saved active_theme to settings but nobody restored it - Added theme restoration to MainLayout onMounted — reads active_theme setting, fetches theme from backend, calls setTheme() before any terminals open Status bar: - h-10 (40px) to match toolbar height for visual balance Selection colors: - Solid #264f78 (VS Code selection blue) instead of rgba transparency Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c4335e0b4f
commit
a36793563c
@ -20,12 +20,16 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Selection styling — xterm.js v6 handles selection via canvas renderer.
|
/* WKWebView focus fix: xterm.js hides its helper textarea with opacity: 0,
|
||||||
No CSS override needed; colors come from terminal.options.theme. */
|
width/height: 0, left: -9999em. macOS WKWebView doesn't reliably focus
|
||||||
|
elements with zero dimensions positioned off-screen. Override to keep it
|
||||||
/* Cursor styling */
|
within the viewport with non-zero dimensions so focus events fire. */
|
||||||
.terminal-container .xterm-cursor-layer {
|
.terminal-container .xterm .xterm-helper-textarea {
|
||||||
z-index: 4;
|
left: 0 !important;
|
||||||
|
top: 0 !important;
|
||||||
|
width: 1px !important;
|
||||||
|
height: 1px !important;
|
||||||
|
opacity: 0.01 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Scrollbar inside terminal */
|
/* Scrollbar inside terminal */
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="h-9 flex items-center justify-between px-4 bg-[var(--wraith-bg-secondary)] border-t border-[var(--wraith-border)] text-sm text-[var(--wraith-text-muted)] shrink-0">
|
<div class="h-10 flex items-center justify-between px-4 bg-[var(--wraith-bg-secondary)] border-t border-[var(--wraith-border)] text-sm text-[var(--wraith-text-muted)] shrink-0">
|
||||||
<!-- Left: connection info -->
|
<!-- Left: connection info -->
|
||||||
<div class="flex items-center gap-3">
|
<div class="flex items-center gap-3">
|
||||||
<template v-if="sessionStore.activeSession">
|
<template v-if="sessionStore.activeSession">
|
||||||
|
|||||||
@ -502,6 +502,19 @@ onMounted(async () => {
|
|||||||
|
|
||||||
await connectionStore.loadAll();
|
await connectionStore.loadAll();
|
||||||
|
|
||||||
|
// Restore saved theme so every terminal opens with the user's preferred colors
|
||||||
|
try {
|
||||||
|
const savedThemeName = await invoke<string | null>("get_setting", { key: "active_theme" });
|
||||||
|
if (savedThemeName) {
|
||||||
|
const themes = await invoke<Array<{ name: string; foreground: string; background: string; cursor: string; black: string; red: string; green: string; yellow: string; blue: string; magenta: string; cyan: string; white: string; brightBlack: string; brightRed: string; brightGreen: string; brightYellow: string; brightBlue: string; brightMagenta: string; brightCyan: string; brightWhite: string }>>("list_themes");
|
||||||
|
const theme = themes?.find(t => t.name === savedThemeName);
|
||||||
|
if (theme) {
|
||||||
|
sessionStore.setTheme(theme);
|
||||||
|
statusBar.value?.setThemeName(theme.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
|
||||||
// Restore workspace — reconnect saved tabs (non-blocking, non-fatal)
|
// Restore workspace — reconnect saved tabs (non-blocking, non-fatal)
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user