diff options
author | sowgro <tpoke.ferrari@gmail.com> | 2024-12-29 23:20:05 -0500 |
---|---|---|
committer | sowgro <tpoke.ferrari@gmail.com> | 2024-12-29 23:20:05 -0500 |
commit | 27c09e334ff2e7b7690c49331040064642a0c46e (patch) | |
tree | b7cc8914c9dfd790e4467a9c36d24c6f430631d8 | |
parent | 514a33483697ff231c075cbb9130606af19d9298 (diff) | |
download | bookmarks-home-drag-n-drop.tar.gz bookmarks-home-drag-n-drop.tar.bz2 bookmarks-home-drag-n-drop.zip |
Refactoringdrag-n-drop
-rw-r--r-- | extension/src/components/BMIcon.tsx | 103 | ||||
-rw-r--r-- | extension/src/components/Bookmark.tsx | 103 | ||||
-rw-r--r-- | extension/src/components/ContextMenu.tsx | 2 | ||||
-rw-r--r-- | extension/src/components/FolderBody.tsx | 2 | ||||
-rw-r--r-- | extension/src/components/FolderButton.tsx | 5 |
5 files changed, 109 insertions, 106 deletions
diff --git a/extension/src/components/BMIcon.tsx b/extension/src/components/BMIcon.tsx new file mode 100644 index 0000000..e7c2a26 --- /dev/null +++ b/extension/src/components/BMIcon.tsx @@ -0,0 +1,103 @@ +import React, {SyntheticEvent, useEffect} from "react"; +import ColorThief from "colorthief"; +import {getBrowser} from "../main.tsx"; + +function BMIcon (props: {url: string, id: string}) { + + let [favicon, setFavicon] = React.useState<string | null>(null); + let [iconMode, setIconMode] = React.useState<"large" | "small" | "letter">("letter"); + let [bgColor, setBgColor] = React.useState<[number, number, number] | null>(null) + let [bgColorPriority, setBgColorPriority] = React.useState(0); + + useEffect(() => { + faviconURL(props).then(r => { + if (r) { + setFavicon(r) + setIconMode("small"); + } + }) + }, []); + + function handleImageLoad(e: SyntheticEvent<HTMLImageElement, Event>) { + if (e.currentTarget.naturalWidth >= 75 || favicon!.startsWith("data:image/svg+xml")) { + setIconMode("large") + } else if(bgColorPriority < 2) { + setBgColor(new ColorThief().getColor(e.currentTarget)) + setBgColorPriority(2); + } + } + + return ( + <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": { + let url = new URL(props.url); + if (bgColorPriority < 1) { + setBgColor(hashStringToColor(url.hostname)); + setBgColorPriority(1); + } + return (<span className={"letter"}>{url.hostname.charAt(0)}</span>) + } + case "small": { + return (<img alt="Bookmark icon" src={favicon!} onLoad={handleImageLoad}/>) + } + case "large": { + return (<img alt="Bookmark icon" src={favicon!}/>) + } + } + })()} + </div> + ) +} + +/** + * Gets the icon for a bookmark + * + * @param data The URL of the link + * @return The URL of the icon + */ +async function faviconURL(data: {url: string, id:string}) { + let i = (await getBrowser().storage.local.get("icon-cache-"+data.id))["icon-cache-"+data.id]; + if (i) return i + // if (i == null) return i; + + const url = new URL('https://www.google.com/s2/favicons'); + url.searchParams.set("sz", "256"); + url.searchParams.set("domain_url", data.url!); + let resp = await fetch(url) + let imgData = resp.ok ? await toDataURL(url.toString()) : null; + getBrowser().storage.local.set({["icon-cache-"+data.id]: imgData}); + return imgData; +} + +function toDataURL(url: string): string { + // @ts-ignore + return fetch(url) + .then(response => response.blob()) + .then(blob => new Promise((resolve, reject) => { + const reader = new FileReader() + reader.onloadend = () => resolve(reader.result) + reader.onerror = reject + reader.readAsDataURL(blob) + })) +} + +function djb2(str: string){ + let hash = 5381; + for (var i = 0; i < str.length; i++) { + hash = ((hash << 5) + hash) + str.charCodeAt(i); /* hash * 33 + c */ + } + return hash; +} + +function hashStringToColor(str: string): [number, number, number] { + let hash = djb2(str); + let r = (hash & 0xFF0000) >> 16; + let g = (hash & 0x00FF00) >> 8; + let b = hash & 0x0000FF; + return [r, g, b]; +} + +export default BMIcon;
\ No newline at end of file diff --git a/extension/src/components/Bookmark.tsx b/extension/src/components/Bookmark.tsx index 2f1bbd9..0e36b56 100644 --- a/extension/src/components/Bookmark.tsx +++ b/extension/src/components/Bookmark.tsx @@ -1,10 +1,10 @@ import BookmarkTreeNode = browser.bookmarks.BookmarkTreeNode; -import React, {SyntheticEvent, useContext, useEffect, useState} from "react"; +import React, {useContext, useEffect, useState} from "react"; import {getBrowser} from "../main.tsx"; import {ActiveDrag, ActiveEdit, Settings} from "./Body.tsx"; -import ColorThief from 'colorthief' import DropTargets from "./DropTargets.tsx"; import ContextMenu from "./ContextMenu.tsx"; +import BMIcon from "./BMIcon.tsx"; /** * A component for a single bookmark @@ -14,10 +14,6 @@ function Bookmark(props: {id: string}) { let [activeDrag, setActiveDrag] = React.useContext(ActiveDrag); const [, setActiveEdit] = useContext(ActiveEdit) - let [favicon, setFavicon] = React.useState<string | null>(null); - let [iconMode, setIconMode] = React.useState<"large" | "small" | "letter">("letter"); - let [bgColor, setBgColor] = React.useState<[number, number, number] | null>(null) - let [bgColorPriority, setBgColorPriority] = React.useState(0); const [bmData, setBmData] = useState<BookmarkTreeNode | undefined>() useEffect(() => { @@ -33,27 +29,8 @@ function Bookmark(props: {id: string}) { }) }, []); - useEffect(() => { - if (!bmData) return; - faviconURL(bmData).then(r => { - if (r) { - setFavicon(r) - setIconMode("small"); - } - }) - }, [bmData]); - if (!bmData) return; - function handleImageLoad(e: SyntheticEvent<HTMLImageElement, Event>) { - if (e.currentTarget.naturalWidth >= 75 || favicon!.startsWith("data:image/svg+xml")) { - setIconMode("large") - } else if(bgColorPriority < 2) { - setBgColor(new ColorThief().getColor(e.currentTarget)) - setBgColorPriority(2); - } - } - // Dragging const handleDrag = () => { setActiveDrag(bmData); @@ -65,7 +42,6 @@ function Bookmark(props: {id: string}) { // Dropping const handleDropLeft = () => { - console.log("drop left bm") getBrowser().bookmarks.move(activeDrag!.id, { parentId: bmData.parentId, index: bmData.index @@ -74,7 +50,6 @@ function Bookmark(props: {id: string}) { }; const handleDropRight = () => { - console.log("drop right bm") getBrowser().bookmarks.move(activeDrag!.id, { parentId: bmData.parentId, index: (bmData.index! + 1) @@ -83,9 +58,7 @@ function Bookmark(props: {id: string}) { }; const handleDropCenter = () => { - console.log("drop center bm") chrome.bookmarks.create({ - // type: "folder", parentId: bmData.parentId, index: bmData.index, title: "New Folder" @@ -96,6 +69,7 @@ function Bookmark(props: {id: string}) { }) }; + // actions const handleDelete = () => { getBrowser().bookmarks.remove(bmData.id); location.reload(); @@ -105,33 +79,12 @@ function Bookmark(props: {id: string}) { e.preventDefault() setActiveEdit(null); setActiveEdit(bmData); - // setActiveEdit(bmData); }; return( <div className={"bookmark"}> <a href={bmData.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": { - let url = new URL(bmData.url!); - if (bgColorPriority < 1) { - setBgColor(hashStringToColor(url.hostname)); - setBgColorPriority(1); - } - return (<span className={"letter"}>{url.hostname.charAt(0)}</span>) - } - case "small": { - return (<img alt="Bookmark icon" src={favicon!} onLoad={handleImageLoad}/>) - } - case "large": { - return (<img alt="Bookmark icon" src={favicon!}/>) - } - } - })()} - </div> + <BMIcon url={bmData.url!} id={bmData.title}/> <span>{bmData.title}</span> </a> {settings.editMode && <ContextMenu onEdit={handleEdit} onDelete={handleDelete}/>} @@ -141,52 +94,4 @@ function Bookmark(props: {id: string}) { ); } -/** - * Gets the icon for a bookmark - * - * @param data The URL of the link - * @return The URL of the icon - */ -async function faviconURL(data: BookmarkTreeNode) { - let i = (await getBrowser().storage.local.get("icon-cache-"+data.id))["icon-cache-"+data.id]; - if (i) return i - // if (i == null) return i; - - const url = new URL('https://www.google.com/s2/favicons'); - url.searchParams.set("sz", "256"); - url.searchParams.set("domain_url", data.url!); - let resp = await fetch(url) - let imgData = resp.ok ? await toDataURL(url.toString()) : null; - getBrowser().storage.local.set({["icon-cache-"+data.id]: imgData}); - return imgData; -} - -function toDataURL(url:string):string { - // @ts-ignore - return fetch(url) - .then(response => response.blob()) - .then(blob => new Promise((resolve, reject) => { - const reader = new FileReader() - reader.onloadend = () => resolve(reader.result) - reader.onerror = reject - reader.readAsDataURL(blob) - })) -} - -function djb2(str: string){ - let hash = 5381; - for (var i = 0; i < str.length; i++) { - hash = ((hash << 5) + hash) + str.charCodeAt(i); /* hash * 33 + c */ - } - return hash; -} - -function hashStringToColor(str: string): [number, number, number] { - let hash = djb2(str); - let r = (hash & 0xFF0000) >> 16; - let g = (hash & 0x00FF00) >> 8; - let b = hash & 0x0000FF; - return [r, g, b]; -} - export default Bookmark;
\ No newline at end of file diff --git a/extension/src/components/ContextMenu.tsx b/extension/src/components/ContextMenu.tsx index 058e9ba..8bcb903 100644 --- a/extension/src/components/ContextMenu.tsx +++ b/extension/src/components/ContextMenu.tsx @@ -9,9 +9,7 @@ function ContextMenu(props: {onEdit: (e: React.MouseEvent<HTMLButtonElement>) => useEffect(() => { let evl = () => { - console.log("clicked") open && setOpen(false); - console.log("evl unregistered") document.body.removeEventListener('click', evl); } if (open) { diff --git a/extension/src/components/FolderBody.tsx b/extension/src/components/FolderBody.tsx index e75fcc7..71dad4a 100644 --- a/extension/src/components/FolderBody.tsx +++ b/extension/src/components/FolderBody.tsx @@ -1,5 +1,5 @@ import BookmarkTreeNode = browser.bookmarks.BookmarkTreeNode; -import {ReactElement, useContext, useEffect, useState} from "react"; +import {useContext, useEffect, useState} from "react"; import {Settings} from "./Body.tsx"; import {getBrowser} from "../main.tsx"; import Bookmark from "./Bookmark.tsx"; diff --git a/extension/src/components/FolderButton.tsx b/extension/src/components/FolderButton.tsx index 7bd55c1..244760d 100644 --- a/extension/src/components/FolderButton.tsx +++ b/extension/src/components/FolderButton.tsx @@ -50,13 +50,11 @@ function FolderButton(props: {id: string}) { }; const handleDragEnd = () => { - console.log("drop end") setActiveDrag(null); }; // Dropping const handleDropLeft = () => { - console.log("drop left folder") getBrowser().bookmarks.move(activeDrag!.id, { parentId: bmData.parentId, index: bmData.index @@ -65,7 +63,6 @@ function FolderButton(props: {id: string}) { }; const handleDropRight = () => { - console.log("drop right folder") getBrowser().bookmarks.move(activeDrag!.id, { parentId: bmData.parentId, index: (bmData.index! + 1) @@ -74,13 +71,13 @@ function FolderButton(props: {id: string}) { }; const handleDropCenter = () => { - console.log("drop center folder") getBrowser().bookmarks.move(activeDrag!.id, { parentId: bmData.id }); location.reload() }; + // actions const handleDelete = () => { getBrowser().bookmarks.removeTree(bmData.id); location.reload(); |