chore(app): missing i18n strings
This commit is contained in:
@@ -50,7 +50,7 @@ export const DialogSettings: Component = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-1 pl-1 py-1 text-12-medium text-text-weak">
|
<div class="flex flex-col gap-1 pl-1 py-1 text-12-medium text-text-weak">
|
||||||
<span>OpenCode Desktop</span>
|
<span>{language.t("app.name.desktop")}</span>
|
||||||
<span class="text-11-regular">v{platform.version}</span>
|
<span class="text-11-regular">v{platform.version}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1565,7 +1565,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
|
|||||||
const timeoutMs = 5 * 60 * 1000
|
const timeoutMs = 5 * 60 * 1000
|
||||||
const timeout = new Promise<Awaited<ReturnType<typeof WorktreeState.wait>>>((resolve) => {
|
const timeout = new Promise<Awaited<ReturnType<typeof WorktreeState.wait>>>((resolve) => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
resolve({ status: "failed", message: "Workspace is still preparing" })
|
resolve({ status: "failed", message: language.t("workspace.error.stillPreparing") })
|
||||||
}, timeoutMs)
|
}, timeoutMs)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -1863,9 +1863,9 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
|
|||||||
store.mode === "shell"
|
store.mode === "shell"
|
||||||
? language.t("prompt.placeholder.shell")
|
? language.t("prompt.placeholder.shell")
|
||||||
: commentCount() > 1
|
: commentCount() > 1
|
||||||
? "Summarize comments…"
|
? language.t("prompt.placeholder.summarizeComments")
|
||||||
: commentCount() === 1
|
: commentCount() === 1
|
||||||
? "Summarize comment…"
|
? language.t("prompt.placeholder.summarizeComment")
|
||||||
: language.t("prompt.placeholder.normal", { example: language.t(EXAMPLES[store.placeholder]) })
|
: language.t("prompt.placeholder.normal", { example: language.t(EXAMPLES[store.placeholder]) })
|
||||||
}
|
}
|
||||||
contenteditable="true"
|
contenteditable="true"
|
||||||
@@ -1887,9 +1887,9 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
|
|||||||
{store.mode === "shell"
|
{store.mode === "shell"
|
||||||
? language.t("prompt.placeholder.shell")
|
? language.t("prompt.placeholder.shell")
|
||||||
: commentCount() > 1
|
: commentCount() > 1
|
||||||
? "Summarize comments…"
|
? language.t("prompt.placeholder.summarizeComments")
|
||||||
: commentCount() === 1
|
: commentCount() === 1
|
||||||
? "Summarize comment…"
|
? language.t("prompt.placeholder.summarizeComment")
|
||||||
: language.t("prompt.placeholder.normal", { example: language.t(EXAMPLES[store.placeholder]) })}
|
: language.t("prompt.placeholder.normal", { example: language.t(EXAMPLES[store.placeholder]) })}
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
|
|||||||
@@ -281,7 +281,7 @@ export function SessionHeader() {
|
|||||||
</TooltipKeybind>
|
</TooltipKeybind>
|
||||||
</div>
|
</div>
|
||||||
<div class="hidden md:block shrink-0">
|
<div class="hidden md:block shrink-0">
|
||||||
<Tooltip value="Toggle file tree" placement="bottom">
|
<Tooltip value={language.t("command.fileTree.toggle")} placement="bottom">
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
class="group/file-tree-toggle size-5 p-0"
|
class="group/file-tree-toggle size-5 p-0"
|
||||||
@@ -290,7 +290,7 @@ export function SessionHeader() {
|
|||||||
if (opening && !view().reviewPanel.opened()) view().reviewPanel.open()
|
if (opening && !view().reviewPanel.opened()) view().reviewPanel.open()
|
||||||
layout.fileTree.toggle()
|
layout.fileTree.toggle()
|
||||||
}}
|
}}
|
||||||
aria-label="Toggle file tree"
|
aria-label={language.t("command.fileTree.toggle")}
|
||||||
aria-expanded={layout.fileTree.opened()}
|
aria-expanded={layout.fileTree.opened()}
|
||||||
>
|
>
|
||||||
<div class="relative flex items-center justify-center size-4">
|
<div class="relative flex items-center justify-center size-4">
|
||||||
|
|||||||
@@ -517,7 +517,7 @@ export const { use: useFile, provider: FileProvider } = createSimpleContext({
|
|||||||
)
|
)
|
||||||
showToast({
|
showToast({
|
||||||
variant: "error",
|
variant: "error",
|
||||||
title: "Failed to list files",
|
title: language.t("toast.file.listFailed.title"),
|
||||||
description: e.message,
|
description: e.message,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ export const dict = {
|
|||||||
"command.category.theme": "Theme",
|
"command.category.theme": "Theme",
|
||||||
"command.category.language": "Language",
|
"command.category.language": "Language",
|
||||||
"command.category.file": "File",
|
"command.category.file": "File",
|
||||||
|
"command.category.context": "Context",
|
||||||
"command.category.terminal": "Terminal",
|
"command.category.terminal": "Terminal",
|
||||||
"command.category.model": "Model",
|
"command.category.model": "Model",
|
||||||
"command.category.mcp": "MCP",
|
"command.category.mcp": "MCP",
|
||||||
@@ -42,7 +43,10 @@ export const dict = {
|
|||||||
"command.session.new": "New session",
|
"command.session.new": "New session",
|
||||||
"command.file.open": "Open file",
|
"command.file.open": "Open file",
|
||||||
"command.file.open.description": "Search files and commands",
|
"command.file.open.description": "Search files and commands",
|
||||||
|
"command.context.addSelection": "Add selection to context",
|
||||||
|
"command.context.addSelection.description": "Add selected lines from the current file",
|
||||||
"command.terminal.toggle": "Toggle terminal",
|
"command.terminal.toggle": "Toggle terminal",
|
||||||
|
"command.fileTree.toggle": "Toggle file tree",
|
||||||
"command.review.toggle": "Toggle review",
|
"command.review.toggle": "Toggle review",
|
||||||
"command.terminal.new": "New terminal",
|
"command.terminal.new": "New terminal",
|
||||||
"command.terminal.new.description": "Create a new terminal tab",
|
"command.terminal.new.description": "Create a new terminal tab",
|
||||||
@@ -172,6 +176,8 @@ export const dict = {
|
|||||||
|
|
||||||
"prompt.placeholder.shell": "Enter shell command...",
|
"prompt.placeholder.shell": "Enter shell command...",
|
||||||
"prompt.placeholder.normal": 'Ask anything... "{{example}}"',
|
"prompt.placeholder.normal": 'Ask anything... "{{example}}"',
|
||||||
|
"prompt.placeholder.summarizeComments": "Summarize comments…",
|
||||||
|
"prompt.placeholder.summarizeComment": "Summarize comment…",
|
||||||
"prompt.mode.shell": "Shell",
|
"prompt.mode.shell": "Shell",
|
||||||
"prompt.mode.shell.exit": "esc to exit",
|
"prompt.mode.shell.exit": "esc to exit",
|
||||||
|
|
||||||
@@ -342,6 +348,10 @@ export const dict = {
|
|||||||
"toast.model.none.description": "Connect a provider to summarize this session",
|
"toast.model.none.description": "Connect a provider to summarize this session",
|
||||||
|
|
||||||
"toast.file.loadFailed.title": "Failed to load file",
|
"toast.file.loadFailed.title": "Failed to load file",
|
||||||
|
"toast.file.listFailed.title": "Failed to list files",
|
||||||
|
|
||||||
|
"toast.context.noLineSelection.title": "No line selection",
|
||||||
|
"toast.context.noLineSelection.description": "Select a line range in a file tab first.",
|
||||||
|
|
||||||
"toast.session.share.copyFailed.title": "Failed to copy URL to clipboard",
|
"toast.session.share.copyFailed.title": "Failed to copy URL to clipboard",
|
||||||
"toast.session.share.success.title": "Session shared",
|
"toast.session.share.success.title": "Session shared",
|
||||||
@@ -417,8 +427,15 @@ export const dict = {
|
|||||||
"session.tab.context": "Context",
|
"session.tab.context": "Context",
|
||||||
"session.panel.reviewAndFiles": "Review and files",
|
"session.panel.reviewAndFiles": "Review and files",
|
||||||
"session.review.filesChanged": "{{count}} Files Changed",
|
"session.review.filesChanged": "{{count}} Files Changed",
|
||||||
|
"session.review.change.one": "Change",
|
||||||
|
"session.review.change.other": "Changes",
|
||||||
"session.review.loadingChanges": "Loading changes...",
|
"session.review.loadingChanges": "Loading changes...",
|
||||||
"session.review.empty": "No changes in this session yet",
|
"session.review.empty": "No changes in this session yet",
|
||||||
|
"session.review.noChanges": "No changes",
|
||||||
|
|
||||||
|
"session.files.selectToOpen": "Select a file to open",
|
||||||
|
"session.files.all": "All files",
|
||||||
|
|
||||||
"session.messages.renderEarlier": "Render earlier messages",
|
"session.messages.renderEarlier": "Render earlier messages",
|
||||||
"session.messages.loadingEarlier": "Loading earlier messages...",
|
"session.messages.loadingEarlier": "Loading earlier messages...",
|
||||||
"session.messages.loadEarlier": "Load earlier messages",
|
"session.messages.loadEarlier": "Load earlier messages",
|
||||||
@@ -495,6 +512,8 @@ export const dict = {
|
|||||||
"sidebar.project.recentSessions": "Recent sessions",
|
"sidebar.project.recentSessions": "Recent sessions",
|
||||||
"sidebar.project.viewAllSessions": "View all sessions",
|
"sidebar.project.viewAllSessions": "View all sessions",
|
||||||
|
|
||||||
|
"app.name.desktop": "OpenCode Desktop",
|
||||||
|
|
||||||
"settings.section.desktop": "Desktop",
|
"settings.section.desktop": "Desktop",
|
||||||
"settings.section.server": "Server",
|
"settings.section.server": "Server",
|
||||||
"settings.tab.general": "General",
|
"settings.tab.general": "General",
|
||||||
@@ -678,6 +697,7 @@ export const dict = {
|
|||||||
"workspace.reset.failed.title": "Failed to reset workspace",
|
"workspace.reset.failed.title": "Failed to reset workspace",
|
||||||
"workspace.reset.success.title": "Workspace reset",
|
"workspace.reset.success.title": "Workspace reset",
|
||||||
"workspace.reset.success.description": "Workspace now matches the default branch.",
|
"workspace.reset.success.description": "Workspace now matches the default branch.",
|
||||||
|
"workspace.error.stillPreparing": "Workspace is still preparing",
|
||||||
"workspace.status.checking": "Checking for unmerged changes...",
|
"workspace.status.checking": "Checking for unmerged changes...",
|
||||||
"workspace.status.error": "Unable to verify git status.",
|
"workspace.status.error": "Unable to verify git status.",
|
||||||
"workspace.status.clean": "No unmerged changes detected.",
|
"workspace.status.clean": "No unmerged changes detected.",
|
||||||
|
|||||||
@@ -586,26 +586,26 @@ export default function Page() {
|
|||||||
command.register(() => [
|
command.register(() => [
|
||||||
{
|
{
|
||||||
id: "session.new",
|
id: "session.new",
|
||||||
title: "New session",
|
title: language.t("command.session.new"),
|
||||||
category: "Session",
|
category: language.t("command.category.session"),
|
||||||
keybind: "mod+shift+s",
|
keybind: "mod+shift+s",
|
||||||
slash: "new",
|
slash: "new",
|
||||||
onSelect: () => navigate(`/${params.dir}/session`),
|
onSelect: () => navigate(`/${params.dir}/session`),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "file.open",
|
id: "file.open",
|
||||||
title: "Open file",
|
title: language.t("command.file.open"),
|
||||||
description: "Search files and commands",
|
description: language.t("command.file.open.description"),
|
||||||
category: "File",
|
category: language.t("command.category.file"),
|
||||||
keybind: "mod+p",
|
keybind: "mod+p",
|
||||||
slash: "open",
|
slash: "open",
|
||||||
onSelect: () => dialog.show(() => <DialogSelectFile />),
|
onSelect: () => dialog.show(() => <DialogSelectFile />),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "context.addSelection",
|
id: "context.addSelection",
|
||||||
title: "Add selection to context",
|
title: language.t("command.context.addSelection"),
|
||||||
description: "Add selected lines from the current file",
|
description: language.t("command.context.addSelection.description"),
|
||||||
category: "Context",
|
category: language.t("command.category.context"),
|
||||||
keybind: "mod+shift+l",
|
keybind: "mod+shift+l",
|
||||||
disabled: (() => {
|
disabled: (() => {
|
||||||
const active = tabs().active()
|
const active = tabs().active()
|
||||||
@@ -623,8 +623,8 @@ export default function Page() {
|
|||||||
const range = file.selectedLines(path)
|
const range = file.selectedLines(path)
|
||||||
if (!range) {
|
if (!range) {
|
||||||
showToast({
|
showToast({
|
||||||
title: "No line selection",
|
title: language.t("toast.context.noLineSelection.title"),
|
||||||
description: "Select a line range in a file tab first.",
|
description: language.t("toast.context.noLineSelection.description"),
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -634,18 +634,18 @@ export default function Page() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "terminal.toggle",
|
id: "terminal.toggle",
|
||||||
title: "Toggle terminal",
|
title: language.t("command.terminal.toggle"),
|
||||||
description: "",
|
description: "",
|
||||||
category: "View",
|
category: language.t("command.category.view"),
|
||||||
keybind: "ctrl+`",
|
keybind: "ctrl+`",
|
||||||
slash: "terminal",
|
slash: "terminal",
|
||||||
onSelect: () => view().terminal.toggle(),
|
onSelect: () => view().terminal.toggle(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "review.toggle",
|
id: "review.toggle",
|
||||||
title: "Toggle review",
|
title: language.t("command.review.toggle"),
|
||||||
description: "",
|
description: "",
|
||||||
category: "View",
|
category: language.t("command.category.view"),
|
||||||
keybind: "mod+shift+r",
|
keybind: "mod+shift+r",
|
||||||
onSelect: () => view().reviewPanel.toggle(),
|
onSelect: () => view().reviewPanel.toggle(),
|
||||||
},
|
},
|
||||||
@@ -662,9 +662,9 @@ export default function Page() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "steps.toggle",
|
id: "steps.toggle",
|
||||||
title: "Toggle steps",
|
title: language.t("command.steps.toggle"),
|
||||||
description: "Show or hide steps for the current message",
|
description: language.t("command.steps.toggle.description"),
|
||||||
category: "View",
|
category: language.t("command.category.view"),
|
||||||
keybind: "mod+e",
|
keybind: "mod+e",
|
||||||
slash: "steps",
|
slash: "steps",
|
||||||
disabled: !params.id,
|
disabled: !params.id,
|
||||||
@@ -676,62 +676,62 @@ export default function Page() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "message.previous",
|
id: "message.previous",
|
||||||
title: "Previous message",
|
title: language.t("command.message.previous"),
|
||||||
description: "Go to the previous user message",
|
description: language.t("command.message.previous.description"),
|
||||||
category: "Session",
|
category: language.t("command.category.session"),
|
||||||
keybind: "mod+arrowup",
|
keybind: "mod+arrowup",
|
||||||
disabled: !params.id,
|
disabled: !params.id,
|
||||||
onSelect: () => navigateMessageByOffset(-1),
|
onSelect: () => navigateMessageByOffset(-1),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "message.next",
|
id: "message.next",
|
||||||
title: "Next message",
|
title: language.t("command.message.next"),
|
||||||
description: "Go to the next user message",
|
description: language.t("command.message.next.description"),
|
||||||
category: "Session",
|
category: language.t("command.category.session"),
|
||||||
keybind: "mod+arrowdown",
|
keybind: "mod+arrowdown",
|
||||||
disabled: !params.id,
|
disabled: !params.id,
|
||||||
onSelect: () => navigateMessageByOffset(1),
|
onSelect: () => navigateMessageByOffset(1),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "model.choose",
|
id: "model.choose",
|
||||||
title: "Choose model",
|
title: language.t("command.model.choose"),
|
||||||
description: "Select a different model",
|
description: language.t("command.model.choose.description"),
|
||||||
category: "Model",
|
category: language.t("command.category.model"),
|
||||||
keybind: "mod+'",
|
keybind: "mod+'",
|
||||||
slash: "model",
|
slash: "model",
|
||||||
onSelect: () => dialog.show(() => <DialogSelectModel />),
|
onSelect: () => dialog.show(() => <DialogSelectModel />),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "mcp.toggle",
|
id: "mcp.toggle",
|
||||||
title: "Toggle MCPs",
|
title: language.t("command.mcp.toggle"),
|
||||||
description: "Toggle MCPs",
|
description: language.t("command.mcp.toggle.description"),
|
||||||
category: "MCP",
|
category: language.t("command.category.mcp"),
|
||||||
keybind: "mod+;",
|
keybind: "mod+;",
|
||||||
slash: "mcp",
|
slash: "mcp",
|
||||||
onSelect: () => dialog.show(() => <DialogSelectMcp />),
|
onSelect: () => dialog.show(() => <DialogSelectMcp />),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "agent.cycle",
|
id: "agent.cycle",
|
||||||
title: "Cycle agent",
|
title: language.t("command.agent.cycle"),
|
||||||
description: "Switch to the next agent",
|
description: language.t("command.agent.cycle.description"),
|
||||||
category: "Agent",
|
category: language.t("command.category.agent"),
|
||||||
keybind: "mod+.",
|
keybind: "mod+.",
|
||||||
slash: "agent",
|
slash: "agent",
|
||||||
onSelect: () => local.agent.move(1),
|
onSelect: () => local.agent.move(1),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "agent.cycle.reverse",
|
id: "agent.cycle.reverse",
|
||||||
title: "Cycle agent backwards",
|
title: language.t("command.agent.cycle.reverse"),
|
||||||
description: "Switch to the previous agent",
|
description: language.t("command.agent.cycle.reverse.description"),
|
||||||
category: "Agent",
|
category: language.t("command.category.agent"),
|
||||||
keybind: "shift+mod+.",
|
keybind: "shift+mod+.",
|
||||||
onSelect: () => local.agent.move(-1),
|
onSelect: () => local.agent.move(-1),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "model.variant.cycle",
|
id: "model.variant.cycle",
|
||||||
title: "Cycle thinking effort",
|
title: language.t("command.model.variant.cycle"),
|
||||||
description: "Switch to the next effort level",
|
description: language.t("command.model.variant.cycle.description"),
|
||||||
category: "Model",
|
category: language.t("command.category.model"),
|
||||||
keybind: "shift+mod+d",
|
keybind: "shift+mod+d",
|
||||||
onSelect: () => {
|
onSelect: () => {
|
||||||
local.model.variant.cycle()
|
local.model.variant.cycle()
|
||||||
@@ -741,9 +741,9 @@ export default function Page() {
|
|||||||
id: "permissions.autoaccept",
|
id: "permissions.autoaccept",
|
||||||
title:
|
title:
|
||||||
params.id && permission.isAutoAccepting(params.id, sdk.directory)
|
params.id && permission.isAutoAccepting(params.id, sdk.directory)
|
||||||
? "Stop auto-accepting edits"
|
? language.t("command.permissions.autoaccept.disable")
|
||||||
: "Auto-accept edits",
|
: language.t("command.permissions.autoaccept.enable"),
|
||||||
category: "Permissions",
|
category: language.t("command.category.permissions"),
|
||||||
keybind: "mod+shift+a",
|
keybind: "mod+shift+a",
|
||||||
disabled: !params.id || !permission.permissionsEnabled(),
|
disabled: !params.id || !permission.permissionsEnabled(),
|
||||||
onSelect: () => {
|
onSelect: () => {
|
||||||
@@ -752,19 +752,19 @@ export default function Page() {
|
|||||||
permission.toggleAutoAccept(sessionID, sdk.directory)
|
permission.toggleAutoAccept(sessionID, sdk.directory)
|
||||||
showToast({
|
showToast({
|
||||||
title: permission.isAutoAccepting(sessionID, sdk.directory)
|
title: permission.isAutoAccepting(sessionID, sdk.directory)
|
||||||
? "Auto-accepting edits"
|
? language.t("toast.permissions.autoaccept.on.title")
|
||||||
: "Stopped auto-accepting edits",
|
: language.t("toast.permissions.autoaccept.off.title"),
|
||||||
description: permission.isAutoAccepting(sessionID, sdk.directory)
|
description: permission.isAutoAccepting(sessionID, sdk.directory)
|
||||||
? "Edit and write permissions will be automatically approved"
|
? language.t("toast.permissions.autoaccept.on.description")
|
||||||
: "Edit and write permissions will require approval",
|
: language.t("toast.permissions.autoaccept.off.description"),
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "session.undo",
|
id: "session.undo",
|
||||||
title: "Undo",
|
title: language.t("command.session.undo"),
|
||||||
description: "Undo the last message",
|
description: language.t("command.session.undo.description"),
|
||||||
category: "Session",
|
category: language.t("command.category.session"),
|
||||||
slash: "undo",
|
slash: "undo",
|
||||||
disabled: !params.id || visibleUserMessages().length === 0,
|
disabled: !params.id || visibleUserMessages().length === 0,
|
||||||
onSelect: async () => {
|
onSelect: async () => {
|
||||||
@@ -791,9 +791,9 @@ export default function Page() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "session.redo",
|
id: "session.redo",
|
||||||
title: "Redo",
|
title: language.t("command.session.redo"),
|
||||||
description: "Redo the last undone message",
|
description: language.t("command.session.redo.description"),
|
||||||
category: "Session",
|
category: language.t("command.category.session"),
|
||||||
slash: "redo",
|
slash: "redo",
|
||||||
disabled: !params.id || !info()?.revert?.messageID,
|
disabled: !params.id || !info()?.revert?.messageID,
|
||||||
onSelect: async () => {
|
onSelect: async () => {
|
||||||
@@ -820,9 +820,9 @@ export default function Page() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "session.compact",
|
id: "session.compact",
|
||||||
title: "Compact session",
|
title: language.t("command.session.compact"),
|
||||||
description: "Summarize the session to reduce context size",
|
description: language.t("command.session.compact.description"),
|
||||||
category: "Session",
|
category: language.t("command.category.session"),
|
||||||
slash: "compact",
|
slash: "compact",
|
||||||
disabled: !params.id || visibleUserMessages().length === 0,
|
disabled: !params.id || visibleUserMessages().length === 0,
|
||||||
onSelect: async () => {
|
onSelect: async () => {
|
||||||
@@ -831,8 +831,8 @@ export default function Page() {
|
|||||||
const model = local.model.current()
|
const model = local.model.current()
|
||||||
if (!model) {
|
if (!model) {
|
||||||
showToast({
|
showToast({
|
||||||
title: "No model selected",
|
title: language.t("toast.model.none.title"),
|
||||||
description: "Connect a provider to summarize this session",
|
description: language.t("toast.model.none.description"),
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -845,9 +845,9 @@ export default function Page() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "session.fork",
|
id: "session.fork",
|
||||||
title: "Fork from message",
|
title: language.t("command.session.fork"),
|
||||||
description: "Create a new session from a previous message",
|
description: language.t("command.session.fork.description"),
|
||||||
category: "Session",
|
category: language.t("command.category.session"),
|
||||||
slash: "fork",
|
slash: "fork",
|
||||||
disabled: !params.id || visibleUserMessages().length === 0,
|
disabled: !params.id || visibleUserMessages().length === 0,
|
||||||
onSelect: () => dialog.show(() => <DialogFork />),
|
onSelect: () => dialog.show(() => <DialogFork />),
|
||||||
@@ -856,9 +856,9 @@ export default function Page() {
|
|||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
id: "session.share",
|
id: "session.share",
|
||||||
title: "Share session",
|
title: language.t("command.session.share"),
|
||||||
description: "Share this session and copy the URL to clipboard",
|
description: language.t("command.session.share.description"),
|
||||||
category: "Session",
|
category: language.t("command.category.session"),
|
||||||
slash: "share",
|
slash: "share",
|
||||||
disabled: !params.id || !!info()?.share?.url,
|
disabled: !params.id || !!info()?.share?.url,
|
||||||
onSelect: async () => {
|
onSelect: async () => {
|
||||||
@@ -868,22 +868,22 @@ export default function Page() {
|
|||||||
.then((res) => {
|
.then((res) => {
|
||||||
navigator.clipboard.writeText(res.data!.share!.url).catch(() =>
|
navigator.clipboard.writeText(res.data!.share!.url).catch(() =>
|
||||||
showToast({
|
showToast({
|
||||||
title: "Failed to copy URL to clipboard",
|
title: language.t("toast.session.share.copyFailed.title"),
|
||||||
variant: "error",
|
variant: "error",
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.then(() =>
|
.then(() =>
|
||||||
showToast({
|
showToast({
|
||||||
title: "Session shared",
|
title: language.t("toast.session.share.success.title"),
|
||||||
description: "Share URL copied to clipboard!",
|
description: language.t("toast.session.share.success.description"),
|
||||||
variant: "success",
|
variant: "success",
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.catch(() =>
|
.catch(() =>
|
||||||
showToast({
|
showToast({
|
||||||
title: "Failed to share session",
|
title: language.t("toast.session.share.failed.title"),
|
||||||
description: "An error occurred while sharing the session",
|
description: language.t("toast.session.share.failed.description"),
|
||||||
variant: "error",
|
variant: "error",
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
@@ -891,9 +891,9 @@ export default function Page() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "session.unshare",
|
id: "session.unshare",
|
||||||
title: "Unshare session",
|
title: language.t("command.session.unshare"),
|
||||||
description: "Stop sharing this session",
|
description: language.t("command.session.unshare.description"),
|
||||||
category: "Session",
|
category: language.t("command.category.session"),
|
||||||
slash: "unshare",
|
slash: "unshare",
|
||||||
disabled: !params.id || !info()?.share?.url,
|
disabled: !params.id || !info()?.share?.url,
|
||||||
onSelect: async () => {
|
onSelect: async () => {
|
||||||
@@ -902,15 +902,15 @@ export default function Page() {
|
|||||||
.unshare({ sessionID: params.id })
|
.unshare({ sessionID: params.id })
|
||||||
.then(() =>
|
.then(() =>
|
||||||
showToast({
|
showToast({
|
||||||
title: "Session unshared",
|
title: language.t("toast.session.unshare.success.title"),
|
||||||
description: "Session unshared successfully!",
|
description: language.t("toast.session.unshare.success.description"),
|
||||||
variant: "success",
|
variant: "success",
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.catch(() =>
|
.catch(() =>
|
||||||
showToast({
|
showToast({
|
||||||
title: "Failed to unshare session",
|
title: language.t("toast.session.unshare.failed.title"),
|
||||||
description: "An error occurred while unsharing the session",
|
description: language.t("toast.session.unshare.failed.description"),
|
||||||
variant: "error",
|
variant: "error",
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
@@ -1759,7 +1759,7 @@ export default function Page() {
|
|||||||
class="text-12-medium opacity-50"
|
class="text-12-medium opacity-50"
|
||||||
onClick={() => setStore("turnStart", 0)}
|
onClick={() => setStore("turnStart", 0)}
|
||||||
>
|
>
|
||||||
Render earlier messages
|
{language.t("session.messages.renderEarlier")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
@@ -1777,7 +1777,9 @@ export default function Page() {
|
|||||||
sync.session.history.loadMore(id)
|
sync.session.history.loadMore(id)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{historyLoading() ? "Loading earlier messages..." : "Load earlier messages"}
|
{historyLoading()
|
||||||
|
? language.t("session.messages.loadingEarlier")
|
||||||
|
: language.t("session.messages.loadEarlier")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
@@ -1911,7 +1913,7 @@ export default function Page() {
|
|||||||
when={prompt.ready()}
|
when={prompt.ready()}
|
||||||
fallback={
|
fallback={
|
||||||
<div class="w-full min-h-32 md:min-h-40 rounded-md border border-border-weak-base bg-background-base/50 px-4 py-3 text-text-weak whitespace-pre-wrap pointer-events-none">
|
<div class="w-full min-h-32 md:min-h-40 rounded-md border border-border-weak-base bg-background-base/50 px-4 py-3 text-text-weak whitespace-pre-wrap pointer-events-none">
|
||||||
{handoff.prompt || "Loading prompt..."}
|
{handoff.prompt || language.t("prompt.loading")}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
@@ -2057,7 +2059,7 @@ export default function Page() {
|
|||||||
<div class="h-full px-6 pb-30 flex flex-col items-center justify-center text-center gap-6">
|
<div class="h-full px-6 pb-30 flex flex-col items-center justify-center text-center gap-6">
|
||||||
<Mark class="w-14 opacity-10" />
|
<Mark class="w-14 opacity-10" />
|
||||||
<div class="text-13-regular text-text-weak max-w-56">
|
<div class="text-13-regular text-text-weak max-w-56">
|
||||||
No changes in this session yet
|
{language.t("session.review.empty")}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Match>
|
</Match>
|
||||||
@@ -2071,7 +2073,9 @@ export default function Page() {
|
|||||||
<Tabs.Content value="review" class="flex flex-col h-full overflow-hidden contain-strict">
|
<Tabs.Content value="review" class="flex flex-col h-full overflow-hidden contain-strict">
|
||||||
<div class="h-full px-6 pb-30 flex flex-col items-center justify-center text-center gap-6">
|
<div class="h-full px-6 pb-30 flex flex-col items-center justify-center text-center gap-6">
|
||||||
<Mark class="w-14 opacity-10" />
|
<Mark class="w-14 opacity-10" />
|
||||||
<div class="text-13-regular text-text-weak max-w-56">Select a file to open</div>
|
<div class="text-13-regular text-text-weak max-w-56">
|
||||||
|
{language.t("session.files.selectToOpen")}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Tabs.Content>
|
</Tabs.Content>
|
||||||
</Show>
|
</Show>
|
||||||
@@ -2609,7 +2613,9 @@ export default function Page() {
|
|||||||
<Match when={true}>
|
<Match when={true}>
|
||||||
<div class="h-full px-6 pb-30 flex flex-col items-center justify-center text-center gap-6">
|
<div class="h-full px-6 pb-30 flex flex-col items-center justify-center text-center gap-6">
|
||||||
<Mark class="w-14 opacity-10" />
|
<Mark class="w-14 opacity-10" />
|
||||||
<div class="text-13-regular text-text-weak max-w-56">No changes in this session yet</div>
|
<div class="text-13-regular text-text-weak max-w-56">
|
||||||
|
{language.t("session.review.empty")}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Match>
|
</Match>
|
||||||
</Switch>
|
</Switch>
|
||||||
@@ -2624,10 +2630,11 @@ export default function Page() {
|
|||||||
<Tabs variant="pill" value={fileTreeTab()} onChange={setFileTreeTabValue} class="h-full">
|
<Tabs variant="pill" value={fileTreeTab()} onChange={setFileTreeTabValue} class="h-full">
|
||||||
<Tabs.List>
|
<Tabs.List>
|
||||||
<Tabs.Trigger value="changes" class="flex-1" classes={{ button: "w-full" }}>
|
<Tabs.Trigger value="changes" class="flex-1" classes={{ button: "w-full" }}>
|
||||||
{reviewCount()} {reviewCount() === 1 ? "Change" : "Changes"}
|
{reviewCount()}{" "}
|
||||||
|
{language.t(reviewCount() === 1 ? "session.review.change.one" : "session.review.change.other")}
|
||||||
</Tabs.Trigger>
|
</Tabs.Trigger>
|
||||||
<Tabs.Trigger value="all" class="flex-1" classes={{ button: "w-full" }}>
|
<Tabs.Trigger value="all" class="flex-1" classes={{ button: "w-full" }}>
|
||||||
All files
|
{language.t("session.files.all")}
|
||||||
</Tabs.Trigger>
|
</Tabs.Trigger>
|
||||||
</Tabs.List>
|
</Tabs.List>
|
||||||
<Tabs.Content value="changes" class="bg-background-base p-2">
|
<Tabs.Content value="changes" class="bg-background-base p-2">
|
||||||
@@ -2635,7 +2642,12 @@ export default function Page() {
|
|||||||
<Match when={hasReview()}>
|
<Match when={hasReview()}>
|
||||||
<Show
|
<Show
|
||||||
when={diffsReady()}
|
when={diffsReady()}
|
||||||
fallback={<div class="px-2 py-2 text-12-regular text-text-weak">Loading...</div>}
|
fallback={
|
||||||
|
<div class="px-2 py-2 text-12-regular text-text-weak">
|
||||||
|
{language.t("common.loading")}
|
||||||
|
{language.t("common.loading.ellipsis")}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<FileTree
|
<FileTree
|
||||||
path=""
|
path=""
|
||||||
@@ -2647,7 +2659,9 @@ export default function Page() {
|
|||||||
</Show>
|
</Show>
|
||||||
</Match>
|
</Match>
|
||||||
<Match when={true}>
|
<Match when={true}>
|
||||||
<div class="px-2 py-2 text-12-regular text-text-weak">No changes</div>
|
<div class="px-2 py-2 text-12-regular text-text-weak">
|
||||||
|
{language.t("session.review.noChanges")}
|
||||||
|
</div>
|
||||||
</Match>
|
</Match>
|
||||||
</Switch>
|
</Switch>
|
||||||
</Tabs.Content>
|
</Tabs.Content>
|
||||||
@@ -2702,9 +2716,14 @@ export default function Page() {
|
|||||||
)}
|
)}
|
||||||
</For>
|
</For>
|
||||||
<div class="flex-1" />
|
<div class="flex-1" />
|
||||||
<div class="text-text-weak pr-2">Loading...</div>
|
<div class="text-text-weak pr-2">
|
||||||
|
{language.t("common.loading")}
|
||||||
|
{language.t("common.loading.ellipsis")}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex-1 flex items-center justify-center text-text-weak">
|
||||||
|
{language.t("terminal.loading")}
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-1 flex items-center justify-center text-text-weak">Loading terminal...</div>
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { onMount, Show, splitProps, type JSX } from "solid-js"
|
import { onMount, Show, splitProps, type JSX } from "solid-js"
|
||||||
import { Button } from "./button"
|
import { Button } from "./button"
|
||||||
import { Icon } from "./icon"
|
import { Icon } from "./icon"
|
||||||
|
import { useI18n } from "../context/i18n"
|
||||||
|
|
||||||
export type LineCommentVariant = "default" | "editor"
|
export type LineCommentVariant = "default" | "editor"
|
||||||
|
|
||||||
@@ -60,13 +61,18 @@ export type LineCommentProps = Omit<LineCommentAnchorProps, "children" | "varian
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const LineComment = (props: LineCommentProps) => {
|
export const LineComment = (props: LineCommentProps) => {
|
||||||
|
const i18n = useI18n()
|
||||||
const [split, rest] = splitProps(props, ["comment", "selection"])
|
const [split, rest] = splitProps(props, ["comment", "selection"])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LineCommentAnchor {...rest} variant="default">
|
<LineCommentAnchor {...rest} variant="default">
|
||||||
<div data-slot="line-comment-content">
|
<div data-slot="line-comment-content">
|
||||||
<div data-slot="line-comment-text">{split.comment}</div>
|
<div data-slot="line-comment-text">{split.comment}</div>
|
||||||
<div data-slot="line-comment-label">Comment on {split.selection}</div>
|
<div data-slot="line-comment-label">
|
||||||
|
{i18n.t("ui.lineComment.label.prefix")}
|
||||||
|
{split.selection}
|
||||||
|
{i18n.t("ui.lineComment.label.suffix")}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</LineCommentAnchor>
|
</LineCommentAnchor>
|
||||||
)
|
)
|
||||||
@@ -86,6 +92,7 @@ export type LineCommentEditorProps = Omit<LineCommentAnchorProps, "children" | "
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const LineCommentEditor = (props: LineCommentEditorProps) => {
|
export const LineCommentEditor = (props: LineCommentEditorProps) => {
|
||||||
|
const i18n = useI18n()
|
||||||
const [split, rest] = splitProps(props, [
|
const [split, rest] = splitProps(props, [
|
||||||
"value",
|
"value",
|
||||||
"selection",
|
"selection",
|
||||||
@@ -125,7 +132,7 @@ export const LineCommentEditor = (props: LineCommentEditorProps) => {
|
|||||||
}}
|
}}
|
||||||
data-slot="line-comment-textarea"
|
data-slot="line-comment-textarea"
|
||||||
rows={split.rows ?? 3}
|
rows={split.rows ?? 3}
|
||||||
placeholder={split.placeholder ?? "Add comment"}
|
placeholder={split.placeholder ?? i18n.t("ui.lineComment.placeholder")}
|
||||||
value={split.value}
|
value={split.value}
|
||||||
onInput={(e) => split.onInput(e.currentTarget.value)}
|
onInput={(e) => split.onInput(e.currentTarget.value)}
|
||||||
onKeyDown={(e) => {
|
onKeyDown={(e) => {
|
||||||
@@ -143,12 +150,16 @@ export const LineCommentEditor = (props: LineCommentEditorProps) => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<div data-slot="line-comment-actions">
|
<div data-slot="line-comment-actions">
|
||||||
<div data-slot="line-comment-editor-label">Commenting on {split.selection}</div>
|
<div data-slot="line-comment-editor-label">
|
||||||
|
{i18n.t("ui.lineComment.editorLabel.prefix")}
|
||||||
|
{split.selection}
|
||||||
|
{i18n.t("ui.lineComment.editorLabel.suffix")}
|
||||||
|
</div>
|
||||||
<Button size="small" variant="ghost" onClick={split.onCancel}>
|
<Button size="small" variant="ghost" onClick={split.onCancel}>
|
||||||
{split.cancelLabel ?? "Cancel"}
|
{split.cancelLabel ?? i18n.t("ui.common.cancel")}
|
||||||
</Button>
|
</Button>
|
||||||
<Button size="small" variant="primary" disabled={split.value.trim().length === 0} onClick={submit}>
|
<Button size="small" variant="primary" disabled={split.value.trim().length === 0} onClick={submit}>
|
||||||
{split.submitLabel ?? "Comment"}
|
{split.submitLabel ?? i18n.t("ui.lineComment.submit")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -530,12 +530,12 @@ export const SessionReview = (props: SessionReviewProps) => {
|
|||||||
<Switch>
|
<Switch>
|
||||||
<Match when={isAdded()}>
|
<Match when={isAdded()}>
|
||||||
<span data-slot="session-review-change" data-type="added">
|
<span data-slot="session-review-change" data-type="added">
|
||||||
Added
|
{i18n.t("ui.sessionReview.change.added")}
|
||||||
</span>
|
</span>
|
||||||
</Match>
|
</Match>
|
||||||
<Match when={isDeleted()}>
|
<Match when={isDeleted()}>
|
||||||
<span data-slot="session-review-change" data-type="removed">
|
<span data-slot="session-review-change" data-type="removed">
|
||||||
Removed
|
{i18n.t("ui.sessionReview.change.removed")}
|
||||||
</span>
|
</span>
|
||||||
</Match>
|
</Match>
|
||||||
<Match when={true}>
|
<Match when={true}>
|
||||||
|
|||||||
@@ -4,6 +4,15 @@ export const dict = {
|
|||||||
"ui.sessionReview.diffStyle.split": "Split",
|
"ui.sessionReview.diffStyle.split": "Split",
|
||||||
"ui.sessionReview.expandAll": "Expand all",
|
"ui.sessionReview.expandAll": "Expand all",
|
||||||
"ui.sessionReview.collapseAll": "Collapse all",
|
"ui.sessionReview.collapseAll": "Collapse all",
|
||||||
|
"ui.sessionReview.change.added": "Added",
|
||||||
|
"ui.sessionReview.change.removed": "Removed",
|
||||||
|
|
||||||
|
"ui.lineComment.label.prefix": "Comment on ",
|
||||||
|
"ui.lineComment.label.suffix": "",
|
||||||
|
"ui.lineComment.editorLabel.prefix": "Commenting on ",
|
||||||
|
"ui.lineComment.editorLabel.suffix": "",
|
||||||
|
"ui.lineComment.placeholder": "Add comment",
|
||||||
|
"ui.lineComment.submit": "Comment",
|
||||||
|
|
||||||
"ui.sessionTurn.steps.show": "Show steps",
|
"ui.sessionTurn.steps.show": "Show steps",
|
||||||
"ui.sessionTurn.steps.hide": "Hide steps",
|
"ui.sessionTurn.steps.hide": "Hide steps",
|
||||||
|
|||||||
Reference in New Issue
Block a user