Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: lists #533

Merged
merged 37 commits into from
Sep 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
5766bd4
feat: lists and feeds sub title in feed column
DIYgod Sep 18, 2024
dcf2883
feat: lists setting panel
DIYgod Sep 18, 2024
b440821
Merge remote-tracking branch 'origin/dev' into feature/lists-2
DIYgod Sep 18, 2024
c9f6496
fix: imports
DIYgod Sep 18, 2024
749d944
Merge remote-tracking branch 'origin/dev' into feature/lists-2
DIYgod Sep 18, 2024
4fdaa1f
fix: avatar align in profile setting
DIYgod Sep 18, 2024
49a7b08
fix: styles in settings
DIYgod Sep 18, 2024
eae7f19
feat: lists setting table
DIYgod Sep 19, 2024
7eda5f6
feat: list and listsubscription types
DIYgod Sep 19, 2024
65fa3ad
feat: target model
DIYgod Sep 20, 2024
6e150a2
fix: target model types errors
DIYgod Sep 20, 2024
fb90a43
Merge remote-tracking branch 'origin/dev' into feature/lists-3
DIYgod Sep 20, 2024
3d9e62a
feat: seperate feed list and list list
DIYgod Sep 20, 2024
6e4316f
feat: edit lists
DIYgod Sep 20, 2024
958d687
feat: lists feeds management
DIYgod Sep 20, 2024
47f7e47
feat: new feed column
DIYgod Sep 20, 2024
1186414
Merge remote-tracking branch 'origin/dev' into feature/lists-3
DIYgod Sep 20, 2024
e21d35e
feat: use feedId for single feed entries request
DIYgod Sep 20, 2024
4ddf9e0
fix: lists feedId
DIYgod Sep 20, 2024
47d5828
feat: disable invalid functions for lists
DIYgod Sep 20, 2024
2e77ca7
Merge remote-tracking branch 'origin/dev' into feature/lists-3
DIYgod Sep 21, 2024
ec60330
feat: discover target selector
DIYgod Sep 21, 2024
e1c1e90
feat: list follow modal
DIYgod Sep 21, 2024
42120e8
feat: feed icon text size
DIYgod Sep 21, 2024
bec9f63
feat: use list get api
DIYgod Sep 21, 2024
30fceed
feat: lists edit action
DIYgod Sep 21, 2024
4dfe1c4
fix: radio color
DIYgod Sep 21, 2024
ed774d9
fix: radio click area
DIYgod Sep 21, 2024
aa0e7f2
Merge remote-tracking branch 'origin/dev' into feature/lists-3
DIYgod Sep 21, 2024
f7823be
feat: list external page
DIYgod Sep 21, 2024
a0fcbbf
feat: hide mark all action for list
DIYgod Sep 21, 2024
da5dfe0
feat: lists unread
DIYgod Sep 21, 2024
95f95d6
fix: types
DIYgod Sep 21, 2024
a3b97bc
fix: add tooltip for resize panel
Innei Sep 21, 2024
f3132eb
feat: add resize indicator
Innei Sep 21, 2024
debdf57
fix: hide section when no lists
Innei Sep 21, 2024
e20f353
Merge remote-tracking branch 'origin/dev' into feature/lists-3
Innei Sep 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 38 additions & 26 deletions apps/renderer/src/components/feed-icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import { getColorScheme, stringToHue } from "~/lib/color"
import { getImageProxyUrl } from "~/lib/img-proxy"
import { cn, getUrlIcon } from "~/lib/utils"
import type { CombinedEntryModel, FeedModel } from "~/models"
import type { CombinedEntryModel, FeedModel, TargetModel } from "~/models"

import { PlatformIcon } from "./ui/platform-icon"

Expand Down Expand Up @@ -75,7 +75,7 @@
siteUrl,
useMedia,
}: {
feed?: FeedModel
feed?: TargetModel
entry?: CombinedEntryModel["entries"]
fallbackUrl?: string
className?: string
Expand All @@ -98,8 +98,8 @@
}

