Message List: Reply focusing stack (#1260)
This commit is contained in:
parent
fa8e750433
commit
e744febfe8
@ -27,7 +27,7 @@ type StateProps = {
|
|||||||
unreadCount?: number;
|
unreadCount?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
type DispatchProps = Pick<GlobalActions, 'focusLastMessage'>;
|
type DispatchProps = Pick<GlobalActions, 'focusNextReply'>;
|
||||||
|
|
||||||
const FOCUS_MARGIN = 20;
|
const FOCUS_MARGIN = 20;
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ const ScrollDownButton: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
canPost,
|
canPost,
|
||||||
messageListType,
|
messageListType,
|
||||||
unreadCount,
|
unreadCount,
|
||||||
focusLastMessage,
|
focusNextReply,
|
||||||
}) => {
|
}) => {
|
||||||
const lang = useLang();
|
const lang = useLang();
|
||||||
// eslint-disable-next-line no-null/no-null
|
// eslint-disable-next-line no-null/no-null
|
||||||
@ -48,7 +48,7 @@ const ScrollDownButton: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (messageListType === 'thread') {
|
if (messageListType === 'thread') {
|
||||||
focusLastMessage();
|
focusNextReply();
|
||||||
} else {
|
} else {
|
||||||
const messagesContainer = elementRef.current!.parentElement!.querySelector<HTMLDivElement>('.MessageList')!;
|
const messagesContainer = elementRef.current!.parentElement!.querySelector<HTMLDivElement>('.MessageList')!;
|
||||||
const messageElements = messagesContainer.querySelectorAll<HTMLDivElement>('.message-list-item');
|
const messageElements = messagesContainer.querySelectorAll<HTMLDivElement>('.message-list-item');
|
||||||
@ -59,7 +59,7 @@ const ScrollDownButton: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
|
|
||||||
fastSmoothScroll(messagesContainer, lastMessageElement, 'end', FOCUS_MARGIN);
|
fastSmoothScroll(messagesContainer, lastMessageElement, 'end', FOCUS_MARGIN);
|
||||||
}
|
}
|
||||||
}, [isShown, messageListType, focusLastMessage]);
|
}, [isShown, messageListType, focusNextReply]);
|
||||||
|
|
||||||
const fabClassName = buildClassName(
|
const fabClassName = buildClassName(
|
||||||
'ScrollDownButton',
|
'ScrollDownButton',
|
||||||
@ -101,5 +101,5 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
unreadCount: chat && threadId === MAIN_THREAD_ID && messageListType === 'thread' ? chat.unreadCount : undefined,
|
unreadCount: chat && threadId === MAIN_THREAD_ID && messageListType === 'thread' ? chat.unreadCount : undefined,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
(setGlobal, actions): DispatchProps => pick(actions, ['focusLastMessage']),
|
(setGlobal, actions): DispatchProps => pick(actions, ['focusNextReply']),
|
||||||
)(ScrollDownButton));
|
)(ScrollDownButton));
|
||||||
|
|||||||
@ -416,8 +416,10 @@ const Message: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
}, [botSender, openUserInfo]);
|
}, [botSender, openUserInfo]);
|
||||||
|
|
||||||
const handleReplyClick = useCallback((): void => {
|
const handleReplyClick = useCallback((): void => {
|
||||||
focusMessage({ chatId, threadId, messageId: message.replyToMessageId });
|
focusMessage({
|
||||||
}, [focusMessage, chatId, threadId, message.replyToMessageId]);
|
chatId, threadId, messageId: message.replyToMessageId, replyMessageId: messageId,
|
||||||
|
});
|
||||||
|
}, [focusMessage, chatId, threadId, message.replyToMessageId, messageId]);
|
||||||
|
|
||||||
const handleMediaClick = useCallback((): void => {
|
const handleMediaClick = useCallback((): void => {
|
||||||
openMediaViewer({
|
openMediaViewer({
|
||||||
|
|||||||
@ -58,6 +58,7 @@ export interface Thread {
|
|||||||
noWebPage?: boolean;
|
noWebPage?: boolean;
|
||||||
threadInfo?: ApiThreadInfo;
|
threadInfo?: ApiThreadInfo;
|
||||||
firstMessageId?: number;
|
firstMessageId?: number;
|
||||||
|
replyStack?: number[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export type GlobalState = {
|
export type GlobalState = {
|
||||||
@ -424,7 +425,7 @@ export type ActionTypes = (
|
|||||||
'openTelegramLink' | 'openChatByUsername' | 'requestThreadInfoUpdate' | 'setScrollOffset' | 'unpinAllMessages' |
|
'openTelegramLink' | 'openChatByUsername' | 'requestThreadInfoUpdate' | 'setScrollOffset' | 'unpinAllMessages' |
|
||||||
'setReplyingToId' | 'setEditingId' | 'editLastMessage' | 'saveDraft' | 'clearDraft' | 'loadPinnedMessages' |
|
'setReplyingToId' | 'setEditingId' | 'editLastMessage' | 'saveDraft' | 'clearDraft' | 'loadPinnedMessages' |
|
||||||
'loadMessageLink' | 'toggleMessageWebPage' | 'replyToNextMessage' | 'deleteChatUser' | 'deleteChat' |
|
'loadMessageLink' | 'toggleMessageWebPage' | 'replyToNextMessage' | 'deleteChatUser' | 'deleteChat' |
|
||||||
'reportMessages' |
|
'reportMessages' | 'focusNextReply' |
|
||||||
// scheduled messages
|
// scheduled messages
|
||||||
'loadScheduledHistory' | 'sendScheduledMessages' | 'rescheduleMessage' | 'deleteScheduledMessages' |
|
'loadScheduledHistory' | 'sendScheduledMessages' | 'rescheduleMessage' | 'deleteScheduledMessages' |
|
||||||
// poll result
|
// poll result
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import { addReducer, setGlobal } from '../../../lib/teact/teactn';
|
import { addReducer, setGlobal } from '../../../lib/teact/teactn';
|
||||||
import {
|
import {
|
||||||
exitMessageSelectMode,
|
exitMessageSelectMode, replaceThreadParam, updateCurrentMessageList,
|
||||||
updateCurrentMessageList,
|
|
||||||
} from '../../reducers';
|
} from '../../reducers';
|
||||||
import { selectCurrentMessageList } from '../../selectors';
|
import { selectCurrentMessageList } from '../../selectors';
|
||||||
import { closeLocalTextSearch } from './localSearch';
|
import { closeLocalTextSearch } from './localSearch';
|
||||||
@ -19,6 +18,7 @@ addReducer('openChat', (global, actions, payload) => {
|
|||||||
|| currentMessageList.threadId !== threadId
|
|| currentMessageList.threadId !== threadId
|
||||||
|| currentMessageList.type !== type
|
|| currentMessageList.type !== type
|
||||||
)) {
|
)) {
|
||||||
|
global = replaceThreadParam(global, id, threadId, 'replyStack', []);
|
||||||
global = exitMessageSelectMode(global);
|
global = exitMessageSelectMode(global);
|
||||||
global = closeLocalTextSearch(global);
|
global = closeLocalTextSearch(global);
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,7 @@ import {
|
|||||||
selectChatMessages,
|
selectChatMessages,
|
||||||
selectAllowedMessageActions,
|
selectAllowedMessageActions,
|
||||||
selectMessageIdsByGroupId,
|
selectMessageIdsByGroupId,
|
||||||
selectForwardedMessageIdsByGroupId, selectIsViewportNewest, selectReplyingToId,
|
selectForwardedMessageIdsByGroupId, selectIsViewportNewest, selectReplyingToId, selectReplyStack,
|
||||||
} from '../../selectors';
|
} from '../../selectors';
|
||||||
import { findLast } from '../../../util/iteratees';
|
import { findLast } from '../../../util/iteratees';
|
||||||
import { IS_TOUCH_ENV } from '../../../util/environment';
|
import { IS_TOUCH_ENV } from '../../../util/environment';
|
||||||
@ -240,9 +240,39 @@ addReducer('focusLastMessage', (global, actions) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
addReducer('focusNextReply', (global, actions) => {
|
||||||
|
const currentMessageList = selectCurrentMessageList(global);
|
||||||
|
if (!currentMessageList) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { chatId, threadId } = currentMessageList;
|
||||||
|
|
||||||
|
const replyStack = selectReplyStack(global, chatId, threadId);
|
||||||
|
|
||||||
|
if (!replyStack || replyStack.length === 0) {
|
||||||
|
actions.focusLastMessage();
|
||||||
|
} else {
|
||||||
|
const messageId = replyStack.pop();
|
||||||
|
|
||||||
|
global = replaceThreadParam(global, chatId, threadId, 'replyStack', [...replyStack]);
|
||||||
|
|
||||||
|
setGlobal(global);
|
||||||
|
|
||||||
|
actions.focusMessage({
|
||||||
|
chatId,
|
||||||
|
threadId,
|
||||||
|
messageId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
});
|
||||||
|
|
||||||
addReducer('focusMessage', (global, actions, payload) => {
|
addReducer('focusMessage', (global, actions, payload) => {
|
||||||
const {
|
const {
|
||||||
chatId, threadId = MAIN_THREAD_ID, messageListType = 'thread', noHighlight, groupedId, groupedChatId,
|
chatId, threadId = MAIN_THREAD_ID, messageListType = 'thread', noHighlight, groupedId, groupedChatId,
|
||||||
|
replyMessageId,
|
||||||
} = payload!;
|
} = payload!;
|
||||||
|
|
||||||
let { messageId } = payload!;
|
let { messageId } = payload!;
|
||||||
@ -275,6 +305,11 @@ addReducer('focusMessage', (global, actions, payload) => {
|
|||||||
global = updateFocusedMessage(global, chatId, messageId, noHighlight);
|
global = updateFocusedMessage(global, chatId, messageId, noHighlight);
|
||||||
global = updateFocusDirection(global, undefined);
|
global = updateFocusDirection(global, undefined);
|
||||||
|
|
||||||
|
if (replyMessageId) {
|
||||||
|
const replyStack = selectReplyStack(global, chatId, threadId) || [];
|
||||||
|
global = replaceThreadParam(global, chatId, threadId, 'replyStack', [...replyStack, replyMessageId]);
|
||||||
|
}
|
||||||
|
|
||||||
if (shouldSwitchChat) {
|
if (shouldSwitchChat) {
|
||||||
global = updateFocusDirection(global, FocusDirection.Static);
|
global = updateFocusDirection(global, FocusDirection.Static);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -150,6 +150,10 @@ export function selectFirstMessageId(global: GlobalState, chatId: number, thread
|
|||||||
return selectThreadParam(global, chatId, threadId, 'firstMessageId');
|
return selectThreadParam(global, chatId, threadId, 'firstMessageId');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function selectReplyStack(global: GlobalState, chatId: number, threadId: number) {
|
||||||
|
return selectThreadParam(global, chatId, threadId, 'replyStack');
|
||||||
|
}
|
||||||
|
|
||||||
export function selectThreadOriginChat(global: GlobalState, chatId: number, threadId: number) {
|
export function selectThreadOriginChat(global: GlobalState, chatId: number, threadId: number) {
|
||||||
if (threadId === MAIN_THREAD_ID) {
|
if (threadId === MAIN_THREAD_ID) {
|
||||||
return selectChat(global, chatId);
|
return selectChat(global, chatId);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user