This commit is contained in:
zsviczian
2023-12-03 20:00:47 +01:00
parent 87b6335905
commit 52cc5d3aa7
23 changed files with 587 additions and 212 deletions

View File

@@ -1,19 +1,88 @@
import { DEVICE, isDarwin } from "src/constants/constants";
import { DEVICE } from "src/constants/constants";
import { ExcalidrawSettings } from "src/settings";
export type ModifierKeys = {shiftKey:boolean, ctrlKey: boolean, metaKey: boolean, altKey: boolean};
export type KeyEvent = PointerEvent | MouseEvent | KeyboardEvent | React.DragEvent | React.PointerEvent | React.MouseEvent | ModifierKeys;
export type PaneTarget = "active-pane"|"new-pane"|"popout-window"|"new-tab"|"md-properties";
export type ExternalDragAction = "insert-link"|"image-url"|"image-import"|"embeddable";
export type LocalFileDragAction = "insert-link"|"image-uri"|"image-import";
export type WebBrowserDragAction = "link"|"image-url"|"image-import"|"embeddable";
export type LocalFileDragAction = "link"|"image-url"|"image-import"|"embeddable";
export type InternalDragAction = "link"|"image"|"image-fullsize"|"embeddable";
export type ModifierSetType = "WebBrowserDragAction" | "LocalFileDragAction" | "InternalDragAction" | "LinkClickAction";
type ModifierKey = {
shift: boolean;
ctrl_cmd: boolean;
alt_opt: boolean;
meta_ctrl: boolean;
result: WebBrowserDragAction | LocalFileDragAction | InternalDragAction | PaneTarget;
};
export type ModifierKeySet = {
defaultAction: WebBrowserDragAction | LocalFileDragAction | InternalDragAction | PaneTarget;
rules: ModifierKey[];
};
export type ModifierKeyTooltipMessages = Partial<{
[modifierSetType in ModifierSetType]: Partial<{
[action in WebBrowserDragAction | LocalFileDragAction | InternalDragAction | PaneTarget]: string;
}>;
}>;
export const modifierKeyTooltipMessages = ():ModifierKeyTooltipMessages => {
return {
WebBrowserDragAction: {
"image-import": "Import Image to Vault",
"image-url": `Insert Image or YouTube Thumbnail with URL`,
"link": "Insert Link",
"embeddable": "Insert Interactive-Frame",
// Add more messages for WebBrowserDragAction as needed
},
LocalFileDragAction: {
"image-import": "Insert Image: import external or reuse existing if path in Vault",
"image-url": `Insert Image: with local URI or internal-link if from Vault`,
"link": "Insert Link: local URI or internal-link if from Vault",
"embeddable": "Insert Interactive-Frame: local URI or internal-link if from Vault",
},
InternalDragAction: {
"image": "Insert Image",
"image-fullsize": "Insert Image @100%",
"link": `Insert Link`,
"embeddable": "Insert Interactive-Frame",
},
LinkClickAction: {
"active-pane": "Open in current active window",
"new-pane": "Open in a new adjacent window",
"popout-window": "Open in a popout window",
"new-tab": "Open in a new tab",
"md-properties": "Show the Markdown image-properties dialog (only relevant if you have embedded a markdown document as an image)",
},
}
};
const processModifiers = (ev: KeyEvent, modifierType: ModifierSetType): WebBrowserDragAction | LocalFileDragAction | InternalDragAction | PaneTarget => {
const settings:ExcalidrawSettings = window.ExcalidrawAutomate.plugin.settings;
const keySet = ((DEVICE.isMacOS || DEVICE.isIOS) ? settings.modifierKeyConfig.Mac : settings.modifierKeyConfig.Win)[modifierType];
for (const rule of keySet.rules) {
const { shift, ctrl_cmd, alt_opt, meta_ctrl, result } = rule;
if (
(isSHIFT(ev) === shift) &&
(isWinCTRLorMacCMD(ev) === ctrl_cmd) &&
(isWinALTorMacOPT(ev) === alt_opt) &&
(isWinMETAorMacCTRL(ev) === meta_ctrl)
) {
return result;
}
}
return keySet.defaultAction;
}
export const labelCTRL = () => DEVICE.isIOS || DEVICE.isMacOS ? "CMD" : "CTRL";
export const labelALT = () => DEVICE.isIOS || DEVICE.isMacOS ? "OPT" : "ALT";
export const labelMETA = () => DEVICE.isIOS || DEVICE.isMacOS ? "CTRL" : (DEVICE.isWindows ? "WIN" : "META");
export const labelSHIFT = () => "SHIFT";
export const isCTRL = (e:KeyEvent) => DEVICE.isIOS || DEVICE.isMacOS ? e.metaKey : e.ctrlKey;
export const isALT = (e:KeyEvent) => e.altKey;
export const isMETA = (e:KeyEvent) => DEVICE.isIOS || DEVICE.isMacOS ? e.ctrlKey : e.metaKey;
export const isWinCTRLorMacCMD = (e:KeyEvent) => DEVICE.isIOS || DEVICE.isMacOS ? e.metaKey : e.ctrlKey;
export const isWinALTorMacOPT = (e:KeyEvent) => e.altKey;
export const isWinMETAorMacCTRL = (e:KeyEvent) => DEVICE.isIOS || DEVICE.isMacOS ? e.ctrlKey : e.metaKey;
export const isSHIFT = (e:KeyEvent) => e.shiftKey;
export const setCTRL = (e:ModifierKeys, value: boolean): ModifierKeys => {
@@ -39,50 +108,38 @@ export const setSHIFT = (e:ModifierKeys, value: boolean): ModifierKeys => {
return e;
}
export const mdPropModifier = (ev: KeyEvent): boolean => !isSHIFT(ev) && isCTRL(ev) && !isALT(ev) && isMETA(ev);
export const scaleToFullsizeModifier = (ev: KeyEvent) =>
( isSHIFT(ev) && !isCTRL(ev) && !isALT(ev) && isMETA(ev)) ||
(!isSHIFT(ev) && isCTRL(ev) && isALT(ev) && !isMETA(ev));
export const linkClickModifierType = (ev: KeyEvent):PaneTarget => {
if(isCTRL(ev) && !isALT(ev) && isSHIFT(ev) && !isMETA(ev)) return "active-pane";
if(isCTRL(ev) && !isALT(ev) && !isSHIFT(ev) && !isMETA(ev)) return "new-tab";
if(isCTRL(ev) && isALT(ev) && !isSHIFT(ev) && !isMETA(ev)) return "new-pane";
if(DEVICE.isDesktop && isCTRL(ev) && isALT(ev) && isSHIFT(ev) && !isMETA(ev) ) return "popout-window";
if(isCTRL(ev) && isALT(ev) && isSHIFT(ev) && !isMETA(ev)) return "new-tab";
if(mdPropModifier(ev)) return "md-properties";
return "active-pane";
export const mdPropModifier = (ev: KeyEvent): boolean => !isSHIFT(ev) && isWinCTRLorMacCMD(ev) && !isWinALTorMacOPT(ev) && isWinMETAorMacCTRL(ev);
export const scaleToFullsizeModifier = (ev: KeyEvent) => {
const settings:ExcalidrawSettings = window.ExcalidrawAutomate.plugin.settings;
const keySet = ((DEVICE.isMacOS || DEVICE.isIOS) ? settings.modifierKeyConfig.Mac : settings.modifierKeyConfig.Win )["InternalDragAction"];
const rule = keySet.rules.find(r => r.result === "image-fullsize");
if(!rule) return false;
const { shift, ctrl_cmd, alt_opt, meta_ctrl, result } = rule;
return (
(isSHIFT(ev) === shift) &&
(isWinCTRLorMacCMD(ev) === ctrl_cmd) &&
(isWinALTorMacOPT(ev) === alt_opt) &&
(isWinMETAorMacCTRL(ev) === meta_ctrl)
);
}
export const externalDragModifierType = (ev: KeyEvent):ExternalDragAction => {
if(DEVICE.isWindows && isSHIFT(ev) && isCTRL(ev) && !isALT(ev) && !isMETA(ev)) return "embeddable";
if(DEVICE.isMacOS && !isSHIFT(ev) && !isCTRL(ev) && isALT(ev) && !isMETA(ev)) return "embeddable";
if(DEVICE.isWindows && !isSHIFT(ev) && isCTRL(ev) && !isALT(ev) && !isMETA(ev)) return "insert-link";
if(DEVICE.isMacOS && isSHIFT(ev) && !isCTRL(ev) && isALT(ev) && !isMETA(ev)) return "insert-link";
if( isSHIFT(ev) && !isCTRL(ev) && !isALT(ev) && !isMETA(ev)) return "image-import";
if(DEVICE.isWindows && !isSHIFT(ev) && !isCTRL(ev) && isALT(ev) && !isMETA(ev)) return "image-import";
return "image-url";
export const linkClickModifierType = (ev: KeyEvent):PaneTarget => {
const action = processModifiers(ev, "LinkClickAction") as PaneTarget;
if(!DEVICE.isDesktop && action === "popout-window") return "active-pane";
return action;
}
export const webbrowserDragModifierType = (ev: KeyEvent):WebBrowserDragAction => {
return processModifiers(ev, "WebBrowserDragAction") as WebBrowserDragAction;
}
export const localFileDragModifierType = (ev: KeyEvent):LocalFileDragAction => {
if(DEVICE.isWindows && isSHIFT(ev) && isCTRL(ev) && !isALT(ev) && !isMETA(ev)) return "image-uri";
if(DEVICE.isMacOS && !isSHIFT(ev) && !isCTRL(ev) && isALT(ev) && !isMETA(ev)) return "image-uri";
if(DEVICE.isWindows && !isSHIFT(ev) && isCTRL(ev) && !isALT(ev) && !isMETA(ev)) return "insert-link";
if(DEVICE.isMacOS && isSHIFT(ev) && !isCTRL(ev) && isALT(ev) && !isMETA(ev)) return "insert-link";
if( isSHIFT(ev) && !isCTRL(ev) && !isALT(ev) && !isMETA(ev)) return "image-import";
if(DEVICE.isWindows && !isSHIFT(ev) && !isCTRL(ev) && isALT(ev) && !isMETA(ev)) return "image-import";
return "image-import";
return processModifiers(ev, "LocalFileDragAction") as LocalFileDragAction;
}
//https://github.com/zsviczian/obsidian-excalidraw-plugin/issues/468
export const internalDragModifierType = (ev: KeyEvent):InternalDragAction => {
if( !(DEVICE.isIOS || DEVICE.isMacOS) && isSHIFT(ev) && isCTRL(ev) && !isALT(ev) && !isMETA(ev)) return "embeddable";
if( (DEVICE.isIOS || DEVICE.isMacOS) && !isSHIFT(ev) && !isCTRL(ev) && !isALT(ev) && isMETA(ev)) return "embeddable";
if( isSHIFT(ev) && !isCTRL(ev) && !isALT(ev) && !isMETA(ev)) return "image";
if(!isSHIFT(ev) && isCTRL(ev) && !isALT(ev) && !isMETA(ev)) return "image";
if(scaleToFullsizeModifier(ev)) return "image-fullsize";
return "link";
return processModifiers(ev, "InternalDragAction") as InternalDragAction;
}
export const emulateCTRLClickForLinks = (e:KeyEvent) => {
@@ -97,27 +154,23 @@ export const emulateCTRLClickForLinks = (e:KeyEvent) => {
export const emulateKeysForLinkClick = (action: PaneTarget): ModifierKeys => {
const ev = {shiftKey: false, ctrlKey: false, metaKey: false, altKey: false};
if(!action) return ev;
switch(action) {
case "active-pane":
setCTRL(ev, true);
setSHIFT(ev, true);
break;
case "new-pane":
setCTRL(ev, true);
setALT(ev, true);
break;
case "popout-window":
setCTRL(ev, true);
setALT(ev, true);
setSHIFT(ev, true);
break;
case "new-tab":
setCTRL(ev, true);
break;
case "md-properties":
setCTRL(ev, true);
setMETA(ev, true);
break;
const platform = DEVICE.isMacOS || DEVICE.isIOS ? "Mac" : "Win";
const settings:ExcalidrawSettings = window.ExcalidrawAutomate.plugin.settings;
const modifierKeyConfig = settings.modifierKeyConfig;
const config = modifierKeyConfig[platform]?.LinkClickAction;
if (config) {
const rule = config.rules.find(rule => rule.result === action);
if (rule) {
setCTRL(ev, rule.ctrl_cmd);
setALT(ev, rule.alt_opt);
setMETA(ev, rule.meta_ctrl);
setSHIFT(ev, rule.shift);
} else {
const defaultAction = config.defaultAction as PaneTarget;
return emulateKeysForLinkClick(defaultAction);
}
}
return ev;
}