Skip to content

Commit 845de20

Browse files
committed
fix: address remaining native check review comments
1 parent 33dc6cb commit 845de20

5 files changed

Lines changed: 48 additions & 4 deletions

File tree

NATIVE_CHECK_FOLLOWUPS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,8 @@ Android 与 Harmony 只有任务串行化,没有按 hash 去重,也不保护已
125125

126126
**复评补充(181952a 引入/暴露)——下载轮次时限应作为一个整体设计统一三端**:
127127
1. 整轮 600s deadline 只落了 Android;iOS 仍逐 URL 600s(上界
128-
attempts×urls×600s,可达 90 分钟),Harmony 完全没有(慢滴 CDN
129-
<60s 一字节即可绕过下载任务的不活动看门狗,轮次可跑数小时);
128+
attempts×urls×600s,可达 90 分钟),Harmony 完全没有(慢滴 CDN 在每个
129+
60 秒窗口内返回至少一个字节即可绕过下载任务的不活动看门狗,轮次可跑数小时);
130130
2. Android 的 deadline 在下一个下载**已发起后**才检查——超时轮次仍会
131131
多启动一个孤儿下载,浪费带宽且可能与 JS 重试并发写版本文件
132132
(修法:发起前先查);

src/__tests__/client.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,6 +1451,23 @@ describe('syncNativeConfig', () => {
14511451
expect(config.afterDownload).toBe('setNeedUpdate');
14521452
});
14531453

1454+
test('persists an explicit disabled state when the config becomes invalid', async () => {
1455+
const syncNativeConfig = mock(() => Promise.resolve());
1456+
setupClientMocks({ syncNativeConfig });
1457+
const { Pushy } = await importFreshClient('sync-config-disabled');
1458+
const client = new Pushy({ appKey: 'demo-app' });
1459+
1460+
client.setOptions({ appKey: '' });
1461+
await Promise.resolve();
1462+
await Promise.resolve();
1463+
await Promise.resolve();
1464+
1465+
expect(syncNativeConfig).toHaveBeenCalledTimes(2);
1466+
expect(
1467+
JSON.parse((syncNativeConfig.mock.calls.at(-1) as unknown as string[])[0])
1468+
).toEqual({ disabled: true });
1469+
});
1470+
14541471
test('persists and exposes the effective overridden package version', async () => {
14551472
const syncNativeConfig = mock(() => Promise.resolve());
14561473
setupClientMocks({ syncNativeConfig });

src/__tests__/provider.render.test.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,23 @@ describe('UpdateProvider rendering', () => {
146146
expect(mockAlert).not.toHaveBeenCalled();
147147
});
148148

149+
test('an expired app package without a bundle hash keeps its download action', async () => {
150+
const client = createClient({ updateStrategy: 'alwaysAlert' });
151+
client.checkUpdate.mockImplementation(async () => ({
152+
expired: true,
153+
update: true,
154+
downloadUrl: 'https://cdn.example.com/app-release.apk',
155+
}));
156+
157+
await renderProvider(client);
158+
159+
expect(client.reportInvalidUpdateOnce).not.toHaveBeenCalled();
160+
expect(mockAlert).toHaveBeenCalledTimes(1);
161+
const [, , buttons] = mockAlert.mock.calls[0] as any[];
162+
expect(buttons).toHaveLength(1);
163+
expect(buttons[0].text).toBe('alert_update_button');
164+
});
165+
149166
test('an update without a downloadable artifact is never shown as actionable', async () => {
150167
const client = createClient({ updateStrategy: 'alwaysAlert' });
151168
client.checkUpdate.mockImplementation(async () => ({

src/client.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,11 @@ const cloneServerConfig = (server: UpdateServerConfig): UpdateServerConfig => ({
9696
queryUrls: server.queryUrls ? [...server.queryUrls] : undefined,
9797
});
9898

99+
// Persist an object (rather than an empty string) so every native bridge keeps
100+
// accepting the payload while the orchestrators treat the missing appKey and
101+
// endpoints as an explicit disabled state.
102+
const NATIVE_CONFIG_DISABLED_JSON = '{"disabled":true}';
103+
99104
const excludeConfiguredEndpoints = (
100105
endpoints: string[],
101106
configuredEndpoints: string[]
@@ -339,10 +344,14 @@ export class Pushy {
339344
};
340345

341346
private syncNativeConfig = () => {
342-
const configJson = this.getNativeConfigJson();
343-
if (!configJson) {
347+
if (
348+
Platform.OS === 'web' ||
349+
typeof PushyModule.syncNativeConfig !== 'function'
350+
) {
344351
return;
345352
}
353+
const configJson =
354+
this.getNativeConfigJson() ?? NATIVE_CONFIG_DISABLED_JSON;
346355
// Always record the latest desired value, even when it matches the last
347356
// completed write. Example: A synced -> B in flight -> options revert to
348357
// A. Comparing only with synced(A) would drop the revert and leave native

src/provider.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ export const UpdateProvider = ({
234234
log
235235
);
236236
if (
237+
!info.expired &&
237238
info.update &&
238239
(typeof info.hash !== 'string' || info.hash.length === 0)
239240
) {

0 commit comments

Comments
 (0)