perfectionist-plugins 2.4.6 → 2.4.7
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-accept.js +8 -8
- package/ban-blocker.js +33 -5
- package/hide-unowned-skins.js +3 -21
- package/package.json +1 -1
- package/perfectionist-utils.js +49 -13
package/auto-accept.js
CHANGED
|
@@ -33,8 +33,8 @@ let attempts = 0;
|
|
|
33
33
|
let unsubscribes = [];
|
|
34
34
|
let removeStyle = null;
|
|
35
35
|
let domObserver = null;
|
|
36
|
-
let domTimer = null;
|
|
37
|
-
|
|
36
|
+
let domTimer = null;
|
|
37
|
+
|
|
38
38
|
function enabled() {
|
|
39
39
|
try {
|
|
40
40
|
return api?.getOption?.(PLUGIN_ID, ACCEPT_KEY, true) === true;
|
|
@@ -99,8 +99,8 @@ async function acceptNow() {
|
|
|
99
99
|
} finally {
|
|
100
100
|
sending = false;
|
|
101
101
|
}
|
|
102
|
-
}
|
|
103
|
-
|
|
102
|
+
}
|
|
103
|
+
|
|
104
104
|
function onPhase(raw) {
|
|
105
105
|
const phase = unwrap(raw);
|
|
106
106
|
if (typeof phase !== "string") return;
|
|
@@ -148,8 +148,8 @@ function toggle() {
|
|
|
148
148
|
syncButton();
|
|
149
149
|
if (next) acceptNow();
|
|
150
150
|
else resetReadyCheck();
|
|
151
|
-
}
|
|
152
|
-
|
|
151
|
+
}
|
|
152
|
+
|
|
153
153
|
function buildButton() {
|
|
154
154
|
const root = document.createElement("div");
|
|
155
155
|
root.id = ROOT_ID;
|
|
@@ -165,8 +165,8 @@ function buildButton() {
|
|
|
165
165
|
event.preventDefault();
|
|
166
166
|
event.stopPropagation();
|
|
167
167
|
toggle();
|
|
168
|
-
});
|
|
169
|
-
|
|
168
|
+
});
|
|
169
|
+
|
|
170
170
|
root.append(option);
|
|
171
171
|
return root;
|
|
172
172
|
}
|
package/ban-blocker.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const version = "3.6.
|
|
1
|
+
export const version = "3.6.2";
|
|
2
2
|
|
|
3
3
|
const PLUGIN_ID = "ban-blocker";
|
|
4
4
|
const STYLE_ID = "perfectionist-ban-blocker-style";
|
|
@@ -70,6 +70,7 @@ const fetchedNames = new Set();
|
|
|
70
70
|
const playerNames = new Map();
|
|
71
71
|
const cellToPlayer = new Map();
|
|
72
72
|
const buttons = new Map();
|
|
73
|
+
const swapSeen = new Set();
|
|
73
74
|
const failedUntil = new Map();
|
|
74
75
|
const failCount = new Map();
|
|
75
76
|
let rows = [];
|
|
@@ -159,10 +160,19 @@ function linkPlayer(p, rowName, cellId) {
|
|
|
159
160
|
return root;
|
|
160
161
|
}
|
|
161
162
|
|
|
163
|
+
function pickStarted(s) {
|
|
164
|
+
const actions = s?.actions?.flat?.() ?? [];
|
|
165
|
+
return actions.some((a) => a.type === "pick" && (a.isInProgress || a.completed));
|
|
166
|
+
}
|
|
167
|
+
|
|
162
168
|
function banPending(s) {
|
|
163
|
-
const
|
|
169
|
+
const actions = s?.actions?.flat?.() ?? [];
|
|
170
|
+
const bans = actions.filter((a) => a.type === "ban");
|
|
164
171
|
if (!bans.length) return true;
|
|
165
|
-
|
|
172
|
+
if (bans.some((a) => !a.completed)) return true;
|
|
173
|
+
const phase = s?.timer?.phase;
|
|
174
|
+
if (phase && phase !== "BAN_PICK") return false;
|
|
175
|
+
return !pickStarted(s);
|
|
166
176
|
}
|
|
167
177
|
|
|
168
178
|
function pump() {
|
|
@@ -254,6 +264,7 @@ function onSessionGone() {
|
|
|
254
264
|
lastSession = null;
|
|
255
265
|
goneAway = true;
|
|
256
266
|
uiVisible = false;
|
|
267
|
+
swapSeen.clear();
|
|
257
268
|
removeButtons();
|
|
258
269
|
if (!goneTimer) {
|
|
259
270
|
goneTimer = setTimeout(() => {
|
|
@@ -449,16 +460,31 @@ function isSelfRow(r) {
|
|
|
449
460
|
return lastSession?.localPlayerCellId != null && (r.cell ?? r.slotId) === lastSession.localPlayerCellId;
|
|
450
461
|
}
|
|
451
462
|
|
|
463
|
+
function rowKey(r) {
|
|
464
|
+
return String(r.slotId ?? r.cell ?? r.index);
|
|
465
|
+
}
|
|
466
|
+
|
|
452
467
|
function nativeSwapIn(circle) {
|
|
453
|
-
|
|
468
|
+
if (!circle) return false;
|
|
469
|
+
return [...circle.querySelectorAll(".swap-button-component")].some((el) => el.dataset.bb !== "1");
|
|
454
470
|
}
|
|
455
471
|
|
|
456
472
|
function ensureButtons() {
|
|
457
473
|
const list = getRows();
|
|
458
474
|
for (const r of list) {
|
|
475
|
+
if (!r.circle || !r.circle.isConnected) r.circle = r.el.querySelector(".champion-icon-container");
|
|
459
476
|
if (!r.circle || !r.circle.isConnected) continue;
|
|
477
|
+
const key = rowKey(r);
|
|
460
478
|
let btn = buttons.get(r.index);
|
|
461
|
-
if (isSelfRow(r)
|
|
479
|
+
if (isSelfRow(r)) {
|
|
480
|
+
if (btn) {
|
|
481
|
+
btn.remove();
|
|
482
|
+
buttons.delete(r.index);
|
|
483
|
+
}
|
|
484
|
+
continue;
|
|
485
|
+
}
|
|
486
|
+
if (nativeSwapIn(r.circle)) swapSeen.add(key);
|
|
487
|
+
if (!swapSeen.has(key)) {
|
|
462
488
|
if (btn) {
|
|
463
489
|
btn.remove();
|
|
464
490
|
buttons.delete(r.index);
|
|
@@ -531,6 +557,7 @@ function update() {
|
|
|
531
557
|
renderButtons();
|
|
532
558
|
} else if (uiVisible) {
|
|
533
559
|
uiVisible = false;
|
|
560
|
+
swapSeen.clear();
|
|
534
561
|
removeButtons();
|
|
535
562
|
}
|
|
536
563
|
}
|
|
@@ -605,6 +632,7 @@ function onDisable() {
|
|
|
605
632
|
observer = null;
|
|
606
633
|
|
|
607
634
|
uiVisible = false;
|
|
635
|
+
swapSeen.clear();
|
|
608
636
|
goneAway = true;
|
|
609
637
|
target = undefined;
|
|
610
638
|
sent = 0;
|
package/hide-unowned-skins.js
CHANGED
|
@@ -78,16 +78,11 @@ function installArrayFilter() {
|
|
|
78
78
|
return owned;
|
|
79
79
|
});
|
|
80
80
|
if (!changed) return result;
|
|
81
|
-
filterStats.array = (filterStats.array || 0) + 1;
|
|
82
|
-
filterStats.source = "array";
|
|
83
|
-
filterStats.lastIn = result.length;
|
|
84
|
-
filterStats.lastOut = kept.length;
|
|
85
81
|
return kept;
|
|
86
82
|
};
|
|
87
83
|
wrapped.__perfSkinFilter = FILTER_VERSION;
|
|
88
84
|
proto.filter = wrapped;
|
|
89
85
|
}
|
|
90
|
-
const filterStats = (globalThis.__perfSkinFilterStats ??= { carousel: 0, source: "", lastIn: 0, lastOut: 0 });
|
|
91
86
|
let rawFetch = (typeof window !== "undefined" && window.fetch && window.fetch.__perfOriginalFetch) || null;
|
|
92
87
|
let clientSkinOrder = [];
|
|
93
88
|
|
|
@@ -127,8 +122,6 @@ function filterSkinList(list) {
|
|
|
127
122
|
})
|
|
128
123
|
.filter(isOwnedSkin);
|
|
129
124
|
if (filtered.length !== list.length) changed = true;
|
|
130
|
-
filterStats.lastIn = list.length;
|
|
131
|
-
filterStats.lastOut = filtered.length;
|
|
132
125
|
return changed ? filtered : null;
|
|
133
126
|
}
|
|
134
127
|
|
|
@@ -153,8 +146,6 @@ function rewriteWebSocketFrame(text) {
|
|
|
153
146
|
if (!payload || typeof payload !== "object" || typeof payload.uri !== "string") return null;
|
|
154
147
|
if (payload.uri.split("?")[0] !== CAROUSEL_URI) return null;
|
|
155
148
|
const kept = filterSkinList(payload.data);
|
|
156
|
-
filterStats.carousel++;
|
|
157
|
-
filterStats.source = "ws";
|
|
158
149
|
recordClientOrder(kept ?? payload.data);
|
|
159
150
|
if (!kept) return null;
|
|
160
151
|
return JSON.stringify([frame[0], frame[1], Object.assign({}, payload, { data: kept })]);
|
|
@@ -235,7 +226,6 @@ function installFetchFilter() {
|
|
|
235
226
|
const original = window.fetch;
|
|
236
227
|
if (typeof original !== "function" || original.__perfSkinFilter === FILTER_VERSION) return;
|
|
237
228
|
if (!rawFetch) rawFetch = original.__perfOriginalFetch || original;
|
|
238
|
-
globalThis.__perfNativeFetch = rawFetch;
|
|
239
229
|
|
|
240
230
|
const wrapped = function (input, init) {
|
|
241
231
|
const url =
|
|
@@ -261,8 +251,6 @@ function installFetchFilter() {
|
|
|
261
251
|
.catch(() => null)
|
|
262
252
|
.then((json) => {
|
|
263
253
|
const kept = filterSkinList(json);
|
|
264
|
-
filterStats.carousel++;
|
|
265
|
-
filterStats.source = "fetch";
|
|
266
254
|
recordClientOrder(kept ?? json);
|
|
267
255
|
if (!kept) return response;
|
|
268
256
|
return new Response(JSON.stringify(kept), {
|
|
@@ -307,8 +295,6 @@ function installXhrFilter() {
|
|
|
307
295
|
try {
|
|
308
296
|
const json = JSON.parse(raw);
|
|
309
297
|
const kept = filterSkinList(json);
|
|
310
|
-
filterStats.carousel++;
|
|
311
|
-
filterStats.source = "xhr";
|
|
312
298
|
recordClientOrder(kept ?? json);
|
|
313
299
|
if (kept) cache.filtered = JSON.stringify(kept);
|
|
314
300
|
} catch {
|
|
@@ -442,10 +428,6 @@ function applyAll() {
|
|
|
442
428
|
});
|
|
443
429
|
}
|
|
444
430
|
|
|
445
|
-
function applyAllGuarded() {
|
|
446
|
-
applyAll();
|
|
447
|
-
}
|
|
448
|
-
|
|
449
431
|
let applyQueued = false;
|
|
450
432
|
|
|
451
433
|
function scheduleApply() {
|
|
@@ -558,7 +540,7 @@ function resetState() {
|
|
|
558
540
|
failure = null;
|
|
559
541
|
sessionMisses = 0;
|
|
560
542
|
championMisses = 0;
|
|
561
|
-
|
|
543
|
+
applyAll();
|
|
562
544
|
}
|
|
563
545
|
|
|
564
546
|
function loadChampion(championId) {
|
|
@@ -579,7 +561,7 @@ function loadChampion(championId) {
|
|
|
579
561
|
topLevelOrder = topLevel;
|
|
580
562
|
ownedTopLevelIds = ownedTopLevel;
|
|
581
563
|
carouselOrder = carouselIds.length > 0 ? carouselIds : inventoryOrder;
|
|
582
|
-
|
|
564
|
+
applyAll();
|
|
583
565
|
},
|
|
584
566
|
(error) => {
|
|
585
567
|
if (token !== requestToken) return;
|
|
@@ -618,7 +600,7 @@ function updateForSession(session, selection) {
|
|
|
618
600
|
}
|
|
619
601
|
}
|
|
620
602
|
|
|
621
|
-
|
|
603
|
+
applyAll();
|
|
622
604
|
}
|
|
623
605
|
|
|
624
606
|
function scheduleRefresh() {
|
package/package.json
CHANGED
package/perfectionist-utils.js
CHANGED
|
@@ -5,7 +5,7 @@ const PANEL_ID = "perfectionist-plugins-panel";
|
|
|
5
5
|
const STYLE_ID = "perfectionist-plugins-style";
|
|
6
6
|
const TAB_TITLE = "Perfectionism";
|
|
7
7
|
|
|
8
|
-
export const version = "2.4.
|
|
8
|
+
export const version = "2.4.6";
|
|
9
9
|
|
|
10
10
|
const PKG = "perfectionist-plugins";
|
|
11
11
|
const CDN = "https://cdn.jsdelivr.net/npm";
|
|
@@ -30,7 +30,7 @@ const BUNDLED_MODULES = [
|
|
|
30
30
|
id: "ban-blocker",
|
|
31
31
|
file: "ban-blocker.js",
|
|
32
32
|
name: "Ban Blocker",
|
|
33
|
-
version: "3.6.
|
|
33
|
+
version: "3.6.2",
|
|
34
34
|
description: "Adds a BLOCK button to your teammates in champ select. While a teammate is blocked, the champion they are about to ban is prepicked for you, so their ban can never land on it.",
|
|
35
35
|
},
|
|
36
36
|
{
|
|
@@ -44,7 +44,7 @@ const BUNDLED_MODULES = [
|
|
|
44
44
|
id: "hide-unowned-skins",
|
|
45
45
|
file: "hide-unowned-skins.js",
|
|
46
46
|
name: "Hide Unowned Skins",
|
|
47
|
-
version: "2.
|
|
47
|
+
version: "2.4.3",
|
|
48
48
|
description: "In champ select, the skin carousel only shows the skins you own for the champion you picked.",
|
|
49
49
|
},
|
|
50
50
|
{
|
|
@@ -849,10 +849,23 @@ function refreshPanel() {
|
|
|
849
849
|
requestAnimationFrame(() => applyScrollTop(next, top));
|
|
850
850
|
}
|
|
851
851
|
|
|
852
|
+
function settingsNavScope() {
|
|
853
|
+
const title =
|
|
854
|
+
document.querySelector(".lol-settings-nav-title:not([data-perfectionist])") ??
|
|
855
|
+
document.querySelector(".lol-settings-nav-title");
|
|
856
|
+
return title?.closest("lol-uikit-scrollable") ?? title?.parentElement ?? null;
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
function navItems() {
|
|
860
|
+
const scope = settingsNavScope();
|
|
861
|
+
if (!scope) return [];
|
|
862
|
+
return [...scope.querySelectorAll('lol-uikit-navigation-item, [class*="settings-nav"]')];
|
|
863
|
+
}
|
|
864
|
+
|
|
852
865
|
function setNavActive(activeNav) {
|
|
853
|
-
for (const nav of
|
|
866
|
+
for (const nav of navItems()) {
|
|
854
867
|
if (nav === activeNav) {
|
|
855
|
-
nav.setAttribute("active", "true");
|
|
868
|
+
if (nav.getAttribute("active") !== "true") nav.setAttribute("active", "true");
|
|
856
869
|
} else if (nav.hasAttribute("active")) {
|
|
857
870
|
nav.removeAttribute("active");
|
|
858
871
|
}
|
|
@@ -861,6 +874,26 @@ function setNavActive(activeNav) {
|
|
|
861
874
|
|
|
862
875
|
let panelRequested = false;
|
|
863
876
|
let syncTimer = null;
|
|
877
|
+
let navObserver = null;
|
|
878
|
+
let nativeActiveBeforeOpen = null;
|
|
879
|
+
|
|
880
|
+
function suppressNativeNavActive() {
|
|
881
|
+
const own = document.getElementById(NAV_ID);
|
|
882
|
+
if (!own) return;
|
|
883
|
+
if (!panelRequested) {
|
|
884
|
+
if (own.hasAttribute("active")) own.removeAttribute("active");
|
|
885
|
+
return;
|
|
886
|
+
}
|
|
887
|
+
for (const nav of navItems()) {
|
|
888
|
+
if (nav !== own && nav.hasAttribute("active")) nav.removeAttribute("active");
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
function watchNavActive() {
|
|
893
|
+
if (navObserver || !document.body) return;
|
|
894
|
+
navObserver = new MutationObserver(suppressNativeNavActive);
|
|
895
|
+
navObserver.observe(document.body, { subtree: true, attributes: true, attributeFilter: ["active"] });
|
|
896
|
+
}
|
|
864
897
|
|
|
865
898
|
function startSync() {
|
|
866
899
|
if (syncTimer === null) syncTimer = setInterval(keepPanelInSync, 300);
|
|
@@ -885,7 +918,11 @@ function openPanel() {
|
|
|
885
918
|
if (existing) existing.remove();
|
|
886
919
|
content.append(buildPanel());
|
|
887
920
|
|
|
888
|
-
|
|
921
|
+
const ownNav = document.getElementById(NAV_ID);
|
|
922
|
+
if (!nativeActiveBeforeOpen) {
|
|
923
|
+
nativeActiveBeforeOpen = navItems().find((nav) => nav !== ownNav && nav.hasAttribute("active")) ?? null;
|
|
924
|
+
}
|
|
925
|
+
setNavActive(ownNav);
|
|
889
926
|
const currentTitle = document.querySelector(".lol-settings-title-current");
|
|
890
927
|
if (currentTitle) currentTitle.textContent = TAB_TITLE.toUpperCase();
|
|
891
928
|
}
|
|
@@ -897,7 +934,9 @@ function closePanel() {
|
|
|
897
934
|
panel.remove();
|
|
898
935
|
const options = document.querySelector(".lol-settings-content .lol-settings-options");
|
|
899
936
|
if (options) options.style.display = "";
|
|
900
|
-
|
|
937
|
+
document.getElementById(NAV_ID)?.removeAttribute("active");
|
|
938
|
+
if (nativeActiveBeforeOpen?.isConnected) nativeActiveBeforeOpen.setAttribute("active", "true");
|
|
939
|
+
nativeActiveBeforeOpen = null;
|
|
901
940
|
}
|
|
902
941
|
|
|
903
942
|
function keepPanelInSync() {
|
|
@@ -905,6 +944,7 @@ function keepPanelInSync() {
|
|
|
905
944
|
if (!content) {
|
|
906
945
|
panelRequested = false;
|
|
907
946
|
stopSync();
|
|
947
|
+
document.getElementById(NAV_ID)?.removeAttribute("active");
|
|
908
948
|
return;
|
|
909
949
|
}
|
|
910
950
|
if (!panelRequested) {
|
|
@@ -923,12 +963,7 @@ function keepPanelInSync() {
|
|
|
923
963
|
if (options && options.style.display !== "none") options.style.display = "none";
|
|
924
964
|
|
|
925
965
|
const nav = document.getElementById(NAV_ID);
|
|
926
|
-
if (nav)
|
|
927
|
-
for (const other of document.querySelectorAll(".lol-settings-nav")) {
|
|
928
|
-
if (other !== nav && other.hasAttribute("active")) other.removeAttribute("active");
|
|
929
|
-
}
|
|
930
|
-
if (nav.getAttribute("active") !== "true") nav.setAttribute("active", "true");
|
|
931
|
-
}
|
|
966
|
+
if (nav) setNavActive(nav);
|
|
932
967
|
|
|
933
968
|
const title = document.querySelector(".lol-settings-title-current");
|
|
934
969
|
if (title && title.textContent !== TAB_TITLE.toUpperCase()) title.textContent = TAB_TITLE.toUpperCase();
|
|
@@ -967,6 +1002,7 @@ function isDoneButton(target) {
|
|
|
967
1002
|
|
|
968
1003
|
function installSettingsTab() {
|
|
969
1004
|
addStyle(STYLE_ID, STYLE_CSS);
|
|
1005
|
+
watchNavActive();
|
|
970
1006
|
|
|
971
1007
|
document.addEventListener(
|
|
972
1008
|
"click",
|