FAB: Scroll to unread reaction on click (#4709)
This commit is contained in:
parent
e2c6199431
commit
a4b72cfd3e
@ -26,7 +26,8 @@ import type {
|
||||
} from '../../../global/types';
|
||||
import type { ObserveFn } from '../../../hooks/useIntersectionObserver';
|
||||
import type {
|
||||
FocusDirection, IAlbum, ISettings, ThreadId,
|
||||
FocusDirection, IAlbum, ISettings, ScrollTargetPosition,
|
||||
ThreadId,
|
||||
} from '../../../types';
|
||||
import type { Signal } from '../../../util/signals';
|
||||
import type { PinnedIntersectionChangedCallback } from '../hooks/usePinnedMessage';
|
||||
@ -234,6 +235,7 @@ type StateProps = {
|
||||
focusDirection?: FocusDirection;
|
||||
focusedQuote?: string;
|
||||
noFocusHighlight?: boolean;
|
||||
scrollTargetPosition?: ScrollTargetPosition;
|
||||
isResizingContainer?: boolean;
|
||||
isForwarding?: boolean;
|
||||
isChatWithSelf?: boolean;
|
||||
@ -354,6 +356,7 @@ const Message: FC<OwnProps & StateProps> = ({
|
||||
focusDirection,
|
||||
focusedQuote,
|
||||
noFocusHighlight,
|
||||
scrollTargetPosition,
|
||||
isResizingContainer,
|
||||
isForwarding,
|
||||
isChatWithSelf,
|
||||
@ -770,7 +773,15 @@ const Message: FC<OwnProps & StateProps> = ({
|
||||
);
|
||||
|
||||
useFocusMessage(
|
||||
ref, chatId, isFocused, focusDirection, noFocusHighlight, isResizingContainer, isJustAdded, Boolean(focusedQuote),
|
||||
ref,
|
||||
chatId,
|
||||
isFocused,
|
||||
focusDirection,
|
||||
noFocusHighlight,
|
||||
isResizingContainer,
|
||||
isJustAdded,
|
||||
Boolean(focusedQuote),
|
||||
scrollTargetPosition,
|
||||
);
|
||||
|
||||
const viaBusinessBotTitle = viaBusinessBot ? getSenderTitle(lang, viaBusinessBot) : undefined;
|
||||
@ -1659,7 +1670,8 @@ export default memo(withGlobal<OwnProps>(
|
||||
);
|
||||
|
||||
const {
|
||||
direction: focusDirection, noHighlight: noFocusHighlight, isResizingContainer, quote: focusedQuote,
|
||||
direction: focusDirection, noHighlight: noFocusHighlight, isResizingContainer,
|
||||
quote: focusedQuote, scrollTargetPosition,
|
||||
} = (isFocused && focusedMessage) || {};
|
||||
|
||||
const { query: highlight } = selectCurrentTextSearch(global) || {};
|
||||
@ -1795,6 +1807,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
noFocusHighlight,
|
||||
isResizingContainer,
|
||||
focusedQuote,
|
||||
scrollTargetPosition,
|
||||
}),
|
||||
senderBoosts,
|
||||
tags: global.savedReactionTags?.byKey,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { useLayoutEffect, useRef } from '../../../../lib/teact/teact';
|
||||
import { addExtraClass } from '../../../../lib/teact/teact-dom';
|
||||
|
||||
import type { FocusDirection } from '../../../../types';
|
||||
import type { FocusDirection, ScrollTargetPosition } from '../../../../types';
|
||||
|
||||
import {
|
||||
requestForcedReflow, requestMeasure, requestMutation,
|
||||
@ -22,6 +22,7 @@ export default function useFocusMessage(
|
||||
isResizingContainer?: boolean,
|
||||
isJustAdded?: boolean,
|
||||
isQuote?: boolean,
|
||||
scrollTargetPosition?: ScrollTargetPosition,
|
||||
) {
|
||||
const isRelocatedRef = useRef(!isJustAdded);
|
||||
|
||||
@ -33,12 +34,13 @@ export default function useFocusMessage(
|
||||
const messagesContainer = elementRef.current.closest<HTMLDivElement>('.MessageList')!;
|
||||
// `noFocusHighlight` is always called with “scroll-to-bottom” buttons
|
||||
const isToBottom = noFocusHighlight;
|
||||
const scrollPosition = scrollTargetPosition || isToBottom ? 'end' : 'centerOrTop';
|
||||
|
||||
const exec = () => {
|
||||
const result = animateScroll(
|
||||
messagesContainer,
|
||||
elementRef.current!,
|
||||
isToBottom ? 'end' : 'centerOrTop',
|
||||
scrollPosition,
|
||||
FOCUS_MARGIN,
|
||||
focusDirection !== undefined ? (isToBottom ? BOTTOM_FOCUS_OFFSET : RELOCATED_FOCUS_OFFSET) : undefined,
|
||||
focusDirection,
|
||||
@ -69,6 +71,6 @@ export default function useFocusMessage(
|
||||
}
|
||||
}
|
||||
}, [
|
||||
elementRef, chatId, isFocused, focusDirection, noFocusHighlight, isResizingContainer, isQuote,
|
||||
elementRef, chatId, isFocused, focusDirection, noFocusHighlight, isResizingContainer, isQuote, scrollTargetPosition,
|
||||
]);
|
||||
}
|
||||
|
||||
@ -440,7 +440,9 @@ addActionHandler('focusNextReaction', (global, actions, payload): ActionReturnTy
|
||||
return undefined;
|
||||
}
|
||||
|
||||
actions.focusMessage({ chatId: chat.id, messageId: chat.unreadReactions[0], tabId });
|
||||
actions.focusMessage({
|
||||
chatId: chat.id, messageId: chat.unreadReactions[0], tabId, scrollTargetPosition: 'end',
|
||||
});
|
||||
actions.markMessagesRead({ messageIds: [chat.unreadReactions[0]], tabId });
|
||||
return undefined;
|
||||
});
|
||||
|
||||
@ -400,7 +400,7 @@ addActionHandler('focusNextReply', (global, actions, payload): ActionReturnType
|
||||
addActionHandler('focusMessage', (global, actions, payload): ActionReturnType => {
|
||||
const {
|
||||
chatId, threadId = MAIN_THREAD_ID, messageListType = 'thread', noHighlight, groupedId, groupedChatId,
|
||||
replyMessageId, isResizingContainer, shouldReplaceHistory, noForumTopicPanel, quote,
|
||||
replyMessageId, isResizingContainer, shouldReplaceHistory, noForumTopicPanel, quote, scrollTargetPosition,
|
||||
tabId = getCurrentTabId(),
|
||||
} = payload;
|
||||
|
||||
@ -445,6 +445,7 @@ addActionHandler('focusMessage', (global, actions, payload): ActionReturnType =>
|
||||
noHighlight,
|
||||
isResizingContainer,
|
||||
quote,
|
||||
scrollTargetPosition,
|
||||
}, tabId);
|
||||
global = updateFocusDirection(global, undefined, tabId);
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import type {
|
||||
ApiMessage, ApiQuickReply, ApiSponsoredMessage, ApiThreadInfo,
|
||||
} from '../../api/types';
|
||||
import type { FocusDirection, ThreadId } from '../../types';
|
||||
import type { FocusDirection, ScrollTargetPosition, ThreadId } from '../../types';
|
||||
import type {
|
||||
GlobalState, MessageList, MessageListType, TabArgs, TabThread, Thread,
|
||||
} from '../types';
|
||||
@ -643,6 +643,7 @@ export function updateFocusedMessage<T extends GlobalState>({
|
||||
noHighlight = false,
|
||||
isResizingContainer = false,
|
||||
quote,
|
||||
scrollTargetPosition,
|
||||
}: {
|
||||
global: T;
|
||||
chatId?: string;
|
||||
@ -651,6 +652,7 @@ export function updateFocusedMessage<T extends GlobalState>({
|
||||
noHighlight?: boolean;
|
||||
isResizingContainer?: boolean;
|
||||
quote?: string;
|
||||
scrollTargetPosition?: ScrollTargetPosition;
|
||||
},
|
||||
...[tabId = getCurrentTabId()]: TabArgs<T>): T {
|
||||
return updateTabState(global, {
|
||||
@ -662,6 +664,7 @@ export function updateFocusedMessage<T extends GlobalState>({
|
||||
noHighlight,
|
||||
isResizingContainer,
|
||||
quote,
|
||||
scrollTargetPosition,
|
||||
},
|
||||
}, tabId);
|
||||
}
|
||||
|
||||
@ -115,6 +115,7 @@ import type {
|
||||
PrivacyVisibility,
|
||||
ProfileEditProgress,
|
||||
ProfileTabType,
|
||||
ScrollTargetPosition,
|
||||
SettingsScreens,
|
||||
SharedMediaType,
|
||||
ShippingOption,
|
||||
@ -311,6 +312,7 @@ export type TabState = {
|
||||
noHighlight?: boolean;
|
||||
isResizingContainer?: boolean;
|
||||
quote?: string;
|
||||
scrollTargetPosition?: ScrollTargetPosition;
|
||||
};
|
||||
|
||||
selectedMessages?: {
|
||||
@ -1908,6 +1910,7 @@ export interface ActionPayloads {
|
||||
shouldReplaceHistory?: boolean;
|
||||
noForumTopicPanel?: boolean;
|
||||
quote?: string;
|
||||
scrollTargetPosition?: ScrollTargetPosition;
|
||||
} & WithTabId;
|
||||
|
||||
focusLastMessage: WithTabId | undefined;
|
||||
|
||||
@ -30,6 +30,8 @@ export enum FocusDirection {
|
||||
Static,
|
||||
}
|
||||
|
||||
export type ScrollTargetPosition = ScrollLogicalPosition | 'centerOrTop';
|
||||
|
||||
export interface IAlbum {
|
||||
albumId: string;
|
||||
messages: ApiMessage[];
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { getGlobal } from '../global';
|
||||
|
||||
import type { ScrollTargetPosition } from '../types';
|
||||
import { FocusDirection } from '../types';
|
||||
|
||||
import {
|
||||
@ -49,7 +50,7 @@ export function restartCurrentScrollAnimation() {
|
||||
function createMutateFunction(
|
||||
container: HTMLElement,
|
||||
element: HTMLElement,
|
||||
position: ScrollLogicalPosition | 'centerOrTop',
|
||||
position: ScrollTargetPosition,
|
||||
margin = 0,
|
||||
maxDistance = FAST_SMOOTH_MAX_DISTANCE,
|
||||
forceDirection?: FocusDirection,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user