mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-07 20:54:14 +08:00
⛅ Sync 2026-09-22 23:24:55
This commit is contained in:
1 parent
de9cc9a6a9
commit
d45e210b8a
16 files changed
+174
-72
No files matched your search
@@ -3,6 +3,7 @@
|
||||
/* Copyright 2025-2026 Lucas Albers <lucas.b.albers@gmail.com> */
|
||||
'require baseclass'; /* LuCI require() needs Class.isSubclass — plain return {} fails */
|
||||
'require fwlive.log as log';
|
||||
'require fwlive.hostname as hostname';
|
||||
|
||||
/**
|
||||
* Link-builder helpers for luci-app-fwlive.
|
||||
@@ -14,7 +15,7 @@
|
||||
* filterLink, addrFilterLink, ruleAdminPath, ruleAdminLink, ifaceLink
|
||||
*
|
||||
* No host element — all functions return DOM nodes or strings.
|
||||
* May require fwlive.log for formatCell.
|
||||
* May require fwlive.log for formatCell and fwlive.hostname for cache reads.
|
||||
*/
|
||||
|
||||
function luciUrl(path) {
|
||||
@@ -75,7 +76,14 @@ function filterLink(field, value, label, onFilterClick) {
|
||||
function addrFilterLink(field, ip, showHostnames, hostnameCache, onFilterClick) {
|
||||
if (!ip) return log.formatCell(ip);
|
||||
|
||||
const name = showHostnames && hostnameCache ? hostnameCache.get(ip) : null;
|
||||
let name = null;
|
||||
if (showHostnames && hostnameCache) {
|
||||
/* Display reads refresh recency so visible names remain warm in the LRU. */
|
||||
name =
|
||||
hostname && typeof hostname.lruGet === 'function'
|
||||
? hostname.lruGet(hostnameCache, ip)
|
||||
: hostnameCache.get(ip);
|
||||
}
|
||||
const display = name || ip;
|
||||
const title = name ? ip : _('Filter by %s').format(field);
|
||||
|
||||
|
||||
@@ -87,6 +87,11 @@ function labelWithZoneCandidates(label, st) {
|
||||
return children;
|
||||
}
|
||||
|
||||
function appendLoggingNotice(host, state) {
|
||||
if (!state.loggingNotice) return;
|
||||
host.appendChild(E('span', { 'class': 'fwlive-logging-notice' }, [state.loggingNotice]));
|
||||
}
|
||||
|
||||
function renderToolbar(host, state, callbacks) {
|
||||
host.innerHTML = '';
|
||||
const st = state.loggingStatus;
|
||||
@@ -107,6 +112,7 @@ function renderToolbar(host, state, callbacks) {
|
||||
)
|
||||
);
|
||||
host.appendChild(links.firewallZonesLink());
|
||||
appendLoggingNotice(host, state);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -116,6 +122,7 @@ function renderToolbar(host, state, callbacks) {
|
||||
_('WAN logging unavailable: missing kernel log modules')
|
||||
])
|
||||
);
|
||||
appendLoggingNotice(host, state);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -144,6 +151,7 @@ function renderToolbar(host, state, callbacks) {
|
||||
children
|
||||
)
|
||||
);
|
||||
appendLoggingNotice(host, state);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -162,6 +170,7 @@ function renderToolbar(host, state, callbacks) {
|
||||
[state.loggingBusy ? _('Enabling…') : _('Enable logging')]
|
||||
)
|
||||
);
|
||||
appendLoggingNotice(host, state);
|
||||
}
|
||||
|
||||
function buildConsentPanel(state, callbacks) {
|
||||
|
||||
@@ -77,6 +77,14 @@ function createScheduler(options) {
|
||||
const elapsed = bucketMs === null ? 0 : Math.max(0, timestamp - bucketMs);
|
||||
bucketMs = timestamp;
|
||||
bucket = Math.min(capacity, bucket + (elapsed * capacity) / 1000);
|
||||
/* A single batch can cost more than one second's budget. Once the
|
||||
* bucket is full, spend that full interval on one paint so a sustained
|
||||
* flood cannot freeze the table until the user changes a control. */
|
||||
if (cost > bucket && bucket >= capacity) {
|
||||
bucket = 0;
|
||||
floodSuppressed = true;
|
||||
return true;
|
||||
}
|
||||
floodSuppressed = cost > bucket;
|
||||
if (floodSuppressed) return false;
|
||||
bucket -= cost;
|
||||
|
||||
@@ -683,10 +683,15 @@ return view.extend({
|
||||
const status = await callFwliveLoggingStatus();
|
||||
if (this.viewDisposed) return;
|
||||
this.loggingStatus = status;
|
||||
this.loggingNotice = '';
|
||||
this.weakDevice = !!(this.loggingStatus && this.loggingStatus.weak_device === true);
|
||||
} catch (_e) {
|
||||
if (this.viewDisposed) return;
|
||||
this.loggingStatus = null;
|
||||
/* Keep last toolbar state. Do not clobber a toggle success/failure notice. */
|
||||
if (!this.loggingNotice)
|
||||
this.loggingNotice = _(
|
||||
'Could not refresh logging status; showing the last known state.'
|
||||
);
|
||||
}
|
||||
this.updateBackendUi();
|
||||
this.updateLoggingToolbarUi();
|
||||
@@ -712,6 +717,10 @@ return view.extend({
|
||||
|
||||
this.loggingNotice = opts.successNotice(res);
|
||||
if (opts.onSuccess) opts.onSuccess(res);
|
||||
if (this.loggingStatus && typeof opts.wanLog === 'boolean')
|
||||
this.loggingStatus = Object.assign({}, this.loggingStatus, {
|
||||
wan_log: opts.wanLog
|
||||
});
|
||||
await this.loadLoggingStatus();
|
||||
} catch (_e) {
|
||||
this.loggingNotice = opts.catchNotice();
|
||||
@@ -725,6 +734,7 @@ return view.extend({
|
||||
|
||||
async handleEnableLogging() {
|
||||
return this.runLoggingToggle({
|
||||
wanLog: true,
|
||||
call: () => callFwliveEnableLogging(),
|
||||
initialUi: () => {
|
||||
this.updateEmptyStateUi();
|
||||
@@ -752,6 +762,7 @@ return view.extend({
|
||||
|
||||
async handleDisableLogging() {
|
||||
return this.runLoggingToggle({
|
||||
wanLog: false,
|
||||
call: () => callFwliveDisableLogging(),
|
||||
initialUi: () => this.updateLoggingToolbarUi(),
|
||||
failureNotice: (res) => {
|
||||
@@ -1333,7 +1344,14 @@ return view.extend({
|
||||
this.summaryRowsShown = false;
|
||||
this.summaryData = null;
|
||||
this.updateSummaryUi();
|
||||
this.renderRows(true);
|
||||
if (this.tablePaused) {
|
||||
const empty = document.getElementById('fwlive-empty');
|
||||
if (empty) {
|
||||
const rows = this.filteredRows();
|
||||
empty.style.display = rows.length ? 'none' : 'block';
|
||||
}
|
||||
this.updateStatus();
|
||||
} else this.renderRows(true);
|
||||
},
|
||||
|
||||
onSummaryRowsToggle() {
|
||||
@@ -1469,8 +1487,10 @@ return view.extend({
|
||||
this.resolveGeneration = (this.resolveGeneration || 0) + 1;
|
||||
this.resolveInFlight = false;
|
||||
|
||||
if (this.showHostnames) this.resolveHostnamesForEntries(this.filteredRows());
|
||||
/* Paint the existing cache immediately; resolving only fills misses. */
|
||||
if (this.tablePaused) this.updateStatus();
|
||||
else this.renderRows(true);
|
||||
if (this.showHostnames) this.resolveHostnamesForEntries(this.filteredRows());
|
||||
},
|
||||
|
||||
onFetchModeChange(ev) {
|
||||
@@ -1646,7 +1666,7 @@ return view.extend({
|
||||
|
||||
for (let i = 0; i < ips.length && need.length < 32; i++) {
|
||||
const ip = ips[i];
|
||||
if (this.hostnameCache.has(ip)) continue;
|
||||
if (hostname.lruGet(this.hostnameCache, ip) !== undefined) continue;
|
||||
if (hostname.failIsHot(this.hostnameFailed, ip, now)) continue;
|
||||
need.push(ip);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user