ikanban-web 0.2.9 → 0.2.11
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-CveYg7XI.js → ghostty-web-BOsxUEnx.js} +1 -1
- package/dist/assets/home-DmwjxlRp.js +1 -0
- package/dist/assets/{index-BlcL7wgr.js → index-CE2ZqGRp.js} +103 -103
- package/dist/assets/index-Z4u1EVXA.css +1 -0
- package/dist/assets/session-FqpMK7PV.js +24 -0
- package/dist/index.html +2 -2
- package/package.json +2 -2
- package/src/app.tsx +82 -57
- 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/prompt-input/submit.ts +1 -1
- package/src/components/titlebar.tsx +12 -1
- package/src/context/notification.tsx +2 -2
- package/src/i18n/en.ts +173 -83
- package/src/i18n/zh.ts +98 -47
- package/src/pages/directory-layout.tsx +2 -2
- package/src/pages/home.tsx +374 -89
- package/src/pages/layout/sidebar-items.tsx +3 -3
- package/src/pages/layout/sidebar-workspace.tsx +1 -1
- package/src/pages/layout.tsx +175 -237
- package/src/pages/session/message-timeline.tsx +6 -5
- package/src/pages/session/use-session-commands.tsx +1 -1
- package/src/pages/session.tsx +2 -1
- package/dist/assets/home-OHGVA1hY.js +0 -1
- package/dist/assets/index-B0TEjAod.css +0 -1
- package/dist/assets/session-CdIG8nTN.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"
|
|
@@ -62,7 +65,6 @@ import {
|
|
|
62
65
|
effectiveWorkspaceOrder,
|
|
63
66
|
errorMessage,
|
|
64
67
|
getDraggableId,
|
|
65
|
-
latestRootSession,
|
|
66
68
|
sortedRootSessions,
|
|
67
69
|
workspaceKey,
|
|
68
70
|
} from "./layout/helpers"
|
|
@@ -122,9 +124,10 @@ export default function Layout(props: ParentProps) {
|
|
|
122
124
|
}
|
|
123
125
|
const colorSchemeLabel = (scheme: ColorScheme) => language.t(colorSchemeKey[scheme])
|
|
124
126
|
const currentDir = createMemo(() => decode64(params.dir) ?? "")
|
|
127
|
+
const hasDirectoryRoute = createMemo(() => !!params.dir)
|
|
125
128
|
|
|
126
129
|
const [state, setState] = createStore({
|
|
127
|
-
autoselect:
|
|
130
|
+
autoselect: false,
|
|
128
131
|
busyWorkspaces: {} as Record<string, boolean>,
|
|
129
132
|
hoverSession: undefined as string | undefined,
|
|
130
133
|
hoverProject: undefined as string | undefined,
|
|
@@ -197,15 +200,7 @@ export default function Layout(props: ParentProps) {
|
|
|
197
200
|
setHoverProject(undefined)
|
|
198
201
|
})
|
|
199
202
|
|
|
200
|
-
const autoselecting = createMemo(() =>
|
|
201
|
-
if (params.dir) return false
|
|
202
|
-
if (!state.autoselect) return false
|
|
203
|
-
if (!pageReady()) return true
|
|
204
|
-
if (!layoutReady()) return true
|
|
205
|
-
const list = layout.projects.list()
|
|
206
|
-
if (list.length > 0) return true
|
|
207
|
-
return !!server.projects.last()
|
|
208
|
-
})
|
|
203
|
+
const autoselecting = createMemo(() => false)
|
|
209
204
|
|
|
210
205
|
createEffect(() => {
|
|
211
206
|
if (!state.autoselect) return
|
|
@@ -326,7 +321,7 @@ export default function Layout(props: ParentProps) {
|
|
|
326
321
|
e.details.type === "permission.asked"
|
|
327
322
|
? language.t("notification.permission.description", { sessionTitle, projectName })
|
|
328
323
|
: language.t("notification.question.description", { sessionTitle, projectName })
|
|
329
|
-
const href = `/${base64Encode(directory)}
|
|
324
|
+
const href = `/${base64Encode(directory)}/${props.sessionID}`
|
|
330
325
|
|
|
331
326
|
const now = Date.now()
|
|
332
327
|
const lastAlerted = alertedAtBySession.get(sessionKey) ?? 0
|
|
@@ -427,34 +422,6 @@ export default function Layout(props: ParentProps) {
|
|
|
427
422
|
return projects.find((p) => p.worktree === root)
|
|
428
423
|
})
|
|
429
424
|
|
|
430
|
-
createEffect(
|
|
431
|
-
on(
|
|
432
|
-
() => ({ ready: pageReady(), layoutReady: layoutReady(), dir: params.dir, list: layout.projects.list() }),
|
|
433
|
-
(value) => {
|
|
434
|
-
if (!value.ready) return
|
|
435
|
-
if (!value.layoutReady) return
|
|
436
|
-
if (!state.autoselect) return
|
|
437
|
-
if (value.dir) return
|
|
438
|
-
|
|
439
|
-
const last = server.projects.last()
|
|
440
|
-
|
|
441
|
-
if (value.list.length === 0) {
|
|
442
|
-
if (!last) return
|
|
443
|
-
setState("autoselect", false)
|
|
444
|
-
openProject(last, false)
|
|
445
|
-
navigateToProject(last)
|
|
446
|
-
return
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
const next = value.list.find((project) => project.worktree === last) ?? value.list[0]
|
|
450
|
-
if (!next) return
|
|
451
|
-
setState("autoselect", false)
|
|
452
|
-
openProject(next.worktree, false)
|
|
453
|
-
navigateToProject(next.worktree)
|
|
454
|
-
},
|
|
455
|
-
),
|
|
456
|
-
)
|
|
457
|
-
|
|
458
425
|
const workspaceName = (directory: string, projectId?: string, branch?: string) => {
|
|
459
426
|
const key = workspaceKey(directory)
|
|
460
427
|
const direct = store.workspaceName[key] ?? store.workspaceName[directory]
|
|
@@ -794,9 +761,9 @@ export default function Layout(props: ParentProps) {
|
|
|
794
761
|
)
|
|
795
762
|
if (session.id === params.id) {
|
|
796
763
|
if (nextSession) {
|
|
797
|
-
navigate(`/${params.dir}
|
|
764
|
+
navigate(`/${params.dir}/${nextSession.id}`)
|
|
798
765
|
} else {
|
|
799
|
-
navigate(`/${params.dir}
|
|
766
|
+
navigate(`/${params.dir}`)
|
|
800
767
|
}
|
|
801
768
|
}
|
|
802
769
|
}
|
|
@@ -810,6 +777,15 @@ export default function Layout(props: ParentProps) {
|
|
|
810
777
|
keybind: "mod+b",
|
|
811
778
|
onSelect: () => layout.sidebar.toggle(),
|
|
812
779
|
},
|
|
780
|
+
{
|
|
781
|
+
id: "file.open",
|
|
782
|
+
title: language.t("command.file.open"),
|
|
783
|
+
description: params.dir ? language.t("palette.search.placeholder") : language.t("command.project.open"),
|
|
784
|
+
category: language.t("command.category.file"),
|
|
785
|
+
keybind: "mod+p",
|
|
786
|
+
slash: "open",
|
|
787
|
+
onSelect: openGlobalFilePicker,
|
|
788
|
+
},
|
|
813
789
|
{
|
|
814
790
|
id: "project.open",
|
|
815
791
|
title: language.t("command.project.open"),
|
|
@@ -1055,74 +1031,12 @@ export default function Layout(props: ParentProps) {
|
|
|
1055
1031
|
if (!directory) return
|
|
1056
1032
|
const root = projectRoot(directory)
|
|
1057
1033
|
server.projects.touch(root)
|
|
1058
|
-
|
|
1059
|
-
let dirs = project
|
|
1060
|
-
? effectiveWorkspaceOrder(root, [root, ...(project.sandboxes ?? [])], store.workspaceOrder[root])
|
|
1061
|
-
: [root]
|
|
1062
|
-
const canOpen = (value: string | undefined) => {
|
|
1063
|
-
if (!value) return false
|
|
1064
|
-
return dirs.some((item) => workspaceKey(item) === workspaceKey(value))
|
|
1065
|
-
}
|
|
1066
|
-
const refreshDirs = async (target?: string) => {
|
|
1067
|
-
if (!target || target === root || canOpen(target)) return canOpen(target)
|
|
1068
|
-
const listed = await globalSDK.client.worktree
|
|
1069
|
-
.list({ directory: root })
|
|
1070
|
-
.then((x) => x.data ?? [])
|
|
1071
|
-
.catch(() => [] as string[])
|
|
1072
|
-
dirs = effectiveWorkspaceOrder(root, [root, ...listed], store.workspaceOrder[root])
|
|
1073
|
-
return canOpen(target)
|
|
1074
|
-
}
|
|
1075
|
-
const openSession = async (target: { directory: string; id: string }) => {
|
|
1076
|
-
if (!canOpen(target.directory)) return false
|
|
1077
|
-
const resolved = await globalSDK.client.session
|
|
1078
|
-
.get({ sessionID: target.id })
|
|
1079
|
-
.then((x) => x.data)
|
|
1080
|
-
.catch(() => undefined)
|
|
1081
|
-
if (!resolved?.directory) return false
|
|
1082
|
-
if (!canOpen(resolved.directory)) return false
|
|
1083
|
-
setStore("lastProjectSession", root, { directory: resolved.directory, id: resolved.id, at: Date.now() })
|
|
1084
|
-
navigateWithSidebarReset(`/${base64Encode(resolved.directory)}/session/${resolved.id}`)
|
|
1085
|
-
return true
|
|
1086
|
-
}
|
|
1087
|
-
|
|
1088
|
-
const projectSession = store.lastProjectSession[root]
|
|
1089
|
-
if (projectSession?.id) {
|
|
1090
|
-
await refreshDirs(projectSession.directory)
|
|
1091
|
-
const opened = await openSession(projectSession)
|
|
1092
|
-
if (opened) return
|
|
1093
|
-
clearLastProjectSession(root)
|
|
1094
|
-
}
|
|
1095
|
-
|
|
1096
|
-
const latest = latestRootSession(
|
|
1097
|
-
dirs.map((item) => globalSync.child(item, { bootstrap: false })[0]),
|
|
1098
|
-
Date.now(),
|
|
1099
|
-
)
|
|
1100
|
-
if (latest && (await openSession(latest))) {
|
|
1101
|
-
return
|
|
1102
|
-
}
|
|
1103
|
-
|
|
1104
|
-
const fetched = latestRootSession(
|
|
1105
|
-
await Promise.all(
|
|
1106
|
-
dirs.map(async (item) => ({
|
|
1107
|
-
path: { directory: item },
|
|
1108
|
-
session: await globalSDK.client.session
|
|
1109
|
-
.list({ directory: item })
|
|
1110
|
-
.then((x) => x.data ?? [])
|
|
1111
|
-
.catch(() => []),
|
|
1112
|
-
})),
|
|
1113
|
-
),
|
|
1114
|
-
Date.now(),
|
|
1115
|
-
)
|
|
1116
|
-
if (fetched && (await openSession(fetched))) {
|
|
1117
|
-
return
|
|
1118
|
-
}
|
|
1119
|
-
|
|
1120
|
-
navigateWithSidebarReset(`/${base64Encode(root)}/session`)
|
|
1034
|
+
navigateWithSidebarReset(`/${base64Encode(root)}`)
|
|
1121
1035
|
}
|
|
1122
1036
|
|
|
1123
1037
|
function navigateToSession(session: Session | undefined) {
|
|
1124
1038
|
if (!session) return
|
|
1125
|
-
navigateWithSidebarReset(`/${base64Encode(session.directory)}
|
|
1039
|
+
navigateWithSidebarReset(`/${base64Encode(session.directory)}/${session.id}`)
|
|
1126
1040
|
}
|
|
1127
1041
|
|
|
1128
1042
|
function openProject(directory: string, navigate = true) {
|
|
@@ -1187,7 +1101,7 @@ export default function Layout(props: ParentProps) {
|
|
|
1187
1101
|
return
|
|
1188
1102
|
}
|
|
1189
1103
|
|
|
1190
|
-
navigateWithSidebarReset(`/${base64Encode(next.worktree)}
|
|
1104
|
+
navigateWithSidebarReset(`/${base64Encode(next.worktree)}`)
|
|
1191
1105
|
layout.projects.close(directory)
|
|
1192
1106
|
queueMicrotask(() => {
|
|
1193
1107
|
void navigateToProject(next.worktree)
|
|
@@ -1232,6 +1146,19 @@ export default function Layout(props: ParentProps) {
|
|
|
1232
1146
|
}
|
|
1233
1147
|
}
|
|
1234
1148
|
|
|
1149
|
+
function openGlobalFilePicker() {
|
|
1150
|
+
if (!params.dir) {
|
|
1151
|
+
dialog.show(() => <DialogCommandPalette />)
|
|
1152
|
+
return
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
dialog.show(() => (
|
|
1156
|
+
<FileProvider>
|
|
1157
|
+
<DialogSelectFile />
|
|
1158
|
+
</FileProvider>
|
|
1159
|
+
))
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1235
1162
|
const deleteWorkspace = async (root: string, directory: string, leaveDeletedWorkspace = false) => {
|
|
1236
1163
|
if (directory === root) return
|
|
1237
1164
|
|
|
@@ -1240,7 +1167,7 @@ export default function Layout(props: ParentProps) {
|
|
|
1240
1167
|
const deletedKey = workspaceKey(directory)
|
|
1241
1168
|
const shouldLeave = leaveDeletedWorkspace || (!!params.dir && currentKey === deletedKey)
|
|
1242
1169
|
if (!leaveDeletedWorkspace && shouldLeave) {
|
|
1243
|
-
navigateWithSidebarReset(`/${base64Encode(root)}
|
|
1170
|
+
navigateWithSidebarReset(`/${base64Encode(root)}`)
|
|
1244
1171
|
}
|
|
1245
1172
|
|
|
1246
1173
|
setBusy(directory, true)
|
|
@@ -1288,7 +1215,7 @@ export default function Layout(props: ParentProps) {
|
|
|
1288
1215
|
const valid = dirs.some((item) => workspaceKey(item) === nextKey)
|
|
1289
1216
|
|
|
1290
1217
|
if (params.dir && projectRoot(nextCurrent) === root && !valid) {
|
|
1291
|
-
navigateWithSidebarReset(`/${base64Encode(root)}
|
|
1218
|
+
navigateWithSidebarReset(`/${base64Encode(root)}`)
|
|
1292
1219
|
}
|
|
1293
1220
|
}
|
|
1294
1221
|
|
|
@@ -1357,7 +1284,7 @@ export default function Layout(props: ParentProps) {
|
|
|
1357
1284
|
{
|
|
1358
1285
|
label: language.t("command.session.new"),
|
|
1359
1286
|
onClick: () => {
|
|
1360
|
-
const href = `/${base64Encode(directory)}
|
|
1287
|
+
const href = `/${base64Encode(directory)}`
|
|
1361
1288
|
navigate(href)
|
|
1362
1289
|
layout.mobileSidebar.hide()
|
|
1363
1290
|
},
|
|
@@ -1393,7 +1320,7 @@ export default function Layout(props: ParentProps) {
|
|
|
1393
1320
|
const handleDelete = () => {
|
|
1394
1321
|
const leaveDeletedWorkspace = !!params.dir && workspaceKey(currentDir()) === workspaceKey(props.directory)
|
|
1395
1322
|
if (leaveDeletedWorkspace) {
|
|
1396
|
-
navigateWithSidebarReset(`/${base64Encode(props.root)}
|
|
1323
|
+
navigateWithSidebarReset(`/${base64Encode(props.root)}`)
|
|
1397
1324
|
}
|
|
1398
1325
|
dialog.close()
|
|
1399
1326
|
void deleteWorkspace(props.root, props.directory, leaveDeletedWorkspace)
|
|
@@ -1544,6 +1471,10 @@ export default function Layout(props: ParentProps) {
|
|
|
1544
1471
|
)
|
|
1545
1472
|
|
|
1546
1473
|
createEffect(() => {
|
|
1474
|
+
if (!hasDirectoryRoute()) {
|
|
1475
|
+
document.documentElement.style.setProperty("--dialog-left-margin", "0px")
|
|
1476
|
+
return
|
|
1477
|
+
}
|
|
1547
1478
|
const sidebarWidth = layout.sidebar.opened() ? layout.sidebar.width() : 48
|
|
1548
1479
|
document.documentElement.style.setProperty("--dialog-left-margin", `${sidebarWidth}px`)
|
|
1549
1480
|
})
|
|
@@ -1691,7 +1622,7 @@ export default function Layout(props: ParentProps) {
|
|
|
1691
1622
|
})
|
|
1692
1623
|
|
|
1693
1624
|
globalSync.child(created.directory)
|
|
1694
|
-
navigateWithSidebarReset(`/${base64Encode(created.directory)}
|
|
1625
|
+
navigateWithSidebarReset(`/${base64Encode(created.directory)}`)
|
|
1695
1626
|
}
|
|
1696
1627
|
|
|
1697
1628
|
const workspaceSidebarCtx: WorkspaceSidebarContext = {
|
|
@@ -1884,7 +1815,7 @@ export default function Layout(props: ParentProps) {
|
|
|
1884
1815
|
size="large"
|
|
1885
1816
|
icon="plus-small"
|
|
1886
1817
|
class="w-full"
|
|
1887
|
-
onClick={() => navigateWithSidebarReset(`/${base64Encode(p().worktree)}
|
|
1818
|
+
onClick={() => navigateWithSidebarReset(`/${base64Encode(p().worktree)}`)}
|
|
1888
1819
|
>
|
|
1889
1820
|
{language.t("command.session.new")}
|
|
1890
1821
|
</Button>
|
|
@@ -1986,136 +1917,143 @@ export default function Layout(props: ParentProps) {
|
|
|
1986
1917
|
|
|
1987
1918
|
return (
|
|
1988
1919
|
<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">
|
|
1989
|
-
<
|
|
1920
|
+
<Show when={hasDirectoryRoute()}>
|
|
1921
|
+
<Titlebar />
|
|
1922
|
+
</Show>
|
|
1990
1923
|
<div class="flex-1 min-h-0 flex">
|
|
1991
|
-
<
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
{(
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
{(worktree) => (
|
|
2050
|
-
<div class="absolute inset-y-0 left-16 z-50 flex" onMouseEnter={aim.reset}>
|
|
2051
|
-
<SidebarPanel project={hoverProjectData()} />
|
|
1924
|
+
<Show when={hasDirectoryRoute()}>
|
|
1925
|
+
<>
|
|
1926
|
+
<nav
|
|
1927
|
+
aria-label={language.t("sidebar.nav.projectsAndSessions")}
|
|
1928
|
+
data-component="sidebar-nav-desktop"
|
|
1929
|
+
classList={{
|
|
1930
|
+
"hidden xl:block": true,
|
|
1931
|
+
"relative shrink-0": true,
|
|
1932
|
+
}}
|
|
1933
|
+
style={{ width: layout.sidebar.opened() ? `${Math.max(layout.sidebar.width(), 244)}px` : "64px" }}
|
|
1934
|
+
ref={(el) => {
|
|
1935
|
+
setState("nav", el)
|
|
1936
|
+
}}
|
|
1937
|
+
onMouseEnter={() => {
|
|
1938
|
+
if (navLeave.current === undefined) return
|
|
1939
|
+
clearTimeout(navLeave.current)
|
|
1940
|
+
navLeave.current = undefined
|
|
1941
|
+
}}
|
|
1942
|
+
onMouseLeave={() => {
|
|
1943
|
+
aim.reset()
|
|
1944
|
+
if (!sidebarHovering()) return
|
|
1945
|
+
|
|
1946
|
+
if (navLeave.current !== undefined) clearTimeout(navLeave.current)
|
|
1947
|
+
navLeave.current = window.setTimeout(() => {
|
|
1948
|
+
navLeave.current = undefined
|
|
1949
|
+
setHoverProject(undefined)
|
|
1950
|
+
setState("hoverSession", undefined)
|
|
1951
|
+
}, 300)
|
|
1952
|
+
}}
|
|
1953
|
+
>
|
|
1954
|
+
<div class="@container w-full h-full contain-strict">
|
|
1955
|
+
<SidebarContent
|
|
1956
|
+
opened={() => layout.sidebar.opened()}
|
|
1957
|
+
aimMove={aim.move}
|
|
1958
|
+
projects={() => layout.projects.list()}
|
|
1959
|
+
renderProject={(project) => (
|
|
1960
|
+
<SortableProject ctx={projectSidebarCtx} project={project} sortNow={sortNow} />
|
|
1961
|
+
)}
|
|
1962
|
+
handleDragStart={handleDragStart}
|
|
1963
|
+
handleDragEnd={handleDragEnd}
|
|
1964
|
+
handleDragOver={handleDragOver}
|
|
1965
|
+
openProjectLabel={language.t("command.project.open")}
|
|
1966
|
+
openProjectKeybind={() => command.keybind("project.open")}
|
|
1967
|
+
onOpenProject={chooseProject}
|
|
1968
|
+
renderProjectOverlay={() => (
|
|
1969
|
+
<ProjectDragOverlay projects={() => layout.projects.list()} activeProject={() => store.activeProject} />
|
|
1970
|
+
)}
|
|
1971
|
+
settingsLabel={() => language.t("sidebar.settings")}
|
|
1972
|
+
settingsKeybind={() => command.keybind("settings.open")}
|
|
1973
|
+
onOpenSettings={openSettings}
|
|
1974
|
+
helpLabel={() => language.t("sidebar.help")}
|
|
1975
|
+
onOpenHelp={() => platform.openLink("https://github.com/isomoes/ikanban/issues")}
|
|
1976
|
+
renderPanel={() => (
|
|
1977
|
+
<Show when={currentProject()} keyed>
|
|
1978
|
+
{(project) => <SidebarPanel project={project} />}
|
|
1979
|
+
</Show>
|
|
1980
|
+
)}
|
|
1981
|
+
/>
|
|
2052
1982
|
</div>
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
1983
|
+
<Show when={!layout.sidebar.opened() ? hoverProjectData()?.worktree : undefined} keyed>
|
|
1984
|
+
{(worktree) => (
|
|
1985
|
+
<div class="absolute inset-y-0 left-16 z-50 flex" onMouseEnter={aim.reset}>
|
|
1986
|
+
<SidebarPanel project={hoverProjectData()} />
|
|
1987
|
+
</div>
|
|
1988
|
+
)}
|
|
1989
|
+
</Show>
|
|
1990
|
+
<Show when={layout.sidebar.opened()}>
|
|
1991
|
+
<ResizeHandle
|
|
1992
|
+
direction="horizontal"
|
|
1993
|
+
size={layout.sidebar.width()}
|
|
1994
|
+
min={244}
|
|
1995
|
+
max={typeof window === "undefined" ? 1000 : window.innerWidth * 0.3 + 64}
|
|
1996
|
+
collapseThreshold={244}
|
|
1997
|
+
onResize={layout.sidebar.resize}
|
|
1998
|
+
onCollapse={layout.sidebar.close}
|
|
1999
|
+
/>
|
|
2000
|
+
</Show>
|
|
2001
|
+
</nav>
|
|
2002
|
+
<div class="xl:hidden">
|
|
2003
|
+
<div
|
|
2004
|
+
classList={{
|
|
2005
|
+
"fixed inset-x-0 top-10 bottom-0 z-40 transition-opacity duration-200": true,
|
|
2006
|
+
"opacity-100 pointer-events-auto": layout.mobileSidebar.opened(),
|
|
2007
|
+
"opacity-0 pointer-events-none": !layout.mobileSidebar.opened(),
|
|
2008
|
+
}}
|
|
2009
|
+
onClick={(e) => {
|
|
2010
|
+
if (e.target === e.currentTarget) layout.mobileSidebar.hide()
|
|
2011
|
+
}}
|
|
2012
|
+
/>
|
|
2013
|
+
<nav
|
|
2014
|
+
aria-label={language.t("sidebar.nav.projectsAndSessions")}
|
|
2015
|
+
data-component="sidebar-nav-mobile"
|
|
2016
|
+
classList={{
|
|
2017
|
+
"@container fixed top-10 bottom-0 left-0 z-50 w-72 bg-background-base transition-transform duration-200 ease-out": true,
|
|
2018
|
+
"translate-x-0": layout.mobileSidebar.opened(),
|
|
2019
|
+
"-translate-x-full": !layout.mobileSidebar.opened(),
|
|
2020
|
+
}}
|
|
2021
|
+
onClick={(e) => e.stopPropagation()}
|
|
2022
|
+
>
|
|
2023
|
+
<SidebarContent
|
|
2024
|
+
mobile
|
|
2025
|
+
opened={() => layout.sidebar.opened()}
|
|
2026
|
+
aimMove={aim.move}
|
|
2027
|
+
projects={() => layout.projects.list()}
|
|
2028
|
+
renderProject={(project) => (
|
|
2029
|
+
<SortableProject ctx={projectSidebarCtx} project={project} sortNow={sortNow} mobile />
|
|
2030
|
+
)}
|
|
2031
|
+
handleDragStart={handleDragStart}
|
|
2032
|
+
handleDragEnd={handleDragEnd}
|
|
2033
|
+
handleDragOver={handleDragOver}
|
|
2034
|
+
openProjectLabel={language.t("command.project.open")}
|
|
2035
|
+
openProjectKeybind={() => command.keybind("project.open")}
|
|
2036
|
+
onOpenProject={chooseProject}
|
|
2037
|
+
renderProjectOverlay={() => (
|
|
2038
|
+
<ProjectDragOverlay projects={() => layout.projects.list()} activeProject={() => store.activeProject} />
|
|
2039
|
+
)}
|
|
2040
|
+
settingsLabel={() => language.t("sidebar.settings")}
|
|
2041
|
+
settingsKeybind={() => command.keybind("settings.open")}
|
|
2042
|
+
onOpenSettings={openSettings}
|
|
2043
|
+
helpLabel={() => language.t("sidebar.help")}
|
|
2044
|
+
onOpenHelp={() => platform.openLink("https://github.com/isomoes/ikanban/issues")}
|
|
2045
|
+
renderPanel={() => <SidebarPanel project={currentProject()} mobile />}
|
|
2046
|
+
/>
|
|
2047
|
+
</nav>
|
|
2048
|
+
</div>
|
|
2049
|
+
</>
|
|
2050
|
+
</Show>
|
|
2114
2051
|
|
|
2115
2052
|
<main
|
|
2116
2053
|
classList={{
|
|
2117
2054
|
"size-full overflow-x-hidden flex flex-col items-start contain-strict border-t border-border-weak-base": true,
|
|
2118
|
-
"xl:border-l xl:rounded-tl-[12px]": !layout.sidebar.opened(),
|
|
2055
|
+
"xl:border-l xl:rounded-tl-[12px]": hasDirectoryRoute() && !layout.sidebar.opened(),
|
|
2056
|
+
"border-t-0": !hasDirectoryRoute(),
|
|
2119
2057
|
}}
|
|
2120
2058
|
>
|
|
2121
2059
|
<Show when={!autoselecting()} fallback={<div class="size-full" />}>
|
|
@@ -190,6 +190,7 @@ export function MessageTimeline(props: {
|
|
|
190
190
|
setScrollRef: (el: HTMLDivElement | undefined) => void
|
|
191
191
|
onScheduleScrollState: (el: HTMLDivElement) => void
|
|
192
192
|
onAutoScrollHandleScroll: () => void
|
|
193
|
+
isUserScrolled: () => boolean
|
|
193
194
|
onMarkScrollGesture: (target?: EventTarget | null) => void
|
|
194
195
|
hasScrollGesture: () => boolean
|
|
195
196
|
isDesktop: boolean
|
|
@@ -345,14 +346,14 @@ export function MessageTimeline(props: {
|
|
|
345
346
|
const navigateAfterSessionRemoval = (sessionID: string, parentID?: string, nextSessionID?: string) => {
|
|
346
347
|
if (params.id !== sessionID) return
|
|
347
348
|
if (parentID) {
|
|
348
|
-
navigate(`/${params.dir}
|
|
349
|
+
navigate(`/${params.dir}/${parentID}`)
|
|
349
350
|
return
|
|
350
351
|
}
|
|
351
352
|
if (nextSessionID) {
|
|
352
|
-
navigate(`/${params.dir}
|
|
353
|
+
navigate(`/${params.dir}/${nextSessionID}`)
|
|
353
354
|
return
|
|
354
355
|
}
|
|
355
|
-
navigate(`/${params.dir}
|
|
356
|
+
navigate(`/${params.dir}`)
|
|
356
357
|
}
|
|
357
358
|
|
|
358
359
|
const archiveSession = async (sessionID: string) => {
|
|
@@ -445,7 +446,7 @@ export function MessageTimeline(props: {
|
|
|
445
446
|
const navigateParent = () => {
|
|
446
447
|
const id = parentID()
|
|
447
448
|
if (!id) return
|
|
448
|
-
navigate(`/${params.dir}
|
|
449
|
+
navigate(`/${params.dir}/${id}`)
|
|
449
450
|
}
|
|
450
451
|
|
|
451
452
|
function DialogDeleteSession(props: { sessionID: string }) {
|
|
@@ -538,8 +539,8 @@ export function MessageTimeline(props: {
|
|
|
538
539
|
onScroll={(e) => {
|
|
539
540
|
props.onScheduleScrollState(e.currentTarget)
|
|
540
541
|
props.onTurnBackfillScroll()
|
|
541
|
-
if (!props.hasScrollGesture()) return
|
|
542
542
|
props.onAutoScrollHandleScroll()
|
|
543
|
+
if (!props.hasScrollGesture() && !props.isUserScrolled()) return
|
|
543
544
|
props.onMarkScrollGesture(e.currentTarget)
|
|
544
545
|
if (props.isDesktop) props.onScrollSpyScroll()
|
|
545
546
|
}}
|
|
@@ -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
|
@@ -1276,6 +1276,7 @@ export default function Page() {
|
|
|
1276
1276
|
setScrollRef={setScrollRef}
|
|
1277
1277
|
onScheduleScrollState={scheduleScrollState}
|
|
1278
1278
|
onAutoScrollHandleScroll={autoScroll.handleScroll}
|
|
1279
|
+
isUserScrolled={autoScroll.userScrolled}
|
|
1279
1280
|
onMarkScrollGesture={markScrollGesture}
|
|
1280
1281
|
hasScrollGesture={hasScrollGesture}
|
|
1281
1282
|
isDesktop={isDesktop()}
|
|
@@ -1318,7 +1319,7 @@ export default function Page() {
|
|
|
1318
1319
|
if (!target) return
|
|
1319
1320
|
if (target === sdk.directory) return
|
|
1320
1321
|
layout.projects.open(target)
|
|
1321
|
-
navigate(`/${base64Encode(target)}
|
|
1322
|
+
navigate(`/${base64Encode(target)}`)
|
|
1322
1323
|
}}
|
|
1323
1324
|
/>
|
|
1324
1325
|
</Match>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{u as D,a as C,b as S,c as L,d as P,e as z,f as M,g,i as l,h as a,L as A,j as B,k as E,m as w,D as F,B as u,M as y,F as I,l as R,I as G,S as H,n as N,o as T,t as o}from"./index-BlcL7wgr.js";var q=o("<div>"),J=o('<div class="mt-20 w-full flex flex-col gap-4"><div class="flex gap-2 items-center justify-between pl-3"><div class="text-14-medium text-text-strong"></div></div><ul class="flex flex-col gap-2">'),K=o('<div class="mt-30 mx-auto flex flex-col items-center gap-3"><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">'),O=o('<div class="mx-auto mt-55 w-full md:w-auto px-4">'),Q=o('<div class="text-14-regular text-text-weak">');function V(){const m=D(),$=C(),p=S(),x=L(),_=P(),n=z(),s=M(),b=g(()=>m.data.path.home),k=g(()=>m.data.project.slice().sort((t,e)=>(e.time.updated??e.time.created)-(t.time.updated??t.time.created)).slice(0,5)),j=g(()=>{const t=n.healthy();return t===!0?"bg-icon-success-base":t===!1?"bg-icon-critical-base":"bg-border-weak-base"});function d(t){$.projects.open(t),n.projects.touch(t),_(`/${N(t)}`)}async function h(){function t(e){if(Array.isArray(e))for(const r of e)d(r);else e&&d(e)}if(p.openDirectoryPickerDialog&&n.isLocal()){const e=await p.openDirectoryPickerDialog?.({title:s.t("command.project.open"),multiple:!0});t(e)}else x.show(()=>a(T,{multiple:!0,onSelect:t}),()=>t(null))}return(()=>{var t=O();return l(t,a(A,{class:"md:w-xl opacity-12"}),null),l(t,a(u,{size:"large",variant:"ghost",class:"mt-4 mx-auto text-14-regular text-text-weak",onClick:()=>x.show(()=>a(F,{})),get children(){return[(()=>{var e=q();return B(r=>E(e,{"size-2 rounded-full":!0,[j()]:!0},r)),e})(),w(()=>n.name)]}}),null),l(t,a(H,{get children(){return[a(y,{get when(){return m.data.project.length>0},get children(){var e=J(),r=e.firstChild,i=r.firstChild,f=r.nextSibling;return l(i,()=>s.t("home.recentProjects")),l(r,a(u,{icon:"folder-add-left",size:"normal",class:"pl-2 pr-3",onClick:h,get children(){return s.t("command.project.open")}}),null),l(f,a(I,{get each(){return k()},children:c=>a(u,{size:"large",variant:"ghost",class:"text-14-mono text-left justify-between px-3",onClick:()=>d(c.worktree),get children(){return[w(()=>c.worktree.replace(b(),"~")),(()=>{var v=Q();return l(v,()=>R.fromMillis(c.time.updated??c.time.created).toRelative()),v})()]}})})),e}}),a(y,{when:!0,get children(){var e=K(),r=e.firstChild,i=r.firstChild,f=i.nextSibling;return l(e,a(G,{name:"folder-add-left",size:"large"}),r),l(i,()=>s.t("home.empty.title")),l(f,()=>s.t("home.empty.description")),l(e,a(u,{class:"px-3 mt-1",onClick:h,get children(){return s.t("command.project.open")}}),null),e}})]}}),null),t})()}export{V as default};
|