fix(游戏共创): 源码公开确认改回默认勾选(与「允许共创即开放源码」口径一致)
按产品裁定回落默认值:保留主动取消能力与全部知情告知,但确认项**默认已勾选**—— 「允许共创本身就意味着源码开放,不设独立开关」,默认不勾选等于第二个开关,与本面板 自己写着的那句「没有单独的源码可见性开关」自相矛盾。 - `projectBundleConfirmed` 初值 true;每次重新选择授权档位都重置为「非禁止档位即已勾选」, 避免把上一次的取消状态带到新的档位选择上(禁止共创时不显示该确认项,值本身无意义)。 - 告知文案一字不减(整个项目目录原样公开、含文档/截图/设计稿/笔记、只自动排除依赖/版本库/ 构建产物/常见凭据、一经发布不可撤销、无法收回已下载内容)。 - 新增一句提示说明默认值来源:「上面这项默认已勾选(平台按「允许共创即开放源码」的默认帮你 勾上,不是替你做决定——你可以随时取消)。」——避免作者以为平台偷偷替他决定。 - 未勾选时的后果提示保留,仍写清「不勾选则本次不上传工程源码……」。 测试(面板 23 条):默认「禁止共创」无确认项;切到非禁止档位后确认项出现且**已勾选**, 并逐条断言告知文案 + 「默认已勾选/可随时取消」;默认状态提交不携带 `includeProjectBundle` (交给原生按授权执行上传);作者主动取消后提交携带 `includeProjectBundle: false`(这是 「作者能退出」的证据);重新选择档位回到已勾选;切回「禁止共创」确认项消失。
This commit is contained in:
+15
-8
@@ -254,13 +254,14 @@ export function GameDistributionPublishPanel({
|
||||
GAME_DISTRIBUTION_DEFAULT_FORK_AUTHORIZATION,
|
||||
);
|
||||
/**
|
||||
* 作者是否已**主动确认**随本次发布公开整个项目目录(默认不勾选)。
|
||||
* 作者是否确认随本次发布公开整个项目目录(**默认已勾选**,作者可主动取消)。
|
||||
*
|
||||
* 产品口径:授权非「禁止共创」即允许他人改编,但工程源码的拒绝规则是黑名单——作者的
|
||||
* `docs/`、截图、设计稿、笔记等不在任何拒绝集内,会随包原样外发。所以这里不做「默认帮作者
|
||||
* 上传」,而是要求作者确认后才能上传;不确认则作品照常发布,只是退化为「只能被产物级改编」。
|
||||
* 产品口径:选择「允许共创」本身就意味着源码开放,不设独立开关——因此默认值必须与授权语义
|
||||
* 一致(默认勾选)。但工程源包的拒绝规则是黑名单,作者的 `docs/`、截图、设计稿、笔记等会随包
|
||||
* 原样外发,所以知情告知一字不减,并且作者可以随时取消:取消即本次不上传源码,作品照常发布,
|
||||
* 只是退化为「只能被产物级改编」。
|
||||
*/
|
||||
const [projectBundleConfirmed, setProjectBundleConfirmed] = useState(false);
|
||||
const [projectBundleConfirmed, setProjectBundleConfirmed] = useState(true);
|
||||
const [busy, setBusy] = useState(false);
|
||||
const [error, setError] = useState('');
|
||||
const [result, setResult] = useState<GameDistributionPublishResult | null>(
|
||||
@@ -960,7 +961,12 @@ export function GameDistributionPublishPanel({
|
||||
value={value}
|
||||
checked={forkAuthorization === value}
|
||||
disabled={forkAuthorizationLocked}
|
||||
onChange={() => setForkAuthorization(value)}
|
||||
onChange={() => {
|
||||
setForkAuthorization(value);
|
||||
// 每次选择授权档位都回到「默认已勾选」:避免把上一次的取消状态带到
|
||||
// 新的档位选择上(禁止共创时不显示也不上传,值本身无意义)。
|
||||
setProjectBundleConfirmed(value !== 'forbidden');
|
||||
}}
|
||||
/>
|
||||
<span>
|
||||
{GAME_DISTRIBUTION_FORK_AUTHORIZATION_LABELS[value]}
|
||||
@@ -999,8 +1005,9 @@ export function GameDistributionPublishPanel({
|
||||
) : null}
|
||||
{forkAuthorization !== 'forbidden' && !forkAuthorizationLocked ? (
|
||||
<p className="game-distribution-publish-panel__fork-hint">
|
||||
不勾选则本次不上传工程源码:作品仍可正常发布,但他人只能拿到已构建成品试玩与
|
||||
参考,不能直接重新发布。
|
||||
{'上面这项'}
|
||||
<strong>默认已勾选</strong>
|
||||
{'(平台按「允许共创即开放源码」的默认帮你勾上,不是替你做决定——你可以随时取消)。不勾选则本次不上传工程源码:作品仍可正常发布,但他人只能拿到已构建成品试玩与参考,不能直接重新发布。'}
|
||||
</p>
|
||||
) : null}
|
||||
</fieldset>
|
||||
|
||||
@@ -382,7 +382,7 @@ describe('GameDistributionPublishPanel', () => {
|
||||
expect(args?.metadata?.forkAuthorization).toBe('full');
|
||||
});
|
||||
|
||||
test('授权开放后才出现源码公开确认,默认不勾选并如实告知后果', async () => {
|
||||
test('授权开放后确认项出现且默认已勾选,并如实告知后果', async () => {
|
||||
installTauriInvoke(async () => undefined);
|
||||
vi.mocked(publishLocalProjectGame).mockResolvedValue({
|
||||
gameId: 'game_1',
|
||||
@@ -400,8 +400,8 @@ describe('GameDistributionPublishPanel', () => {
|
||||
|
||||
fireEvent.click(screen.getByRole('radio', { name: '允许非商用共创' }));
|
||||
const consent = await screen.findByRole('checkbox');
|
||||
// 知情同意:必须由作者主动确认,默认不勾选。
|
||||
expect(consent).toHaveProperty('checked', false);
|
||||
// 产品口径:允许共创即开放源码,不设独立开关 → 默认已勾选(作者可主动取消)。
|
||||
expect(consent).toHaveProperty('checked', true);
|
||||
// 告知必须如实:整个项目目录会外发、只自动排除少数几类、且不可撤销。
|
||||
expect(screen.getByText(/我已确认项目里没有不愿公开的内容/u)).not.toBeNull();
|
||||
expect(screen.getByText(/整个项目目录/u)).not.toBeNull();
|
||||
@@ -409,7 +409,10 @@ describe('GameDistributionPublishPanel', () => {
|
||||
expect(screen.getByText(/只会自动排除依赖目录、版本库、构建产物与常见凭据文件/u)).not.toBeNull();
|
||||
expect(screen.getByText(/不可撤销/u)).not.toBeNull();
|
||||
expect(screen.getByText(/无法收回别人已经下载的内容/u)).not.toBeNull();
|
||||
// 不勾选的后果也要在发布前就说清楚。
|
||||
// 默认值是平台替你勾上的,这一点要写出来,避免作者以为平台偷偷替他决定。
|
||||
expect(screen.getByText(/默认已勾选/u)).not.toBeNull();
|
||||
expect(screen.getByText(/你可以随时取消/u)).not.toBeNull();
|
||||
// 取消的后果也要在发布前就说清楚。
|
||||
expect(
|
||||
screen.getByText(/不勾选则本次不上传工程源码/u),
|
||||
).not.toBeNull();
|
||||
@@ -418,7 +421,7 @@ describe('GameDistributionPublishPanel', () => {
|
||||
screen.getByText(/没有单独的源码可见性开关/u),
|
||||
).not.toBeNull();
|
||||
|
||||
// 未确认 → 明确告诉原生不要把工程源码交出去(作品照常发布)。
|
||||
// 默认勾选 → 不携带 includeProjectBundle,交给原生按「授权非禁止」执行上传。
|
||||
await selectCover();
|
||||
fireEvent.click(screen.getByRole('button', { name: '发布游戏' }));
|
||||
await waitFor(() =>
|
||||
@@ -426,10 +429,10 @@ describe('GameDistributionPublishPanel', () => {
|
||||
);
|
||||
expect(
|
||||
vi.mocked(publishLocalProjectGame).mock.calls[0]?.[0],
|
||||
).toMatchObject({ includeProjectBundle: false });
|
||||
).not.toHaveProperty('includeProjectBundle');
|
||||
});
|
||||
|
||||
test('确认公开整个项目目录后才上传工程源码', async () => {
|
||||
test('作者主动取消确认后,本次不上传工程源码(作品照常发布)', async () => {
|
||||
installTauriInvoke(async () => undefined);
|
||||
vi.mocked(publishLocalProjectGame).mockResolvedValue({
|
||||
gameId: 'game_1',
|
||||
@@ -445,7 +448,7 @@ describe('GameDistributionPublishPanel', () => {
|
||||
fireEvent.click(screen.getByRole('radio', { name: '允许全开放共创' }));
|
||||
fireEvent.click(await screen.findByRole('checkbox'));
|
||||
await waitFor(() =>
|
||||
expect(screen.queryByRole('checkbox')).toHaveProperty('checked', true),
|
||||
expect(screen.queryByRole('checkbox')).toHaveProperty('checked', false),
|
||||
);
|
||||
|
||||
await selectCover();
|
||||
@@ -453,10 +456,33 @@ describe('GameDistributionPublishPanel', () => {
|
||||
await waitFor(() =>
|
||||
expect(publishLocalProjectGame).toHaveBeenCalledTimes(1),
|
||||
);
|
||||
// 已确认时不带 includeProjectBundle:由原生按「授权非禁止」执行上传。
|
||||
// 这是「作者能退出」的证据:显式 false 表示源码不外发。
|
||||
expect(
|
||||
vi.mocked(publishLocalProjectGame).mock.calls[0]?.[0],
|
||||
).not.toHaveProperty('includeProjectBundle');
|
||||
).toMatchObject({ includeProjectBundle: false });
|
||||
});
|
||||
|
||||
test('重新选择授权档位会回到「默认已勾选」,切回禁止共创则不出现确认项', async () => {
|
||||
installTauriInvoke(async () => undefined);
|
||||
renderPanel();
|
||||
|
||||
// 取消后换一个档位:不应把上一次的取消带过去。
|
||||
fireEvent.click(screen.getByRole('radio', { name: '允许非商用共创' }));
|
||||
fireEvent.click(await screen.findByRole('checkbox'));
|
||||
await waitFor(() =>
|
||||
expect(screen.queryByRole('checkbox')).toHaveProperty('checked', false),
|
||||
);
|
||||
fireEvent.click(screen.getByRole('radio', { name: '允许全开放共创' }));
|
||||
await waitFor(() =>
|
||||
expect(screen.queryByRole('checkbox')).toHaveProperty('checked', true),
|
||||
);
|
||||
|
||||
// 切回「禁止共创」:确认项消失(源码谁也取不走,不需要这个动作)。
|
||||
fireEvent.click(screen.getByRole('radio', { name: '禁止共创' }));
|
||||
await waitFor(() => expect(screen.queryByRole('checkbox')).toBeNull());
|
||||
expect(
|
||||
screen.getByRole('radio', { name: '禁止共创' }),
|
||||
).toHaveProperty('checked', true);
|
||||
});
|
||||
|
||||
test('工程源包未上传时成功页如实提示只能产物级改编', async () => {
|
||||
|
||||
Reference in New Issue
Block a user