Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions packages/app/src/components/dialog-delete-session.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { Dialog } from "@opencode-ai/ui/dialog"
import { Button } from "@opencode-ai/ui/button"
import { useDialog } from "@opencode-ai/ui/context/dialog"
import { createMemo, createSignal } from "solid-js"
import { useLanguage } from "@/context/language"
import { useSync } from "@/context/sync"
import { sessionTitle } from "@/utils/session-title"

export function DialogDeleteSession(props: {
sessionID: string
onConfirm: () => Promise<void> | void
}) {
const sync = useSync()
const language = useLanguage()
const dialog = useDialog()
const [deleting, setDeleting] = createSignal(false)

const name = createMemo(
() => sessionTitle(sync.session.get(props.sessionID)?.title) ?? language.t("command.session.new"),
)

const handleDelete = async () => {
if (deleting()) return
setDeleting(true)
try {
await props.onConfirm()
dialog.close()
} finally {
setDeleting(false)
}
}
Comment thread
Astro-Han marked this conversation as resolved.

return (
<Dialog title={language.t("session.delete.title")} fit>
<div class="flex flex-col gap-4 pl-6 pr-2.5 pb-3">
<div class="flex flex-col gap-1">
<span class="text-13-regular text-text-strong">
{language.t("session.delete.confirm", { name: name() })}
</span>
</div>
<div class="flex justify-end gap-2">
<Button variant="ghost" size="large" onClick={() => dialog.close()} disabled={deleting()}>
{language.t("common.cancel")}
</Button>
<Button variant="primary" size="large" onClick={handleDelete} disabled={deleting()}>
{language.t("common.delete")}
</Button>
</div>
</div>
</Dialog>
)
}
12 changes: 6 additions & 6 deletions packages/app/src/components/dialog-select-model.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ const ModelList: Component<{
<div class="w-full min-w-0 flex items-center gap-x-2 text-13-regular text-left">
<span class="min-w-0 truncate">{i.name}</span>
<For each={visible}>
{(tag) => <Tag class="shrink-0 rounded-full!">{language.t(`model.tag.${tag}`)}</Tag>}
{(tag) => <Tag class="shrink-0">{language.t(`model.tag.${tag}`)}</Tag>}
</For>
</div>
)
Expand Down Expand Up @@ -166,8 +166,8 @@ export function ModelSelectorPopover(props: {
</Kobalte.Trigger>
<Kobalte.Portal>
<Kobalte.Content
class="w-72 h-80 flex flex-col p-2 border border-border-base bg-surface-raised-stronger-non-alpha shadow-md z-50 outline-none overflow-hidden"
style={{ "border-radius": "16px" }}
class="w-72 h-80 flex flex-col bg-surface-raised-stronger-non-alpha z-50 outline-none overflow-hidden"
style={{ "border-radius": "14px", "box-shadow": "var(--shadow-floating)" }}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
onEscapeKeyDown={(event) => {
close("escape")
event.preventDefault()
Expand Down Expand Up @@ -196,9 +196,9 @@ export function ModelSelectorPopover(props: {
<div class="flex items-center gap-1">
<Tooltip placement="top" value={language.t("command.provider.connect")}>
<IconButton
icon="plus-small"
icon="plus"
variant="ghost"
iconSize="normal"
iconSize="small"
class="size-6"
aria-label={language.t("command.provider.connect")}
onClick={handleConnectProvider}
Expand All @@ -208,7 +208,7 @@ export function ModelSelectorPopover(props: {
<IconButton
icon="sliders"
variant="ghost"
iconSize="normal"
iconSize="small"
class="size-6"
aria-label={language.t("dialog.model.manage")}
onClick={handleManage}
Expand Down
24 changes: 13 additions & 11 deletions packages/app/src/components/prompt-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { Tooltip, TooltipKeybind } from "@opencode-ai/ui/tooltip"
import { useDialog } from "@opencode-ai/ui/context/dialog"
import { ModelSelectorPopover } from "@/components/dialog-select-model"
import { WorkspaceChip } from "@/components/prompt-input/workspace-chip"
import { SessionContextUsage } from "@/components/session-context-usage"
import { translateVariant } from "./prompt-input/variant-label"
import { SendButton } from "./prompt-input/send-button"
import { useProviders } from "@/hooks/use-providers"
Expand Down Expand Up @@ -1126,7 +1127,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
as="div"
variant="ghost"
size="normal"
class="h-[28px]! min-w-0 w-44 px-3 justify-start! text-13-medium! text-text-base group rounded-full! border! border-border-strong-base! transition-colors hover:bg-surface-base-hover"
class="h-[28px]! min-w-0 w-44 px-1.5 justify-start! text-13-regular! text-text-base group rounded-xl! transition-colors hover:bg-surface-base-hover"
style={triggerStyle()}
onClick={() => {
void import("@/components/dialog-select-model-unpaid").then((x) => {
Expand Down Expand Up @@ -1163,7 +1164,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
size: "normal",
style: triggerStyle(),
class:
"h-[28px]! min-w-0 w-44 px-3 justify-start! text-13-medium! text-text-base group rounded-full! border! border-border-strong-base! transition-colors hover:bg-surface-base-hover",
"h-[28px]! min-w-0 w-44 px-1.5 justify-start! text-13-regular! text-text-base group rounded-xl! transition-colors hover:bg-surface-base-hover",
"data-action": "prompt-model",
}}
onClose={restoreFocus}
Expand Down Expand Up @@ -1207,21 +1208,23 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
"aria-haspopup": "menu",
style: triggerStyle(),
class:
"h-[28px] px-3 max-w-[140px] inline-flex items-center gap-1.5 rounded-full border border-border-strong-base text-13-medium text-text-base transition-colors hover:bg-surface-base-hover",
"h-[28px] px-2 max-w-[160px] inline-flex items-center gap-1.5 rounded-xl text-13-regular text-text-base transition-colors hover:bg-surface-base-hover",
} as any
}
trigger={
<>
<span class="truncate leading-none">
<span class="truncate">
{translateVariant(language.t, local.model.variant.current() ?? "default")}
</span>
<Icon name="chevron-down" size="small" class="text-text-weak" />
</>
}
class="min-w-32 border border-border-base bg-surface-raised-stronger-non-alpha p-2 shadow-md"
style={{ "border-radius": "16px" }}
class="min-w-32 bg-surface-raised-stronger-non-alpha"
>
<div role="menu">
<div class="px-2 pt-0.5 pb-2 text-13-regular text-text-weak">
{language.t("prompt.variant.popover.title")}
</div>
<For each={variants()}>
{(variant) => {
const active = createMemo(() => (local.model.variant.current() ?? "default") === variant)
Expand All @@ -1230,8 +1233,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
type="button"
role="menuitemradio"
aria-checked={active()}
class="flex w-full items-center justify-between gap-2 rounded-md px-2 py-1.5 text-left text-13-medium text-text-strong outline-none hover:bg-surface-raised-base-hover focus-visible:bg-surface-raised-base-hover"
classList={{ "font-medium": active() }}
class="flex w-full items-center justify-between gap-2 rounded-md px-2 py-1.5 text-left text-13-regular text-text-strong outline-none hover:bg-surface-raised-base-hover focus-visible:bg-surface-raised-base-hover"
onClick={() => {
local.model.variant.set(variant === "default" ? undefined : variant)
setVariantOpen(false)
Expand Down Expand Up @@ -1435,7 +1437,6 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
onSubmit={handleSubmit}
classList={{
"group/prompt-input": true,
"focus-within:shadow-xs-border": true,
"border-icon-info-active border-dashed": store.draggingType !== null,
[props.class ?? ""]: !!props.class,
}}
Expand Down Expand Up @@ -1479,7 +1480,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
}}
>
<div
class="relative min-h-[120px] max-h-[240px] overflow-y-auto no-scrollbar"
class="relative min-h-[100px] max-h-[240px] overflow-y-auto no-scrollbar"
ref={(el) => (scrollRef = el)}
style={{ "scroll-padding-bottom": space }}
>
Expand Down Expand Up @@ -1566,7 +1567,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
data-action="prompt-attach"
type="button"
variant="ghost"
class="size-7 shrink-0 p-0"
class="size-7 shrink-0 p-0 rounded-xl!"
style={buttons()}
onClick={pick}
disabled={store.mode !== "normal"}
Expand All @@ -1586,6 +1587,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
</div>

<div class="flex items-center gap-2 pointer-events-auto">
<SessionContextUsage placement="top" />
<Tooltip placement="top" inactive={!working() && blank()} value={tip()}>
<SendButton
stopping={stopping()}
Expand Down
20 changes: 8 additions & 12 deletions packages/app/src/components/prompt-input/workspace-chip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,27 +63,26 @@ export function WorkspaceChip(props: { style?: JSX.CSSProperties | string } = {}
"aria-label": language.t("workspace.chip.ariaLabel"),
"aria-haspopup": "menu",
class:
"h-[28px] px-3 inline-flex items-center gap-1.5 rounded-full border border-border-strong-base text-13-medium text-text-base transition-colors hover:bg-surface-base-hover",
"h-[28px] px-1.5 inline-flex items-center gap-1.5 rounded-xl text-13-regular text-text-base transition-colors hover:bg-surface-base-hover",
style: props.style,
} as any
}
trigger={
<>
<Icon name="folder" size="small" class="shrink-0 text-text-weak" />
<span class="max-w-[120px] truncate leading-none">{label()}</span>
<span class="max-w-[120px] truncate">{label()}</span>
<Icon name="chevron-down" size="small" class="shrink-0 text-text-weak" />
</>
}
class="min-w-56 max-w-xs border border-border-base bg-surface-raised-stronger-non-alpha p-2 shadow-md"
style={{ "border-radius": "16px" }}
class="min-w-56 max-w-xs bg-surface-raised-stronger-non-alpha"
>
<div role="menu" aria-label={language.t("workspace.chip.popover.title")}>
<div class="px-2 pt-0.5 pb-2 text-11 font-medium text-text-weak">
<div class="px-2 pt-0.5 pb-2 text-13-regular text-text-weak">
{language.t("workspace.chip.popover.title")}
</div>
<Show
when={workspaces().length > 0}
fallback={<div class="px-2 py-2 text-12 text-text-weak">{language.t("workspace.chip.empty")}</div>}
fallback={<div class="px-2 py-2 text-13-regular text-text-weak">{language.t("workspace.chip.empty")}</div>}
>
<For each={workspaces()}>
{(workspace) => {
Expand All @@ -96,17 +95,14 @@ export function WorkspaceChip(props: { style?: JSX.CSSProperties | string } = {}
type="button"
role="menuitemradio"
aria-checked={active()}
class="flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-13-medium outline-none hover:bg-surface-raised-base-hover focus-visible:bg-surface-raised-base-hover"
class="flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-13-regular outline-none hover:bg-surface-raised-base-hover focus-visible:bg-surface-raised-base-hover"
onClick={() => {
navigate(`/${base64Encode(workspace.path)}/session`)
setOpen(false)
}}
>
<Icon name="folder" size="small" class="shrink-0 text-text-weak" />
<span
class="min-w-0 flex-1 truncate text-text-strong"
classList={{ "font-medium": active() }}
>
<span class="min-w-0 flex-1 truncate text-text-strong">
{getFilename(workspace.path)}
</span>
<Show when={active()}>
Expand All @@ -122,7 +118,7 @@ export function WorkspaceChip(props: { style?: JSX.CSSProperties | string } = {}
type="button"
role="menuitem"
data-action="workspace-chip-add"
class="flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-13-medium text-text-base outline-none hover:bg-surface-raised-base-hover focus-visible:bg-surface-raised-base-hover"
class="flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-13-regular text-text-base outline-none hover:bg-surface-raised-base-hover focus-visible:bg-surface-raised-base-hover"
onClick={() => {
setOpen(false)
layoutPage.openProject()
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/components/session-context-usage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export function SessionContextUsage(props: SessionContextUsageProps) {
<Button
type="button"
variant="ghost"
class="size-6"
class="size-7 shrink-0 p-0 rounded-xl!"
onClick={openContext}
aria-label={language.t("context.usage.view")}
>
Expand Down
11 changes: 5 additions & 6 deletions packages/app/src/components/titlebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export function Titlebar() {
<div class="h-full shrink-0" style={{ width: `${72 / zoom()}px` }} />
<div class="xl:hidden w-10 shrink-0 flex items-center justify-center">
<IconButton
icon="menu"
icon={layout.mobileSidebar.opened() ? "sidebar-active" : "sidebar"}
variant="ghost"
class="titlebar-icon rounded-md"
onClick={layout.mobileSidebar.toggle}
Expand All @@ -115,7 +115,7 @@ export function Titlebar() {
<Show when={!mac()}>
<div class="xl:hidden w-[48px] shrink-0 flex items-center justify-center">
<IconButton
icon="menu"
icon={layout.mobileSidebar.opened() ? "sidebar-active" : "sidebar"}
variant="ghost"
class="titlebar-icon rounded-md"
onClick={layout.mobileSidebar.toggle}
Expand All @@ -141,17 +141,16 @@ export function Titlebar() {
<Icon size="small" name={layout.sidebar.opened() ? "sidebar-active" : "sidebar"} />
</Button>
</TooltipKeybind>
<div class="hidden xl:flex items-center shrink-0">
<div class="flex items-center shrink-0">
<Show when={params.dir}>
<div
class="flex items-center shrink-0 w-8"
aria-hidden={layout.sidebar.opened() ? "true" : undefined}
>
<div
class="transition-opacity"
class="transition-opacity duration-120 ease-out opacity-100"
classList={{
"opacity-100 duration-120 ease-out": !layout.sidebar.opened(),
"opacity-0 duration-120 ease-in delay-0 pointer-events-none": layout.sidebar.opened(),
"xl:opacity-0 xl:ease-in xl:delay-0 xl:pointer-events-none": layout.sidebar.opened(),
}}
>
<TooltipKeybind
Expand Down
1 change: 1 addition & 0 deletions packages/app/src/context/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext(
},
},
rightPanel: {
opened: createMemo(() => store.rightPanel?.opened ?? false),
width: createMemo(() => clampRightPanelWidth(store.rightPanel?.width)),
resize(width: number) {
setStore("rightPanel", "width", clampRightPanelWidth(width))
Expand Down
1 change: 1 addition & 0 deletions packages/app/src/context/platform.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export type Platform = {
sessionID: string,
directory: string,
defaultName?: string,
title?: string,
): Promise<{ ok: true; path: string } | { ok: false; error: string }>

/** Storage mechanism, defaults to localStorage */
Expand Down
12 changes: 0 additions & 12 deletions packages/app/src/context/sync.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -616,18 +616,6 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
})
},
more: createMemo(() => current()[0].session.length >= current()[0].limit),
archive: async (sessionID: string) => {
const directory = sdk.directory
const client = sdk.client
const [, setStore] = globalSync.child(directory)
await client.session.update({ sessionID, time: { archived: Date.now() } })
setStore(
produce((draft) => {
const match = Binary.search(draft.session, sessionID, (s) => s.id)
if (match.found) draft.session.splice(match.index, 1)
}),
)
},
},
absolute,
get directory() {
Expand Down
11 changes: 5 additions & 6 deletions packages/app/src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ export const dict = {
"command.session.next": "Next session",
"command.session.previous.unseen": "Previous unread session",
"command.session.next.unseen": "Next unread session",
"command.session.archive": "Archive session",

"command.palette": "Command palette",

Expand Down Expand Up @@ -487,8 +486,8 @@ export const dict = {
"toast.update.action.installRestart": "Install and restart",
"toast.update.action.notYet": "Not yet",

"error.page.title": "Something went wrong",
"error.page.description": "An error occurred while loading the application.",
"error.page.title": "Something broke",
"error.page.description": "A restart usually fixes this. If not, send us the details.",
"error.page.details.label": "Error Details",
"error.page.action.restart": "Restart",
"error.page.action.checking": "Checking...",
Expand Down Expand Up @@ -618,7 +617,7 @@ export const dict = {
"session.todo.title": "Todos",
"session.todo.collapse": "Collapse",
"session.todo.expand": "Expand",
"session.todo.progress": "{{done}} of {{total}} todos completed",
"session.todo.progress": "Task {{current}} of {{total}}",
"session.todo.cancelled": "Cancelled",
"session.question.progress": "{{current}} of {{total}} questions",
"session.followupDock.summary.one": "{{count}} queued message",
Expand Down Expand Up @@ -710,7 +709,7 @@ export const dict = {
"session.share.copy.copied": "Copied",
"session.share.copy.copyLink": "Copy link",

"session.export.action.export": "Export session log",
"session.export.action.export": "Export session",
"session.export.success": "Session exported",
"session.export.error.failed": "Export failed",

Expand All @@ -735,7 +734,6 @@ export const dict = {
"common.learnMore": "Learn more",
"common.rename": "Rename",
"common.reset": "Reset",
"common.archive": "Archive",
"common.delete": "Delete",
"common.close": "Close",
"common.edit": "Edit",
Expand Down Expand Up @@ -1097,6 +1095,7 @@ export const dict = {
"workspace.chip.empty": "No workspaces available",
"workspace.chip.popover.title": "Workspaces",
"workspace.chip.add": "Add workspace",
"prompt.variant.popover.title": "Reasoning effort",
"about.title": "About PawWork",
"about.version": "Version",
"about.build": "Build",
Expand Down
Loading
Loading