mirror of
https://gitee.com/zhangsken/opencode.git
synced 2026-10-16 02:24:10 +08:00
feat(app): copy version from about settings
This commit is contained in:
@@ -1151,6 +1151,7 @@ export const dict = {
|
|||||||
"settings.tab.about": "About",
|
"settings.tab.about": "About",
|
||||||
"settings.about.version": "Version {{version}}",
|
"settings.about.version": "Version {{version}}",
|
||||||
"settings.about.devVersion": "development",
|
"settings.about.devVersion": "development",
|
||||||
|
"settings.about.copyVersionFailed": "Failed to copy version",
|
||||||
"settings.about.license": "Released under the MIT License",
|
"settings.about.license": "Released under the MIT License",
|
||||||
"settings.about.writtenBy": "Written by",
|
"settings.about.writtenBy": "Written by",
|
||||||
"settings.about.illustratedBy": "Illustrated by",
|
"settings.about.illustratedBy": "Illustrated by",
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
import { createResource } from "solid-js"
|
import { Tooltip } from "@opencode/ui/tooltip"
|
||||||
|
import { createEffect, createResource, onCleanup } from "solid-js"
|
||||||
|
import { createStore } from "solid-js/store"
|
||||||
import { useLanguage } from "@/runtime/i18n/language"
|
import { useLanguage } from "@/runtime/i18n/language"
|
||||||
import { usePlatform } from "@/runtime/platform/platform"
|
import { usePlatform } from "@/runtime/platform/platform"
|
||||||
import { ExternalLink } from "@/runtime/platform/external-link"
|
import { ExternalLink } from "@/runtime/platform/external-link"
|
||||||
|
import { showToast } from "@/shell/notifications/toast"
|
||||||
import legal from "./legal.svg"
|
import legal from "./legal.svg"
|
||||||
import anomalyBrush from "./anomaly-brush.svg"
|
import anomalyBrush from "./anomaly-brush.svg"
|
||||||
import { AnimatedWordmark } from "./animated-wordmark"
|
import { AnimatedWordmark } from "./animated-wordmark"
|
||||||
@@ -30,11 +33,36 @@ const illustrators = ["usrnk1", "ludvigrask_", "arvsrn", "iamdavidhill"] as cons
|
|||||||
export function SettingsAbout(props: { active: boolean }) {
|
export function SettingsAbout(props: { active: boolean }) {
|
||||||
const language = useLanguage()
|
const language = useLanguage()
|
||||||
const platform = usePlatform()
|
const platform = usePlatform()
|
||||||
|
const [copy, setCopy] = createStore({ pending: false, copied: false, forceCopied: false })
|
||||||
|
const version = () => platform.version ?? language.t("settings.about.devVersion")
|
||||||
|
const versionLabel = () => language.t("settings.about.version", { version: version() })
|
||||||
const [otherContributors] = createResource(
|
const [otherContributors] = createResource(
|
||||||
() => props.active || undefined,
|
() => props.active || undefined,
|
||||||
() => loadOtherContributorCount(platform.fetch ?? fetch),
|
() => loadOtherContributorCount(platform.fetch ?? fetch),
|
||||||
{ initialValue: FALLBACK_OTHER_CONTRIBUTORS },
|
{ initialValue: FALLBACK_OTHER_CONTRIBUTORS },
|
||||||
)
|
)
|
||||||
|
createEffect(() => {
|
||||||
|
if (!copy.copied) return
|
||||||
|
const close = setTimeout(() => setCopy("forceCopied", false), 2000)
|
||||||
|
const reset = setTimeout(() => setCopy("copied", false), 2120)
|
||||||
|
onCleanup(() => {
|
||||||
|
clearTimeout(close)
|
||||||
|
clearTimeout(reset)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
const copyVersion = async () => {
|
||||||
|
if (copy.pending) return
|
||||||
|
setCopy({ pending: true, copied: false, forceCopied: false })
|
||||||
|
await (platform.writeClipboardText?.(versionLabel()) ?? navigator.clipboard.writeText(versionLabel()))
|
||||||
|
.then(() => setCopy({ copied: true, forceCopied: true }))
|
||||||
|
.catch(() =>
|
||||||
|
showToast({
|
||||||
|
variant: "error",
|
||||||
|
title: language.t("settings.about.copyVersionFailed"),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.finally(() => setCopy("pending", false))
|
||||||
|
}
|
||||||
const credit = (name: string) => (
|
const credit = (name: string) => (
|
||||||
<bdi dir="ltr">
|
<bdi dir="ltr">
|
||||||
<ExternalLink href={profile(name)}>{name}</ExternalLink>
|
<ExternalLink href={profile(name)}>{name}</ExternalLink>
|
||||||
@@ -52,11 +80,27 @@ export function SettingsAbout(props: { active: boolean }) {
|
|||||||
return (
|
return (
|
||||||
<div class="settings-about-content">
|
<div class="settings-about-content">
|
||||||
<div class="settings-about-intro">
|
<div class="settings-about-intro">
|
||||||
<p>
|
<div class="settings-about-version-line">
|
||||||
{language.t("settings.about.version", {
|
<Tooltip
|
||||||
version: platform.version ?? language.t("settings.about.devVersion"),
|
value={language.t(copy.copied ? "common.copied" : "ui.message.copy")}
|
||||||
})}
|
placement="top"
|
||||||
</p>
|
forceOpen={copy.forceCopied ? true : undefined}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="settings-about-version"
|
||||||
|
disabled={copy.pending}
|
||||||
|
aria-label={language.t(copy.copied ? "common.copied" : "ui.message.copy")}
|
||||||
|
onClick={() => void copyVersion()}
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
{language.rich("settings.about.version", {
|
||||||
|
version: <bdi dir="ltr">{version()}</bdi>,
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
<p>{language.t("settings.about.license")}</p>
|
<p>{language.t("settings.about.license")}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -233,6 +233,54 @@
|
|||||||
gap: 14px;
|
gap: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.settings-about-version-line {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-about-version {
|
||||||
|
position: relative;
|
||||||
|
isolation: isolate;
|
||||||
|
display: inline-flex;
|
||||||
|
min-height: 24px;
|
||||||
|
align-items: center;
|
||||||
|
margin-block: -2px;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: transparent;
|
||||||
|
color: inherit;
|
||||||
|
font: inherit;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: color 120ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-about-version::before {
|
||||||
|
position: absolute;
|
||||||
|
z-index: -1;
|
||||||
|
inset-block: 0;
|
||||||
|
inset-inline: -6px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: transparent;
|
||||||
|
content: "";
|
||||||
|
transition: background-color 120ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-about-version:hover,
|
||||||
|
.settings-about-version:focus-visible {
|
||||||
|
color: var(--v2-text-text-base);
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-about-version:hover::before,
|
||||||
|
.settings-about-version:focus-visible::before {
|
||||||
|
background: var(--v2-background-bg-layer-02);
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-about-version:disabled {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
.settings-about-credits,
|
.settings-about-credits,
|
||||||
.settings-about-publication,
|
.settings-about-publication,
|
||||||
.settings-about-details {
|
.settings-about-details {
|
||||||
|
|||||||
Reference in New Issue
Block a user