Browse Source

feat: toggle auto-like btn on chan. page if toggled in dialog

Sv443 8 months ago
parent
commit
f5325c69ba

+ 15 - 11
src/dialogs/autoLike.ts

@@ -24,6 +24,7 @@ export async function getAutoLikeDialog() {
       closeOnBgClick: true,
       closeOnEscPress: true,
       destroyOnClose: true,
+      removeListenersOnDestroy: false,
       small: true,
       verticalAlign: "top",
       renderHeader,
@@ -40,6 +41,8 @@ export async function getAutoLikeDialog() {
         log("Auto-like channels updated, refreshed dialog");
       }
     });
+
+    autoLikeDialog.on("close", () => emitSiteEvent("autoLikeChannelsUpdated"));
   }
   
   if(!autoLikeImExDialog) {
@@ -143,15 +146,13 @@ async function renderBody() {
   const channelListCont = document.createElement("div");
   channelListCont.id = "bytm-auto-like-channels-list";
 
-  const removeChannel = (id: string) => autoLikeStore.setData({
-    channels: autoLikeStore.getData().channels.filter((ch) => ch.id !== id),
-  });
-
-  const setChannelEnabled = (id: string, enabled: boolean) => debounce(
-    () => autoLikeStore.setData({
-      channels: autoLikeStore.getData().channels
-        .map((ch) => ch.id === id ? { ...ch, enabled } : ch),
-    }),
+  const setChannelEnabled = debounce(
+    (id: string, enabled: boolean) => {
+      autoLikeStore.setData({
+        channels: autoLikeStore.getData().channels
+          .map((ch) => ch.id === id ? { ...ch, enabled } : ch),
+      });
+    },
     250,
     "rising"
   );
@@ -190,7 +191,7 @@ async function renderBody() {
     nameLabelEl.appendChild(idElem);
 
     const toggleElem = await createToggleInput({
-      id: `bytm-auto-like-channel-list-toggle-${chanId}`,
+      id: `auto-like-channel-list-${chanId}`,
       labelPos: "off",
       initialValue: enabled,
       onChange: (en) => setChannelEnabled(chanId, en),
@@ -228,7 +229,10 @@ async function renderBody() {
       resourceName: "icon-delete",
       title: t("remove_entry"),
       async onClick() {
-        await removeChannel(chanId);
+        autoLikeStore.setData({
+          channels: autoLikeStore.getData().channels.filter((ch) => ch.id !== chanId),
+        });
+        emitSiteEvent("autoLikeChannelsUpdated");
         rowElem.remove();
       },
     });

+ 19 - 2
src/features/input.ts

@@ -1,5 +1,5 @@
 import { DataStore, clamp, compress, decompress } from "@sv443-network/userutils";
-import { error, getVideoTime, info, log, warn, getVideoSelector, getDomain, compressionSupported, t, clearNode, resourceAsString, getCurrentChannelId, currentMediaType } from "../utils/index.js";
+import { error, getVideoTime, info, log, warn, getVideoSelector, getDomain, compressionSupported, t, clearNode, resourceAsString, getCurrentChannelId, currentMediaType, sanitizeChannelId } from "../utils/index.js";
 import type { AutoLikeData, Domain } from "../types.js";
 import { disableBeforeUnload } from "./behavior.js";
 import { emitSiteEvent, siteEvents } from "../siteEvents.js";
@@ -356,7 +356,7 @@ async function addAutoLikeToggleBtn(siblingEl: HTMLElement, channelId: string, c
 
         buttonEl.title = buttonEl.ariaLabel = t(`auto_like_button_tooltip${toggled ? "_enabled" : "_disabled"}`);
 
-        const chanId = buttonEl.dataset.channelId ?? channelId;
+        const chanId = sanitizeChannelId(buttonEl.dataset.channelId ?? channelId);
 
         const imgEl = buttonEl.querySelector<HTMLElement>(".bytm-generic-btn-img");
         const imgHtml = await resourceAsString(`icon-auto_like${toggled ? "_enabled" : ""}`);
@@ -394,4 +394,21 @@ async function addAutoLikeToggleBtn(siblingEl: HTMLElement, channelId: string, c
   buttonEl.dataset.channelId = channelId;
 
   siblingEl.insertAdjacentElement("afterend", createRipple(buttonEl));
+
+  siteEvents.on("autoLikeChannelsUpdated", async () => {
+    const buttonEl = document.querySelector<HTMLElement>(`.bytm-auto-like-toggle-btn[data-channel-id="${channelId}"]`);
+    if(!buttonEl)
+      return;
+
+    const enabled = autoLikeStore.getData().channels.find((ch) => ch.id === channelId)?.enabled ?? false;
+    if(enabled)
+      buttonEl.classList.add("toggled");
+    else
+      buttonEl.classList.remove("toggled");
+
+    const imgEl = buttonEl.querySelector<HTMLElement>(".bytm-generic-btn-img");
+    const imgHtml = await resourceAsString(`icon-auto_like${enabled ? "_enabled" : ""}`);
+    if(imgEl && imgHtml)
+      imgEl.innerHTML = imgHtml;
+  });
 }

+ 1 - 2
src/features/layout.ts

@@ -2,7 +2,7 @@ import { addParent, autoPlural, debounce, fetchAdvanced, pauseFor } from "@sv443
 import { getFeature, getFeatures } from "../config.js";
 import { siteEvents } from "../siteEvents.js";
 import { addSelectorListener } from "../observers.js";
-import { error, getResourceUrl, log, warn, t, onInteraction, openInTab, getBestThumbnailUrl, getDomain, addStyle, currentMediaType, domLoaded, waitVideoElementReady, getVideoTime, fetchCss, addStyleFromResource, fetchVideoVotes, getWatchId, getLocale, dbg, tp } from "../utils/index.js";
+import { error, getResourceUrl, log, warn, t, onInteraction, openInTab, getBestThumbnailUrl, getDomain, addStyle, currentMediaType, domLoaded, waitVideoElementReady, getVideoTime, fetchCss, addStyleFromResource, fetchVideoVotes, getWatchId, getLocale, tp } from "../utils/index.js";
 import { mode, scriptInfo } from "../constants.js";
 import { openCfgMenu } from "../menu/menu_old.js";
 import { createCircularBtn, createRipple } from "../components/index.js";
@@ -342,7 +342,6 @@ export async function initRemShareTrackParam() {
   addSelectorListener("body", sharePanelSel, {
     listener: (sharePanelEl) => {
       const obs = new MutationObserver(() => {
-        dbg("># TODO:#DBG share panel changed");
         const inputElem = sharePanelEl.querySelector<HTMLInputElement>(inputSel);
         inputElem && removeSiParam(inputElem);
       });

+ 1 - 4
src/stories/assets/plus_circle_small.svg

@@ -1,4 +1 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg height="24" viewBox="0 -960 960 960" width="24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
-  <path fill="#ffffff" d="m 456.54655,-331.45728 h 46.9069 v -125.08927 h 125.08927 v -46.9069 H 503.45345 v -125.08927 h -46.9069 v 125.08927 H 331.45728 v 46.9069 h 125.08927 z m 23.50583,148.54349 q -61.63461,0 -115.86705,-23.39169 -54.23324,-23.39169 -94.35014,-63.49062 -40.11769,-40.0997 -63.51955,-94.3087 -23.40185,-54.20821 -23.40185,-115.84282 0,-61.63461 23.39169,-115.86705 23.39169,-54.23324 63.49062,-94.35014 40.0997,-40.11769 94.3087,-63.51955 54.20821,-23.40185 115.84282,-23.40185 61.63461,0 115.86705,23.39169 54.23324,23.39169 94.35014,63.49062 40.11769,40.0997 63.51955,94.3087 23.40185,54.20821 23.40185,115.84282 0,61.63461 -23.39169,115.86705 -23.39169,54.23324 -63.49062,94.35014 -40.0997,40.11769 -94.3087,63.51955 -54.20821,23.40185 -115.84282,23.40185 z M 480,-229.82148 q 104.76226,0 177.47039,-72.70813 72.70813,-72.70813 72.70813,-177.47039 0,-104.76226 -72.70813,-177.47039 Q 584.76226,-730.17852 480,-730.17852 q -104.76226,0 -177.47039,72.70813 -72.70813,72.70813 -72.70813,177.47039 0,104.76226 72.70813,177.47039 72.70813,72.70813 177.47039,72.70813 z M 480,-480 Z" style="stroke-width:0.781808" />
-</svg>
+<svg height="24" viewBox="0 -960 960 960" width="24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"><path fill="#ffffff" d="m 456.54655,-331.45728 h 46.9069 v -125.08927 h 125.08927 v -46.9069 H 503.45345 v -125.08927 h -46.9069 v 125.08927 H 331.45728 v 46.9069 h 125.08927 z m 23.50583,148.54349 q -61.63461,0 -115.86705,-23.39169 -54.23324,-23.39169 -94.35014,-63.49062 -40.11769,-40.0997 -63.51955,-94.3087 -23.40185,-54.20821 -23.40185,-115.84282 0,-61.63461 23.39169,-115.86705 23.39169,-54.23324 63.49062,-94.35014 40.0997,-40.11769 94.3087,-63.51955 54.20821,-23.40185 115.84282,-23.40185 61.63461,0 115.86705,23.39169 54.23324,23.39169 94.35014,63.49062 40.11769,40.0997 63.51955,94.3087 23.40185,54.20821 23.40185,115.84282 0,61.63461 -23.39169,115.86705 -23.39169,54.23324 -63.49062,94.35014 -40.0997,40.11769 -94.3087,63.51955 -54.20821,23.40185 -115.84282,23.40185 z M 480,-229.82148 q 104.76226,0 177.47039,-72.70813 72.70813,-72.70813 72.70813,-177.47039 0,-104.76226 -72.70813,-177.47039 Q 584.76226,-730.17852 480,-730.17852 q -104.76226,0 -177.47039,72.70813 -72.70813,72.70813 -72.70813,177.47039 0,104.76226 72.70813,177.47039 72.70813,72.70813 177.47039,72.70813 z M 480,-480 Z" style="stroke-width:0.781808" /></svg>

+ 2 - 2
src/utils/NanoEmitter.ts

@@ -19,7 +19,7 @@ export class NanoEmitter<TEvtMap extends EventsMap = DefaultEvents> {
   }
 
   /** Subscribes to an event - returns a function that unsubscribes the event listener */
-  public on<TKey extends keyof TEvtMap>(event: TKey, cb: TEvtMap[TKey]) {
+  public on<TKey extends keyof TEvtMap>(event: TKey | "_", cb: TEvtMap[TKey]) {
     // eslint-disable-next-line prefer-const
     let unsub: Unsubscribe | undefined;
 
@@ -37,7 +37,7 @@ export class NanoEmitter<TEvtMap extends EventsMap = DefaultEvents> {
   }
 
   /** Subscribes to an event and calls the callback or resolves the Promise only once */
-  public once<TKey extends keyof TEvtMap>(event: TKey, cb?: TEvtMap[TKey]): Promise<Parameters<TEvtMap[TKey]>> {
+  public once<TKey extends keyof TEvtMap>(event: TKey | "_", cb?: TEvtMap[TKey]): Promise<Parameters<TEvtMap[TKey]>> {
     return new Promise((resolve) => {
       // eslint-disable-next-line prefer-const
       let unsub: Unsubscribe | undefined;

+ 6 - 0
src/utils/misc.ts

@@ -162,6 +162,12 @@ export async function tryToDecompressAndParse<TData = Record<string, unknown>>(i
   return parsed;
 }
 
+/** Sanitizes a channel ID by adding a leading `@` if the ID doesn't start with `UC...` */
+export function sanitizeChannelId(channelId: string) {
+  channelId = String(channelId);
+  return (channelId.startsWith("UC") ? channelId : `@${channelId}`).trim();
+}
+
 //#region resources
 
 /**