diff options
Diffstat (limited to 'extension')
-rw-r--r-- | extension/src/components/Bookmark.tsx | 165 | ||||
-rw-r--r-- | extension/src/components/DropTargets.tsx | 52 | ||||
-rw-r--r-- | extension/src/components/FolderButton.tsx | 58 |
3 files changed, 150 insertions, 125 deletions
diff --git a/extension/src/components/Bookmark.tsx b/extension/src/components/Bookmark.tsx index 5a406eb..2442e02 100644 --- a/extension/src/components/Bookmark.tsx +++ b/extension/src/components/Bookmark.tsx @@ -3,8 +3,7 @@ import React, {SyntheticEvent, useEffect} from "react"; import {getBrowser} from "../main.tsx"; import {ActiveDrag, Settings} from "./Body.tsx"; import ColorThief from 'colorthief' -import CreateFolderIcon from "../assets/create_folder.svg?react" -import react from "@vitejs/plugin-react"; +import DropTargets from "./DropTargets.tsx"; /** * A component for a single bookmark @@ -12,16 +11,14 @@ import react from "@vitejs/plugin-react"; * @param props.data The BookmarkTreeNode with the data for the bookmark */ function Bookmark(props: {data: BookmarkTreeNode}) { + let [settings, _] = React.useContext(Settings); + let [activeDrag, setActiveDrag] = React.useContext(ActiveDrag); + let [favicon, setFavicon] = React.useState<string | null>(null); let [iconMode, setIconMode] = React.useState<"large" | "small" | "letter">("letter"); - let [settings, setSettings] = React.useContext(Settings); let [bgColor, setBgColor] = React.useState<[number, number, number] | null>(null) let [bgColorPriority, setBgColorPriority] = React.useState(0); - let [activeDrag, setActiveDrag] = React.useContext(ActiveDrag); - let [dropRight, setDropRight] = React.useState(false); - let [dropLeft, setDropLeft] = React.useState(false); - let [dropCenter, setDropCenter] = React.useState(false); - let [thisDragged, setThisDragged] = React.useState(false); + useEffect(() => { faviconURL(props.data).then(r => { @@ -32,12 +29,6 @@ function Bookmark(props: {data: BookmarkTreeNode}) { }) }, []); - useEffect(() => { - setDropLeft(false); - setDropRight(false); - setDropCenter(false); - }, [activeDrag]); - function handleImageLoad(e: SyntheticEvent<HTMLImageElement, Event>) { if (e.currentTarget.naturalWidth >= 75 || favicon!.startsWith("data:image/svg+xml")) { setIconMode("large") @@ -47,27 +38,51 @@ function Bookmark(props: {data: BookmarkTreeNode}) { } } - function handleDragStart(e: React.DragEvent<HTMLAnchorElement>) { - // e.dataTransfer.setData("text/bm-id", props.data.id); - // setActiveDrag(true); - console.log("data", e.dataTransfer.getData("text/bm-id").toString()) - } - - function handleDrag(e: React.DragEvent<HTMLAnchorElement>) { - // e.dataTransfer.setData("text/bm-id", props.data.id); + // Dragging + function handleDrag() { setActiveDrag(props.data); - setThisDragged(true); - // e.dataTransfer.dropEffect = "move"; } function handleDragEnd() { setActiveDrag(null); - setThisDragged(false); + } + + // Dropping + function handleDropLeft() { + console.log("drop left bm") + getBrowser().bookmarks.move(activeDrag!.id, { + parentId: props.data.parentId, + index: props.data.index + }) + location.reload() + } + + function handleDropRight() { + console.log("drop right bm") + getBrowser().bookmarks.move(activeDrag!.id, { + parentId: props.data.parentId, + index: (props.data.index! + 1) + }) + location.reload(); + } + + function handleDropCenter() { + console.log("drop center bm") + chrome.bookmarks.create({ + // type: "folder", + parentId: props.data.parentId, + index: props.data.index, + title: "New Folder" + }).then(r => { + getBrowser().bookmarks.move(props.data.id, {parentId: r.id}); + getBrowser().bookmarks.move(activeDrag!.id, {parentId: r.id}); + location.reload() + }) } return( <div className={"bookmark"}> - <a draggable={settings.editMode} href={props.data.url} onDragStart={handleDragStart} onDrag={handleDrag} onDragEnd={handleDragEnd}> + <a href={props.data.url} draggable={settings.editMode} onDrag={handleDrag} onDragEnd={handleDragEnd}> <div className={"icon-box " + (iconMode)} style={bgColor ? {"--icon-bg": `rgba(${bgColor[0]}, ${bgColor[1]}, ${bgColor[2]}, 0.2)`} as React.CSSProperties : undefined}> {(() => { switch (iconMode) { case "letter": { @@ -88,92 +103,8 @@ function Bookmark(props: {data: BookmarkTreeNode}) { </div> <span>{props.data.title}</span> </a> - {activeDrag && !thisDragged && ( - <div className={"drop-targets"}> - <div - className={"left"} - onDragOver={e => { - e.preventDefault() - setDropLeft(true) - }} - onDragEnter={e =>{ - e.preventDefault() - }} - onDragLeave={_ => { - setDropLeft(false) - }} - onDrop={e => { - getBrowser().bookmarks.move(activeDrag.id, { - parentId: props.data.parentId, - index: props.data.index - }) - location.reload() - }} - style={dropLeft ? undefined : {opacity: 0}} - // hidden={!dropLeft} - > - <div/> - </div> - <div - className={"right"} - onDragOver={e => { - e.preventDefault(); - setDropRight(true); - }} - onDragEnter={e => { - e.preventDefault(); - }} - onDragLeave={_ => { - setDropRight(false) - }} - onDrop={e => { - getBrowser().bookmarks.move(activeDrag.id, { - parentId: props.data.parentId, - index: (props.data.index! + 1) - }) - location.reload() - e.preventDefault() - }} - style={dropRight ? undefined : {opacity: 0}} - // hidden={!dropRight} - > - <div/> - </div> - <div - className={"center"} - onDragOver={e => { - e.preventDefault() - setDropCenter(true) - // console.log("dropped") - }} - onDragEnter={e => { - e.preventDefault() - // console.log("enter") - }} - onDragLeave={_ => { - setDropCenter(false) - // console.log("exit") - }} - onDrop={e => { - e.preventDefault(); - chrome.bookmarks.create({ - // type: "folder", - parentId: props.data.parentId, - index: props.data.index, - title: "New Folder" - }).then(r => { - getBrowser().bookmarks.move(props.data.id, {parentId: r.id}); - getBrowser().bookmarks.move(activeDrag?.id, {parentId: r.id}); - location.reload() - }) - }} - style={dropCenter ? undefined : {opacity: 0}} - // hidden={!dropCenter} - > - <CreateFolderIcon/> - </div> - </div> - )} + {activeDrag && activeDrag !== props.data && + <DropTargets onDropLeft={handleDropLeft} onDropRight={handleDropRight} onDropCenter={handleDropCenter}/>} </div> ); } @@ -211,7 +142,7 @@ function toDataURL(url:string):string { } function djb2(str: string){ - var hash = 5381; + let hash = 5381; for (var i = 0; i < str.length; i++) { hash = ((hash << 5) + hash) + str.charCodeAt(i); /* hash * 33 + c */ } @@ -219,10 +150,10 @@ function djb2(str: string){ } function hashStringToColor(str: string): [number, number, number] { - var hash = djb2(str); - var r = (hash & 0xFF0000) >> 16; - var g = (hash & 0x00FF00) >> 8; - var b = hash & 0x0000FF; + let hash = djb2(str); + let r = (hash & 0xFF0000) >> 16; + let g = (hash & 0x00FF00) >> 8; + let b = hash & 0x0000FF; return [r, g, b]; } diff --git a/extension/src/components/DropTargets.tsx b/extension/src/components/DropTargets.tsx new file mode 100644 index 0000000..297f366 --- /dev/null +++ b/extension/src/components/DropTargets.tsx @@ -0,0 +1,52 @@ +import React, {useEffect} from "react"; +import {ActiveDrag} from "./Body.tsx"; +import CreateFolderIcon from "../assets/create_folder.svg?react" + +function DropTarget(props: {children: React.ReactNode, className: string, onDrop: () => void}) { + let [drop, setDrop] = React.useState(false); + let [activeDrag, _] = React.useContext(ActiveDrag); + + useEffect(() => { + setDrop(false); + }, [activeDrag]); + + function handleDragOver(e: React.DragEvent<HTMLDivElement>) { + e.preventDefault() + setDrop(true) + } + + function handleDragLeave(e: React.DragEvent<HTMLDivElement>) { + setDrop(false) + } + + function handleDrop(e: React.DragEvent<HTMLDivElement>) { + e.preventDefault(); + props.onDrop(); + } + + return ( + <div className={props.className} style={drop ? undefined : {opacity: 0}} + onDragOver={handleDragOver} onDragLeave={handleDragLeave} onDrop={handleDrop}> + {props.children} + </div> + ); +} + +function DropTargets(props: { onDropLeft: () => void, onDropRight: () => void, onDropCenter: () => void }) { + + return ( + <div className={"drop-targets"}> + <DropTarget className={"left"} onDrop={props.onDropLeft}> + <div/> + </DropTarget> + <DropTarget className={"right"} onDrop={props.onDropRight}> + <div/> + </DropTarget> + <DropTarget className={"center"} onDrop={props.onDropCenter}> + <CreateFolderIcon/> + </DropTarget> + </div> + ); +} + +export default DropTargets;
\ No newline at end of file diff --git a/extension/src/components/FolderButton.tsx b/extension/src/components/FolderButton.tsx index 2b59d56..b1a8a64 100644 --- a/extension/src/components/FolderButton.tsx +++ b/extension/src/components/FolderButton.tsx @@ -2,8 +2,10 @@ import BookmarkTreeNode = browser.bookmarks.BookmarkTreeNode; import FolderBody from "./FolderBody.tsx"; import FolderIcon from "../assets/folder.svg?react" import FolderIconOpen from "../assets/folder_open.svg?react" -import {useState} from "react"; -import bookmark from "./Bookmark.tsx"; +import React, {useState} from "react"; +import DropTargets from "./DropTargets.tsx"; +import {ActiveDrag, Settings} from "./Body.tsx"; +import {getBrowser} from "../main.tsx"; /** * A component for the button used to open a bookmark folder. @@ -12,24 +14,64 @@ import bookmark from "./Bookmark.tsx"; * @param props.data The BookmarkTreeNode containing the data of the folder */ function FolderButton(props: {data: BookmarkTreeNode}) { + let [settings, _] = React.useContext(Settings); + let [activeDrag, setActiveDrag] = React.useContext(ActiveDrag); + const [folderOpen, setFolderOpen] = useState(false); + // Dragging + function handleDrag() { + setActiveDrag(props.data); + } + + function handleDragEnd() { + console.log("drop end") + setActiveDrag(null); + } + + // Dropping + function handleDropLeft() { + console.log("drop left folder") + getBrowser().bookmarks.move(activeDrag!.id, { + parentId: props.data.parentId, + index: props.data.index + }) + location.reload() + } + + function handleDropRight() { + console.log("drop right folder") + getBrowser().bookmarks.move(activeDrag!.id, { + parentId: props.data.parentId, + index: (props.data.index! + 1) + }) + location.reload(); + } + + function handleDropCenter() { + console.log("drop center folder") + getBrowser().bookmarks.move(activeDrag!.id, { + parentId: props.data.id + }); + location.reload() + } + return( <> <div className={"bookmark"}> - <a onClick={() => setFolderOpen(!folderOpen)}> + <a onClick={() => setFolderOpen(!folderOpen)} draggable={settings.editMode} onDrag={handleDrag} onDragEnd={handleDragEnd}> <div className="icon-box"> {folderOpen ? <FolderIconOpen/> : <FolderIcon/>} </div> <span>{props.data.title}</span> </a> + {activeDrag && activeDrag !== props.data && + <DropTargets onDropLeft={handleDropLeft} onDropRight={handleDropRight} onDropCenter={handleDropCenter}/>} </div> - {folderOpen - && props.data.children - && props.data.children.length > 0 - && (<FolderBody data={props.data}/>)} + {folderOpen && props.data.children && props.data.children.length > 0 && + <FolderBody data={props.data}/>} </> -); + ); } export default FolderButton
\ No newline at end of file |