desktop dev update channel: every push to main builds dev bundles (<next patch>-dev.<UTC>), the VDS signs and publishes dev/latest.json (newest 5); app channel setting stable|dev, background updater at start / 15 min / resume / channel switch, deferred while in use, no downgrade, autostart rewritten on every start, card shows version and channel

This commit is contained in:
CRTkafa 2026-10-23 23:14:08 +08:00
parent 4dff7d9b2e
commit 39b2f73ad7
25 changed files with 732 additions and 47 deletions

View file

@ -126,6 +126,7 @@ export function Card({ host, lang }: { host: CardHost; lang: CardLang }) {
</Section>
)}
</div>
{s?.build && <footer className="tc-foot" data-testid="card-build">{T('build', { version: s.build.version, channel: T(s.build.channel === 'dev' ? 'chDev' : s.build.channel === 'beta' ? 'chBeta' : 'chStable') })}</footer>}
</div>
);
}

View file

@ -51,7 +51,7 @@ export function TrayCardBridge() {
asc: ios ? ascUrl(ios.ascAppId) : null, play: st?.app?.platforms.android || a.android ? playUrlFor(d, a) : null,
};
});
return cardSnapshot(inputs, { at: d.live?.value.at ?? d.portfolio?.at ?? null, busy: all.busy, muted: d.muteUntil > Date.now() });
return cardSnapshot(inputs, { at: d.live?.value.at ?? d.portfolio?.at ?? null, busy: all.busy, muted: d.muteUntil > Date.now(), build: d.info ? { version: d.info.version, channel: d.settings.channel } : null });
}, [visible, d, extra, all.busy]);
const last = useRef('');

View file

@ -56,3 +56,4 @@ body.tc-page.tc-in .tc { animation: tc-in 120ms ease-out; }
.tc-stars { display: inline-flex; gap: 1px; align-items: center; color: var(--warn-solid); }
.tc-rname { font-weight: var(--ds-w-strong); font-size: var(--ds-t-meta); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tc-rtext { grid-column: 1 / -1; font-size: var(--ds-t-meta); color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tc-foot { padding: 6px 12px 8px; color: var(--muted); font-size: var(--ds-t-micro); border-top: 1px solid var(--ds-stroke); font-variant-numeric: tabular-nums; }

View file

@ -23,6 +23,8 @@ export interface CardSnapshot {
health: CardHealth[];
/** Apps with something on the card, for the quick actions (console links). */
links: CardApp[];
/** This app's version and update channel (Settings > Updates), shown at the card's foot. */
build?: { version: string; channel: string } | null;
}
export interface CardInput {
@ -48,7 +50,7 @@ export function healthAlerts(h: HealthSnapshot | null | undefined): ('crash' | '
return out;
}
export function cardSnapshot(apps: CardInput[], o: { at: string | null; busy: boolean; muted: boolean; now?: number }): CardSnapshot {
export function cardSnapshot(apps: CardInput[], o: { at: string | null; busy: boolean; muted: boolean; now?: number; build?: { version: string; channel: string } | null }): CardSnapshot {
const now = o.now ?? Date.now();
const rejections: CardRejection[] = [], releases: CardRelease[] = [], low: CardLowReview[] = [], health: CardHealth[] = [];
const touched = new Set<string>();
@ -82,5 +84,6 @@ export function cardSnapshot(apps: CardInput[], o: { at: string | null; busy: bo
rejections: rejections.slice(0, MAX_ROWS), releases: releases.slice(0, MAX_ROWS),
reviews: { recent, low: low.slice(0, MAX_LOW) }, health: health.slice(0, MAX_ROWS),
links: apps.filter(a => touched.has(a.key)).map(a => ({ key: a.key, name: a.name, hue: a.hue, asc: a.asc ?? null, play: a.play ?? null })),
build: o.build ?? null,
};
}

View file

@ -28,6 +28,10 @@ export const en = {
refresh: 'Refresh',
refreshing: 'Reading…',
openMain: 'Open storebound',
build: 'storebound {version} · {channel} channel',
chStable: 'stable',
chDev: 'dev',
chBeta: 'beta',
more: 'More',
mute: 'Mute notifications for 1 hour',
unmute: 'Unmute notifications',
@ -70,6 +74,10 @@ export const tr: Record<CardKey, string> = {
refresh: 'Yenile',
refreshing: 'Okunuyor…',
openMain: 'storebound\'u aç',
build: 'storebound {version} · {channel} kanalı',
chStable: 'kararlı',
chDev: 'geliştirme',
chBeta: 'beta',
more: 'Diğer',
mute: 'Bildirimleri 1 saat sustur',
unmute: 'Bildirimleri aç',