Make the welcome screen not include Alt in Ctrl+Alt+N on desktop

This commit is contained in:
Keavon Chambers
2025-11-17 15:26:23 -08:00
parent 85965c8b6a
commit 12453d2e61
13 changed files with 54 additions and 66 deletions
+1 -1
View File
@@ -61,7 +61,7 @@
}); });
</script> </script>
<MainWindow platform={$appWindow.platform} maximized={$appWindow.maximized} viewportHolePunch={$appWindow.viewportHolePunch} /> <MainWindow />
<style lang="scss" global> <style lang="scss" global>
// Disable the spinning loading indicator // Disable the spinning loading indicator
+3 -3
View File
@@ -14,7 +14,7 @@
} from "@graphite/messages"; } from "@graphite/messages";
import type { DataBuffer, LayerPanelEntry } from "@graphite/messages"; import type { DataBuffer, LayerPanelEntry } from "@graphite/messages";
import type { NodeGraphState } from "@graphite/state-providers/node-graph"; import type { NodeGraphState } from "@graphite/state-providers/node-graph";
import { platformIsMac } from "@graphite/utility-functions/platform"; import { operatingSystem } from "@graphite/utility-functions/platform";
import { extractPixelData } from "@graphite/utility-functions/rasterization"; import { extractPixelData } from "@graphite/utility-functions/rasterization";
import LayoutCol from "@graphite/components/layout/LayoutCol.svelte"; import LayoutCol from "@graphite/components/layout/LayoutCol.svelte";
@@ -177,7 +177,7 @@
} }
function handleExpandArrowClickWithModifiers(e: MouseEvent, id: bigint) { function handleExpandArrowClickWithModifiers(e: MouseEvent, id: bigint) {
const accel = platformIsMac() ? e.metaKey : e.ctrlKey; const accel = operatingSystem() === "Mac" ? e.metaKey : e.ctrlKey;
const collapseRecursive = e.altKey || accel; const collapseRecursive = e.altKey || accel;
editor.handle.toggleLayerExpansion(id, collapseRecursive); editor.handle.toggleLayerExpansion(id, collapseRecursive);
e.stopPropagation(); e.stopPropagation();
@@ -226,7 +226,7 @@
// Get the pressed state of the modifier keys // Get the pressed state of the modifier keys
const [ctrl, meta, shift, alt] = [e.ctrlKey, e.metaKey, e.shiftKey, e.altKey]; const [ctrl, meta, shift, alt] = [e.ctrlKey, e.metaKey, e.shiftKey, e.altKey];
// Get the state of the platform's accel key and its opposite platform's accel key // Get the state of the platform's accel key and its opposite platform's accel key
const [accel, oppositeAccel] = platformIsMac() ? [meta, ctrl] : [ctrl, meta]; const [accel, oppositeAccel] = operatingSystem() === "Mac" ? [meta, ctrl] : [ctrl, meta];
// Alt-clicking to make a clipping mask // Alt-clicking to make a clipping mask
if (layerToClipAltKeyPressed && layerToClipUponClick && layerToClipUponClick.entry.clippable) clipLayer(layerToClipUponClick); if (layerToClipAltKeyPressed && layerToClipUponClick && layerToClipUponClick.entry.clippable) clipLayer(layerToClipUponClick);
@@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import { createEventDispatcher } from "svelte"; import { createEventDispatcher } from "svelte";
import { platformIsMac } from "@graphite/utility-functions/platform"; import { operatingSystem } from "@graphite/utility-functions/platform";
import { preventEscapeClosingParentFloatingMenu } from "@graphite/components/layout/FloatingMenu.svelte"; import { preventEscapeClosingParentFloatingMenu } from "@graphite/components/layout/FloatingMenu.svelte";
import LayoutRow from "@graphite/components/layout/LayoutRow.svelte"; import LayoutRow from "@graphite/components/layout/LayoutRow.svelte";
@@ -31,7 +31,7 @@
let inputOrTextarea: HTMLInputElement | HTMLTextAreaElement | undefined; let inputOrTextarea: HTMLInputElement | HTMLTextAreaElement | undefined;
let id = String(Math.random()).substring(2); let id = String(Math.random()).substring(2);
let macKeyboardLayout = platformIsMac(); let macKeyboardLayout = operatingSystem() === "Mac";
$: dispatch("value", value); $: dispatch("value", value);
@@ -4,7 +4,7 @@
import { type KeyRaw, type LayoutKeysGroup, type Key, type MouseMotion } from "@graphite/messages"; import { type KeyRaw, type LayoutKeysGroup, type Key, type MouseMotion } from "@graphite/messages";
import type { FullscreenState } from "@graphite/state-providers/fullscreen"; import type { FullscreenState } from "@graphite/state-providers/fullscreen";
import type { IconName } from "@graphite/utility-functions/icons"; import type { IconName } from "@graphite/utility-functions/icons";
import { platformIsMac } from "@graphite/utility-functions/platform"; import { operatingSystem } from "@graphite/utility-functions/platform";
import LayoutRow from "@graphite/components/layout/LayoutRow.svelte"; import LayoutRow from "@graphite/components/layout/LayoutRow.svelte";
import IconLabel from "@graphite/components/widgets/labels/IconLabel.svelte"; import IconLabel from "@graphite/components/widgets/labels/IconLabel.svelte";
@@ -29,7 +29,7 @@
Enter: 2, Enter: 2,
Tab: 2, Tab: 2,
Space: 3, Space: 3,
...(platformIsMac() ? ICON_WIDTHS_MAC : {}), ...(operatingSystem() === "Mac" ? ICON_WIDTHS_MAC : {}),
}; };
const fullscreen = getContext<FullscreenState>("fullscreen"); const fullscreen = getContext<FullscreenState>("fullscreen");
@@ -65,7 +65,7 @@
const label = keyWithLabel.label; const label = keyWithLabel.label;
// Replace Alt and Accel keys with their Mac-specific equivalents // Replace Alt and Accel keys with their Mac-specific equivalents
if (platformIsMac()) { if (operatingSystem() === "Mac") {
if (key === "Alt") key = "Option"; if (key === "Alt") key = "Option";
if (key === "Accel") key = "Command"; if (key === "Accel") key = "Command";
} }
@@ -1,18 +1,18 @@
<script lang="ts"> <script lang="ts">
import type { AppWindowPlatform } from "@graphite/messages"; import { getContext } from "svelte";
import type { AppWindowState } from "@graphite/state-providers/app-window";
import LayoutCol from "@graphite/components/layout/LayoutCol.svelte"; import LayoutCol from "@graphite/components/layout/LayoutCol.svelte";
import StatusBar from "@graphite/components/window/status-bar/StatusBar.svelte"; import StatusBar from "@graphite/components/window/status-bar/StatusBar.svelte";
import TitleBar from "@graphite/components/window/title-bar/TitleBar.svelte"; import TitleBar from "@graphite/components/window/title-bar/TitleBar.svelte";
import Workspace from "@graphite/components/window/workspace/Workspace.svelte"; import Workspace from "@graphite/components/window/workspace/Workspace.svelte";
export let platform: AppWindowPlatform; const appWindow = getContext<AppWindowState>("appWindow");
export let maximized: boolean;
export let viewportHolePunch: boolean;
</script> </script>
<LayoutCol class="main-window" classes={{ "viewport-hole-punch": viewportHolePunch }}> <LayoutCol class="main-window" classes={{ "viewport-hole-punch": $appWindow.viewportHolePunch }}>
<TitleBar {platform} {maximized} /> <TitleBar />
<Workspace /> <Workspace />
@@ -3,7 +3,7 @@
import type { Editor } from "@graphite/editor"; import type { Editor } from "@graphite/editor";
import { type HintData, type HintInfo, type LayoutKeysGroup, UpdateInputHints } from "@graphite/messages"; import { type HintData, type HintInfo, type LayoutKeysGroup, UpdateInputHints } from "@graphite/messages";
import { platformIsMac } from "@graphite/utility-functions/platform"; import { operatingSystem } from "@graphite/utility-functions/platform";
import LayoutRow from "@graphite/components/layout/LayoutRow.svelte"; import LayoutRow from "@graphite/components/layout/LayoutRow.svelte";
import Separator from "@graphite/components/widgets/labels/Separator.svelte"; import Separator from "@graphite/components/widgets/labels/Separator.svelte";
@@ -14,8 +14,7 @@
let hintData: HintData = []; let hintData: HintData = [];
function inputKeysForPlatform(hint: HintInfo): LayoutKeysGroup[] { function inputKeysForPlatform(hint: HintInfo): LayoutKeysGroup[] {
if (platformIsMac() && hint.keyGroupsMac) return hint.keyGroupsMac; return operatingSystem() === "Mac" && hint.keyGroupsMac ? hint.keyGroupsMac : hint.keyGroups;
return hint.keyGroups;
} }
onMount(() => { onMount(() => {
@@ -2,8 +2,9 @@
import { getContext, onMount } from "svelte"; import { getContext, onMount } from "svelte";
import type { Editor } from "@graphite/editor"; import type { Editor } from "@graphite/editor";
import { type KeyRaw, type LayoutKeysGroup, type MenuBarEntry, type MenuListEntry, type AppWindowPlatform, UpdateMenuBarLayout } from "@graphite/messages"; import { type KeyRaw, type LayoutKeysGroup, type MenuBarEntry, type MenuListEntry, UpdateMenuBarLayout } from "@graphite/messages";
import { platformIsMac } from "@graphite/utility-functions/platform"; import type { AppWindowState } from "@graphite/state-providers/app-window";
import { operatingSystem } from "@graphite/utility-functions/platform";
import LayoutRow from "@graphite/components/layout/LayoutRow.svelte"; import LayoutRow from "@graphite/components/layout/LayoutRow.svelte";
import TextButton from "@graphite/components/widgets/buttons/TextButton.svelte"; import TextButton from "@graphite/components/widgets/buttons/TextButton.svelte";
@@ -11,13 +12,11 @@
import WindowButtonsWeb from "@graphite/components/window/title-bar/WindowButtonsWeb.svelte"; import WindowButtonsWeb from "@graphite/components/window/title-bar/WindowButtonsWeb.svelte";
import WindowButtonsWindows from "@graphite/components/window/title-bar/WindowButtonsWindows.svelte"; import WindowButtonsWindows from "@graphite/components/window/title-bar/WindowButtonsWindows.svelte";
export let platform: AppWindowPlatform; const appWindow = getContext<AppWindowState>("appWindow");
export let maximized: boolean;
const editor = getContext<Editor>("editor"); const editor = getContext<Editor>("editor");
// TODO: Apparently, Safari does not support the Keyboard.lock() API but does relax its authority over certain keyboard shortcuts in fullscreen mode, which we should take advantage of // TODO: Apparently, Safari does not support the Keyboard.lock() API but does relax its authority over certain keyboard shortcuts in fullscreen mode, which we should take advantage of
const ACCEL_KEY = platformIsMac() ? "Command" : "Control"; const ACCEL_KEY = operatingSystem() === "Mac" ? "Command" : "Control";
const LOCK_REQUIRING_SHORTCUTS: KeyRaw[][] = [ const LOCK_REQUIRING_SHORTCUTS: KeyRaw[][] = [
[ACCEL_KEY, "KeyW"], [ACCEL_KEY, "KeyW"],
[ACCEL_KEY, "KeyN"], [ACCEL_KEY, "KeyN"],
@@ -61,7 +60,7 @@
<LayoutRow class="title-bar"> <LayoutRow class="title-bar">
<!-- Menu bar --> <!-- Menu bar -->
<LayoutRow> <LayoutRow>
{#if platform !== "Mac"} {#if $appWindow.platform !== "Mac"}
{#each entries as entry} {#each entries as entry}
<TextButton label={entry.label} icon={entry.icon} menuListChildren={entry.children} action={entry.action} flush={true} /> <TextButton label={entry.label} icon={entry.icon} menuListChildren={entry.children} action={entry.action} flush={true} />
{/each} {/each}
@@ -71,12 +70,12 @@
<LayoutRow class="spacer" on:mousedown={() => editor.handle.appWindowDrag()} on:dblclick={() => editor.handle.appWindowMaximize()} /> <LayoutRow class="spacer" on:mousedown={() => editor.handle.appWindowDrag()} on:dblclick={() => editor.handle.appWindowMaximize()} />
<!-- Window buttons --> <!-- Window buttons -->
<LayoutRow> <LayoutRow>
{#if platform === "Web"} {#if $appWindow.platform === "Web"}
<WindowButtonsWeb /> <WindowButtonsWeb />
{:else if platform === "Windows"} {:else if $appWindow.platform === "Windows"}
<WindowButtonsWindows {maximized} /> <WindowButtonsWindows />
{:else if platform === "Linux"} {:else if $appWindow.platform === "Linux"}
<WindowButtonsLinux {maximized} /> <WindowButtonsLinux />
{/if} {/if}
</LayoutRow> </LayoutRow>
</LayoutRow> </LayoutRow>
@@ -2,20 +2,20 @@
import { getContext } from "svelte"; import { getContext } from "svelte";
import type { Editor } from "@graphite/editor"; import type { Editor } from "@graphite/editor";
import type { AppWindowState } from "@graphite/state-providers/app-window";
import LayoutRow from "@graphite/components/layout/LayoutRow.svelte"; import LayoutRow from "@graphite/components/layout/LayoutRow.svelte";
import IconLabel from "@graphite/components/widgets/labels/IconLabel.svelte"; import IconLabel from "@graphite/components/widgets/labels/IconLabel.svelte";
export let maximized; const appWindow = getContext<AppWindowState>("appWindow");
const editor = getContext<Editor>("editor"); const editor = getContext<Editor>("editor");
</script> </script>
<LayoutRow class="window-button linux" tooltip="Minimize" on:click={() => editor.handle.appWindowMinimize()}> <LayoutRow class="window-button linux" tooltip="Minimize" on:click={() => editor.handle.appWindowMinimize()}>
<IconLabel icon="WindowButtonWinMinimize" /> <IconLabel icon="WindowButtonWinMinimize" />
</LayoutRow> </LayoutRow>
<LayoutRow class="window-button linux" tooltip={maximized ? "Unmaximize" : "Maximize"} on:click={() => editor.handle.appWindowMaximize()}> <LayoutRow class="window-button linux" tooltip={$appWindow.maximized ? "Unmaximize" : "Maximize"} on:click={() => editor.handle.appWindowMaximize()}>
<IconLabel icon={maximized ? "WindowButtonWinRestoreDown" : "WindowButtonWinMaximize"} /> <IconLabel icon={$appWindow.maximized ? "WindowButtonWinRestoreDown" : "WindowButtonWinMaximize"} />
</LayoutRow> </LayoutRow>
<LayoutRow class="window-button linux" tooltip="Close" on:click={() => editor.handle.appWindowClose()}> <LayoutRow class="window-button linux" tooltip="Close" on:click={() => editor.handle.appWindowClose()}>
<IconLabel icon="WindowButtonWinClose" /> <IconLabel icon="WindowButtonWinClose" />
@@ -2,20 +2,20 @@
import { getContext } from "svelte"; import { getContext } from "svelte";
import type { Editor } from "@graphite/editor"; import type { Editor } from "@graphite/editor";
import type { AppWindowState } from "@graphite/state-providers/app-window";
import LayoutRow from "@graphite/components/layout/LayoutRow.svelte"; import LayoutRow from "@graphite/components/layout/LayoutRow.svelte";
import IconLabel from "@graphite/components/widgets/labels/IconLabel.svelte"; import IconLabel from "@graphite/components/widgets/labels/IconLabel.svelte";
export let maximized; const appWindow = getContext<AppWindowState>("appWindow");
const editor = getContext<Editor>("editor"); const editor = getContext<Editor>("editor");
</script> </script>
<LayoutRow class="window-button windows" tooltip="Minimize" on:click={() => editor.handle.appWindowMinimize()}> <LayoutRow class="window-button windows" tooltip="Minimize" on:click={() => editor.handle.appWindowMinimize()}>
<IconLabel icon="WindowButtonWinMinimize" /> <IconLabel icon="WindowButtonWinMinimize" />
</LayoutRow> </LayoutRow>
<LayoutRow class="window-button windows" tooltip={maximized ? "Restore Down" : "Maximize"} on:click={() => editor.handle.appWindowMaximize()}> <LayoutRow class="window-button windows" tooltip={$appWindow.maximized ? "Restore Down" : "Maximize"} on:click={() => editor.handle.appWindowMaximize()}>
<IconLabel icon={maximized ? "WindowButtonWinRestoreDown" : "WindowButtonWinMaximize"} /> <IconLabel icon={$appWindow.maximized ? "WindowButtonWinRestoreDown" : "WindowButtonWinMaximize"} />
</LayoutRow> </LayoutRow>
<LayoutRow class="window-button windows" tooltip="Close" on:click={() => editor.handle.appWindowClose()}> <LayoutRow class="window-button windows" tooltip="Close" on:click={() => editor.handle.appWindowClose()}>
<IconLabel icon="WindowButtonWinClose" /> <IconLabel icon="WindowButtonWinClose" />
@@ -18,7 +18,8 @@
import type { Editor } from "@graphite/editor"; import type { Editor } from "@graphite/editor";
import { type LayoutKeysGroup, type Key } from "@graphite/messages"; import { type LayoutKeysGroup, type Key } from "@graphite/messages";
import { platformIsMac, isEventSupported } from "@graphite/utility-functions/platform"; import type { AppWindowState } from "@graphite/state-providers/app-window";
import { operatingSystem, isEventSupported } from "@graphite/utility-functions/platform";
import { extractPixelData } from "@graphite/utility-functions/rasterization"; import { extractPixelData } from "@graphite/utility-functions/rasterization";
import LayoutCol from "@graphite/components/layout/LayoutCol.svelte"; import LayoutCol from "@graphite/components/layout/LayoutCol.svelte";
@@ -32,6 +33,7 @@
const BUTTON_LEFT = 0; const BUTTON_LEFT = 0;
const BUTTON_MIDDLE = 1; const BUTTON_MIDDLE = 1;
const appWindow = getContext<AppWindowState>("appWindow");
const editor = getContext<Editor>("editor"); const editor = getContext<Editor>("editor");
export let tabMinWidths = false; export let tabMinWidths = false;
@@ -52,14 +54,18 @@
let tabElements: (LayoutRow | undefined)[] = []; let tabElements: (LayoutRow | undefined)[] = [];
function platformModifiers(reservedKey: boolean): LayoutKeysGroup { function platformModifiedAccelKey(browserReservedKey: boolean): LayoutKeysGroup {
// TODO: Remove this by properly feeding these keys from a layout provided by the backend // TODO: Remove this by properly feeding these keys from a layout provided by the backend
const ALT: Key = { key: "Alt", label: "Alt" }; const ALT: Key = { key: "Alt", label: "Alt" };
const COMMAND: Key = { key: "Command", label: "Command" }; const COMMAND: Key = { key: "Command", label: "Command" };
const CONTROL: Key = { key: "Control", label: "Ctrl" }; const CONTROL: Key = { key: "Control", label: "Ctrl" };
if (platformIsMac()) return reservedKey ? [ALT, COMMAND] : [COMMAND]; // Only consider the browser reserved key on web platforms
const reservedKey = $appWindow.platform === "Web" ? browserReservedKey : false;
// Return either Command (Mac) or Control (Windows/Linux), with Alt added if the browser reserves the shortcut
if (operatingSystem() === "Mac") return reservedKey ? [ALT, COMMAND] : [COMMAND];
return reservedKey ? [CONTROL, ALT] : [CONTROL]; return reservedKey ? [CONTROL, ALT] : [CONTROL];
} }
@@ -179,7 +185,7 @@
<TextButton label="New Document" icon="File" flush={true} action={() => editor.handle.newDocumentDialog()} /> <TextButton label="New Document" icon="File" flush={true} action={() => editor.handle.newDocumentDialog()} />
</td> </td>
<td> <td>
<UserInputLabel keysWithLabelsGroups={[[...platformModifiers(true), { key: "KeyN", label: "N" }]]} /> <UserInputLabel keysWithLabelsGroups={[[...platformModifiedAccelKey(true), { key: "KeyN", label: "N" }]]} />
</td> </td>
</tr> </tr>
<tr> <tr>
@@ -187,7 +193,7 @@
<TextButton label="Open Document" icon="Folder" flush={true} action={() => editor.handle.openDocument()} /> <TextButton label="Open Document" icon="Folder" flush={true} action={() => editor.handle.openDocument()} />
</td> </td>
<td> <td>
<UserInputLabel keysWithLabelsGroups={[[...platformModifiers(false), { key: "KeyO", label: "O" }]]} /> <UserInputLabel keysWithLabelsGroups={[[...platformModifiedAccelKey(false), { key: "KeyO", label: "O" }]]} />
</td> </td>
</tr> </tr>
<tr> <tr>
+2 -2
View File
@@ -7,7 +7,7 @@ import { type DocumentState } from "@graphite/state-providers/document";
import { type FullscreenState } from "@graphite/state-providers/fullscreen"; import { type FullscreenState } from "@graphite/state-providers/fullscreen";
import { type PortfolioState } from "@graphite/state-providers/portfolio"; import { type PortfolioState } from "@graphite/state-providers/portfolio";
import { makeKeyboardModifiersBitfield, textInputCleanup, getLocalizedScanCode } from "@graphite/utility-functions/keyboard-entry"; import { makeKeyboardModifiersBitfield, textInputCleanup, getLocalizedScanCode } from "@graphite/utility-functions/keyboard-entry";
import { platformIsMac } from "@graphite/utility-functions/platform"; import { operatingSystem } from "@graphite/utility-functions/platform";
import { extractPixelData } from "@graphite/utility-functions/rasterization"; import { extractPixelData } from "@graphite/utility-functions/rasterization";
import { stripIndents } from "@graphite/utility-functions/strip-indents"; import { stripIndents } from "@graphite/utility-functions/strip-indents";
import { updateBoundsOfViewports } from "@graphite/utility-functions/viewports"; import { updateBoundsOfViewports } from "@graphite/utility-functions/viewports";
@@ -82,7 +82,7 @@ export function createInputManager(editor: Editor, dialog: DialogState, portfoli
const key = await getLocalizedScanCode(e); const key = await getLocalizedScanCode(e);
// TODO: Switch to a system where everything is sent to the backend, then the input preprocessor makes decisions and kicks some inputs back to the frontend // TODO: Switch to a system where everything is sent to the backend, then the input preprocessor makes decisions and kicks some inputs back to the frontend
const accelKey = platformIsMac() ? e.metaKey : e.ctrlKey; const accelKey = operatingSystem() === "Mac" ? e.metaKey : e.ctrlKey;
// Don't redirect user input from text entry into HTML elements // Don't redirect user input from text entry into HTML elements
if (targetIsTextField(e.target || undefined) && key !== "Escape" && !(accelKey && ["Enter", "NumpadEnter"].includes(key))) return false; if (targetIsTextField(e.target || undefined) && key !== "Escape" && !(accelKey && ["Enter", "NumpadEnter"].includes(key))) return false;
+1 -1
View File
@@ -40,7 +40,7 @@ export function githubUrl(panicDetails: string): string {
Provide any further information or context that you think would be helpful in fixing the issue. Screenshots or video can be linked or attached to this issue. Provide any further information or context that you think would be helpful in fixing the issue. Screenshots or video can be linked or attached to this issue.
**Browser and OS** **Browser and OS**
${browserVersion()}, ${operatingSystem(true).replace("Unknown", "YOUR OPERATING SYSTEM")} ${browserVersion()}, ${operatingSystem().replace("Unknown", "YOUR OPERATING SYSTEM")}
**Stack Trace** **Stack Trace**
Copied from the crash dialog in the Graphite editor: Copied from the crash dialog in the Graphite editor:
+4 -20
View File
@@ -23,36 +23,20 @@ export function browserVersion(): string {
return `${match[0]} ${match[1]}`; return `${match[0]} ${match[1]}`;
} }
export function operatingSystem(detailed = false): string { export type OperatingSystem = "Windows" | "Mac" | "Linux" | "Unknown";
const osTableDetailed: Record<string, string> = {
"Windows NT 10": "Windows 10 or 11", export function operatingSystem(): OperatingSystem {
"Windows NT 6.3": "Windows 8.1", const osTable: Record<string, OperatingSystem> = {
"Windows NT 6.2": "Windows 8",
"Windows NT 6.1": "Windows 7",
"Windows NT 6.0": "Windows Vista",
"Windows NT 5.1": "Windows XP",
"Windows NT 5.0": "Windows 2000",
Mac: "Mac",
X11: "Unix",
Linux: "Linux",
Unknown: "Unknown",
};
const osTableSimple: Record<string, string> = {
Windows: "Windows", Windows: "Windows",
Mac: "Mac", Mac: "Mac",
Linux: "Linux", Linux: "Linux",
Unknown: "Unknown", Unknown: "Unknown",
}; };
const osTable = detailed ? osTableDetailed : osTableSimple;
const userAgentOS = Object.keys(osTable).find((key) => window.navigator.userAgent.includes(key)); const userAgentOS = Object.keys(osTable).find((key) => window.navigator.userAgent.includes(key));
return osTable[userAgentOS || "Unknown"]; return osTable[userAgentOS || "Unknown"];
} }
export function platformIsMac(): boolean {
return operatingSystem() === "Mac";
}
export function isEventSupported(eventName: string) { export function isEventSupported(eventName: string) {
const onEventName = `on${eventName}`; const onEventName = `on${eventName}`;