|
@@ -3,17 +3,23 @@
|
|
|
import * as Sidebar from "$lib/components/ui/sidebar/index.js";
|
|
import * as Sidebar from "$lib/components/ui/sidebar/index.js";
|
|
|
import { toggleMode } from "mode-watcher";
|
|
import { toggleMode } from "mode-watcher";
|
|
|
import { Button } from "$lib/components/ui/button";
|
|
import { Button } from "$lib/components/ui/button";
|
|
|
- import { SunIcon, MoonIcon, Lock } from "@lucide/svelte";
|
|
|
|
|
|
|
+ import {
|
|
|
|
|
+ SunIcon,
|
|
|
|
|
+ MoonIcon,
|
|
|
|
|
+ Lock,
|
|
|
|
|
+ CircleQuestionMarkIcon,
|
|
|
|
|
+ } from "@lucide/svelte";
|
|
|
import WorkspaceEntry from "$lib/components/WorkspaceEntry.svelte";
|
|
import WorkspaceEntry from "$lib/components/WorkspaceEntry.svelte";
|
|
|
import {
|
|
import {
|
|
|
state as _state,
|
|
state as _state,
|
|
|
selectNextEntry,
|
|
selectNextEntry,
|
|
|
selectPreviousEntry,
|
|
selectPreviousEntry,
|
|
|
- } from "$lib/state.svelte";
|
|
|
|
|
- import {
|
|
|
|
|
listWorkspaces,
|
|
listWorkspaces,
|
|
|
loadWorkspace,
|
|
loadWorkspace,
|
|
|
selectEntry,
|
|
selectEntry,
|
|
|
|
|
+ isRequestSending,
|
|
|
|
|
+ cancelRequest,
|
|
|
|
|
+ sendRequest,
|
|
|
} from "$lib/state.svelte";
|
|
} from "$lib/state.svelte";
|
|
|
import { SlidersHorizontal } from "@lucide/svelte";
|
|
import { SlidersHorizontal } from "@lucide/svelte";
|
|
|
import Environment from "$lib/components/Environment.svelte";
|
|
import Environment from "$lib/components/Environment.svelte";
|
|
@@ -23,15 +29,22 @@
|
|
|
import { getSetting } from "$lib/settings.svelte";
|
|
import { getSetting } from "$lib/settings.svelte";
|
|
|
import Header from "$lib/components/Header.svelte";
|
|
import Header from "$lib/components/Header.svelte";
|
|
|
import AppSidebar from "$lib/components/Sidebar.svelte";
|
|
import AppSidebar from "$lib/components/Sidebar.svelte";
|
|
|
|
|
+ import Shortcuts from "$lib/components/Shortcuts.svelte";
|
|
|
|
|
|
|
|
let sidePane: Resizable.Pane;
|
|
let sidePane: Resizable.Pane;
|
|
|
let mainPane: Resizable.Pane;
|
|
let mainPane: Resizable.Pane;
|
|
|
|
|
|
|
|
- let displayModal: "env" | "auth" | null = $state(null);
|
|
|
|
|
|
|
+ let requestPane: Resizable.Pane | undefined = $state();
|
|
|
|
|
+ let responsePane: Resizable.Pane | undefined = $state();
|
|
|
|
|
+
|
|
|
|
|
+ let hoveringOverButton = $state(false);
|
|
|
|
|
+ let displayModal: "env" | "auth" | "shortcuts" | null = $state(null);
|
|
|
|
|
|
|
|
let workspaces: Workspace[] = $state([]);
|
|
let workspaces: Workspace[] = $state([]);
|
|
|
|
|
|
|
|
window.addEventListener("keydown", (e) => {
|
|
window.addEventListener("keydown", (e) => {
|
|
|
|
|
+ // console.log(e.ctrlKey, e.key);
|
|
|
|
|
+
|
|
|
if (e.ctrlKey && e.key === "o") {
|
|
if (e.ctrlKey && e.key === "o") {
|
|
|
selectPreviousEntry();
|
|
selectPreviousEntry();
|
|
|
return;
|
|
return;
|
|
@@ -41,8 +54,46 @@
|
|
|
selectNextEntry();
|
|
selectNextEntry();
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ if (e.ctrlKey && e.key === "Enter") {
|
|
|
|
|
+ if (_state.entry) {
|
|
|
|
|
+ handleRequest();
|
|
|
|
|
+ }
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (e.ctrlKey && e.key === "h") {
|
|
|
|
|
+ if (displayModal === "shortcuts") {
|
|
|
|
|
+ displayModal = null;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ displayModal = "shortcuts";
|
|
|
|
|
+ }
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
|
|
+ async function handleRequest() {
|
|
|
|
|
+ if (isRequestSending()) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ await cancelRequest();
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ console.error("error cancelling request", e);
|
|
|
|
|
+ }
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ await sendRequest();
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ console.error("error sending request", e);
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ if (responsePane && responsePane.getSize() === 0) {
|
|
|
|
|
+ requestPane!!.resize(50);
|
|
|
|
|
+ responsePane!!.resize(50);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
onMount(async () => {
|
|
onMount(async () => {
|
|
|
workspaces = await listWorkspaces();
|
|
workspaces = await listWorkspaces();
|
|
|
const lastEntry = await getSetting("lastEntry");
|
|
const lastEntry = await getSetting("lastEntry");
|
|
@@ -58,6 +109,30 @@
|
|
|
});
|
|
});
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
|
|
+{#snippet floatingBadge(value: string)}
|
|
|
|
|
+ {#if displayModal === "shortcuts" && hoveringOverButton}
|
|
|
|
|
+ <div
|
|
|
|
|
+ class="
|
|
|
|
|
+ absolute right-full top-1/2 mr-2 -translate-y-1/2
|
|
|
|
|
+ z-50 whitespace-nowrap
|
|
|
|
|
+ rounded-md px-3 text-sm text-popover-foreground
|
|
|
|
|
+ bg-secondary
|
|
|
|
|
+ shadow-md
|
|
|
|
|
+ after:content-['']
|
|
|
|
|
+ after:absolute
|
|
|
|
|
+ after:right-[-11px]
|
|
|
|
|
+ after:top-1/2
|
|
|
|
|
+ after:-translate-y-1/2
|
|
|
|
|
+ after:border-6
|
|
|
|
|
+ after:border-transparent
|
|
|
|
|
+ after:border-l-secondary
|
|
|
|
|
+ "
|
|
|
|
|
+ >
|
|
|
|
|
+ {value}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ {/if}
|
|
|
|
|
+{/snippet}
|
|
|
|
|
+
|
|
|
<Resizable.PaneGroup direction="horizontal">
|
|
<Resizable.PaneGroup direction="horizontal">
|
|
|
<Resizable.Pane bind:this={sidePane} defaultSize={15}>
|
|
<Resizable.Pane bind:this={sidePane} defaultSize={15}>
|
|
|
<AppSidebar onSelect={() => (displayModal = null)} />
|
|
<AppSidebar onSelect={() => (displayModal = null)} />
|
|
@@ -73,21 +148,34 @@
|
|
|
|
|
|
|
|
<Resizable.Pane bind:this={mainPane} defaultSize={85}>
|
|
<Resizable.Pane bind:this={mainPane} defaultSize={85}>
|
|
|
<main class="w-full h-full px-2 py-4 space-y-4">
|
|
<main class="w-full h-full px-2 py-4 space-y-4">
|
|
|
- <Header {workspaces} />
|
|
|
|
|
|
|
+ {#if displayModal !== "shortcuts"}
|
|
|
|
|
+ <Header {workspaces} />
|
|
|
|
|
+ {/if}
|
|
|
{#if displayModal === "env"}
|
|
{#if displayModal === "env"}
|
|
|
<Environment />
|
|
<Environment />
|
|
|
{:else if displayModal === "auth"}
|
|
{:else if displayModal === "auth"}
|
|
|
<Auth />
|
|
<Auth />
|
|
|
|
|
+ {:else if displayModal === "shortcuts"}
|
|
|
|
|
+ <Shortcuts />
|
|
|
{:else if _state.entry}
|
|
{:else if _state.entry}
|
|
|
- <WorkspaceEntry />
|
|
|
|
|
|
|
+ <WorkspaceEntry bind:requestPane bind:responsePane />
|
|
|
{:else}{/if}
|
|
{:else}{/if}
|
|
|
</main>
|
|
</main>
|
|
|
</Resizable.Pane>
|
|
</Resizable.Pane>
|
|
|
</Resizable.PaneGroup>
|
|
</Resizable.PaneGroup>
|
|
|
|
|
|
|
|
-<Sidebar.Menu class="bg-sidebar rounded-xl p-1 my-2 mr-2 w-fit items-center">
|
|
|
|
|
- <Sidebar.MenuItem class="pt-2">
|
|
|
|
|
- <Button onclick={toggleMode} variant="ghost" size="icon-sm">
|
|
|
|
|
|
|
+<Sidebar.Menu
|
|
|
|
|
+ class="flex flex-col items-center bg-sidebar rounded-xl p-1 my-2 mr-2 w-fit"
|
|
|
|
|
+>
|
|
|
|
|
+ <Sidebar.MenuItem class="relative pt-2">
|
|
|
|
|
+ {@render floatingBadge("Toggle theme")}
|
|
|
|
|
+ <Button
|
|
|
|
|
+ onclick={toggleMode}
|
|
|
|
|
+ variant="ghost"
|
|
|
|
|
+ size="icon-sm"
|
|
|
|
|
+ onmouseenter={() => (hoveringOverButton = true)}
|
|
|
|
|
+ onmouseleave={() => (hoveringOverButton = false)}
|
|
|
|
|
+ >
|
|
|
<SunIcon
|
|
<SunIcon
|
|
|
class="h-1 w-1 scale-100 rotate-0 transition-all! dark:scale-0 dark:-rotate-90"
|
|
class="h-1 w-1 scale-100 rotate-0 transition-all! dark:scale-0 dark:-rotate-90"
|
|
|
/>
|
|
/>
|
|
@@ -98,7 +186,12 @@
|
|
|
</Button>
|
|
</Button>
|
|
|
</Sidebar.MenuItem>
|
|
</Sidebar.MenuItem>
|
|
|
|
|
|
|
|
- <Sidebar.MenuItem class="pt-2">
|
|
|
|
|
|
|
+ <Sidebar.MenuItem
|
|
|
|
|
+ class="relative pt-2"
|
|
|
|
|
+ onmouseenter={() => (hoveringOverButton = true)}
|
|
|
|
|
+ onmouseleave={() => (hoveringOverButton = false)}
|
|
|
|
|
+ >
|
|
|
|
|
+ {@render floatingBadge("Edit environment")}
|
|
|
<Button
|
|
<Button
|
|
|
onclick={() => (displayModal = displayModal === "env" ? null : "env")}
|
|
onclick={() => (displayModal = displayModal === "env" ? null : "env")}
|
|
|
variant={displayModal === "env" ? "default" : "ghost"}
|
|
variant={displayModal === "env" ? "default" : "ghost"}
|
|
@@ -109,7 +202,12 @@
|
|
|
</Button>
|
|
</Button>
|
|
|
</Sidebar.MenuItem>
|
|
</Sidebar.MenuItem>
|
|
|
|
|
|
|
|
- <Sidebar.MenuItem class="pt-2">
|
|
|
|
|
|
|
+ <Sidebar.MenuItem
|
|
|
|
|
+ class="relative pt-2"
|
|
|
|
|
+ onmouseenter={() => (hoveringOverButton = true)}
|
|
|
|
|
+ onmouseleave={() => (hoveringOverButton = false)}
|
|
|
|
|
+ >
|
|
|
|
|
+ {@render floatingBadge("Manage authentication schemes")}
|
|
|
<Button
|
|
<Button
|
|
|
onclick={() => (displayModal = displayModal === "auth" ? null : "auth")}
|
|
onclick={() => (displayModal = displayModal === "auth" ? null : "auth")}
|
|
|
variant={displayModal === "auth" ? "default" : "ghost"}
|
|
variant={displayModal === "auth" ? "default" : "ghost"}
|
|
@@ -119,4 +217,24 @@
|
|
|
<span class="sr-only">Display auth</span>
|
|
<span class="sr-only">Display auth</span>
|
|
|
</Button>
|
|
</Button>
|
|
|
</Sidebar.MenuItem>
|
|
</Sidebar.MenuItem>
|
|
|
|
|
+
|
|
|
|
|
+ <Sidebar.MenuItem class="relative pt-2 flex-1"></Sidebar.MenuItem>
|
|
|
|
|
+ <Sidebar.Separator />
|
|
|
|
|
+
|
|
|
|
|
+ <Sidebar.MenuItem
|
|
|
|
|
+ class="relative pt-2"
|
|
|
|
|
+ onmouseenter={() => (hoveringOverButton = true)}
|
|
|
|
|
+ onmouseleave={() => (hoveringOverButton = false)}
|
|
|
|
|
+ >
|
|
|
|
|
+ {@render floatingBadge("Toggle help")}
|
|
|
|
|
+ <Button
|
|
|
|
|
+ onclick={() =>
|
|
|
|
|
+ (displayModal = displayModal === "shortcuts" ? null : "shortcuts")}
|
|
|
|
|
+ variant={displayModal === "shortcuts" ? "default" : "ghost"}
|
|
|
|
|
+ size="icon-sm"
|
|
|
|
|
+ >
|
|
|
|
|
+ <CircleQuestionMarkIcon />
|
|
|
|
|
+ <span class="sr-only">Display shortcuts</span>
|
|
|
|
|
+ </Button>
|
|
|
|
|
+ </Sidebar.MenuItem>
|
|
|
</Sidebar.Menu>
|
|
</Sidebar.Menu>
|