Files
hikari-desktop/src/lib/components/editor/InputDialog.svelte
T
hikari b745100bd5
Security Scan and Upload / Security & DefectDojo Upload (push) Successful in 1m28s
CI / Lint & Test (push) Has started running
CI / Build Linux (push) Has been cancelled
CI / Build Windows (cross-compile) (push) Has been cancelled
feat: Claude CLI 2.1.50–2.1.53 audit (#171)
## Summary

This PR covers the full audit of Claude CLI changes from 2.1.50 to 2.1.53, plus a batch of bug fixes, new features, and maintenance work identified during that review.

### New Features
- **Workspace trust gate** — detects hooks, MCP servers, and custom commands in a workspace before connecting; persists trust decisions so users aren't prompted repeatedly
- **Custom background image** — users can set a background image with configurable opacity; character panel and compact mode go transparent when active
- **Draggable tab reordering** — conversation tabs can be reordered via pointer-event drag-and-drop (HTML5 drag is intercepted by Tauri/WebView2, so pointer events are used instead)
- **Org UUID in account info** — exposes the org UUID from Claude auth status

### Bug Fixes
- **Unread dot false positives** — initialise unread counts on mount to prevent all tabs showing the blue dot after toggling the file editor (Closes #164)
- **Watchdog for hung WSL bridge** — detects connections that never receive `system:init` and kills the stale process after 1 minute (Closes #166)
- **Suppress terminal window flash on Windows** — applies `CREATE_NO_WINDOW` to all subprocesses via a `HideWindow` trait extension (Closes #165)
- **HTML escaping in markdown renderer** — escape `<` and `>` in `codespan` and `html` renderer callbacks to prevent raw HTML injection (Closes #169)

### Maintenance
- Verify stream-JSON handles tool results above the 50K threshold correctly (Closes #162)
- Reviewed hook security fixes from CLI 2.1.51 — not applicable to our setup (Closes #163)
- Expose org UUID from `claude auth status` (Closes #160)
- Clean up Svelte and Vite build warnings (`a11y_click_events_have_key_events`, `state_referenced_locally`, `non_reactive_update`, `codeSplitting`, chunk size, CodeMirror dynamic import)
- Update all npm dependencies to latest compatible versions with exact pinning (Closes #81, Closes #82, Closes #83, Closes #84, Closes #85, Closes #86, Closes #87, Closes #90, Closes #91, Closes #93, Closes #94, Closes #95, Closes #96, Closes #97, Closes #98, Closes #99, Closes #101, Closes #141, Closes #142, Closes #143, Closes #145, Closes #146, Closes #147)
- Run `cargo update` to bring Cargo.lock up to date

### Closes

Closes #160
Closes #162
Closes #163
Closes #164
Closes #165
Closes #166
Closes #167
Closes #168
Closes #169
Closes #81
Closes #82
Closes #83
Closes #84
Closes #85
Closes #86
Closes #87
Closes #90
Closes #91
Closes #93
Closes #94
Closes #95
Closes #96
Closes #97
Closes #98
Closes #99
Closes #101
Closes #141
Closes #142
Closes #143
Closes #145
Closes #146
Closes #147

 This PR was created with help from Hikari~ 🌸

Reviewed-on: #171
Co-authored-by: Hikari <hikari@nhcarrigan.com>
Co-committed-by: Hikari <hikari@nhcarrigan.com>
2026-02-25 22:55:47 -08:00

174 lines
3.8 KiB
Svelte

<script lang="ts">
interface Props {
title: string;
placeholder?: string;
confirmText?: string;
cancelText?: string;
initialValue?: string;
onConfirm: (value: string) => void;
onCancel: () => void;
}
let {
title,
placeholder = "",
confirmText = "Create",
cancelText = "Cancel",
initialValue = "",
onConfirm,
onCancel,
}: Props = $props();
let inputValue = $state(initialValue);
let inputElement: HTMLInputElement | undefined = $state();
$effect(() => {
if (inputElement) {
inputElement.focus();
// Select all text for rename operations
if (initialValue) {
inputElement.select();
}
}
});
function handleSubmit() {
const trimmed = inputValue.trim();
if (trimmed) {
onConfirm(trimmed);
}
}
function handleKeydown(event: KeyboardEvent) {
if (event.key === "Escape") {
onCancel();
} else if (event.key === "Enter") {
handleSubmit();
}
}
</script>
<svelte:window onkeydown={handleKeydown} />
<!-- svelte-ignore a11y_no_static_element_interactions a11y_click_events_have_key_events -->
<div class="dialog-overlay" onclick={onCancel}>
<!-- svelte-ignore a11y_no_static_element_interactions a11y_click_events_have_key_events -->
<div class="dialog-content" onclick={(e) => e.stopPropagation()}>
<h2 class="dialog-title">{title}</h2>
<input
bind:this={inputElement}
bind:value={inputValue}
type="text"
{placeholder}
class="dialog-input"
/>
<div class="dialog-actions">
<button class="btn-cancel" onclick={onCancel}>
{cancelText}
</button>
<button class="btn-confirm" onclick={handleSubmit} disabled={!inputValue.trim()}>
{confirmText}
</button>
</div>
</div>
</div>
<style>
.dialog-overlay {
position: fixed;
inset: 0;
z-index: 50;
display: flex;
align-items: center;
justify-content: center;
background-color: rgba(0, 0, 0, 0.5);
}
.dialog-content {
margin: 0 1rem;
width: 100%;
max-width: 28rem;
border-radius: 0.5rem;
border: 1px solid var(--border-color);
background-color: var(--bg-secondary);
padding: 1.5rem;
box-shadow:
0 20px 25px -5px rgba(0, 0, 0, 0.1),
0 10px 10px -5px rgba(0, 0, 0, 0.04);
}
.dialog-title {
margin-bottom: 1rem;
font-size: 1.125rem;
font-weight: 600;
color: var(--text-primary);
}
.dialog-input {
width: 100%;
margin-bottom: 1.5rem;
padding: 0.5rem 0.75rem;
border-radius: 0.375rem;
border: 1px solid var(--border-color);
background-color: var(--bg-primary);
font-size: 0.875rem;
color: var(--text-primary);
outline: none;
transition:
border-color 0.15s ease,
box-shadow 0.15s ease;
}
.dialog-input::placeholder {
color: var(--text-secondary);
}
.dialog-input:focus {
border-color: var(--accent-primary);
box-shadow: 0 0 0 1px var(--accent-primary);
}
.dialog-actions {
display: flex;
justify-content: flex-end;
gap: 0.75rem;
}
.btn-cancel {
border-radius: 0.375rem;
border: 1px solid var(--border-color);
background-color: var(--bg-primary);
padding: 0.5rem 1rem;
font-size: 0.875rem;
color: var(--text-primary);
cursor: pointer;
transition: background-color 0.15s ease;
}
.btn-cancel:hover {
background-color: var(--bg-secondary);
}
.btn-confirm {
border-radius: 0.375rem;
border: none;
background-color: var(--accent-primary);
padding: 0.5rem 1rem;
font-size: 0.875rem;
color: white;
cursor: pointer;
transition: background-color 0.15s ease;
}
.btn-confirm:hover {
background-color: var(--accent-secondary);
}
.btn-confirm:disabled {
cursor: not-allowed;
opacity: 0.5;
}
</style>