feat(desktop/account-health): mark freshly bound accounts as live
Bind callbacks now stamp the runtime account as health=live with a fresh verified_at and seed the health record via markTrackedAccountBound, so the UI doesn't show a just-bound account as 尚未校验 while waiting for the next probe. Also let force probes bypass the cached-result short-circuit so the manual 重新校验 button always re-runs the probe. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -402,7 +402,7 @@ function canUseCachedProbe(
|
|||||||
now = Date.now(),
|
now = Date.now(),
|
||||||
): boolean {
|
): boolean {
|
||||||
if (options.force) {
|
if (options.force) {
|
||||||
return Boolean(record.lastProbeAt && now - record.lastProbeAt < MANUAL_PROBE_MIN_INTERVAL_MS);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -675,6 +675,36 @@ export function forgetTrackedAccountHealth(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function markTrackedAccountBound(
|
||||||
|
account: PublishAccountIdentity,
|
||||||
|
profile: AccountHealthProfile | null = null,
|
||||||
|
): AccountHealthSnapshot {
|
||||||
|
const record = ensureRecord(account);
|
||||||
|
const previousSignature = snapshotSignature(record);
|
||||||
|
const now = Date.now();
|
||||||
|
const resolvedProfile: AccountHealthProfile = {
|
||||||
|
displayName: profile?.displayName ?? account.displayName ?? null,
|
||||||
|
avatarUrl: profile?.avatarUrl ?? null,
|
||||||
|
subjectUid: profile?.subjectUid ?? account.platformUid ?? null,
|
||||||
|
};
|
||||||
|
|
||||||
|
trackedAccounts.set(account.id, account);
|
||||||
|
record.platform = account.platform;
|
||||||
|
record.authState = "active";
|
||||||
|
record.probeState = "idle";
|
||||||
|
record.authReason = "bind_success";
|
||||||
|
record.lastVerifiedAt = now;
|
||||||
|
record.lastProbeAt = now;
|
||||||
|
record.nextProbeAt = nextRegularProbeAt(now);
|
||||||
|
record.lastAuthFailureAt = null;
|
||||||
|
record.profile = resolvedProfile;
|
||||||
|
record.sessionFingerprint = resolvedProfile.subjectUid ?? record.sessionFingerprint;
|
||||||
|
record.suspectedExpiredAt = null;
|
||||||
|
record.confirmFailureCount = 0;
|
||||||
|
|
||||||
|
return commitRecord(record, previousSignature);
|
||||||
|
}
|
||||||
|
|
||||||
export function getAccountHealthSnapshot(accountId: string): AccountHealthSnapshot | null {
|
export function getAccountHealthSnapshot(accountId: string): AccountHealthSnapshot | null {
|
||||||
ensureInitialized();
|
ensureInitialized();
|
||||||
const record = records.get(accountId);
|
const record = records.get(accountId);
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ import {
|
|||||||
forgetTrackedAccountHealth,
|
forgetTrackedAccountHealth,
|
||||||
getAccountHealthSnapshot,
|
getAccountHealthSnapshot,
|
||||||
getProjectedAccountHealth,
|
getProjectedAccountHealth,
|
||||||
|
markTrackedAccountBound,
|
||||||
probeTrackedAccount,
|
probeTrackedAccount,
|
||||||
reportAccountFailure,
|
reportAccountFailure,
|
||||||
syncTrackedAccounts,
|
syncTrackedAccounts,
|
||||||
@@ -1255,9 +1256,12 @@ export async function requestRuntimeAccountProbe(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function noteRuntimeAccountBound(account: DesktopAccountInfo): void {
|
export function noteRuntimeAccountBound(account: DesktopAccountInfo): void {
|
||||||
|
const verifiedAt = new Date().toISOString();
|
||||||
const normalizedAccount: DesktopAccountInfo = {
|
const normalizedAccount: DesktopAccountInfo = {
|
||||||
...account,
|
...account,
|
||||||
platform_uid: normalizeAccountPlatformUid(account.platform_uid) || account.platform_uid,
|
platform_uid: normalizeAccountPlatformUid(account.platform_uid) || account.platform_uid,
|
||||||
|
health: "live",
|
||||||
|
verified_at: account.verified_at ?? verifiedAt,
|
||||||
};
|
};
|
||||||
const existingIndex = state.accounts.findIndex((item) =>
|
const existingIndex = state.accounts.findIndex((item) =>
|
||||||
item.id === normalizedAccount.id
|
item.id === normalizedAccount.id
|
||||||
@@ -1282,6 +1286,12 @@ export function noteRuntimeAccountBound(account: DesktopAccountInfo): void {
|
|||||||
});
|
});
|
||||||
state.lastAccountsSyncAt = Date.now();
|
state.lastAccountsSyncAt = Date.now();
|
||||||
syncTrackedAccounts(state.accounts.map((item) => accountIdentityFromDesktopAccount(item)));
|
syncTrackedAccounts(state.accounts.map((item) => accountIdentityFromDesktopAccount(item)));
|
||||||
|
markTrackedAccountBound(accountIdentityFromDesktopAccount(normalizedAccount), {
|
||||||
|
subjectUid: normalizedAccount.platform_uid,
|
||||||
|
displayName: normalizedAccount.display_name,
|
||||||
|
avatarUrl: normalizedAccount.avatar_url,
|
||||||
|
});
|
||||||
|
enqueueAccountHealthReport(normalizedAccount.id);
|
||||||
refreshAccountNames();
|
refreshAccountNames();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user