/* * Vencord, a modification for Discord's desktop app * Copyright (c) 2022 Vendicated and contributors * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ import { Clipboard, Toasts } from "@webpack/common"; /** * Recursively merges defaults into an object and returns the same object * @param obj Object * @param defaults Defaults * @returns obj */ export function mergeDefaults(obj: T, defaults: T): T { for (const key in defaults) { const v = defaults[key]; if (typeof v === "object" && !Array.isArray(v)) { obj[key] ??= {} as any; mergeDefaults(obj[key], v); } else { obj[key] ??= v; } } return obj; } /** * Calls .join(" ") on the arguments * classes("one", "two") => "one two" */ export function classes(...classes: Array) { return classes.filter(Boolean).join(" "); } /** * Returns a promise that resolves after the specified amount of time */ export function sleep(ms: number): Promise { return new Promise(r => setTimeout(r, ms)); } export function copyWithToast(text: string, toastMessage = "Copied to clipboard!") { if (Clipboard.SUPPORTS_COPY) { Clipboard.copy(text); } else { toastMessage = "Your browser does not support copying to clipboard"; } Toasts.show({ message: toastMessage, id: Toasts.genId(), type: Toasts.Type.SUCCESS }); } /** * Check if obj is a true object: of type "object" and not null or array */ export function isObject(obj: unknown): obj is object { return typeof obj === "object" && obj !== null && !Array.isArray(obj); } /** * Returns null if value is not a URL, otherwise return URL object. * Avoids having to wrap url checks in a try/catch */ export function parseUrl(urlString: string): URL | null { try { return new URL(urlString); } catch { return null; } } /** * Checks whether an element is on screen */ export const checkIntersecting = (el: Element) => { const elementBox = el.getBoundingClientRect(); const documentHeight = Math.max(document.documentElement.clientHeight, window.innerHeight); return !(elementBox.bottom < 0 || elementBox.top - documentHeight >= 0); }; export function identity(value: T): T { return value; } // https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent#mobile_tablet_or_desktop // "In summary, we recommend looking for the string Mobi anywhere in the User Agent to detect a mobile device." export const isMobile = navigator.userAgent.includes("Mobi");