play managed publishing: console plan/verify play-publish-changes, ready-to-publish items in play status, desktop hint

This commit is contained in:
CRTkafa 2026-10-24 11:56:07 +08:00
parent 29a9683ab7
commit 1bb43fd4a0
20 changed files with 184 additions and 9 deletions

View file

@ -154,6 +154,8 @@ export const en = {
'phase.pageUnknown': "Couldn't check the store page",
'phase.pageStale': "couldn't check the store page, as of {when}",
'phase.reviewLive': 'In review (live: {version})',
'roll.publishReady': 'If the release is approved, publish it in Publishing overview ("Publish N changes"). The agent prepares it with `{cmd}`; the final press is for the owner.',
'roll.publishOpen': 'Open Publishing overview',
'phase.reviewManaged': 'In review / ready to publish (managed publishing)',
'phase.rejected': 'Rejected',
'phase.testing': 'Testing',

View file

@ -156,6 +156,8 @@ export const tr: Record<keyof typeof en, string> = {
'phase.pageUnknown': 'Mağaza sayfası kontrol edilemedi',
'phase.pageStale': 'mağaza sayfası kontrol edilemedi, {when} itibarıyla',
'phase.reviewLive': 'İncelemede (yayında: {version})',
'roll.publishReady': 'Sürüm onaylandıysa Yayınlama özetinde yayınlayın ("Publish N changes"). Ajan `{cmd}` ile hazırlar; son basış sahibine aittir.',
'roll.publishOpen': 'Yayınlama özetini aç',
'phase.reviewManaged': 'İncelemede / yayına hazır (yönetilen yayınlama)',
'phase.rejected': 'Reddedildi',
'phase.testing': 'Testte',

View file

@ -11,6 +11,7 @@ import { WriteButton } from '../../ui/WriteButton';
import { type Key, t } from '../../i18n';
import { ago, date, share } from '../../lib/format';
import { type Lane, STAGES, type TestFlightStatus, trainLanes, versionHistory } from '../../lib/model';
import { api } from '../../api';
import { useData, useRead, useWrite } from '../../store';
import { Icon, StoreGlyph } from '../../ui/icons';
import { RolloutBar } from '../../ui/charts';
@ -19,6 +20,8 @@ import { EmptyState, Section, StatusPill, tintStyle, useTint } from '../../ui/ds
import { AppleSubmitCard, PlayProductionCard } from './Submit';
import { useContextMenu } from '../../ui/ContextMenu';
import { releaseMenu } from '../../ui/app-menu';
import { consoleUrl } from '../../../../../cli/lib/console-links';
import { PUBLISH_PLAN_HINT } from '../../../../../cli/lib/play-publish';
import '../../styles/releases.css';
const STAGE_KEY: Record<(typeof STAGES)[number], Key> = { build: 'stage.build', testing: 'stage.testing', review: 'stage.review', live: 'stage.live', rollout: 'stage.rollout' };
@ -92,11 +95,24 @@ function LaneRow({ lane, version, st, app }: { lane: Lane; version: string; st:
)}
</div>
)}
{r && r.store === 'android' && r.managed && r.phase === 'review' && <PublishHint st={st} />}
{r && app.project && <RolloutControls app={app} r={r} />}
</article>
);
}
/** Managed publishing: the approved production release waits in Publishing overview ("Publish N changes"). */
function PublishHint({ st }: { st: AppStatus }) {
const a = st.app?.platforms.android;
const url = consoleUrl('play.publishing', { playDeveloperId: a?.developerId, playAppId: a?.appId });
return (
<div className="roll-ctl" data-hint="publish-changes">
<span className="small muted">{t('roll.publishReady', { cmd: PUBLISH_PLAN_HINT })}</span>
<button className="btn btn-sm" onClick={() => { api.openExternal(url).catch(() => {}); }}><Icon name="external" />{t('roll.publishOpen')}</button>
</div>
);
}
const SHARES = [1, 2, 5, 10, 20, 50];
/** Rollout controls of one store release: Play staged rollout share / halt / resume / complete, iOS phased release