perfectionist-plugins 1.6.0 → 1.8.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/auto-read.js +59 -2
- package/package.json +1 -1
- package/perfectionist-utils.js +27 -8
package/auto-read.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const PLUGIN_ID = "auto-read";
|
|
2
|
-
const version = "1.
|
|
2
|
+
const version = "1.1.0";
|
|
3
3
|
|
|
4
4
|
const SWEEP_DEBOUNCE_MS = 500;
|
|
5
5
|
const ITEM_COOLDOWN_MS = 10 * 60 * 1000;
|
|
@@ -9,6 +9,16 @@ const MISSIONS_URI = "/lol-missions/v1/missions";
|
|
|
9
9
|
const MISSIONS_PLAYER_URI = "/lol-missions/v1/player";
|
|
10
10
|
const LOOT_URI = "/lol-loot/v1/player-loot";
|
|
11
11
|
const CLASH_FLAGS_URI = "/lol-clash/v1/simple-state-flags";
|
|
12
|
+
const REWARDS_GRANTS_URI = "/lol-rewards/v1/grants";
|
|
13
|
+
const REWARDS_VIEW_URI = "/lol-rewards/v1/grants/view";
|
|
14
|
+
const LOOT_NOTIF_URI = "/lol-loot/v1/player-loot-notifications";
|
|
15
|
+
const MASTERY_NOTIF_URI = "/lol-champion-mastery/v1/notifications";
|
|
16
|
+
const MASTERY_ACK_URI = "/lol-champion-mastery/v1/notifications/ack";
|
|
17
|
+
const HONOR_NOTICES = [
|
|
18
|
+
{ uri: "/lol-honor-v2/v1/reward-granted", ack: "/lol-honor-v2/v1/reward-granted/ack", present: (d) => Number(d?.quantity ?? -1) >= 0 || Boolean(d?.rewardType) },
|
|
19
|
+
{ uri: "/lol-honor-v2/v1/mutual-honor", ack: "/lol-honor-v2/v1/mutual-honor/ack", present: (d) => (d?.summoners?.length ?? 0) > 0 },
|
|
20
|
+
{ uri: "/lol-honor-v2/v1/level-change", ack: "/lol-honor-v2/v1/level-change/ack", present: (d) => Number(d?.currentState?.level ?? -1) >= 0 },
|
|
21
|
+
];
|
|
12
22
|
const RANKED_NOTIF_URI = "/lol-ranked/v1/notifications";
|
|
13
23
|
const EOS_NOTIF_URI = "/lol-ranked/v1/eos-notifications";
|
|
14
24
|
const NOTICE_LIST_URIS = [
|
|
@@ -39,6 +49,7 @@ let sweepRunning = false;
|
|
|
39
49
|
let sweepQueued = false;
|
|
40
50
|
let unsubscribes = [];
|
|
41
51
|
const cooldowns = new Map();
|
|
52
|
+
const markedGrants = new Set();
|
|
42
53
|
|
|
43
54
|
function on(key) {
|
|
44
55
|
try {
|
|
@@ -116,6 +127,49 @@ async function sweepClash() {
|
|
|
116
127
|
}
|
|
117
128
|
}
|
|
118
129
|
|
|
130
|
+
async function sweepRewards() {
|
|
131
|
+
const grants = await getJson(REWARDS_GRANTS_URI).catch(() => null);
|
|
132
|
+
if (Array.isArray(grants) && grants.length && ready("rewards-grants", BULK_COOLDOWN_MS)) {
|
|
133
|
+
const ids = [];
|
|
134
|
+
for (const grant of grants) {
|
|
135
|
+
const id = grant?.grantId ?? grant?.id;
|
|
136
|
+
if (typeof id !== "string" || !id || markedGrants.has(id)) continue;
|
|
137
|
+
ids.push(id);
|
|
138
|
+
}
|
|
139
|
+
if (ids.length) {
|
|
140
|
+
stamp("rewards-grants");
|
|
141
|
+
for (const id of ids) markedGrants.add(id);
|
|
142
|
+
await sendJson("PATCH", REWARDS_VIEW_URI, ids).catch(() => {
|
|
143
|
+
for (const id of ids) markedGrants.delete(id);
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const notes = await getJson(LOOT_NOTIF_URI).catch(() => null);
|
|
149
|
+
if (Array.isArray(notes)) {
|
|
150
|
+
for (const note of notes) {
|
|
151
|
+
const id = note?.id ?? note?.lootId;
|
|
152
|
+
if (!id || !ready(`lootnote:${id}`, ITEM_COOLDOWN_MS)) continue;
|
|
153
|
+
stamp(`lootnote:${id}`);
|
|
154
|
+
await sendJson("POST", `${LOOT_NOTIF_URI}/${encodeURIComponent(id)}/acknowledge`).catch(() => {});
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const mastery = await getJson(MASTERY_NOTIF_URI).catch(() => null);
|
|
159
|
+
if (Number(mastery?.championId ?? 0) > 0 && ready("mastery", ITEM_COOLDOWN_MS)) {
|
|
160
|
+
stamp("mastery");
|
|
161
|
+
await sendJson("POST", MASTERY_ACK_URI).catch(() => {});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
for (const notice of HONOR_NOTICES) {
|
|
165
|
+
const data = await getJson(notice.uri).catch(() => null);
|
|
166
|
+
const key = `honor:${notice.uri}`;
|
|
167
|
+
if (!data || !notice.present(data) || !ready(key, ITEM_COOLDOWN_MS)) continue;
|
|
168
|
+
stamp(key);
|
|
169
|
+
await sendJson("POST", notice.ack).catch(() => {});
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
119
173
|
async function sweepRanked() {
|
|
120
174
|
for (const uri of [RANKED_NOTIF_URI, EOS_NOTIF_URI]) {
|
|
121
175
|
const list = await getJson(uri).catch(() => null);
|
|
@@ -176,6 +230,7 @@ async function runSweep() {
|
|
|
176
230
|
try {
|
|
177
231
|
if (on("quests")) await sweepQuests().catch(() => {});
|
|
178
232
|
if (on("loot")) await sweepLootMarks().catch(() => {});
|
|
233
|
+
if (on("rewards")) await sweepRewards().catch(() => {});
|
|
179
234
|
if (on("clash")) await sweepClash().catch(() => {});
|
|
180
235
|
if (on("ranked")) await sweepRanked().catch(() => {});
|
|
181
236
|
if (on("notices")) await sweepNotices().catch(() => {});
|
|
@@ -192,7 +247,7 @@ function onEnable(utils) {
|
|
|
192
247
|
api = utils;
|
|
193
248
|
active = true;
|
|
194
249
|
cooldowns.clear();
|
|
195
|
-
for (const uri of [MISSIONS_URI, LOOT_URI, CLASH_FLAGS_URI, RANKED_NOTIF_URI, EOS_NOTIF_URI, ...NOTICE_LIST_URIS]) {
|
|
250
|
+
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]) {
|
|
196
251
|
try {
|
|
197
252
|
const off = api.subscribe(uri, scheduleSweep);
|
|
198
253
|
if (off) unsubscribes.push(off);
|
|
@@ -215,6 +270,7 @@ function onDisable() {
|
|
|
215
270
|
}
|
|
216
271
|
unsubscribes = [];
|
|
217
272
|
cooldowns.clear();
|
|
273
|
+
markedGrants.clear();
|
|
218
274
|
api = null;
|
|
219
275
|
syncPips();
|
|
220
276
|
}
|
|
@@ -242,6 +298,7 @@ export function init() {
|
|
|
242
298
|
items: [
|
|
243
299
|
{ id: "quests", label: "Quests", description: "Quest and mission badges, including the mission button counter.", default: true },
|
|
244
300
|
{ id: "loot", label: "Loot marks", description: "The new mark on freshly earned loot.", default: true },
|
|
301
|
+
{ id: "rewards", label: "Rewards", description: "The dot on your avatar for new tokens, titles and banners, plus mastery, honor and loot notifications.", default: true },
|
|
245
302
|
{ id: "clash", label: "Clash", description: "Clash tab flags and Clash notifications.", default: true },
|
|
246
303
|
{ id: "ranked", label: "Ranked", description: "Ranked, end-of-season and champion mastery notices.", default: true },
|
|
247
304
|
{ id: "notices", label: "Notices", description: "Patch, patcher, leaver buster, lobby, behavior and gameflow notices.", default: true },
|
package/package.json
CHANGED
package/perfectionist-utils.js
CHANGED
|
@@ -6,7 +6,7 @@ const PANEL_ID = "perfectionist-plugins-panel";
|
|
|
6
6
|
const STYLE_ID = "perfectionist-plugins-style";
|
|
7
7
|
const TAB_TITLE = "Perfectionism";
|
|
8
8
|
|
|
9
|
-
export const version = "1.
|
|
9
|
+
export const version = "1.7.0";
|
|
10
10
|
|
|
11
11
|
const PKG = "perfectionist-plugins";
|
|
12
12
|
const CDN = "https://cdn.jsdelivr.net/npm";
|
|
@@ -54,7 +54,7 @@ const BUNDLED_MODULES = [
|
|
|
54
54
|
id: "auto-read",
|
|
55
55
|
file: "auto-read.js",
|
|
56
56
|
name: "Auto Read",
|
|
57
|
-
version: "1.
|
|
57
|
+
version: "1.1.0",
|
|
58
58
|
description: "Automatically marks quests, loot, Clash and client notices as read so no badge or dot stays lit.",
|
|
59
59
|
},
|
|
60
60
|
];
|
|
@@ -267,7 +267,7 @@ function getOption(id, key) {
|
|
|
267
267
|
return stored === undefined ? Boolean(fallback) : Boolean(stored);
|
|
268
268
|
}
|
|
269
269
|
|
|
270
|
-
function setOption(id, key, value) {
|
|
270
|
+
function setOption(id, key, value, refresh = true) {
|
|
271
271
|
if (!state.options[id]) state.options[id] = {};
|
|
272
272
|
state.options[id][key] = Boolean(value);
|
|
273
273
|
saveState();
|
|
@@ -277,7 +277,7 @@ function setOption(id, key, value) {
|
|
|
277
277
|
} catch (error) {
|
|
278
278
|
logError(`${entry?.name ?? id} could not apply the option change.`, error);
|
|
279
279
|
}
|
|
280
|
-
refreshPanel();
|
|
280
|
+
if (refresh) refreshPanel();
|
|
281
281
|
}
|
|
282
282
|
|
|
283
283
|
function getPlugins() {
|
|
@@ -599,7 +599,7 @@ function buildOptionRow(mod, option, disabled, onChange) {
|
|
|
599
599
|
input.setAttribute("aria-label", `${mod.name}: ${option.label}`);
|
|
600
600
|
input.addEventListener("change", () => {
|
|
601
601
|
if (onChange) onChange(input.checked);
|
|
602
|
-
else setOption(mod.id, option.key, input.checked);
|
|
602
|
+
else setOption(mod.id, option.key, input.checked, false);
|
|
603
603
|
});
|
|
604
604
|
row.append(input, el("span", "perf-box"), el("span", "perf-opt-label", option.label));
|
|
605
605
|
return row;
|
|
@@ -616,7 +616,10 @@ function buildChips(mod, option) {
|
|
|
616
616
|
chip.type = "button";
|
|
617
617
|
chip.title = item.description ?? "";
|
|
618
618
|
if (getOption(mod.id, key)) chip.classList.add("perf-chip--on");
|
|
619
|
-
chip.addEventListener("click", () =>
|
|
619
|
+
chip.addEventListener("click", () => {
|
|
620
|
+
setOption(mod.id, key, !getOption(mod.id, key), false);
|
|
621
|
+
chip.classList.toggle("perf-chip--on", getOption(mod.id, key));
|
|
622
|
+
});
|
|
620
623
|
row.append(chip);
|
|
621
624
|
}
|
|
622
625
|
block.append(row);
|
|
@@ -650,7 +653,7 @@ function buildOptions(mod) {
|
|
|
650
653
|
}
|
|
651
654
|
const master = buildOptionRow(mod, option, false, (checked) => {
|
|
652
655
|
for (const input of childInputs) input.disabled = !checked;
|
|
653
|
-
setOption(mod.id, option.key, checked);
|
|
656
|
+
setOption(mod.id, option.key, checked, false);
|
|
654
657
|
});
|
|
655
658
|
const groupKey = `${mod.id}:${option.key}`;
|
|
656
659
|
const setExpanded = (open) => {
|
|
@@ -743,9 +746,25 @@ function buildPanel() {
|
|
|
743
746
|
return panel;
|
|
744
747
|
}
|
|
745
748
|
|
|
749
|
+
function panelScrollTop(panel) {
|
|
750
|
+
return panel?.querySelector("lol-uikit-scrollable")?.scrollTop ?? 0;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
function applyScrollTop(panel, top) {
|
|
754
|
+
if (!top || !panel) return;
|
|
755
|
+
const host = panel.querySelector("lol-uikit-scrollable");
|
|
756
|
+
if (host) host.scrollTop = top;
|
|
757
|
+
}
|
|
758
|
+
|
|
746
759
|
function refreshPanel() {
|
|
747
760
|
const current = document.getElementById(PANEL_ID);
|
|
748
|
-
if (current)
|
|
761
|
+
if (!current) return;
|
|
762
|
+
const top = panelScrollTop(current);
|
|
763
|
+
const next = buildPanel();
|
|
764
|
+
current.replaceWith(next);
|
|
765
|
+
if (!top) return;
|
|
766
|
+
applyScrollTop(next, top);
|
|
767
|
+
requestAnimationFrame(() => applyScrollTop(next, top));
|
|
749
768
|
}
|
|
750
769
|
|
|
751
770
|
function setNavActive(activeNav) {
|