From 0d910da7b2b880e83bdae3ac30bc0556861ab2f8 Mon Sep 17 00:00:00 2001 From: zubiden <19638254+zubiden@users.noreply.github.com> Date: Wed, 8 Oct 2025 12:33:44 +0200 Subject: [PATCH] Profile: Expand on avatar click (#6334) --- src/components/common/profile/ProfileInfo.tsx | 13 ++++++++++- src/components/left/main/ChatList.tsx | 7 +++++- src/components/right/Profile.tsx | 11 +++++++--- src/hooks/scroll/useTopOverscroll.tsx | 22 ++++++++++++++----- 4 files changed, 43 insertions(+), 10 deletions(-) diff --git a/src/components/common/profile/ProfileInfo.tsx b/src/components/common/profile/ProfileInfo.tsx index cd6a7a5bc..f74f10a9e 100644 --- a/src/components/common/profile/ProfileInfo.tsx +++ b/src/components/common/profile/ProfileInfo.tsx @@ -76,6 +76,7 @@ type OwnProps = { isForSettings?: boolean; canPlayVideo: boolean; isForMonoforum?: boolean; + onExpand?: NoneToVoidFunction; }; type StateProps = { @@ -130,6 +131,7 @@ const ProfileInfo = ({ theme, isPlain, savedGifts, + onExpand, }: OwnProps & StateProps) => { const { openMediaViewer, @@ -279,6 +281,15 @@ const ProfileInfo = ({ } }); + const handleMinimizedAvatarClick = useLastCallback(() => { + if (isForSettings) { + handleProfilePhotoClick(); + return; + } + + onExpand?.(); + }); + function handleSelectFallbackPhoto() { if (!isFirst) return; setHasSlideAnimation(true); @@ -565,7 +576,7 @@ const ProfileInfo = ({ size="jumbo" peer={peer} style={createVtnStyle('avatar', true)} - onClick={isForSettings ? handleProfilePhotoClick : undefined} + onClick={handleMinimizedAvatarClick} /> )} diff --git a/src/components/left/main/ChatList.tsx b/src/components/left/main/ChatList.tsx index dff9ca886..6fee30913 100644 --- a/src/components/left/main/ChatList.tsx +++ b/src/components/left/main/ChatList.tsx @@ -215,7 +215,12 @@ const ChatList: FC = ({ toggleStoryRibbon({ isShown: false, isArchived }); }); - useTopOverscroll(containerRef, handleShowStoryRibbon, handleHideStoryRibbon, isSaved); + useTopOverscroll({ + containerRef, + onOverscroll: handleShowStoryRibbon, + onReset: handleHideStoryRibbon, + isDisabled: isSaved, + }); function renderChats() { const viewportOffset = orderedIds!.indexOf(viewportIds![0]); diff --git a/src/components/right/Profile.tsx b/src/components/right/Profile.tsx index 096c6fe53..e1b4ed879 100644 --- a/src/components/right/Profile.tsx +++ b/src/components/right/Profile.tsx @@ -627,9 +627,13 @@ const Profile = ({ resetGiftProfileFilter({ peerId: chatId }); }); - useTopOverscroll( - containerRef, handleExpandProfile, handleCollapseProfile, !hasAvatar || !shouldRenderProfileInfo, - ); + useTopOverscroll({ + containerRef, + onOverscroll: handleExpandProfile, + onReset: handleCollapseProfile, + isOverscrolled: isProfileExpanded, + isDisabled: !hasAvatar || !shouldRenderProfileInfo, + }); useEffect(() => { if (!transitionRef.current || !IS_TOUCH_ENV) { @@ -1055,6 +1059,7 @@ const Profile = ({ peerId={peerId} canPlayVideo={isReady} isForMonoforum={Boolean(monoforumChannel)} + onExpand={handleExpandProfile} /> , - onOverscroll?: AnyToVoidFunction, - onReset?: AnyToVoidFunction, - isDisabled?: boolean, +export default function useTopOverscroll({ + containerRef, + isOverscrolled, + isDisabled, + onOverscroll, + onReset, +}: { + containerRef: ElementRef; + isOverscrolled?: boolean; + onOverscroll?: AnyToVoidFunction; + onReset?: AnyToVoidFunction; + isDisabled?: boolean; +}, ) { const [getState, setState] = useSignal('normal'); const activeScrollRef = useRef({ ...initialActiveScrollContext }); @@ -197,6 +205,10 @@ export default function useTopOverscroll( }; }, [containerRef, isDisabled, getState]); + useEffect(() => { + setState(isOverscrolled ? 'overscroll' : 'normal'); + }, [isOverscrolled, setState]); + useEffect(() => { const container = containerRef.current; if (isDisabled || !container) {