diff --git a/src/main/index.ts b/src/main/index.ts index a9d3a9496..67a56741d 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -109,7 +109,6 @@ Menu.setApplicationMenu( label: "Settings...", accelerator: "CmdOrCtrl+,", click: () => { - console.log("Oh, hi there!") createWindow({ extraPath: "/settings", width: 800, @@ -131,5 +130,30 @@ Menu.setApplicationMenu( { role: "viewMenu" }, { role: "windowMenu" }, { role: "help" }, + { + label: "Dev", + submenu: [ + { + label: "follow https://rsshub.app/twitter/user/DIYgod", + click: () => { + createWindow({ + extraPath: `/follow?url=${encodeURIComponent("https://rsshub.app/twitter/user/DIYgod")}`, + width: 800, + height: 600, + }) + }, + }, + { + label: "follow https://diygod.me/feed", + click: () => { + createWindow({ + extraPath: `/follow?url=${encodeURIComponent("https://diygod.me/feed")}`, + width: 800, + height: 600, + }) + }, + }, + ], + }, ]), ) diff --git a/src/renderer/src/assets/base.css b/src/renderer/src/assets/base.css index 179f44c6a..e6ec9676e 100644 --- a/src/renderer/src/assets/base.css +++ b/src/renderer/src/assets/base.css @@ -3,6 +3,7 @@ body, @apply h-screen; @apply cursor-default; @apply select-none; + @apply bg-white; font-family: "SN Pro", sans-serif; } diff --git a/src/renderer/src/components/discover/dialog.tsx b/src/renderer/src/components/discover/dialog.tsx index 49f7b8d36..375bee25a 100644 --- a/src/renderer/src/components/discover/dialog.tsx +++ b/src/renderer/src/components/discover/dialog.tsx @@ -115,7 +115,7 @@ export function FollowDialog({ View diff --git a/src/renderer/src/components/discover/form.tsx b/src/renderer/src/components/discover/form.tsx index ab661d16b..d5a86ee42 100644 --- a/src/renderer/src/components/discover/form.tsx +++ b/src/renderer/src/components/discover/form.tsx @@ -130,7 +130,7 @@ export function DiscoverForm({ type }: { type: string }) { {mutation.data?.map((item) => ( - + {item.docs ? ( diff --git a/src/renderer/src/components/discover/import.tsx b/src/renderer/src/components/discover/import.tsx index e8535bebc..941afc4a1 100644 --- a/src/renderer/src/components/discover/import.tsx +++ b/src/renderer/src/components/discover/import.tsx @@ -147,7 +147,7 @@ export function DiscoverImport() { No items )} {mutation.data?.[item.key].map((feed: FeedResponse) => ( - + ))} diff --git a/src/renderer/src/components/feed-summary.tsx b/src/renderer/src/components/feed-summary.tsx index 2250f4fab..897050b08 100644 --- a/src/renderer/src/components/feed-summary.tsx +++ b/src/renderer/src/components/feed-summary.tsx @@ -1,15 +1,18 @@ import { FeedIcon } from "@renderer/components/feed-icon" -import type { FeedResponse } from "@renderer/lib/types" +import type { FeedModel } from "@renderer/lib/types" +import { cn } from "@renderer/lib/utils" export function FollowSummary({ feed, docs, + className, }: { - feed: FeedResponse + feed: FeedModel docs?: string + className?: string }) { return ( - + ( { setOpen(false) props.onBlur?.(e) diff --git a/src/renderer/src/components/ui/button.tsx b/src/renderer/src/components/ui/button.tsx index 76e4f93fa..be1b9d596 100644 --- a/src/renderer/src/components/ui/button.tsx +++ b/src/renderer/src/components/ui/button.tsx @@ -8,6 +8,13 @@ const buttonVariants = cva( "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", { variants: { + size: { + default: "h-10 px-4 py-2", + sm: "h-8 rounded-md px-4", + lg: "h-11 rounded-md px-8", + xl: "h-14 rounded-lg px-10", + icon: "size-10", + }, variant: { default: "bg-primary text-primary-foreground hover:bg-primary/90", destructive: @@ -16,16 +23,9 @@ const buttonVariants = cva( "border border-input bg-background hover:bg-accent hover:text-accent-foreground", secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80", - ghost: "hover:bg-zinc-500/10", + ghost: "hover:bg-zinc-500/10 px-1.5", link: "text-primary underline-offset-4 hover:underline", }, - size: { - default: "h-10 px-4 py-2", - sm: "h-8 rounded-md px-1.5", - lg: "h-11 rounded-md px-8", - xl: "h-14 rounded-lg px-10", - icon: "size-10", - }, }, defaultVariants: { variant: "default", diff --git a/src/renderer/src/pages/follow/index.tsx b/src/renderer/src/pages/follow/index.tsx index afa549e7e..4960fcaa4 100644 --- a/src/renderer/src/pages/follow/index.tsx +++ b/src/renderer/src/pages/follow/index.tsx @@ -1,7 +1,215 @@ +import { zodResolver } from "@hookform/resolvers/zod"; +import { FollowSummary } from "@renderer/components/feed-summary"; +import { AutoComplete } from "@renderer/components/ui/autocomplete"; +import { Button } from "@renderer/components/ui/button"; +import { + Form, + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@renderer/components/ui/form"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@renderer/components/ui/select"; +import { Switch } from "@renderer/components/ui/switch"; +import { useBizQuery } from "@renderer/hooks/useBizQuery"; +import { views } from "@renderer/lib/constants"; +import { cn } from "@renderer/lib/utils"; +import { Queries } from "@renderer/queries"; +import { apiFetch } from "@renderer/queries/api-fetch"; +import { useFeed } from "@renderer/queries/feed"; +import { useMutation } from "@tanstack/react-query"; +import { useEffect } from "react"; +import { useForm } from "react-hook-form"; +import { z } from "zod"; +import { Card, CardHeader } from "@renderer/components/ui/card"; + +const formSchema = z.object({ + view: z.string(), + category: z.string().nullable().optional(), + isPrivate: z.boolean().optional(), +}); + export function Component() { + const urlSearchParams = new URLSearchParams(location.search); + const paramUrl = urlSearchParams.get("url"); + const url = paramUrl ? decodeURIComponent(paramUrl) : undefined; + const id = urlSearchParams.get("id") || undefined; + + const feed = useFeed({ + url, + id, + }); + + const isSubscribed = !!feed.data?.subscription; + const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + view: "0", + }, + }); + + useEffect(() => { + if (feed.data?.subscription) { + form.setValue("view", `${feed.data?.subscription?.view}`); + form.setValue("category", feed.data?.subscription?.category); + form.setValue("isPrivate", feed.data?.subscription?.isPrivate || false); + } + }, [feed.data?.subscription]); + + const followMutation = useMutation({ + mutationFn: async (values: z.infer) => + apiFetch("/subscriptions", { + method: isSubscribed ? "PATCH" : "POST", + body: { + url: feed.data?.feed.url, + view: Number.parseInt(values.view), + category: values.category, + isPrivate: values.isPrivate, + ...(isSubscribed && { feedId: feed.data?.feed.id }), + }, + }), + onSuccess: (_, variables) => { + if ( + isSubscribed && + variables.view !== `${feed.data?.subscription?.view}` + ) { + Queries.subscription.byView(feed.data?.subscription?.view).invalidate(); + } + Queries.subscription.byView(Number.parseInt(variables.view)).invalidate(); + }, + }); + + function onSubmit(values: z.infer) { + followMutation.mutate(values); + } + + const categories = useBizQuery( + Queries.subscription.categories(Number.parseInt(form.watch("view"))) + ); + return ( - <> - Follow - > - ) + + + + New follow + + {feed.isLoading ? ( + + Loading... + + ) : ( + !feed.data?.feed ? ( + + Feed not found. + {url} + + ) : ( + + + + + + + + + ( + + View + + + + + + + + {views.map((view, index) => ( + + + + {view.icon} + + {view.name} + + + ))} + + + + + )} + /> + ( + + + Category + + By default, your follows will be grouped by website. + + + + + + + + )} + /> + ( + + + Prviate Follow + + Whether this follow is publicly visible on your + profile page. + + + + + + + )} + /> + + {isSubscribed ? "Update" : "Follow"} + + + + + ) + )} + + ); }
Feed not found.
{url}