diff options
author | sowgro <tpoke.ferrari@gmail.com> | 2024-11-07 12:40:42 -0500 |
---|---|---|
committer | sowgro <tpoke.ferrari@gmail.com> | 2024-11-07 12:40:42 -0500 |
commit | 03b7ccaa5c152c8d7ed73374be8ad4d4d034845b (patch) | |
tree | 7ce20a5749018fbe82c85ee1bd7c2a5c5083eb4b /extension | |
parent | 958ab3cd5edad8b48a3fa49e0f151b3285abdbfa (diff) | |
download | bookmarks-home-03b7ccaa5c152c8d7ed73374be8ad4d4d034845b.tar.gz bookmarks-home-03b7ccaa5c152c8d7ed73374be8ad4d4d034845b.tar.bz2 bookmarks-home-03b7ccaa5c152c8d7ed73374be8ad4d4d034845b.zip |
Implement sorting and refactor
Diffstat (limited to 'extension')
-rw-r--r-- | extension/src/FolderBody.tsx | 20 | ||||
-rw-r--r-- | extension/src/Settings.ts | 2 | ||||
-rw-r--r-- | extension/src/components/Body.tsx (renamed from extension/src/Body.tsx) | 10 | ||||
-rw-r--r-- | extension/src/components/Bookmark.tsx (renamed from extension/src/Bookmark.tsx) | 12 | ||||
-rw-r--r-- | extension/src/components/FolderBody.tsx | 72 | ||||
-rw-r--r-- | extension/src/components/FolderButton.tsx (renamed from extension/src/FolderButton.tsx) | 11 | ||||
-rw-r--r-- | extension/src/components/RadioButtonGroup.tsx (renamed from extension/src/RadioButtonGroup.tsx) | 15 | ||||
-rw-r--r-- | extension/src/components/SettingsEditor.tsx (renamed from extension/src/SettingsEditor.tsx) | 13 | ||||
-rw-r--r-- | extension/src/index.css | 2 | ||||
-rw-r--r-- | extension/src/main.tsx | 2 | ||||
-rw-r--r-- | extension/tsconfig.app.tsbuildinfo | 2 |
11 files changed, 123 insertions, 38 deletions
diff --git a/extension/src/FolderBody.tsx b/extension/src/FolderBody.tsx deleted file mode 100644 index b013d97..0000000 --- a/extension/src/FolderBody.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import BookmarkTreeNode = browser.bookmarks.BookmarkTreeNode; -import Bookmark from "./Bookmark.tsx"; -import FolderButton from "./FolderButton.tsx"; - -function FolderBody (props: {data: BookmarkTreeNode}) { - return ( - <div className={"folderBody"}> - { - props.data.children && - props.data.children.map(child => - child.children - ? <FolderButton data={child} /> - : <Bookmark data={child} /> - ) - } - </div> - ) -} - -export default FolderBody;
\ No newline at end of file diff --git a/extension/src/Settings.ts b/extension/src/Settings.ts index 2f2c8e1..2bf490b 100644 --- a/extension/src/Settings.ts +++ b/extension/src/Settings.ts @@ -1,7 +1,7 @@ import {getBrowser} from "./main.tsx"; export interface ISettings { - sort: "from-bookmarks" | "alphabetical" | "frequency" | "recent" + sort: "from-bookmarks" | "alphabetical" | "recent" foldersFirst: boolean backgroundMode: "theme" | "color" | "image" backgroundColor: string diff --git a/extension/src/Body.tsx b/extension/src/components/Body.tsx index 2a46a67..193e68e 100644 --- a/extension/src/Body.tsx +++ b/extension/src/components/Body.tsx @@ -1,10 +1,10 @@ import React, {useEffect, useState} from "react"; import SettingsEditor from "./SettingsEditor.tsx"; -import imageUrl from "./assets/settings.svg" +import imageUrl from "../assets/settings.svg" import BookmarkTreeNode = browser.bookmarks.BookmarkTreeNode; import FolderBody from "./FolderBody.tsx"; -import {defaultSettings, ISettings, loadSettings, writeSettings} from "./Settings.ts"; -import {getBrowser} from "./main.tsx"; +import {defaultSettings, ISettings, loadSettings, writeSettings} from "../Settings.ts"; +import {getBrowser} from "../main.tsx"; export const Settings = React.createContext<[ISettings, (arg0: ISettings) => void]>([ @@ -12,6 +12,10 @@ export const Settings = () => {} ]); +/** + * 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); diff --git a/extension/src/Bookmark.tsx b/extension/src/components/Bookmark.tsx index 64c2811..75badd7 100644 --- a/extension/src/Bookmark.tsx +++ b/extension/src/components/Bookmark.tsx @@ -1,7 +1,11 @@ import BookmarkTreeNode = browser.bookmarks.BookmarkTreeNode; +/** + * A component for a single bookmark + * + * @param props.data The BookmarkTreeNode with the data for the bookmark + */ function Bookmark(props: {data: BookmarkTreeNode}) { - return( <a className="bookmark draggable" href={props.data.url}> <img alt="Bookmark icon" src={faviconURL(props.data.url)}></img> @@ -10,6 +14,12 @@ function Bookmark(props: {data: BookmarkTreeNode}) { ); } +/** + * Gets the icon for a bookmark + * + * @param u The URL of the link + * @return The URL of the icon + */ function faviconURL(u: string | undefined) { if (!u) return ""; u = new URL(u).hostname.toString(); diff --git a/extension/src/components/FolderBody.tsx b/extension/src/components/FolderBody.tsx new file mode 100644 index 0000000..a573a6e --- /dev/null +++ b/extension/src/components/FolderBody.tsx @@ -0,0 +1,72 @@ +import BookmarkTreeNode = browser.bookmarks.BookmarkTreeNode; +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) + + if (!props.data.children) return; + + let content = [...props.data.children].sort(getSortFunction(settings.sort)) + if (settings.foldersFirst) { + let [bookmarks, folders] = separateFolders(content) + content = folders.concat(bookmarks) + } + + return ( + <div className={"folderBody"}> + {content.map(child => + child.children + ? <FolderButton data={child} /> + : <Bookmark data={child} /> + )} + </div> + ) +} + +/** + * Gets the correct sort function based on the sort setting + * @param sort The sort setting state + * @return The corresponding sort function + */ +function getSortFunction(sort: "from-bookmarks" | "alphabetical" | "recent"): ((a:BookmarkTreeNode, b:BookmarkTreeNode) => number) | undefined { + switch (sort) { + case "alphabetical": return (a, b) => { + return a.title.localeCompare(b.title); + } + case "recent": return (a, b) => { + // @ts-ignore + return a.dateLastUsed - b.dateLastUsed + } + } +} + +/** + * Separate the folders and the bookmarks into two separate lists + * @param content THe bookmark list + * @returns tuple in the format [bookmarks, folders] + */ +function separateFolders(content: BookmarkTreeNode[]) { + let bookmarks = []; + let folders = []; + for (let bookmarkTreeNode of content) { + if (bookmarkTreeNode.children) { + folders.push(bookmarkTreeNode) + } else { + bookmarks.push(bookmarkTreeNode) + } + } + return [bookmarks, folders] +} + + + +export default FolderBody;
\ No newline at end of file diff --git a/extension/src/FolderButton.tsx b/extension/src/components/FolderButton.tsx index e74cdbf..2d7cc9e 100644 --- a/extension/src/FolderButton.tsx +++ b/extension/src/components/FolderButton.tsx @@ -1,11 +1,16 @@ import BookmarkTreeNode = browser.bookmarks.BookmarkTreeNode; import FolderBody from "./FolderBody.tsx"; -import folderIcon from "./assets/folder.svg" -import folderIconOpen from "./assets/folder_open.svg" +import folderIcon from "../assets/folder.svg" +import folderIconOpen from "../assets/folder_open.svg" import {useState} from "react"; +/** + * 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}) { - const [folderOpen, setFolderOpen] = useState(false); return( diff --git a/extension/src/RadioButtonGroup.tsx b/extension/src/components/RadioButtonGroup.tsx index da1b521..297800d 100644 --- a/extension/src/RadioButtonGroup.tsx +++ b/extension/src/components/RadioButtonGroup.tsx @@ -1,12 +1,13 @@ import React, {ReactElement, useEffect, useId, useState} from "react"; -interface RadioProps { - children: ReactElement<HTMLOptionElement>[], - value: any, - onChange?: (arg0: any) => void -} - -function RadioButtonGroup(props: RadioProps) { +/** + * A component for a group of radio buttons where only one can be selected + * + * @param props.children html <option> elements for each radio option + * @param props.value The option which is selected + * @param props.onChange A function that will be called when the selected option changes + */ +function RadioButtonGroup(props: { children: ReactElement<HTMLOptionElement>[], value: any, onChange?: (arg0: any) => void }) { const [selected, setSelected] = useState(props.value); useEffect(() => { setSelected(props.value); diff --git a/extension/src/SettingsEditor.tsx b/extension/src/components/SettingsEditor.tsx index ca0feeb..abf9888 100644 --- a/extension/src/SettingsEditor.tsx +++ b/extension/src/components/SettingsEditor.tsx @@ -1,9 +1,15 @@ import RadioButtonGroup from "./RadioButtonGroup.tsx"; import React, {useContext} from "react"; -import imageUrl from "./assets/close.svg" +import imageUrl from "../assets/close.svg" import BookmarkTreeNode = browser.bookmarks.BookmarkTreeNode; import {Settings} from "./Body.tsx"; +/** + * A component for the settings sidebar + * + * @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>>]}) { const [settings, setSettings] = useContext(Settings) const [open, setOpen] = props.isOpen; @@ -76,6 +82,11 @@ function SettingsEditor(props: {tree: BookmarkTreeNode[], isOpen: [boolean, Rea ) } +/** + * Walks the tree and creates a list of the folders + * + * @param tree The full tree to walk through + */ function getFoldersFromTree(tree: BookmarkTreeNode[]) { let folderList: BookmarkTreeNode[] = []; rec(tree); diff --git a/extension/src/index.css b/extension/src/index.css index b59ee20..64f3bf2 100644 --- a/extension/src/index.css +++ b/extension/src/index.css @@ -73,6 +73,8 @@ body > .folderBody { border-style: none; position: relative; animation: none; + max-height: 100%; + overflow: auto; } /* Bookmark */ diff --git a/extension/src/main.tsx b/extension/src/main.tsx index 4776db3..d1fa6c2 100644 --- a/extension/src/main.tsx +++ b/extension/src/main.tsx @@ -1,6 +1,6 @@ import { createRoot } from 'react-dom/client' import './index.css' -import Body from "./Body.tsx"; +import Body from "./components/Body.tsx"; export function getBrowser() { if (typeof browser === "undefined") { diff --git a/extension/tsconfig.app.tsbuildinfo b/extension/tsconfig.app.tsbuildinfo index 2c29adc..62cc1da 100644 --- a/extension/tsconfig.app.tsbuildinfo +++ b/extension/tsconfig.app.tsbuildinfo @@ -1 +1 @@ -{"root":["./src/Body.tsx","./src/Bookmark.tsx","./src/FolderBody.tsx","./src/FolderButton.tsx","./src/RadioButtonGroup.tsx","./src/Settings.ts","./src/SettingsEditor.tsx","./src/main.tsx","./src/vite-env.d.ts"],"version":"5.6.2"}
\ No newline at end of file +{"root":["./src/Settings.ts","./src/main.tsx","./src/vite-env.d.ts","./src/components/Body.tsx","./src/components/Bookmark.tsx","./src/components/FolderBody.tsx","./src/components/FolderButton.tsx","./src/components/RadioButtonGroup.tsx","./src/components/SettingsEditor.tsx"],"version":"5.6.2"}
\ No newline at end of file |