Skip to content

Commit

Permalink
feat: optimize the style of the profile to maximize the presentation …
Browse files Browse the repository at this point in the history
…of the content

Signed-off-by: Innei <i@innei.in>
  • Loading branch information
Innei committed Aug 1, 2024
1 parent 5915357 commit 96769fb
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 49 deletions.
1 change: 1 addition & 0 deletions icons/mgc/list_check_3_cute_re.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions icons/mgc/list_check_cute_re.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions src/renderer/src/components/user-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export const ProfileButton: FC<LoginProps> = memo((props) => {
const { user } = session || {}
const signOut = useSignOut()
const settingModalPresent = useSettingModal()
const presentUserProfile = usePresentUserProfileModal()
const presentUserProfile = usePresentUserProfileModal("dialog")
if (status !== "authenticated") {
return <LoginButton {...props} />
}
Expand Down Expand Up @@ -137,7 +137,7 @@ export const ProfileButton: FC<LoginProps> = memo((props) => {
window.open(`${repository.url}/releases`)
}}
>
<i className="i-mgc-gift-cute-re mr-1.5" />
<i className="i-mgc-download-2-cute-re mr-1.5" />
Download Desktop app
</DropdownMenuItem>
<DropdownMenuSeparator />
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/src/modules/entry-content/read-history.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ const EntryUser: Component<{
i: number
}> = ({ userId, i }) => {
const user = useUserById(userId)
const presentUserProfile = usePresentUserProfileModal()
const presentUserProfile = usePresentUserProfileModal("drawer")
if (!user) return null
return (
<Tooltip>
Expand Down
7 changes: 5 additions & 2 deletions src/renderer/src/modules/profile/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ export const useUserSubscriptionsQuery = (userId: string | undefined) => {
return subscriptions
}

export const usePresentUserProfileModal = () => {
export const usePresentUserProfileModal = (
variant: "drawer" | "dialog" = "dialog",
) => {
const { present } = useModalStack()

return useCallback(
Expand All @@ -53,11 +55,12 @@ export const usePresentUserProfileModal = () => {
content: () =>
createElement(UserProfileModalContent, {
userId,
variant,
}),
CustomModalComponent: NoopChildren,
clickOutsideToDismiss: true,
})
},
[present],
[present, variant],
)
}
183 changes: 140 additions & 43 deletions src/renderer/src/modules/profile/user-profile-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,16 @@ import { useSubscriptionStore } from "@renderer/store/subscription"
import { useAnimationControls } from "framer-motion"
import { throttle } from "lodash-es"
import type { FC } from "react"
import { Fragment, useEffect, useState } from "react"
import { Fragment, useEffect, useMemo, useRef, useState } from "react"

import { FeedForm } from "../discover/feed-form"

type ItemVariant = "loose" | "compact"
export const UserProfileModalContent: FC<{
userId: string
}> = ({ userId }) => {

variant: "drawer" | "dialog"
}> = ({ userId, variant }) => {
const user = useAuthQuery(
defineQuery(["profiles", userId], async () => {
const res = await apiClient.profiles.$get({
Expand All @@ -50,9 +53,9 @@ export const UserProfileModalContent: FC<{
const winHeight = useState(() => window.innerHeight)[0]

const [scrollerRef, setScrollerRef] = useState<HTMLDivElement | null>(null)

const [isHeaderSimple, setHeaderSimple] = useState(false)

const currentVisibleRef = useRef<Set<string>>()
useEffect(() => {
const $ref = scrollerRef

Expand All @@ -71,19 +74,54 @@ export const UserProfileModalContent: FC<{
return current
})
}, 16)

const currentVisible = new Set<string>()
const ob = new IntersectionObserver((en) => {
en.forEach((entry) => {
const id = (entry.target as HTMLElement).dataset.feedId as string
if (!id) return
if (entry.isIntersecting) {
currentVisible.add(id)
} else {
currentVisible.delete(id)
}
})

if (currentVisible.size === 0) return
currentVisibleRef.current = currentVisible
})

$ref.querySelectorAll("[data-feed-id]").forEach((el) => {
ob.observe(el)
})
return () => {
$ref.onscroll = null

ob.disconnect()
}
}, [scrollerRef])
}, [scrollerRef, subscriptions])

return (
<div className="container center h-full" onClick={modal.dismiss}>
<m.div
onClick={(e) => e.stopPropagation()}
tabIndex={-1}
initial="initial"
animate={controller}
variants={{
const modalVariant = useMemo(() => {
switch (variant) {
case "drawer": {
return {
enter: {
x: 0,
opacity: 1,
},
initial: {
x: 700,
opacity: 0.9,
},
exit: {
x: 750,
opacity: 0,
},
}
}

case "dialog": {
return {
enter: {
y: 0,
opacity: 1,
Expand All @@ -95,7 +133,27 @@ export const UserProfileModalContent: FC<{
exit: {
y: winHeight,
},
}}
}
}
}
}, [variant, winHeight])

const [itemStyle, setItemStyle] = useState("loose" as ItemVariant)
return (
<div
className={
variant === "drawer" ?
"flex h-full justify-end overflow-hidden" :
"container center h-full"
}
onClick={modal.dismiss}
>
<m.div
onClick={(e) => e.stopPropagation()}
tabIndex={-1}
initial="initial"
animate={controller}
variants={modalVariant}
transition={{
type: "spring",
mass: 0.4,
Expand All @@ -104,9 +162,40 @@ export const UserProfileModalContent: FC<{
}}
exit="exit"
layout="size"
className="shadow-perfect perfect-sm relative flex h-[80vh] flex-col items-center overflow-hidden rounded-xl border bg-theme-background p-8 lg:max-h-[calc(100vh-10rem)]"
className={cn(
"shadow-perfect perfect-sm relative flex flex-col items-center overflow-hidden rounded-xl border bg-theme-background p-8",
variant === "drawer" ?
"my-auto mr-4 h-[calc(100%-4rem)] w-[60ch] max-w-full" :
"h-[80vh] w-[500px] max-w-full lg:max-h-[calc(100vh-10rem)]",
)}
>
<div className="absolute right-2 top-2 z-10 flex items-center gap-2 text-[20px] opacity-80">
<ActionButton
tooltip="Toggle Item Style"
onClick={() => {
const currentVisible = currentVisibleRef.current
const topOfCurrent = currentVisible?.values().next().value

setItemStyle((current) =>
current === "loose" ? "compact" : "loose",
)
if (!topOfCurrent) return

nextFrame(() => {
scrollerRef
?.querySelector(`[data-feed-id="${topOfCurrent}"]`)
?.scrollIntoView()
})
}}
>
<i
className={cn(
itemStyle === "loose" ?
"i-mgc-list-check-3-cute-re" :
"i-mgc-list-check-cute-re",
)}
/>
</ActionButton>
<ActionButton
tooltip="Share"
onClick={() => {
Expand Down Expand Up @@ -166,9 +255,8 @@ export const UserProfileModalContent: FC<{
</m.div>
</div>
<ScrollArea.ScrollArea
mask
ref={setScrollerRef}
rootClassName="mb-4 h-[400px] grow w-[70ch] max-w-full px-5"
rootClassName="mb-4 h-[400px] grow max-w-full px-5 w-full"
viewportClassName="[&>div]:space-y-4"
>
{subscriptions.isLoading ? (
Expand All @@ -178,60 +266,69 @@ export const UserProfileModalContent: FC<{
/>
) : (
subscriptions.data &&
Object.keys(subscriptions.data)
.map((category) => (
<div key={category}>
<div className="mb-2 flex items-center text-2xl font-bold">
<h3>{category}</h3>
</div>
<div>
{subscriptions.data?.[category].map((subscription) => (
<SubscriptionItem
key={subscription.feedId}
subscription={subscription}
/>
))}
</div>
Object.keys(subscriptions.data).map((category) => (
<div key={category}>
<div className="mb-2 flex items-center text-2xl font-bold">
<h3>{category}</h3>
</div>
<div>
{subscriptions.data?.[category].map((subscription) => (
<SubscriptionItem
variant={itemStyle}
key={subscription.feedId}
subscription={subscription}
/>
))}
</div>
))
</div>
))
)}
</ScrollArea.ScrollArea>
</Fragment>
)}

{!user.data && (
<LoadingCircle
size="large"
className="center h-[80vh] w-[70ch] max-w-full"
/>
)}
{!user.data && <LoadingCircle size="large" className="center h-full" />}
</m.div>
</div>
)
}

const SubscriptionItem: FC<{
subscription: SubscriptionModel
}> = ({ subscription }) => {

variant: ItemVariant
}> = ({ subscription, variant }) => {
const isFollowed = !!useSubscriptionStore(
(state) => state.data[subscription.feedId],
)
const { present } = useModalStack()
const isLoose = variant === "loose"
return (
<div className="group relative border-b py-5">
<div
className={cn("group relative", isLoose ? "border-b py-5" : "py-2")}
data-feed-id={subscription.feedId}
>
<a
className="flex flex-1 cursor-default"
href={subscription.feeds.siteUrl!}
target="_blank"
>
<FeedIcon feed={subscription.feeds} size={22} className="mr-3" />
<div className={cn("w-0 flex-1 grow", "group-hover:grow-[0.85]")}>
<div
className={cn(
"w-0 flex-1 grow",
"group-hover:grow-[0.85]",
!isLoose && "flex items-center",
)}
>
<div className="truncate font-medium leading-none">
{subscription.feeds?.title}
</div>
<div className="mt-1 line-clamp-1 text-xs text-zinc-500">
{subscription.feeds?.description}
</div>
{isLoose && (
<div className="mt-1 line-clamp-1 text-xs text-zinc-500">
{subscription.feeds?.description}
</div>
)}
</div>
<div className="absolute right-0 opacity-0 transition-opacity group-hover:opacity-100">
<StyledButton
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/src/pages/(main)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ const FeedResponsiveResizerContainer = ({
<>
<div
className={cn(
"shrink-0",
"shrink-0 overflow-hidden",
"absolute inset-y-0 z-10",
!feedColumnShow ? "-translate-x-full" : "",
)}
Expand Down

0 comments on commit 96769fb

Please sign in to comment.