aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMohamedBassem <me@mbassem.com>2024-02-12 20:50:12 +0000
committerMohamedBassem <me@mbassem.com>2024-02-12 20:50:12 +0000
commit6e6d2c3cbc860d0024e9631b01eeef55b47933a5 (patch)
tree33cf443237fcc757f8f22436f861652d369d6330
parente2bdccd483677cd60a92f4b0308bd2e4a0c02bfb (diff)
downloadkarakeep-6e6d2c3cbc860d0024e9631b01eeef55b47933a5.tar.zst
WIP: Implement saving page functionality in browser extension
-rw-r--r--packages/browser-extension/.eslintrc.cjs18
-rw-r--r--packages/browser-extension/manifest.json5
-rw-r--r--packages/browser-extension/package.json9
-rw-r--r--packages/browser-extension/src/App.tsx29
-rw-r--r--packages/browser-extension/src/SavePage.tsx40
-rw-r--r--packages/browser-extension/src/SettingsPage.tsx53
-rw-r--r--packages/browser-extension/src/main.tsx33
-rw-r--r--packages/browser-extension/src/settings.ts13
-rw-r--r--yarn.lock140
9 files changed, 309 insertions, 31 deletions
diff --git a/packages/browser-extension/.eslintrc.cjs b/packages/browser-extension/.eslintrc.cjs
deleted file mode 100644
index d6c95379..00000000
--- a/packages/browser-extension/.eslintrc.cjs
+++ /dev/null
@@ -1,18 +0,0 @@
-module.exports = {
- root: true,
- env: { browser: true, es2020: true },
- extends: [
- 'eslint:recommended',
- 'plugin:@typescript-eslint/recommended',
- 'plugin:react-hooks/recommended',
- ],
- ignorePatterns: ['dist', '.eslintrc.cjs'],
- parser: '@typescript-eslint/parser',
- plugins: ['react-refresh'],
- rules: {
- 'react-refresh/only-export-components': [
- 'warn',
- { allowConstantExport: true },
- ],
- },
-}
diff --git a/packages/browser-extension/manifest.json b/packages/browser-extension/manifest.json
index 0eb8879d..bf3293ca 100644
--- a/packages/browser-extension/manifest.json
+++ b/packages/browser-extension/manifest.json
@@ -5,5 +5,8 @@
"version": "1.0",
"action": {
"default_popup": "index.html"
- }
+ },
+ "permissions": [
+ "storage"
+ ]
}
diff --git a/packages/browser-extension/package.json b/packages/browser-extension/package.json
index a4688cd6..3c8a4e8d 100644
--- a/packages/browser-extension/package.json
+++ b/packages/browser-extension/package.json
@@ -10,8 +10,15 @@
"preview": "vite preview"
},
"dependencies": {
+ "@types/chrome": "^0.0.260",
+ "localforage": "^1.10.0",
+ "match-sorter": "^6.3.4",
"react": "^18.2.0",
- "react-dom": "^18.2.0"
+ "react-dom": "^18.2.0",
+ "react-router-dom": "^6.22.0",
+ "sort-by": "^1.2.0",
+ "use-chrome-storage": "^1.2.2",
+ "zod": "^3.22.4"
},
"devDependencies": {
"@crxjs/vite-plugin": "^1.0.14",
diff --git a/packages/browser-extension/src/App.tsx b/packages/browser-extension/src/App.tsx
index 7daedc37..21fec92f 100644
--- a/packages/browser-extension/src/App.tsx
+++ b/packages/browser-extension/src/App.tsx
@@ -1,8 +1,31 @@
+import { redirect } from "react-router-dom";
+import SavePage from "./SavePage";
+import usePluginSettings from "./settings";
+import { useNavigate } from "react-router-dom";
+
function App() {
+ const navigate = useNavigate();
+ const [settings, _1, _2, _3, isInit] = usePluginSettings();
+
+ if (!isInit) {
+ return <div className="p-4">Loading ... </div>;
+ }
+
+ if (!settings.apiKey || !settings.address) {
+ navigate("/settings");
+ return;
+ }
+
return (
- <>
- <div className="text-3xl">Test</div>
- </>
+ <div className="flex flex-col space-y-2">
+ <SavePage settings={settings} />
+ <hr />
+ <div className="flex justify-end">
+ <button className="w-2/6" onClick={() => navigate("/settings")}>
+ Settings
+ </button>
+ </div>
+ </div>
);
}
diff --git a/packages/browser-extension/src/SavePage.tsx b/packages/browser-extension/src/SavePage.tsx
new file mode 100644
index 00000000..c66cc0ad
--- /dev/null
+++ b/packages/browser-extension/src/SavePage.tsx
@@ -0,0 +1,40 @@
+import { useEffect, useState } from "react";
+import { Settings } from "./settings";
+
+export default function SavePage({ settings }: { settings: Settings }) {
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState<string | undefined>(undefined);
+
+ async function runFetch() {
+ const resp = await fetch(
+ `${settings.address}/api/trpc/bookmarks.bookmarkLink`,
+ {
+ method: "POST",
+ },
+ );
+
+ if (!resp.ok) {
+ setError("Something went wrong: " + (await resp.json()));
+ }
+ setLoading(false);
+ }
+
+ useEffect(() => {
+ runFetch();
+ }, []);
+
+ if (loading) {
+ return <div>Loading ...</div>;
+ }
+
+ if (error) {
+ return <div className="text-red-500">{error} ...</div>;
+ }
+
+ return (
+ <div>
+ SAVED!
+ <button onClick={runFetch}> Reload </button>
+ </div>
+ );
+}
diff --git a/packages/browser-extension/src/SettingsPage.tsx b/packages/browser-extension/src/SettingsPage.tsx
new file mode 100644
index 00000000..bae870ac
--- /dev/null
+++ b/packages/browser-extension/src/SettingsPage.tsx
@@ -0,0 +1,53 @@
+import { useRef } from "react";
+import usePluginSettings from "./settings";
+import { useNavigate } from "react-router-dom";
+
+export default function SettingsPage() {
+ const navigate = useNavigate();
+ const [settings, setSettings, _1, _2, _3] = usePluginSettings();
+
+ const apiKeyRef = useRef<HTMLInputElement>(null);
+ const addressRef = useRef<HTMLInputElement>(null);
+
+ const onSave = () => {
+ setSettings({
+ apiKey: apiKeyRef.current?.value || "",
+ address: addressRef.current?.value || "",
+ });
+ };
+
+ return (
+ <div className="flex flex-col space-y-2">
+ <span className="text-lg">Settings</span>
+ <hr />
+ <div className="flex space-x-2 pt-2">
+ <label className="m-auto h-full">API Key</label>
+ <input
+ ref={apiKeyRef}
+ defaultValue={settings.apiKey}
+ className="h-8 flex-1 rounded-lg border border-gray-300 p-2"
+ />
+ </div>
+ <div className="flex space-x-2">
+ <label className="m-auto h-full">Server Address</label>
+ <input
+ ref={addressRef}
+ defaultValue={settings.address}
+ className="h-8 flex-1 rounded-lg border border-gray-300 p-2"
+ />
+ </div>
+ <button
+ className="rounded-lg border border-gray-200"
+ onClick={onSave}
+ >
+ Save
+ </button>
+ <button
+ className="rounded-lg border border-gray-200"
+ onClick={() => navigate("/")}
+ >
+ Back
+ </button>
+ </div>
+ );
+}
diff --git a/packages/browser-extension/src/main.tsx b/packages/browser-extension/src/main.tsx
index 3d7150da..298ab388 100644
--- a/packages/browser-extension/src/main.tsx
+++ b/packages/browser-extension/src/main.tsx
@@ -1,10 +1,29 @@
-import React from 'react'
-import ReactDOM from 'react-dom/client'
-import App from './App.tsx'
-import './index.css'
+import React from "react";
+import ReactDOM from "react-dom/client";
+import App from "./App.tsx";
+import "./index.css";
+import { createBrowserRouter, Navigate, RouterProvider } from "react-router-dom";
+import SettingsPage from "./SettingsPage.tsx";
-ReactDOM.createRoot(document.getElementById('root')!).render(
+const router = createBrowserRouter([
+ {
+ path: "/index.html",
+ element: <Navigate to="/" />,
+ },
+ {
+ path: "/",
+ element: <App />,
+ },
+ {
+ path: "/settings",
+ element: <SettingsPage />,
+ },
+]);
+
+ReactDOM.createRoot(document.getElementById("root")!).render(
<React.StrictMode>
- <App />
+ <div className="p-4 w-96">
+ <RouterProvider router={router} />
+ </div>
</React.StrictMode>,
-)
+);
diff --git a/packages/browser-extension/src/settings.ts b/packages/browser-extension/src/settings.ts
new file mode 100644
index 00000000..ee7f0722
--- /dev/null
+++ b/packages/browser-extension/src/settings.ts
@@ -0,0 +1,13 @@
+import { useChromeStorageSync } from "use-chrome-storage";
+
+export type Settings = {
+ apiKey: string;
+ address: string;
+};
+
+export default function usePluginSettings() {
+ return useChromeStorageSync("settings", {
+ apiKey: "",
+ address: "",
+ } as Settings);
+}
diff --git a/yarn.lock b/yarn.lock
index b142ffb4..77301e73 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -243,7 +243,7 @@ __metadata:
languageName: node
linkType: hard
-"@babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.23.7":
+"@babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.23.7, @babel/runtime@npm:^7.23.8":
version: 7.23.9
resolution: "@babel/runtime@npm:7.23.9"
dependencies:
@@ -1702,6 +1702,13 @@ __metadata:
languageName: unknown
linkType: soft
+"@remix-run/router@npm:1.15.0":
+ version: 1.15.0
+ resolution: "@remix-run/router@npm:1.15.0"
+ checksum: 10c0/4805b5761ccbce3a522d3313c74ece7d4a411f02fd6d495d20f4352dcc87d8899f1b79a4c172a130e0f7a73b5f63a29177d8860131c35e3388552b1bd38a97f2
+ languageName: node
+ linkType: hard
+
"@rollup/pluginutils@npm:^4.1.2":
version: 4.2.1
resolution: "@rollup/pluginutils@npm:4.2.1"
@@ -2105,6 +2112,16 @@ __metadata:
languageName: node
linkType: hard
+"@types/chrome@npm:^0.0.260":
+ version: 0.0.260
+ resolution: "@types/chrome@npm:0.0.260"
+ dependencies:
+ "@types/filesystem": "npm:*"
+ "@types/har-format": "npm:*"
+ checksum: 10c0/58d844c2f88794d0181325d8f79b47462c1cbfca44d59b18bc49243a85a97757c6ec4290c207912a9b751831f955c5f7598379be0eb5b8f509025da691d113a2
+ languageName: node
+ linkType: hard
+
"@types/debug@npm:^4.1.0":
version: 4.1.12
resolution: "@types/debug@npm:4.1.12"
@@ -2121,6 +2138,29 @@ __metadata:
languageName: node
linkType: hard
+"@types/filesystem@npm:*":
+ version: 0.0.35
+ resolution: "@types/filesystem@npm:0.0.35"
+ dependencies:
+ "@types/filewriter": "npm:*"
+ checksum: 10c0/16a380e9774c5a9e1358f3ee28a3d85a93488443f235d160da3969aae7858dc6c6148cb3ff6b7e814f1c43f17940da0941f004373566d4fe7f75d9fda5efe246
+ languageName: node
+ linkType: hard
+
+"@types/filewriter@npm:*":
+ version: 0.0.33
+ resolution: "@types/filewriter@npm:0.0.33"
+ checksum: 10c0/363ef9a658a961ceae04f52934562e4ebdcdc3a2564dd8544f593d77113c16574938b6ba4fea0bee418c37bda0668c1e03dfedb6adf00d55853f51fb3a59247b
+ languageName: node
+ linkType: hard
+
+"@types/har-format@npm:*":
+ version: 1.2.15
+ resolution: "@types/har-format@npm:1.2.15"
+ checksum: 10c0/43ede55c3947e5cf59561f165930dc2eb3ae983fd162980cdc7274be1e7f528a6f77e65fee9a02a20d91b09bde10bed832b0470724f5c744ef6669015d00564e
+ languageName: node
+ linkType: hard
+
"@types/http-cache-semantics@npm:*":
version: 4.0.4
resolution: "@types/http-cache-semantics@npm:4.0.4"
@@ -2933,6 +2973,7 @@ __metadata:
resolution: "browser-extension@workspace:packages/browser-extension"
dependencies:
"@crxjs/vite-plugin": "npm:^1.0.14"
+ "@types/chrome": "npm:^0.0.260"
"@types/react": "npm:^18.2.55"
"@types/react-dom": "npm:^18.2.19"
"@typescript-eslint/eslint-plugin": "npm:^6.21.0"
@@ -2942,12 +2983,18 @@ __metadata:
eslint: "npm:^8.56.0"
eslint-plugin-react-hooks: "npm:^4.6.0"
eslint-plugin-react-refresh: "npm:^0.4.5"
+ localforage: "npm:^1.10.0"
+ match-sorter: "npm:^6.3.4"
postcss: "npm:^8.4.35"
react: "npm:^18.2.0"
react-dom: "npm:^18.2.0"
+ react-router-dom: "npm:^6.22.0"
+ sort-by: "npm:^1.2.0"
tailwindcss: "npm:^3.4.1"
typescript: "npm:^5.2.2"
+ use-chrome-storage: "npm:^1.2.2"
vite: "npm:^5.1.0"
+ zod: "npm:^3.22.4"
languageName: unknown
linkType: soft
@@ -5208,6 +5255,13 @@ __metadata:
languageName: node
linkType: hard
+"immediate@npm:~3.0.5":
+ version: 3.0.6
+ resolution: "immediate@npm:3.0.6"
+ checksum: 10c0/f8ba7ede69bee9260241ad078d2d535848745ff5f6995c7c7cb41cfdc9ccc213f66e10fa5afb881f90298b24a3f7344b637b592beb4f54e582770cdce3f1f039
+ languageName: node
+ linkType: hard
+
"import-fresh@npm:^3.2.1, import-fresh@npm:^3.3.0":
version: 3.3.0
resolution: "import-fresh@npm:3.3.0"
@@ -5967,6 +6021,15 @@ __metadata:
languageName: node
linkType: hard
+"lie@npm:3.1.1":
+ version: 3.1.1
+ resolution: "lie@npm:3.1.1"
+ dependencies:
+ immediate: "npm:~3.0.5"
+ checksum: 10c0/d62685786590351b8e407814acdd89efe1cb136f05cb9236c5a97b2efdca1f631d2997310ad2d565c753db7596799870140e4777c9c9b8c44a0f6bf42d1804a1
+ languageName: node
+ linkType: hard
+
"lilconfig@npm:^2.1.0":
version: 2.1.0
resolution: "lilconfig@npm:2.1.0"
@@ -5988,6 +6051,15 @@ __metadata:
languageName: node
linkType: hard
+"localforage@npm:^1.10.0":
+ version: 1.10.0
+ resolution: "localforage@npm:1.10.0"
+ dependencies:
+ lie: "npm:3.1.1"
+ checksum: 10c0/00f19f1f97002e6721587ed5017f502d58faf80dae567d5065d4d1ee0caf0762f40d2e2dba7f0ef7d3f14ee6203242daae9ecad97359bfc10ecff36df11d85a3
+ languageName: node
+ linkType: hard
+
"locate-path@npm:^6.0.0":
version: 6.0.0
resolution: "locate-path@npm:6.0.0"
@@ -6149,6 +6221,16 @@ __metadata:
languageName: node
linkType: hard
+"match-sorter@npm:^6.3.4":
+ version: 6.3.4
+ resolution: "match-sorter@npm:6.3.4"
+ dependencies:
+ "@babel/runtime": "npm:^7.23.8"
+ remove-accents: "npm:0.5.0"
+ checksum: 10c0/35d2a6b6df003c677d9ec87ecd4683657638f5bce856f43f9cf90b03e357ed2f09813ebbac759defa7e7438706936dd34dc2bfe1a18771f7d2541f14d639b4ad
+ languageName: node
+ linkType: hard
+
"md5@npm:^2.3.0":
version: 2.3.0
resolution: "md5@npm:2.3.0"
@@ -6878,6 +6960,13 @@ __metadata:
languageName: node
linkType: hard
+"object-path@npm:0.6.0":
+ version: 0.6.0
+ resolution: "object-path@npm:0.6.0"
+ checksum: 10c0/3a2708f6eef295e600e2d28f4854c1cee0ded6040425b50af164449adcf61ca873a024fff59b0a8b36c02dfd22d9148e4821302292a24ff0ddcd51194fde8338
+ languageName: node
+ linkType: hard
+
"object.assign@npm:^4.1.4":
version: 4.1.5
resolution: "object.assign@npm:4.1.5"
@@ -7755,6 +7844,30 @@ __metadata:
languageName: node
linkType: hard
+"react-router-dom@npm:^6.22.0":
+ version: 6.22.0
+ resolution: "react-router-dom@npm:6.22.0"
+ dependencies:
+ "@remix-run/router": "npm:1.15.0"
+ react-router: "npm:6.22.0"
+ peerDependencies:
+ react: ">=16.8"
+ react-dom: ">=16.8"
+ checksum: 10c0/f1c338d6a37ee331f141d683a9139bc397128f6c15ef796589894ba29de1101eeeab7c4bf26429632c86bbca7376a9d900a6bfbd351ac5c9e1e231ac1b05fe5d
+ languageName: node
+ linkType: hard
+
+"react-router@npm:6.22.0":
+ version: 6.22.0
+ resolution: "react-router@npm:6.22.0"
+ dependencies:
+ "@remix-run/router": "npm:1.15.0"
+ peerDependencies:
+ react: ">=16.8"
+ checksum: 10c0/aa3878321797e526e4f3a57f97e8dd06f7cf6d7b9f95db39ea5d74259a2058404a04af0f852296ba6f09f9cecd7ca5f67125b9853ceb7fe6a852ffa5e3369dca
+ languageName: node
+ linkType: hard
+
"react-style-singleton@npm:^2.2.1":
version: 2.2.1
resolution: "react-style-singleton@npm:2.2.1"
@@ -7884,6 +7997,13 @@ __metadata:
languageName: unknown
linkType: soft
+"remove-accents@npm:0.5.0":
+ version: 0.5.0
+ resolution: "remove-accents@npm:0.5.0"
+ checksum: 10c0/a75321aa1b53d9abe82637115a492770bfe42bb38ed258be748bf6795871202bc8b4badff22013494a7029f5a241057ad8d3f72adf67884dbe15a9e37e87adc4
+ languageName: node
+ linkType: hard
+
"require-directory@npm:^2.1.1":
version: 2.1.1
resolution: "require-directory@npm:2.1.1"
@@ -8315,6 +8435,15 @@ __metadata:
languageName: node
linkType: hard
+"sort-by@npm:^1.2.0":
+ version: 1.2.0
+ resolution: "sort-by@npm:1.2.0"
+ dependencies:
+ object-path: "npm:0.6.0"
+ checksum: 10c0/cd88745e6ae33fce8f836955102398fed1adbbee8ee33e20d91ab713625a4e70da91036e866a3c348dbc6a99141215c9718727d53c2e62e6658cf2cde6352892
+ languageName: node
+ linkType: hard
+
"source-map-js@npm:^1.0.2":
version: 1.0.2
resolution: "source-map-js@npm:1.0.2"
@@ -9085,6 +9214,15 @@ __metadata:
languageName: node
linkType: hard
+"use-chrome-storage@npm:^1.2.2":
+ version: 1.2.2
+ resolution: "use-chrome-storage@npm:1.2.2"
+ peerDependencies:
+ react: ^16.9.0 || ^17.0.0 || ^18.0.0
+ checksum: 10c0/8fe3814586f91529a97c413fd79e2a30853e171071db119373e5622862f528406126df7f72705cc4572aefdf0c5cab7a0152990a443a7a415c23d75bb68ea72e
+ languageName: node
+ linkType: hard
+
"use-sidecar@npm:^1.1.2":
version: 1.1.2
resolution: "use-sidecar@npm:1.1.2"