fix(quota): remove extra reset restrictions while preserving confirmation

- Allow resets when applicable credits are zero or a previous reset failed
- Remove applicable-credit details from the confirmation and obsolete tooltips
- Keep the existing in-app dialog and require explicit confirmation before submitting
- Update regression tests for cancellation, confirmation, and retries
This commit is contained in:
lzt404 committed 2026-09-09 12:13:57 +08:00
1 parent 5548324c8f
commit 805e2aece0
7 files changed
+54 -29

No files matched your search

-3
View File
@@ -195,10 +195,7 @@ export const jaOverrides = {
'quota.service.xaiPaidHealth': '有料 API の会話が利用可能です。xAI は現在、この OAuth 認証情報の総クォータを提供していません。',
'quota.service.xaiPaidQuotaUnavailable': 'このアカウントの残りクォータは提供されていません。',
'quota.confirm.button': 'リセットを実行',
'quota.confirm.applicableLabel': '現在適用可能な回数',
'quota.resetting': 'リセットを送信してクォータを更新中…',
'quota.resetNotApplicable': '現在適用可能なリセット回数がありません。クォータを更新して確認してください',
'quota.resetCheckFirst': '前回の結果が未確認です。重複リセットを避けるため、先にクォータを更新してください',
'quota.resetResult.submitted': 'リセット要求を送信し、クォータを再取得しました。カードの最新クォータを確認してください。',
'quota.resetResult.refreshFailed': 'リセット要求は送信済みですが、クォータの更新に失敗しました:{error}。再消費を避けるため、先にクォータを更新してください。',
'quota.resetResult.failed': 'リセットの成功を確認できませんでした:{error}。再試行する前にクォータを更新してください。',
-3
View File
@@ -182,10 +182,7 @@ export const en: Record<MessageKey, string> = {
'quota.service.xaiPaidHealth': 'Paid API chat is available. xAI does not currently provide total quota data for this OAuth credential.',
'quota.service.xaiPaidQuotaUnavailable': 'Remaining quota is not provided for this account.',
'quota.confirm.button': 'Confirm Reset',
'quota.confirm.applicableLabel': 'Currently applicable resets',
'quota.resetting': 'Submitting reset and refreshing quota…',
'quota.resetNotApplicable': 'No reset credits currently apply. Refresh quota before trying again',
'quota.resetCheckFirst': 'The previous result is unconfirmed. Refresh quota first to avoid another reset',
'quota.resetResult.submitted': 'The reset request was submitted and quota was refreshed. Check the latest quota on this card.',
'quota.resetResult.refreshFailed': 'The reset request was submitted, but refreshing quota failed: {error}. Refresh quota first to avoid consuming another reset credit.',
'quota.resetResult.failed': 'Could not confirm the reset: {error}. Refresh quota before deciding whether to retry.',
-3
View File
@@ -181,10 +181,7 @@ export const zhCN = {
'quota.service.xaiPaidHealth': '付费 API 对话可用。xAI 暂不为此 OAuth 凭证提供额度总量数据。',
'quota.service.xaiPaidQuotaUnavailable': '此账号不提供剩余额度。',
'quota.confirm.button': '确认重置',
'quota.confirm.applicableLabel': '当前适用次数',
'quota.resetting': '正在提交重置并刷新额度…',
'quota.resetNotApplicable': '当前没有适用的重置次数,请刷新额度后再确认',
'quota.resetCheckFirst': '上次操作结果尚未确认,请先刷新额度,避免重复重置',
'quota.resetResult.submitted': '重置请求已提交,额度已重新获取。请查看卡片中的最新额度。',
'quota.resetResult.refreshFailed': '重置请求已提交,但额度刷新失败:{error}。请先刷新查询,避免重复消耗重置机会。',
'quota.resetResult.failed': '无法确认重置成功:{error}。请先刷新额度,再决定是否重试。',
+1 -2
View File
@@ -102,7 +102,6 @@ export function QuotaPage() {
confirmText: t('quota.confirm.button'),
details: [
{ label: t('quota.resetCredits'), value: String(quota.resetCredits ?? '—') },
{ label: t('quota.confirm.applicableLabel'), value: String(quota.resetCreditsApplicable ?? '—') },
{ label: t('quota.earliestExpiry'), value: formatQuotaTimestamp(quota.resetCreditsEarliestExpiry, locale) },
],
warning: t('quota.confirm.warning'),
@@ -198,7 +197,7 @@ export function QuotaCard({ file, quota, onRefresh, onReset }: { file: AuthFile;
<div className="real-quota-card-header">
<div><strong title={name}>{name}</strong><span>{provider ? providerMeta[provider].label : t('quota.unknownProvider')}{quota.plan ? ' · ' + quota.plan : ''}</span></div>
<div className="quota-card-actions">
{onReset && (quota.resetCredits ?? 0) > 0 ? <button type="button" className="secondary-button compact-button" onClick={onReset} disabled={!canResetCodexQuota(file, quota)} title={quota.resetCreditsApplicable === 0 ? t('quota.resetNotApplicable') : quota.actionResult?.action === 'reset' && quota.actionResult.status !== 'success' ? t('quota.resetCheckFirst') : t('quota.reset')}>{t('quota.reset')}</button> : null}
{onReset && (quota.resetCredits ?? 0) > 0 ? <button type="button" className="secondary-button compact-button" onClick={onReset} disabled={!canResetCodexQuota(file, quota)} title={t('quota.reset')}>{t('quota.reset')}</button> : null}
<button type="button" className="icon-button quiet" onClick={onRefresh} disabled={disabled || quota.status === 'loading'} title={disabled ? t('quota.fileDisabled') : t('quota.refresh')}><RefreshCw size={16} className={quota.status === 'loading' ? 'spin' : ''} /></button>
</div>
</div>
+2 -4
View File
@@ -16,10 +16,8 @@ type QuotaActionOutcome = 'cancelled' | 'success' | 'refresh-error' | 'error';
export const canResetCodexQuota = (file: AuthFile, quota: QuotaState): boolean =>
providerForFile(file) === 'codex'
&& !readBoolean(file, 'disabled')
&& quota.status === 'success'
&& (quota.resetCredits ?? 0) > 0
&& quota.resetCreditsApplicable !== 0
&& !(quota.actionResult?.action === 'reset' && quota.actionResult.status !== 'success');
&& quota.status !== 'loading'
&& (quota.resetCredits ?? 0) > 0;
async function runConfirmedQuotaAction(
file: AuthFile,