From 1687d1105da2182331fee8b3694cfe10b68e04b5 Mon Sep 17 00:00:00 2001 From: liuycy Date: Wed, 28 Feb 2024 22:19:03 +0800 Subject: [PATCH] feat: optional open item on checkbox (#151) * fix: typescript error while using native events * feat: diff cursor on folders while pressing alt key with checkbox opened * feat: optional open item on checkbox --------- close alist-org/alist#6113 close alist-org/alist#6108 close alist-org/alist#6096 --------- Co-authored-by: Andy Hsu --- src/lang/en/home.json | 8 +++++++- src/main.tsx | 8 ++++++++ src/pages/home/folder/GridItem.tsx | 12 ++++++------ src/pages/home/folder/ImageItem.tsx | 9 ++++++--- src/pages/home/folder/ListItem.tsx | 14 +++++++------- src/pages/home/folder/helper.ts | 27 +++++++++++++++++++++++++++ src/store/local_settings.ts | 6 ++++++ 7 files changed, 67 insertions(+), 17 deletions(-) create mode 100644 src/pages/home/folder/helper.ts diff --git a/src/lang/en/home.json b/src/lang/en/home.json index 7bc2add6c3..cf031f1615 100644 --- a/src/lang/en/home.json +++ b/src/lang/en/home.json @@ -123,7 +123,13 @@ "none": "None", "visible": "Visible" }, - "filename_scrollable": "Filename scrollable" + "filename_scrollable": "Filename scrollable", + "open_item_on_checkbox": "Open item on Checkbox", + "open_item_on_checkbox_options": { + "direct": "Direct", + "with_ctrl": "With Ctrl/Command hold", + "with_alt": "With Alt/Option hold" + } }, "package_download": { "current_status": "Current Status", diff --git a/src/main.tsx b/src/main.tsx index 8f942b7889..6cbe4251e7 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -9,6 +9,14 @@ declare global { [key: string]: any } } + +declare module "solid-js" { + namespace JSX { + interface CustomEvents extends HTMLElementEventMap {} + interface CustomCaptureEvents extends HTMLElementEventMap {} + } +} + render( () => ( diff --git a/src/pages/home/folder/GridItem.tsx b/src/pages/home/folder/GridItem.tsx index c9f9c0a1ab..3737ebf369 100644 --- a/src/pages/home/folder/GridItem.tsx +++ b/src/pages/home/folder/GridItem.tsx @@ -14,6 +14,7 @@ import { import { ObjType, StoreObj } from "~/types" import { bus, hoverColor } from "~/utils" import { getIconByObj } from "~/utils/icon" +import { useOpenItemWithCheckbox } from "./helper" export const GridItem = (props: { obj: StoreObj; index: number }) => { const { isHide } = useUtil() @@ -34,6 +35,7 @@ export const GridItem = (props: { obj: StoreObj; index: number }) => { ) const { show } = useContextMenu({ id: 1 }) const { pushHref, to } = useRouter() + const isShouldOpenItem = useOpenItemWithCheckbox() return ( { }} as={LinkWithPush} href={props.obj.name} - // @ts-ignore - on:click={(e: PointerEvent) => { + cursor={!checkboxOpen() || isShouldOpenItem() ? "pointer" : "default"} + on:click={(e: MouseEvent) => { if (!checkboxOpen()) return e.preventDefault() if (e.altKey) { @@ -89,8 +91,7 @@ export const GridItem = (props: { obj: StoreObj; index: number }) => { class="item-thumbnail" h={`${parseInt(local["grid_item_size"])}px`} w="$full" - // @ts-ignore - on:click={(e) => { + on:click={(e: MouseEvent) => { if (checkboxOpen()) return if (props.obj.type === ObjType.IMAGE) { e.stopPropagation() @@ -106,8 +107,7 @@ export const GridItem = (props: { obj: StoreObj; index: number }) => { left="$1" top="$1" // colorScheme="neutral" - // @ts-expect-error - on:click={(e) => { + on:click={(e: MouseEvent) => { e.stopPropagation() }} checked={props.obj.selected} diff --git a/src/pages/home/folder/ImageItem.tsx b/src/pages/home/folder/ImageItem.tsx index a8533cadc2..4e0bd4b1d6 100644 --- a/src/pages/home/folder/ImageItem.tsx +++ b/src/pages/home/folder/ImageItem.tsx @@ -8,6 +8,7 @@ import { checkboxOpen, getMainColor, selectAll, selectIndex } from "~/store" import { ObjType, StoreObj } from "~/types" import { bus } from "~/utils" import { getIconByObj } from "~/utils/icon" +import { useOpenItemWithCheckbox } from "./helper" export const ImageItem = (props: { obj: StoreObj; index: number }) => { const { isHide } = useUtil() @@ -24,6 +25,7 @@ export const ImageItem = (props: { obj: StoreObj; index: number }) => { ) const { show } = useContextMenu({ id: 1 }) const { rawLink } = useLink() + const isShouldOpenItem = useOpenItemWithCheckbox() return ( { fallbackErr={objIcon} src={rawLink(props.obj)} loading="lazy" - cursor="pointer" - // @ts-expect-error - on:click={(e: PointerEvent) => { + cursor={ + !checkboxOpen() || isShouldOpenItem() ? "pointer" : "default" + } + on:click={(e: MouseEvent) => { if (!checkboxOpen() || e.altKey) { bus.emit("gallery", props.obj.name) return diff --git a/src/pages/home/folder/ListItem.tsx b/src/pages/home/folder/ListItem.tsx index 42f4ea1215..ee725f6e20 100644 --- a/src/pages/home/folder/ListItem.tsx +++ b/src/pages/home/folder/ListItem.tsx @@ -15,6 +15,7 @@ import { import { ObjType, StoreObj } from "~/types" import { bus, formatDate, getFileSize, hoverColor } from "~/utils" import { getIconByObj } from "~/utils/icon" +import { useOpenItemWithCheckbox } from "./helper" export interface Col { name: OrderBy @@ -36,6 +37,7 @@ export const ListItem = (props: { obj: StoreObj; index: number }) => { const { setPathAs } = usePath() const { show } = useContextMenu({ id: 1 }) const { pushHref, to } = useRouter() + const isShouldOpenItem = useOpenItemWithCheckbox() const filenameScrollable = () => local["filename_scrollable"] === "true" return ( { }} as={LinkWithPush} href={props.obj.name} - // @ts-expect-error - on:click={(e: PointerEvent) => { + cursor={!checkboxOpen() || isShouldOpenItem() ? "pointer" : "default"} + on:click={(e: MouseEvent) => { if (!checkboxOpen()) return e.preventDefault() - if (e.altKey) { + if (isShouldOpenItem()) { // click with alt/option key to(pushHref(props.obj.name)) return @@ -87,8 +89,7 @@ export const ListItem = (props: { obj: StoreObj; index: number }) => { { + on:click={(e: MouseEvent) => { e.stopPropagation() }} checked={props.obj.selected} @@ -103,8 +104,7 @@ export const ListItem = (props: { obj: StoreObj; index: number }) => { color={getMainColor()} as={getIconByObj(props.obj)} mr="$1" - // @ts-expect-error - on:click={(e) => { + on:click={(e: MouseEvent) => { if (props.obj.type === ObjType.IMAGE) { e.stopPropagation() e.preventDefault() diff --git a/src/pages/home/folder/helper.ts b/src/pages/home/folder/helper.ts new file mode 100644 index 0000000000..6370a7a796 --- /dev/null +++ b/src/pages/home/folder/helper.ts @@ -0,0 +1,27 @@ +import { createKeyHold } from "@solid-primitives/keyboard" +import { createEffect, createSignal } from "solid-js" +import { local } from "~/store" + +export function useOpenItemWithCheckbox() { + const [shouldOpen, setShouldOpen] = createSignal( + local["open_item_on_checkbox"] === "direct", + ) + const isAltKeyPressed = createKeyHold("Alt") + const isControlKeyPressed = createKeyHold("Control") + createEffect(() => { + switch (local["open_item_on_checkbox"]) { + case "direct": { + setShouldOpen(true) + break + } + case "with_ctrl": { + setShouldOpen(isControlKeyPressed()) + break + } + case "with_alt": { + setShouldOpen(isAltKeyPressed()) + } + } + }) + return shouldOpen +} diff --git a/src/store/local_settings.ts b/src/store/local_settings.ts index 7cd888cfc8..0a2d83b024 100644 --- a/src/store/local_settings.ts +++ b/src/store/local_settings.ts @@ -51,6 +51,12 @@ export const initialLocalSettings = [ default: "false", type: "boolean", }, + { + key: "open_item_on_checkbox", + default: "direct", + type: "select", + options: ["direct", "with_alt"], // "with_ctrl",? mac's control key can't be prevented + }, ] export type LocalSetting = (typeof initialLocalSettings)[number] for (const setting of initialLocalSettings) {