Implement controlPressed and shiftPressed

This commit is contained in:
Henrik Giesel 2021-06-29 18:32:37 +02:00
parent 4601ebb347
commit 0ff0e87dbc
2 changed files with 40 additions and 34 deletions

View file

@ -7,6 +7,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import { nightModeKey } from "components/contextKeys"; import { nightModeKey } from "components/contextKeys";
import Badge from "components/Badge.svelte"; import Badge from "components/Badge.svelte";
import { deleteIcon } from "./icons"; import { deleteIcon } from "./icons";
import { controlPressed, shiftPressed } from "lib/keys";
export let name: string; export let name: string;
@ -23,39 +24,35 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
setTimeout(() => (flashing = false), 300); setTimeout(() => (flashing = false), 300);
} }
let showDelete = true; let hideDelete = false;
function hideDeleteOnCtrlShfit(event: MouseEvent) { function setDeleteIcon(event: KeyboardEvent | MouseEvent) {
showDelete = !event.ctrlKey && !event.shiftKey; hideDelete = controlPressed(event) || shiftPressed(event);
} }
function showDeleteOnLeave() { function showDeleteIcon() {
showDelete = true; hideDelete = true;
}
function toggleDelete() {
// TODO
} }
const nightMode = getContext<boolean>(nightModeKey); const nightMode = getContext<boolean>(nightModeKey);
</script> </script>
<svelte:body on:keydown={setDeleteIcon} on:keyup={setDeleteIcon} />
<button <button
class="btn d-inline-flex align-items-center text-nowrap rounded ps-2 pe-1 me-1" class="tag btn d-inline-flex align-items-center text-nowrap rounded ps-2 pe-1 me-1"
class:flashing class:flashing
class:hide-delete={hideDelete}
class:btn-day={!nightMode} class:btn-day={!nightMode}
class:btn-night={nightMode} class:btn-night={nightMode}
tabindex="-1" tabindex="-1"
on:mousemove={hideDeleteOnCtrlShfit} on:mouseleave={showDeleteIcon}
on:mouseleave={showDeleteOnLeave} on:mousemove={setDeleteIcon}
on:keydown={toggleDelete}
on:keyup={toggleDelete}
on:click on:click
> >
<span>{name}</span> <span>{name}</span>
<Badge <Badge class="delete-icon rounded ms-1 mt-1" on:click={deleteTag}
class={`delete-icon rounded ms-1 mt-1${showDelete ? "" : " opacity-0"}`} >{@html deleteIcon}</Badge
on:click={deleteTag}>{@html deleteIcon}</Badge
> >
</button> </button>
@ -85,15 +82,16 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
&.flashing { &.flashing {
animation: flash 0.3s linear; animation: flash 0.3s linear;
} }
&.hide-delete:hover :global(.delete-icon) {
opacity: 0;
}
} }
@include button.btn-day($with-active: false);
@include button.btn-night($with-active: false);
$white-translucent: rgba(255 255 255 / 0.5);
$dark-translucent: rgba(0 0 0 / 0.2);
:global(.delete-icon > svg:hover) { :global(.delete-icon > svg:hover) {
$white-translucent: rgba(255 255 255 / 0.5);
$dark-translucent: rgba(0 0 0 / 0.2);
.btn-day & { .btn-day & {
background-color: $dark-translucent; background-color: $dark-translucent;
} }
@ -102,4 +100,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
background-color: $white-translucent; background-color: $white-translucent;
} }
} }
@include button.btn-day($with-active: false);
@include button.btn-night($with-active: false);
</style> </style>

View file

@ -4,15 +4,17 @@
import * as tr from "./i18n"; import * as tr from "./i18n";
import { isApplePlatform } from "./platform"; import { isApplePlatform } from "./platform";
// those are the modifiers that Anki works with
export type Modifier = "Control" | "Alt" | "Shift" | "Meta"; export type Modifier = "Control" | "Alt" | "Shift" | "Meta";
// how modifiers are mapped
const allModifiers: Modifier[] = ["Control", "Alt", "Shift", "Meta"]; const allModifiers: Modifier[] = ["Control", "Alt", "Shift", "Meta"];
const platformModifiers = isApplePlatform() const platformModifiers: string[] = isApplePlatform()
? ["Meta", "Alt", "Shift", "Control"] ? ["Meta", "Alt", "Shift", "Control"]
: ["Control", "Alt", "Shift", "OS"]; : ["Control", "Alt", "Shift", "OS"];
function translateModifierToPlatform(modifier: Modifier): string {
return platformModifiers[allModifiers.indexOf(modifier)];
}
export const checkModifiers = export const checkModifiers =
(required: Modifier[], optional: Modifier[] = []) => (required: Modifier[], optional: Modifier[] = []) =>
@ -31,15 +33,18 @@ export const checkModifiers =
); );
}; };
export const hasModifier = (modifier: Modifier) => (event: KeyboardEvent): boolean => event.getModifierState(platformModifiers[allModifiers.indexOf(modifier)]); const modifierPressed =
(modifier: Modifier) =>
(event: MouseEvent | KeyboardEvent): boolean => {
const translated = translateModifierToPlatform(modifier);
const state = event.getModifierState(translated);
return event.type === "keyup"
? state && (event as KeyboardEvent).key !== translated
: state;
};
export function isControl(key: string): boolean { export const controlPressed = modifierPressed("Control");
return key === platformModifiers[0]; export const shiftPressed = modifierPressed("Shift");
}
export function isShift(key: string): boolean {
return key === platformModifiers[2];
}
export function modifiersToPlatformString(modifiers: string[]): string { export function modifiersToPlatformString(modifiers: string[]): string {
const displayModifiers = isApplePlatform() const displayModifiers = isApplePlatform()