mirror of
git://f0xx.org/ac/ac-be-hub
synced 2026-07-29 03:19:51 +03:00
121 lines
3.5 KiB
JavaScript
121 lines
3.5 KiB
JavaScript
(function () {
|
|
'use strict';
|
|
|
|
/** Orchestration default channel; stable is fallback for promoted releases. */
|
|
var OTA_CHANNELS = ['staging', 'stable'];
|
|
|
|
function setStatus(msg) {
|
|
var el = document.getElementById('hub-download-apk-status');
|
|
if (el) {
|
|
el.textContent = msg;
|
|
}
|
|
}
|
|
|
|
function fetchJson(url) {
|
|
return fetch(url, { cache: 'no-store' }).then(function (r) {
|
|
if (!r.ok) {
|
|
throw new Error('HTTP ' + r.status + ' for ' + url);
|
|
}
|
|
return r.json();
|
|
});
|
|
}
|
|
|
|
function resolveApkFromChannel(channelName) {
|
|
return fetchJson('/v0/ota/channel/' + encodeURIComponent(channelName) + '.json')
|
|
.then(function (channel) {
|
|
var manifestUrl = channel && channel.manifestUrl;
|
|
if (!manifestUrl) {
|
|
throw new Error(channelName + ' missing manifestUrl');
|
|
}
|
|
return fetchJson(manifestUrl);
|
|
})
|
|
.then(function (manifest) {
|
|
var url =
|
|
(manifest && (manifest.browserApkUrl || manifest.apkUrl)) || '';
|
|
if (!url) {
|
|
throw new Error('manifest missing browserApkUrl/apkUrl');
|
|
}
|
|
if (!manifest.browserApkUrl && /\.otapkg(\?|$)/.test(url)) {
|
|
url = url.replace(/\.otapkg(\?|$)/, '.apk$1');
|
|
}
|
|
var nameMatch = url.match(/\/([^/?#]+\.apk)(?:\?|$)/i);
|
|
var filename = nameMatch ? nameMatch[1] : 'android_cast-latest.apk';
|
|
return { url: url, filename: filename, channel: channelName };
|
|
});
|
|
}
|
|
|
|
function resolveApkUrl() {
|
|
var chain = Promise.reject(new Error('no channel'));
|
|
OTA_CHANNELS.forEach(function (ch) {
|
|
chain = chain.catch(function () {
|
|
return resolveApkFromChannel(ch);
|
|
});
|
|
});
|
|
return chain;
|
|
}
|
|
|
|
function triggerDownload(url, filename) {
|
|
if (/\.apk(\?|$)/i.test(url)) {
|
|
var a = document.createElement('a');
|
|
a.href = url;
|
|
a.download = filename;
|
|
a.rel = 'noopener';
|
|
document.body.appendChild(a);
|
|
a.click();
|
|
a.remove();
|
|
return Promise.resolve();
|
|
}
|
|
return fetch(url, { cache: 'no-store' })
|
|
.then(function (r) {
|
|
if (!r.ok) {
|
|
throw new Error('download HTTP ' + r.status);
|
|
}
|
|
return r.blob();
|
|
})
|
|
.then(function (blob) {
|
|
var blobUrl = URL.createObjectURL(blob);
|
|
var link = document.createElement('a');
|
|
link.href = blobUrl;
|
|
link.download = filename;
|
|
link.rel = 'noopener';
|
|
document.body.appendChild(link);
|
|
link.click();
|
|
link.remove();
|
|
setTimeout(function () {
|
|
URL.revokeObjectURL(blobUrl);
|
|
}, 60000);
|
|
});
|
|
}
|
|
|
|
function wireApkButton() {
|
|
var btn = document.getElementById('hub-download-apk');
|
|
if (!btn) {
|
|
return;
|
|
}
|
|
btn.addEventListener('click', function () {
|
|
btn.disabled = true;
|
|
setStatus('Resolving OTA channel…');
|
|
resolveApkUrl()
|
|
.then(function (resolved) {
|
|
setStatus('Downloading ' + resolved.filename + ' (' + resolved.channel + ')…');
|
|
return triggerDownload(resolved.url, resolved.filename);
|
|
})
|
|
.catch(function (err) {
|
|
setStatus(
|
|
'APK unavailable — run builder with OTA publish (staging). ' +
|
|
(err.message || err)
|
|
);
|
|
})
|
|
.finally(function () {
|
|
btn.disabled = false;
|
|
});
|
|
});
|
|
}
|
|
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', wireApkButton);
|
|
} else {
|
|
wireApkButton();
|
|
}
|
|
})();
|