aboutsummaryrefslogtreecommitdiff
path: root/extension/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'extension/src/components')
-rw-r--r--extension/src/components/BMEditor.tsx55
-rw-r--r--extension/src/components/Body.tsx42
-rw-r--r--extension/src/components/Bookmark.tsx139
-rw-r--r--extension/src/components/ContextMenu.tsx51
-rw-r--r--extension/src/components/FolderBody.tsx46
-rw-r--r--extension/src/components/FolderButton.tsx93
-rw-r--r--extension/src/components/SettingsEditor.tsx36
7 files changed, 348 insertions, 114 deletions
diff --git a/extension/src/components/BMEditor.tsx b/extension/src/components/BMEditor.tsx
new file mode 100644
index 0000000..1ac72c6
--- /dev/null
+++ b/extension/src/components/BMEditor.tsx
@@ -0,0 +1,55 @@
+import React, {useContext, useEffect, useState} from "react";
+import CloseIcon from "../assets/close.svg?react"
+import {ActiveEdit} from "./Body.tsx";
+import {getBrowser} from "../main.tsx";
+import RadioButtonGroup from "./RadioButtonGroup.tsx";
+
+
+function BMEditor() {
+ const [activeEdit, setActiveEdit] = useContext(ActiveEdit);
+
+ const [iconOptions, setIconOptions] = useState<string[]>([]);
+
+ useEffect(() => {
+ if (!activeEdit) return;
+ getBrowser().storage.local.get("icon-aval-"+activeEdit.id).then( r => {
+ setIconOptions(r["icon-aval-"+activeEdit.id]);
+ });
+ }, [activeEdit]);
+
+ if (!activeEdit) return;
+
+ let isFolder = activeEdit && activeEdit.children && activeEdit.children.length > 0;
+ return (
+ <div id="settings-menu" className={activeEdit ? "open" : "closed"}>
+ <button id="settings-close" onClick={_ => setActiveEdit(null)}>
+ <CloseIcon/>
+ </button>
+
+ <h1>Edit {isFolder ? "Folder" : "Bookmark"}</h1>
+
+ <h3>Name</h3>
+ <input type={"text"} defaultValue={activeEdit?.title} onChange={e => {
+ getBrowser().bookmarks.update(activeEdit!.id, {title: e.target.value})
+ }}/>
+
+ {!isFolder && (<>
+ <h3>URL</h3>
+ <input type={"url"} defaultValue={activeEdit?.url} onChange={e => {
+ getBrowser().bookmarks.update(activeEdit!.id, {url: e.target.value})
+ }}/>
+ </>)}
+
+ <h3>Icon</h3>
+ {/*<RadioButtonGroup value={undefined}>*/}
+ {iconOptions && iconOptions.map(s =>
+ // <option value={s}>
+ <img src={s}/>
+ // </option>
+ )}
+ {/*</RadioButtonGroup>*/}
+ </div>
+ );
+}
+
+export default BMEditor; \ No newline at end of file
diff --git a/extension/src/components/Body.tsx b/extension/src/components/Body.tsx
index 70f8fce..e4c371b 100644
--- a/extension/src/components/Body.tsx
+++ b/extension/src/components/Body.tsx
@@ -1,11 +1,13 @@
import React, {useEffect, useState} from "react";
import SettingsEditor from "./SettingsEditor.tsx";
import SettingsIcon from "../assets/settings.svg?react";
-import EditIcon from "../assets/move.svg?react";
+import EditIcon from "../assets/edit.svg?react";
import BookmarkTreeNode = browser.bookmarks.BookmarkTreeNode;
import FolderBody from "./FolderBody.tsx";
import {defaultSettings, ISettings, loadSettings, writeSettings} from "../Settings.ts";
import {getBrowser} from "../main.tsx";
+import BMEditor from "./BMEditor.tsx";
+import EditOffIcon from "../assets/edit_off.svg?react";
export const Settings =
React.createContext<[ISettings, (arg0: ISettings) => void]>([
@@ -19,58 +21,58 @@ export const ActiveDrag =
() => {}
])
+export const ActiveEdit =
+ React.createContext<[BookmarkTreeNode | null, (arg0: BookmarkTreeNode | null) => void]>([
+ null,
+ () => {}
+ ])
+
/**
* A component for the full body of the application
* Also stores the trees and settings
*/
function Body() {
const [settingsOpen, setSettingsOpen] = useState(false);
- const [settings, setSettings] = useState<ISettings>(defaultSettings);
- const [selectedBookmarkTree, setSelectedBookmarkTree] = useState<BookmarkTreeNode[]>([])
- const [fullBookmarkTree, setFullBookmarkTree] = useState<BookmarkTreeNode[] | null>([])
+ const [settings, setSettings] = useState<ISettings | undefined>(undefined);
const [activeDrag, setActiveDrag] = useState<BookmarkTreeNode | null>(null);
+ const [activeEdit, setActiveEdit] = useState<BookmarkTreeNode | null>(null);
useEffect(() => {
loadSettings().then(r => {
setSettings(r);
})
- getBrowser().bookmarks.getTree().then(t => {
- setFullBookmarkTree(t);
- })
}, [])
useEffect(() => {
- writeSettings(settings);
- if (settings.rootFolder) {
- getBrowser().bookmarks.getSubTree(settings.rootFolder).then(t => {
- setSelectedBookmarkTree(t);
- });
- } else {
- getBrowser().bookmarks.getTree().then(t => {
- setSelectedBookmarkTree(t);
- })
+ if (settings) {
+ writeSettings(settings);
}
}, [settings]);
+ if (!settings) return;
+
return (
<Settings.Provider value={[settings!, setSettings]}>
<ActiveDrag.Provider value={[activeDrag, setActiveDrag]}>
+ <ActiveEdit.Provider value={[activeEdit, setActiveEdit]}>
{(() => {switch (settings.backgroundMode) {
case "color": return (<style>{"body {background-color: " + settings.backgroundColor + "; }"}</style>)
case "image": return (<style>{"body {background-image: url(\"" + settings.backgroundImage + "\"); }"}</style>)
}})()}
<style>{"body > .folderBody, a {color: " + settings.foregroundColor + "; }"}</style>
<div id={"action-area"}>
- {settings.editMode && <span>Move mode: Drag bookmarks to change order</span>}
+ {settings.editMode && <span>Edit mode: Drag bookmarks to change order</span>}
<button onClick={_ => setSettings({...settings, editMode: !settings.editMode})}>
- <EditIcon className={settings.editMode? "enabled" : ""}/>
+ {settings.editMode ? <EditIcon/> : <EditOffIcon/>}
</button>
<button onClick={_ => setSettingsOpen(!settingsOpen)}>
<SettingsIcon/>
</button>
</div>
- <SettingsEditor tree={fullBookmarkTree!} isOpen={[settingsOpen, setSettingsOpen]}/>
- {selectedBookmarkTree[0] && (<FolderBody data={selectedBookmarkTree[0]}/>)}
+ <SettingsEditor isOpen={[settingsOpen, setSettingsOpen]}/>
+ <BMEditor/>
+ <FolderBody id={settings.rootFolder || '0'}/>
+ </ActiveEdit.Provider>
</ActiveDrag.Provider>
</Settings.Provider>
)
diff --git a/extension/src/components/Bookmark.tsx b/extension/src/components/Bookmark.tsx
index 2442e02..e378b0f 100644
--- a/extension/src/components/Bookmark.tsx
+++ b/extension/src/components/Bookmark.tsx
@@ -1,33 +1,63 @@
import BookmarkTreeNode = browser.bookmarks.BookmarkTreeNode;
-import React, {SyntheticEvent, useEffect} from "react";
+import React, {SyntheticEvent, useContext, useEffect, useState} from "react";
import {getBrowser} from "../main.tsx";
-import {ActiveDrag, Settings} from "./Body.tsx";
+import {ActiveDrag, ActiveEdit, Settings} from "./Body.tsx";
import ColorThief from 'colorthief'
import DropTargets from "./DropTargets.tsx";
+import ContextMenu from "./ContextMenu.tsx";
/**
* A component for a single bookmark
- *
- * @param props.data The BookmarkTreeNode with the data for the bookmark
*/
-function Bookmark(props: {data: BookmarkTreeNode}) {
- let [settings, _] = React.useContext(Settings);
+function Bookmark(props: {id: string}) {
+ let [settings] = React.useContext(Settings);
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>()
+ const [renameMode, setRenameMode] = useState(false);
+
+ useEffect(() => {
+ getBrowser().bookmarks.get(props.id).then(r => {
+ setBmData(r[0]);
+ })
+ getBrowser().bookmarks.onChanged.addListener((id: string) => {
+ if (id !== props.id) return;
+ getBrowser().bookmarks.get(props.id).then(r => {
+ setBmData(r[0]);
+ })
+ })
+ }, []);
useEffect(() => {
- faviconURL(props.data).then(r => {
+ if (!bmData) return;
+ faviconURL(bmData).then(r => {
if (r) {
setFavicon(r)
setIconMode("small");
}
})
- }, []);
+ }, [bmData]);
+
+ useEffect(() => {
+ let evl = () => {
+ console.log("clicked")
+ renameMode && setRenameMode(false);
+ console.log("evl unregistered")
+ document.body.removeEventListener('click', evl);
+ }
+ if (renameMode) {
+ console.log("evl registered")
+ document.body.addEventListener('click', evl);
+ }
+ }, [renameMode]);
+
+ if (!bmData) return;
function handleImageLoad(e: SyntheticEvent<HTMLImageElement, Event>) {
if (e.currentTarget.naturalWidth >= 75 || favicon!.startsWith("data:image/svg+xml")) {
@@ -39,71 +69,92 @@ function Bookmark(props: {data: BookmarkTreeNode}) {
}
// Dragging
- function handleDrag() {
- setActiveDrag(props.data);
- }
+ const handleDrag = () => {
+ setActiveDrag(bmData);
+ };
- function handleDragEnd() {
+ const handleDragEnd = () => {
setActiveDrag(null);
- }
+ };
// Dropping
- function handleDropLeft() {
+ const handleDropLeft = () => {
console.log("drop left bm")
getBrowser().bookmarks.move(activeDrag!.id, {
- parentId: props.data.parentId,
- index: props.data.index
+ parentId: bmData.parentId,
+ index: bmData.index
})
location.reload()
- }
+ };
- function handleDropRight() {
+ const handleDropRight = () => {
console.log("drop right bm")
getBrowser().bookmarks.move(activeDrag!.id, {
- parentId: props.data.parentId,
- index: (props.data.index! + 1)
+ parentId: bmData.parentId,
+ index: (bmData.index! + 1)
})
location.reload();
- }
+ };
- function handleDropCenter() {
+ const handleDropCenter = () => {
console.log("drop center bm")
chrome.bookmarks.create({
// type: "folder",
- parentId: props.data.parentId,
- index: props.data.index,
+ parentId: bmData.parentId,
+ index: bmData.index,
title: "New Folder"
}).then(r => {
- getBrowser().bookmarks.move(props.data.id, {parentId: r.id});
+ getBrowser().bookmarks.move(bmData.id, {parentId: r.id});
getBrowser().bookmarks.move(activeDrag!.id, {parentId: r.id});
location.reload()
})
- }
+ };
+
+ const handleDelete = () => {
+ getBrowser().bookmarks.remove(bmData.id);
+ location.reload();
+ };
+
+ const handleEdit = (e: React.MouseEvent<HTMLButtonElement>) => {
+ e.preventDefault()
+ setRenameMode(true)
+ // setActiveEdit(bmData);
+ };
return(
<div className={"bookmark"}>
- <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": {
- let url = new URL(props.data.url!);
- if (bgColorPriority < 1) {
- setBgColor(hashStringToColor(url.hostname));
- setBgColorPriority(1);
+ <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!}/>)
}
- 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>
- <span>{props.data.title}</span>
+ {renameMode
+ ? <input type={'text'}
+ defaultValue={bmData.title}
+ onChange={e => {
+ getBrowser().bookmarks.update(props.id, {title: e.target.value})
+ }}/>
+ : <span>{bmData.title}</span>}
</a>
- {activeDrag && activeDrag !== props.data &&
+ {settings.editMode && <ContextMenu onEdit={handleEdit} onDelete={handleDelete}/>}
+ {activeDrag && activeDrag !== bmData &&
<DropTargets onDropLeft={handleDropLeft} onDropRight={handleDropRight} onDropCenter={handleDropCenter}/>}
</div>
);
diff --git a/extension/src/components/ContextMenu.tsx b/extension/src/components/ContextMenu.tsx
new file mode 100644
index 0000000..058e9ba
--- /dev/null
+++ b/extension/src/components/ContextMenu.tsx
@@ -0,0 +1,51 @@
+import DeleteIcon from "../assets/delete.svg?react";
+import EditIcon from "../assets/edit.svg?react";
+import DragIcon from "../assets/drag.svg?react";
+import MoreIcon from "../assets/more.svg?react";
+import React, {useEffect, useState} from "react";
+
+function ContextMenu(props: {onEdit: (e: React.MouseEvent<HTMLButtonElement>) => void, onDelete: (e: React.MouseEvent<HTMLButtonElement>) => void}) {
+ const [open, setOpen] = useState(false)
+
+ useEffect(() => {
+ let evl = () => {
+ console.log("clicked")
+ open && setOpen(false);
+ console.log("evl unregistered")
+ document.body.removeEventListener('click', evl);
+ }
+ if (open) {
+ console.log("evl registered")
+ document.body.addEventListener('click', evl);
+ }
+ }, [open]);
+
+ return (
+ <div className={"overflow"}>
+ <button onClick={e => {
+ e.preventDefault();
+ setOpen(!open);
+ }}>
+ <MoreIcon/>
+ </button>
+ {open && <div className={"context-menu"}>
+ <button onClick={e => {
+ setOpen(false);
+ props.onEdit(e);
+ }}>
+ <EditIcon />
+ Edit
+ </button>
+ <button className={"del"} onClick={e => {
+ setOpen(false);
+ props.onDelete(e);
+ }}>
+ <DeleteIcon/>
+ Delete
+ </button>
+ </div>}
+ </div>
+ )
+}
+
+export default ContextMenu; \ No newline at end of file
diff --git a/extension/src/components/FolderBody.tsx b/extension/src/components/FolderBody.tsx
index a573a6e..e75fcc7 100644
--- a/extension/src/components/FolderBody.tsx
+++ b/extension/src/components/FolderBody.tsx
@@ -1,32 +1,48 @@
import BookmarkTreeNode = browser.bookmarks.BookmarkTreeNode;
+import {ReactElement, useContext, useEffect, useState} from "react";
+import {Settings} from "./Body.tsx";
+import {getBrowser} from "../main.tsx";
import Bookmark from "./Bookmark.tsx";
import FolderButton from "./FolderButton.tsx";
-import {useContext} from "react";
-import {Settings} from "./Body.tsx";
/**
* A component that displays the contents of a bookmark folder
- *
- * @param props.data The BookmarkTreeNode with data for the folder
- * @constructor
*/
-function FolderBody (props: {data: BookmarkTreeNode}) {
- const [settings, _] = useContext(Settings)
+function FolderBody (props: {id: string}) {
+
+ const [settings, ] = useContext(Settings)
- if (!props.data.children) return;
+ const [children, setChildren] = useState<BookmarkTreeNode[]>([])
- let content = [...props.data.children].sort(getSortFunction(settings.sort))
- if (settings.foldersFirst) {
- let [bookmarks, folders] = separateFolders(content)
- content = folders.concat(bookmarks)
+ const updateBookmarks = () => {
+ getBrowser().bookmarks.getSubTree(props.id).then(r => {
+ let content = [...r[0].children!].sort(getSortFunction(settings.sort))
+ if (settings.foldersFirst) {
+ let [bookmarks, folders] = separateFolders(content)
+ content = folders.concat(bookmarks)
+ }
+ setChildren(content);
+ })
}
+ useEffect(() => {
+ updateBookmarks();
+ // getBrowser().bookmarks.onRemoved.addListener((id: string, moveInfo) => {
+ // if (moveInfo.parentId !== props.id) return;
+ // updateBookmarks();
+ // })
+ }, []);
+
+ useEffect(() => {
+ updateBookmarks();
+ }, [settings]);
+
return (
<div className={"folderBody"}>
- {content.map(child =>
+ {children.map(child =>
child.children
- ? <FolderButton data={child} />
- : <Bookmark data={child} />
+ ? <FolderButton id={child.id} />
+ : <Bookmark id={child.id} />
)}
</div>
)
diff --git a/extension/src/components/FolderButton.tsx b/extension/src/components/FolderButton.tsx
index eff035e..374982a 100644
--- a/extension/src/components/FolderButton.tsx
+++ b/extension/src/components/FolderButton.tsx
@@ -2,78 +2,111 @@ 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 React, {useState} from "react";
+import React, {useEffect, useState} from "react";
import DropTargets from "./DropTargets.tsx";
-import {ActiveDrag, Settings} from "./Body.tsx";
+import {ActiveDrag, ActiveEdit, Settings} from "./Body.tsx";
import {getBrowser} from "../main.tsx";
+import ContextMenu from "./ContextMenu.tsx";
/**
* A component for the button used to open a bookmark folder.
* This is themed the same as a bookmark
- *
- * @param props.data The BookmarkTreeNode containing the data of the folder
*/
-function FolderButton(props: {data: BookmarkTreeNode}) {
- let [settings, _] = React.useContext(Settings);
+function FolderButton(props: {id: string}) {
+ let [settings, ] = React.useContext(Settings);
let [activeDrag, setActiveDrag] = React.useContext(ActiveDrag);
+ let [, setActiveEdit] = React.useContext(ActiveEdit)
- const [folderOpen, setFolderOpen] = useState(false);
+ const [folderOpen, setFolderOpen] = useState<undefined | boolean>(undefined);
+ const [bmData, setBmData] = useState<BookmarkTreeNode | undefined>()
+
+ useEffect(() => {
+ console.log(props.id+" state="+folderOpen)
+ getBrowser().storage.local.set({['keepopen-'+props.id]: folderOpen})
+ }, [folderOpen]);
+
+ useEffect(() => {
+ if (settings.keepFoldersOpen) {
+ getBrowser().storage.local.get('keepopen-' + props.id).then(r => {
+ setFolderOpen(r['keepopen-' + props.id] == true);
+ })
+ } else {
+ setFolderOpen(false);
+ }
+ getBrowser().bookmarks.get(props.id).then(r => {
+ setBmData(r[0])
+ })
+ }, []);
+
+ if (!bmData) return;
// Dragging
- function handleDragStart(e: React.DragEvent<HTMLAnchorElement>) {
+ const handleDragStart = (e: React.DragEvent<HTMLAnchorElement>) => {
e.dataTransfer.setData("sowgro", "placeholder")
- }
+ };
- function handleDrag() {
- setActiveDrag(props.data);
- }
+ const handleDrag = () => {
+ setActiveDrag(bmData);
+ };
- function handleDragEnd() {
+ const handleDragEnd = () => {
console.log("drop end")
setActiveDrag(null);
- }
+ };
// Dropping
- function handleDropLeft() {
+ const handleDropLeft = () => {
console.log("drop left folder")
getBrowser().bookmarks.move(activeDrag!.id, {
- parentId: props.data.parentId,
- index: props.data.index
+ parentId: bmData.parentId,
+ index: bmData.index
})
location.reload()
- }
+ };
- function handleDropRight() {
+ const handleDropRight = () => {
console.log("drop right folder")
getBrowser().bookmarks.move(activeDrag!.id, {
- parentId: props.data.parentId,
- index: (props.data.index! + 1)
+ parentId: bmData.parentId,
+ index: (bmData.index! + 1)
})
location.reload();
- }
+ };
- function handleDropCenter() {
+ const handleDropCenter = () => {
console.log("drop center folder")
getBrowser().bookmarks.move(activeDrag!.id, {
- parentId: props.data.id
+ parentId: bmData.id
});
location.reload()
- }
+ };
+
+ const handleDelete = () => {
+ getBrowser().bookmarks.removeTree(bmData.id);
+ location.reload();
+ };
+
+ const handleEdit = (e: React.MouseEvent<HTMLButtonElement>) => {
+ e.preventDefault();
+ setActiveEdit(bmData);
+ };
return(
<>
<div className={"bookmark"}>
- <a onClick={() => setFolderOpen(!folderOpen)} draggable={settings.editMode} onDrag={handleDrag} onDragEnd={handleDragEnd}>
+ <a onClick={() => setFolderOpen(!folderOpen)} draggable={settings.editMode} onDrag={handleDrag}
+ onDragStart={handleDragStart} onDragEnd={handleDragEnd}>
<div className="icon-box">
{folderOpen ? <FolderIconOpen/> : <FolderIcon/>}
</div>
- <span>{props.data.title}</span>
+ <span>{bmData.title}</span>
</a>
- {activeDrag && activeDrag !== props.data &&
+ {settings.editMode && <ContextMenu onEdit={handleEdit} onDelete={handleDelete}/>}
+ {activeDrag && activeDrag !== bmData &&
<DropTargets onDropLeft={handleDropLeft} onDropRight={handleDropRight} onDropCenter={handleDropCenter}/>}
</div>
- {folderOpen && props.data.children && props.data.children.length > 0 &&
- <FolderBody data={props.data}/>}
+ {folderOpen && /*bmData.children && bmData.children.length > 0 &&*/
+ <FolderBody id={bmData.id}/>}
</>
);
}
diff --git a/extension/src/components/SettingsEditor.tsx b/extension/src/components/SettingsEditor.tsx
index d11158e..2ad5104 100644
--- a/extension/src/components/SettingsEditor.tsx
+++ b/extension/src/components/SettingsEditor.tsx
@@ -1,5 +1,5 @@
import RadioButtonGroup from "./RadioButtonGroup.tsx";
-import React, {useContext} from "react";
+import React, {useContext, useEffect, useState} from "react";
import CloseIcon from "../assets/close.svg?react"
import BookmarkTreeNode = browser.bookmarks.BookmarkTreeNode;
import {Settings} from "./Body.tsx";
@@ -11,9 +11,16 @@ import {getBrowser} from "../main.tsx";
* @param props.tree The full bookmarks tree (for use in the root selector)
* @param props.isOpen State for weather the menu is open
*/
-function SettingsEditor(props: {tree: BookmarkTreeNode[], isOpen: [boolean, React.Dispatch<React.SetStateAction<boolean>>]}) {
+function SettingsEditor(props: {isOpen: [boolean, React.Dispatch<React.SetStateAction<boolean>>]}) {
const [settings, setSettings] = useContext(Settings)
const [open, setOpen] = props.isOpen;
+ const [folders, setFolders] = useState<BookmarkTreeNode[] | undefined>()
+
+ useEffect(() => {
+ getFoldersFromTree().then(r => setFolders(r));
+ }, []);
+
+ if (!folders) return;
return (
<div id="settings-menu" className={open ? "open" : "closed"}>
@@ -74,13 +81,31 @@ function SettingsEditor(props: {tree: BookmarkTreeNode[], isOpen: [boolean, Rea
<h3>Root folder</h3>
<select value={settings.rootFolder!}
onChange={e => setSettings({...settings, rootFolder: e.target.value})}>
- {getFoldersFromTree(props.tree).map(i =>
+ {folders.map(i =>
<option value={i.id}>{i.title ? i.title : "Untitled (id:" + i.id + ")"}</option>
)}
</select>
<h3>Icon Cache</h3>
- <button onClick={_ => getBrowser().storage.local.clear()}>Clear Icon Cache</button>
+ <button className={"default"} onClick={_ => getBrowser().storage.local.clear()}>Clear Icon Cache</button>
+
+ {/*<h3>Editing</h3>*/}
+ {/*<label>*/}
+ {/* <input type={"checkbox"}*/}
+ {/* checked={!settings.editMode}*/}
+ {/* onChange={e => setSettings({...settings, editMode: !e.target.checked})}*/}
+ {/* />*/}
+ {/* Prevent editing of bookmarks*/}
+ {/*</label>*/}
+
+ <h3>Open Folders</h3>
+ <label>
+ <input type={"checkbox"}
+ checked={settings.keepFoldersOpen}
+ onChange={e => setSettings({...settings, keepFoldersOpen: e.target.checked})}
+ />
+ Keep folders open
+ </label>
</div>
)
@@ -91,7 +116,8 @@ function SettingsEditor(props: {tree: BookmarkTreeNode[], isOpen: [boolean, Rea
*
* @param tree The full tree to walk through
*/
-function getFoldersFromTree(tree: BookmarkTreeNode[]) {
+async function getFoldersFromTree() {
+ let tree = await getBrowser().bookmarks.getTree();
let folderList: BookmarkTreeNode[] = [];
rec(tree);