Explorar o código

fix response header and content scrolling

biblius hai 2 semanas
pai
achega
77f43f326b

+ 28 - 0
src/lib/codemirror.svelte.ts

@@ -19,6 +19,33 @@ const stateChangeListener = new Compartment();
 const vimConfig = new Compartment();
 const lineWrapConfig = new Compartment();
 
+const editorPadding = EditorView.theme({
+  ".cm-content": {
+    marginBottom: "4rem",
+  },
+  ".cm-scroller": {
+    marginBottom: "2rem",
+  },
+
+  "@media (min-height: 900px)": {
+    ".cm-content": {
+      marginBottom: "3rem",
+    },
+    ".cm-scroller": {
+      marginBottom: "1rem",
+    },
+  },
+
+  "@media (min-height: 1200px)": {
+    ".cm-content": {
+      marginBottom: "2rem",
+    },
+    ".cm-scroller": {
+      marginBottom: "0.5rem",
+    },
+  },
+});
+
 export function init(
   id: string,
   lineWrap: boolean,
@@ -28,6 +55,7 @@ export function init(
     basicSetup,
     cmHtml(),
     jsonExt,
+    editorPadding,
     stateChangeListener.of(EditorView.updateListener.of(() => {})),
   ];
 

+ 1 - 1
src/lib/components/Editable.svelte

@@ -78,7 +78,7 @@
   }
 </script>
 
-<div class="flex items-center">
+<div class="flex min-w-fit items-center">
   {#if editing}
     <input
       use:clickOutsideCancel

+ 1 - 6
src/lib/components/Header.svelte

@@ -14,12 +14,7 @@
   } from "$lib/state.svelte";
   import { Input } from "$lib/components/ui/input";
   import type { Workspace } from "$lib/types";
-  import {
-    ArrowLeftCircleIcon,
-    ArrowUpRight,
-    SendToBack,
-    StepBack,
-  } from "@lucide/svelte";
+  import { StepBack } from "@lucide/svelte";
 
   let { workspaces = $bindable() }: { workspaces: Workspace[] } = $props();
 

+ 59 - 17
src/lib/components/Response.svelte

@@ -49,49 +49,49 @@
 </script>
 
 <Tabs.Root value="body" class="min-h-0">
-  <header class="flex items-center w-full px-2 py-2 gap-4">
-    <Badge variant="outline" class={`rounded-sm ${borderColor}`}>
+  <header class="flex items-center w-full py-2 gap-4 border-b">
+    <Badge variant="outline" class={`h-4 rounded-sm ${borderColor}`}>
       <Dot strokeWidth={5} color={dotColor} />
       {response.status}
     </Badge>
 
-    <Tabs.List>
+    <Tabs.List class="h-6">
       <Tabs.Trigger class="text-xs" value="body">Body</Tabs.Trigger>
       <Tabs.Trigger class="text-xs" value="headers">Headers</Tabs.Trigger>
     </Tabs.List>
 
-    <Tabs.Content value="body">
-      <div class="justify-center relative">
+    <Tabs.Content value="body" class="flex items-center">
+      <div class="flex items-center gap-1">
         <Button
+          class="h-6 p-1"
           variant={wrap ? "default" : "outline"}
           onclick={handleToggleWrap}
-          size="icon-sm"><TextWrap /></Button
+          size="icon-sm"
         >
+          <TextWrap />
+        </Button>
         <Button
+          class="h-6 p-1"
           onclick={() => copyContent(view)}
           variant="outline"
-          size="icon-sm"><Clipboard /></Button
+          size="icon-sm"
         >
+          <Clipboard />
+        </Button>
       </div>
     </Tabs.Content>
   </header>
 
-  <Tabs.Content
-    value="body"
-    class="pb-5 flex flex-col w-full max-h-11/12 overflow-scroll"
-  >
+  <Tabs.Content value="body" class="flex-1 min-h-0 overflow-auto">
     {#if response.body != null}
       <!-- EDITOR -->
 
-      <div id="response-view" class="rounded-md"></div>
+      <div id="response-view"></div>
     {/if}
   </Tabs.Content>
 
-  <Tabs.Content
-    value="headers"
-    class="flex flex-col w-full max-h-10/12 overflow-scroll"
-  >
-    <div class="grid grid-cols-2">
+  <Tabs.Content value="headers" class="flex-1 overflow-auto">
+    <div class="grid grid-cols-2" id="header-tab">
       {#each response.headers as [name, value]}
         <p>{name}</p>
         <p class="wrap-anywhere">{value}</p>
@@ -99,3 +99,45 @@
     </div>
   </Tabs.Content>
 </Tabs.Root>
+
+<style>
+  #header-tab {
+    padding-bottom: 8rem;
+  }
+
+  @media (min-height: 400px) {
+    #header-tab {
+      padding-bottom: 7rem;
+    }
+  }
+
+  @media (min-height: 600px) {
+    #header-tab {
+      padding-bottom: 6rem;
+    }
+  }
+
+  @media (min-height: 800px) {
+    #header-tab {
+      padding-bottom: 5rem;
+    }
+  }
+
+  @media (min-height: 900px) {
+    #header-tab {
+      padding-bottom: 4rem;
+    }
+  }
+
+  @media (min-height: 1000px) {
+    #header-tab {
+      padding-bottom: 3rem;
+    }
+  }
+
+  @media (min-height: 1200px) {
+    #header-tab {
+      padding-bottom: 2rem;
+    }
+  }
+</style>

