fix: avoid repeated daily starlanguage refresh
This commit is contained in:
@@ -102,6 +102,7 @@ import {
|
||||
requestOnboardingWithRecovery,
|
||||
} from "@/lib/onboarding-client";
|
||||
import { protectOnboardingPhrases } from "@/lib/onboarding-copy";
|
||||
import { preserveShallowEqual } from "@/lib/preserve-shallow-equal";
|
||||
import {
|
||||
SessionModelPersistenceQueue,
|
||||
persistSessionModelSelection,
|
||||
@@ -1797,7 +1798,7 @@ export default function Home() {
|
||||
const latest = await fetchAccount();
|
||||
if (!accountRefreshGuard.current.isCurrent(requestIdentity)) return;
|
||||
const nextProfile = readProfile(latest.profile);
|
||||
setProfile(nextProfile);
|
||||
setProfile((current) => preserveShallowEqual(current, nextProfile));
|
||||
setAccount(latest);
|
||||
setAccountError("");
|
||||
} catch (caught) {
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
export function preserveShallowEqual<T extends object>(current: T, next: T): T {
|
||||
if (Object.is(current, next)) return current;
|
||||
|
||||
const currentRecord = current as Record<string, unknown>;
|
||||
const nextRecord = next as Record<string, unknown>;
|
||||
const currentKeys = Object.keys(currentRecord);
|
||||
const nextKeys = Object.keys(nextRecord);
|
||||
|
||||
if (currentKeys.length !== nextKeys.length) return next;
|
||||
|
||||
for (const key of currentKeys) {
|
||||
if (!Object.hasOwn(nextRecord, key) || !Object.is(currentRecord[key], nextRecord[key])) {
|
||||
return next;
|
||||
}
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { readFileSync } from "node:fs";
|
||||
import test from "node:test";
|
||||
import { preserveShallowEqual } from "../src/lib/preserve-shallow-equal.ts";
|
||||
|
||||
const pageSource = readFileSync(new URL("../src/app/page.tsx", import.meta.url), "utf8");
|
||||
|
||||
test("preserves the current profile reference when refreshed values are unchanged", () => {
|
||||
const current = {
|
||||
name: "测试用户",
|
||||
date: "2000-01-01",
|
||||
time: "",
|
||||
birthTimeSource: "period_only",
|
||||
birthTimePeriod: "evening",
|
||||
timezoneId: "Asia/Shanghai",
|
||||
latitude: 31.23,
|
||||
longitude: 121.47,
|
||||
timezoneOffset: null,
|
||||
};
|
||||
const refreshed = { ...current };
|
||||
|
||||
assert.notEqual(refreshed, current);
|
||||
assert.equal(preserveShallowEqual(current, refreshed), current);
|
||||
});
|
||||
|
||||
test("uses the refreshed profile reference when a value changed", () => {
|
||||
const current = {
|
||||
name: "测试用户",
|
||||
birthTimePeriod: "evening",
|
||||
timezoneId: "Asia/Shanghai",
|
||||
};
|
||||
const refreshed = {
|
||||
...current,
|
||||
birthTimePeriod: "morning",
|
||||
};
|
||||
|
||||
assert.equal(preserveShallowEqual(current, refreshed), refreshed);
|
||||
});
|
||||
|
||||
test("account refresh preserves an equivalent normalized profile instead of replacing it", () => {
|
||||
const refreshAccountStart = pageSource.indexOf("async function refreshAccount()");
|
||||
const refreshAccountSource = pageSource.slice(
|
||||
refreshAccountStart,
|
||||
pageSource.indexOf("function updateSession", refreshAccountStart),
|
||||
);
|
||||
|
||||
assert.match(
|
||||
refreshAccountSource,
|
||||
/setProfile\(\(current\) => preserveShallowEqual\(current, nextProfile\)\)/,
|
||||
);
|
||||
assert.doesNotMatch(refreshAccountSource, /setProfile\(nextProfile\)/);
|
||||
});
|
||||
Reference in New Issue
Block a user