diff --git a/.env.example b/.env.example index 59da0dc..e930c54 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,5 @@ +VITE_UPTAB_API_KEY= + VITE_GLITCHTIP_DSN= CHROME_CLIENT_ID= diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a6f3e9..c032164 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,24 @@ UpTab adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [V1.3.0] — Unreleased + +### ✨ Added + +- + +### 🐛 Fixed + +- + +### 🧹 Removed + +- + +### ♻️ Changed + +- + ## [V1.2.0] — 2024-02-16 ### ✨ Added @@ -75,6 +93,7 @@ UpTab adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Added Bookmarks: allowing you to easily view, open and delete your browser bookmarks - Added `CTRL+U` shortkey to open popup +[V1.3.0]: https://github.com/AJGeel/uptab/compare/v1.3.0...v1.2.0 [V1.2.0]: https://github.com/AJGeel/uptab/compare/v1.2.0...v1.1.0 [V1.1.0]: https://github.com/AJGeel/uptab/compare/v1.1.0...v1.0.1 [V1.0.1]: https://github.com/AJGeel/uptab/compare/v1.0.0...v1.0.1 diff --git a/bun.lockb b/bun.lockb index 0345f28..941e11f 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 84e3670..298a22c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "uptab", "displayName": "UpTab", - "version": "1.2.0", + "version": "1.3.0", "description": "What's UpTab?", "author": "Arthur Geel ", "scripts": { @@ -23,6 +23,7 @@ "dependencies": { "@heroicons/react": "^2.1.1", "@radix-ui/react-dialog": "^1.0.5", + "@radix-ui/react-select": "^2.0.0", "@radix-ui/react-switch": "^1.0.3", "@sentry/browser": "^7.101.0", "@tanstack/react-query": "^5.20.5", diff --git a/src/components/Homescreen/Homescreen.tsx b/src/components/Homescreen/Homescreen.tsx index ab1834e..804e8d0 100644 --- a/src/components/Homescreen/Homescreen.tsx +++ b/src/components/Homescreen/Homescreen.tsx @@ -13,7 +13,6 @@ import ImageFadeIn from "../ui/ImageFadeIn"; const Homescreen = () => { const { data: settings, isPending, toggleSidebarSetting } = useSettings(); const { activeBg } = useRandomBackground(); - const isSidebarOpen = settings?.sidebar?.isOpen; useKeyPress(hotkeys.backslash, () => toggleSidebarSetting("isOpen")); @@ -23,6 +22,9 @@ const Homescreen = () => { return <>; } + const bgImage = activeBg.src; + // const bgImage = `http://localhost:3000/api/background?theme=${settings?.background.theme}`; + return ( <> @@ -33,7 +35,7 @@ const Homescreen = () => { /> { title="Edit Preferences" className="max-w-xl" > -
+
{!!settings && ( -
+
+ {}} + /> + + ), + }, { label: "Sidebar", content: ( @@ -44,6 +60,7 @@ const SettingsModal = () => { key={"sidebar" + row.title} title={row.title} description={row.description} + type="Switch" isActive={settings.sidebar[row.setting]} onClick={() => { toggleSidebarSetting(row.setting); @@ -61,6 +78,7 @@ const SettingsModal = () => { { @@ -75,7 +93,7 @@ const SettingsModal = () => { />
)} -
+
); diff --git a/src/components/Modals/SettingsModal/partials/rows.ts b/src/components/Modals/SettingsModal/partials/rows.ts index 8368414..b56dbc5 100644 --- a/src/components/Modals/SettingsModal/partials/rows.ts +++ b/src/components/Modals/SettingsModal/partials/rows.ts @@ -1,9 +1,15 @@ import { + BackgroundSettings, HomescreenSettings, SidebarSettings, } from "@/src/services/settings/types"; type SettingsRows = { + background: { + setting: keyof BackgroundSettings; + title: string; + description: string; + }[]; sidebar: { setting: keyof SidebarSettings; title: string; @@ -17,6 +23,13 @@ type SettingsRows = { }; export const rows: SettingsRows = { + background: [ + { + setting: "theme", + title: "Background theme", + description: "Pick a snazzy theme", + }, + ], sidebar: [ { setting: "showInfoWidget", diff --git a/src/components/ui/Select.tsx b/src/components/ui/Select.tsx new file mode 100644 index 0000000..955f4fb --- /dev/null +++ b/src/components/ui/Select.tsx @@ -0,0 +1,171 @@ +"use client"; + +import { + CheckIcon, + ChevronDownIcon, + ChevronUpIcon, +} from "@heroicons/react/24/solid"; +import * as SelectPrimitive from "@radix-ui/react-select"; +import * as React from "react"; + +import { cn } from "@/src/utils"; + +const Select = SelectPrimitive.Root; + +const SelectGroup = SelectPrimitive.Group; + +const SelectValue = SelectPrimitive.Value; + +type ClassName = { + className?: string; +}; + +const SelectTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & ClassName +>(({ className, children, ...props }, ref) => ( + span]:line-clamp-1", + className + )} + {...props} + > + {children} + + + + +)); +SelectTrigger.displayName = SelectPrimitive.Trigger.displayName; + +const SelectScrollUpButton = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & + ClassName +>(({ className, ...props }, ref) => ( + + + +)); +SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName; + +const SelectScrollDownButton = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & + ClassName +>(({ className, ...props }, ref) => ( + + + +)); +SelectScrollDownButton.displayName = + SelectPrimitive.ScrollDownButton.displayName; + +const SelectContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & + ClassName & { position?: string } +>(({ className, children, position = "popper", ...props }, ref) => ( + + + + + {children} + + + + +)); +SelectContent.displayName = SelectPrimitive.Content.displayName; + +const SelectLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & ClassName +>(({ className, ...props }, ref) => ( + +)); +SelectLabel.displayName = SelectPrimitive.Label.displayName; + +const SelectItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & ClassName +>(({ className, children, ...props }, ref) => ( + + + + + + + + {children} + +)); +SelectItem.displayName = SelectPrimitive.Item.displayName; + +const SelectSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & ClassName +>(({ className, ...props }, ref) => ( + +)); +SelectSeparator.displayName = SelectPrimitive.Separator.displayName; + +export { + Select, + SelectGroup, + SelectValue, + SelectTrigger, + SelectContent, + SelectLabel, + SelectItem, + SelectSeparator, + SelectScrollUpButton, + SelectScrollDownButton, +}; diff --git a/src/hooks/useBackground.ts b/src/hooks/useBackground.ts new file mode 100644 index 0000000..aa1f9a1 --- /dev/null +++ b/src/hooks/useBackground.ts @@ -0,0 +1,31 @@ +import { useQuery } from "@tanstack/react-query"; + +import { useSettings } from "./useSettings"; +import { getBackground } from "../services/background/getBackground"; + +export const useBackground = () => { + const { data: settings } = useSettings(); + + const { + isPending, + isError, + data: backgroundImage, + } = useQuery({ + queryFn: async () => await getBackground(settings?.background.theme), + enabled: !!settings, + queryKey: ["background", settings?.background.theme], + // + refetchOnWindowFocus: false, + refetchOnReconnect: false, + staleTime: 12 * 60 * 60 * 1000, // 12 hours + gcTime: 12 * 60 * 60 * 1000, // 12 hours + }); + + // TODO: Handle error state with a fallback image + + return { + isPending, + isError, + backgroundImage, + }; +}; diff --git a/src/hooks/useSettings.ts b/src/hooks/useSettings.ts index d7a754e..b4a93d5 100644 --- a/src/hooks/useSettings.ts +++ b/src/hooks/useSettings.ts @@ -44,6 +44,7 @@ export const useSettings = () => { }); }; + // TODO: Refactor, toggleSidebarSetting and toggleHomescreenSettings contain too much duplication. const toggleHomescreenSetting = async (key: keyof HomescreenSettings) => { if (!data) { return; @@ -58,6 +59,8 @@ export const useSettings = () => { }); }; + // TODO: Add function to mutate background settings + const resetDefaultSettings = async () => { await editMutation.mutateAsync(defaultSettings); }; diff --git a/src/manifest.ts b/src/manifest.ts index 8c24ebe..1e4e15a 100755 --- a/src/manifest.ts +++ b/src/manifest.ts @@ -40,7 +40,14 @@ const manifest: Manifest.WebExtensionManifest = { }, manifest_version: 3, name: "UpTab", - permissions: ["storage", "geolocation", "bookmarks"], + permissions: [ + "storage", + "geolocation", + "bookmarks", + "http://localhost:*", + "http://uptab.vercel.app/", + "https://uptab.vercel.app/", + ], version: pkg.version, web_accessible_resources: [ { diff --git a/src/pages/newtab/Newtab.tsx b/src/pages/newtab/Newtab.tsx index 7e2b781..3662417 100644 --- a/src/pages/newtab/Newtab.tsx +++ b/src/pages/newtab/Newtab.tsx @@ -3,7 +3,13 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import Homescreen from "@/src/components/Homescreen/Homescreen"; import { useEasterEggs } from "@/src/hooks/useEasterEggs"; -const queryClient = new QueryClient(); +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + gcTime: Infinity, + }, + }, +}); export default function Newtab() { useEasterEggs(); diff --git a/src/services/background/getBackground.ts b/src/services/background/getBackground.ts new file mode 100644 index 0000000..e7d3e03 --- /dev/null +++ b/src/services/background/getBackground.ts @@ -0,0 +1,25 @@ +// const apiUrl = "https://uptab.vercel.app/api/background"; +const apiUrl = "http://localhost:3000/api/background"; + +export const getBackground = async (theme?: string) => { + try { + const url = theme ? `${apiUrl}?theme=${theme}` : apiUrl; + + const response = await fetch(url, { + mode: "cors", + headers: { + "Uptab-Api-Key": import.meta.env.UPTAB_API_KEY ?? "", + }, + }); + + console.log(response); + + const image = await response.json(); + + console.log(image); + + return image; + } catch (error) { + throw new Error(`Unable to get an image from the backend: ${error}`); + } +}; diff --git a/src/services/background/types.ts b/src/services/background/types.ts new file mode 100644 index 0000000..c0d482d --- /dev/null +++ b/src/services/background/types.ts @@ -0,0 +1,8 @@ +export const bgThemes = { + holland: "holland", + abstract: "abstract", + underwater: "underwater", + safari: "safari", +} as const; + +export type BgTheme = (typeof bgThemes)[keyof typeof bgThemes]; diff --git a/src/services/settings/defaultSettings.ts b/src/services/settings/defaultSettings.ts index 1baffa2..73c6e43 100644 --- a/src/services/settings/defaultSettings.ts +++ b/src/services/settings/defaultSettings.ts @@ -1,4 +1,5 @@ import { Settings } from "./types"; +import { bgThemes } from "../background/types"; export const defaultSettings: Settings = { sidebar: { @@ -12,4 +13,7 @@ export const defaultSettings: Settings = { showFeedbackPrompt: true, showInfoWidget: true, }, + background: { + theme: bgThemes.holland, + }, }; diff --git a/src/services/settings/types.ts b/src/services/settings/types.ts index 5992479..0155ae3 100644 --- a/src/services/settings/types.ts +++ b/src/services/settings/types.ts @@ -1,3 +1,5 @@ +import { BgTheme } from "../background/types"; + export type SidebarSettings = { showShortlinks: boolean; showBookmarks: boolean; @@ -11,7 +13,12 @@ export type HomescreenSettings = { showInfoWidget: boolean; }; +export type BackgroundSettings = { + theme: BgTheme; +}; + export type Settings = { + background: BackgroundSettings; sidebar: SidebarSettings; homescreen: HomescreenSettings; };