perfectionist-plugins 2.4.6 → 2.4.8
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 +116 -33
- package/dodge-helper.js +66 -28
- package/hide-unowned-skins.js +11 -28
- package/package.json +1 -1
- package/perfectionist-utils.js +52 -15
- package/unlock-profile-skins.js +49 -16
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.6";
|
|
2
2
|
|
|
3
3
|
const PLUGIN_ID = "ban-blocker";
|
|
4
4
|
const STYLE_ID = "perfectionist-ban-blocker-style";
|
|
@@ -28,7 +28,8 @@ const CSS = `
|
|
|
28
28
|
right: -2px !important;
|
|
29
29
|
left: auto !important;
|
|
30
30
|
bottom: auto !important;
|
|
31
|
-
z-index:
|
|
31
|
+
z-index: 50 !important;
|
|
32
|
+
pointer-events: auto !important;
|
|
32
33
|
}
|
|
33
34
|
.swap-button-component.${BTN_CLASS} .icon {
|
|
34
35
|
-webkit-mask-image: url("${BAN_GLYPH}") !important;
|
|
@@ -65,11 +66,13 @@ let uiScheduled = false;
|
|
|
65
66
|
let lastDetect = -Infinity;
|
|
66
67
|
|
|
67
68
|
const enabled = new Map();
|
|
69
|
+
const blockedCellIds = new Set();
|
|
68
70
|
const alias = new Map();
|
|
69
71
|
const fetchedNames = new Set();
|
|
70
72
|
const playerNames = new Map();
|
|
71
73
|
const cellToPlayer = new Map();
|
|
72
74
|
const buttons = new Map();
|
|
75
|
+
const swapSeen = new Set();
|
|
73
76
|
const failedUntil = new Map();
|
|
74
77
|
const failCount = new Map();
|
|
75
78
|
let rows = [];
|
|
@@ -159,10 +162,19 @@ function linkPlayer(p, rowName, cellId) {
|
|
|
159
162
|
return root;
|
|
160
163
|
}
|
|
161
164
|
|
|
165
|
+
function pickStarted(s) {
|
|
166
|
+
const actions = s?.actions?.flat?.() ?? [];
|
|
167
|
+
return actions.some((a) => a.type === "pick" && (a.isInProgress || a.completed));
|
|
168
|
+
}
|
|
169
|
+
|
|
162
170
|
function banPending(s) {
|
|
163
|
-
const
|
|
171
|
+
const actions = s?.actions?.flat?.() ?? [];
|
|
172
|
+
const bans = actions.filter((a) => a.type === "ban");
|
|
164
173
|
if (!bans.length) return true;
|
|
165
|
-
|
|
174
|
+
if (bans.some((a) => !a.completed)) return true;
|
|
175
|
+
const phase = s?.timer?.phase;
|
|
176
|
+
if (phase && phase !== "BAN_PICK") return false;
|
|
177
|
+
return !pickStarted(s);
|
|
166
178
|
}
|
|
167
179
|
|
|
168
180
|
function pump() {
|
|
@@ -222,7 +234,9 @@ function decide(s) {
|
|
|
222
234
|
}
|
|
223
235
|
myActionId = myPick ? myPick.id : null;
|
|
224
236
|
|
|
225
|
-
const blockedCells = new Set(
|
|
237
|
+
const blockedCells = new Set(
|
|
238
|
+
m.filter((p) => blockedCellIds.has(p.cellId) || isBlocked(cellToPlayer.get(p.cellId))).map((p) => p.cellId),
|
|
239
|
+
);
|
|
226
240
|
|
|
227
241
|
let threat = 0;
|
|
228
242
|
for (const a of actions) {
|
|
@@ -254,6 +268,8 @@ function onSessionGone() {
|
|
|
254
268
|
lastSession = null;
|
|
255
269
|
goneAway = true;
|
|
256
270
|
uiVisible = false;
|
|
271
|
+
blockedCellIds.clear();
|
|
272
|
+
swapSeen.clear();
|
|
257
273
|
removeButtons();
|
|
258
274
|
if (!goneTimer) {
|
|
259
275
|
goneTimer = setTimeout(() => {
|
|
@@ -367,22 +383,29 @@ function bindRowsToTeam(session) {
|
|
|
367
383
|
const selfIdx = list.findIndex((r) => isSelfRow(r));
|
|
368
384
|
const selfCellIdx =
|
|
369
385
|
session?.localPlayerCellId != null ? cells.findIndex((c) => c.cellId === session.localPlayerCellId) : -1;
|
|
386
|
+
|
|
387
|
+
// The DOM can label allied rows 0-4 while the session uses cell IDs 5-9 (red side).
|
|
388
|
+
// If every row still has a unique matching cell, slot IDs are reliable; otherwise
|
|
389
|
+
// align by the local row's position in myTeam, then fall back to row order.
|
|
390
|
+
const bySlot = list.map((r) =>
|
|
391
|
+
r.slotId != null ? cells.find((c) => c.cellId === r.slotId) ?? null : null,
|
|
392
|
+
);
|
|
393
|
+
const slotMapComplete =
|
|
394
|
+
bySlot.every(Boolean) && new Set(bySlot.map((c) => c.cellId)).size === list.length;
|
|
370
395
|
let pick;
|
|
371
|
-
if (
|
|
372
|
-
|
|
373
|
-
if (selfSlot != null && selfSlot === cells[selfCellIdx].cellId) {
|
|
374
|
-
pick = (r) => (r.slotId != null ? cells.find((c) => c.cellId === r.slotId) : null);
|
|
375
|
-
} else if (selfIdx === selfCellIdx) {
|
|
376
|
-
pick = (r) => (r.slotId != null ? cells[r.slotId] : null) ?? cells[r.index];
|
|
377
|
-
} else {
|
|
378
|
-
pick = () => null;
|
|
379
|
-
}
|
|
396
|
+
if (slotMapComplete) {
|
|
397
|
+
pick = (r) => bySlot[r.index] ?? null;
|
|
380
398
|
} else {
|
|
381
|
-
|
|
399
|
+
const shift = selfIdx >= 0 && selfCellIdx >= 0 ? selfCellIdx - selfIdx : 0;
|
|
400
|
+
pick = (r) => cells[r.index + shift] ?? null;
|
|
382
401
|
}
|
|
383
402
|
|
|
384
403
|
for (const r of list) {
|
|
385
|
-
const
|
|
404
|
+
const rowName = norm(r.name);
|
|
405
|
+
const cell =
|
|
406
|
+
pick(r) ??
|
|
407
|
+
cells.find((c) => rowName && (norm(c.summonerName) === rowName || payloadName(c) === rowName)) ??
|
|
408
|
+
cells.find((c) => nameMatches(r.name, keyOf(c)));
|
|
386
409
|
if (cell) {
|
|
387
410
|
r.cell = cell.cellId;
|
|
388
411
|
r.player = linkPlayer(cell, r.name, cell.cellId);
|
|
@@ -399,23 +422,56 @@ function stopEvent(e) {
|
|
|
399
422
|
e.preventDefault();
|
|
400
423
|
}
|
|
401
424
|
|
|
425
|
+
function cellForRow(r) {
|
|
426
|
+
if (!r) return null;
|
|
427
|
+
if (r.cell != null) return r.cell;
|
|
428
|
+
const cells = lastSession?.myTeam ?? [];
|
|
429
|
+
if (!cells.length) return r.slotId ?? null;
|
|
430
|
+
const direct = r.slotId != null ? cells.find((c) => c.cellId === r.slotId) : null;
|
|
431
|
+
if (direct) return direct.cellId;
|
|
432
|
+
const selfIdx = rows.findIndex((x) => isSelfRow(x));
|
|
433
|
+
const selfCellIdx =
|
|
434
|
+
lastSession?.localPlayerCellId != null
|
|
435
|
+
? cells.findIndex((c) => c.cellId === lastSession.localPlayerCellId)
|
|
436
|
+
: -1;
|
|
437
|
+
const shift = selfIdx >= 0 && selfCellIdx >= 0 ? selfCellIdx - selfIdx : 0;
|
|
438
|
+
return cells[r.index + shift]?.cellId ?? cells[r.index]?.cellId ?? null;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
function badgeCell(btn) {
|
|
442
|
+
const rowEl = btn.closest(".summoner-object");
|
|
443
|
+
const r = rowEl ? rows.find((x) => x.el === rowEl) : rows[Number(btn.dataset.slot)];
|
|
444
|
+
const cell = cellForRow(r) ?? (btn.dataset.cell ? Number(btn.dataset.cell) : null);
|
|
445
|
+
return cell == null ? null : Number(cell);
|
|
446
|
+
}
|
|
447
|
+
|
|
402
448
|
function playerForBadge(btn) {
|
|
403
449
|
const rowEl = btn.closest(".summoner-object");
|
|
404
450
|
const r = rowEl ? rows.find((x) => x.el === rowEl) : rows[Number(btn.dataset.slot)];
|
|
405
|
-
const
|
|
451
|
+
const cell = badgeCell(btn);
|
|
452
|
+
const member = cell == null ? null : (lastSession?.myTeam ?? []).find((p) => p.cellId === cell);
|
|
453
|
+
if (member) {
|
|
454
|
+
const id = linkPlayer(member, r?.name, cell);
|
|
455
|
+
cellToPlayer.set(cell, id);
|
|
456
|
+
return canonOf(id);
|
|
457
|
+
}
|
|
458
|
+
const byCell = cell == null ? null : cellToPlayer.get(cell) ?? null;
|
|
406
459
|
return canonOf(byCell ?? r?.player ?? null);
|
|
407
460
|
}
|
|
408
461
|
|
|
409
462
|
function toggle(btn) {
|
|
410
|
-
|
|
411
|
-
if (id == null && lastSession) {
|
|
463
|
+
if (lastSession) {
|
|
412
464
|
bindRowsToTeam(lastSession);
|
|
413
|
-
|
|
465
|
+
decide(lastSession);
|
|
414
466
|
}
|
|
415
|
-
|
|
467
|
+
const cell = badgeCell(btn);
|
|
416
468
|
const myCell = lastSession?.localPlayerCellId;
|
|
417
|
-
if (myCell != null &&
|
|
418
|
-
|
|
469
|
+
if (cell == null || (myCell != null && cell === myCell)) return;
|
|
470
|
+
const next = !blockedCellIds.has(cell);
|
|
471
|
+
if (next) blockedCellIds.add(cell);
|
|
472
|
+
else blockedCellIds.delete(cell);
|
|
473
|
+
const id = playerForBadge(btn);
|
|
474
|
+
if (id != null) enabled.set(id, next);
|
|
419
475
|
renderButtons();
|
|
420
476
|
if (lastSession) {
|
|
421
477
|
decide(lastSession);
|
|
@@ -449,19 +505,41 @@ function isSelfRow(r) {
|
|
|
449
505
|
return lastSession?.localPlayerCellId != null && (r.cell ?? r.slotId) === lastSession.localPlayerCellId;
|
|
450
506
|
}
|
|
451
507
|
|
|
508
|
+
function rowKey(r) {
|
|
509
|
+
return String(r.cell ?? r.slotId ?? r.index);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
function buttonKey(r) {
|
|
513
|
+
const cell = r.cell ?? r.slotId;
|
|
514
|
+
return cell == null ? `row:${r.index}` : `cell:${cell}`;
|
|
515
|
+
}
|
|
516
|
+
|
|
452
517
|
function nativeSwapIn(circle) {
|
|
453
|
-
|
|
518
|
+
if (!circle) return false;
|
|
519
|
+
return [...circle.querySelectorAll(".swap-button-component")].some((el) => el.dataset.bb !== "1");
|
|
454
520
|
}
|
|
455
521
|
|
|
456
522
|
function ensureButtons() {
|
|
457
523
|
const list = getRows();
|
|
524
|
+
const active = new Set();
|
|
458
525
|
for (const r of list) {
|
|
526
|
+
if (!r.circle || !r.circle.isConnected) r.circle = r.el.querySelector(".champion-icon-container");
|
|
459
527
|
if (!r.circle || !r.circle.isConnected) continue;
|
|
460
|
-
|
|
461
|
-
|
|
528
|
+
const swapKey = rowKey(r);
|
|
529
|
+
const key = buttonKey(r);
|
|
530
|
+
let btn = buttons.get(key);
|
|
531
|
+
if (isSelfRow(r)) {
|
|
532
|
+
if (btn) {
|
|
533
|
+
btn.remove();
|
|
534
|
+
buttons.delete(key);
|
|
535
|
+
}
|
|
536
|
+
continue;
|
|
537
|
+
}
|
|
538
|
+
if (nativeSwapIn(r.circle)) swapSeen.add(swapKey);
|
|
539
|
+
if (!swapSeen.has(swapKey)) {
|
|
462
540
|
if (btn) {
|
|
463
541
|
btn.remove();
|
|
464
|
-
buttons.delete(
|
|
542
|
+
buttons.delete(key);
|
|
465
543
|
}
|
|
466
544
|
continue;
|
|
467
545
|
}
|
|
@@ -470,16 +548,17 @@ function ensureButtons() {
|
|
|
470
548
|
for (const orphan of r.circle.querySelectorAll(`:scope > .${BTN_CLASS}`)) orphan.remove();
|
|
471
549
|
btn = buildBadge(r.index);
|
|
472
550
|
r.circle.appendChild(btn);
|
|
473
|
-
buttons.set(
|
|
551
|
+
buttons.set(key, btn);
|
|
474
552
|
}
|
|
553
|
+
active.add(key);
|
|
475
554
|
btn.dataset.slot = String(r.index);
|
|
476
|
-
const cell = r
|
|
555
|
+
const cell = cellForRow(r);
|
|
477
556
|
btn.dataset.cell = cell == null ? "" : String(cell);
|
|
478
557
|
}
|
|
479
|
-
for (const [
|
|
480
|
-
if (!
|
|
558
|
+
for (const [key, btn] of [...buttons]) {
|
|
559
|
+
if (!active.has(key) || !btn.isConnected) {
|
|
481
560
|
btn.remove();
|
|
482
|
-
buttons.delete(
|
|
561
|
+
buttons.delete(key);
|
|
483
562
|
}
|
|
484
563
|
}
|
|
485
564
|
}
|
|
@@ -488,7 +567,8 @@ function renderButtons() {
|
|
|
488
567
|
const hasSession = !!lastSession?.myTeam;
|
|
489
568
|
for (const [, btn] of buttons) {
|
|
490
569
|
const id = playerForBadge(btn);
|
|
491
|
-
const
|
|
570
|
+
const cell = badgeCell(btn);
|
|
571
|
+
const on = (cell != null && blockedCellIds.has(cell)) || (id != null && isBlocked(id));
|
|
492
572
|
btn.classList.toggle("on", on);
|
|
493
573
|
btn.classList.toggle("unresolved", id == null && hasSession);
|
|
494
574
|
const title = on ? "Blocked — click to allow their bans" : "Block this teammate's bans";
|
|
@@ -531,6 +611,7 @@ function update() {
|
|
|
531
611
|
renderButtons();
|
|
532
612
|
} else if (uiVisible) {
|
|
533
613
|
uiVisible = false;
|
|
614
|
+
swapSeen.clear();
|
|
534
615
|
removeButtons();
|
|
535
616
|
}
|
|
536
617
|
}
|
|
@@ -605,6 +686,7 @@ function onDisable() {
|
|
|
605
686
|
observer = null;
|
|
606
687
|
|
|
607
688
|
uiVisible = false;
|
|
689
|
+
swapSeen.clear();
|
|
608
690
|
goneAway = true;
|
|
609
691
|
target = undefined;
|
|
610
692
|
sent = 0;
|
|
@@ -612,6 +694,7 @@ function onDisable() {
|
|
|
612
694
|
failCount.clear();
|
|
613
695
|
cellToPlayer.clear();
|
|
614
696
|
enabled.clear();
|
|
697
|
+
blockedCellIds.clear();
|
|
615
698
|
playerNames.clear();
|
|
616
699
|
alias.clear();
|
|
617
700
|
fetchedNames.clear();
|
package/dodge-helper.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const PLUGIN_ID = "dodge-helper";
|
|
2
|
-
export const version = "1.4.
|
|
2
|
+
export const version = "1.4.14";
|
|
3
3
|
|
|
4
4
|
const PHASE_URI = "/lol-gameflow/v1/gameflow-phase";
|
|
5
5
|
const SESSION_URI = "/lol-gameflow/v1/session";
|
|
@@ -7,8 +7,8 @@ const CHAMP_SELECT_URI = "/lol-champ-select/v1/session";
|
|
|
7
7
|
const TIMER_URI = "/lol-champ-select/v1/session/timer";
|
|
8
8
|
const SUMMONER_URI = "/lol-summoner/v1/current-summoner";
|
|
9
9
|
const RANKED_STATS_URI = "/lol-ranked/v1/current-ranked-stats";
|
|
10
|
-
const
|
|
11
|
-
const
|
|
10
|
+
const QUIT_V2_URI = '/lol-login/v1/session/invoke?destination=lcdsServiceProxy&method=call&args=["","teambuilder-draft","quitV2",""]';
|
|
11
|
+
const CUSTOM_CANCEL_URI = "/lol-lobby/v1/lobby/custom/cancel-champ-select";
|
|
12
12
|
const STORE_KEY = "perfectionist:dodge-helper:accounts:v1";
|
|
13
13
|
const PENDING_KEY = "perfectionist:dodge-helper:pending:v1";
|
|
14
14
|
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
@@ -43,15 +43,30 @@ const GAME_PHASES = new Set([
|
|
|
43
43
|
|
|
44
44
|
const CSS = `
|
|
45
45
|
#${LAYER_ID} {
|
|
46
|
-
position: fixed !important; inset: 0 !important; z-index:
|
|
46
|
+
position: fixed !important; inset: 0 !important; z-index: 100 !important;
|
|
47
47
|
pointer-events: none !important;
|
|
48
48
|
}
|
|
49
49
|
#${ROOT_ID} {
|
|
50
50
|
position: fixed !important; display: flex !important; align-items: flex-end !important;
|
|
51
|
-
justify-content: center !important; width:
|
|
51
|
+
justify-content: center !important; width: 114px !important; height: 32px !important;
|
|
52
52
|
pointer-events: auto !important; z-index: 1 !important;
|
|
53
53
|
}
|
|
54
|
-
#${ROOT_ID}
|
|
54
|
+
#${ROOT_ID} .perf-dodge-button {
|
|
55
|
+
width: 100% !important; height: 32px !important; box-sizing: border-box !important;
|
|
56
|
+
appearance: none !important; -webkit-appearance: none !important; border-radius: 0 !important;
|
|
57
|
+
padding: 0 !important; border: 1px solid #785a28 !important;
|
|
58
|
+
background: linear-gradient(to bottom, #1e2328 0%, #11161c 55%, #0a0e12 100%) !important;
|
|
59
|
+
color: #cdbe91 !important; font-family: var(--font-display, "Beaufort for LOL", serif) !important;
|
|
60
|
+
font-size: 13px !important; font-weight: 700 !important; letter-spacing: 1px !important;
|
|
61
|
+
text-transform: uppercase !important; cursor: pointer !important;
|
|
62
|
+
text-shadow: 0 1px 2px #000 !important;
|
|
63
|
+
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.55), inset 0 1px 0 rgba(240, 230, 210, 0.12) !important;
|
|
64
|
+
}
|
|
65
|
+
#${ROOT_ID} .perf-dodge-button:hover {
|
|
66
|
+
color: #f0e6d2 !important; border-color: #c89b3c !important;
|
|
67
|
+
background: linear-gradient(to bottom, #2a3038 0%, #192027 55%, #0e141a 100%) !important;
|
|
68
|
+
}
|
|
69
|
+
#${ROOT_ID} .perf-dodge-button:disabled { opacity: 0.6 !important; cursor: default !important; }
|
|
55
70
|
#${ROOT_ID} .perf-dodge-cost {
|
|
56
71
|
position: absolute !important; left: 50% !important; bottom: calc(100% + 4px) !important;
|
|
57
72
|
transform: translateX(-50%) !important; box-sizing: border-box !important;
|
|
@@ -399,24 +414,20 @@ function build() {
|
|
|
399
414
|
const cost = document.createElement("div");
|
|
400
415
|
cost.id = COST_ID;
|
|
401
416
|
cost.className = "perf-dodge-cost";
|
|
402
|
-
const button = document.createElement("
|
|
417
|
+
const button = document.createElement("button");
|
|
418
|
+
button.type = "button";
|
|
403
419
|
button.id = BUTTON_ID;
|
|
420
|
+
button.className = "perf-dodge-button";
|
|
421
|
+
button.textContent = "DODGE";
|
|
404
422
|
bindButton(button);
|
|
405
423
|
root.append(cost, button);
|
|
406
424
|
return root;
|
|
407
425
|
}
|
|
408
426
|
|
|
409
427
|
function bindButton(button) {
|
|
410
|
-
if (!button) return;
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
button.addEventListener("click", onButtonClick, true);
|
|
414
|
-
}
|
|
415
|
-
const inner = button.shadowRoot?.querySelector(".lol-uikit-flat-button");
|
|
416
|
-
if (inner && !inner.__perfClickBound) {
|
|
417
|
-
inner.__perfClickBound = true;
|
|
418
|
-
inner.addEventListener("click", onButtonClick);
|
|
419
|
-
}
|
|
428
|
+
if (!button || button.__perfClickBound) return;
|
|
429
|
+
button.__perfClickBound = true;
|
|
430
|
+
button.addEventListener("click", onButtonClick);
|
|
420
431
|
}
|
|
421
432
|
|
|
422
433
|
function onButtonClick(event) {
|
|
@@ -470,19 +481,30 @@ function positionRoot() {
|
|
|
470
481
|
const root = document.getElementById(ROOT_ID);
|
|
471
482
|
if (!root) return;
|
|
472
483
|
const footer = visibleFooter();
|
|
473
|
-
const width = root.offsetWidth || 125;
|
|
474
484
|
const height = root.offsetHeight || 32;
|
|
475
|
-
if (footer
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
485
|
+
if (footer) {
|
|
486
|
+
const footerElement = document.querySelector(FOOTER_SELECTOR);
|
|
487
|
+
const chat = footerElement?.querySelector("lol-social-chat-toggle-button");
|
|
488
|
+
const voice = footerElement?.querySelector(".champ-select-voice-button-wrapper");
|
|
489
|
+
const chatRect = chat?.getBoundingClientRect();
|
|
490
|
+
const voiceRect = voice?.getBoundingClientRect();
|
|
491
|
+
const left = chatRect?.left;
|
|
492
|
+
const rightEdge = voiceRect?.right ?? footer.right;
|
|
493
|
+
const width = left && rightEdge > left ? Math.round(rightEdge - left) : 114;
|
|
494
|
+
const right = Math.round(Math.max(8, window.innerWidth - rightEdge));
|
|
495
|
+
const top = Math.round(Math.max(8, footer.top - height - 8));
|
|
496
|
+
root.style.width = `${width}px`;
|
|
497
|
+
root.style.left = "auto";
|
|
498
|
+
root.style.right = `${right}px`;
|
|
499
|
+
root.style.top = `${top}px`;
|
|
479
500
|
root.style.bottom = "auto";
|
|
480
501
|
return;
|
|
481
502
|
}
|
|
503
|
+
root.style.width = "114px";
|
|
482
504
|
root.style.left = "auto";
|
|
483
505
|
root.style.top = "auto";
|
|
484
|
-
root.style.right = "
|
|
485
|
-
root.style.bottom = "
|
|
506
|
+
root.style.right = "20px";
|
|
507
|
+
root.style.bottom = "76px";
|
|
486
508
|
}
|
|
487
509
|
|
|
488
510
|
function schedulePosition() {
|
|
@@ -698,14 +720,30 @@ function handleTimer(raw) {
|
|
|
698
720
|
syncTimer(raw);
|
|
699
721
|
}
|
|
700
722
|
|
|
723
|
+
async function requestDodge(uri) {
|
|
724
|
+
const options = { method: "POST" };
|
|
725
|
+
if (uri === QUIT_V2_URI) options.body = '["","teambuilder-draft","quitV2",""]';
|
|
726
|
+
const response = await fetch(uri, options);
|
|
727
|
+
if (!response.ok) throw new Error(`LCU ${uri} responded ${response.status}`);
|
|
728
|
+
return response;
|
|
729
|
+
}
|
|
730
|
+
|
|
701
731
|
async function quitOrDodge() {
|
|
702
732
|
if (!active || dodging || !state.queueId || isCustomQueue() || state.showQuitButton) return;
|
|
703
733
|
dodging = true;
|
|
704
734
|
render();
|
|
705
|
-
const ranked = RANKED_QUEUES.has(Number(state.queueId));
|
|
706
|
-
const uri = ranked ? DODGE_URI : QUIT_URI;
|
|
707
735
|
try {
|
|
708
|
-
|
|
736
|
+
let sent = false;
|
|
737
|
+
let lastError = null;
|
|
738
|
+
for (const uri of [QUIT_V2_URI, CUSTOM_CANCEL_URI]) {
|
|
739
|
+
try {
|
|
740
|
+
await requestDodge(uri);
|
|
741
|
+
sent = true;
|
|
742
|
+
} catch (error) {
|
|
743
|
+
lastError = error;
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
if (!sent) throw lastError ?? new Error("No dodge endpoint accepted the request");
|
|
709
747
|
await recordDodge();
|
|
710
748
|
} catch (error) {
|
|
711
749
|
console.warn("[Dodge Helper] quit failed:", error);
|
|
@@ -832,4 +870,4 @@ export function init() {
|
|
|
832
870
|
addEventListener("perfectionist:utils-ready", (event) => registerWith(event.detail ?? window.PerfectionistUtils), {
|
|
833
871
|
once: true,
|
|
834
872
|
});
|
|
835
|
-
}
|
|
873
|
+
}
|
package/hide-unowned-skins.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const version = "2.4.
|
|
1
|
+
export const version = "2.4.5";
|
|
2
2
|
|
|
3
3
|
const PLUGIN_ID = "hide-unowned-skins";
|
|
4
4
|
const STYLE_ID = "perfectionist-hide-unowned-skins-style";
|
|
@@ -27,7 +27,7 @@ const OBSERVER_OPTIONS = {
|
|
|
27
27
|
attributeFilter: ["src"],
|
|
28
28
|
};
|
|
29
29
|
|
|
30
|
-
const FILTER_VERSION = "2.4.
|
|
30
|
+
const FILTER_VERSION = "2.4.5";
|
|
31
31
|
const FILTER_STATE_KEY = "__perfSkinFilterState";
|
|
32
32
|
const filterState = (globalThis[FILTER_STATE_KEY] ??= { active: true });
|
|
33
33
|
|
|
@@ -69,7 +69,7 @@ function installArrayFilter() {
|
|
|
69
69
|
const nativeFilter = proto.filter;
|
|
70
70
|
const wrapped = function (callback, thisArg) {
|
|
71
71
|
const result = nativeFilter.call(this, callback, thisArg);
|
|
72
|
-
if (!filterState.active || !isSkinCollection(result)) return result;
|
|
72
|
+
if (!filterState.active || currentChampionId === null || !isSkinCollection(result)) return result;
|
|
73
73
|
let changed = false;
|
|
74
74
|
if (!skinShapeKeys) learnSkinShape(result);
|
|
75
75
|
const kept = nativeFilter.call(result, (skin) => {
|
|
@@ -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
|
|
|
@@ -114,7 +109,7 @@ function isOwnedSkin(skin) {
|
|
|
114
109
|
}
|
|
115
110
|
|
|
116
111
|
function filterSkinList(list) {
|
|
117
|
-
if (!Array.isArray(list)) return null;
|
|
112
|
+
if (!Array.isArray(list) || currentChampionId === null) return null;
|
|
118
113
|
if (!skinShapeKeys && isSkinCollection(list)) learnSkinShape(list);
|
|
119
114
|
let changed = false;
|
|
120
115
|
const filtered = list
|
|
@@ -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
|
|
|
@@ -140,7 +133,7 @@ function recordClientOrder(list) {
|
|
|
140
133
|
}
|
|
141
134
|
|
|
142
135
|
function rewriteWebSocketFrame(text) {
|
|
143
|
-
if (!filterState.active || typeof text !== "string") return null;
|
|
136
|
+
if (!filterState.active || currentChampionId === null || typeof text !== "string") return null;
|
|
144
137
|
if (text.indexOf("skin-carousel-skins") === -1) return null;
|
|
145
138
|
let frame;
|
|
146
139
|
try {
|
|
@@ -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 =
|
|
@@ -247,7 +237,7 @@ function installFetchFilter() {
|
|
|
247
237
|
? input.href
|
|
248
238
|
: "";
|
|
249
239
|
const promise = original.call(this, input, init);
|
|
250
|
-
if (!filterState.active || url.split("?")[0].indexOf(CAROUSEL_URI) === -1) return promise;
|
|
240
|
+
if (!filterState.active || currentChampionId === null || url.split("?")[0].indexOf(CAROUSEL_URI) === -1) return promise;
|
|
251
241
|
return promise.then((response) => {
|
|
252
242
|
if (!response || !response.ok) return response;
|
|
253
243
|
let body;
|
|
@@ -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), {
|
|
@@ -300,15 +288,13 @@ function installXhrFilter() {
|
|
|
300
288
|
const cache = { raw: null, filtered: null };
|
|
301
289
|
const filteredText = () => {
|
|
302
290
|
const raw = textDescriptor.get.call(xhr);
|
|
303
|
-
if (!filterState.active) return raw;
|
|
291
|
+
if (!filterState.active || currentChampionId === null) return raw;
|
|
304
292
|
if (cache.filtered === null || cache.raw !== raw) {
|
|
305
293
|
cache.raw = raw;
|
|
306
294
|
cache.filtered = raw;
|
|
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() {
|
|
@@ -454,6 +436,7 @@ function scheduleApply() {
|
|
|
454
436
|
requestAnimationFrame(() => {
|
|
455
437
|
applyQueued = false;
|
|
456
438
|
ensureSourceFilter();
|
|
439
|
+
if (currentChampionId === null) return;
|
|
457
440
|
const item = document.querySelector(SKIN_ITEM_SELECTOR);
|
|
458
441
|
if (!item && !document.querySelector(DOT_SELECTOR)) return;
|
|
459
442
|
applyAll();
|
|
@@ -558,7 +541,7 @@ function resetState() {
|
|
|
558
541
|
failure = null;
|
|
559
542
|
sessionMisses = 0;
|
|
560
543
|
championMisses = 0;
|
|
561
|
-
|
|
544
|
+
applyAll();
|
|
562
545
|
}
|
|
563
546
|
|
|
564
547
|
function loadChampion(championId) {
|
|
@@ -579,7 +562,7 @@ function loadChampion(championId) {
|
|
|
579
562
|
topLevelOrder = topLevel;
|
|
580
563
|
ownedTopLevelIds = ownedTopLevel;
|
|
581
564
|
carouselOrder = carouselIds.length > 0 ? carouselIds : inventoryOrder;
|
|
582
|
-
|
|
565
|
+
applyAll();
|
|
583
566
|
},
|
|
584
567
|
(error) => {
|
|
585
568
|
if (token !== requestToken) return;
|
|
@@ -618,7 +601,7 @@ function updateForSession(session, selection) {
|
|
|
618
601
|
}
|
|
619
602
|
}
|
|
620
603
|
|
|
621
|
-
|
|
604
|
+
applyAll();
|
|
622
605
|
}
|
|
623
606
|
|
|
624
607
|
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,21 +30,21 @@ 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.6",
|
|
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
|
{
|
|
37
37
|
id: "unlock-profile-skins",
|
|
38
38
|
file: "unlock-profile-skins.js",
|
|
39
39
|
name: "Unlock Profile Skins",
|
|
40
|
-
version: "1.2.
|
|
40
|
+
version: "1.2.6",
|
|
41
41
|
description: "Shows every skin as unlocked in the Set profile background window, event skins included, so you can pick any skin as your profile background.",
|
|
42
42
|
},
|
|
43
43
|
{
|
|
44
44
|
id: "hide-unowned-skins",
|
|
45
45
|
file: "hide-unowned-skins.js",
|
|
46
46
|
name: "Hide Unowned Skins",
|
|
47
|
-
version: "2.5
|
|
47
|
+
version: "2.4.5",
|
|
48
48
|
description: "In champ select, the skin carousel only shows the skins you own for the champion you picked.",
|
|
49
49
|
},
|
|
50
50
|
{
|
|
@@ -58,7 +58,7 @@ const BUNDLED_MODULES = [
|
|
|
58
58
|
id: "dodge-helper",
|
|
59
59
|
file: "dodge-helper.js",
|
|
60
60
|
name: "Dodge Helper",
|
|
61
|
-
version: "1.4.
|
|
61
|
+
version: "1.4.13",
|
|
62
62
|
description: "Adds a DODGE/QUIT button to champ select, showing the LP and queue penalty for the next dodge.",
|
|
63
63
|
},
|
|
64
64
|
{
|
|
@@ -384,6 +384,7 @@ function isInstalled(mod) {
|
|
|
384
384
|
}
|
|
385
385
|
|
|
386
386
|
function moduleUrl(file) {
|
|
387
|
+
if (coords?.moduleBase) return new URL(file, coords.moduleBase).href;
|
|
387
388
|
return `${CDN}/${PKG}@${runningVersion}/${file}`;
|
|
388
389
|
}
|
|
389
390
|
|
|
@@ -849,10 +850,23 @@ function refreshPanel() {
|
|
|
849
850
|
requestAnimationFrame(() => applyScrollTop(next, top));
|
|
850
851
|
}
|
|
851
852
|
|
|
853
|
+
function settingsNavScope() {
|
|
854
|
+
const title =
|
|
855
|
+
document.querySelector(".lol-settings-nav-title:not([data-perfectionist])") ??
|
|
856
|
+
document.querySelector(".lol-settings-nav-title");
|
|
857
|
+
return title?.closest("lol-uikit-scrollable") ?? title?.parentElement ?? null;
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
function navItems() {
|
|
861
|
+
const scope = settingsNavScope();
|
|
862
|
+
if (!scope) return [];
|
|
863
|
+
return [...scope.querySelectorAll('lol-uikit-navigation-item, [class*="settings-nav"]')];
|
|
864
|
+
}
|
|
865
|
+
|
|
852
866
|
function setNavActive(activeNav) {
|
|
853
|
-
for (const nav of
|
|
867
|
+
for (const nav of navItems()) {
|
|
854
868
|
if (nav === activeNav) {
|
|
855
|
-
nav.setAttribute("active", "true");
|
|
869
|
+
if (nav.getAttribute("active") !== "true") nav.setAttribute("active", "true");
|
|
856
870
|
} else if (nav.hasAttribute("active")) {
|
|
857
871
|
nav.removeAttribute("active");
|
|
858
872
|
}
|
|
@@ -861,6 +875,26 @@ function setNavActive(activeNav) {
|
|
|
861
875
|
|
|
862
876
|
let panelRequested = false;
|
|
863
877
|
let syncTimer = null;
|
|
878
|
+
let navObserver = null;
|
|
879
|
+
let nativeActiveBeforeOpen = null;
|
|
880
|
+
|
|
881
|
+
function suppressNativeNavActive() {
|
|
882
|
+
const own = document.getElementById(NAV_ID);
|
|
883
|
+
if (!own) return;
|
|
884
|
+
if (!panelRequested) {
|
|
885
|
+
if (own.hasAttribute("active")) own.removeAttribute("active");
|
|
886
|
+
return;
|
|
887
|
+
}
|
|
888
|
+
for (const nav of navItems()) {
|
|
889
|
+
if (nav !== own && nav.hasAttribute("active")) nav.removeAttribute("active");
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
function watchNavActive() {
|
|
894
|
+
if (navObserver || !document.body) return;
|
|
895
|
+
navObserver = new MutationObserver(suppressNativeNavActive);
|
|
896
|
+
navObserver.observe(document.body, { subtree: true, attributes: true, attributeFilter: ["active"] });
|
|
897
|
+
}
|
|
864
898
|
|
|
865
899
|
function startSync() {
|
|
866
900
|
if (syncTimer === null) syncTimer = setInterval(keepPanelInSync, 300);
|
|
@@ -885,7 +919,11 @@ function openPanel() {
|
|
|
885
919
|
if (existing) existing.remove();
|
|
886
920
|
content.append(buildPanel());
|
|
887
921
|
|
|
888
|
-
|
|
922
|
+
const ownNav = document.getElementById(NAV_ID);
|
|
923
|
+
if (!nativeActiveBeforeOpen) {
|
|
924
|
+
nativeActiveBeforeOpen = navItems().find((nav) => nav !== ownNav && nav.hasAttribute("active")) ?? null;
|
|
925
|
+
}
|
|
926
|
+
setNavActive(ownNav);
|
|
889
927
|
const currentTitle = document.querySelector(".lol-settings-title-current");
|
|
890
928
|
if (currentTitle) currentTitle.textContent = TAB_TITLE.toUpperCase();
|
|
891
929
|
}
|
|
@@ -897,7 +935,9 @@ function closePanel() {
|
|
|
897
935
|
panel.remove();
|
|
898
936
|
const options = document.querySelector(".lol-settings-content .lol-settings-options");
|
|
899
937
|
if (options) options.style.display = "";
|
|
900
|
-
|
|
938
|
+
document.getElementById(NAV_ID)?.removeAttribute("active");
|
|
939
|
+
if (nativeActiveBeforeOpen?.isConnected) nativeActiveBeforeOpen.setAttribute("active", "true");
|
|
940
|
+
nativeActiveBeforeOpen = null;
|
|
901
941
|
}
|
|
902
942
|
|
|
903
943
|
function keepPanelInSync() {
|
|
@@ -905,6 +945,7 @@ function keepPanelInSync() {
|
|
|
905
945
|
if (!content) {
|
|
906
946
|
panelRequested = false;
|
|
907
947
|
stopSync();
|
|
948
|
+
document.getElementById(NAV_ID)?.removeAttribute("active");
|
|
908
949
|
return;
|
|
909
950
|
}
|
|
910
951
|
if (!panelRequested) {
|
|
@@ -923,12 +964,7 @@ function keepPanelInSync() {
|
|
|
923
964
|
if (options && options.style.display !== "none") options.style.display = "none";
|
|
924
965
|
|
|
925
966
|
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
|
-
}
|
|
967
|
+
if (nav) setNavActive(nav);
|
|
932
968
|
|
|
933
969
|
const title = document.querySelector(".lol-settings-title-current");
|
|
934
970
|
if (title && title.textContent !== TAB_TITLE.toUpperCase()) title.textContent = TAB_TITLE.toUpperCase();
|
|
@@ -967,6 +1003,7 @@ function isDoneButton(target) {
|
|
|
967
1003
|
|
|
968
1004
|
function installSettingsTab() {
|
|
969
1005
|
addStyle(STYLE_ID, STYLE_CSS);
|
|
1006
|
+
watchNavActive();
|
|
970
1007
|
|
|
971
1008
|
document.addEventListener(
|
|
972
1009
|
"click",
|
package/unlock-profile-skins.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const version = "1.2.
|
|
1
|
+
export const version = "1.2.6";
|
|
2
2
|
|
|
3
3
|
const PLUGIN_ID = "unlock-profile-skins";
|
|
4
4
|
const PICKER_BUTTON_SELECTOR = ".style-profile-skin-picker-button";
|
|
@@ -39,8 +39,39 @@ function logError(scope, error) {
|
|
|
39
39
|
console.error(`[Perfectionist] Unlock Profile Skins: ${scope}`, error);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
const PICKER_ARM_MS = 5000;
|
|
43
|
+
let pickerArmUntil = 0;
|
|
44
|
+
let pickerArmTimer = null;
|
|
45
|
+
|
|
42
46
|
function isPickerOpen() {
|
|
43
|
-
|
|
47
|
+
for (const dialog of document.querySelectorAll("lol-uikit-dialog-frame")) {
|
|
48
|
+
const rect = dialog.getBoundingClientRect();
|
|
49
|
+
if (rect.width <= 0 || rect.height <= 0) continue;
|
|
50
|
+
if (/set profile background/i.test(dialog.textContent || "")) return true;
|
|
51
|
+
}
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function shouldFilter() {
|
|
56
|
+
return filterActive && (isPickerOpen() || Date.now() < pickerArmUntil);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function armPicker() {
|
|
60
|
+
pickerArmUntil = Date.now() + PICKER_ARM_MS;
|
|
61
|
+
if (pickerArmTimer !== null) clearTimeout(pickerArmTimer);
|
|
62
|
+
const waitForPicker = () => {
|
|
63
|
+
if (isPickerOpen()) {
|
|
64
|
+
pickerArmTimer = null;
|
|
65
|
+
startTierGrouping();
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (Date.now() >= pickerArmUntil) {
|
|
69
|
+
pickerArmTimer = null;
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
pickerArmTimer = setTimeout(waitForPicker, 100);
|
|
73
|
+
};
|
|
74
|
+
pickerArmTimer = setTimeout(waitForPicker, 50);
|
|
44
75
|
}
|
|
45
76
|
|
|
46
77
|
function cleanPath(url) {
|
|
@@ -386,7 +417,7 @@ function ensureSummonerId() {
|
|
|
386
417
|
});
|
|
387
418
|
}
|
|
388
419
|
function rewriteInventoryText(raw) {
|
|
389
|
-
if (typeof raw !== "string") return raw;
|
|
420
|
+
if (!shouldFilter() || typeof raw !== "string") return raw;
|
|
390
421
|
if (inventoryTextCache.has(raw)) {
|
|
391
422
|
const cached = inventoryTextCache.get(raw);
|
|
392
423
|
inventoryTextCache.delete(raw);
|
|
@@ -406,7 +437,7 @@ function rewriteInventoryText(raw) {
|
|
|
406
437
|
}
|
|
407
438
|
|
|
408
439
|
function rewriteWebSocketFrame(text) {
|
|
409
|
-
if (!
|
|
440
|
+
if (!shouldFilter() || typeof text !== "string") return null;
|
|
410
441
|
const targetFrame = text.indexOf("lol-champions/v1/inventories") !== -1;
|
|
411
442
|
const augmentFrame = text.indexOf("SKIN_AUGMENT") !== -1;
|
|
412
443
|
if (!targetFrame && !augmentFrame) return null;
|
|
@@ -512,12 +543,12 @@ function installFetchFilter() {
|
|
|
512
543
|
const inventory = pathIdOf(url) !== null;
|
|
513
544
|
const augmentRequest = isAugmentUrl(url);
|
|
514
545
|
let options = init;
|
|
515
|
-
if (
|
|
546
|
+
if (shouldFilter() && options && typeof options.body === "string") {
|
|
516
547
|
const mapped = remapVariantIds(options.body);
|
|
517
548
|
if (mapped !== options.body) options = { ...options, body: mapped };
|
|
518
549
|
}
|
|
519
550
|
const promise = original.call(this, input, options);
|
|
520
|
-
if (!
|
|
551
|
+
if (!shouldFilter() || (!inventory && !augmentRequest)) return promise;
|
|
521
552
|
if (inventory) maybeRefreshSummoner();
|
|
522
553
|
|
|
523
554
|
return whenSummonerKnown(SUMMONER_WAIT_MS).then(() => {
|
|
@@ -594,13 +625,13 @@ function installXhrFilter() {
|
|
|
594
625
|
const url = this.__perfProfileUrl || "";
|
|
595
626
|
const target = isTargetUrl(url);
|
|
596
627
|
const augment = !target && isAugmentUrl(url);
|
|
597
|
-
if (
|
|
598
|
-
if (
|
|
628
|
+
if (shouldFilter() && pathIdOf(url) !== null) maybeRefreshSummoner();
|
|
629
|
+
if (shouldFilter() && typeof args[0] === "string") {
|
|
599
630
|
const mapped = remapVariantIds(args[0]);
|
|
600
631
|
if (mapped !== args[0]) args = [mapped, ...args.slice(1)];
|
|
601
632
|
}
|
|
602
633
|
const xhr = this;
|
|
603
|
-
if (target &&
|
|
634
|
+
if (target && shouldFilter() && augmentIds.size === 0 && textDescriptor && textDescriptor.get) {
|
|
604
635
|
const latch = new Promise((resolve) => {
|
|
605
636
|
const finish = () => {
|
|
606
637
|
if (augmentIds.size === 0) {
|
|
@@ -619,7 +650,7 @@ function installXhrFilter() {
|
|
|
619
650
|
}
|
|
620
651
|
if (textDescriptor && textDescriptor.get && (pathIdOf(url) !== null || augment)) {
|
|
621
652
|
const cache = { raw: null, gate: null, filtered: null };
|
|
622
|
-
const gateOpen = () =>
|
|
653
|
+
const gateOpen = () => shouldFilter() && (augment || isTargetUrl(url));
|
|
623
654
|
const rewriteBody = (json) => (augment ? unlockAugmentInventory(json) : unlockDeep(json));
|
|
624
655
|
const filteredText = () => {
|
|
625
656
|
const gate = gateOpen();
|
|
@@ -653,7 +684,7 @@ function installXhrFilter() {
|
|
|
653
684
|
});
|
|
654
685
|
}
|
|
655
686
|
}
|
|
656
|
-
if (augment &&
|
|
687
|
+
if (augment && shouldFilter() && augmentIds.size === 0) {
|
|
657
688
|
const sendArgs = args;
|
|
658
689
|
ensureAugmentIds().finally(() => {
|
|
659
690
|
try {
|
|
@@ -693,11 +724,10 @@ function onEnable(utils) {
|
|
|
693
724
|
filterActive = true;
|
|
694
725
|
ensureSourceFilter();
|
|
695
726
|
ensureSummonerId();
|
|
696
|
-
tierArmListener = () => {
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
}, 0);
|
|
727
|
+
tierArmListener = (event) => {
|
|
728
|
+
const target = event.target instanceof Element ? event.target.closest(PICKER_BUTTON_SELECTOR) : null;
|
|
729
|
+
if (!target) return;
|
|
730
|
+
armPicker();
|
|
701
731
|
};
|
|
702
732
|
document.addEventListener("click", tierArmListener, true);
|
|
703
733
|
if (isPickerOpen()) startTierGrouping();
|
|
@@ -708,6 +738,9 @@ function onDisable() {
|
|
|
708
738
|
inventoryTextCache.clear();
|
|
709
739
|
if (tierArmListener) document.removeEventListener("click", tierArmListener, true);
|
|
710
740
|
tierArmListener = null;
|
|
741
|
+
if (pickerArmTimer !== null) clearTimeout(pickerArmTimer);
|
|
742
|
+
pickerArmTimer = null;
|
|
743
|
+
pickerArmUntil = 0;
|
|
711
744
|
stopTierGrouping();
|
|
712
745
|
api = null;
|
|
713
746
|
}
|