wsb-daemon 0.275.7622

wsb's daemon: the workbench, the GitHub mirror's schedule and peer continuity, for every workspace on the machine
<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>