const colors = useMemo(
() => getColorScheme(stringToHue(feed?.title || feed?.url || siteUrl!), true),
[feed?.title, feed?.url, siteUrl],
() => getColorScheme(stringToHue(feed?.title || (feed as FeedModel)?.url || siteUrl!), true),
[feed?.title, (feed as FeedModel)?.url, siteUrl],

Check warning on line 102 in apps/renderer/src/components/feed-icon.tsx

View workflow job for this annotation

GitHub Actions / Format, Lint and Typecheck (18.x)

React Hook useMemo has a missing dependency: 'feed'. Either include it or remove the dependency array

Check warning on line 102 in apps/renderer/src/components/feed-icon.tsx

View workflow job for this annotation

GitHub Actions / Format, Lint and Typecheck (18.x)

React Hook useMemo has a complex expression in the dependency array. Extract it to a separate variable so it can be statically checked
)
let ImageElement: ReactNode
let finalSrc = ""
Expand All @@ -109,6 +109,32 @@
height: size,
}

const fallbackIcon = (
<span
style={
{
...sizeStyle,
"--fo-light-background": colors.light.background,
"--fo-dark-background": colors.dark.background,
} as any
}
className={cn(
"flex shrink-0 items-center justify-center rounded-sm",
"bg-[var(--fo-light-background)] text-white dark:bg-[var(--fo-dark-background)]",
"mr-2",
className,
)}
>
<span
style={{
fontSize: size / 2,
}}
>
{!!feed?.title && feed.title[0]}
</span>
</span>
)

