Prechádzať zdrojové kódy

ref: migrate feat help menu to dialog

Sv443 1 rok pred
rodič
commit
53cce4a0a6

+ 6 - 5
src/components/BytmDialog.ts

@@ -20,6 +20,8 @@ export interface BytmDialogOptions {
   closeBtnEnabled?: boolean;
   /** Whether the dialog should be destroyed when it's closed - defaults to false */
   destroyOnClose?: boolean;
+  /** Whether the dialog should be unmounted when it's closed - defaults to false */
+  unmountOnClose?: boolean;
   /** Whether the menu should have a smaller overall appearance - defaults to false */
   smallDialog?: boolean;
   /** Called to render the body of the dialog */
@@ -51,7 +53,6 @@ export class BytmDialog extends NanoEmitter<{
 
   private dialogOpen = false;
   private dialogMounted = false;
-  private listenersAttached = false;
 
   constructor(options: BytmDialogOptions) {
     super();
@@ -61,6 +62,7 @@ export class BytmDialog extends NanoEmitter<{
       closeOnEscPress: true,
       closeBtnEnabled: true,
       destroyOnClose: false,
+      unmountOnClose: false,
       smallHeader: false,
       ...options,
     };
@@ -186,6 +188,9 @@ export class BytmDialog extends NanoEmitter<{
 
     if(this.options.destroyOnClose)
       this.destroy();
+
+    if(this.options.unmountOnClose)
+      this.unmount();
   }
 
   /** Returns true if the dialog is currently open */
@@ -216,10 +221,6 @@ export class BytmDialog extends NanoEmitter<{
 
   /** Called once to attach all generic event listeners */
   protected attachListeners(bgElem: HTMLElement) {
-    if(this.listenersAttached)
-      return;
-    this.listenersAttached = true;
-
     if(this.options.closeOnBgClick) {
       bgElem.addEventListener("click", (e) => {
         if(this.isOpen() && (e.target as HTMLElement)?.id === `bytm-${this.id}-dialog-bg`)

+ 72 - 0
src/dialogs/featHelp.ts

@@ -0,0 +1,72 @@
+import { resourceToHTMLString, t } from "../utils";
+import { BytmDialog } from "../components";
+import { featInfo } from "../features";
+import type { FeatureKey } from "../types";
+
+let featHelpDialog: BytmDialog | null = null;
+
+export type FeatHelpDialogRenderProps = {
+  featKey: FeatureKey;
+};
+
+/** Creates and/or returns the help dialog for a specific feature */
+export async function getFeatHelpDialog({
+  featKey,
+}: FeatHelpDialogRenderProps) {
+  if(!featHelpDialog) {
+    featHelpDialog = new BytmDialog({
+      id: "feat-help",
+      maxWidth: 600,
+      maxHeight: 400,
+      closeBtnEnabled: true,
+      closeOnBgClick: true,
+      closeOnEscPress: true,
+      destroyOnClose: true,
+      smallDialog: true,
+      renderHeader,
+      renderBody: () => renderBody({ featKey }),
+    });
+
+    featHelpDialog.on("destroy", () => featHelpDialog = null);
+
+    // make config menu inert while help dialog is open
+    featHelpDialog.on("open", () => document.querySelector("#bytm-cfg-menu")?.setAttribute("inert", "true"));
+    featHelpDialog.on("close", () => document.querySelector("#bytm-cfg-menu")?.removeAttribute("inert"));
+  }
+  return featHelpDialog;
+}
+
+async function renderHeader() {
+  const headerEl = document.createElement("div");
+  headerEl.role = "heading";
+  headerEl.ariaLevel = "1";
+  const helpIconSvg = await resourceToHTMLString("icon-help");
+  if(helpIconSvg)
+    headerEl.innerHTML = helpIconSvg;
+
+  return headerEl;
+}
+
+async function renderBody({
+  featKey,
+}: {
+  featKey: FeatureKey;
+}) {
+  const contElem = document.createElement("div");
+
+  const featDescElem = document.createElement("h3");
+  featDescElem.role = "subheading";
+  featDescElem.textContent = t(`feature_desc_${featKey}`);
+  featDescElem.id = "bytm-feat-help-menu-desc";
+
+  const helpTextElem = document.createElement("div");
+  helpTextElem.id = "bytm-feat-help-menu-text";
+  // @ts-ignore
+  const helpText: string | undefined = featInfo[featKey]?.helpText?.();
+  helpTextElem.textContent = helpText ?? t(`feature_helptext_${featKey}`);
+
+  contElem.appendChild(featDescElem);
+  contElem.appendChild(helpTextElem);
+
+  return contElem;
+}

+ 1 - 0
src/dialogs/index.ts

@@ -1,3 +1,4 @@
 import "./dialogs.css";
 
 export * from "./versionNotif";
+export * from "./featHelp";

+ 10 - 4
src/menu/menu_old.css

@@ -404,16 +404,22 @@
   font-weight: bolder;
 }
 
+.bytm-markdown-container ul li > ul li > ul li::before {
+  white-space: pre-wrap;
+  content: "        • ";
+  font-weight: bolder;
+}
+
 #bytm-feat-help-menu-desc, #bytm-feat-help-menu-text {
   overflow-wrap: break-word;
   white-space: pre-wrap;
-  padding: 10px 10px 15px 20px;
-  font-size: 1.5em;
+  font-size: 1.5rem;
+  line-height: 1.25em;
 }
 
 #bytm-feat-help-menu-desc {
-  font-size: 1.65em;
-  padding-bottom: 5px;
+  font-size: 1.8rem;
+  padding-bottom: 10px;
 }
 
 .bytm-ftitem-help-btn {

+ 3 - 121
src/menu/menu_old.ts

@@ -5,6 +5,7 @@ import { featInfo, disableBeforeUnload } from "../features/index";
 import { error, getResourceUrl, info, log, resourceToHTMLString, warn, getLocale, hasKey, initTranslations, setLocale, t, compressionSupported, getChangelogHtmlWithDetails, arrayWithSeparators, tp, type TrKey, onInteraction } from "../utils";
 import { formatVersion } from "../config";
 import { emitSiteEvent, siteEvents } from "../siteEvents";
+import { getFeatHelpDialog } from "../dialogs";
 import type { FeatureCategory, FeatureKey, FeatureConfig, HotkeyObj, FeatureInfo } from "../types";
 import "./menu_old.css";
 import { createHotkeyInput, createToggleInput } from "../components";
@@ -342,11 +343,11 @@ async function addCfgMenu() {
             helpElem.role = "button";
             helpElem.tabIndex = 0;
             helpElem.innerHTML = helpElemImgHtml;
-            onInteraction(helpElem, (e: MouseEvent | KeyboardEvent) => {
+            onInteraction(helpElem, async (e: MouseEvent | KeyboardEvent) => {
               e.preventDefault();
               e.stopPropagation();
 
-              openHelpDialog(featKey as FeatureKey);
+              await (await getFeatHelpDialog({ featKey: featKey as FeatureKey })).open();
             });
           }
           else {
@@ -793,125 +794,6 @@ function checkToggleScrollIndicator() {
   }
 }
 
-//#MARKER help dialog
-
-let isHelpDialogOpen = false;
-/** Key of the feature currently loaded in the help dialog */
-let helpDialogCurFeature: FeatureKey | undefined;
-
-/** Opens the feature help dialog for the given feature */
-async function openHelpDialog(featureKey: FeatureKey) {
-  if(isHelpDialogOpen)
-    return;
-  isHelpDialogOpen = true;
-
-  let menuBgElem: HTMLElement;
-
-  if(!helpDialogCurFeature) {
-    // create menu
-
-    const headerElem = document.createElement("div");
-    headerElem.classList.add("bytm-menu-header", "small");
-
-    const titleCont = document.createElement("div");
-    titleCont.className = "bytm-menu-titlecont-no-title";
-    titleCont.role = "heading";
-    titleCont.ariaLevel = "1";
-
-    const helpIconSvg = await resourceToHTMLString("icon-help");
-    if(helpIconSvg)
-      titleCont.innerHTML = helpIconSvg;
-
-    const closeElem = document.createElement("img");
-    closeElem.classList.add("bytm-menu-close", "small");
-    closeElem.role = "button";
-    closeElem.tabIndex = 0;
-    closeElem.src = await getResourceUrl("img-close");
-    closeElem.ariaLabel = closeElem.title = t("close_menu_tooltip");
-    onInteraction(closeElem, closeHelpDialog);
-
-    headerElem.appendChild(titleCont);
-    headerElem.appendChild(closeElem);
-
-    menuBgElem = document.createElement("div");
-    menuBgElem.id = "bytm-feat-help-menu-bg";
-    menuBgElem.classList.add("bytm-menu-bg");
-    menuBgElem.ariaLabel = menuBgElem.title = t("close_menu_tooltip");
-    menuBgElem.style.visibility = "hidden";
-    menuBgElem.style.display = "none";
-    menuBgElem.addEventListener("click", (e) => {
-      if(isHelpDialogOpen && (e.target as HTMLElement)?.id === "bytm-feat-help-menu-bg")
-        closeHelpDialog(e);
-    });
-    document.body.addEventListener("keydown", (e) => {
-      if(isHelpDialogOpen && e.key === "Escape")
-        closeHelpDialog(e);
-    });
-
-    const menuContainer = document.createElement("div");
-    menuContainer.ariaLabel = menuContainer.title = ""; // prevent bg title from propagating downwards
-    menuContainer.classList.add("bytm-menu");
-    menuContainer.id = "bytm-feat-help-menu";
-
-    const featDescElem = document.createElement("h3");
-    featDescElem.id = "bytm-feat-help-menu-desc";
-
-    const helpTextElem = document.createElement("div");
-    helpTextElem.id = "bytm-feat-help-menu-text";
-
-    menuContainer.appendChild(headerElem);
-    menuContainer.appendChild(featDescElem);
-    menuContainer.appendChild(helpTextElem);
-
-    menuBgElem.appendChild(menuContainer);
-    document.body.appendChild(menuBgElem);
-  }
-  else
-    menuBgElem = document.querySelector<HTMLElement>("#bytm-feat-help-menu-bg")!;
-
-  if(helpDialogCurFeature !== featureKey) {
-    // update help text
-    const featDescElem = menuBgElem.querySelector<HTMLElement>("#bytm-feat-help-menu-desc")!;
-    const helpTextElem = menuBgElem.querySelector<HTMLElement>("#bytm-feat-help-menu-text")!;
-
-    featDescElem.textContent = t(`feature_desc_${featureKey}`);
-
-    // @ts-ignore
-    const helpText: string | undefined = featInfo[featureKey]?.helpText?.();
-    helpTextElem.textContent = helpText ?? t(`feature_helptext_${featureKey}`);
-  }
-
-  // show menu
-  const menuBg = document.querySelector<HTMLElement>("#bytm-feat-help-menu-bg");
-
-  if(!menuBg)
-    return warn("Couldn't find feature help dialog background element");
-
-  helpDialogCurFeature = featureKey;
-
-  menuBg.style.visibility = "visible";
-  menuBg.style.display = "block";
-
-  document.querySelector("#bytm-cfg-menu")?.setAttribute("inert", "true");
-}
-
-function closeHelpDialog(evt?: MouseEvent | KeyboardEvent) {
-  if(!isHelpDialogOpen)
-    return;
-  isHelpDialogOpen = false;
-  evt?.bubbles && evt.stopPropagation();
-
-  const menuBg = document.querySelector<HTMLElement>("#bytm-feat-help-menu-bg");
-
-  if(!menuBg)
-    return warn("Couldn't find feature help dialog background element");
-
-  menuBg.style.visibility = "hidden";
-  menuBg.style.display = "none";
-
-  document.querySelector("#bytm-cfg-menu")?.removeAttribute("inert");
-}
-
 //#MARKER export menu
 
 let isExportMenuAdded = false;