+ 33 - 20
src/lib/components/WorkspaceEntry.svelte

@@ -1,4 +1,5 @@
 <script lang="ts">
+  import { Clipboard } from "@lucide/svelte";
   import * as Select from "$lib/components/ui/select";
   import {
     state as _state,
@@ -220,21 +221,38 @@
     <h2 class="pb-2 w-full border-b">Auth</h2>
     {@render authParams(_state.entry!!)}
   </div>
-{:else if _state.entry?.type === "Request"}
+{:else if _state.entry && _state.entry.type === "Request"}
   <!-- REQUEST WORK AREA -->
 
-  <Editable
-    bind:value={_state.entry!!.name}
-    onSave={(value) => {
-      updateEntryName(value);
-    }}
-  >
-    {#snippet display({ value, startEdit })}
-      <h1 ondblclick={startEdit}>
-        {value || _state.entry!!.type + "(" + _state.entry!!.id + ")"}
-      </h1>
-    {/snippet}
-  </Editable>
+  <div class="flex w-full items-center">
+    <Editable
+      bind:value={_state.entry!!.name}
+      onSave={(value) => {
+        updateEntryName(value);
+      }}
+    >
+      {#snippet display({ value, startEdit })}
+        <h1 ondblclick={startEdit}>
+          {value || _state.entry!!.type + "(" + _state.entry!!.id + ")"}
+        </h1>
+      {/snippet}
+    </Editable>
+
+    {#if _state.entry.expandedUrl != null}
+      <div class="flex justify-end items-center w-full pr-2">
+        <p class="text-xs text-muted-foreground text-right">
+          {_state.entry.expandedUrl ?? ""}
+        </p>
+        <Button
+          onclick={() =>
+            navigator.clipboard.writeText(_state.entry!!.expandedUrl)}
+          variant="ghost"
+          class="border-none mx-2 text-muted-foreground hover:text-foreground"
+          size="icon-sm"><Clipboard /></Button
+        >
+      </div>
+    {/if}
+  </div>
 
   <section class="h-[90%] space-y-4">
     <!-- URL BAR -->
@@ -262,10 +280,6 @@
           Send
         {/if}
       </Button>
-
-      <p class="w-full pl-1 text-xs text-muted-foreground">
-        {_state.entry.expandedUrl ?? ""}
-      </p>
     </div>
 
     <!-- ================= REQUEST PANEL ================= -->
@@ -413,8 +427,7 @@
       </Resizable.Pane>
 
       <Resizable.Handle
-        withHandle
-        class="p-0.5"
+        class="hover:bg-primary"
         ondblclick={() => {
           requestPane.resize(50);
           responsePane.resize(50);
@@ -424,7 +437,7 @@
       <!-- RESPONSE -->
 
       <Resizable.Pane
-        class="flex flex-col min-h-0"
+        class="flex flex-col"
         defaultSize={0}
         bind:this={responsePane}
       >

+ 7 - 4
src/lib/types.ts

@@ -3,9 +3,7 @@ export type Workspace = {
   name: string;
 };
 
-export type WorkspaceEntryType = "Request" | "Collection";
-
-export type WorkspaceEntry = WorkspaceEntryBase | WorkspaceRequest;
+export type WorkspaceEntry = WorkspaceCollection | WorkspaceRequest;
 
 export type WorkspaceEntryBase = {
   // Values from models
@@ -13,7 +11,6 @@ export type WorkspaceEntryBase = {
   workspace_id: number;
   parent_id: number | null;
   name: string;
-  type: WorkspaceEntryType;
 
   auth: number | null;
   auth_inherit: boolean;
@@ -22,7 +19,13 @@ export type WorkspaceEntryBase = {
   open?: boolean;
 };
 
+export type WorkspaceCollection = WorkspaceEntryBase & {
+  type: "Collection";
+};
+
 export type WorkspaceRequest = WorkspaceEntryBase & {
+  type: "Request";
+
   method: string;
   url: string;
   body: RequestBody | null;

+ 2 - 2
src/routes/+page.svelte

@@ -48,7 +48,7 @@
   </Resizable.Pane>
 
   <Resizable.Handle
-    class="p-0.5"
+    class="hover:bg-primary"
     ondblclick={() => {
       sidePane.resize(15);
       mainPane.resize(85);
@@ -56,7 +56,7 @@
   />
 
   <Resizable.Pane bind:this={mainPane} defaultSize={85}>
-    <main class="w-full h-full p-4 space-y-4">
+    <main class="w-full h-full px-2 py-4 space-y-4">
       <Header {workspaces} />
       {#if displayModal === "env"}
         <Environment />