Scroll Down Button: Fix flickering mention & reaction buttons (#2344)
This commit is contained in:
parent
4f68d23f73
commit
e6866aaeaf
@ -10,6 +10,19 @@
|
||||
z-index: var(--z-scroll-down-button);
|
||||
pointer-events: none;
|
||||
|
||||
.hidden {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.reactions {
|
||||
transition: 0.2s ease opacity, 0.25s cubic-bezier(0.34, 1.56, 0.64, 1) transform;
|
||||
}
|
||||
|
||||
.transform-down {
|
||||
transform: translateY(4rem);
|
||||
}
|
||||
|
||||
.unread {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@ -93,24 +93,27 @@ const FloatingActionButtons: FC<OwnProps & StateProps> = ({
|
||||
|
||||
return (
|
||||
<div ref={elementRef} className={fabClassName}>
|
||||
{hasUnreadReactions && (
|
||||
<ScrollDownButton
|
||||
icon="heart-outline"
|
||||
ariaLabelLang="AccDescrReactionMentionDown"
|
||||
onClick={focusNextReaction}
|
||||
onReadAll={readAllReactions}
|
||||
unreadCount={reactionsCount}
|
||||
/>
|
||||
)}
|
||||
{hasUnreadMentions && (
|
||||
<ScrollDownButton
|
||||
icon="mention"
|
||||
ariaLabelLang="AccDescrMentionDown"
|
||||
onClick={focusNextMention}
|
||||
onReadAll={readAllMentions}
|
||||
unreadCount={mentionsCount}
|
||||
/>
|
||||
)}
|
||||
<ScrollDownButton
|
||||
icon="heart-outline"
|
||||
ariaLabelLang="AccDescrReactionMentionDown"
|
||||
onClick={focusNextReaction}
|
||||
onReadAll={readAllReactions}
|
||||
unreadCount={reactionsCount}
|
||||
className={buildClassName(
|
||||
styles.reactions,
|
||||
!hasUnreadReactions && styles.hidden,
|
||||
!hasUnreadMentions && styles.transformDown,
|
||||
)}
|
||||
/>
|
||||
|
||||
<ScrollDownButton
|
||||
icon="mention"
|
||||
ariaLabelLang="AccDescrMentionDown"
|
||||
onClick={focusNextMention}
|
||||
onReadAll={readAllMentions}
|
||||
unreadCount={mentionsCount}
|
||||
className={!hasUnreadMentions && styles.hidden}
|
||||
/>
|
||||
|
||||
<ScrollDownButton
|
||||
icon="arrow-down"
|
||||
|
||||
@ -244,7 +244,6 @@ const MiddleColumn: FC<OwnProps & StateProps> = ({
|
||||
|
||||
useOnChange(() => {
|
||||
setDropAreaState(DropAreaState.None);
|
||||
setIsFabShown(undefined);
|
||||
setIsNotchShown(undefined);
|
||||
}, [chatId]);
|
||||
|
||||
|
||||
@ -69,6 +69,8 @@ export default function useScrollHooks(
|
||||
const isNearBottom = scrollBottom <= FAB_THRESHOLD;
|
||||
const isAtBottom = scrollBottom <= NOTCH_THRESHOLD;
|
||||
|
||||
if (scrollHeight === 0) return;
|
||||
|
||||
onFabToggle(isUnread ? !isAtBottom : !isNearBottom);
|
||||
onNotchToggle(!isAtBottom);
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ class TelegramClient {
|
||||
private invokeMiddleware?: <A, R>(mockClient: TelegramClient, request: Api.Request<A, R>)
|
||||
=> Promise<R | undefined | 'pass'>;
|
||||
|
||||
private mockData: MockTypes = {
|
||||
public mockData: MockTypes = {
|
||||
users: [],
|
||||
chats: [],
|
||||
channels: [],
|
||||
@ -93,7 +93,7 @@ class TelegramClient {
|
||||
}
|
||||
|
||||
getDialogs(type: 'active' | 'archived' = 'active') {
|
||||
return this.mockData.dialogs[type].map((dialog) => createMockedDialog(dialog, this.mockData));
|
||||
return this.mockData.dialogs[type].map((dialog) => createMockedDialog(dialog.id, this.mockData));
|
||||
}
|
||||
|
||||
start({
|
||||
|
||||
16
src/lib/gramjs/client/__invokeMiddlewares__/mention.ts
Normal file
16
src/lib/gramjs/client/__invokeMiddlewares__/mention.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import Api from '../../tl/api';
|
||||
import type TelegramClient from '../MockClient';
|
||||
import createMockedMessage from '../mockUtils/createMockedMessage';
|
||||
|
||||
export default async function<A, R>(mockClient: TelegramClient, request: Api.Request<A, R>) {
|
||||
if (request instanceof Api.messages.GetUnreadMentions) {
|
||||
return new Api.messages.Messages({
|
||||
messages: [
|
||||
createMockedMessage('2', 13, mockClient.mockData),
|
||||
],
|
||||
chats: [],
|
||||
users: [],
|
||||
});
|
||||
}
|
||||
return 'pass';
|
||||
}
|
||||
83
src/lib/gramjs/client/__mocks__/mention.json
Normal file
83
src/lib/gramjs/client/__mocks__/mention.json
Normal file
@ -0,0 +1,83 @@
|
||||
{
|
||||
"users": [
|
||||
{
|
||||
"id": "1",
|
||||
"self": true,
|
||||
"username": "test"
|
||||
}
|
||||
],
|
||||
"chats": [
|
||||
],
|
||||
"channels": [
|
||||
{
|
||||
"id": "2",
|
||||
"title": "Mention",
|
||||
"creator": true
|
||||
}
|
||||
],
|
||||
"dialogs": {
|
||||
"active": [
|
||||
{
|
||||
"id": "2",
|
||||
"unreadMentionsCount": 1,
|
||||
"unreadCount": 1,
|
||||
"topMessage": 13,
|
||||
"readInboxMaxId": 12
|
||||
}
|
||||
],
|
||||
"archived": []
|
||||
},
|
||||
"messages": {
|
||||
"2": [
|
||||
{
|
||||
"id": 3,
|
||||
"message": "Hello!"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"message": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed at nibh accumsan, condimentum nunc at, volutpat dolor. Integer laoreet dui in neque commodo, eu sagittis nibh consequat. Integer eu velit quis odio dictum vulputate auctor nec metus. Nunc vestibulum iaculis rhoncus. Vivamus pretium mollis odio condimentum euismod. Aliquam erat volutpat. 2!"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"message": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed at nibh accumsan, condimentum nunc at, volutpat dolor. Integer laoreet dui in neque commodo, eu sagittis nibh consequat. Integer eu velit quis odio dictum vulputate auctor nec metus. Nunc vestibulum iaculis rhoncus. Vivamus pretium mollis odio condimentum euismod. Aliquam erat volutpat. 2!"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"message": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed at nibh accumsan, condimentum nunc at, volutpat dolor. Integer laoreet dui in neque commodo, eu sagittis nibh consequat. Integer eu velit quis odio dictum vulputate auctor nec metus. Nunc vestibulum iaculis rhoncus. Vivamus pretium mollis odio condimentum euismod. Aliquam erat volutpat. 2!"
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"message": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed at nibh accumsan, condimentum nunc at, volutpat dolor. Integer laoreet dui in neque commodo, eu sagittis nibh consequat. Integer eu velit quis odio dictum vulputate auctor nec metus. Nunc vestibulum iaculis rhoncus. Vivamus pretium mollis odio condimentum euismod. Aliquam erat volutpat. 2!"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"message": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed at nibh accumsan, condimentum nunc at, volutpat dolor. Integer laoreet dui in neque commodo, eu sagittis nibh consequat. Integer eu velit quis odio dictum vulputate auctor nec metus. Nunc vestibulum iaculis rhoncus. Vivamus pretium mollis odio condimentum euismod. Aliquam erat volutpat. 2!"
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"message": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed at nibh accumsan, condimentum nunc at, volutpat dolor. Integer laoreet dui in neque commodo, eu sagittis nibh consequat. Integer eu velit quis odio dictum vulputate auctor nec metus. Nunc vestibulum iaculis rhoncus. Vivamus pretium mollis odio condimentum euismod. Aliquam erat volutpat. 2!"
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"message": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed at nibh accumsan, condimentum nunc at, volutpat dolor. Integer laoreet dui in neque commodo, eu sagittis nibh consequat. Integer eu velit quis odio dictum vulputate auctor nec metus. Nunc vestibulum iaculis rhoncus. Vivamus pretium mollis odio condimentum euismod. Aliquam erat volutpat. 2!"
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"message": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed at nibh accumsan, condimentum nunc at, volutpat dolor. Integer laoreet dui in neque commodo, eu sagittis nibh consequat. Integer eu velit quis odio dictum vulputate auctor nec metus. Nunc vestibulum iaculis rhoncus. Vivamus pretium mollis odio condimentum euismod. Aliquam erat volutpat. 2!"
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"message": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed at nibh accumsan, condimentum nunc at, volutpat dolor. Integer laoreet dui in neque commodo, eu sagittis nibh consequat. Integer eu velit quis odio dictum vulputate auctor nec metus. Nunc vestibulum iaculis rhoncus. Vivamus pretium mollis odio condimentum euismod. Aliquam erat volutpat. 2!"
|
||||
},
|
||||
{
|
||||
"id": 13,
|
||||
"mentioned": true,
|
||||
"mediaUnread": true,
|
||||
"message": "@test"
|
||||
}
|
||||
]
|
||||
},
|
||||
"availableReactions": [],
|
||||
"dialogFilters": [],
|
||||
"documents": []
|
||||
}
|
||||
@ -3,7 +3,7 @@ import type Api from '../../tl/api';
|
||||
import type { ApiAvailableReaction } from '../../../../api/types';
|
||||
import type { GramJsAppConfig } from '../../../../api/gramjs/apiBuilders/appConfig';
|
||||
|
||||
export type MockDialog = {
|
||||
export type MockDialog = Partial<Api.Dialog> & {
|
||||
id: string;
|
||||
};
|
||||
|
||||
|
||||
@ -1,18 +1,30 @@
|
||||
import Api from "../../tl/api";
|
||||
import createMockedTypePeer from "./createMockedTypePeer";
|
||||
import {MockDialog, MockTypes} from "./MockTypes";
|
||||
import Api from '../../tl/api';
|
||||
import createMockedTypePeer from './createMockedTypePeer';
|
||||
import type { MockTypes } from './MockTypes';
|
||||
|
||||
export default function createMockedDialog(id: string, mockData: MockTypes): Api.Dialog {
|
||||
const dialog = mockData.dialogs.active.find((d) => d.id === id)
|
||||
|| mockData.dialogs.archived.find((d) => d.id === id);
|
||||
|
||||
if (!dialog) throw Error('No such dialog');
|
||||
|
||||
const {
|
||||
unreadMentionsCount = 0,
|
||||
unreadReactionsCount = 0,
|
||||
readInboxMaxId = 0,
|
||||
readOutboxMaxId = 0,
|
||||
unreadCount = 0,
|
||||
topMessage = 0,
|
||||
} = dialog;
|
||||
|
||||
export default function createMockedDialog({
|
||||
id,
|
||||
}: MockDialog, mockData: MockTypes): Api.Dialog {
|
||||
return new Api.Dialog({
|
||||
peer: createMockedTypePeer(id, mockData),
|
||||
topMessage: 0,
|
||||
readInboxMaxId: 0,
|
||||
readOutboxMaxId: 0,
|
||||
unreadCount: 0,
|
||||
unreadMentionsCount: 0,
|
||||
unreadReactionsCount: 0,
|
||||
topMessage,
|
||||
readInboxMaxId,
|
||||
readOutboxMaxId,
|
||||
unreadCount,
|
||||
unreadMentionsCount,
|
||||
unreadReactionsCount,
|
||||
notifySettings: new Api.PeerNotifySettings({}),
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,24 +1,26 @@
|
||||
import Api from '../../tl/api';
|
||||
import {MOCK_STARTING_DATE, MockTypes} from "./MockTypes";
|
||||
import createMockedTypePeer from "./createMockedTypePeer";
|
||||
import createMockedMessageMedia from "./createMockedMessageMedia";
|
||||
import createMockedMessageReactions from "./createMockedMessageReactions";
|
||||
import createMockedReplies from "./createMockedReplies";
|
||||
import createMockedReplyTo from "./createMockedReplyTo";
|
||||
import {omit} from "../../../../util/iteratees";
|
||||
import type { MockTypes } from './MockTypes';
|
||||
import { MOCK_STARTING_DATE } from './MockTypes';
|
||||
import createMockedTypePeer from './createMockedTypePeer';
|
||||
import createMockedMessageMedia from './createMockedMessageMedia';
|
||||
import createMockedMessageReactions from './createMockedMessageReactions';
|
||||
import createMockedReplies from './createMockedReplies';
|
||||
import createMockedReplyTo from './createMockedReplyTo';
|
||||
import { omit } from '../../../../util/iteratees';
|
||||
|
||||
export default function createMockedMessage(chatId: string, id: number, mockData: MockTypes): Api.Message {
|
||||
const msg = mockData.messages[chatId].find((message) => message.id === id);
|
||||
|
||||
if(!msg) throw Error("No such message " + id);
|
||||
if (!msg) throw Error(`No such message ${id}`);
|
||||
|
||||
const {
|
||||
date = MOCK_STARTING_DATE + id,
|
||||
message = "Message",
|
||||
message = 'Message',
|
||||
media,
|
||||
reactions,
|
||||
replies,
|
||||
replyTo = createMockedReplyTo(chatId, id, mockData),
|
||||
entities = [new Api.MessageEntityMention({ offset: 0, length: 5 })],
|
||||
...rest
|
||||
} = omit(msg, ['replyToMsgId', 'replyToTopId', 'replyToForumTopic']);
|
||||
|
||||
@ -28,6 +30,7 @@ export default function createMockedMessage(chatId: string, id: number, mockData
|
||||
peerId: createMockedTypePeer(chatId, mockData),
|
||||
date,
|
||||
message,
|
||||
entities,
|
||||
replyTo,
|
||||
...(media ? { media: createMockedMessageMedia(media, mockData) } : undefined),
|
||||
...(reactions ? { reactions: createMockedMessageReactions(chatId, id, mockData) } : undefined),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user