🌴 Sync 2026-05-13 20:46:46

This commit is contained in:
github-actions[bot] committed 2026-05-13 20:46:46 +08:00
1 parent 6bb23e315c
commit a15c25c73e
16 files changed
+886 -315

No files matched your search

@@ -283,7 +283,6 @@ return view.extend({
var verPlugin = E('span', _('Collecting data...'));
var verKernel = E('span', _('Collecting data...'));
var verRescue = E('span', _('Collecting data...'));
var branchSpan = E('span');
// Per-action status spans (right side, updated by poll)
var statusFw = E('span');
@@ -419,8 +418,7 @@ return view.extend({
E('p', _('Provide OpenWrt Firmware, Kernel and Plugin online check, download and update service.')),
E('div', { class: 'cbi-section' }, [
E('p', { style: 'text-align:center' }, [
_('Update plugins first, then update the kernel or firmware. More options can be configured in [Plugin Settings].'),
' ', branchSpan
_('Update plugins first, then update the kernel or firmware. More options can be configured in [Plugin Settings].')
]),
E('table', { class: 'amlogic-row-table' }, [
E('tr', [
@@ -461,10 +459,6 @@ return view.extend({
dom.content(verKernel, s && s.current_kernel_version
? E('span', { class: 'amlogic-status-ok' }, _('Current Version') + ' [ ' + s.current_kernel_version + ' ] ')
: E('span', { class: 'amlogic-status-err' }, _('Invalid value.')));
var branchLabel = s && s.plugin_branch
? (s.plugin_branch === 'lua' ? 'Lua' : 'JavaScript')
: (s && s.has_luci_js ? 'JavaScript' : 'Lua');
dom.content(branchSpan, ' [ ' + branchLabel + ' ] ');
// Rescue row: show same kernel version directly via the verRescue span
dom.content(verRescue, s && s.current_kernel_version
@@ -23,6 +23,9 @@ const callAuthor = rpc.declare({
// Called on every info page load so the sidebar menu is correct from first visit.
const callSyncMenu = rpc.declare({ object: 'luci.amlogic', method: 'sync_menu' });
// Get runtime state to determine plugin_branch for the language badge.
const callState = rpc.declare({ object: 'luci.amlogic', method: 'state' });
// Static list of supported boxes (display only, not used in any logic).
const SUPPORTED_BOXES = [
_('Amlogic s922x --- [ Beelink, Beelink-Pro, Ugoos-AM6-Plus, ODROID-N2, Khadas-VIM3, Ali-CT2000 ]'),
@@ -57,9 +60,27 @@ return view.extend({
handleReset: null,
load: function () {
// Fire sync_menu in background (don't block render on it).
callSyncMenu().catch(function () {});
return callAuthor();
// Call sync_menu and wait for it. sync_menu writes menu_install /
// menu_armcpu into UCI and clears the LuCI index cache on the server.
// On first boot from USB the install menu may be missing from the
// browser-side navigation (built before sync_menu ran). After the RPC
// returns we check if the sidebar already has an install link; if not,
// reload once so the browser re-fetches the updated menu tree.
// A URL hash flag (#menu-synced) prevents an infinite reload loop.
const alreadyReloaded = window.location.hash === '#menu-synced';
const syncMenuPromise = callSyncMenu().then(function (res) {
if (alreadyReloaded) return;
if (res && res.show_install === 'yes') {
// Check if the sidebar navigation already contains the install link.
const installLink = document.querySelector('a[href*="amlogic/install"]');
if (!installLink) {
// Server has updated the index cache; reload to pick up new nav.
window.location.replace(window.location.pathname + '#menu-synced');
window.location.reload();
}
}
}).catch(function () {});
return Promise.all([callAuthor(), syncMenuPromise]).then(function (r) { return r[0]; });
},
render: function (authorUrl) {
@@ -67,6 +88,23 @@ return view.extend({
amlogicShared.ensureCss();
const res = L.resource('amlogic');
// Language badge image — default to javascript.svg (JS version),
// will be confirmed/corrected after the state RPC resolves.
var langsImg = E('img', {
id: 'Langs',
src: res + '/javascript.svg', alt: 'javascript',
width: '86', height: '20',
style: 'margin:0 5px; vertical-align:middle; border-radius:3px'
});
// Fetch plugin_branch from state and update the language badge.
callState().then(function (s) {
var isLua = s && s.plugin_branch === 'lua';
langsImg.src = res + (isLua ? '/lua.svg' : '/javascript.svg');
langsImg.alt = isLua ? 'lua' : 'javascript';
langsImg.setAttribute('width', isLua ? '46' : '86');
}).catch(function () {});
// Flatten the supported-boxes list to [text, <br>, text, <br>, ...].
const boxRows = [];
for (let i = 0; i < SUPPORTED_BOXES.length; i++)
@@ -86,13 +124,13 @@ return view.extend({
E('img', {
src: res + '/packit.svg', alt: 'Packit',
width: '168', height: '20',
style: 'cursor:pointer; margin:0 5px',
style: 'cursor:pointer; margin:0 5px; vertical-align:middle; border-radius:3px',
click: function () { openExternal('https://github.com/unifreq/openwrt_packit'); }
}),
E('img', {
src: res + '/author.svg', alt: 'Author',
width: '168', height: '20',
style: 'cursor:pointer; margin:0 5px',
style: 'cursor:pointer; margin:0 5px; vertical-align:middle; border-radius:3px',
click: function () {
callAuthor().then(function (repo) {
let url = String(repo || '').trim();
@@ -106,9 +144,10 @@ return view.extend({
E('img', {
src: res + '/plugin.svg', alt: 'luci-app-amlogic',
width: '160', height: '20',
style: 'cursor:pointer; margin:0 5px',
style: 'cursor:pointer; margin:0 5px; vertical-align:middle; border-radius:3px',
click: function () { openExternal('https://github.com/ophub/luci-app-amlogic'); }
})
}),
langsImg
])
]),
E('tr', [
@@ -69,7 +69,7 @@ return view.extend({
value: _('Update OpenWrt firmware'), style: 'display:none',
click: ui.createHandlerFn(this, function (ev) {
return doButton(ev.currentTarget,
_('Updating...'), _('Successful Update'), _('Update Failed'),
_('Updating...'), _('Update Failed'),
function () { return callStartUpd('auto@updated@/tmp'); });
})
});
@@ -78,7 +78,7 @@ return view.extend({
value: _('Replace OpenWrt Kernel'), style: 'display:none; margin-left:5px',
click: ui.createHandlerFn(this, function (ev) {
return doButton(ev.currentTarget,
_('Updating...'), _('Successful Update'), _('Update Failed'),
_('Updating...'), _('Update Failed'),
function () { return callStartKnl(); });
})
});
@@ -86,13 +86,23 @@ return view.extend({
const knLog = E('span');
const fwVer = E('span', _('Collecting data...'));
function doButton(btn, busyText, ok, fail, fn) {
// Shared button state machine: disabled -> RPC -> success/fail label.
function doButton(btn, busyText, fail, fn) {
// Shared button state machine: disabled -> RPC -> updating/fail label.
// On success (code==0) the button stays in busyText state and
// remains disabled — the device is about to reboot, so there is
// nothing to restore. Only on failure do we surface an error and
// re-enable the button so the user can retry.
btn.disabled = true; btn.value = busyText;
return Promise.resolve(fn()).then(function (r) {
btn.value = (r && r.code == 0) ? ok : fail;
}).catch(function () { btn.value = fail; })
.finally(function () { btn.disabled = false; });
if (!r || r.code !== 0) {
btn.value = fail;
btn.disabled = false;
}
// code == 0 → keep busyText + disabled (update in progress)
}).catch(function () {
btn.value = fail;
btn.disabled = false;
});
}
function refreshList() {