Ver código fonte

feat: show toast on error

Sv443 8 meses atrás
pai
commit
962af4cbab
6 arquivos alterados com 39 adições e 13 exclusões
  1. 7 1
      src/components/toast.css
  2. 11 9
      src/components/toast.ts
  3. 4 2
      src/config.ts
  4. 2 1
      src/dialogs/dialogs.css
  5. 2 0
      src/types.ts
  6. 13 0
      src/utils/logging.ts

+ 7 - 1
src/components/toast.css

@@ -66,7 +66,13 @@
   gap: 10px;
 }
 
-.bytm-toast-icon.img {
+.bytm-toast-icon.img,
+.bytm-toast-icon svg
+{
   width: 24px;
   height: 24px;
 }
+
+.bytm-toast-icon path {
+  fill: var(--toast-icon-fill, #fff);
+}

+ 11 - 9
src/components/toast.ts

@@ -66,7 +66,7 @@ export async function showIconToast({
 
   toastWrapper.appendChild(toastMessage);
 
-  await showToast({
+  return await showToast({
     duration,
     position,
     element: toastWrapper,
@@ -75,11 +75,11 @@ export async function showIconToast({
 }
 
 /** Shows a toast message in the top right corner of the screen by default and uses the default timeout from the config option `toastDuration` */
-export async function showToast(message: string): Promise<void>;
+export async function showToast(message: string): Promise<HTMLDivElement | void>;
 /** Shows a toast message or element in the top right corner of the screen by default and uses the default timeout from the config option `toastDuration` */
-export async function showToast(props: ToastProps): Promise<void>;
+export async function showToast(props: ToastProps): Promise<HTMLDivElement | void>;
 /** Shows a toast message or element in the specified position (top right corner by default) and uses the default timeout from the config option `toastDuration` */
-export async function showToast(arg: string | ToastProps): Promise<void> {
+export async function showToast(arg: string | ToastProps): Promise<HTMLDivElement | void> {
   const props: ToastProps = typeof arg === "string"
     ? { message: arg, duration: getFeature("toastDuration") }
     : arg;
@@ -110,15 +110,17 @@ export async function showToast(arg: string | ToastProps): Promise<void> {
     toastElem.appendChild(rest.element);
     toastElem.title = toastElem.ariaLabel = rest.title;
   }
-  
+
   document.body.appendChild(toastElem);
 
-  await pauseFor(100);
+  pauseFor(100).then(async () => {
+    toastElem.classList.add("visible", `pos-${position.toLowerCase()}`);
 
-  toastElem.classList.add("visible", `pos-${position.toLowerCase()}`);
+    if(duration < Number.POSITIVE_INFINITY)
+      timeout = setTimeout(async () => await closeToast(), duration * 1000);
+  });
 
-  if(duration < Number.POSITIVE_INFINITY)
-    timeout = setTimeout(async () => await closeToast(), duration * 1000);
+  return toastElem;
 }
 
 /** Closes the currently open toast */

+ 4 - 2
src/config.ts

@@ -8,7 +8,7 @@ import { closeCfgMenu } from "./menu/menu_old.js";
 import type { FeatureConfig, FeatureKey } from "./types.js";
 
 /** If this number is incremented, the features object data will be migrated to the new format */
-export const formatVersion = 6;
+export const formatVersion = 7;
 
 export const defaultData = (Object.keys(featInfo) as (keyof typeof featInfo)[])
   // @ts-ignore
@@ -95,7 +95,9 @@ export const migrations: DataMigrationsDict = {
   // TODO(v2.2): set autoLikeChannels to true on migration once feature is fully implemented
 
   // 6 -> 7 (v2.2)
-  // 7: (oldData: FeatureConfig) =>
+  7: (oldData: FeatureConfig) => useDefaultConfig(oldData, [
+    "showToastOnGenericError",
+  ]),
 } as const satisfies DataMigrationsDict;
 
 /** Uses the default config as the base, then overwrites all values with the passed {@linkcode baseData}, then sets all passed {@linkcode resetKeys} to their default values */

+ 2 - 1
src/dialogs/dialogs.css

@@ -3,7 +3,8 @@
   --bytm-locale-color: #5ea2ec;
   --bytm-advanced-mode-color: #ceb663;
   --bytm-experimental-col: #cc83e5;
-  --bytm-warning-col: #e07664;
+  --bytm-warning-col: #e5a63b;
+  --bytm-error-col: #fa5b5b;
   --bytm-reload-col: #77e064;
 }
 

+ 2 - 0
src/types.ts

@@ -580,6 +580,8 @@ export interface FeatureConfig {
   initTimeout: number;
   /** Amount of seconds to show BYTM's toasts for */
   toastDuration: number;
+  /** Whether to show a toast on generic errors */
+  showToastOnGenericError: boolean;
   /** Button that resets the config to the default state */
   resetConfig: undefined;
   /** Whether to show advanced settings in the config menu */

+ 13 - 0
src/utils/logging.ts

@@ -2,6 +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 { t } from "./translations.js";
+import { getFeature } from "src/config.js";
 
 let curLogLevel = LogLevel.Info;
 
@@ -55,8 +58,18 @@ export function warn(...args: unknown[]): void {
 /** 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({
+      icon: "icon-error",
+      message: t("generic_error_toast", args.find(e => e instanceof Error)?.name ?? t("error")),
+    }).then((el) => {
+      el?.style.setProperty("--toast-icon-fill", "var(--bytm-error-col)");
+    });
 }
 
+document.addEventListener("DOMContentLoaded", () => error("Ayo chungus", new TypeError("chungus moment encountered")));
+
 /** Logs all passed values to the console with a debug-specific prefix */
 export function dbg(...args: unknown[]): void {
   console.log(consPrefixDbg, ...args);