generated from nhcarrigan/template
b745100bd5
## 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>
174 lines
3.8 KiB
Svelte
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>
|