mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-01 01:35:13 +08:00
🌴 Sync 2026-08-31 11:11:11
This commit is contained in:
1 parent
5151f60573
commit
9ba6bd09a1
5 files changed
+60
-24
No files matched your search
@@ -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
|
||||
|
||||
Reference in new issue
Block a user