mirror of
https://github.com/sst/opencode.git
synced 2025-12-23 10:11:41 +00:00
wip: desktop cleanup
This commit is contained in:
parent
9efc2eaf2e
commit
84e8eea52e
1 changed files with 33 additions and 55 deletions
|
|
@ -2,7 +2,7 @@ import { FileIcon, Icon, IconButton, Logo, Tooltip } from "@/ui"
|
||||||
import { Tabs } from "@/ui/tabs"
|
import { Tabs } from "@/ui/tabs"
|
||||||
import { Select } from "@/components/select"
|
import { Select } from "@/components/select"
|
||||||
import FileTree from "@/components/file-tree"
|
import FileTree from "@/components/file-tree"
|
||||||
import { createSignal, For, Match, onCleanup, onMount, Show, Switch } from "solid-js"
|
import { For, Match, onCleanup, onMount, Show, Switch } from "solid-js"
|
||||||
import { useLocal, useSDK } from "@/context"
|
import { useLocal, useSDK } from "@/context"
|
||||||
import { Code } from "@/components/code"
|
import { Code } from "@/components/code"
|
||||||
import {
|
import {
|
||||||
|
|
@ -18,15 +18,17 @@ import type { DragEvent, Transformer } from "@thisbeyond/solid-dnd"
|
||||||
import type { LocalFile } from "@/context/local"
|
import type { LocalFile } from "@/context/local"
|
||||||
import SessionList from "@/components/session-list"
|
import SessionList from "@/components/session-list"
|
||||||
import SessionTimeline from "@/components/session-timeline"
|
import SessionTimeline from "@/components/session-timeline"
|
||||||
|
import { createStore } from "solid-js/store"
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
const sdk = useSDK()
|
const sdk = useSDK()
|
||||||
const local = useLocal()
|
const local = useLocal()
|
||||||
const [clickTimer, setClickTimer] = createSignal<number | undefined>()
|
const [store, setStore] = createStore({
|
||||||
const [activeItem, setActiveItem] = createSignal<string | undefined>(undefined)
|
clickTimer: undefined as number | undefined,
|
||||||
const [inputValue, setInputValue] = createSignal("")
|
activeItem: undefined as string | undefined,
|
||||||
const [isDragging, setIsDragging] = createSignal<"left" | "right" | undefined>(undefined)
|
prompt: "",
|
||||||
const [leftScrolled, setLeftScrolled] = createSignal(false)
|
dragging: undefined as "left" | "right" | undefined,
|
||||||
|
})
|
||||||
|
|
||||||
let inputRef: HTMLInputElement | undefined = undefined
|
let inputRef: HTMLInputElement | undefined = undefined
|
||||||
|
|
||||||
|
|
@ -78,20 +80,20 @@ export default function Page() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const resetClickTimer = () => {
|
const resetClickTimer = () => {
|
||||||
if (!clickTimer()) return
|
if (!store.clickTimer) return
|
||||||
clearTimeout(clickTimer())
|
clearTimeout(store.clickTimer)
|
||||||
setClickTimer(undefined)
|
setStore("clickTimer", undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
const startClickTimer = () => {
|
const startClickTimer = () => {
|
||||||
const newClickTimer = setTimeout(() => {
|
const newClickTimer = setTimeout(() => {
|
||||||
setClickTimer(undefined)
|
setStore("clickTimer", undefined)
|
||||||
}, 300)
|
}, 300)
|
||||||
setClickTimer(newClickTimer as unknown as number)
|
setStore("clickTimer", newClickTimer as unknown as number)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleFileClick = async (file: LocalFile) => {
|
const handleFileClick = async (file: LocalFile) => {
|
||||||
if (clickTimer()) {
|
if (store.clickTimer) {
|
||||||
resetClickTimer()
|
resetClickTimer()
|
||||||
local.file.update(file.path, { ...file, pinned: true })
|
local.file.update(file.path, { ...file, pinned: true })
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -109,7 +111,7 @@ export default function Page() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const onDragStart = (event: any) => {
|
const onDragStart = (event: any) => {
|
||||||
setActiveItem(event.draggable.id as string)
|
setStore("activeItem", event.draggable.id as string)
|
||||||
}
|
}
|
||||||
|
|
||||||
const onDragOver = (event: DragEvent) => {
|
const onDragOver = (event: DragEvent) => {
|
||||||
|
|
@ -125,12 +127,12 @@ export default function Page() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const onDragEnd = () => {
|
const onDragEnd = () => {
|
||||||
setActiveItem(undefined)
|
setStore("activeItem", undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleLeftDragStart = (e: MouseEvent) => {
|
const handleLeftDragStart = (e: MouseEvent) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
setIsDragging("left")
|
setStore("dragging", "left")
|
||||||
const startX = e.clientX
|
const startX = e.clientX
|
||||||
const startWidth = local.layout.leftWidth()
|
const startWidth = local.layout.leftWidth()
|
||||||
|
|
||||||
|
|
@ -141,7 +143,7 @@ export default function Page() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleMouseUp = () => {
|
const handleMouseUp = () => {
|
||||||
setIsDragging(undefined)
|
setStore("dragging", undefined)
|
||||||
document.removeEventListener("mousemove", handleMouseMove)
|
document.removeEventListener("mousemove", handleMouseMove)
|
||||||
document.removeEventListener("mouseup", handleMouseUp)
|
document.removeEventListener("mouseup", handleMouseUp)
|
||||||
}
|
}
|
||||||
|
|
@ -152,7 +154,7 @@ export default function Page() {
|
||||||
|
|
||||||
const handleRightDragStart = (e: MouseEvent) => {
|
const handleRightDragStart = (e: MouseEvent) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
setIsDragging("right")
|
setStore("dragging", "right")
|
||||||
const startX = e.clientX
|
const startX = e.clientX
|
||||||
const startWidth = local.layout.rightWidth()
|
const startWidth = local.layout.rightWidth()
|
||||||
|
|
||||||
|
|
@ -163,7 +165,7 @@ export default function Page() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleMouseUp = () => {
|
const handleMouseUp = () => {
|
||||||
setIsDragging(undefined)
|
setStore("dragging", undefined)
|
||||||
document.removeEventListener("mousemove", handleMouseMove)
|
document.removeEventListener("mousemove", handleMouseMove)
|
||||||
document.removeEventListener("mouseup", handleMouseUp)
|
document.removeEventListener("mouseup", handleMouseUp)
|
||||||
}
|
}
|
||||||
|
|
@ -174,8 +176,8 @@ export default function Page() {
|
||||||
|
|
||||||
const handleSubmit = async (e: SubmitEvent) => {
|
const handleSubmit = async (e: SubmitEvent) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
const prompt = inputValue()
|
const prompt = store.prompt
|
||||||
setInputValue("")
|
setStore("prompt", "")
|
||||||
inputRef?.blur()
|
inputRef?.blur()
|
||||||
|
|
||||||
const session =
|
const session =
|
||||||
|
|
@ -238,24 +240,8 @@ export default function Page() {
|
||||||
</Tabs.Trigger>
|
</Tabs.Trigger>
|
||||||
</Tabs.List>
|
</Tabs.List>
|
||||||
</div>
|
</div>
|
||||||
<Tabs.Content
|
<Tabs.Content value="files" class="grow min-h-0 py-2 bg-background">
|
||||||
value="files"
|
|
||||||
class="grow min-h-0 py-2 bg-background"
|
|
||||||
onScroll={(e: Event & { currentTarget: HTMLDivElement }) => setLeftScrolled(e.currentTarget.scrollTop > 0)}
|
|
||||||
>
|
|
||||||
<FileTree path="" onFileClick={handleFileClick} />
|
<FileTree path="" onFileClick={handleFileClick} />
|
||||||
<Show when={leftScrolled()}>
|
|
||||||
<div
|
|
||||||
class="pointer-events-none sticky top-20 left-px h-4
|
|
||||||
bg-gradient-to-t from-transparent to-background"
|
|
||||||
style={`width: ${local.layout.leftWidth() - 2}px`}
|
|
||||||
/>
|
|
||||||
</Show>
|
|
||||||
<div
|
|
||||||
class="pointer-events-none fixed bottom-0 left-px h-4
|
|
||||||
bg-gradient-to-b from-transparent to-background"
|
|
||||||
style={`width: ${local.layout.leftWidth() - 2}px`}
|
|
||||||
/>
|
|
||||||
</Tabs.Content>
|
</Tabs.Content>
|
||||||
<Tabs.Content value="changes" class="grow min-h-0 py-2 bg-background">
|
<Tabs.Content value="changes" class="grow min-h-0 py-2 bg-background">
|
||||||
<div class="px-2 text-xs text-text-muted">No changes yet</div>
|
<div class="px-2 text-xs text-text-muted">No changes yet</div>
|
||||||
|
|
@ -268,9 +254,9 @@ export default function Page() {
|
||||||
onMouseDown={(e) => handleLeftDragStart(e)}
|
onMouseDown={(e) => handleLeftDragStart(e)}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="w-0.5 h-full bg-transparent group-hover:bg-border-active transition-colors"
|
|
||||||
classList={{
|
classList={{
|
||||||
"bg-border-active": isDragging() === "left",
|
"w-0.5 h-full bg-transparent group-hover:bg-border-active transition-colors": true,
|
||||||
|
"bg-border-active!": store.dragging === "left",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -302,16 +288,6 @@ export default function Page() {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Show>
|
</Show>
|
||||||
<div
|
|
||||||
class="pointer-events-none fixed top-0 right-px h-4
|
|
||||||
bg-gradient-to-t from-transparent to-background"
|
|
||||||
style={`width: ${local.layout.rightWidth() - 2}px`}
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
class="pointer-events-none fixed bottom-0 right-px h-4
|
|
||||||
bg-gradient-to-b from-transparent to-background"
|
|
||||||
style={`width: ${local.layout.rightWidth() - 2}px`}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
|
@ -320,8 +296,10 @@ export default function Page() {
|
||||||
onMouseDown={(e) => handleRightDragStart(e)}
|
onMouseDown={(e) => handleRightDragStart(e)}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="w-0.5 h-full bg-transparent group-hover:bg-border-active transition-colors"
|
classList={{
|
||||||
classList={{ "bg-border-active": isDragging() === "right" }}
|
"w-0.5 h-full bg-transparent group-hover:bg-border-active transition-colors": true,
|
||||||
|
"bg-border-active!": store.dragging === "right",
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
|
|
@ -443,9 +421,9 @@ export default function Page() {
|
||||||
</For>
|
</For>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
<DragOverlay>
|
<DragOverlay>
|
||||||
{activeItem() &&
|
{store.activeItem &&
|
||||||
(() => {
|
(() => {
|
||||||
const draggedFile = local.file.node(activeItem()!)
|
const draggedFile = local.file.node(store.activeItem!)
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class="relative px-3 h-8 flex items-center
|
class="relative px-3 h-8 flex items-center
|
||||||
|
|
@ -490,8 +468,8 @@ export default function Page() {
|
||||||
<input
|
<input
|
||||||
ref={(el) => (inputRef = el)}
|
ref={(el) => (inputRef = el)}
|
||||||
type="text"
|
type="text"
|
||||||
value={inputValue()}
|
value={store.prompt}
|
||||||
onInput={(e) => setInputValue(e.currentTarget.value)}
|
onInput={(e) => setStore("prompt", e.currentTarget.value)}
|
||||||
placeholder="It all starts with a prompt..."
|
placeholder="It all starts with a prompt..."
|
||||||
class="w-full p-1 pb-4 text-text font-light placeholder-text-muted/70 text-sm focus:outline-none"
|
class="w-full p-1 pb-4 text-text font-light placeholder-text-muted/70 text-sm focus:outline-none"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue