aboutsummaryrefslogtreecommitdiff
path: root/extension
diff options
context:
space:
mode:
authorsowgro <tpoke.ferrari@gmail.com>2024-11-07 12:40:42 -0500
committersowgro <tpoke.ferrari@gmail.com>2024-11-07 12:40:42 -0500
commit03b7ccaa5c152c8d7ed73374be8ad4d4d034845b (patch)
tree7ce20a5749018fbe82c85ee1bd7c2a5c5083eb4b /extension
parent958ab3cd5edad8b48a3fa49e0f151b3285abdbfa (diff)
downloadbookmarks-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.tsx20
-rw-r--r--extension/src/Settings.ts2
-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.tsx72
-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.css2
-rw-r--r--extension/src/main.tsx2
-rw-r--r--extension/tsconfig.app.tsbuildinfo2
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