feat(git stash): add stash listing and push/apply/pop/drop UI
This change introduces Git stash support end-to-end, including a new backend command to list stashes and operations to push, apply, pop, and drop them. The frontend now fetches stashes as part of the repository bundle and provides a dedicated panel to manage shelved changes. - Add GitStash model and Tauri commands for stash operations - Implement StashPanel component and wire it into the app - Adjust sidebar layout and add stash-specific styling
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
<script lang="ts">
|
||||
import { Archive, Download, Trash2, Upload } from "@lucide/svelte";
|
||||
import type { GitStash } from "../types";
|
||||
|
||||
interface Props {
|
||||
stashes: GitStash[];
|
||||
changedCount: number;
|
||||
hasRepository: boolean;
|
||||
isBusy: boolean;
|
||||
onPush: (message: string, includeUntracked: boolean) => void;
|
||||
onApply: (stash: GitStash) => void;
|
||||
onPop: (stash: GitStash) => void;
|
||||
onDrop: (stash: GitStash) => void;
|
||||
}
|
||||
|
||||
let {
|
||||
stashes = [],
|
||||
changedCount = 0,
|
||||
hasRepository = false,
|
||||
isBusy = false,
|
||||
onPush = () => {},
|
||||
onApply = () => {},
|
||||
onPop = () => {},
|
||||
onDrop = () => {},
|
||||
}: Props = $props();
|
||||
|
||||
let message = $state("");
|
||||
let includeUntracked = $state(true);
|
||||
|
||||
function submitPush() {
|
||||
onPush(message, includeUntracked);
|
||||
message = "";
|
||||
}
|
||||
|
||||
function stashTitle(stash: GitStash): string {
|
||||
return stash.message || stash.selector;
|
||||
}
|
||||
</script>
|
||||
|
||||
<section class="panel stash-panel overflow-hidden" aria-label="Git stash">
|
||||
<div class="section-head">
|
||||
<div>
|
||||
<span class="eyebrow">Stash</span>
|
||||
<h2 class="mt-0.5 text-ink text-base font-bold leading-tight">Shelved changes</h2>
|
||||
</div>
|
||||
<span class="pill pill-count">{stashes.length}</span>
|
||||
</div>
|
||||
|
||||
{#if !hasRepository}
|
||||
<div class="blank-state">No repository loaded.</div>
|
||||
{:else}
|
||||
<div class="stash-create">
|
||||
<input
|
||||
class="stash-input"
|
||||
type="text"
|
||||
bind:value={message}
|
||||
placeholder="Optional message"
|
||||
disabled={isBusy || changedCount === 0}
|
||||
onkeydown={(event) => {
|
||||
if (event.key === "Enter" && changedCount > 0 && !isBusy) submitPush();
|
||||
}}
|
||||
/>
|
||||
<label class="stash-check">
|
||||
<input type="checkbox" bind:checked={includeUntracked} disabled={isBusy || changedCount === 0} />
|
||||
Untracked
|
||||
</label>
|
||||
<button
|
||||
class="btn-sm stash-save-button"
|
||||
type="button"
|
||||
onclick={submitPush}
|
||||
disabled={isBusy || changedCount === 0}
|
||||
title="Save current working tree changes to a stash"
|
||||
>
|
||||
<Archive size={14} aria-hidden="true" />
|
||||
Stash
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{#if stashes.length === 0}
|
||||
<div class="blank-state stash-empty">No stashes saved.</div>
|
||||
{:else}
|
||||
<div class="stash-list">
|
||||
{#each stashes as stash (stash.selector)}
|
||||
<article class="stash-row">
|
||||
<div class="stash-row-main">
|
||||
<strong title={stashTitle(stash)}>{stashTitle(stash)}</strong>
|
||||
<span>
|
||||
{stash.selector}
|
||||
{#if stash.branch}
|
||||
on {stash.branch}
|
||||
{/if}
|
||||
{#if stash.date}
|
||||
- {stash.date}
|
||||
{/if}
|
||||
</span>
|
||||
</div>
|
||||
<div class="stash-actions">
|
||||
<button class="btn-sm" type="button" onclick={() => onApply(stash)} disabled={isBusy} title="Apply stash and keep it">
|
||||
<Download size={13} aria-hidden="true" />
|
||||
Apply
|
||||
</button>
|
||||
<button class="btn-sm" type="button" onclick={() => onPop(stash)} disabled={isBusy} title="Apply stash and remove it if successful">
|
||||
<Upload size={13} aria-hidden="true" />
|
||||
Pop
|
||||
</button>
|
||||
<button class="btn-sm danger" type="button" onclick={() => onDrop(stash)} disabled={isBusy} title="Delete stash">
|
||||
<Trash2 size={13} aria-hidden="true" />
|
||||
Drop
|
||||
</button>
|
||||
</div>
|
||||
</article>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</section>
|
||||
Reference in New Issue
Block a user