ikanban-web 0.2.10 → 0.2.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/{ghostty-web-CkHg_Jfr.js → ghostty-web-CEQVZrGO.js} +1 -1
- package/dist/assets/home-BfGWAM3p.js +1 -0
- package/dist/assets/{index-DbuHW0gF.css → index-7dPULZd1.css} +1 -1
- package/dist/assets/{index-n2BMSLCz.js → index-WJDzUYhg.js} +106 -106
- package/dist/assets/session-BDqUCVwy.js +24 -0
- package/dist/index.html +2 -2
- package/package.json +1 -1
- package/src/app.tsx +82 -61
- package/src/components/dialog-command-palette.tsx +70 -0
- package/src/components/dialog-fork.tsx +1 -1
- package/src/components/dialog-select-file.tsx +1 -1
- package/src/components/dialog-select-server.test.ts +16 -0
- package/src/components/dialog-select-server.tsx +59 -51
- package/src/components/prompt-input/submit.ts +1 -1
- package/src/components/server-list-item-frame.tsx +15 -0
- package/src/components/titlebar.tsx +12 -31
- package/src/context/global-sync/bootstrap-mode.ts +17 -0
- package/src/context/global-sync/bootstrap.ts +18 -10
- package/src/context/global-sync.test.ts +57 -0
- package/src/context/global-sync.tsx +5 -0
- package/src/context/notification.tsx +2 -2
- package/src/i18n/en.ts +13 -13
- package/src/i18n/zh.ts +13 -13
- package/src/pages/directory-layout.tsx +2 -2
- package/src/pages/home.tsx +104 -19
- package/src/pages/layout/sidebar-items.tsx +3 -3
- package/src/pages/layout/sidebar-project.tsx +1 -3
- package/src/pages/layout/sidebar-shell-helpers.ts +1 -1
- package/src/pages/layout/sidebar-shell.test.ts +2 -2
- package/src/pages/layout/sidebar-workspace.tsx +1 -1
- package/src/pages/layout.tsx +89 -179
- package/src/pages/session/message-timeline.tsx +4 -4
- package/src/pages/session/use-session-commands.tsx +1 -1
- package/src/pages/session.tsx +1 -1
- package/dist/assets/home-BTCNns6Z.js +0 -1
- package/dist/assets/session-S93i-VnN.js +0 -24
package/src/pages/layout.tsx
CHANGED
|
@@ -49,7 +49,10 @@ import { useTheme, type ColorScheme } from "ikanban-ui/theme"
|
|
|
49
49
|
import { DialogSelectProvider } from "@/components/dialog-select-provider"
|
|
50
50
|
import { DialogSelectServer } from "@/components/dialog-select-server"
|
|
51
51
|
import { DialogSettings } from "@/components/dialog-settings"
|
|
52
|
+
import { DialogCommandPalette } from "@/components/dialog-command-palette"
|
|
53
|
+
import { DialogSelectFile } from "@/components/dialog-select-file"
|
|
52
54
|
import { useCommand, type CommandOption } from "@/context/command"
|
|
55
|
+
import { FileProvider } from "@/context/file"
|
|
53
56
|
import { ConstrainDragXAxis } from "@/utils/solid-dnd"
|
|
54
57
|
import { DialogSelectDirectory } from "@/components/dialog-select-directory"
|
|
55
58
|
import { DialogEditProject } from "@/components/dialog-edit-project"
|
|
@@ -121,9 +124,10 @@ export default function Layout(props: ParentProps) {
|
|
|
121
124
|
}
|
|
122
125
|
const colorSchemeLabel = (scheme: ColorScheme) => language.t(colorSchemeKey[scheme])
|
|
123
126
|
const currentDir = createMemo(() => decode64(params.dir) ?? "")
|
|
127
|
+
const hasDirectoryRoute = createMemo(() => !!params.dir)
|
|
124
128
|
|
|
125
129
|
const [state, setState] = createStore({
|
|
126
|
-
autoselect:
|
|
130
|
+
autoselect: false,
|
|
127
131
|
busyWorkspaces: {} as Record<string, boolean>,
|
|
128
132
|
hoverSession: undefined as string | undefined,
|
|
129
133
|
hoverProject: undefined as string | undefined,
|
|
@@ -196,15 +200,7 @@ export default function Layout(props: ParentProps) {
|
|
|
196
200
|
setHoverProject(undefined)
|
|
197
201
|
})
|
|
198
202
|
|
|
199
|
-
const autoselecting = createMemo(() =>
|
|
200
|
-
if (params.dir) return false
|
|
201
|
-
if (!state.autoselect) return false
|
|
202
|
-
if (!pageReady()) return true
|
|
203
|
-
if (!layoutReady()) return true
|
|
204
|
-
const list = layout.projects.list()
|
|
205
|
-
if (list.length > 0) return true
|
|
206
|
-
return !!server.projects.last()
|
|
207
|
-
})
|
|
203
|
+
const autoselecting = createMemo(() => false)
|
|
208
204
|
|
|
209
205
|
createEffect(() => {
|
|
210
206
|
if (!state.autoselect) return
|
|
@@ -325,7 +321,7 @@ export default function Layout(props: ParentProps) {
|
|
|
325
321
|
e.details.type === "permission.asked"
|
|
326
322
|
? language.t("notification.permission.description", { sessionTitle, projectName })
|
|
327
323
|
: language.t("notification.question.description", { sessionTitle, projectName })
|
|
328
|
-
const href = `/${base64Encode(directory)}
|
|
324
|
+
const href = `/${base64Encode(directory)}/${props.sessionID}`
|
|
329
325
|
|
|
330
326
|
const now = Date.now()
|
|
331
327
|
const lastAlerted = alertedAtBySession.get(sessionKey) ?? 0
|
|
@@ -426,34 +422,6 @@ export default function Layout(props: ParentProps) {
|
|
|
426
422
|
return projects.find((p) => p.worktree === root)
|
|
427
423
|
})
|
|
428
424
|
|
|
429
|
-
createEffect(
|
|
430
|
-
on(
|
|
431
|
-
() => ({ ready: pageReady(), layoutReady: layoutReady(), dir: params.dir, list: layout.projects.list() }),
|
|
432
|
-
(value) => {
|
|
433
|
-
if (!value.ready) return
|
|
434
|
-
if (!value.layoutReady) return
|
|
435
|
-
if (!state.autoselect) return
|
|
436
|
-
if (value.dir) return
|
|
437
|
-
|
|
438
|
-
const last = server.projects.last()
|
|
439
|
-
|
|
440
|
-
if (value.list.length === 0) {
|
|
441
|
-
if (!last) return
|
|
442
|
-
setState("autoselect", false)
|
|
443
|
-
openProject(last, false)
|
|
444
|
-
navigateToProject(last)
|
|
445
|
-
return
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
const next = value.list.find((project) => project.worktree === last) ?? value.list[0]
|
|
449
|
-
if (!next) return
|
|
450
|
-
setState("autoselect", false)
|
|
451
|
-
openProject(next.worktree, false)
|
|
452
|
-
navigateToProject(next.worktree)
|
|
453
|
-
},
|
|
454
|
-
),
|
|
455
|
-
)
|
|
456
|
-
|
|
457
425
|
const workspaceName = (directory: string, projectId?: string, branch?: string) => {
|
|
458
426
|
const key = workspaceKey(directory)
|
|
459
427
|
const direct = store.workspaceName[key] ?? store.workspaceName[directory]
|
|
@@ -793,9 +761,9 @@ export default function Layout(props: ParentProps) {
|
|
|
793
761
|
)
|
|
794
762
|
if (session.id === params.id) {
|
|
795
763
|
if (nextSession) {
|
|
796
|
-
navigate(`/${params.dir}
|
|
764
|
+
navigate(`/${params.dir}/${nextSession.id}`)
|
|
797
765
|
} else {
|
|
798
|
-
navigate(`/${params.dir}
|
|
766
|
+
navigate(`/${params.dir}`)
|
|
799
767
|
}
|
|
800
768
|
}
|
|
801
769
|
}
|
|
@@ -803,11 +771,13 @@ export default function Layout(props: ParentProps) {
|
|
|
803
771
|
command.register("layout", () => {
|
|
804
772
|
const commands: CommandOption[] = [
|
|
805
773
|
{
|
|
806
|
-
id: "
|
|
807
|
-
title: language.t("command.
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
774
|
+
id: "file.open",
|
|
775
|
+
title: language.t("command.file.open"),
|
|
776
|
+
description: params.dir ? language.t("palette.search.placeholder") : language.t("command.project.open"),
|
|
777
|
+
category: language.t("command.category.file"),
|
|
778
|
+
keybind: "mod+p",
|
|
779
|
+
slash: "open",
|
|
780
|
+
onSelect: openGlobalFilePicker,
|
|
811
781
|
},
|
|
812
782
|
{
|
|
813
783
|
id: "project.open",
|
|
@@ -1059,7 +1029,7 @@ export default function Layout(props: ParentProps) {
|
|
|
1059
1029
|
|
|
1060
1030
|
function navigateToSession(session: Session | undefined) {
|
|
1061
1031
|
if (!session) return
|
|
1062
|
-
navigateWithSidebarReset(`/${base64Encode(session.directory)}
|
|
1032
|
+
navigateWithSidebarReset(`/${base64Encode(session.directory)}/${session.id}`)
|
|
1063
1033
|
}
|
|
1064
1034
|
|
|
1065
1035
|
function openProject(directory: string, navigate = true) {
|
|
@@ -1124,7 +1094,7 @@ export default function Layout(props: ParentProps) {
|
|
|
1124
1094
|
return
|
|
1125
1095
|
}
|
|
1126
1096
|
|
|
1127
|
-
navigateWithSidebarReset(`/${base64Encode(next.worktree)}
|
|
1097
|
+
navigateWithSidebarReset(`/${base64Encode(next.worktree)}`)
|
|
1128
1098
|
layout.projects.close(directory)
|
|
1129
1099
|
queueMicrotask(() => {
|
|
1130
1100
|
void navigateToProject(next.worktree)
|
|
@@ -1169,6 +1139,19 @@ export default function Layout(props: ParentProps) {
|
|
|
1169
1139
|
}
|
|
1170
1140
|
}
|
|
1171
1141
|
|
|
1142
|
+
function openGlobalFilePicker() {
|
|
1143
|
+
if (!params.dir) {
|
|
1144
|
+
dialog.show(() => <DialogCommandPalette />)
|
|
1145
|
+
return
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
dialog.show(() => (
|
|
1149
|
+
<FileProvider>
|
|
1150
|
+
<DialogSelectFile />
|
|
1151
|
+
</FileProvider>
|
|
1152
|
+
))
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1172
1155
|
const deleteWorkspace = async (root: string, directory: string, leaveDeletedWorkspace = false) => {
|
|
1173
1156
|
if (directory === root) return
|
|
1174
1157
|
|
|
@@ -1177,7 +1160,7 @@ export default function Layout(props: ParentProps) {
|
|
|
1177
1160
|
const deletedKey = workspaceKey(directory)
|
|
1178
1161
|
const shouldLeave = leaveDeletedWorkspace || (!!params.dir && currentKey === deletedKey)
|
|
1179
1162
|
if (!leaveDeletedWorkspace && shouldLeave) {
|
|
1180
|
-
navigateWithSidebarReset(`/${base64Encode(root)}
|
|
1163
|
+
navigateWithSidebarReset(`/${base64Encode(root)}`)
|
|
1181
1164
|
}
|
|
1182
1165
|
|
|
1183
1166
|
setBusy(directory, true)
|
|
@@ -1225,7 +1208,7 @@ export default function Layout(props: ParentProps) {
|
|
|
1225
1208
|
const valid = dirs.some((item) => workspaceKey(item) === nextKey)
|
|
1226
1209
|
|
|
1227
1210
|
if (params.dir && projectRoot(nextCurrent) === root && !valid) {
|
|
1228
|
-
navigateWithSidebarReset(`/${base64Encode(root)}
|
|
1211
|
+
navigateWithSidebarReset(`/${base64Encode(root)}`)
|
|
1229
1212
|
}
|
|
1230
1213
|
}
|
|
1231
1214
|
|
|
@@ -1294,7 +1277,7 @@ export default function Layout(props: ParentProps) {
|
|
|
1294
1277
|
{
|
|
1295
1278
|
label: language.t("command.session.new"),
|
|
1296
1279
|
onClick: () => {
|
|
1297
|
-
const href = `/${base64Encode(directory)}
|
|
1280
|
+
const href = `/${base64Encode(directory)}`
|
|
1298
1281
|
navigate(href)
|
|
1299
1282
|
layout.mobileSidebar.hide()
|
|
1300
1283
|
},
|
|
@@ -1330,7 +1313,7 @@ export default function Layout(props: ParentProps) {
|
|
|
1330
1313
|
const handleDelete = () => {
|
|
1331
1314
|
const leaveDeletedWorkspace = !!params.dir && workspaceKey(currentDir()) === workspaceKey(props.directory)
|
|
1332
1315
|
if (leaveDeletedWorkspace) {
|
|
1333
|
-
navigateWithSidebarReset(`/${base64Encode(props.root)}
|
|
1316
|
+
navigateWithSidebarReset(`/${base64Encode(props.root)}`)
|
|
1334
1317
|
}
|
|
1335
1318
|
dialog.close()
|
|
1336
1319
|
void deleteWorkspace(props.root, props.directory, leaveDeletedWorkspace)
|
|
@@ -1481,8 +1464,7 @@ export default function Layout(props: ParentProps) {
|
|
|
1481
1464
|
)
|
|
1482
1465
|
|
|
1483
1466
|
createEffect(() => {
|
|
1484
|
-
|
|
1485
|
-
document.documentElement.style.setProperty("--dialog-left-margin", `${sidebarWidth}px`)
|
|
1467
|
+
document.documentElement.style.setProperty("--dialog-left-margin", "0px")
|
|
1486
1468
|
})
|
|
1487
1469
|
|
|
1488
1470
|
const loadedSessionDirs = new Set<string>()
|
|
@@ -1628,7 +1610,7 @@ export default function Layout(props: ParentProps) {
|
|
|
1628
1610
|
})
|
|
1629
1611
|
|
|
1630
1612
|
globalSync.child(created.directory)
|
|
1631
|
-
navigateWithSidebarReset(`/${base64Encode(created.directory)}
|
|
1613
|
+
navigateWithSidebarReset(`/${base64Encode(created.directory)}`)
|
|
1632
1614
|
}
|
|
1633
1615
|
|
|
1634
1616
|
const workspaceSidebarCtx: WorkspaceSidebarContext = {
|
|
@@ -1821,7 +1803,7 @@ export default function Layout(props: ParentProps) {
|
|
|
1821
1803
|
size="large"
|
|
1822
1804
|
icon="plus-small"
|
|
1823
1805
|
class="w-full"
|
|
1824
|
-
onClick={() => navigateWithSidebarReset(`/${base64Encode(p().worktree)}
|
|
1806
|
+
onClick={() => navigateWithSidebarReset(`/${base64Encode(p().worktree)}`)}
|
|
1825
1807
|
>
|
|
1826
1808
|
{language.t("command.session.new")}
|
|
1827
1809
|
</Button>
|
|
@@ -1923,136 +1905,64 @@ export default function Layout(props: ParentProps) {
|
|
|
1923
1905
|
|
|
1924
1906
|
return (
|
|
1925
1907
|
<div class="relative bg-background-base flex-1 min-h-0 flex flex-col select-none [&_input]:select-text [&_textarea]:select-text [&_[contenteditable]]:select-text">
|
|
1926
|
-
<
|
|
1908
|
+
<Show when={hasDirectoryRoute()}>
|
|
1909
|
+
<Titlebar />
|
|
1910
|
+
</Show>
|
|
1927
1911
|
<div class="flex-1 min-h-0 flex">
|
|
1928
|
-
<
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
onMouseEnter={() => {
|
|
1940
|
-
if (navLeave.current === undefined) return
|
|
1941
|
-
clearTimeout(navLeave.current)
|
|
1942
|
-
navLeave.current = undefined
|
|
1943
|
-
}}
|
|
1944
|
-
onMouseLeave={() => {
|
|
1945
|
-
aim.reset()
|
|
1946
|
-
if (!sidebarHovering()) return
|
|
1947
|
-
|
|
1948
|
-
if (navLeave.current !== undefined) clearTimeout(navLeave.current)
|
|
1949
|
-
navLeave.current = window.setTimeout(() => {
|
|
1950
|
-
navLeave.current = undefined
|
|
1951
|
-
setHoverProject(undefined)
|
|
1952
|
-
setState("hoverSession", undefined)
|
|
1953
|
-
}, 300)
|
|
1954
|
-
}}
|
|
1955
|
-
>
|
|
1956
|
-
<div class="@container w-full h-full contain-strict">
|
|
1957
|
-
<SidebarContent
|
|
1958
|
-
opened={() => layout.sidebar.opened()}
|
|
1959
|
-
aimMove={aim.move}
|
|
1960
|
-
projects={() => layout.projects.list()}
|
|
1961
|
-
renderProject={(project) => (
|
|
1962
|
-
<SortableProject ctx={projectSidebarCtx} project={project} sortNow={sortNow} />
|
|
1963
|
-
)}
|
|
1964
|
-
handleDragStart={handleDragStart}
|
|
1965
|
-
handleDragEnd={handleDragEnd}
|
|
1966
|
-
handleDragOver={handleDragOver}
|
|
1967
|
-
openProjectLabel={language.t("command.project.open")}
|
|
1968
|
-
openProjectKeybind={() => command.keybind("project.open")}
|
|
1969
|
-
onOpenProject={chooseProject}
|
|
1970
|
-
renderProjectOverlay={() => (
|
|
1971
|
-
<ProjectDragOverlay projects={() => layout.projects.list()} activeProject={() => store.activeProject} />
|
|
1972
|
-
)}
|
|
1973
|
-
settingsLabel={() => language.t("sidebar.settings")}
|
|
1974
|
-
settingsKeybind={() => command.keybind("settings.open")}
|
|
1975
|
-
onOpenSettings={openSettings}
|
|
1976
|
-
helpLabel={() => language.t("sidebar.help")}
|
|
1977
|
-
onOpenHelp={() => platform.openLink("https://github.com/isomoes/ikanban/issues")}
|
|
1978
|
-
renderPanel={() => (
|
|
1979
|
-
<Show when={currentProject()} keyed>
|
|
1980
|
-
{(project) => <SidebarPanel project={project} />}
|
|
1981
|
-
</Show>
|
|
1982
|
-
)}
|
|
1912
|
+
<Show when={hasDirectoryRoute()}>
|
|
1913
|
+
<div class="xl:hidden">
|
|
1914
|
+
<div
|
|
1915
|
+
classList={{
|
|
1916
|
+
"fixed inset-x-0 top-10 bottom-0 z-40 transition-opacity duration-200": true,
|
|
1917
|
+
"opacity-100 pointer-events-auto": layout.mobileSidebar.opened(),
|
|
1918
|
+
"opacity-0 pointer-events-none": !layout.mobileSidebar.opened(),
|
|
1919
|
+
}}
|
|
1920
|
+
onClick={(e) => {
|
|
1921
|
+
if (e.target === e.currentTarget) layout.mobileSidebar.hide()
|
|
1922
|
+
}}
|
|
1983
1923
|
/>
|
|
1924
|
+
<nav
|
|
1925
|
+
aria-label={language.t("sidebar.nav.projectsAndSessions")}
|
|
1926
|
+
data-component="sidebar-nav-mobile"
|
|
1927
|
+
classList={{
|
|
1928
|
+
"@container fixed top-10 bottom-0 left-0 z-50 w-72 bg-background-base transition-transform duration-200 ease-out": true,
|
|
1929
|
+
"translate-x-0": layout.mobileSidebar.opened(),
|
|
1930
|
+
"-translate-x-full": !layout.mobileSidebar.opened(),
|
|
1931
|
+
}}
|
|
1932
|
+
onClick={(e) => e.stopPropagation()}
|
|
1933
|
+
>
|
|
1934
|
+
<SidebarContent
|
|
1935
|
+
mobile
|
|
1936
|
+
opened={() => false}
|
|
1937
|
+
aimMove={aim.move}
|
|
1938
|
+
projects={() => layout.projects.list()}
|
|
1939
|
+
renderProject={(project) => (
|
|
1940
|
+
<SortableProject ctx={projectSidebarCtx} project={project} sortNow={sortNow} mobile />
|
|
1941
|
+
)}
|
|
1942
|
+
handleDragStart={handleDragStart}
|
|
1943
|
+
handleDragEnd={handleDragEnd}
|
|
1944
|
+
handleDragOver={handleDragOver}
|
|
1945
|
+
openProjectLabel={language.t("command.project.open")}
|
|
1946
|
+
openProjectKeybind={() => command.keybind("project.open")}
|
|
1947
|
+
onOpenProject={chooseProject}
|
|
1948
|
+
renderProjectOverlay={() => (
|
|
1949
|
+
<ProjectDragOverlay projects={() => layout.projects.list()} activeProject={() => store.activeProject} />
|
|
1950
|
+
)}
|
|
1951
|
+
settingsLabel={() => language.t("sidebar.settings")}
|
|
1952
|
+
settingsKeybind={() => command.keybind("settings.open")}
|
|
1953
|
+
onOpenSettings={openSettings}
|
|
1954
|
+
helpLabel={() => language.t("sidebar.help")}
|
|
1955
|
+
onOpenHelp={() => platform.openLink("https://github.com/isomoes/ikanban/issues")}
|
|
1956
|
+
renderPanel={() => <SidebarPanel project={currentProject()} mobile />}
|
|
1957
|
+
/>
|
|
1958
|
+
</nav>
|
|
1984
1959
|
</div>
|
|
1985
|
-
|
|
1986
|
-
{(worktree) => (
|
|
1987
|
-
<div class="absolute inset-y-0 left-16 z-50 flex" onMouseEnter={aim.reset}>
|
|
1988
|
-
<SidebarPanel project={hoverProjectData()} />
|
|
1989
|
-
</div>
|
|
1990
|
-
)}
|
|
1991
|
-
</Show>
|
|
1992
|
-
<Show when={layout.sidebar.opened()}>
|
|
1993
|
-
<ResizeHandle
|
|
1994
|
-
direction="horizontal"
|
|
1995
|
-
size={layout.sidebar.width()}
|
|
1996
|
-
min={244}
|
|
1997
|
-
max={typeof window === "undefined" ? 1000 : window.innerWidth * 0.3 + 64}
|
|
1998
|
-
collapseThreshold={244}
|
|
1999
|
-
onResize={layout.sidebar.resize}
|
|
2000
|
-
onCollapse={layout.sidebar.close}
|
|
2001
|
-
/>
|
|
2002
|
-
</Show>
|
|
2003
|
-
</nav>
|
|
2004
|
-
<div class="xl:hidden">
|
|
2005
|
-
<div
|
|
2006
|
-
classList={{
|
|
2007
|
-
"fixed inset-x-0 top-10 bottom-0 z-40 transition-opacity duration-200": true,
|
|
2008
|
-
"opacity-100 pointer-events-auto": layout.mobileSidebar.opened(),
|
|
2009
|
-
"opacity-0 pointer-events-none": !layout.mobileSidebar.opened(),
|
|
2010
|
-
}}
|
|
2011
|
-
onClick={(e) => {
|
|
2012
|
-
if (e.target === e.currentTarget) layout.mobileSidebar.hide()
|
|
2013
|
-
}}
|
|
2014
|
-
/>
|
|
2015
|
-
<nav
|
|
2016
|
-
aria-label={language.t("sidebar.nav.projectsAndSessions")}
|
|
2017
|
-
data-component="sidebar-nav-mobile"
|
|
2018
|
-
classList={{
|
|
2019
|
-
"@container fixed top-10 bottom-0 left-0 z-50 w-72 bg-background-base transition-transform duration-200 ease-out": true,
|
|
2020
|
-
"translate-x-0": layout.mobileSidebar.opened(),
|
|
2021
|
-
"-translate-x-full": !layout.mobileSidebar.opened(),
|
|
2022
|
-
}}
|
|
2023
|
-
onClick={(e) => e.stopPropagation()}
|
|
2024
|
-
>
|
|
2025
|
-
<SidebarContent
|
|
2026
|
-
mobile
|
|
2027
|
-
opened={() => layout.sidebar.opened()}
|
|
2028
|
-
aimMove={aim.move}
|
|
2029
|
-
projects={() => layout.projects.list()}
|
|
2030
|
-
renderProject={(project) => (
|
|
2031
|
-
<SortableProject ctx={projectSidebarCtx} project={project} sortNow={sortNow} mobile />
|
|
2032
|
-
)}
|
|
2033
|
-
handleDragStart={handleDragStart}
|
|
2034
|
-
handleDragEnd={handleDragEnd}
|
|
2035
|
-
handleDragOver={handleDragOver}
|
|
2036
|
-
openProjectLabel={language.t("command.project.open")}
|
|
2037
|
-
openProjectKeybind={() => command.keybind("project.open")}
|
|
2038
|
-
onOpenProject={chooseProject}
|
|
2039
|
-
renderProjectOverlay={() => (
|
|
2040
|
-
<ProjectDragOverlay projects={() => layout.projects.list()} activeProject={() => store.activeProject} />
|
|
2041
|
-
)}
|
|
2042
|
-
settingsLabel={() => language.t("sidebar.settings")}
|
|
2043
|
-
settingsKeybind={() => command.keybind("settings.open")}
|
|
2044
|
-
onOpenSettings={openSettings}
|
|
2045
|
-
helpLabel={() => language.t("sidebar.help")}
|
|
2046
|
-
onOpenHelp={() => platform.openLink("https://github.com/isomoes/ikanban/issues")}
|
|
2047
|
-
renderPanel={() => <SidebarPanel project={currentProject()} mobile />}
|
|
2048
|
-
/>
|
|
2049
|
-
</nav>
|
|
2050
|
-
</div>
|
|
1960
|
+
</Show>
|
|
2051
1961
|
|
|
2052
1962
|
<main
|
|
2053
1963
|
classList={{
|
|
2054
1964
|
"size-full overflow-x-hidden flex flex-col items-start contain-strict border-t border-border-weak-base": true,
|
|
2055
|
-
"
|
|
1965
|
+
"border-t-0": !hasDirectoryRoute(),
|
|
2056
1966
|
}}
|
|
2057
1967
|
>
|
|
2058
1968
|
<Show when={!autoselecting()} fallback={<div class="size-full" />}>
|
|
@@ -346,14 +346,14 @@ export function MessageTimeline(props: {
|
|
|
346
346
|
const navigateAfterSessionRemoval = (sessionID: string, parentID?: string, nextSessionID?: string) => {
|
|
347
347
|
if (params.id !== sessionID) return
|
|
348
348
|
if (parentID) {
|
|
349
|
-
navigate(`/${params.dir}
|
|
349
|
+
navigate(`/${params.dir}/${parentID}`)
|
|
350
350
|
return
|
|
351
351
|
}
|
|
352
352
|
if (nextSessionID) {
|
|
353
|
-
navigate(`/${params.dir}
|
|
353
|
+
navigate(`/${params.dir}/${nextSessionID}`)
|
|
354
354
|
return
|
|
355
355
|
}
|
|
356
|
-
navigate(`/${params.dir}
|
|
356
|
+
navigate(`/${params.dir}`)
|
|
357
357
|
}
|
|
358
358
|
|
|
359
359
|
const archiveSession = async (sessionID: string) => {
|
|
@@ -446,7 +446,7 @@ export function MessageTimeline(props: {
|
|
|
446
446
|
const navigateParent = () => {
|
|
447
447
|
const id = parentID()
|
|
448
448
|
if (!id) return
|
|
449
|
-
navigate(`/${params.dir}
|
|
449
|
+
navigate(`/${params.dir}/${id}`)
|
|
450
450
|
}
|
|
451
451
|
|
|
452
452
|
function DialogDeleteSession(props: { sessionID: string }) {
|
|
@@ -194,7 +194,7 @@ export const useSessionCommands = (actions: SessionCommandContext) => {
|
|
|
194
194
|
title: language.t("command.session.new"),
|
|
195
195
|
keybind: "mod+shift+s",
|
|
196
196
|
slash: "new",
|
|
197
|
-
onSelect: () => navigate(`/${params.dir}
|
|
197
|
+
onSelect: () => navigate(`/${params.dir}`),
|
|
198
198
|
}),
|
|
199
199
|
]);
|
|
200
200
|
|
package/src/pages/session.tsx
CHANGED
|
@@ -1319,7 +1319,7 @@ export default function Page() {
|
|
|
1319
1319
|
if (!target) return
|
|
1320
1320
|
if (target === sdk.directory) return
|
|
1321
1321
|
layout.projects.open(target)
|
|
1322
|
-
navigate(`/${base64Encode(target)}
|
|
1322
|
+
navigate(`/${base64Encode(target)}`)
|
|
1323
1323
|
}}
|
|
1324
1324
|
/>
|
|
1325
1325
|
</Match>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{u as K,a as N,b as q,c as H,d as T,e as V,f as J,g as Q,h as P,s as U,i as W,j as t,k as s,L as X,B as z,l as I,m as Y,n as Z,D as ee,M as A,I as L,S as R,o as O,p as te,t as c,F as re,q as se,r as le,v as ie}from"./index-n2BMSLCz.js";var ne=c("<div>"),oe=c('<div class="mt-6 flex w-full flex-col gap-6"><section class="flex flex-col gap-4"><div class="grid gap-3 lg:grid-cols-2">'),ae=c('<div class="mt-6 rounded-2xl border border-dashed border-border-weak bg-background-base/60 px-6 py-10"><div class="mx-auto flex max-w-md flex-col items-center gap-3 text-center"><div class="flex size-12 items-center justify-center rounded-2xl border border-border-weak bg-background-base/80"></div><div class="flex flex-col gap-1 items-center justify-center"><div class="text-14-medium text-text-strong"></div><div class="text-12-regular text-text-weak">'),ce=c('<div class="mx-auto w-full max-w-7xl px-4 py-6 md:px-6 md:py-8"><div class="flex flex-col gap-4 md:flex-row md:items-start md:justify-between"><div class=min-w-0><div class="flex items-center gap-3"><div class="flex size-10 items-center justify-center rounded-2xl border border-border-weak bg-background-base/80"></div><div><div class="text-18-medium text-text-strong"></div><div class="mt-0.5 text-12-regular text-text-weak"></div></div></div></div><div class="flex items-center gap-2 self-start md:justify-end">'),de=c('<div class="rounded-xl border border-dashed border-border-weak px-3 py-8 text-center text-12-regular text-text-weak">'),ue=c('<section class="rounded-2xl border border-border-weak bg-background-base/80 p-3 md:p-4 min-h-72"><div class="flex items-center justify-between gap-3"><div class="flex items-center gap-2 min-w-0"><div></div><div class="text-14-medium text-text-strong"></div></div><div class="text-12-mono text-text-weak"></div></div><div class="mt-3 flex flex-col gap-2">'),me=c('<span class="min-w-0 flex-1 truncate text-12-regular text-text-weak">'),ge=c('<div class="flex shrink-0 items-center gap-2 text-12-regular text-text-weak"><span>'),fe=c('<div class="overflow-hidden rounded-xl border border-border-weak bg-background-base/70 hover:border-border-strong"><div class="flex items-start justify-between gap-3 px-3 pt-3"><div class="min-w-0 flex-1 pt-1"><div class="truncate text-14-medium leading-tight text-text-strong">');function xe(){const l=K(),j=N(),x=q(),h=H(),v=T(),b=V(),g=J(),i=Q(),C=P(()=>l.data.project.slice().sort((e,r)=>(r.time.updated??r.time.created)-(e.time.updated??e.time.created)).slice(0,5)),n=P(()=>{const e=Date.now(),r={progress:[],idle:[]};for(const a of C()){const[d]=l.child(a.worktree),u=U(d,e);for(const f of u){const y=d.session_status[f.id],B=f.time.updated??f.time.created,_={session:f,projectDirectory:a.worktree,updatedAt:B};if(y?.type==="busy"||y?.type==="retry"){r.progress.push(_);continue}r.idle.push(_)}}for(const a of Object.keys(r))r[a].sort((d,u)=>u.updatedAt-d.updatedAt);return r});W(()=>{for(const e of C())l.child(e.worktree)});const w=P(()=>{const e=g.healthy();return e===!0?"bg-icon-success-base":e===!1?"bg-icon-critical-base":"bg-border-weak-base"});function $(e){j.projects.open(e),g.projects.touch(e),v(`/${O(e)}/session`)}function S(e,r){j.projects.open(e),g.projects.touch(e),v(`/${O(e)}/session/${r}`)}async function D(e,r){const[,a]=l.child(e,{bootstrap:!1});await b.client.session.update({sessionID:r,time:{archived:Date.now()}}),a("session",d=>d.filter(u=>u.id!==r))}async function o(){function e(r){if(Array.isArray(r))for(const a of r)$(a);else r&&$(r)}if(x.openDirectoryPickerDialog&&g.isLocal()){const r=await x.openDirectoryPickerDialog?.({title:i.t("command.project.open"),multiple:!0});e(r)}else h.show(()=>s(te,{multiple:!0,onSelect:e}),()=>e(null))}return(()=>{var e=ce(),r=e.firstChild,a=r.firstChild,d=a.firstChild,u=d.firstChild,f=u.nextSibling,y=f.firstChild,B=y.nextSibling,_=a.nextSibling;return t(u,s(X,{class:"w-6 opacity-90"})),t(y,()=>i.t("home.sessionBoard")),t(B,()=>i.t("home.sessionBoard.description")),t(_,s(z,{icon:"folder-add-left",size:"normal",class:"pl-2 pr-3",onClick:o,get children(){return i.t("command.project.open")}}),null),t(_,s(z,{size:"normal",variant:"ghost",class:"pr-3 text-13-regular text-text-weak",onClick:()=>h.show(()=>s(ee,{})),get children(){return[(()=>{var m=ne();return I(p=>Y(m,{"size-2 rounded-full":!0,[w()]:!0},p)),m})(),Z(()=>g.name)]}}),null),t(e,s(R,{get children(){return[s(A,{get when(){return l.data.project.length>0},get children(){var m=oe(),p=m.firstChild,k=p.firstChild;return t(k,s(E,{get title(){return i.t("home.sessionBoard.progress")},icon:"brain",tone:"progress",get cards(){return n().progress},onOpen:S,onArchive:D,get empty(){return i.t("home.sessionBoard.emptyProgress")}}),null),t(k,s(E,{get title(){return i.t("home.sessionBoard.idle")},icon:"dash",tone:"idle",get cards(){return n().idle},onOpen:S,onArchive:D,get empty(){return i.t("home.sessionBoard.emptyIdle")}}),null),m}}),s(A,{when:!0,get children(){var m=ae(),p=m.firstChild,k=p.firstChild,F=k.nextSibling,M=F.firstChild,G=M.nextSibling;return t(k,s(L,{name:"folder-add-left",size:"large"})),t(M,()=>i.t("home.empty.title")),t(G,()=>i.t("home.empty.description")),t(p,s(z,{class:"mt-1 px-3",onClick:o,get children(){return i.t("command.project.open")}}),null),m}})]}}),null),e})()}function E(l){const j=()=>l.tone==="progress"?"bg-emerald-500/12 text-emerald-300 border-emerald-500/20":"bg-sky-500/12 text-sky-300 border-sky-500/20";return(()=>{var x=ue(),h=x.firstChild,v=h.firstChild,b=v.firstChild,g=b.nextSibling,i=v.nextSibling,C=h.nextSibling;return t(b,s(L,{get name(){return l.icon},size:"small"})),t(g,()=>l.title),t(i,()=>l.cards.length),t(C,s(R,{get children(){return[s(A,{get when(){return l.cards.length>0},get children(){return s(re,{get each(){return l.cards},children:n=>(()=>{var w=fe(),$=w.firstChild,S=$.firstChild,D=S.firstChild;return t(D,()=>n.session.title),t($,s(se,{icon:"archive",variant:"ghost",class:"size-7 rounded-md","aria-label":"Archive session",onClick:o=>{o.preventDefault(),o.stopPropagation(),l.onArchive(n.projectDirectory,n.session.id)}}),null),t(w,s(z,{variant:"ghost",class:"flex h-auto w-full min-w-0 items-center justify-between gap-3 rounded-none border-0 bg-transparent px-3 pb-3 pt-2 text-left",onClick:()=>l.onOpen(n.projectDirectory,n.session.id),get children(){return[(()=>{var o=me();return t(o,()=>n.projectDirectory.replace(/^.*?([^/\\]+(?:[/\\][^/\\]+)?)$/,"$1")),o})(),(()=>{var o=ge(),e=o.firstChild;return t(e,()=>le.fromMillis(n.updatedAt).toRelative()),t(o,s(L,{name:"arrow-right",size:"small",class:"text-icon-weak shrink-0"}),null),o})()]}}),null),w})()})}}),s(A,{when:!0,get children(){var n=de();return t(n,()=>l.empty),n}})]}})),I(()=>ie(b,`size-7 rounded-full border flex items-center justify-center ${j()}`)),x})()}export{xe as default};
|