1
0
mirror of https://gitcode.com/gh_mirrors/re/react-native-pushy.git synced 2025-10-23 09:38:52 +08:00
Code Issues Packages Projects Releases Wiki Activity GitHub Gitee

support multiple versions

This commit is contained in:
sunnylqm
2025-09-04 00:24:35 +08:00
parent 41e1028b2d
commit e58903a634
3 changed files with 116 additions and 84 deletions

View File

@@ -91,7 +91,8 @@ export class Pushy {
options = defaultClientOptions;
clientType: 'Pushy' | 'Cresc' = 'Pushy';
lastChecking?: number;
lastRespJson?: Promise<any>;
lastRespJson?: Promise<CheckResult>;
lastRespText?: Promise<string>;
version = cInfo.rnu;
loggerPromise = (() => {
@@ -294,20 +295,23 @@ export class Pushy {
this.throwIfEnabled(new Error('errorChecking'));
return this.lastRespJson ? await this.lastRespJson : emptyObj;
}
if (resp.status !== 200) {
const errorMessage = `${resp.status}: ${resp.statusText}`;
this.report({
type: 'errorChecking',
message: errorMessage,
});
this.throwIfEnabled(new Error(errorMessage));
log('error checking response:', resp.status, await resp.text());
return this.lastRespJson ? await this.lastRespJson : emptyObj;
}
this.lastRespJson = resp.json();
const result: CheckResult = await this.lastRespJson;
log('checking result:', result);
if (resp.status !== 200) {
this.report({
type: 'errorChecking',
message: result.message,
});
this.throwIfEnabled(new Error(result.message));
}
return result;
};
getBackupEndpoints = async () => {

View File

@@ -14,7 +14,12 @@ import {
} from 'react-native';
import { Pushy, Cresc, sharedState } from './client';
import { currentVersion, packageVersion, getCurrentVersionInfo } from './core';
import { CheckResult, ProgressData, UpdateTestPayload } from './type';
import {
CheckResult,
MixedCheckResult,
ProgressData,
UpdateTestPayload,
} from './type';
import { UpdateContext } from './context';
import { URL } from 'react-native-url-polyfill';
import { isInRollout } from './isInRollout';
@@ -158,84 +163,95 @@ export const UpdateProvider = ({
return;
}
lastChecking.current = now;
let info: CheckResult;
let rootInfo: MixedCheckResult | undefined;
try {
info = await client.checkUpdate(extra);
rootInfo = await client.checkUpdate(extra);
} catch (e: any) {
setLastError(e);
alertError('更新检查失败', e.message);
throwErrorIfEnabled(e);
return;
}
if (!info) {
if (!rootInfo) {
return;
}
const rollout = info.config?.rollout?.[packageVersion];
if (info.update && rollout) {
if (!isInRollout(rollout)) {
log(`not in ${rollout}% rollout, ignored`);
return;
const versions = rootInfo.versions || [rootInfo as CheckResult];
delete rootInfo.versions;
for (const versionInfo of versions) {
const info: CheckResult = {
...versionInfo,
...rootInfo,
};
const rollout = info.config?.rollout?.[packageVersion];
if (info.update && rollout) {
if (!isInRollout(rollout)) {
log(`${info.name} not in ${rollout}% rollout, ignored`);
continue;
}
log(`${info.name} in ${rollout}% rollout, continue`);
}
log(`in ${rollout}% rollout, continue`);
}
info.description = info.description ?? '';
updateInfoRef.current = info;
setUpdateInfo(info);
if (info.expired) {
if (
options.onPackageExpired &&
(await options.onPackageExpired(info)) === false
) {
log('onPackageExpired returned false, skipping');
return;
}
const { downloadUrl } = info;
if (downloadUrl && sharedState.apkStatus === null) {
if (options.updateStrategy === 'silentAndNow') {
if (Platform.OS === 'android' && downloadUrl.endsWith('.apk')) {
downloadAndInstallApk(downloadUrl);
} else {
Linking.openURL(downloadUrl);
info.description = info.description ?? '';
updateInfoRef.current = info;
setUpdateInfo(info);
if (info.expired) {
if (
options.onPackageExpired &&
(await options.onPackageExpired(info)) === false
) {
log('onPackageExpired returned false, skipping');
return;
}
const { downloadUrl } = info;
if (downloadUrl && sharedState.apkStatus === null) {
if (options.updateStrategy === 'silentAndNow') {
if (Platform.OS === 'android' && downloadUrl.endsWith('.apk')) {
downloadAndInstallApk(downloadUrl);
} else {
Linking.openURL(downloadUrl);
}
return info;
}
alertUpdate('提示', '您的应用版本已更新,点击更新下载安装新版本', [
{
text: '更新',
onPress: () => {
if (
Platform.OS === 'android' &&
downloadUrl.endsWith('.apk')
) {
downloadAndInstallApk(downloadUrl);
} else {
Linking.openURL(downloadUrl);
}
},
},
]);
}
} else if (info.update) {
if (
options.updateStrategy === 'silentAndNow' ||
options.updateStrategy === 'silentAndLater'
) {
downloadUpdate(info);
return info;
}
alertUpdate('提示', '您的应用版本已更新,点击更新下载安装新版本', [
{
text: '更新',
onPress: () => {
if (Platform.OS === 'android' && downloadUrl.endsWith('.apk')) {
downloadAndInstallApk(downloadUrl);
} else {
Linking.openURL(downloadUrl);
}
alertUpdate(
'提示',
'检查到新的版本' + info.name + ',是否下载?\n' + info.description,
[
{ text: '取消', style: 'cancel' },
{
text: '确定',
style: 'default',
onPress: () => {
downloadUpdate();
},
},
},
]);
],
);
}
} else if (info.update) {
if (
options.updateStrategy === 'silentAndNow' ||
options.updateStrategy === 'silentAndLater'
) {
downloadUpdate(info);
return info;
}
alertUpdate(
'提示',
'检查到新的版本' + info.name + ',是否下载?\n' + info.description,
[
{ text: '取消', style: 'cancel' },
{
text: '确定',
style: 'default',
onPress: () => {
downloadUpdate();
},
},
],
);
return info;
}
return info;
},
[
client,

View File

@@ -1,14 +1,10 @@
export interface CheckResult {
upToDate?: true;
expired?: true;
downloadUrl?: string;
update?: true;
name?: string; // version name
hash?: string;
description?: string;
metaInfo?: string;
config?: {
rollout?: {
export interface VersionInfo {
name: string;
hash: string;
description: string;
metaInfo: string;
config: {
rollout: {
[packageVersion: string]: number;
};
[key: string]: any;
@@ -16,11 +12,27 @@ export interface CheckResult {
pdiff?: string;
diff?: string;
full?: string;
paths?: string[];
}
interface RootResult {
upToDate?: true;
expired?: true;
downloadUrl?: string;
update?: true;
paused?: 'app' | 'package';
message?: string;
paths?: string[];
}
export type CheckResult = RootResult & VersionInfo;
export type CheckResultV2 = RootResult & {
versions?: VersionInfo[];
};
export type MixedCheckResult = CheckResult | CheckResultV2;
export interface ProgressData {
hash: string;
received: number;