Merge pull request 'Feat/发布页引导用户使用客户端' (#557) from feat/guide-user-use-client into master
Project CI / AI game creator shell Rust lane 2/2 (push) Failing after 1m14s
Project CI / AI game creator shell Rust lane 1/2 (push) Failing after 1m14s
Project CI / AI game creator shell Rust smoke (push) Failing after 1m13s
Project CI / AI game creator shell Rust crates (push) Successful in 1m37s
Project CI / Frontend tests (push) Successful in 3m37s
Project CI / Repository checks (push) Successful in 4m18s
Project CI / AI game creator shell web tests (push) Successful in 2m24s
Project CI / Backend tests (push) Successful in 6m42s
Project CI / Native shell tests (push) Successful in 7m35s
Project CI / AI game creator shell Rust lane 2/2 (push) Failing after 1m14s
Project CI / AI game creator shell Rust lane 1/2 (push) Failing after 1m14s
Project CI / AI game creator shell Rust smoke (push) Failing after 1m13s
Project CI / AI game creator shell Rust crates (push) Successful in 1m37s
Project CI / Frontend tests (push) Successful in 3m37s
Project CI / Repository checks (push) Successful in 4m18s
Project CI / AI game creator shell web tests (push) Successful in 2m24s
Project CI / Backend tests (push) Successful in 6m42s
Project CI / Native shell tests (push) Successful in 7m35s
Reviewed-on: #557
This commit was merged in pull request #557.
This commit is contained in:
@@ -1,4 +1,8 @@
|
||||
import { getPlatformActionButtonClassName } from '@genarrative/shared/components';
|
||||
import {
|
||||
getPlatformActionButtonClassName,
|
||||
type PlatformActionButtonSize,
|
||||
type PlatformActionButtonTone,
|
||||
} from '@genarrative/shared/components';
|
||||
import { Download, Monitor } from 'lucide-react';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
@@ -10,6 +14,16 @@ import { UnifiedModal } from '../common/UnifiedModal';
|
||||
|
||||
const DOWNLOAD_ERROR = '暂时无法获取最新版本,请稍后重试';
|
||||
|
||||
type ClientDownloadEntryProps = {
|
||||
/** 按钮文案,默认「下载客户端」。 */
|
||||
label?: string;
|
||||
tone?: PlatformActionButtonTone;
|
||||
size?: PlatformActionButtonSize;
|
||||
/** 窄屏只留图标:平台顶栏默认开启,页面级引导入口传 false 保留完整文案。 */
|
||||
iconOnlyOnNarrowScreens?: boolean;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
type DownloadState =
|
||||
| { status: 'loading' }
|
||||
| { status: 'ready'; release: ClientDownloadResponse }
|
||||
@@ -22,7 +36,13 @@ function downloadLabel(download: ClientDownloadResponse['downloads'][number]) {
|
||||
return `macOS(${download.architecture === 'aarch64' ? 'Apple Silicon' : 'Intel'})`;
|
||||
}
|
||||
|
||||
export function ClientDownloadEntry() {
|
||||
export function ClientDownloadEntry({
|
||||
label = '下载客户端',
|
||||
tone = 'secondary',
|
||||
size = 'sm',
|
||||
iconOnlyOnNarrowScreens = true,
|
||||
className,
|
||||
}: ClientDownloadEntryProps = {}) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [attempt, setAttempt] = useState(0);
|
||||
const [state, setState] = useState<DownloadState>({ status: 'loading' });
|
||||
@@ -72,19 +92,31 @@ export function ClientDownloadEntry() {
|
||||
return (
|
||||
<>
|
||||
<PlatformActionButton
|
||||
tone="secondary"
|
||||
size="sm"
|
||||
tone={tone}
|
||||
size={size}
|
||||
shape="pill"
|
||||
aria-label="下载客户端"
|
||||
title="下载客户端"
|
||||
className="min-h-11 shrink-0 gap-0 whitespace-nowrap max-sm:h-11 max-sm:w-11 max-sm:px-0 sm:gap-2 sm:px-4"
|
||||
aria-label={label}
|
||||
title={label}
|
||||
className={[
|
||||
'shrink-0 whitespace-nowrap',
|
||||
iconOnlyOnNarrowScreens
|
||||
? 'min-h-11 gap-0 max-sm:h-11 max-sm:w-11 max-sm:px-0 sm:gap-2 sm:px-4'
|
||||
: 'gap-2',
|
||||
className,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(' ')}
|
||||
onClick={() => {
|
||||
setState({ status: 'loading' });
|
||||
setOpen(true);
|
||||
}}
|
||||
>
|
||||
<Download className="h-4 w-4 shrink-0" aria-hidden="true" />
|
||||
<span className="hidden sm:inline">下载客户端</span>
|
||||
<span
|
||||
className={iconOnlyOnNarrowScreens ? 'hidden sm:inline' : undefined}
|
||||
>
|
||||
{label}
|
||||
</span>
|
||||
</PlatformActionButton>
|
||||
<UnifiedModal
|
||||
open={open}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import type { HTMLAttributes } from 'react';
|
||||
|
||||
import { ClientDownloadEntry } from '../creation-home/ClientDownloadEntry';
|
||||
|
||||
type GamePublishClientGuideProps = HTMLAttributes<HTMLElement>;
|
||||
|
||||
/** 悬浮引导卡片:把还没有游戏包的作者引到客户端。 */
|
||||
export function GamePublishClientGuide({
|
||||
className,
|
||||
...props
|
||||
}: GamePublishClientGuideProps) {
|
||||
return (
|
||||
<section
|
||||
className={`flex w-fit max-w-full flex-none flex-col items-center gap-3
|
||||
rounded-2xl border px-[1.15rem] py-[0.9rem] text-center
|
||||
[background:linear-gradient(135deg,color-mix(in_srgb,var(--platform-action-accent,#c7653d)_11%,var(--platform-panel-fill))_0%,color-mix(in_srgb,var(--platform-action-accent,#c7653d)_4%,var(--platform-panel-fill))_100%)]
|
||||
border-[color-mix(in_srgb,var(--platform-action-accent,#c7653d)_26%,transparent)]
|
||||
[box-shadow:0_0.55rem_1.1rem_color-mix(in_srgb,var(--platform-action-accent,#c7653d)_12%,transparent)]
|
||||
${className ?? ''}`}
|
||||
{...props}
|
||||
>
|
||||
<strong className="text-[0.82rem] text-(--platform-text-strong)">
|
||||
还没有游戏包?
|
||||
</strong>
|
||||
<ClientDownloadEntry
|
||||
label="下载客户端制作游戏"
|
||||
tone="accentSoft"
|
||||
size="sm"
|
||||
iconOnlyOnNarrowScreens={false}
|
||||
/>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export default GamePublishClientGuide;
|
||||
@@ -29,6 +29,7 @@ import {
|
||||
resolveGamePublishImagePreview,
|
||||
uploadGamePublishImageAsset,
|
||||
} from './gamePublishAssets';
|
||||
import { GamePublishClientGuide } from './GamePublishClientGuide';
|
||||
import {
|
||||
clearPublishDraft,
|
||||
type GamePublishDraft,
|
||||
@@ -711,12 +712,12 @@ export function GamePublishPage({
|
||||
<button type="button" className="game-back-button" onClick={onBack}>
|
||||
<ArrowLeft /> 返回
|
||||
</button>
|
||||
<div className="game-toolbar">
|
||||
<div className="game-toolbar__title">
|
||||
<div className="game-toolbar [flex-wrap:nowrap] max-[720px]:[flex-wrap:wrap]">
|
||||
<div className="game-toolbar__title [min-width:0]">
|
||||
<span className="game-eyebrow">
|
||||
{updateGameId ? '发布新版本' : '发布游戏'}
|
||||
</span>
|
||||
<h2>
|
||||
<h2 className="[white-space:nowrap] max-[720px]:[white-space:normal]">
|
||||
{updateGameId
|
||||
? updateContext
|
||||
? `为《${updateContext.title}》发布 v${updateContext.versionNumber + 1}`
|
||||
@@ -724,6 +725,9 @@ export function GamePublishPage({
|
||||
: '上传可在线游玩的网页游戏'}
|
||||
</h2>
|
||||
</div>
|
||||
{!updateGameId ? (
|
||||
<GamePublishClientGuide className="ml-auto max-[720px]:ml-0" />
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
{error ? (
|
||||
|
||||
Reference in New Issue
Block a user