switch (true) {
case !feed && !!siteUrl: {
const [src] = getFeedIconSrc({
Expand Down Expand Up @@ -137,9 +163,9 @@
break
}
case !!fallbackUrl:
case !!feed?.siteUrl: {
case !!(feed as FeedModel)?.siteUrl: {
const [src, fallbackSrc] = getFeedIconSrc({
siteUrl: feed?.siteUrl || fallbackUrl,
siteUrl: (feed as FeedModel)?.siteUrl || fallbackUrl,
fallback,
proxy: {
width: size * 2,
Expand All @@ -150,7 +176,7 @@

ImageElement = (
<PlatformIcon
url={feed?.siteUrl || fallbackUrl}
url={(feed as FeedModel)?.siteUrl || fallbackUrl}
style={sizeStyle}
className={cn("center mr-2", className)}
>
Expand All @@ -163,6 +189,10 @@
)
break
}
case !!feed?.title && !!feed.title[0]: {
ImageElement = fallbackIcon
break
}
default: {
ImageElement = <i className="i-mgc-link-cute-re mr-2 shrink-0" style={sizeStyle} />
break
Expand All @@ -183,25 +213,7 @@
>
{ImageElement}
</AvatarImage>
<AvatarFallback asChild>
<span
style={
{
...sizeStyle,
"--fo-light-background": colors.light.background,
"--fo-dark-background": colors.dark.background,
} as any
}
className={cn(
"flex shrink-0 items-center justify-center rounded-sm",
"bg-[var(--fo-light-background)] text-white dark:bg-[var(--fo-dark-background)]",
"mr-2",
className,
)}
>
<span className="text-[9px]">{!!feed?.title && feed.title[0]}</span>
</span>
</AvatarFallback>
<AvatarFallback asChild>{fallbackIcon}</AvatarFallback>
</Avatar>
)
}
Expand Down
18 changes: 12 additions & 6 deletions apps/renderer/src/components/feed-summary.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { WEB_URL } from "@follow/shared/constants"

import { FeedIcon } from "~/components/feed-icon"
import { cn } from "~/lib/utils"
import type { FeedModel } from "~/models"
import type { TargetModel } from "~/models"

import { FeedCertification } from "./feed-certification"
import { EllipsisHorizontalTextWithTooltip } from "./ui/typography"
Expand All @@ -10,14 +12,14 @@ export function FollowSummary({
docs,
className,
}: {
feed: FeedModel
feed: TargetModel
docs?: string
className?: string
}) {
return (
<div className={cn("flex select-text flex-col gap-2 text-sm", className)}>
<a
href={feed.siteUrl || void 0}
href={feed.type === "feed" ? feed.siteUrl || void 0 : `${WEB_URL}/list/${feed.id}`}
target="_blank"
className="flex items-center"
rel="noreferrer"
Expand All @@ -31,7 +33,7 @@ export function FollowSummary({
<div className="truncate text-base font-semibold leading-tight">
<div className="flex items-center">
{feed.title}
<FeedCertification className="center" feed={feed} />
{feed.type === "feed" && <FeedCertification className="center" feed={feed} />}
</div>
<EllipsisHorizontalTextWithTooltip className="truncate text-xs font-normal text-zinc-500">
{feed.description}
Expand All @@ -40,8 +42,12 @@ export function FollowSummary({
</a>
<div className="flex items-center gap-1 truncate text-zinc-500">
<i className="i-mgc-right-cute-re shrink-0" />
<a href={feed.url || docs} target="_blank" rel="noreferrer">
{feed.url || docs}
<a
href={feed.type === "feed" ? feed.url || docs : `${WEB_URL}/list/${feed.id}`}
target="_blank"
rel="noreferrer"
>
{feed.type === "feed" ? feed.url || docs : `list:${feed.id}`}
</a>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ const safeUrl = (url: string, baseUrl: string) => {
export const MarkdownLink = (props: LinkProps) => {
const { view, feedId } = useEntryContentContext()

const feedSiteUrl = useFeedByIdSelector(feedId, (feed) => feed?.siteUrl)
const feedSiteUrl = useFeedByIdSelector(feedId, (feed) =>
"siteUrl" in feed ? feed.siteUrl : undefined,
)

const populatedFullHref = useMemo(() => {
const { href } = props
Expand Down
9 changes: 6 additions & 3 deletions apps/renderer/src/components/ui/radio-group/Radio.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,24 @@ export const Radio: FC<
onChange?.(e)
})
return (
<div className={cn("flex items-center gap-2", wrapperClassName)}>
<div className={cn("flex items-center", wrapperClassName)}>
<input
{...rest}
type="radio"
id={id ?? fallbackId}
className={cn(
"radio radio-accent radio-sm disabled:radio-current disabled:cursor-not-allowed disabled:text-theme-disabled",
"radio radio-accent radio-sm accent-accent disabled:radio-current disabled:cursor-not-allowed disabled:text-theme-disabled",
className,
)}
value={value}
checked={ctxValue === value}
onChange={handleChange}
/>

<label className={cn(rest.disabled ? "text-theme-disabled" : "")} htmlFor={id ?? fallbackId}>
<label
className={cn(rest.disabled ? "text-theme-disabled" : "", "pl-2")}
htmlFor={id ?? fallbackId}
>
{label}
</label>
</div>
Expand Down
4 changes: 2 additions & 2 deletions apps/renderer/src/database/schemas/feed.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { FeedModel } from "~/models"
import type { TargetModel } from "~/models"

export type DB_FeedUnread = {
id: string
count: number
}

export type DB_Feed = FeedModel & { id: string }
export type DB_Feed = TargetModel & { id: string }
92 changes: 64 additions & 28 deletions apps/renderer/src/hooks/biz/useFeedActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export const useFeedActions = ({

const items = useMemo(() => {
if (!feed) return []
const isList = feed?.type === "list"
const items: NativeMenuItem[] = [
{
type: "text" as const,
Expand All @@ -46,7 +47,9 @@ export const useFeedActions = ({
click: () => {
present({
title: t("sidebar.feed_actions.edit_feed"),
content: ({ dismiss }) => <FeedForm asWidget id={feedId} onSuccess={dismiss} />,
content: ({ dismiss }) => (
<FeedForm asWidget id={feedId} onSuccess={dismiss} isList={isList} />
),
})
},
},
Expand All @@ -60,7 +63,11 @@ export const useFeedActions = ({
},
{
type: "text" as const,
label: t("sidebar.feed_actions.navigate_to_feed"),
label: t(
isList
? "sidebar.feed_actions.navigate_to_list"
: "sidebar.feed_actions.navigate_to_feed",
),
shortcut: "Meta+G",
disabled: !isEntryList || getRouteParams().feedId === feedId,
click: () => {
Expand All @@ -71,14 +78,18 @@ export const useFeedActions = ({
type: "separator" as const,
disabled: isEntryList,
},
{
type: "text",
label: t("sidebar.feed_actions.mark_all_as_read"),
shortcut: "Meta+Shift+A",
disabled: isEntryList,
click: () => subscriptionActions.markReadByFeedIds([feedId]),
},
...(!feed.ownerUserId && !!feed.id
...(!isList
? [
{
type: "text" as const,
label: t("sidebar.feed_actions.mark_all_as_read"),
shortcut: "Meta+Shift+A",
disabled: isEntryList,
click: () => subscriptionActions.markReadByFeedIds({ feedIds: [feedId] }),
},
]
: []),
...(!feed.ownerUserId && !!feed.id && !isList
? [
{
type: "text" as const,
Expand All @@ -96,7 +107,11 @@ export const useFeedActions = ({
? [
{
type: "text" as const,
label: t("sidebar.feed_actions.feed_owned_by_you"),
label: t(
isList
? "sidebar.feed_actions.list_owned_by_you"
: "sidebar.feed_actions.feed_owned_by_you",
),
},
]
: []),
Expand All @@ -106,37 +121,58 @@ export const useFeedActions = ({
},
{
type: "text" as const,
label: t("sidebar.feed_actions.open_feed_in_browser"),
label: t(
isList
? "sidebar.feed_actions.open_list_in_browser"
: "sidebar.feed_actions.open_feed_in_browser",
),
disabled: isEntryList,
shortcut: "O",
click: () => window.open(`${WEB_URL}/feed/${feedId}?view=${view}`, "_blank"),
},
{
type: "text" as const,
label: t("sidebar.feed_actions.open_site_in_browser"),
shortcut: "Meta+O",
disabled: isEntryList,
click: () => {
const feed = getFeedById(feedId)
if (feed) {
feed.siteUrl && window.open(feed.siteUrl, "_blank")
}
},
click: () =>
window.open(
isList
? `${WEB_URL}/list/${feedId}?view=${view}`
: `${WEB_URL}/feed/${feedId}?view=${view}`,
"_blank",
),
},
...(!isList
? [
{
type: "text" as const,
label: t("sidebar.feed_actions.open_site_in_browser"),
shortcut: "Meta+O",
disabled: isEntryList,
click: () => {
const feed = getFeedById(feedId)
if (feed) {
"siteUrl" in feed && feed.siteUrl && window.open(feed.siteUrl, "_blank")
}
},
},
]
: []),
{
type: "separator",
disabled: isEntryList,
},
{
type: "text" as const,
label: t("sidebar.feed_actions.copy_feed_url"),
label: t(
isList ? "sidebar.feed_actions.copy_list_url" : "sidebar.feed_actions.copy_feed_url",
),
disabled: isEntryList,
shortcut: "Meta+C",
click: () => navigator.clipboard.writeText(feed.url),
click: () => {
const url = isList ? `${WEB_URL}/list/${feedId}?view=${view}` : feed.url
navigator.clipboard.writeText(url)
},
},
{
type: "text" as const,
label: t("sidebar.feed_actions.copy_feed_id"),
label: t(
isList ? "sidebar.feed_actions.copy_list_id" : "sidebar.feed_actions.copy_feed_id",
),
shortcut: "Meta+Shift+C",
disabled: isEntryList,
click: () => {
Expand Down
3 changes: 2 additions & 1 deletion apps/renderer/src/hooks/biz/useSubscriptionActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ export const useDeleteSubscription = ({ onSuccess }: { onSuccess?: () => void })
// TODO store action
await apiClient.subscriptions.$post({
json: {
url: feed.url,
url: feed.type === "feed" ? feed.url : undefined,
listId: feed.type === "list" ? feed.id : undefined,
view: subscription.view,
category: subscription.category,
isPrivate: subscription.isPrivate,
Expand Down
6 changes: 5 additions & 1 deletion apps/renderer/src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ export function getEntriesParams({ id, view }: { id?: number | string; view?: nu
if (id === FEED_COLLECTION_LIST) {
params.isCollection = true
} else if (id && id !== ROUTE_FEED_PENDING) {
params.feedIdList = `${id}`.split(",")
if (id.toString().includes(",")) {
params.feedIdList = `${id}`.split(",")
} else {
params.feedId = `${id}`
}
}
if (view === FeedViewType.SocialMedia) {
params.withContent = true
Expand Down
Loading
Loading