Переглянути джерело

feat: add detail dialog when clicking on error toast

Sv443 8 місяців тому
батько
коміт
964082a726

+ 4 - 0
dist/BetterYTM.css

@@ -708,6 +708,10 @@ body .bytm-ripple.slower {
   transition: opacity var(--bytm-toast-transition-time) ease, transform var(--bytm-toast-transition-time) ease;
 }
 
+#bytm-toast.clickable {
+  cursor: pointer;
+}
+
 #bytm-toast.visible {
   pointer-events: auto;
   opacity: 1;

+ 4 - 9
src/components/MarkdownDialog.ts

@@ -30,12 +30,8 @@ export class MarkdownDialog extends BytmDialog {
 
   /** Renders the dialog body elements from a markdown string using what's set in `this.opts.body` */
   protected async renderBody(): Promise<HTMLElement> {
-    const panesCont = document.createElement("div");
-    panesCont.classList.add("bytm-exim-dialog-panes-cont");
-
-    const markdownPane = document.createElement("div");
-    markdownPane.classList.add("bytm-exim-dialog-pane");
-    markdownPane.classList.add("bytm-exim-dialog-markdown-pane");
+    const bodyEl = document.createElement("div");
+    bodyEl.classList.add("bytm-md-dialog-body");
 
     const mdCont = typeof this.opts.body === "string"
       ? this.opts.body
@@ -45,9 +41,8 @@ export class MarkdownDialog extends BytmDialog {
     markdownEl.classList.add("bytm-exim-dialog-markdown");
     markdownEl.innerHTML = await MarkdownDialog.parseMd(mdCont);
 
-    markdownPane.appendChild(markdownEl);
-    panesCont.appendChild(markdownPane);
+    bodyEl.appendChild(markdownEl);
 
-    return panesCont;
+    return bodyEl;
   }
 }

+ 4 - 0
src/components/toast.css

@@ -22,6 +22,10 @@
   transition: opacity var(--bytm-toast-transition-time) ease, transform var(--bytm-toast-transition-time) ease;
 }
 
+#bytm-toast.clickable {
+  cursor: pointer;
+}
+
 #bytm-toast.visible {
   pointer-events: auto;
   opacity: 1;

+ 10 - 1
src/components/toast.ts

@@ -9,7 +9,10 @@ export type ToastPos = "tl" | "tr" | "bl" | "br";
 export type ToastProps = {
   /** Duration in milliseconds */
   duration?: number;
+  /** Position of the toast on the screen */
   position?: ToastPos;
+  /** Function to be called when the toast is clicked */
+  onClick?: (evt?: MouseEvent) => void;
 } & (
   | {
     /** Message (plus title) for the toast */
@@ -93,6 +96,7 @@ export async function showIconToast({
     position,
     element: toastWrapper,
     title: "message" in rest ? rest.message : rest.title,
+    onClick: rest.onClick,
   });
 }
 
@@ -111,6 +115,7 @@ export async function showToast(arg: string | ToastProps): Promise<HTMLDivElemen
 
   const {
     duration: durationMs = getFeature("toastDuration") * 1000,
+    onClick,
     position = "tr",
     ...rest
   } = props;
@@ -122,12 +127,16 @@ export async function showToast(arg: string | ToastProps): Promise<HTMLDivElemen
     await closeToast();
 
   const toastElem = document.createElement("div");
+  onClick && toastElem.classList.add("clickable");
   toastElem.id = "bytm-toast";
   toastElem.role = "alert";
   toastElem.ariaLive = "polite";
   toastElem.ariaAtomic = "true";
 
-  toastElem.addEventListener("click", async () => await closeToast(), { once: true });
+  toastElem.addEventListener("click", async (e) => {
+    onClick?.(e);
+    await closeToast();
+  }, { once: true });
 
   if("message" in rest)
     toastElem.title = toastElem.ariaLabel = toastElem.textContent = rest.message;

+ 1 - 1
src/features/behavior.ts

@@ -223,7 +223,7 @@ export function disableDarkReader() {
 
   const metaElem = document.createElement("meta");
   metaElem.name = "darkreader-lock";
-  metaElem.classList.add("bytm-disable-darkreader");
+  metaElem.id = "bytm-disable-dark-reader";
   document.head.appendChild(metaElem);
 
   info("Disabled Dark Reader");

+ 32 - 5
src/utils/logging.ts

@@ -2,9 +2,9 @@ import { clamp } from "@sv443-network/userutils";
 import { scriptInfo } from "../constants.js";
 import { setGlobalProp } from "../interface.js";
 import { LogLevel } from "../types.js";
-import { showIconToast } from "src/components/toast.js";
+import { MarkdownDialog, showIconToast } from "../components/index.js";
 import { t } from "./translations.js";
-import { getFeature } from "src/config.js";
+import { getFeature } from "../config.js";
 
 let curLogLevel = LogLevel.Info;
 
@@ -55,16 +55,43 @@ export function warn(...args: unknown[]): void {
   console.warn(consPrefix, ...args);
 }
 
+let errorDialog: MarkdownDialog;
+
+function getErrorDialog(errName: string, args: unknown[]) {
+  if(errorDialog)
+    return errorDialog;
+
+  return errorDialog = new MarkdownDialog({
+    id: "generic-error",
+    height: 400,
+    width: 500,
+    small: true,
+    renderHeader() {
+      const header = document.createElement("h2");
+      header.classList.add("bytm-dialog-title");
+      header.role = "heading";
+      header.ariaLevel = "1";
+      header.tabIndex = 0;
+      header.textContent = header.ariaLabel = errName;
+      return header;
+    },
+    body: args.join(" "),
+  });
+}
+
 /** Logs all passed values to the console as an error, no matter the log level. */
 export function error(...args: unknown[]): void {
   console.error(consPrefix, ...args);
 
-  getFeature("showToastOnGenericError")
-    && showIconToast({
-      message: t("generic_error_toast", args.find(a => a instanceof Error)?.name ?? t("error")),
+  if(getFeature("showToastOnGenericError")) {
+    const errName = args.find(a => a instanceof Error)?.name ?? t("error");
+    showIconToast({
+      message: t("generic_error_toast", errName),
       icon: "icon-error",
       iconFill: "var(--bytm-error-col)",
+      onClick: () => getErrorDialog(errName, Array.isArray(args) ? args : []).open(),
     });
+  }
 }
 
 /** Logs all passed values to the console with a debug-specific prefix */