diff --git a/packages/app/src/components/session/session-header.tsx b/packages/app/src/components/session/session-header.tsx index bb4d9812503..31ac6c16ba0 100644 --- a/packages/app/src/components/session/session-header.tsx +++ b/packages/app/src/components/session/session-header.tsx @@ -343,6 +343,22 @@ export function SessionHeader() { .catch((err: unknown) => showRequestError(language, err)) } + const copySessionID = () => { + const id = params.id + if (!id) return + navigator.clipboard + .writeText(id) + .then(() => { + showToast({ + variant: "success", + icon: "circle-check", + title: language.t("session.share.copy.copied"), + description: id, + }) + }) + .catch((err: unknown) => showRequestError(language, err)) + } + const share = useSessionShare({ globalSDK, currentSession, @@ -407,6 +423,20 @@ export function SessionHeader() { {language.t("session.header.open.copyPath")} + +
+ +
} > @@ -497,6 +527,20 @@ export function SessionHeader() { {language.t("session.header.open.copyPath")} + { + setMenu("open", false) + copySessionID() + }} + disabled={!params.id} + > +
+ +
+ + {language.t("session.header.open.copySessionID")} + +
diff --git a/packages/app/src/i18n/en.ts b/packages/app/src/i18n/en.ts index 7e95fd739df..4556277c4bb 100644 --- a/packages/app/src/i18n/en.ts +++ b/packages/app/src/i18n/en.ts @@ -541,6 +541,7 @@ export const dict = { "session.header.open.ariaLabel": "Open in {{app}}", "session.header.open.menu": "Open options", "session.header.open.copyPath": "Copy path", + "session.header.open.copySessionID": "Copy session ID", "status.popover.trigger": "Status", "status.popover.ariaLabel": "Server configurations", diff --git a/packages/app/src/pages/session/use-session-commands.tsx b/packages/app/src/pages/session/use-session-commands.tsx index b8ddeda8235..531c4636e49 100644 --- a/packages/app/src/pages/session/use-session-commands.tsx +++ b/packages/app/src/pages/session/use-session-commands.tsx @@ -79,6 +79,30 @@ export const useSessionCommands = (actions: SessionCommandContext) => { return lines.slice(0, 2).join("\n") } + const write = (value: string) => { + const body = typeof document === "undefined" ? undefined : document.body + if (body) { + const textarea = document.createElement("textarea") + textarea.value = value + textarea.setAttribute("readonly", "") + textarea.style.position = "fixed" + textarea.style.opacity = "0" + textarea.style.pointerEvents = "none" + body.appendChild(textarea) + textarea.select() + const copied = document.execCommand("copy") + body.removeChild(textarea) + if (copied) return Promise.resolve(true) + } + + const clipboard = typeof navigator === "undefined" ? undefined : navigator.clipboard + if (!clipboard?.writeText) return Promise.resolve(false) + return clipboard.writeText(value).then( + () => true, + () => false, + ) + } + const addSelectionToContext = (path: string, selection: FileSelection) => { const preview = selectionPreview(path, selection) prompt.context.add({ type: "file", path, selection, preview }) @@ -395,30 +419,6 @@ export const useSessionCommands = (actions: SessionCommandContext) => { onSelect: async () => { if (!params.id) return - const write = (value: string) => { - const body = typeof document === "undefined" ? undefined : document.body - if (body) { - const textarea = document.createElement("textarea") - textarea.value = value - textarea.setAttribute("readonly", "") - textarea.style.position = "fixed" - textarea.style.opacity = "0" - textarea.style.pointerEvents = "none" - body.appendChild(textarea) - textarea.select() - const copied = document.execCommand("copy") - body.removeChild(textarea) - if (copied) return Promise.resolve(true) - } - - const clipboard = typeof navigator === "undefined" ? undefined : navigator.clipboard - if (!clipboard?.writeText) return Promise.resolve(false) - return clipboard.writeText(value).then( - () => true, - () => false, - ) - } - const copy = async (url: string, existing: boolean) => { const ok = await write(url) if (!ok) {