desktop reads everything by itself: one background read scheduler (4 per store, starts spaced per account, App Store Connect X-Rate-Limit slows it below 20 % and pauses at 100 left, backoff with jitter on 429 / RESOURCE_EXHAUSTED, visible app first, one read per key), per-method TTLs over the saved reads, Settings auto-read (on) and interval (15 min, paused while hidden), Refresh all, a refresh icon and 'read 3 min ago' / 'couldn't refresh' per card, writes invalidate, status line with progress and quota; quota reaches the window through ToolResult.quota (cli/lib/quota.ts); Health top issues open with versions, sample stack (health --issue / --signature, read health_issue), Open in Play Console, Copy for AI and likely-cause hints (cli/lib/crash-hints.ts); tests/scheduler.test.ts, tests/quota-crash-hints.test.ts, boot check auto-read case
This commit is contained in:
parent
89256f1e80
commit
0fb4ce0001
46 changed files with 1531 additions and 141 deletions
|
|
@ -4,11 +4,11 @@ import { Fragment, useState } from 'react';
|
|||
import type { UnifiedApp } from '../../lib/identity';
|
||||
import { WriteButton } from '../../ui/WriteButton';
|
||||
import { t } from '../../i18n';
|
||||
import { ago, date, num } from '../../lib/format';
|
||||
import { date, num } from '../../lib/format';
|
||||
import type { TestFlightStatus, TfBuild, TfGroup, Tone } from '../../lib/model';
|
||||
import { useData, useRead, useWrite } from '../../store';
|
||||
import { Icon } from '../../ui/icons';
|
||||
import { Card, Chip, Empty, Notice, Skeleton } from '../../ui/kit';
|
||||
import { Card, Chip, Empty, Notice, ReadControl, Skeleton } from '../../ui/kit';
|
||||
|
||||
/** Beta state word -> tone and a short label. */
|
||||
export function betaState(s: string | null): { tone: Tone; text: string } {
|
||||
|
|
@ -96,10 +96,9 @@ export function TestFlightTab({ app }: { app: UnifiedApp }) {
|
|||
return (
|
||||
<>
|
||||
<div className="row between">
|
||||
<span className="stamp"><Icon name="clock" />{r.fromCache ? t('common.cachedFrom', { when: ago(r.at) }) : t('common.readWhen', { when: ago(r.at) })}</span>
|
||||
<button className="btn btn-sm" onClick={r.refresh} disabled={r.loading}><Icon name="refresh" />{t('action.refresh')}</button>
|
||||
<span />
|
||||
<ReadControl r={r} />
|
||||
</div>
|
||||
{r.error && <Notice tone="warn">{t('common.readFailedKeep', { error: r.error })}</Notice>}
|
||||
{s.missingGroups.length > 0 && (
|
||||
<Notice tone="warn" action={writable ? <WriteButton run={w} icon="plus" w={{ method: 'apple.testflight_groups', args: {}, title: t('tf.groupsSync'), done: t('tf.groupsSynced'), after: r.refresh }} hint={t('tf.groupsSyncHint')}>{t('tf.groupsSync')}</WriteButton> : undefined}>
|
||||
{t('tf.missingGroups', { groups: s.missingGroups.join(', ') })}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue