🌴 Sync 2026-08-31 11:11:11

This commit is contained in:
github-actions[bot] committed 2026-08-31 11:11:11 +08:00
1 parent 5151f60573
commit 9ba6bd09a1
5 files changed
+60 -24

No files matched your search

+1 -1
View File
@@ -17,7 +17,7 @@ LUCI_NAME:=luci-theme-footstrap
FOOTSTRAP_VERSION?=
ifneq ($(FOOTSTRAP_VERSION),)
PKG_VERSION:=$(FOOTSTRAP_VERSION)
PKG_RELEASE:=46
PKG_RELEASE:=47
endif
LUCI_TITLE:=Footstrap Theme
@@ -104,7 +104,9 @@ function index() {
* An optional package can add rows to the same list — one indexes the SECTION titles inside each
* page, so "footstrap" finds System -> Appearance. A source hands over entries in the shape
* buildIndex() produces and nothing else: the matching, the ranking and the rendering stay here,
* or two lists would disagree about what a hit is.
* or two lists would disagree about what a hit is. Two fields are the source's alone: `onTake`,
* called when the row is chosen, and `key`, what the recents list stores it under when its `path`
* is not its own (see keyOf).
*
* Registration is a GLOBAL ARRAY, not an export a package requires. This module is fetched on the
* first gesture and most sessions never make it; a package that had to `require` it to register
@@ -177,20 +179,31 @@ function search(q, limit) {
/* What the palette shows before anything is typed: an admin lives in three or four pages, so the
* empty state is its most-used view.
*
* Only the path is stored, never the title — the title is resolved through the index on every
* render, so it follows the UI language and a page removed with its package drops out instead of
* lingering as a dead row. */
* Only the KEY is stored, never the title — the title is resolved through the pool on every
* render, so it follows the UI language and a row whose package went away drops out instead of
* lingering as a dead row. A page's key is its menu path; a row from a source carries its own
* `key`, because a section has no dispatcher node and therefore no path that is only its own —
* the sections source keys one `admin/system/system#Footstrap`, the page it is on plus its own
* heading. */
const RECENT_KEY = 'fs-recent';
const RECENT_MAX = 8;
/* the string a row is remembered under, and the one menu-footstrap-common's remember() writes */
function keyOf(e) {
return e.key || e.path;
}
/* The list is WRITTEN by menu-footstrap-common.js, which is on every page — this module is not any
* more, and a palette that only loads when it is opened cannot be what records where the admin has
* been. Read here, at open time, so it is always current. `prefs.lsGetArr` owns the parse, the
* corruption guard and the Array check; only the "these are paths" filter belongs here. */
* corruption guard and the Array check; only the "these are keys" filter belongs here. */
function recentEntries() {
const recent = prefs.lsGetArr(RECENT_KEY).filter((x) => typeof x === 'string');
const byPath = new Map(index().map((e) => [ e.path, e ]));
return recent.map((p) => byPath.get(p)).filter(Boolean).slice(0, RECENT_MAX);
/* pool(), not index(): a section is recalled exactly as a page is. Against the index alone a
* section key resolved to nothing and the row silently vanished, so taking "Footstrap" left
* only "System" in the list — the page path is all either row carries. */
const byKey = new Map(pool().map((e) => [ keyOf(e), e ]));
return recent.map((k) => byKey.get(k)).filter(Boolean).slice(0, RECENT_MAX);
}
/* ---- the palette -------------------------------------------------------- */
@@ -54,11 +54,20 @@ const RECENT_KEY = 'fs-recent';
const RECENT_MAX = 8;
const RECENT_WARM = 5;
function remember(segs) {
if (!Array.isArray(segs) || !segs.length) return;
const path = segs.join('/');
/* A key is a menu path, or a page path plus the heading of a section inside it
* (`admin/system/system#Footstrap`) — a section has no dispatcher node to name it, and only the
* source that produced the row can build that half. Exported for exactly that: the writer stays
* one function, or the two halves would drift on the cap and the de-duplication. */
function remember(key) {
if (typeof key !== 'string' || !key) return;
const recent = prefs.lsGetArr(RECENT_KEY).filter((x) => typeof x === 'string');
prefs.lsSet(RECENT_KEY, JSON.stringify([ path ].concat(recent.filter((p) => p !== path)).slice(0, RECENT_MAX)));
prefs.lsSet(RECENT_KEY, JSON.stringify([ key ].concat(recent.filter((p) => p !== key)).slice(0, RECENT_MAX)));
}
/* the page half of a key: what the router can navigate to and what warmRecent() prefetches */
function pageOf(key) {
const h = key.indexOf('#');
return h < 0 ? key : key.slice(0, h);
}
/* ---- warm the pages this admin actually uses ----
@@ -75,8 +84,10 @@ function remember(segs) {
function warmRecent() {
try { if (navigator.connection && navigator.connection.saveData) return; } catch (e) {}
const here = (L.env.dispatchpath || []).join('/');
const paths = prefs.lsGetArr(RECENT_KEY)
.filter((p) => typeof p === 'string' && p !== here).slice(0, RECENT_WARM);
/* Keys, not paths: a section key names the page it sits on, and two sections of one page must
* warm it once — the module chain is the page's. */
const keys = prefs.lsGetArr(RECENT_KEY).filter((p) => typeof p === 'string');
const paths = [ ...new Set(keys.map(pageOf)) ].filter((p) => p !== here).slice(0, RECENT_WARM);
if (!paths.length) return;
const go = () => paths.forEach((p) => router.prefetchSegs(p.split('/')));
if (typeof window.requestIdleCallback === 'function')
@@ -91,8 +102,9 @@ function wireSearch() {
const RT = window.L;
/* the page this full load landed on; onNavigate covers the SPA path afterwards */
remember(L.env.dispatchpath || []);
router.onNavigate(remember);
const rememberSegs = (segs) => remember((segs || []).join('/'));
rememberSegs(L.env.dispatchpath);
router.onNavigate(rememberSegs);
warmRecent();
/* One fetch, on the first gesture. The module builds its overlay and opens itself; every later
@@ -219,6 +231,10 @@ ensureOverviewHelpers();
* halves (fs-menutree, fs-prefs) are separate modules. */
return baseclass.extend({
/* the seam a companion package writes its own rows into the recents list through; see
* remember() for what a key is */
remember,
init(renderMainMenu) {
/* First, and outside the promise: a third-party sheet that outranks the chrome is already
* painting (fs-sheets: openclash's `* { margin: 0; padding: 0 }`). Deferring this to
+2 -2
View File
@@ -14,8 +14,8 @@ MISE_HASH_x86_64:=3832f39c325e343f81fe3d92b2447c5d1a5eea1bc85092bb7b6c2580622264
MISE_HASH_aarch64:=06186cfbfe947049b21d58575fb0ea800cc26ed1375f20f4b678cb3a9d679437
PKG_NAME:=mise
PKG_VERSION:=2026.8.14
PKG_RELEASE:=1
PKG_VERSION:=2026.8.15
PKG_RELEASE:=2
PKG_SOURCE:=$(PKG_NAME)-v$(PKG_VERSION)-linux-$(MISE_ARCH)-musl.tar.gz
PKG_SOURCE_URL:=https://github.com/jdx/mise/releases/download/v$(PKG_VERSION)/
PKG_HASH:=skip
+13 -6
View File
@@ -43,12 +43,12 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=wwand
PKG_RELEASE:=14
PKG_RELEASE:=15
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/ddimension/wwand.git
PKG_SOURCE_VERSION:=199a2f8a2f242376adb6e3781443750f3d71c502
PKG_SOURCE_DATE:=2026-08-30
PKG_SOURCE_VERSION:=95acd0064d8307cde67a05c5a93bf9e62254ab8d
PKG_SOURCE_DATE:=2026-08-31
PKG_MIRROR_HASH:=skip
PKG_LICENSE:=GPL-2.0-only
@@ -89,15 +89,15 @@ UCDIR:=/usr/share/ucode/wwand
# silently ship in the base too. The per-backend install lists below carry the
# QMI/MBIM/NCM/eSIM modules; main.uc/wwandctl.uc install as executables.
WWAND_BASE_UC:=apndb.uc atcmd.uc atcmd_parse.uc atport.uc backend.uc board.uc \
client.uc config.uc config_check.uc context_common.uc context_monitor_qmi.uc \
carrier_config.uc client.uc config.uc config_check.uc context_common.uc context_monitor_qmi.uc \
ctx_settings.uc daemon.uc discovery.uc hwops.uc log.uc modem_datapath_qmi.uc \
modem_common.uc modem_init_qmi.uc modem_quirks.uc modeswitch.uc ncm_vendors.uc \
netlink.uc netsel_ops.uc protocol_switch.uc reconnect.uc recovery.uc regdetail.uc \
sim.uc sim_plmn.uc simops.uc sms.uc sms_pdu.uc telemetry_mbim.uc telemetry_ncm.uc \
telemetry_qmi.uc transport.uc ubus.uc
WWAND_BASE_CODEC:=arfcn_bands.uc hex.uc qmux.uc tlv.uc
WWAND_BASE_SCHEMA:=ctl.uc dms.uc dsd.uc loc.uc loc_lazy.uc merge.uc nas.uc rat.uc \
uim.uc wda.uc wds.uc wms.uc wms_lazy.uc
WWAND_BASE_SCHEMA:=cat.uc ctl.uc dms.uc dsd.uc loc.uc loc_lazy.uc merge.uc nas.uc pdc.uc rat.uc \
tmd.uc uim.uc wda.uc wds.uc wms.uc wms_lazy.uc
# DEVELOPERS: set CONFIG_WWAND_UCODE_SOURCE to ship readable .uc source
# instead of bytecode — for editing modules live under /usr/share/ucode/wwand
@@ -201,6 +201,13 @@ define Package/wwand/install
# new_id bind / late kmodloader) re-kick a modem parked in no_at_port backoff
$(INSTALL_DIR) $(1)/etc/hotplug.d/tty
$(INSTALL_DATA) $(PKG_BUILD_DIR)/files/wwand.hotplug.tty $(1)/etc/hotplug.d/tty/20-wwand
# usb hotplug: bind qmi_wwan to the Huawei E1820's ethernet function. The
# kernel hands the device to qmi_wwan (cdc_ether blacklists it) but its
# table entry wants a vendor-specific class this old 802.3 layout does not
# carry, so a scoped dynamic new_id is what makes the control channel appear
# at all — and it is volatile, so it has to be re-created on every replug.
$(INSTALL_DIR) $(1)/etc/hotplug.d/usb
$(INSTALL_DATA) $(PKG_BUILD_DIR)/files/wwand.hotplug.e1820 $(1)/etc/hotplug.d/usb/21-wwand-e1820
# NOTE: the kernel-wwan-subsystem hotplug (/etc/hotplug.d/wwan/20-wwand) is
# NOT installed here — it belongs to wwand-mhi, which also pulls the MHI
# drivers that create /sys/class/wwan in the first place (procd only arms a