fix: resolve Android APK download URLs for mobile updates
Prefers a real APK asset when the update API points to an AAB Keeps direct APK links from the API unchanged Uses the GitHub releases API as a fallback for Android mobile downloads
This commit is contained in:
@@ -13,6 +13,7 @@ const PACKAGE_PATH_SEGMENTS = PACKAGE_NAME.split('/');
|
||||
const NPM_REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}`;
|
||||
const CHANGELOG_URL = 'https://raw.githubusercontent.com/openchamber/openchamber/main/CHANGELOG.md';
|
||||
const GITHUB_RELEASES_URL = 'https://github.com/openchamber/openchamber/releases';
|
||||
const GITHUB_RELEASES_API_URL = 'https://api.github.com/repos/openchamber/openchamber/releases';
|
||||
let cachedDetectedPm = null;
|
||||
|
||||
function getSpawnSyncBaseOptions() {
|
||||
@@ -85,6 +86,40 @@ function normalizeArch(value) {
|
||||
return mapArch(process.arch);
|
||||
}
|
||||
|
||||
async function resolveAndroidApkUrl(version, candidateUrl) {
|
||||
if (typeof candidateUrl === 'string') {
|
||||
try {
|
||||
if (new URL(candidateUrl).pathname.toLowerCase().endsWith('.apk')) return candidateUrl;
|
||||
} catch {
|
||||
// Resolve malformed or non-APK values from the authoritative release assets below.
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`${GITHUB_RELEASES_API_URL}/tags/v${version}`, {
|
||||
headers: {
|
||||
Accept: 'application/vnd.github+json',
|
||||
'User-Agent': 'openchamber-update-check',
|
||||
},
|
||||
signal: AbortSignal.timeout(10000),
|
||||
});
|
||||
if (!response.ok) return undefined;
|
||||
|
||||
const release = await response.json();
|
||||
const apkAssets = Array.isArray(release?.assets)
|
||||
? release.assets.filter((asset) => (
|
||||
typeof asset?.name === 'string'
|
||||
&& asset.name.toLowerCase().endsWith('.apk')
|
||||
&& typeof asset.browser_download_url === 'string'
|
||||
))
|
||||
: [];
|
||||
const canonicalAsset = apkAssets.find((asset) => /^OpenChamber-.+-android\.apk$/i.test(asset.name));
|
||||
return (canonicalAsset || apkAssets[0])?.browser_download_url;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
async function checkForUpdatesFromApi(currentVersion, options = {}) {
|
||||
try {
|
||||
const appType = normalizeAppType(options.appType);
|
||||
@@ -128,13 +163,17 @@ async function checkForUpdatesFromApi(currentVersion, options = {}) {
|
||||
: typeof data.download?.url === 'string'
|
||||
? data.download.url
|
||||
: undefined;
|
||||
const updateAvailable = Boolean(data.updateAvailable) && versionComparison > 0;
|
||||
const mobileDownloadUrl = updateAvailable && appType === 'mobile-capacitor' && platform === 'android'
|
||||
? await resolveAndroidApkUrl(data.latestVersion, downloadUrl)
|
||||
: undefined;
|
||||
return {
|
||||
available: Boolean(data.updateAvailable) && versionComparison > 0,
|
||||
available: updateAvailable,
|
||||
version: data.latestVersion,
|
||||
currentVersion,
|
||||
body: typeof data.releaseNotes === 'string' ? data.releaseNotes : undefined,
|
||||
releaseUrl: typeof data.releaseNotesUrl === 'string' ? data.releaseNotesUrl : releaseUrl,
|
||||
downloadUrl: appType === 'mobile-capacitor' ? (downloadUrl || releaseUrl) : undefined,
|
||||
downloadUrl: mobileDownloadUrl,
|
||||
nextSuggestedCheckInSec:
|
||||
typeof data.nextSuggestedCheckInSec === 'number' && Number.isFinite(data.nextSuggestedCheckInSec)
|
||||
? data.nextSuggestedCheckInSec
|
||||
@@ -762,8 +801,12 @@ export async function checkForUpdates(options = {}) {
|
||||
|
||||
const available = compareVersions(latestVersion, currentVersion) > 0;
|
||||
let changelog;
|
||||
let downloadUrl;
|
||||
if (available) {
|
||||
changelog = await fetchChangelogNotes(currentVersion, latestVersion);
|
||||
if (appType === 'mobile-capacitor' && platform === 'android') {
|
||||
downloadUrl = await resolveAndroidApkUrl(latestVersion);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -772,7 +815,7 @@ export async function checkForUpdates(options = {}) {
|
||||
currentVersion,
|
||||
body: changelog,
|
||||
releaseUrl: `${GITHUB_RELEASES_URL}/tag/v${latestVersion}`,
|
||||
downloadUrl: appType === 'mobile-capacitor' && platform === 'android' ? `${GITHUB_RELEASES_URL}/tag/v${latestVersion}` : undefined,
|
||||
downloadUrl,
|
||||
packageManager: pm,
|
||||
// Show our CLI command, not raw package manager command
|
||||
updateCommand: 'openchamber update',
|
||||
|
||||
Reference in New Issue
Block a user