perfectionist-plugins 2.4.8 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -52
- package/auto-accept.js +296 -294
- package/auto-claimer.js +1 -37
- package/auto-read.js +107 -42
- package/ban-blocker.js +483 -732
- package/better-client.js +362 -793
- package/dodge-helper.js +377 -713
- package/hide-unowned-skins.js +63 -687
- package/package.json +40 -40
- package/perfectionist-utils.js +539 -301
- package/unlock-profile-skins.js +173 -652
package/auto-read.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const PLUGIN_ID = "auto-read";
|
|
2
|
-
const version = "1.
|
|
2
|
+
const version = "1.3.0";
|
|
3
3
|
|
|
4
4
|
const SWEEP_DEBOUNCE_MS = 500;
|
|
5
5
|
const ITEM_COOLDOWN_MS = 10 * 60 * 1000;
|
|
@@ -46,14 +46,35 @@ const LEVELUP_PREFS_URI = "/lol-settings/v2/account/LCUPreferences/lol-challenge
|
|
|
46
46
|
const TFT_BATTLE_PASS_URI = "/lol-tft-pass/v1/battle-pass";
|
|
47
47
|
const TFT_HOME_HUB_URI = "/lol-tft/v1/tft/homeHub";
|
|
48
48
|
const TFT_PREFS_URI = "/lol-settings/v2/account/LCUPreferences/lol-tft";
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
// The pips on the home screen's activity tabs. The client shows one for every tab that is not in
|
|
50
|
+
// tabsViewed, and on the patch notes tab until lastPatchNotesViewed matches the current major.minor build.
|
|
51
|
+
const ACTIVITY_PREFS_URI = "/lol-settings/v2/account/LCUPreferences/activity-center";
|
|
52
|
+
const ACTIVITY_NAV_URI = "/lol-activity-center/v1/content/client-nav";
|
|
53
|
+
const BUILD_URI = "/system/v1/builds";
|
|
54
|
+
const PATCH_NOTES_TAB = "lol-patch-notes";
|
|
55
|
+
const INFO_HUB_TAB = "info-hub";
|
|
56
|
+
// The client reads the activity-center setting once at startup, so a pip it already drew stays until the next
|
|
57
|
+
// restart even after it was marked seen. Only those already-seen pips are hidden (they are read at the source).
|
|
58
|
+
const SEEN_PIPS_STYLE_ID = "auto-read-seen-pips";
|
|
59
|
+
const SEEN_PIPS_CSS = ".activity-center__tab_label_notification_pip { display: none !important; }";
|
|
60
|
+
|
|
61
|
+
function hideSeenPips(hide) {
|
|
62
|
+
const existing = document.getElementById(SEEN_PIPS_STYLE_ID);
|
|
63
|
+
if (hide && !existing) {
|
|
64
|
+
const style = document.createElement("style");
|
|
65
|
+
style.id = SEEN_PIPS_STYLE_ID;
|
|
66
|
+
style.textContent = SEEN_PIPS_CSS;
|
|
67
|
+
document.head.appendChild(style);
|
|
68
|
+
} else if (!hide && existing) {
|
|
69
|
+
existing.remove();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
51
72
|
|
|
52
73
|
let api = null;
|
|
53
74
|
let active = false;
|
|
54
75
|
let sweepTimer = null;
|
|
55
76
|
let sweepRunning = false;
|
|
56
|
-
|
|
77
|
+
const pendingCategories = new Set();
|
|
57
78
|
let unsubscribes = [];
|
|
58
79
|
const cooldowns = new Map();
|
|
59
80
|
const markedGrants = new Set();
|
|
@@ -267,49 +288,92 @@ async function sweepTft() {
|
|
|
267
288
|
await sendJson("PATCH", TFT_PREFS_URI, { data: { seenOfferIds: target }, schemaVersion: 1 }).catch(() => {});
|
|
268
289
|
}
|
|
269
290
|
|
|
270
|
-
function
|
|
271
|
-
const
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
291
|
+
async function sweepPips() {
|
|
292
|
+
const [prefs, nav, build] = await Promise.all([
|
|
293
|
+
getJson(ACTIVITY_PREFS_URI).catch(() => null),
|
|
294
|
+
getJson(ACTIVITY_NAV_URI).catch(() => null),
|
|
295
|
+
getJson(BUILD_URI).catch(() => null),
|
|
296
|
+
]);
|
|
297
|
+
const tabs = (Array.isArray(nav?.data) ? nav.data : []).map((tab) => tab?.navigationItemID).filter((id) => typeof id === "string" && id);
|
|
298
|
+
if (!tabs.length) return;
|
|
299
|
+
let viewed = {};
|
|
300
|
+
try {
|
|
301
|
+
viewed = JSON.parse(prefs?.data?.tabsViewed ?? "{}") || {};
|
|
302
|
+
} catch {}
|
|
303
|
+
const patch = String(build?.version ?? "").split(".").slice(0, 2).join(".");
|
|
304
|
+
const missing = [...tabs, INFO_HUB_TAB].filter((id) => id !== PATCH_NOTES_TAB && viewed[id] !== true);
|
|
305
|
+
const patchUnseen = Boolean(patch) && tabs.includes(PATCH_NOTES_TAB) && prefs?.data?.lastPatchNotesViewed !== patch;
|
|
306
|
+
if (!missing.length && !patchUnseen) {
|
|
307
|
+
hideSeenPips(true);
|
|
308
|
+
return;
|
|
280
309
|
}
|
|
310
|
+
if (!ready("activity-pips", BULK_COOLDOWN_MS)) return;
|
|
311
|
+
stamp("activity-pips");
|
|
312
|
+
const next = { ...viewed };
|
|
313
|
+
for (const id of missing) next[id] = true;
|
|
314
|
+
const data = { tabsViewed: JSON.stringify(next) };
|
|
315
|
+
if (patchUnseen) data.lastPatchNotesViewed = patch;
|
|
316
|
+
const saved = await sendJson("PATCH", ACTIVITY_PREFS_URI, { data, schemaVersion: 1 }).then(() => true, () => false);
|
|
317
|
+
if (saved && active) hideSeenPips(true);
|
|
281
318
|
}
|
|
282
319
|
|
|
283
|
-
|
|
320
|
+
const SWEEPS = {
|
|
321
|
+
quests: () => sweepQuests(),
|
|
322
|
+
loot: () => sweepLootMarks(),
|
|
323
|
+
rewards: async () => {
|
|
324
|
+
await sweepRewards().catch(() => {});
|
|
325
|
+
await sweepIdentity().catch(() => {});
|
|
326
|
+
},
|
|
327
|
+
tft: () => sweepTft(),
|
|
328
|
+
pips: () => sweepPips(),
|
|
329
|
+
clash: () => sweepClash(),
|
|
330
|
+
ranked: () => sweepRanked(),
|
|
331
|
+
notices: () => sweepNotices(),
|
|
332
|
+
};
|
|
333
|
+
const ALL_CATEGORIES = Object.keys(SWEEPS);
|
|
334
|
+
|
|
335
|
+
// Which category a pushed URI belongs to, so one change only re-checks what it can affect.
|
|
336
|
+
const URI_CATEGORIES = new Map([
|
|
337
|
+
[MISSIONS_URI, ["quests"]],
|
|
338
|
+
[LOOT_URI, ["loot"]],
|
|
339
|
+
[CLASH_FLAGS_URI, ["clash"]],
|
|
340
|
+
[REWARDS_GRANTS_URI, ["rewards"]],
|
|
341
|
+
[LOOT_NOTIF_URI, ["rewards"]],
|
|
342
|
+
[MASTERY_NOTIF_URI, ["rewards"]],
|
|
343
|
+
...HONOR_NOTICES.map((notice) => [notice.uri, ["rewards"]]),
|
|
344
|
+
...IDENTITY_NOTICE_TYPES.map((type) => [`/lol-inventory/v1/notifications/${type}`, ["rewards"]]),
|
|
345
|
+
[TOKENS_PREFS_URI, ["rewards"]],
|
|
346
|
+
[LEVELUP_PREFS_URI, ["rewards"]],
|
|
347
|
+
[RANKED_NOTIF_URI, ["ranked"]],
|
|
348
|
+
[EOS_NOTIF_URI, ["ranked"]],
|
|
349
|
+
...NOTICE_LIST_URIS.map((uri) => [uri, ["notices"]]),
|
|
350
|
+
[TFT_BATTLE_PASS_URI, ["tft"]],
|
|
351
|
+
[TFT_HOME_HUB_URI, ["tft"]],
|
|
352
|
+
[TFT_PREFS_URI, ["tft"]],
|
|
353
|
+
[ACTIVITY_PREFS_URI, ["pips"]],
|
|
354
|
+
[ACTIVITY_NAV_URI, ["pips"]],
|
|
355
|
+
]);
|
|
356
|
+
|
|
357
|
+
function scheduleSweep(categories = ALL_CATEGORIES) {
|
|
284
358
|
if (!active) return;
|
|
359
|
+
for (const category of categories) pendingCategories.add(category);
|
|
285
360
|
clearTimeout(sweepTimer);
|
|
286
361
|
sweepTimer = setTimeout(runSweep, SWEEP_DEBOUNCE_MS);
|
|
287
362
|
}
|
|
288
363
|
|
|
289
364
|
async function runSweep() {
|
|
290
|
-
if (!active) return;
|
|
291
|
-
if (sweepRunning) {
|
|
292
|
-
sweepQueued = true;
|
|
293
|
-
return;
|
|
294
|
-
}
|
|
365
|
+
if (!active || sweepRunning) return;
|
|
295
366
|
sweepRunning = true;
|
|
296
367
|
try {
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
368
|
+
while (active && pendingCategories.size) {
|
|
369
|
+
const batch = [...pendingCategories];
|
|
370
|
+
pendingCategories.clear();
|
|
371
|
+
for (const category of batch) {
|
|
372
|
+
if (on(category)) await Promise.resolve(SWEEPS[category]()).catch(() => {});
|
|
373
|
+
}
|
|
302
374
|
}
|
|
303
|
-
if (on("tft")) await sweepTft().catch(() => {});
|
|
304
|
-
if (on("clash")) await sweepClash().catch(() => {});
|
|
305
|
-
if (on("ranked")) await sweepRanked().catch(() => {});
|
|
306
|
-
if (on("notices")) await sweepNotices().catch(() => {});
|
|
307
375
|
} finally {
|
|
308
376
|
sweepRunning = false;
|
|
309
|
-
if (sweepQueued) {
|
|
310
|
-
sweepQueued = false;
|
|
311
|
-
scheduleSweep();
|
|
312
|
-
}
|
|
313
377
|
}
|
|
314
378
|
}
|
|
315
379
|
|
|
@@ -317,14 +381,14 @@ function onEnable(utils) {
|
|
|
317
381
|
api = utils;
|
|
318
382
|
active = true;
|
|
319
383
|
cooldowns.clear();
|
|
320
|
-
for (const uri of [MISSIONS_URI, LOOT_URI, CLASH_FLAGS_URI, REWARDS_GRANTS_URI, LOOT_NOTIF_URI, MASTERY_NOTIF_URI, ...HONOR_NOTICES.map((n) => n.uri), RANKED_NOTIF_URI, EOS_NOTIF_URI, ...NOTICE_LIST_URIS, ...IDENTITY_NOTICE_TYPES.map((type) => `/lol-inventory/v1/notifications/${type}`), TOKENS_PREFS_URI, LEVELUP_PREFS_URI, TFT_BATTLE_PASS_URI, TFT_HOME_HUB_URI, TFT_PREFS_URI]) {
|
|
384
|
+
for (const uri of [MISSIONS_URI, LOOT_URI, CLASH_FLAGS_URI, REWARDS_GRANTS_URI, LOOT_NOTIF_URI, MASTERY_NOTIF_URI, ...HONOR_NOTICES.map((n) => n.uri), RANKED_NOTIF_URI, EOS_NOTIF_URI, ...NOTICE_LIST_URIS, ...IDENTITY_NOTICE_TYPES.map((type) => `/lol-inventory/v1/notifications/${type}`), TOKENS_PREFS_URI, LEVELUP_PREFS_URI, TFT_BATTLE_PASS_URI, TFT_HOME_HUB_URI, TFT_PREFS_URI, ACTIVITY_PREFS_URI, ACTIVITY_NAV_URI]) {
|
|
321
385
|
try {
|
|
322
|
-
const
|
|
386
|
+
const categories = URI_CATEGORIES.get(uri) ?? ALL_CATEGORIES;
|
|
387
|
+
const off = api.subscribe(uri, () => scheduleSweep(categories));
|
|
323
388
|
if (off) unsubscribes.push(off);
|
|
324
389
|
} catch {}
|
|
325
390
|
}
|
|
326
391
|
scheduleSweep();
|
|
327
|
-
syncPips();
|
|
328
392
|
}
|
|
329
393
|
|
|
330
394
|
function onDisable() {
|
|
@@ -332,7 +396,7 @@ function onDisable() {
|
|
|
332
396
|
clearTimeout(sweepTimer);
|
|
333
397
|
sweepTimer = null;
|
|
334
398
|
sweepRunning = false;
|
|
335
|
-
|
|
399
|
+
pendingCategories.clear();
|
|
336
400
|
for (const off of unsubscribes) {
|
|
337
401
|
try {
|
|
338
402
|
off();
|
|
@@ -341,14 +405,15 @@ function onDisable() {
|
|
|
341
405
|
unsubscribes = [];
|
|
342
406
|
cooldowns.clear();
|
|
343
407
|
markedGrants.clear();
|
|
408
|
+
hideSeenPips(false);
|
|
344
409
|
api = null;
|
|
345
|
-
syncPips();
|
|
346
410
|
}
|
|
347
411
|
|
|
348
|
-
function onOptionChange() {
|
|
412
|
+
function onOptionChange(key, value) {
|
|
349
413
|
if (!active) return;
|
|
350
|
-
|
|
351
|
-
|
|
414
|
+
const category = String(key).replace(/^read./, "");
|
|
415
|
+
if (value && SWEEPS[category]) scheduleSweep([category]);
|
|
416
|
+
if (category === "pips" && !value) hideSeenPips(false);
|
|
352
417
|
}
|
|
353
418
|
|
|
354
419
|
export function init() {
|
|
@@ -372,7 +437,7 @@ export function init() {
|
|
|
372
437
|
{ id: "clash", label: "Clash", description: "Clash tab flags and Clash notifications.", default: true },
|
|
373
438
|
{ id: "ranked", label: "Ranked", description: "Ranked, end-of-season and champion mastery notices.", default: true },
|
|
374
439
|
{ id: "notices", label: "Notices", description: "Patch, patcher, leaver buster, lobby, behavior and gameflow notices.", default: true },
|
|
375
|
-
{ id: "pips", label: "Tab pips", description: "
|
|
440
|
+
{ id: "pips", label: "Tab pips", description: "Marks the home screen's activity tabs and patch notes as seen, so their new pips go away.", default: true },
|
|
376
441
|
],
|
|
377
442
|
},
|
|
378
443
|
],
|