perfectionist-plugins 2.4.3 → 2.4.5

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/dodge-helper.js CHANGED
@@ -1,5 +1,5 @@
1
1
  const PLUGIN_ID = "dodge-helper";
2
- export const version = "1.4.0";
2
+ export const version = "1.4.2";
3
3
 
4
4
  const PHASE_URI = "/lol-gameflow/v1/gameflow-phase";
5
5
  const SESSION_URI = "/lol-gameflow/v1/session";
@@ -62,6 +62,7 @@ const state = {
62
62
  account: null,
63
63
  penalty: null,
64
64
  lastSelfDodgeAt: 0,
65
+ lockedLocalPick: false,
65
66
  anchor: null,
66
67
  };
67
68
 
@@ -198,6 +199,8 @@ async function refreshPenalty() {
198
199
  if (!active || token !== penaltyToken || queueId !== state.queueId) return;
199
200
  state.penalty = penalty;
200
201
  render();
202
+ bindButton(document.getElementById(BUTTON_ID));
203
+ requestAnimationFrame(() => bindButton(document.getElementById(BUTTON_ID)));
201
204
  }
202
205
 
203
206
  function applySession(raw) {
@@ -219,6 +222,16 @@ function applySession(raw) {
219
222
  ensureMount();
220
223
  }
221
224
 
225
+ function syncLocalPick(session) {
226
+ const cellId = Number(session?.localPlayerCellId);
227
+ if (!Number.isFinite(cellId)) return;
228
+ const actions = Array.isArray(session.actions) ? session.actions.flat() : [];
229
+ const locked = actions.some(
230
+ (action) => Number(action?.actorCellId) === cellId && action?.type === "pick" && action?.completed === true
231
+ );
232
+ if (locked) state.lockedLocalPick = true;
233
+ }
234
+
222
235
  function applyChampSelect(raw) {
223
236
  const session = unwrap(raw);
224
237
  if (!session) return;
@@ -226,6 +239,7 @@ function applyChampSelect(raw) {
226
239
  const queueId = Number(session.queueId ?? 0) || 0;
227
240
  if (queueId > 0) state.queueId = queueId;
228
241
  if (session.isCustomGame) state.isCustom = true;
242
+ syncLocalPick(session);
229
243
  ensureMount();
230
244
  syncWatching();
231
245
  }
@@ -238,6 +252,25 @@ function unmount() {
238
252
  }
239
253
  }
240
254
 
255
+ function onButtonClick(event) {
256
+ event.preventDefault();
257
+ event.stopPropagation();
258
+ quitOrDodge();
259
+ }
260
+
261
+ function bindButton(button) {
262
+ if (!button) return;
263
+ if (!button.__perfClickBound) {
264
+ button.__perfClickBound = true;
265
+ button.addEventListener("click", onButtonClick, true);
266
+ }
267
+ const inner = button.shadowRoot?.querySelector(".lol-uikit-flat-button");
268
+ if (inner && !inner.__perfClickBound) {
269
+ inner.__perfClickBound = true;
270
+ inner.addEventListener("click", onButtonClick);
271
+ }
272
+ }
273
+
241
274
  function build() {
242
275
  const root = document.createElement("div");
243
276
  root.id = ROOT_ID;
@@ -246,11 +279,7 @@ function build() {
246
279
  lp.className = "perf-dodge-lp";
247
280
  const button = document.createElement("lol-uikit-flat-button");
248
281
  button.id = BUTTON_ID;
249
- button.addEventListener("click", (event) => {
250
- event.preventDefault();
251
- event.stopPropagation();
252
- quitOrDodge();
253
- });
282
+ bindButton(button);
254
283
  root.append(lp, button);
255
284
  return root;
256
285
  }
@@ -287,11 +316,15 @@ function ensureMount() {
287
316
  const roots = [...document.querySelectorAll(`#${ROOT_ID}`)];
288
317
  for (const extra of roots.slice(1)) extra.remove();
289
318
  const root = roots[0] ?? build();
290
- if (root.parentElement !== target.element) target.element.append(root);
319
+ if (root.parentElement !== target.element) target.element.prepend(root);
320
+ else if (target.kind === "quit" && target.element.firstElementChild !== root) target.element.prepend(root);
291
321
  root.classList.toggle("perf-dodge-quit", target.kind === "quit");
292
322
  root.classList.toggle("perf-dodge-bar", target.kind === "bar");
293
323
  root.classList.toggle("perf-dodge-floating", target.kind === "floating");
294
324
  render();
325
+ bindButton(document.getElementById(BUTTON_ID));
326
+ requestAnimationFrame(() => bindButton(document.getElementById(BUTTON_ID)));
327
+ setTimeout(() => bindButton(document.getElementById(BUTTON_ID)), 500);
295
328
  }
296
329
 
297
330
  function scheduleMount() {
@@ -409,8 +442,16 @@ async function quitOrDodge() {
409
442
  }
410
443
 
411
444
  async function handlePhase(raw) {
445
+ const previous = state.phase;
412
446
  const phase = typeof raw === "string" ? raw : unwrap(raw);
413
447
  if (typeof phase === "string" && phase) state.phase = phase;
448
+ if (previous === "ChampSelect" && state.phase !== "ChampSelect" && state.phase !== "GameStart" && state.phase !== "InProgress") {
449
+ if (RANKED_QUEUES.has(state.queueId) && !state.lockedLocalPick && !hasNativeQuit()) {
450
+ recordDodge();
451
+ }
452
+ state.lockedLocalPick = false;
453
+ }
454
+ if (state.phase === "ChampSelect" && previous !== "ChampSelect") state.lockedLocalPick = false;
414
455
  if (state.phase === "ChampSelect") {
415
456
  await loadAccount();
416
457
  const [session, champSelect] = await Promise.all([
@@ -491,6 +532,7 @@ function onDisable() {
491
532
  state.account = null;
492
533
  state.penalty = null;
493
534
  state.lastSelfDodgeAt = 0;
535
+ state.lockedLocalPick = false;
494
536
  penaltyToken = 0;
495
537
  api = null;
496
538
  }
@@ -503,7 +545,6 @@ export function init() {
503
545
  description:
504
546
  "Adds a DODGE/QUIT button to champion select: DODGE with the estimated LP loss for ranked queues, QUIT for every other mode. Hidden when the client already shows its own QUIT button.",
505
547
  version,
506
- defaultEnabled: true,
507
548
  onEnable,
508
549
  onDisable,
509
550
  });
@@ -516,4 +557,4 @@ export function init() {
516
557
  addEventListener("perfectionist:utils-ready", (event) => registerWith(event.detail ?? window.PerfectionistUtils), {
517
558
  once: true,
518
559
  });
519
- }
560
+ }
@@ -361,7 +361,6 @@ let topLevelOrder = [];
361
361
  let ownedTopLevelIds = null;
362
362
  let currentChampionId = null;
363
363
  let carouselOrder = [];
364
- let selectedSkinId = null;
365
364
  let failure = null;
366
365
  let requestToken = 0;
367
366
  let refreshTimer = null;
@@ -371,7 +370,6 @@ let selectInFlight = false;
371
370
  let sessionMisses = 0;
372
371
  let championMisses = 0;
373
372
  let renderObserver = null;
374
- const skinSuffixCache = new Map();
375
373
  let removeStyle = null;
376
374
 
377
375
  function logError(scope, error) {
@@ -536,7 +534,6 @@ function nextOwnedSkin(owned, fromId, direction) {
536
534
  }
537
535
 
538
536
  async function selectSkin(skinId) {
539
- selectedSkinId = skinId;
540
537
  selectInFlight = true;
541
538
  const guard = setTimeout(() => {
542
539
  selectInFlight = false;
@@ -556,7 +553,6 @@ function resetState() {
556
553
  topLevelOrder = [];
557
554
  ownedTopLevelIds = null;
558
555
  currentChampionId = null;
559
- selectedSkinId = null;
560
556
  carouselOrder = [];
561
557
  clientSkinOrder = [];
562
558
  failure = null;
@@ -576,7 +572,7 @@ function loadChampion(championId) {
576
572
  const token = ++requestToken;
577
573
 
578
574
  Promise.all([loadOwnedSkins(championId), loadCarouselOrder()]).then(
579
- ([{ owned, order: inventoryOrder, topLevel, ownedTopLevel, entries }, carouselIds]) => {
575
+ ([{ owned, order: inventoryOrder, topLevel, ownedTopLevel }, carouselIds]) => {
580
576
  if (token !== requestToken) return;
581
577
  ownedSkinIds = owned;
582
578
  allSkinIds = new Set(inventoryOrder);
@@ -613,8 +609,6 @@ function updateForSession(session, selection) {
613
609
  if (ownedSkinIds === null) return;
614
610
 
615
611
  const serverSkinId = selection?.selectedSkinId || me.selectedSkinId || null;
616
- const belongsToChampion = serverSkinId !== null && Math.floor(serverSkinId / 1000) === championId;
617
- if (!selectInFlight && belongsToChampion) selectedSkinId = serverSkinId;
618
612
 
619
613
  const knownUnownedSkin = allSkinIds !== null && allSkinIds.has(serverSkinId) && !ownedSkinIds.has(serverSkinId);
620
614
  if (!selectInFlight && knownUnownedSkin) {
@@ -697,7 +691,6 @@ export function init() {
697
691
  name: "Hide Unowned Skins",
698
692
  description: "In champion select, only shows the skins you own for the picked champion.",
699
693
  version,
700
- defaultEnabled: true,
701
694
  onEnable,
702
695
  onDisable,
703
696
  });
@@ -708,4 +701,4 @@ export function init() {
708
701
  } else {
709
702
  addEventListener("perfectionist:utils-ready", (event) => registerWith(event.detail), { once: true });
710
703
  }
711
- }
704
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "perfectionist-plugins",
3
- "version": "2.4.3",
3
+ "version": "2.4.5",
4
4
  "description": "Small plugins that fix the annoying parts of League of Legends champ select. Built for Pengu Loader.",
5
5
  "type": "module",
6
6
  "main": "perfectionist-utils.js",