<script lang="ts">
import { onMount } from "svelte";
import { gists } from "../../../stores/gists.svelte.js";
import { workbench } from "../../../stores/workbench.svelte.js";
import GistList from "../../gists/GistList.svelte";
import SidebarHeader from "../SidebarHeader.svelte";
import AppIcon from "../../layout/AppIcon.svelte";
onMount(async () => {
await gists.loadList();
});
async function handleSelect(id: string) {
await gists.selectGist(id);
if (gists.selectedGist) {
workbench.openGist(gists.selectedGist);
}
}
function handleCreate() {
gists.clearSelection();
workbench.openNewGist();
}
</script>
<div class="panel">
<SidebarHeader
title="Gists"
onrefresh={() => gists.refresh()}
refreshing={gists.refreshing}
refreshTitle="Ask the daemon to refresh the gists"
>
{#snippet actions()}
<button
class="panel-action-btn"
title="New gist"
aria-label="New gist"
onclick={handleCreate}
>
<AppIcon name="plus" size={14} />
</button>
{/snippet}
</SidebarHeader>
{#if gists.noToken}
<div class="panel-auth">
<strong>Not being refreshed</strong>
<span>The list below is what was last read. There is no GitHub token; log in to
refresh it: <code>gh auth login</code></span>
</div>
{/if}
{#if gists.error}
<div class="panel-error">{gists.error}</div>
{/if}
<div class="panel-body">
<GistList
gists={gists.gists}
loading={gists.loading}
selectedId={gists.selectedGistId}
onselect={handleSelect}
/>
</div>
<!--
What the list IS, rather than what a fetch did. An empty list with no note
beside it is the thing this exists to stop: it reads as "you have no gists"
whether or not anybody ever managed to ask. At the foot, because it is
looked up after reading the list rather than before.
-->
<div class="panel-standing" class:panel-standing--problem={!!gists.sync?.last_error}>
{#if gists.sync?.last_error}
Last refresh failed: {gists.sync.last_error}
{:else if gists.sync?.synced_at}
As of {new Date(gists.sync.synced_at).toLocaleString()}
{:else}
Not read yet
{/if}
</div>
</div>
<style>
.panel {
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
}
.panel-auth,
.panel-error {
margin: var(--wb-spacing-10) var(--wb-spacing-12) 0;
padding: var(--wb-spacing-10) var(--wb-spacing-12);
border-radius: var(--wsb-radius-sm);
font-size: var(--wb-font-size-12);
display: flex;
flex-direction: column;
gap: var(--wb-spacing-6);
}
.panel-auth {
/* The refusal is written as lines — the key, where the store is, the
command that adds it. Collapsed into one paragraph it reads as a
run-on sentence and the command is lost in the middle of it. */
white-space: pre-wrap;
background: color-mix(in srgb, var(--vscode-editorWarning-foreground) 10%, transparent);
border: 1px solid color-mix(in srgb, var(--vscode-editorWarning-foreground) 24%, transparent);
}
.panel-error {
background: color-mix(in srgb, var(--vscode-errorForeground) 8%, transparent);
border: 1px solid color-mix(in srgb, var(--vscode-errorForeground) 18%, transparent);
color: var(--vscode-errorForeground);
}
.link-btn {
align-self: flex-start;
color: white;
background: var(--vscode-focusBorder);
border-radius: var(--wsb-radius-sm);
padding: var(--wb-spacing-6) var(--wb-spacing-10);
font-size: var(--wb-font-size-11);
}
.panel-body {
flex: 1;
min-height: 0;
}
</style>