🌈 Sync 2026-05-19 02:35:14

This commit is contained in:
github-actions[bot] committed 2026-05-19 02:35:14 +08:00
1 parent 595807ea37
commit ca5e918f4b
81 files changed
+12003 -3193

No files matched your search

@@ -0,0 +1,115 @@
'use strict';
'require ui';
'require poll';
'require fs';
'require uci';
function getSignalColor(percent) {
if (percent === null || percent === undefined || percent < 5) {
return '#000000';
}
let p = percent;
if (p >= 80) return '#00cc00';
if (p >= 67) {
const ratio = (p - 50) / 30;
const r = Math.floor(255 * (1 - ratio));
const g = 255;
return `rgb(${r}, ${g}, 0)`;
}
if (p >= 35) {
const ratio = (p - 25) / 25;
const r = 255;
const g = Math.floor(165 + (90 * ratio));
return `rgb(${r}, ${g}, 0)`;
}
const ratio = (p - 5) / 20;
const r = 255;
const g = Math.floor(165 * ratio);
return `rgb(${r}, ${g}, 0)`;
}
function getSignalState(percent) {
const p = percent || 0;
if (p < 10) return 'error';
if (p < 25) return 'warning';
if (p < 50) return 'warning';
return 'active';
}
function isUciIndexTwo() {
return L.resolveDefault(fs.exec_direct('/sbin/uci', ['get', 'modeminfo.@general[0].index']), '')
.then(function(value) {
return value.trim() === '2';
})
.catch(function() {
return false;
});
}
function updateIndicator() {
isUciIndexTwo().then(function(ok) {
if (!ok) {
ui.hideIndicator('modem-status');
return;
}
if (window.location.pathname.includes('/cgi-bin/luci/admin/modem/main')) {
ui.hideIndicator('modem-status');
return;
}
L.resolveDefault(fs.exec_direct('/usr/bin/modeminfo'), '{"modem":[]}')
.then(function(res) {
var data = JSON.parse(res);
if (!data.modem || !data.modem.length) {
ui.hideIndicator('modem-status');
return;
}
var parts = data.modem.map(function(modem) {
var percent = parseInt(modem.csq_per);
var cops = modem.cops || '';
var mode = modem.mode + (parseInt(modem.lteca) > 0 ? '+' : '');
return { mode: mode, cops: cops, percent: percent };
});
var minPercent = Math.min.apply(null, parts.map(function(p) { return p.percent; }));
var state = getSignalState(minPercent);
var status = parts.map(function(p) {
return p.mode + ' ' + p.cops;
}).join(' | ');
ui.showIndicator('modem-status', status, null, state);
var indicator = document.querySelector('[data-indicator="modem-status"]');
if (indicator) {
var html = parts.map(function(p) {
var color = getSignalColor(p.percent);
return '<span style="color:' + color + '; -webkit-text-stroke: 0.5px black; text-stroke: 0.5px black;">●</span> ' + p.mode + ' ' + p.cops;
}).join(' | ');
indicator.innerHTML = html;
}
})
.catch(function() {
ui.hideIndicator('modem-status');
});
});
}
setTimeout(function() {
updateIndicator();
poll.add(updateIndicator, 10);
}, 500);
return L.Class.extend({
__name__: 'ModemIndicator'
});
@@ -0,0 +1,6 @@
'use strict';
'require modem-indicator';
return L.Class.extend({
__name__: 'preload.modem-indicator'
});
@@ -60,7 +60,7 @@ var qdesc = _('Select qmi port.');
var lacdec = _('Show LAC and CID in decimal.');
var mmdesc = _('Get device hardware name via mmcli utility if aviable.');
var qmidesc = _('Set qmi mode.');
var idesc = _('Short info on Overview page');
var idesc = _('Show short info.<br />Overview: show info on main page \"Cellular Network\" section<br />MenuBar: show info on menubar all pages<br />NOTICE: Don\'t add too many modems in menubar, it may break the theme display.');
var portplace = _('Please select a port');
return view.extend({
@@ -88,8 +88,12 @@ return view.extend({
s = m.section(form.TypedSection, 'general', _('General option'), null);
s.anonymous = true;
o = s.option(form.Flag, 'index', _('Index page'), idesc);
s.anonymous = true;
o = s.option(form.ListValue, 'index', _('Short info'), idesc);
o.widget="radio";
o.value(0,_('none'));
o.value(1,_('overview'));
o.value(2,_('menubar'));
o.default = '0';
o.rmempty = true;
o = s.option(form.Flag, 'decimail', _('Show decimal'), lacdec);
@@ -19,7 +19,11 @@ return baseclass.extend({
title: _('Cellular network'),
load: async function() {
uci.load('modeminfo');
await uci.load('modeminfo');
var index = uci.sections('modeminfo', 'general');
if (!index || !index[0] || index[0].index !== "1") {
return null;
};
return new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
@@ -43,10 +47,15 @@ return baseclass.extend({
render: function(data){
if (!data || data.trim() === '') {
return E('div', {
'class': 'cbi-section',
'style': 'color: #999; text-align: center;'
}, _('Wait devices information'));
var index = uci.sections('modeminfo', 'general');
if (!index || !index[0] || index[0].index !== "1") {
return null;
} else {
return E('div', {
'class': 'cbi-section',
'style': 'color: #999; text-align: center;'
}, _('Wait devices information'));
}
}
try {