Skip to content

Commit

Permalink
Merge branch 'dev' into feat/new-user-guide
Browse files Browse the repository at this point in the history
  • Loading branch information
hyoban authored Oct 21, 2024
2 parents 235eb07 + 93461e8 commit 01a8522
Show file tree
Hide file tree
Showing 21 changed files with 377 additions and 142 deletions.
8 changes: 8 additions & 0 deletions apps/renderer/src/atoms/server-configs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { atom } from "jotai"

import { createAtomHooks } from "~/lib/jotai"
import type { ServerConfigs } from "~/models"

export const [, , useServerConfigs, , getServerConfigs, setServerConfigs] = createAtomHooks(
atom<Nullable<ServerConfigs>>(null),
)
99 changes: 52 additions & 47 deletions apps/renderer/src/components/ui/tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ const tabsTriggerVariants = cva("", {
variant: {
default:
"py-1.5 border-b-2 border-transparent data-[state=active]:text-accent dark:data-[state=active]:text-theme-accent-500",
rounded:
"py-1 rounded-sm data-[state=active]:bg-theme-accent-300 dark:data-[state=active]:bg-theme-accent-800 data-[state=active]:shadow-sm",
rounded: "!py-1 !px-3 bg-transparent",
},
},
defaultVariants: {
Expand All @@ -68,58 +67,64 @@ const tabsTriggerVariants = cva("", {
export interface TabsTriggerProps
extends React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>,
VariantProps<typeof tabsTriggerVariants> {}
const TabsTrigger = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Trigger>,
TabsTriggerProps
>(({ className, variant, children, ...props }, ref) => {
const triggerRef = React.useRef(null)
React.useImperativeHandle(ref, () => triggerRef.current!, [ref])
const TabsTrigger = React.forwardRef<HTMLDivElement, TabsTriggerProps>(
({ className, variant, children, ...props }, ref) => {
const triggerRef = React.useRef<HTMLDivElement>(null)
React.useImperativeHandle(ref, () => triggerRef.current!, [])

const [isSelect, setIsSelect] = React.useState(false)
const id = React.useContext(TabsIdContext)
const layoutId = `tab-selected-underline-${id}`
React.useLayoutEffect(() => {
if (!triggerRef.current) return
const [isSelect, setIsSelect] = React.useState(false)
const id = React.useContext(TabsIdContext)
const layoutId = `tab-selected-underline-${id}`
React.useLayoutEffect(() => {
if (!triggerRef.current) return

const trigger = triggerRef.current as HTMLElement
const trigger = triggerRef.current as HTMLElement

const isSelect = trigger.dataset.state === "active"
setIsSelect(isSelect)
const ob = new MutationObserver(() => {
const isSelect = trigger.dataset.state === "active"
setIsSelect(isSelect)
})
ob.observe(trigger, {
attributes: true,
attributeFilter: ["data-state"],
})
const ob = new MutationObserver(() => {
const isSelect = trigger.dataset.state === "active"
setIsSelect(isSelect)
})
ob.observe(trigger, {
attributes: true,
attributeFilter: ["data-state"],
})

return () => {
ob.disconnect()
}
}, [])
return () => {
ob.disconnect()
}
}, [])

return (
<TabsPrimitive.Trigger
ref={triggerRef}
className={cn(
"inline-flex items-center justify-center whitespace-nowrap px-3 text-sm font-medium ring-offset-background transition-all disabled:pointer-events-none disabled:opacity-50 data-[state=active]:text-theme-foreground",
"relative",
tabsTriggerVariants({ variant }),
className,
)}
{...props}
>
{children}
{isSelect && (
<m.span
layoutId={layoutId}
className="absolute -bottom-1 h-0.5 w-[calc(100%-16px)] rounded bg-accent"
/>
)}
</TabsPrimitive.Trigger>
)
})
return (
<TabsPrimitive.Trigger
ref={triggerRef as any}
className={cn(
"inline-flex items-center justify-center whitespace-nowrap px-3 text-sm font-medium ring-offset-background transition-all disabled:pointer-events-none disabled:opacity-50 data-[state=active]:text-theme-foreground",
"group relative z-[1]",
tabsTriggerVariants({ variant }),
// !isSelect &&
// "hover:before:bg-theme-item-hover before:content-[''] before:pointer-events-none before:absolute before:inset-y-0 before:inset-x-1 before:duration-200 before:opacity-60 before:rounded-lg",
// className,
)}
{...props}
>
{children}
{isSelect && (
<m.span
layoutId={layoutId}
className={cn(
"absolute",
variant === "rounded"
? "inset-0 z-[-1] rounded-lg bg-muted duration-200 group-hover:bg-theme-item-hover"
: "-bottom-1 h-0.5 w-[calc(100%-16px)] rounded bg-accent",
)}
/>
)}
</TabsPrimitive.Trigger>
)
},
)
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName

const TabsContent = React.forwardRef<
Expand Down
3 changes: 0 additions & 3 deletions apps/renderer/src/constants/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,4 @@ export const ROUTE_FEED_IN_FOLDER = "folder-"
export const ROUTE_FEED_IN_LIST = "list-"
export const ROUTE_FEED_IN_INBOX = "inbox-"

export const DAILY_CLAIM_AMOUNT = "20"
export const INVITATION_PRICE = "100"

export const INBOX_PREFIX_ID = "inbox-"
37 changes: 37 additions & 0 deletions apps/renderer/src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { memoize } from "lodash-es"
import { twMerge } from "tailwind-merge"
import { parse } from "tldts"

import { getServerConfigs } from "~/atoms/server-configs"
import type { MediaModel } from "~/models"
import type { RSSHubRoute } from "~/modules/discover/types"

Expand Down Expand Up @@ -286,3 +287,39 @@ export const filterSmallMedia = (media: MediaModel) => {
(m) => !(m.type === "photo" && m.width && m.width < 65 && m.height && m.height < 65),
)
}

export const getLevelMultiplier = (level: number) => {
if (level === 0) {
return 0.1
}
const serverConfigs = getServerConfigs()
if (!serverConfigs) {
return 1
}
const level1Range = serverConfigs?.LEVEL_PERCENTAGES[3] - serverConfigs?.LEVEL_PERCENTAGES[2]
const percentageIndex = serverConfigs.LEVEL_PERCENTAGES.length - level
let levelCurrentRange
if (percentageIndex - 1 < 0) {
levelCurrentRange = serverConfigs?.LEVEL_PERCENTAGES[percentageIndex]
} else {
levelCurrentRange =
serverConfigs?.LEVEL_PERCENTAGES[percentageIndex] -
serverConfigs?.LEVEL_PERCENTAGES[percentageIndex - 1]
}
const rangeMultiplier = levelCurrentRange / level1Range

const poolMultiplier =
serverConfigs?.DAILY_POWER_PERCENTAGES[level] / serverConfigs?.DAILY_POWER_PERCENTAGES[1]

return (poolMultiplier / rangeMultiplier).toFixed(0)
}

export const getBlockchainExplorerUrl = () => {
const serverConfigs = getServerConfigs()

if (serverConfigs?.IS_RSS3_TESTNET) {
return `https://scan.testnet.rss3.io`
} else {
return `https://scan.rss3.io`
}
}
2 changes: 2 additions & 0 deletions apps/renderer/src/models/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,5 @@ export type ActionsInput = {
export const TransactionTypes = ["mint", "purchase", "tip", "withdraw"] as const

export type WalletModel = ExtractBizResponse<typeof apiClient.wallets.$get>["data"][number]

export type ServerConfigs = ExtractBizResponse<typeof apiClient.status.configs.$get>["data"]
2 changes: 1 addition & 1 deletion apps/renderer/src/modules/discover/form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ const SearchCard: FC<{
</Button>
<div className="ml-6 text-zinc-500">
<span className="font-medium text-zinc-800 dark:text-zinc-200">
{item.subscriptionCount}
{item.subscriptionCount ?? 0}
</span>{" "}
Followers
</div>
Expand Down
67 changes: 7 additions & 60 deletions apps/renderer/src/modules/entry-column/layouts/EntryListHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,21 @@ import { ImpressionView } from "~/components/common/ImpressionTracker"
import { ActionButton } from "~/components/ui/button"
import { DividerVertical } from "~/components/ui/divider"
import { RotatingRefreshIcon } from "~/components/ui/loading"
import { Tabs, TabsList, TabsTrigger } from "~/components/ui/tabs"
import { EllipsisHorizontalTextWithTooltip } from "~/components/ui/typography"
import { FEED_COLLECTION_LIST, ROUTE_ENTRY_PENDING, views } from "~/constants"
import { shortcuts } from "~/constants/shortcuts"
import { useNavigateEntry } from "~/hooks/biz/useNavigateEntry"
import { useRouteParams } from "~/hooks/biz/useRouteParams"
import { useIsOnline } from "~/hooks/common"
import { stopPropagation } from "~/lib/dom"
import { FeedViewType } from "~/lib/enum"
import { cn, getOS, isBizId } from "~/lib/utils"
import { useAIDailyReportModal } from "~/modules/ai/ai-daily/hooks"
import { EntryHeader } from "~/modules/entry-content/header"
import { InboxItem, ListItem } from "~/modules/feed-column/item"
import { useRefreshFeedMutation } from "~/queries/feed"
import { useFeedById, useFeedHeaderTitle } from "~/store/feed"
import { useSubscriptionStore } from "~/store/subscription"

import { MarkAllReadWithOverlay } from "../components/mark-all-button"
import { TimelineTabs } from "./TimelineTabs"

export const EntryListHeader: FC<{
totalCount: number
Expand All @@ -40,24 +37,14 @@ export const EntryListHeader: FC<{

const unreadOnly = useGeneralSettingKey("unreadOnly")

const { feedId, entryId, view, listId, inboxId } = routerParams
const { feedId, entryId, view, listId } = routerParams

const headerTitle = useFeedHeaderTitle()
const os = getOS()

const titleAtBottom = IN_ELECTRON && os === "macOS"
const isInCollectionList = feedId === FEED_COLLECTION_LIST

const listsData = useSubscriptionStore((state) =>
state.feedIdByView[view].map((id) => state.data[id]).filter((s) => "listId" in s),
)
const inboxData = useSubscriptionStore((state) =>
state.feedIdByView[view].map((id) => state.data[id]).filter((s) => "inboxId" in s),
)
const hasData = listsData.length > 0 || inboxData.length > 0

const timeline = listId || inboxId || ""

const titleInfo = !!headerTitle && (
<div className={!titleAtBottom ? "min-w-0 translate-y-1" : void 0}>
<div className="mt-1 h-6 min-w-0 break-all text-lg font-bold leading-tight">
Expand All @@ -82,12 +69,11 @@ export const EntryListHeader: FC<{
const isList = !!listId

const containerRef = React.useRef<HTMLDivElement>(null)
const navigate = useNavigateEntry()

return (
<div
ref={containerRef}
className="mb-2 flex w-full flex-col pl-6 pr-4 pt-2.5 transition-[padding] duration-300 ease-in-out"
className="flex w-full flex-col pl-6 pr-4 pt-2.5 transition-[padding] duration-300 ease-in-out"
>
<div className={cn("flex w-full", titleAtBottom ? "justify-end" : "justify-between")}>
{!titleAtBottom && titleInfo}
Expand Down Expand Up @@ -115,8 +101,8 @@ export const EntryListHeader: FC<{
{view === FeedViewType.Pictures && <FilterNoImageButton />}
</AppendTaildingDivider>

{isOnline ? (
feed?.ownerUserId === user?.id &&
{isOnline &&
(feed?.ownerUserId === user?.id &&
isBizId(routerParams.feedId!) &&
feed?.type === "feed" ? (
<ActionButton
Expand All @@ -143,8 +129,7 @@ export const EntryListHeader: FC<{
isRefreshing={isRefreshing}
/>
</ActionButton>
)
) : null}
))}
{!isList && (
<>
<ActionButton
Expand All @@ -168,45 +153,7 @@ export const EntryListHeader: FC<{
</div>
</div>
{titleAtBottom && titleInfo}
{hasData && (
<Tabs
className="-ml-3 overflow-x-auto scrollbar-none"
value={timeline}
onValueChange={(val) => {
if (!val) {
navigate({
feedId: null,
entryId: null,
view,
})
}
}}
>
<TabsList className="h-10 border-b-0">
<TabsTrigger value="">Yours</TabsTrigger>
{listsData.map((s) => (
<TabsTrigger key={s.listId} value={s.listId!}>
<ListItem
listId={s.listId!}
view={view}
iconSize={16}
className="h-5 !bg-transparent p-0 leading-none"
/>
</TabsTrigger>
))}
{inboxData.map((s) => (
<TabsTrigger key={s.inboxId} value={s.inboxId!}>
<InboxItem
inboxId={s.inboxId!}
view={view}
iconSize={16}
className="h-5 !bg-transparent p-0 leading-none"
/>
</TabsTrigger>
))}
</TabsList>
</Tabs>
)}
<TimelineTabs />
</div>
)
}
Expand Down
64 changes: 64 additions & 0 deletions apps/renderer/src/modules/entry-column/layouts/TimelineTabs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { Tabs, TabsList, TabsTrigger } from "~/components/ui/tabs"
import { useNavigateEntry } from "~/hooks/biz/useNavigateEntry"
import { useRouteParams } from "~/hooks/biz/useRouteParams"
import { InboxItem, ListItem } from "~/modules/feed-column/item"
import { useSubscriptionStore } from "~/store/subscription"

export const TimelineTabs = () => {
const routerParams = useRouteParams()
const { view, listId, inboxId } = routerParams

const listsData = useSubscriptionStore((state) =>
state.feedIdByView[view].map((id) => state.data[id]).filter((s) => "listId" in s),
)
const inboxData = useSubscriptionStore((state) =>
state.feedIdByView[view].map((id) => state.data[id]).filter((s) => "inboxId" in s),
)
const hasData = listsData.length > 0 || inboxData.length > 0

const timeline = listId || inboxId || ""

const navigate = useNavigateEntry()
if (!hasData) return null
return (
<Tabs
className="-ml-3 -mr-4 mt-1 overflow-x-auto scrollbar-none"
value={timeline}
onValueChange={(val) => {
if (!val) {
navigate({
feedId: null,
entryId: null,
view,
})
}
}}
>
<TabsList className="h-10 border-b-0">
<TabsTrigger variant={"rounded"} className="p-0" value="">
Yours
</TabsTrigger>
{listsData.map((s) => (
<TabsTrigger variant={"rounded"} className="p-0" key={s.listId} value={s.listId!}>
<ListItem
listId={s.listId!}
view={view}
iconSize={16}
className="h-5 !bg-transparent p-0 leading-none"
/>
</TabsTrigger>
))}
{inboxData.map((s) => (
<TabsTrigger variant={"rounded"} key={s.inboxId} value={s.inboxId!}>
<InboxItem
inboxId={s.inboxId!}
view={view}
iconSize={16}
className="h-5 !bg-transparent p-0 leading-none"
/>
</TabsTrigger>
))}
</TabsList>
</Tabs>
)
}
Loading

0 comments on commit 01a8522

Please sign in to comment.