110 lines
3.5 KiB
TypeScript
110 lines
3.5 KiB
TypeScript
/**
|
|
* OS utility functions for platform detection and keyboard shortcuts
|
|
*/
|
|
import React from 'react';
|
|
|
|
/**
|
|
* Detects the current operating system platform
|
|
* @returns The platform name
|
|
*/
|
|
export const getPlatform = (): 'mac' | 'windows' | 'linux' | 'unknown' => {
|
|
const userAgent = navigator.userAgent.toLowerCase();
|
|
const platform = navigator.platform.toLowerCase();
|
|
|
|
if (platform.includes('mac') || userAgent.includes('mac')) {
|
|
return 'mac';
|
|
} else if (platform.includes('win') || userAgent.includes('win')) {
|
|
return 'windows';
|
|
} else if (platform.includes('linux') || userAgent.includes('linux')) {
|
|
return 'linux';
|
|
}
|
|
|
|
return 'unknown';
|
|
};
|
|
|
|
/**
|
|
* Checks if the appropriate modifier key is pressed based on the current platform
|
|
* On Mac: checks for metaKey (CMD)
|
|
* On Windows/Linux: checks for ctrlKey (CTRL)
|
|
* @param event - The keyboard or mouse event (both native and React events)
|
|
* @returns true if the platform-appropriate modifier key is pressed
|
|
*/
|
|
export const isModifierKeyPressed = (event: KeyboardEvent | MouseEvent | React.KeyboardEvent | React.MouseEvent): boolean => {
|
|
const platform = getPlatform();
|
|
|
|
if (platform === 'mac') {
|
|
return event.metaKey;
|
|
} else {
|
|
// Windows, Linux, or unknown - use Ctrl key
|
|
return event.ctrlKey;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Gets the display name of the modifier key for the current platform
|
|
* @returns The display name (e.g., "Cmd" for Mac, "Ctrl" for others)
|
|
*/
|
|
export const getModifierKeyDisplayName = (): string => {
|
|
const platform = getPlatform();
|
|
return platform === 'mac' ? 'Cmd' : 'Ctrl';
|
|
};
|
|
|
|
/**
|
|
* Resolves a keyboard shortcut string by replacing 'ctrl' with the appropriate modifier for the current platform
|
|
* @param shortcut - The shortcut string (e.g., "ctrl+z", "ctrl+shift+z")
|
|
* @returns The resolved shortcut with platform-specific modifiers
|
|
*/
|
|
export const resolveKeyboardShortcut = (shortcut: string): string => {
|
|
const platform = getPlatform();
|
|
if (platform === 'mac') {
|
|
// Replace 'ctrl' with 'cmd' on Mac
|
|
return shortcut.replace(/\bctrl\b/gi, 'cmd');
|
|
}
|
|
return shortcut;
|
|
};
|
|
|
|
/**
|
|
* Checks if a keyboard event matches a given shortcut string
|
|
* @param event - The keyboard event
|
|
* @param shortcut - The shortcut string (e.g., "ctrl+z", "ctrl+shift+z")
|
|
* @returns true if the event matches the shortcut
|
|
*/
|
|
export const matchesKeyboardShortcut = (event: KeyboardEvent | React.KeyboardEvent, shortcut: string): boolean => {
|
|
const normalizedShortcut = shortcut.toLowerCase();
|
|
const keys = normalizedShortcut.split('+');
|
|
|
|
// Extract the main key (last part)
|
|
const mainKey = keys[keys.length - 1];
|
|
|
|
// Handle special key mappings
|
|
let eventKey = event.key.toLowerCase();
|
|
if (eventKey === ' ') {
|
|
eventKey = 'space';
|
|
}
|
|
|
|
if (eventKey !== mainKey) {
|
|
return false;
|
|
}
|
|
|
|
// Check modifiers
|
|
const hasCtrl = keys.includes('ctrl');
|
|
const hasShift = keys.includes('shift');
|
|
const hasAlt = keys.includes('alt');
|
|
const hasCmd = keys.includes('cmd');
|
|
|
|
const platform = getPlatform();
|
|
|
|
// Handle platform-specific modifier checking
|
|
let expectedCtrlOrCmd = false;
|
|
if (platform === 'mac') {
|
|
expectedCtrlOrCmd = hasCmd || hasCtrl; // On Mac, both 'ctrl' and 'cmd' should map to metaKey
|
|
} else {
|
|
expectedCtrlOrCmd = hasCtrl; // On other platforms, only 'ctrl' maps to ctrlKey
|
|
}
|
|
|
|
const actualCtrlOrCmd = platform === 'mac' ? event.metaKey : event.ctrlKey;
|
|
|
|
return actualCtrlOrCmd === expectedCtrlOrCmd &&
|
|
event.shiftKey === hasShift &&
|
|
event.altKey === hasAlt;
|
|
}; |