aboutsummaryrefslogtreecommitdiffstats
path: root/packages/browser-extension
diff options
context:
space:
mode:
authorMohamedBassem <me@mbassem.com>2024-03-05 13:52:19 +0000
committerMohamedBassem <me@mbassem.com>2024-03-05 13:52:19 +0000
commit4ddfd0e322d79fb1b3b6603a252c0f3fa5a98270 (patch)
tree1e9ad6be760314b6561e9aceb02656911f2f2455 /packages/browser-extension
parent8a46ecb7373d6c5e7300861169ea51a7917cd2b4 (diff)
downloadkarakeep-4ddfd0e322d79fb1b3b6603a252c0f3fa5a98270.tar.zst
extension: Use react-query and trpc in the extension
Diffstat (limited to 'packages/browser-extension')
-rw-r--r--packages/browser-extension/package.json7
-rw-r--r--packages/browser-extension/src/App.tsx11
-rw-r--r--packages/browser-extension/src/OptionsPage.tsx6
-rw-r--r--packages/browser-extension/src/SavePage.tsx83
-rw-r--r--packages/browser-extension/src/main.tsx5
-rw-r--r--packages/browser-extension/src/providers.tsx30
-rw-r--r--packages/browser-extension/src/utils/providers.tsx40
-rw-r--r--packages/browser-extension/src/utils/settings.ts (renamed from packages/browser-extension/src/settings.ts)0
-rw-r--r--packages/browser-extension/src/utils/trpc.ts4
9 files changed, 133 insertions, 53 deletions
diff --git a/packages/browser-extension/package.json b/packages/browser-extension/package.json
index 297ba18e..b205a257 100644
--- a/packages/browser-extension/package.json
+++ b/packages/browser-extension/package.json
@@ -10,12 +10,19 @@
"preview": "vite preview"
},
"dependencies": {
+ "@hoarder/trpc": "0.1.0",
+ "@tanstack/react-query": "^5.24.8",
+ "@trpc/client": "11.0.0-next-beta.308",
+ "@trpc/next": "11.0.0-next-beta.308",
+ "@trpc/react-query": "11.0.0-next-beta.308",
+ "@trpc/server": "11.0.0-next-beta.308",
"@types/chrome": "^0.0.260",
"lucide-react": "^0.330.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.22.0",
"use-chrome-storage": "^1.2.2",
+ "superjson": "^2.2.1",
"zod": "^3.22.4"
},
"devDependencies": {
diff --git a/packages/browser-extension/src/App.tsx b/packages/browser-extension/src/App.tsx
index 1044363b..279c8b7a 100644
--- a/packages/browser-extension/src/App.tsx
+++ b/packages/browser-extension/src/App.tsx
@@ -1,6 +1,6 @@
-import { Settings, X } from "lucide-react";
+import { RefreshCw, Settings, X } from "lucide-react";
import SavePage from "./SavePage";
-import usePluginSettings from "./settings";
+import usePluginSettings from "./utils/settings";
import { useNavigate } from "react-router-dom";
function App() {
@@ -18,9 +18,14 @@ function App() {
return (
<div className="flex flex-col space-y-2">
- <SavePage settings={settings} />
+ <SavePage />
<hr />
<div className="flex justify-end space-x-3">
+ {process.env.NODE_ENV == "development" && (
+ <button onClick={() => navigate(0)}>
+ <RefreshCw className="w-4" />
+ </button>
+ )}
<button onClick={() => navigate("/options")}>
<Settings className="w-4" />
</button>
diff --git a/packages/browser-extension/src/OptionsPage.tsx b/packages/browser-extension/src/OptionsPage.tsx
index 11a1a76d..5cb4a45b 100644
--- a/packages/browser-extension/src/OptionsPage.tsx
+++ b/packages/browser-extension/src/OptionsPage.tsx
@@ -1,5 +1,5 @@
import { useRef, useState } from "react";
-import usePluginSettings from "./settings";
+import usePluginSettings from "./utils/settings";
export default function OptionsPage() {
const [settings, setSettings, _1, _2, _3] = usePluginSettings();
@@ -38,7 +38,7 @@ export default function OptionsPage() {
<label className="m-auto h-full">Server Address</label>
<input
ref={addressRef}
- defaultValue={settings.address || "https://demo.hoarder.app"}
+ value={settings.address || "https://demo.hoarder.app"}
className="h-8 flex-1 rounded-lg border border-gray-300 p-2"
/>
</div>
@@ -46,7 +46,7 @@ export default function OptionsPage() {
<label className="m-auto h-full">API Key</label>
<input
ref={apiKeyRef}
- defaultValue={settings.apiKey}
+ value={settings.apiKey}
className="h-8 flex-1 rounded-lg border border-gray-300 p-2"
/>
</div>
diff --git a/packages/browser-extension/src/SavePage.tsx b/packages/browser-extension/src/SavePage.tsx
index 955cc7cb..003d4025 100644
--- a/packages/browser-extension/src/SavePage.tsx
+++ b/packages/browser-extension/src/SavePage.tsx
@@ -1,13 +1,19 @@
import { useEffect, useState } from "react";
-import { Settings } from "./settings";
import Spinner from "./Spinner";
+import { api } from "./utils/trpc";
-export default function SavePage({ settings }: { settings: Settings }) {
- const [loading, setLoading] = useState(true);
+export default function SavePage() {
const [error, setError] = useState<string | undefined>(undefined);
+ const { mutate: createBookmark, status } =
+ api.bookmarks.createBookmark.useMutation({
+ onError: (e) => {
+ setError("Something went wrong: " + e.message);
+ },
+ });
+
useEffect(() => {
- async function runFetch() {
+ async function runSave() {
let currentUrl;
const [currentTab] = await chrome.tabs.query({
active: true,
@@ -17,52 +23,37 @@ export default function SavePage({ settings }: { settings: Settings }) {
currentUrl = currentTab.url;
} else {
setError("Couldn't find the URL of the current tab");
- setLoading(false);
return;
}
- try {
- const resp = await fetch(
- `${settings.address}/api/trpc/bookmarks.createBookmark`,
- {
- method: "POST",
- headers: {
- Authorization: `Bearer ${settings.apiKey}`,
- "Content-Type": "application/json",
- },
- body: JSON.stringify({
- json: {
- type: "link",
- url: currentUrl,
- },
- }),
- },
- );
- if (!resp.ok) {
- setError(
- "Something went wrong: " + JSON.stringify(await resp.json()),
- );
- }
- } catch (e) {
- setError("Message: " + (e as Error).message);
- }
-
- setLoading(false);
+ createBookmark({
+ type: "link",
+ url: currentUrl,
+ });
}
- runFetch();
- }, [settings]);
-
- if (loading) {
- return (
- <div className="m-auto">
- <Spinner />
- </div>
- );
- }
+ runSave();
+ }, [createBookmark]);
- if (error) {
- return <div className="text-red-500">{error} ...</div>;
+ switch (status) {
+ case "error": {
+ return <div className="text-red-500">{error}</div>;
+ }
+ case "success": {
+ return <div className="m-auto text-lg">Bookmark Saved</div>;
+ }
+ case "pending": {
+ return (
+ <div className="m-auto">
+ <Spinner />
+ </div>
+ );
+ }
+ case "idle": {
+ return (
+ <div className="m-auto">
+ <Spinner />
+ </div>
+ );
+ }
}
-
- return <div className="m-auto text-lg">Bookmark Saved</div>;
}
diff --git a/packages/browser-extension/src/main.tsx b/packages/browser-extension/src/main.tsx
index c4f5a2d9..3e269982 100644
--- a/packages/browser-extension/src/main.tsx
+++ b/packages/browser-extension/src/main.tsx
@@ -5,6 +5,7 @@ import "./index.css";
import { createHashRouter, RouterProvider } from "react-router-dom";
import OptionsPage from "./OptionsPage.tsx";
import NotConfiguredPage from "./NotConfiguredPage.tsx";
+import { Providers } from "./utils/providers.tsx";
const router = createHashRouter([
{
@@ -24,7 +25,9 @@ const router = createHashRouter([
ReactDOM.createRoot(document.getElementById("root")!).render(
<React.StrictMode>
<div className="w-96 p-4">
- <RouterProvider router={router} />
+ <Providers>
+ <RouterProvider router={router} />
+ </Providers>
</div>
</React.StrictMode>,
);
diff --git a/packages/browser-extension/src/providers.tsx b/packages/browser-extension/src/providers.tsx
new file mode 100644
index 00000000..a055f3d1
--- /dev/null
+++ b/packages/browser-extension/src/providers.tsx
@@ -0,0 +1,30 @@
+import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
+import { httpBatchLink } from "@trpc/client";
+import React, { useState } from "react";
+import { trpc } from "./trpc";
+
+export function App() {
+ const [queryClient] = useState(() => new QueryClient());
+ const [trpcClient] = useState(() =>
+ trpc.createClient({
+ links: [
+ httpBatchLink({
+ url: "http://localhost:3000/trpc",
+ // You can pass any HTTP headers you wish here
+ async headers() {
+ return {
+ // authorization: getAuthCookie(),
+ };
+ },
+ }),
+ ],
+ }),
+ );
+ return (
+ <trpc.Provider client={trpcClient} queryClient={queryClient}>
+ <QueryClientProvider client={queryClient}>
+ {/* Your app here */}
+ </QueryClientProvider>
+ </trpc.Provider>
+ );
+}
diff --git a/packages/browser-extension/src/utils/providers.tsx b/packages/browser-extension/src/utils/providers.tsx
new file mode 100644
index 00000000..c11331f0
--- /dev/null
+++ b/packages/browser-extension/src/utils/providers.tsx
@@ -0,0 +1,40 @@
+import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
+import { httpBatchLink } from "@trpc/client";
+import { useCallback, useEffect, useState } from "react";
+import { api } from "./trpc";
+import usePluginSettings from "./settings";
+import superjson from "superjson";
+
+export function Providers({ children }: { children: React.ReactNode }) {
+ const [settings] = usePluginSettings();
+ const [queryClient] = useState(() => new QueryClient());
+
+ const getTrpcClient = useCallback(() => {
+ console.log(settings);
+ return api.createClient({
+ links: [
+ httpBatchLink({
+ url: `${settings.address}/api/trpc`,
+ async headers() {
+ return {
+ Authorization: `Bearer ${settings.apiKey}`,
+ };
+ },
+ transformer: superjson,
+ }),
+ ],
+ });
+ }, [settings]);
+
+ const [trpcClient, setTrpcClient] = useState(getTrpcClient());
+
+ useEffect(() => {
+ setTrpcClient(getTrpcClient());
+ }, [getTrpcClient]);
+
+ return (
+ <api.Provider client={trpcClient} queryClient={queryClient}>
+ <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
+ </api.Provider>
+ );
+}
diff --git a/packages/browser-extension/src/settings.ts b/packages/browser-extension/src/utils/settings.ts
index ee7f0722..ee7f0722 100644
--- a/packages/browser-extension/src/settings.ts
+++ b/packages/browser-extension/src/utils/settings.ts
diff --git a/packages/browser-extension/src/utils/trpc.ts b/packages/browser-extension/src/utils/trpc.ts
new file mode 100644
index 00000000..da21a55a
--- /dev/null
+++ b/packages/browser-extension/src/utils/trpc.ts
@@ -0,0 +1,4 @@
+import { createTRPCReact } from "@trpc/react-query";
+import type { AppRouter } from "@hoarder/trpc/routers/_app";
+
+export const api = createTRPCReact<AppRouter>();