mirror of
https://github.com/anomalyco/opencode.git
synced 2026-02-01 22:48:16 +00:00
fix(app): new layout issues
This commit is contained in:
@@ -47,13 +47,34 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext(
|
||||
const globalSdk = useGlobalSDK()
|
||||
const globalSync = useGlobalSync()
|
||||
const server = useServer()
|
||||
|
||||
const isRecord = (value: unknown): value is Record<string, unknown> =>
|
||||
typeof value === "object" && value !== null && !Array.isArray(value)
|
||||
|
||||
const migrate = (value: unknown) => {
|
||||
if (!isRecord(value)) return value
|
||||
const sidebar = value.sidebar
|
||||
if (!isRecord(sidebar)) return value
|
||||
if (typeof sidebar.workspaces !== "boolean") return value
|
||||
return {
|
||||
...value,
|
||||
sidebar: {
|
||||
...sidebar,
|
||||
workspaces: {},
|
||||
workspacesDefault: sidebar.workspaces,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const target = Persist.global("layout", ["layout.v6"])
|
||||
const [store, setStore, _, ready] = persisted(
|
||||
Persist.global("layout", ["layout.v6"]),
|
||||
{ ...target, migrate },
|
||||
createStore({
|
||||
sidebar: {
|
||||
opened: false,
|
||||
width: 280,
|
||||
workspaces: false,
|
||||
workspaces: {} as Record<string, boolean>,
|
||||
workspacesDefault: false,
|
||||
},
|
||||
terminal: {
|
||||
height: 280,
|
||||
@@ -305,12 +326,15 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext(
|
||||
resize(width: number) {
|
||||
setStore("sidebar", "width", width)
|
||||
},
|
||||
workspaces: createMemo(() => store.sidebar.workspaces ?? false),
|
||||
setWorkspaces(value: boolean) {
|
||||
setStore("sidebar", "workspaces", value)
|
||||
workspaces(directory: string) {
|
||||
return createMemo(() => store.sidebar.workspaces[directory] ?? store.sidebar.workspacesDefault ?? false)
|
||||
},
|
||||
toggleWorkspaces() {
|
||||
setStore("sidebar", "workspaces", (x) => !x)
|
||||
setWorkspaces(directory: string, value: boolean) {
|
||||
setStore("sidebar", "workspaces", directory, value)
|
||||
},
|
||||
toggleWorkspaces(directory: string) {
|
||||
const current = store.sidebar.workspaces[directory] ?? store.sidebar.workspacesDefault ?? false
|
||||
setStore("sidebar", "workspaces", directory, !current)
|
||||
},
|
||||
},
|
||||
terminal: {
|
||||
|
||||
@@ -271,6 +271,12 @@ export default function Layout(props: ParentProps) {
|
||||
return layout.projects.list().find((p) => p.worktree === directory || p.sandboxes?.includes(directory))
|
||||
})
|
||||
|
||||
const workspaceSetting = createMemo(() => {
|
||||
const project = currentProject()
|
||||
if (!project) return false
|
||||
return layout.sidebar.workspaces(project.worktree)()
|
||||
})
|
||||
|
||||
createEffect(() => {
|
||||
const project = currentProject()
|
||||
if (!project) return
|
||||
@@ -306,7 +312,16 @@ export default function Layout(props: ParentProps) {
|
||||
return sessions.filter((s) => !s.parentID)
|
||||
}
|
||||
|
||||
const currentSessions = createMemo(() => projectSessions(currentProject()))
|
||||
const currentSessions = createMemo(() => {
|
||||
const project = currentProject()
|
||||
if (!project) return [] as Session[]
|
||||
if (workspaceSetting()) return projectSessions(project)
|
||||
const [projectStore] = globalSync.child(project.worktree)
|
||||
return projectStore.session
|
||||
.filter((session) => session.directory === projectStore.path.directory)
|
||||
.filter((session) => !session.parentID)
|
||||
.toSorted(sortSessions)
|
||||
})
|
||||
|
||||
type PrefetchQueue = {
|
||||
inflight: Set<string>
|
||||
@@ -729,6 +744,21 @@ export default function Layout(props: ParentProps) {
|
||||
requestAnimationFrame(() => scrollToSession(id))
|
||||
})
|
||||
|
||||
createEffect(() => {
|
||||
const project = currentProject()
|
||||
if (!project) return
|
||||
|
||||
if (workspaceSetting()) {
|
||||
const dirs = [project.worktree, ...(project.sandboxes ?? [])]
|
||||
for (const directory of dirs) {
|
||||
globalSync.project.loadSessions(directory)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
globalSync.project.loadSessions(project.worktree)
|
||||
})
|
||||
|
||||
createEffect(() => {
|
||||
if (isLargeViewport()) {
|
||||
const sidebarWidth = layout.sidebar.opened() ? layout.sidebar.width() : 64
|
||||
@@ -943,6 +973,7 @@ export default function Layout(props: ParentProps) {
|
||||
})
|
||||
|
||||
const workspaces = createMemo(() => workspaceIds(props.project).slice(0, 2))
|
||||
const workspaceEnabled = createMemo(() => layout.sidebar.workspaces(props.project.worktree)())
|
||||
const label = (directory: string) => {
|
||||
const [data] = globalSync.child(directory)
|
||||
const kind = directory === props.project.worktree ? "local" : "sandbox"
|
||||
@@ -959,6 +990,15 @@ export default function Layout(props: ParentProps) {
|
||||
.slice(0, 2)
|
||||
}
|
||||
|
||||
const projectSessions = () => {
|
||||
const [data] = globalSync.child(props.project.worktree)
|
||||
return data.session
|
||||
.filter((session) => session.directory === data.path.directory)
|
||||
.filter((session) => !session.parentID)
|
||||
.toSorted(sortSessions)
|
||||
.slice(0, 2)
|
||||
}
|
||||
|
||||
const trigger = (
|
||||
<button
|
||||
type="button"
|
||||
@@ -980,23 +1020,39 @@ export default function Layout(props: ParentProps) {
|
||||
<div class="-m-3 flex flex-col w-72">
|
||||
<div class="px-3 py-2 text-12-medium text-text-strong">Recent sessions</div>
|
||||
<div class="px-2 pb-2 flex flex-col gap-2">
|
||||
<For each={workspaces()}>
|
||||
{(directory) => (
|
||||
<div class="flex flex-col gap-1">
|
||||
<div class="px-2 py-0.5 flex items-center gap-1 min-w-0">
|
||||
<div class="shrink-0 size-6 flex items-center justify-center">
|
||||
<Icon name="branch" size="small" class="text-icon-base" />
|
||||
<Show
|
||||
when={workspaceEnabled()}
|
||||
fallback={
|
||||
<For each={projectSessions()}>
|
||||
{(session) => (
|
||||
<SessionItem
|
||||
session={session}
|
||||
slug={base64Encode(props.project.worktree)}
|
||||
dense
|
||||
mobile={props.mobile}
|
||||
/>
|
||||
)}
|
||||
</For>
|
||||
}
|
||||
>
|
||||
<For each={workspaces()}>
|
||||
{(directory) => (
|
||||
<div class="flex flex-col gap-1">
|
||||
<div class="px-2 py-0.5 flex items-center gap-1 min-w-0">
|
||||
<div class="shrink-0 size-6 flex items-center justify-center">
|
||||
<Icon name="branch" size="small" class="text-icon-base" />
|
||||
</div>
|
||||
<span class="truncate text-14-medium text-text-strong">{label(directory)}</span>
|
||||
</div>
|
||||
<span class="truncate text-14-medium text-text-strong">{label(directory)}</span>
|
||||
<For each={sessions(directory)}>
|
||||
{(session) => (
|
||||
<SessionItem session={session} slug={base64Encode(directory)} dense mobile={props.mobile} />
|
||||
)}
|
||||
</For>
|
||||
</div>
|
||||
<For each={sessions(directory)}>
|
||||
{(session) => (
|
||||
<SessionItem session={session} slug={base64Encode(directory)} dense mobile={props.mobile} />
|
||||
)}
|
||||
</For>
|
||||
</div>
|
||||
)}
|
||||
</For>
|
||||
)}
|
||||
</For>
|
||||
</Show>
|
||||
</div>
|
||||
<div class="px-2 py-2 border-t border-border-weak-base">
|
||||
<Button
|
||||
@@ -1068,7 +1124,7 @@ export default function Layout(props: ParentProps) {
|
||||
return `${kind} : ${name}`
|
||||
})
|
||||
const open = createMemo(() => store.workspaceExpanded[props.directory] ?? true)
|
||||
const hasMore = createMemo(() => local() && workspaceStore.session.length >= workspaceStore.limit)
|
||||
const hasMore = createMemo(() => local() && workspaceStore.sessionTotal > workspaceStore.session.length)
|
||||
const loadMore = async () => {
|
||||
if (!local()) return
|
||||
setWorkspaceStore("limit", (limit) => limit + 5)
|
||||
@@ -1157,7 +1213,7 @@ export default function Layout(props: ParentProps) {
|
||||
.filter((session) => !session.parentID)
|
||||
.toSorted(sortSessions),
|
||||
)
|
||||
const hasMore = createMemo(() => workspaceStore.session.length >= workspaceStore.limit)
|
||||
const hasMore = createMemo(() => workspaceStore.sessionTotal > workspaceStore.session.length)
|
||||
const loadMore = async () => {
|
||||
setWorkspaceStore("limit", (limit) => limit + 5)
|
||||
await globalSync.project.loadSessions(props.project.worktree)
|
||||
@@ -1324,9 +1380,9 @@ export default function Layout(props: ParentProps) {
|
||||
<DropdownMenu.ItemLabel>Close project</DropdownMenu.ItemLabel>
|
||||
</DropdownMenu.Item>
|
||||
<DropdownMenu.Separator />
|
||||
<DropdownMenu.Item onSelect={() => layout.sidebar.toggleWorkspaces()}>
|
||||
<DropdownMenu.Item onSelect={() => layout.sidebar.toggleWorkspaces(p().worktree)}>
|
||||
<DropdownMenu.ItemLabel>
|
||||
{layout.sidebar.workspaces() ? "Disable workspaces" : "Enable workspaces"}
|
||||
{layout.sidebar.workspaces(p().worktree)() ? "Disable workspaces" : "Enable workspaces"}
|
||||
</DropdownMenu.ItemLabel>
|
||||
</DropdownMenu.Item>
|
||||
</DropdownMenu.Content>
|
||||
@@ -1336,7 +1392,7 @@ export default function Layout(props: ParentProps) {
|
||||
</div>
|
||||
|
||||
<Show
|
||||
when={layout.sidebar.workspaces()}
|
||||
when={layout.sidebar.workspaces(p().worktree)()}
|
||||
fallback={
|
||||
<>
|
||||
<div class="py-4 px-3">
|
||||
|
||||
@@ -293,6 +293,11 @@ pub fn run() {
|
||||
"#
|
||||
));
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
let window_builder = window_builder
|
||||
.title_bar_style(tauri::TitleBarStyle::Overlay)
|
||||
.hidden_title(true);
|
||||
|
||||
let _window = window_builder.build().expect("Failed to create window");
|
||||
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
@@ -319,9 +319,6 @@ render(() => {
|
||||
return (
|
||||
<PlatformProvider value={platform}>
|
||||
<AppBaseProviders>
|
||||
{ostype() === "macos" && (
|
||||
<div class="mx-px bg-background-base border-b border-border-weak-base h-8" data-tauri-drag-region />
|
||||
)}
|
||||
<ServerGate>
|
||||
{(data) => {
|
||||
setServerPassword(data().password)
|
||||
|
||||
Reference in New Issue
Block a user