|
|
@@ -172,9 +172,9 @@ export default function Layout(props: ParentProps) {
|
|
|
const perm = e.details.properties
|
|
|
if (permission.autoResponds(perm)) return
|
|
|
|
|
|
- const sessionKey = `${directory}:${perm.sessionID}`
|
|
|
const [store] = globalSync.child(directory)
|
|
|
const session = store.session.find((s) => s.id === perm.sessionID)
|
|
|
+ const sessionKey = `${directory}:${perm.sessionID}`
|
|
|
|
|
|
const sessionTitle = session?.title ?? "New session"
|
|
|
const projectName = getFilename(directory)
|
|
|
@@ -665,14 +665,13 @@ export default function Layout(props: ParentProps) {
|
|
|
<>
|
|
|
<div
|
|
|
data-session-id={props.session.id}
|
|
|
- class="group/session relative w-full pr-2 py-1 rounded-md cursor-default transition-colors
|
|
|
+ class="group/session relative w-full rounded-md cursor-default transition-colors
|
|
|
hover:bg-surface-raised-base-hover focus-within:bg-surface-raised-base-hover has-[.active]:bg-surface-raised-base-hover"
|
|
|
- style={{ "padding-left": "16px" }}
|
|
|
>
|
|
|
<Tooltip placement={props.mobile ? "bottom" : "right"} value={props.session.title} gutter={10}>
|
|
|
<A
|
|
|
href={`${props.slug}/session/${props.session.id}`}
|
|
|
- class="flex flex-col min-w-0 text-left w-full focus:outline-none"
|
|
|
+ class="flex flex-col min-w-0 text-left w-full focus:outline-none pl-4 pr-2 py-1"
|
|
|
>
|
|
|
<div class="flex items-center self-stretch gap-6 justify-between transition-[padding] group-hover/session:pr-7 group-focus-within/session:pr-7 group-active/session:pr-7">
|
|
|
<span
|
|
|
@@ -740,10 +739,17 @@ export default function Layout(props: ParentProps) {
|
|
|
const SortableProject = (props: { project: LocalProject; mobile?: boolean }): JSX.Element => {
|
|
|
const sortable = createSortable(props.project.worktree)
|
|
|
const showExpanded = createMemo(() => props.mobile || layout.sidebar.opened())
|
|
|
- const slug = createMemo(() => base64Encode(props.project.worktree))
|
|
|
+ const defaultWorktree = createMemo(() => base64Encode(props.project.worktree))
|
|
|
const name = createMemo(() => props.project.name || getFilename(props.project.worktree))
|
|
|
const [store, setProjectStore] = globalSync.child(props.project.worktree)
|
|
|
- const sessions = createMemo(() => store.session.toSorted(sortSessions))
|
|
|
+ const stores = createMemo(() =>
|
|
|
+ [props.project.worktree, ...(props.project.sandboxes ?? [])].map((dir) => globalSync.child(dir)[0]),
|
|
|
+ )
|
|
|
+ const sessions = createMemo(() =>
|
|
|
+ stores()
|
|
|
+ .flatMap((store) => store.session.filter((session) => session.directory === store.path.directory))
|
|
|
+ .toSorted(sortSessions),
|
|
|
+ )
|
|
|
const rootSessions = createMemo(() => sessions().filter((s) => !s.parentID))
|
|
|
const hasMoreSessions = createMemo(() => store.session.length >= store.limit)
|
|
|
const loadMoreSessions = async () => {
|
|
|
@@ -799,7 +805,7 @@ export default function Layout(props: ParentProps) {
|
|
|
</DropdownMenu.Portal>
|
|
|
</DropdownMenu>
|
|
|
<TooltipKeybind placement="top" title="New session" keybind={command.keybind("session.new")}>
|
|
|
- <IconButton as={A} href={`${slug()}/session`} icon="plus-small" variant="ghost" />
|
|
|
+ <IconButton as={A} href={`${defaultWorktree()}/session`} icon="plus-small" variant="ghost" />
|
|
|
</TooltipKeybind>
|
|
|
</div>
|
|
|
</Button>
|
|
|
@@ -807,7 +813,12 @@ export default function Layout(props: ParentProps) {
|
|
|
<nav class="hidden @[4rem]:flex w-full flex-col gap-1.5">
|
|
|
<For each={rootSessions()}>
|
|
|
{(session) => (
|
|
|
- <SessionItem session={session} slug={slug()} project={props.project} mobile={props.mobile} />
|
|
|
+ <SessionItem
|
|
|
+ session={session}
|
|
|
+ slug={base64Encode(session.directory)}
|
|
|
+ project={props.project}
|
|
|
+ mobile={props.mobile}
|
|
|
+ />
|
|
|
)}
|
|
|
</For>
|
|
|
<Show when={rootSessions().length === 0}>
|
|
|
@@ -819,7 +830,7 @@ export default function Layout(props: ParentProps) {
|
|
|
<div class="flex-1 min-w-0">
|
|
|
<Tooltip placement={props.mobile ? "bottom" : "right"} value="New session">
|
|
|
<A
|
|
|
- href={`${slug()}/session`}
|
|
|
+ href={`${defaultWorktree()}/session`}
|
|
|
class="flex flex-col gap-1 min-w-0 text-left w-full focus:outline-none"
|
|
|
>
|
|
|
<div class="flex items-center self-stretch gap-6 justify-between">
|
|
|
@@ -875,76 +886,85 @@ export default function Layout(props: ParentProps) {
|
|
|
const SidebarContent = (sidebarProps: { mobile?: boolean }) => {
|
|
|
const expanded = () => sidebarProps.mobile || layout.sidebar.opened()
|
|
|
return (
|
|
|
- <>
|
|
|
- <div class="flex flex-col items-start self-stretch gap-4 p-2 min-h-0 overflow-hidden">
|
|
|
+ <div class="flex flex-col self-stretch h-full items-center justify-between overflow-hidden min-h-0">
|
|
|
+ <div class="flex flex-col items-start self-stretch gap-4 min-h-0">
|
|
|
<Show when={!sidebarProps.mobile}>
|
|
|
- <A href="/" class="shrink-0 h-8 flex items-center justify-start px-2" data-tauri-drag-region>
|
|
|
- <Mark class="shrink-0" />
|
|
|
- </A>
|
|
|
- </Show>
|
|
|
- <Show when={!sidebarProps.mobile}>
|
|
|
- <TooltipKeybind
|
|
|
- class="shrink-0"
|
|
|
- placement="right"
|
|
|
- title="Toggle sidebar"
|
|
|
- keybind={command.keybind("sidebar.toggle")}
|
|
|
- inactive={expanded()}
|
|
|
- >
|
|
|
- <Button
|
|
|
- variant="ghost"
|
|
|
- size="large"
|
|
|
- class="group/sidebar-toggle shrink-0 w-full text-left justify-start rounded-lg px-2"
|
|
|
- onClick={layout.sidebar.toggle}
|
|
|
- >
|
|
|
- <div class="relative -ml-px flex items-center justify-center size-4 [&>*]:absolute [&>*]:inset-0">
|
|
|
- <Icon
|
|
|
- name={layout.sidebar.opened() ? "layout-left" : "layout-right"}
|
|
|
- size="small"
|
|
|
- class="group-hover/sidebar-toggle:hidden"
|
|
|
- />
|
|
|
- <Icon
|
|
|
- name={layout.sidebar.opened() ? "layout-left-partial" : "layout-right-partial"}
|
|
|
- size="small"
|
|
|
- class="hidden group-hover/sidebar-toggle:inline-block"
|
|
|
- />
|
|
|
- <Icon
|
|
|
- name={layout.sidebar.opened() ? "layout-left-full" : "layout-right-full"}
|
|
|
- size="small"
|
|
|
- class="hidden group-active/sidebar-toggle:inline-block"
|
|
|
- />
|
|
|
- </div>
|
|
|
- <Show when={layout.sidebar.opened()}>
|
|
|
- <div class="hidden group-hover/sidebar-toggle:block group-active/sidebar-toggle:block text-text-base">
|
|
|
- Toggle sidebar
|
|
|
- </div>
|
|
|
- </Show>
|
|
|
- </Button>
|
|
|
- </TooltipKeybind>
|
|
|
- </Show>
|
|
|
- <DragDropProvider
|
|
|
- onDragStart={handleDragStart}
|
|
|
- onDragEnd={handleDragEnd}
|
|
|
- onDragOver={handleDragOver}
|
|
|
- collisionDetector={closestCenter}
|
|
|
- >
|
|
|
- <DragDropSensors />
|
|
|
- <ConstrainDragXAxis />
|
|
|
<div
|
|
|
- ref={(el) => {
|
|
|
- if (!sidebarProps.mobile) scrollContainerRef = el
|
|
|
+ classList={{
|
|
|
+ "border-b border-border-weak-base w-full h-12 ml-px flex items-center pl-1.75 shrink-0": true,
|
|
|
+ "justify-start": expanded(),
|
|
|
}}
|
|
|
- class="w-full min-w-8 flex flex-col gap-2 min-h-0 overflow-y-auto no-scrollbar"
|
|
|
>
|
|
|
- <SortableProvider ids={layout.projects.list().map((p) => p.worktree)}>
|
|
|
- <For each={layout.projects.list()}>
|
|
|
- {(project) => <SortableProject project={project} mobile={sidebarProps.mobile} />}
|
|
|
- </For>
|
|
|
- </SortableProvider>
|
|
|
+ <A href="/" class="shrink-0 h-8 flex items-center justify-start px-2 w-full" data-tauri-drag-region>
|
|
|
+ <Mark class="shrink-0" />
|
|
|
+ </A>
|
|
|
</div>
|
|
|
- <DragOverlay>
|
|
|
- <ProjectDragOverlay />
|
|
|
- </DragOverlay>
|
|
|
- </DragDropProvider>
|
|
|
+ </Show>
|
|
|
+ <div class="flex flex-col items-start self-stretch gap-4 px-2 overflow-hidden min-h-0">
|
|
|
+ <Show when={!sidebarProps.mobile}>
|
|
|
+ <TooltipKeybind
|
|
|
+ class="shrink-0"
|
|
|
+ placement="right"
|
|
|
+ title="Toggle sidebar"
|
|
|
+ keybind={command.keybind("sidebar.toggle")}
|
|
|
+ inactive={expanded()}
|
|
|
+ >
|
|
|
+ <Button
|
|
|
+ variant="ghost"
|
|
|
+ size="large"
|
|
|
+ class="group/sidebar-toggle shrink-0 w-full text-left justify-start rounded-lg px-2"
|
|
|
+ onClick={layout.sidebar.toggle}
|
|
|
+ >
|
|
|
+ <div class="relative -ml-px flex items-center justify-center size-4 [&>*]:absolute [&>*]:inset-0">
|
|
|
+ <Icon
|
|
|
+ name={layout.sidebar.opened() ? "layout-left" : "layout-right"}
|
|
|
+ size="small"
|
|
|
+ class="group-hover/sidebar-toggle:hidden"
|
|
|
+ />
|
|
|
+ <Icon
|
|
|
+ name={layout.sidebar.opened() ? "layout-left-partial" : "layout-right-partial"}
|
|
|
+ size="small"
|
|
|
+ class="hidden group-hover/sidebar-toggle:inline-block"
|
|
|
+ />
|
|
|
+ <Icon
|
|
|
+ name={layout.sidebar.opened() ? "layout-left-full" : "layout-right-full"}
|
|
|
+ size="small"
|
|
|
+ class="hidden group-active/sidebar-toggle:inline-block"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <Show when={layout.sidebar.opened()}>
|
|
|
+ <div class="hidden group-hover/sidebar-toggle:block group-active/sidebar-toggle:block text-text-base">
|
|
|
+ Toggle sidebar
|
|
|
+ </div>
|
|
|
+ </Show>
|
|
|
+ </Button>
|
|
|
+ </TooltipKeybind>
|
|
|
+ </Show>
|
|
|
+ <DragDropProvider
|
|
|
+ onDragStart={handleDragStart}
|
|
|
+ onDragEnd={handleDragEnd}
|
|
|
+ onDragOver={handleDragOver}
|
|
|
+ collisionDetector={closestCenter}
|
|
|
+ >
|
|
|
+ <DragDropSensors />
|
|
|
+ <ConstrainDragXAxis />
|
|
|
+ <div
|
|
|
+ ref={(el) => {
|
|
|
+ if (!sidebarProps.mobile) scrollContainerRef = el
|
|
|
+ }}
|
|
|
+ class="w-full min-w-8 flex flex-col gap-2 min-h-0 overflow-y-auto no-scrollbar"
|
|
|
+ >
|
|
|
+ <SortableProvider ids={layout.projects.list().map((p) => p.worktree)}>
|
|
|
+ <For each={layout.projects.list()}>
|
|
|
+ {(project) => <SortableProject project={project} mobile={sidebarProps.mobile} />}
|
|
|
+ </For>
|
|
|
+ </SortableProvider>
|
|
|
+ </div>
|
|
|
+ <DragOverlay>
|
|
|
+ <ProjectDragOverlay />
|
|
|
+ </DragOverlay>
|
|
|
+ </DragDropProvider>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
<div class="flex flex-col gap-1.5 self-stretch items-start shrink-0 px-2 py-3">
|
|
|
<Switch>
|
|
|
@@ -1017,7 +1037,7 @@ export default function Layout(props: ParentProps) {
|
|
|
</Button>
|
|
|
</Tooltip>
|
|
|
</div>
|
|
|
- </>
|
|
|
+ </div>
|
|
|
)
|
|
|
}
|
|
|
|