aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsowgro <tpoke.ferrari@gmail.com>2024-12-29 23:20:05 -0500
committersowgro <tpoke.ferrari@gmail.com>2024-12-29 23:20:05 -0500
commit27c09e334ff2e7b7690c49331040064642a0c46e (patch)
treeb7cc8914c9dfd790e4467a9c36d24c6f430631d8
parent514a33483697ff231c075cbb9130606af19d9298 (diff)
downloadbookmarks-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.tsx103
-rw-r--r--extension/src/components/Bookmark.tsx103
-rw-r--r--extension/src/components/ContextMenu.tsx2
-rw-r--r--extension/src/components/FolderBody.tsx2
-rw-r--r--extension/src/components/FolderButton.tsx5
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();