diff options
| author | MohamedBassem <me@mbassem.com> | 2024-02-12 20:50:12 +0000 |
|---|---|---|
| committer | MohamedBassem <me@mbassem.com> | 2024-02-12 20:50:12 +0000 |
| commit | 6e6d2c3cbc860d0024e9631b01eeef55b47933a5 (patch) | |
| tree | 33cf443237fcc757f8f22436f861652d369d6330 | |
| parent | e2bdccd483677cd60a92f4b0308bd2e4a0c02bfb (diff) | |
| download | karakeep-6e6d2c3cbc860d0024e9631b01eeef55b47933a5.tar.zst | |
WIP: Implement saving page functionality in browser extension
| -rw-r--r-- | packages/browser-extension/.eslintrc.cjs | 18 | ||||
| -rw-r--r-- | packages/browser-extension/manifest.json | 5 | ||||
| -rw-r--r-- | packages/browser-extension/package.json | 9 | ||||
| -rw-r--r-- | packages/browser-extension/src/App.tsx | 29 | ||||
| -rw-r--r-- | packages/browser-extension/src/SavePage.tsx | 40 | ||||
| -rw-r--r-- | packages/browser-extension/src/SettingsPage.tsx | 53 | ||||
| -rw-r--r-- | packages/browser-extension/src/main.tsx | 33 | ||||
| -rw-r--r-- | packages/browser-extension/src/settings.ts | 13 | ||||
| -rw-r--r-- | yarn.lock | 140 |
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); +} @@ -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" |
