aboutsummaryrefslogtreecommitdiff
path: root/extension
diff options
context:
space:
mode:
authorsowgro <tpoke.ferrari@gmail.com>2024-12-03 00:02:21 -0500
committersowgro <tpoke.ferrari@gmail.com>2024-12-03 00:02:21 -0500
commit8ad470aaf5434005db4c59106dcbcf4cbc8cf49b (patch)
treee7df44904ce00bed8d7d45e8d1c22e7253eed6b1 /extension
parentafa44751b7f9d39c4842d5a91a9e3ce28d74bfce (diff)
downloadbookmarks-home-8ad470aaf5434005db4c59106dcbcf4cbc8cf49b.tar.gz
bookmarks-home-8ad470aaf5434005db4c59106dcbcf4cbc8cf49b.tar.bz2
bookmarks-home-8ad470aaf5434005db4c59106dcbcf4cbc8cf49b.zip
Push drag and drop code so far
Diffstat (limited to 'extension')
-rw-r--r--extension/src/assets/create_folder.svg1
-rw-r--r--extension/src/components/Body.tsx15
-rw-r--r--extension/src/components/Bookmark-backup.txt161
-rw-r--r--extension/src/components/Bookmark.tsx92
-rw-r--r--extension/src/index.css17
5 files changed, 116 insertions, 170 deletions
diff --git a/extension/src/assets/create_folder.svg b/extension/src/assets/create_folder.svg
new file mode 100644
index 0000000..3e94c9c
--- /dev/null
+++ b/extension/src/assets/create_folder.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e8eaed"><path d="M560-320h80v-80h80v-80h-80v-80h-80v80h-80v80h80v80ZM160-160q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h240l80 80h320q33 0 56.5 23.5T880-640v400q0 33-23.5 56.5T800-160H160Z"/></svg> \ No newline at end of file
diff --git a/extension/src/components/Body.tsx b/extension/src/components/Body.tsx
index e575d89..07b0259 100644
--- a/extension/src/components/Body.tsx
+++ b/extension/src/components/Body.tsx
@@ -9,9 +9,15 @@ import {getBrowser} from "../main.tsx";
export const Settings =
React.createContext<[ISettings, (arg0: ISettings) => void]>([
- defaultSettings,
- () => {}
-]);
+ defaultSettings,
+ () => {}
+ ]);
+
+export const ActiveDrag =
+ React.createContext<[boolean, (arg0: boolean) => void]>([
+ false,
+ () => {}
+ ])
/**
* A component for the full body of the application
@@ -22,6 +28,7 @@ function Body() {
const [settings, setSettings] = useState<ISettings>(defaultSettings);
const [selectedBookmarkTree, setSelectedBookmarkTree] = useState<BookmarkTreeNode[]>([])
const [fullBookmarkTree, setFullBookmarkTree] = useState<BookmarkTreeNode[] | null>([])
+ const [activeDrag, setActiveDrag] = useState(false);
useEffect(() => {
loadSettings().then(r => {
@@ -47,6 +54,7 @@ function Body() {
return (
<Settings.Provider value={[settings!, setSettings]}>
+ <ActiveDrag.Provider value={[activeDrag, setActiveDrag]}>
{(() => {switch (settings.backgroundMode) {
case "color": return (<style>{"body {background-color: " + settings.backgroundColor + "; }"}</style>)
case "image": return (<style>{"body {background-image: url(\"" + settings.backgroundImage + "\"); }"}</style>)
@@ -63,6 +71,7 @@ function Body() {
</div>
<SettingsEditor tree={fullBookmarkTree!} isOpen={[settingsOpen, setSettingsOpen]}/>
{selectedBookmarkTree[0] && (<FolderBody data={selectedBookmarkTree[0]}/>)}
+ </ActiveDrag.Provider>
</Settings.Provider>
)
}
diff --git a/extension/src/components/Bookmark-backup.txt b/extension/src/components/Bookmark-backup.txt
deleted file mode 100644
index 4d1eb60..0000000
--- a/extension/src/components/Bookmark-backup.txt
+++ /dev/null
@@ -1,161 +0,0 @@
-import BookmarkTreeNode = browser.bookmarks.BookmarkTreeNode;
-import React, {SyntheticEvent, useEffect} from "react";
-import {getBrowser} from "../main.tsx";
-import {Settings} from "./Body.tsx";
-import react from "@vitejs/plugin-react";
-
-/**
- * A component for a single bookmark
- *
- * @param props.data The BookmarkTreeNode with the data for the bookmark
- */
-function Bookmark(props: {data: BookmarkTreeNode}) {
- 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 [dropRight, setDropRight] = React.useState(false);
- // let [dropLeft, setDropLeft] = React.useState(false);
- // let [dropCenter, setDropCenter] = React.useState(false);
-
- useEffect(() => {
- setBgColor([255, 0, 0])
- // faviconURL(props.data.url).then(o => o && setFavicon(o))
- faviconURL(props.data).then(r => {
- if (r) {
- setFavicon(r)
- setIconMode("small");
- }
- })
- }, []);
-
- // useEffect(() => {
- // console.log("signal received", dropCenter)
- // }, [dropCenter]);
-
- function handleImageLoad(e: SyntheticEvent<HTMLImageElement, Event>) {
- if (e.currentTarget.naturalWidth >= 75 || favicon!.startsWith("data:image/svg+xml")) {
- setIconMode("large")
- }
- }
-
- return(
- <div className={"bookmark"}>
- <a draggable={settings.editMode} href={props.data.url}
- // onDragStart={e => {
- // console.log("dragStart")
- // e.dataTransfer.dropEffect = "move";
- // e.dataTransfer.setData("bm-id", props.data.id);
- // }}
- >
- <div className={"icon-box " + (iconMode)}
- style={bgColor ? {"--icon-bg": `rgba(${bgColor[0]}, ${bgColor[1]}, ${bgColor[2]}, 0.2)`} as React.CSSProperties : undefined}>
- {favicon ? (
- <img alt="Bookmark icon"
- draggable={false}
- src={favicon}
- onLoad={handleImageLoad}
- />
- ) : (
- <span className={"letter"}>{new URL(props.data.url!).hostname.charAt(0)}</span>
- )}
-
- </div>
- <span>{props.data.title}</span>
- </a>
- {/*<div className={"drop-targets"}>*/}
- {/* <div*/}
- {/* className={"left"}*/}
- {/* onDragEnter={_ => setDropLeft(true)}*/}
- {/* onDragLeave={_ => setDropRight(false)}*/}
- {/* onDrop={e => getBrowser().bookmarks.move(e.dataTransfer.getData("bm-id"), {parentId: props.data.parentId, index: props.data.index})}*/}
- {/* style={dropLeft ? undefined : {visibility: "hidden"}}*/}
- {/* // hidden={!dropLeft}*/}
- {/* >*/}
- {/* <div/>*/}
- {/* </div>*/}
- {/* <div*/}
- {/* className={"right"}*/}
- {/* onDragEnter={_ => setDropLeft(true)}*/}
- {/* onDragLeave={_ => setDropRight(false)}*/}
- {/* onDrop={e => getBrowser().bookmarks.move(e.dataTransfer.getData("bm-id"), {parentId: props.data.parentId, index: (props.data.index! + 1)})}*/}
- {/* style={dropRight ? undefined : {visibility: "hidden"}}*/}
- {/* // hidden={!dropRight}*/}
- {/* >*/}
- {/* <div/>*/}
- {/* </div>*/}
- {/* <div*/}
- {/* className={"center"}*/}
- {/* onDragOver={e => {*/}
- {/* e.preventDefault()*/}
- {/* // console.log("dropped")*/}
- {/* }}*/}
- {/* onDragEnter={e => {*/}
- {/* e.preventDefault()*/}
- {/* setDropCenter(true)*/}
- {/* console.log("enter")*/}
- {/* }}*/}
- {/* onDragLeave={_ => {*/}
- {/* setDropCenter(false)*/}
- {/* console.log("exit")*/}
- {/* }}*/}
- {/* onDrop={e => {*/}
- {/* e.preventDefault();*/}
- {/* console.log("dropped")*/}
- {/* }}*/}
- {/* style={dropCenter ? undefined : {visibility: "hidden"}}*/}
- {/* // hidden={!dropCenter}*/}
- {/* >*/}
- {/* <span>+</span>*/}
- {/* </div>*/}
- {/*</div>*/}
- </div>
- );
-}
-
-/**
- * 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
-
- 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 hashColor(url:string) {
-// hashCode(String)
-// }
-//
-// function hashCode(str: string) {
-// let hash = 0;
-// for (let i = 0, len = str.length; i < len; i++) {
-// let chr = str.charCodeAt(i);
-// hash = (hash << 5) - hash + chr;
-// hash |= 0; // Convert to 32bit integer
-// }
-// return hash;
-// }
-
-export default Bookmark; \ No newline at end of file
diff --git a/extension/src/components/Bookmark.tsx b/extension/src/components/Bookmark.tsx
index d1c1756..fc73387 100644
--- a/extension/src/components/Bookmark.tsx
+++ b/extension/src/components/Bookmark.tsx
@@ -1,8 +1,9 @@
import BookmarkTreeNode = browser.bookmarks.BookmarkTreeNode;
import React, {SyntheticEvent, useEffect} from "react";
import {getBrowser} from "../main.tsx";
-import {Settings} from "./Body.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";
/**
@@ -15,6 +16,10 @@ function Bookmark(props: {data: BookmarkTreeNode}) {
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 [activeDrag, setActiveDrag] = React.useContext(ActiveDrag);
+ let [dropRight, setDropRight] = React.useState(false);
+ let [dropLeft, setDropLeft] = React.useState(false);
+ let [dropCenter, setDropCenter] = React.useState(false);
useEffect(() => {
faviconURL(props.data).then(r => {
@@ -33,9 +38,15 @@ function Bookmark(props: {data: BookmarkTreeNode}) {
}
}
+ function handleDrag(e: React.DragEvent<HTMLAnchorElement>) {
+ e.dataTransfer.dropEffect = "move";
+ e.dataTransfer.setData("bm-id", props.data.id);
+ setActiveDrag(true);
+ }
+
return(
<div className={"bookmark"}>
- <a draggable={settings.editMode} href={props.data.url}>
+ <a draggable={settings.editMode} href={props.data.url} onDrag={handleDrag} onDragEnd={_ => setActiveDrag(false)}>
<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": {
@@ -55,6 +66,83 @@ function Bookmark(props: {data: BookmarkTreeNode}) {
</div>
<span>{props.data.title}</span>
</a>
+ {activeDrag && (
+ <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(e.dataTransfer.getData("bm-id"), {
+ parentId: props.data.parentId,
+ index: props.data.index
+ })
+ console.log("dropped")
+ }}
+ 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(e.dataTransfer.getData("bm-id"), {
+ parentId: props.data.parentId,
+ index: (props.data.index! + 1)
+ })
+ e.preventDefault()
+ console.log("dropped right", e.dataTransfer.getData("bm-id"))
+ }}
+ 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();
+ console.log("dropped")
+ }}
+ style={dropCenter ? undefined : {opacity: 0}}
+ // hidden={!dropCenter}
+ >
+ <CreateFolderIcon/>
+ </div>
+ </div>
+ )}
</div>
);
}
diff --git a/extension/src/index.css b/extension/src/index.css
index a85aeaf..a14e0d6 100644
--- a/extension/src/index.css
+++ b/extension/src/index.css
@@ -191,7 +191,7 @@ a {
/* Drop targets */
.drop-targets {
- pointer-events: none;
+ /*pointer-events: none;*/
position: absolute;
top: 0;
/* bottom: 0; */
@@ -215,7 +215,7 @@ a {
align-items: center;
> div {
- background-color: aqua;
+ background-color: white;
height: 50%;
width: 4px;
}
@@ -231,7 +231,7 @@ a {
align-items: center;
> div {
- background-color: aqua;
+ background-color: white;
width: 4px;
height: 50%;
}
@@ -248,13 +248,22 @@ a {
align-items: center;
> span {
- color: aqua;
+ /*color: aqua;*/
font-size: 100px;
/* background-color: aqua; */
/* aspect-ratio: 1 / 1; */
/* height: 100px; */
font-family: monospace;
}
+
+ > svg {
+ background-color: #000000ba;
+ width: 65px;
+ height: 65px;
+ border-radius: 10px;
+ padding: 10px;
+ margin-bottom: 14px;
+ }
}