Close search, contacts on list click
This commit is contained in:
parent
13c4b541cd
commit
275bd4f77d
@ -8,7 +8,7 @@ export class SearchGroup {
|
||||
nameEl: HTMLDivElement;
|
||||
list: HTMLUListElement;
|
||||
|
||||
constructor(public name: string, public type: string, private clearable = true, className?: string, clickable = true, public autonomous = true) {
|
||||
constructor(public name: string, public type: string, private clearable = true, className?: string, clickable = true, public autonomous = true, public onFound?: () => void) {
|
||||
this.list = document.createElement('ul');
|
||||
this.container = document.createElement('div');
|
||||
if(className) this.container.className = className;
|
||||
@ -25,7 +25,7 @@ export class SearchGroup {
|
||||
this.container.style.display = 'none';
|
||||
|
||||
if(clickable) {
|
||||
appDialogsManager.setListClickListener(this.list, undefined, undefined, autonomous);
|
||||
appDialogsManager.setListClickListener(this.list, onFound, undefined, autonomous);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,6 @@ import { ripple } from "./ripple";
|
||||
import Scrollable, { ScrollableX } from "./scrollable";
|
||||
import { wrapDocument, wrapPhoto, wrapVideo } from "./wrappers";
|
||||
import useHeavyAnimationCheck, { getHeavyAnimationPromise } from "../hooks/useHeavyAnimationCheck";
|
||||
import { p } from "../mock/srp";
|
||||
|
||||
const testScroll = false;
|
||||
|
||||
@ -706,7 +705,7 @@ export default class AppSearchSuper {
|
||||
drawStatus: false,
|
||||
meAsSaved: true,
|
||||
avatarSize: 48,
|
||||
autonomous: false
|
||||
autonomous: true
|
||||
});
|
||||
|
||||
dom.lastMessageSpan.innerText = peerId > 0 ? appUsersManager.getUserStatusString(peerId) : appChatsManager.getChatMembersString(peerId);
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { CHAT_ANIMATION_GROUP } from "../../lib/appManagers/appImManager";
|
||||
import type { AppMessagesManager, Dialog, HistoryResult, MyMessage } from "../../lib/appManagers/appMessagesManager";
|
||||
import type { AppSidebarRight } from "../sidebarRight";
|
||||
import { AppImManager, CHAT_ANIMATION_GROUP } from "../../lib/appManagers/appImManager";
|
||||
import type { AppMessagesManager, HistoryResult, MyMessage } from "../../lib/appManagers/appMessagesManager";
|
||||
import type { AppStickersManager } from "../../lib/appManagers/appStickersManager";
|
||||
import type { AppUsersManager } from "../../lib/appManagers/appUsersManager";
|
||||
import type { AppInlineBotsManager } from "../../lib/appManagers/appInlineBotsManager";
|
||||
import type { AppPhotosManager } from "../../lib/appManagers/appPhotosManager";
|
||||
import type { AppDocsManager } from "../../lib/appManagers/appDocsManager";
|
||||
import type { AppPeersManager } from "../../lib/appManagers/appPeersManager";
|
||||
import type sessionStorage from '../../lib/sessionStorage';
|
||||
import { findUpClassName, cancelEvent, findUpTag, whichChild, getElementByPoint, attachClickEvent, positionElementByIndex } from "../../helpers/dom";
|
||||
import { getObjectKeysAndSort } from "../../helpers/object";
|
||||
import { isTouchSupported } from "../../helpers/touchSupport";
|
||||
@ -24,7 +24,7 @@ import animationIntersector from "../animationIntersector";
|
||||
import { months } from "../../helpers/date";
|
||||
import RichTextProcessor from "../../lib/richtextprocessor";
|
||||
import mediaSizes from "../../helpers/mediaSizes";
|
||||
import { isAndroid, isApple, isSafari, isAppleMobile } from "../../helpers/userAgent";
|
||||
import { isAndroid, isApple, isSafari } from "../../helpers/userAgent";
|
||||
import { langPack } from "../../lib/langPack";
|
||||
import AvatarElement from "../avatar";
|
||||
import { formatPhoneNumber } from "../misc";
|
||||
@ -37,13 +37,12 @@ import Chat from "./chat";
|
||||
import ListenerSetter from "../../helpers/listenerSetter";
|
||||
import PollElement from "../poll";
|
||||
import AudioElement from "../audio";
|
||||
import { Message, MessageEntity, MessageReplies, MessageReplyHeader } from "../../layer";
|
||||
import { DEBUG, MOUNT_CLASS_TO, REPLIES_PEER_ID } from "../../lib/mtproto/mtproto_config";
|
||||
import { Message, MessageEntity, MessageReplyHeader } from "../../layer";
|
||||
import { DEBUG, REPLIES_PEER_ID } from "../../lib/mtproto/mtproto_config";
|
||||
import { FocusDirection } from "../../helpers/fastSmoothScroll";
|
||||
import useHeavyAnimationCheck, { getHeavyAnimationPromise, dispatchHeavyAnimationEvent } from "../../hooks/useHeavyAnimationCheck";
|
||||
import { fastRaf } from "../../helpers/schedulers";
|
||||
import { deferredPromise, CancellablePromise } from "../../helpers/cancellablePromise";
|
||||
import EventListenerBase from "../../helpers/eventListenerBase";
|
||||
import { deferredPromise } from "../../helpers/cancellablePromise";
|
||||
|
||||
const USE_MEDIA_TAILS = false;
|
||||
const IGNORE_ACTIONS = ['messageActionHistoryClear'];
|
||||
@ -117,7 +116,7 @@ export default class ChatBubbles {
|
||||
|
||||
public isFirstLoad = true;
|
||||
|
||||
constructor(private chat: Chat, private appMessagesManager: AppMessagesManager, private appStickersManager: AppStickersManager, private appUsersManager: AppUsersManager, private appInlineBotsManager: AppInlineBotsManager, private appPhotosManager: AppPhotosManager, private appDocsManager: AppDocsManager, private appPeersManager: AppPeersManager, private appChatsManager: AppChatsManager) {
|
||||
constructor(private chat: Chat, private appMessagesManager: AppMessagesManager, private appStickersManager: AppStickersManager, private appUsersManager: AppUsersManager, private appInlineBotsManager: AppInlineBotsManager, private appPhotosManager: AppPhotosManager, private appDocsManager: AppDocsManager, private appPeersManager: AppPeersManager, private appChatsManager: AppChatsManager, private storage: typeof sessionStorage) {
|
||||
//this.chat.log.error('Bubbles construction');
|
||||
|
||||
this.listenerSetter = new ListenerSetter();
|
||||
@ -889,6 +888,28 @@ export default class ChatBubbles {
|
||||
}
|
||||
}
|
||||
|
||||
public getBubbleByPoint(verticalSide: 'top' | 'bottom') {
|
||||
let element = getElementByPoint(this.scrollable.container, verticalSide, 'center');
|
||||
/* if(element) {
|
||||
if(element.classList.contains('bubbles-date-group')) {
|
||||
const children = Array.from(element.children) as HTMLElement[];
|
||||
if(verticalSide === 'top') {
|
||||
element = children[this.stickyIntersector ? 2 : 1];
|
||||
} else {
|
||||
element = children[children.length - 1];
|
||||
}
|
||||
} else {
|
||||
element = findUpClassName(element, 'bubble');
|
||||
if(element && element.classList.contains('is-date')) {
|
||||
element = element.nextElementSibling as HTMLElement;
|
||||
}
|
||||
}
|
||||
} */
|
||||
if(element) element = findUpClassName(element, 'bubble');
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
public getGroupedBubble(groupId: string) {
|
||||
const group = this.appMessagesManager.groupedMessagesStorage[groupId];
|
||||
for(const mid in group) {
|
||||
@ -1325,8 +1346,15 @@ export default class ChatBubbles {
|
||||
topMessage = 0;
|
||||
}
|
||||
|
||||
let readMaxId = 0;
|
||||
if(!isTarget && topMessage) {
|
||||
let readMaxId = 0;//, savedPosition: ReturnType<AppImManager['getChatSavedPosition']>;
|
||||
if(!isTarget) {
|
||||
/* if(!samePeer) {
|
||||
savedPosition = this.chat.appImManager.getChatSavedPosition(this.chat);
|
||||
}
|
||||
|
||||
if(savedPosition) {
|
||||
lastMsgId = savedPosition.mid;
|
||||
} else */if(topMessage) {
|
||||
readMaxId = this.appMessagesManager.getReadMaxIdIfUnread(peerId, this.chat.threadId);
|
||||
if(/* dialog.unread_count */readMaxId && !samePeer) {
|
||||
lastMsgId = readMaxId;
|
||||
@ -1335,6 +1363,7 @@ export default class ChatBubbles {
|
||||
//lastMsgID = topMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const isJump = lastMsgId !== topMessage;
|
||||
|
||||
@ -1378,14 +1407,11 @@ export default class ChatBubbles {
|
||||
|
||||
let maxBubbleId = 0;
|
||||
if(samePeer) {
|
||||
let el = getElementByPoint(this.chat.bubbles.scrollable.container, 'bottom'); // ! this may not work if being called when chat is hidden
|
||||
let el = this.getBubbleByPoint('bottom'); // ! this may not work if being called when chat is hidden
|
||||
//this.chat.log('[PM]: setCorrectIndex: get last element perf:', performance.now() - perf, el);
|
||||
if(el) {
|
||||
el = findUpClassName(el, 'bubble');
|
||||
if(el) { // TODO: а что делать, если id будет -1, -2, -3?
|
||||
maxBubbleId = +el.dataset.mid;
|
||||
}
|
||||
}
|
||||
|
||||
if(maxBubbleId <= 0) {
|
||||
maxBubbleId = Math.max(...Object.keys(this.bubbles).map(mid => +mid));
|
||||
@ -1438,7 +1464,19 @@ export default class ChatBubbles {
|
||||
this.lazyLoadQueue.unlock();
|
||||
|
||||
//if(dialog && lastMsgID && lastMsgID != topMessage && (this.bubbles[lastMsgID] || this.firstUnreadBubble)) {
|
||||
if((topMessage && isJump) || isTarget) {
|
||||
/* if(savedPosition) {
|
||||
const mountedByLastMsgId = this.getMountedBubble(lastMsgId);
|
||||
let bubble: HTMLElement = mountedByLastMsgId?.bubble;
|
||||
if(!bubble?.parentElement) {
|
||||
bubble = this.findNextMountedBubbleByMsgId(lastMsgId);
|
||||
}
|
||||
|
||||
if(bubble) {
|
||||
const top = bubble.getBoundingClientRect().top;
|
||||
const distance = savedPosition.top - top;
|
||||
this.scrollable.scrollTop += distance;
|
||||
}
|
||||
} else */if((topMessage && isJump) || isTarget) {
|
||||
const fromUp = maxBubbleId > 0 && (maxBubbleId < lastMsgId || lastMsgId < 0);
|
||||
const followingUnread = readMaxId === lastMsgId && !isTarget;
|
||||
if(!fromUp && samePeer) {
|
||||
|
@ -13,6 +13,7 @@ import type { AppWebPagesManager } from "../../lib/appManagers/appWebPagesManage
|
||||
import type { ApiManagerProxy } from "../../lib/mtproto/mtprotoworker";
|
||||
import type { AppDraftsManager } from "../../lib/appManagers/appDraftsManager";
|
||||
import type { ServerTimeManager } from "../../lib/mtproto/serverTimeManager";
|
||||
import type sessionStorage from '../../lib/sessionStorage';
|
||||
import EventListenerBase from "../../helpers/eventListenerBase";
|
||||
import { logger, LogLevels } from "../../lib/logger";
|
||||
import rootScope from "../../lib/rootScope";
|
||||
@ -49,7 +50,7 @@ export default class Chat extends EventListenerBase<{
|
||||
|
||||
public type: ChatType = 'chat';
|
||||
|
||||
constructor(public appImManager: AppImManager, public appChatsManager: AppChatsManager, public appDocsManager: AppDocsManager, public appInlineBotsManager: AppInlineBotsManager, public appMessagesManager: AppMessagesManager, public appPeersManager: AppPeersManager, public appPhotosManager: AppPhotosManager, public appProfileManager: AppProfileManager, public appStickersManager: AppStickersManager, public appUsersManager: AppUsersManager, public appWebPagesManager: AppWebPagesManager, public appPollsManager: AppPollsManager, public apiManager: ApiManagerProxy, public appDraftsManager: AppDraftsManager, public serverTimeManager: ServerTimeManager) {
|
||||
constructor(public appImManager: AppImManager, public appChatsManager: AppChatsManager, public appDocsManager: AppDocsManager, public appInlineBotsManager: AppInlineBotsManager, public appMessagesManager: AppMessagesManager, public appPeersManager: AppPeersManager, public appPhotosManager: AppPhotosManager, public appProfileManager: AppProfileManager, public appStickersManager: AppStickersManager, public appUsersManager: AppUsersManager, public appWebPagesManager: AppWebPagesManager, public appPollsManager: AppPollsManager, public apiManager: ApiManagerProxy, public appDraftsManager: AppDraftsManager, public serverTimeManager: ServerTimeManager, public storage: typeof sessionStorage) {
|
||||
super();
|
||||
|
||||
this.container = document.createElement('div');
|
||||
@ -80,7 +81,7 @@ export default class Chat extends EventListenerBase<{
|
||||
this.initPeerId = peerId;
|
||||
|
||||
this.topbar = new ChatTopbar(this, appSidebarRight, this.appMessagesManager, this.appPeersManager, this.appChatsManager);
|
||||
this.bubbles = new ChatBubbles(this, this.appMessagesManager, this.appStickersManager, this.appUsersManager, this.appInlineBotsManager, this.appPhotosManager, this.appDocsManager, this.appPeersManager, this.appChatsManager);
|
||||
this.bubbles = new ChatBubbles(this, this.appMessagesManager, this.appStickersManager, this.appUsersManager, this.appInlineBotsManager, this.appPhotosManager, this.appDocsManager, this.appPeersManager, this.appChatsManager, this.storage);
|
||||
this.input = new ChatInput(this, this.appMessagesManager, this.appDocsManager, this.appChatsManager, this.appPeersManager, this.appWebPagesManager, this.appImManager, this.appDraftsManager, this.serverTimeManager);
|
||||
this.selection = new ChatSelection(this, this.bubbles, this.input, this.appMessagesManager);
|
||||
this.contextMenu = new ChatContextMenu(this.bubbles.bubblesContainer, this, this.appMessagesManager, this.appChatsManager, this.appPeersManager, this.appPollsManager);
|
||||
|
@ -1,13 +1,12 @@
|
||||
import type { AppMessagesManager } from "../../lib/appManagers/appMessagesManager";
|
||||
import type { AppPeersManager } from "../../lib/appManagers/appPeersManager";
|
||||
import type ChatTopbar from "./topbar";
|
||||
import { ScreenSize } from "../../helpers/mediaSizes";
|
||||
import PopupPinMessage from "../popups/unpinMessage";
|
||||
import PinnedContainer from "./pinnedContainer";
|
||||
import PinnedMessageBorder from "./pinnedMessageBorder";
|
||||
import ReplyContainer, { wrapReplyDivAndCaption } from "./replyContainer";
|
||||
import rootScope from "../../lib/rootScope";
|
||||
import { attachClickEvent, cancelEvent, findUpClassName, getElementByPoint, handleScrollSideEvent } from "../../helpers/dom";
|
||||
import { attachClickEvent, cancelEvent, handleScrollSideEvent } from "../../helpers/dom";
|
||||
import Chat from "./chat";
|
||||
import ListenerSetter from "../../helpers/listenerSetter";
|
||||
import ButtonIcon from "../buttonIcon";
|
||||
@ -336,11 +335,9 @@ export default class ChatPinnedMessage {
|
||||
}
|
||||
|
||||
//const perf = performance.now();
|
||||
let el = getElementByPoint(this.chat.bubbles.scrollable.container, 'bottom');
|
||||
let el = this.chat.bubbles.getBubbleByPoint('bottom');
|
||||
//this.chat.log('[PM]: setCorrectIndex: get last element perf:', performance.now() - perf, el);
|
||||
if(!el) return;
|
||||
el = findUpClassName(el, 'bubble');
|
||||
if(!el) return;
|
||||
|
||||
//return;
|
||||
|
||||
|
@ -172,12 +172,16 @@ export class AppSidebarLeft extends SidebarSlider {
|
||||
|
||||
const scrollable = new Scrollable(searchContainer);
|
||||
|
||||
const close = () => {
|
||||
this.backBtn.click();
|
||||
};
|
||||
|
||||
this.searchGroups = {
|
||||
contacts: new SearchGroup('Chats', 'contacts'),
|
||||
globalContacts: new SearchGroup('Global Search', 'contacts'),
|
||||
contacts: new SearchGroup('Chats', 'contacts', undefined, undefined, undefined, undefined, close),
|
||||
globalContacts: new SearchGroup('Global Search', 'contacts', undefined, undefined, undefined, undefined, close),
|
||||
messages: new SearchGroup('Messages', 'messages'),
|
||||
people: new SearchGroup('', 'contacts', true, 'search-group-people', true, false),
|
||||
recent: new SearchGroup('Recent', 'contacts', true, 'search-group-recent', true, false)
|
||||
people: new SearchGroup('', 'contacts', true, 'search-group-people', true, false, close),
|
||||
recent: new SearchGroup('Recent', 'contacts', true, 'search-group-recent', true, true, close)
|
||||
};
|
||||
|
||||
const searchSuper = this.searchSuper = new AppSearchSuper([{
|
||||
|
@ -21,7 +21,10 @@ export default class AppContactsTab implements SliderTab {
|
||||
this.container = document.getElementById('contacts-container');
|
||||
this.list = this.container.querySelector('#contacts');
|
||||
|
||||
appDialogsManager.setListClickListener(this.list);
|
||||
appDialogsManager.setListClickListener(this.list, () => {
|
||||
(this.container.querySelector('.sidebar-close-button') as HTMLElement).click();
|
||||
}, undefined, true);
|
||||
|
||||
this.scrollable = new Scrollable(this.list.parentElement);
|
||||
|
||||
this.inputSearch = new InputSearch('Search', (value) => {
|
||||
@ -95,7 +98,7 @@ export default class AppContactsTab implements SliderTab {
|
||||
container: this.list,
|
||||
drawStatus: false,
|
||||
avatarSize: 48,
|
||||
autonomous: false
|
||||
autonomous: true
|
||||
});
|
||||
|
||||
let status = appUsersManager.getUserStatusString(user.id);
|
||||
|
@ -643,13 +643,15 @@ export const handleScrollSideEvent = (elem: HTMLElement, side: 'top' | 'bottom',
|
||||
}
|
||||
};
|
||||
|
||||
export const getElementByPoint = (container: HTMLElement, verticalSide: 'top' | 'bottom'): HTMLElement => {
|
||||
export const getElementByPoint = (container: HTMLElement, verticalSide: 'top' | 'bottom', horizontalSide: 'center' | 'left'): HTMLElement => {
|
||||
const rect = container.getBoundingClientRect();
|
||||
const x = Math.ceil(rect.left + ((rect.right - rect.left) / 2) + 1);
|
||||
const y = verticalSide == 'bottom' ? Math.floor(rect.top + rect.height - 1) : Math.ceil(rect.top + 1);
|
||||
const x = horizontalSide === 'center' ? Math.ceil(rect.left + ((rect.right - rect.left) / 2) + 1) : Math.ceil(rect.left + 1);
|
||||
const y = verticalSide === 'bottom' ? Math.floor(rect.top + rect.height - 1) : Math.ceil(rect.top + 1);
|
||||
return document.elementFromPoint(x, y) as any;
|
||||
};
|
||||
|
||||
MOUNT_CLASS_TO && (MOUNT_CLASS_TO.getElementByPoint = getElementByPoint);
|
||||
|
||||
export async function getFilesFromEvent(e: ClipboardEvent | DragEvent, onlyTypes = false): Promise<any[]> {
|
||||
const files: any[] = [];
|
||||
|
||||
|
@ -32,6 +32,7 @@ import lottieLoader from '../lottieLoader';
|
||||
import useHeavyAnimationCheck, { dispatchHeavyAnimationEvent } from '../../hooks/useHeavyAnimationCheck';
|
||||
import appDraftsManager from './appDraftsManager';
|
||||
import serverTimeManager from '../mtproto/serverTimeManager';
|
||||
import sessionStorage from '../sessionStorage';
|
||||
|
||||
//console.log('appImManager included33!');
|
||||
|
||||
@ -152,8 +153,39 @@ export class AppImManager {
|
||||
animationIntersector.setOnlyOnePlayableGroup('');
|
||||
animationIntersector.checkAnimations(false);
|
||||
});
|
||||
|
||||
/* rootScope.on('peer_changing', (chat) => {
|
||||
this.saveChatPosition(chat);
|
||||
});
|
||||
|
||||
sessionStorage.get('chatPositions').then((c) => {
|
||||
sessionStorage.setToCache('chatPositions', c || {});
|
||||
}); */
|
||||
}
|
||||
|
||||
/* public saveChatPosition(chat: Chat) {
|
||||
const bubble = chat.bubbles.getBubbleByPoint('top');
|
||||
if(bubble) {
|
||||
const top = bubble.getBoundingClientRect().top;
|
||||
|
||||
this.log('saving position by bubble:', bubble, top);
|
||||
|
||||
const key = chat.peerId + (chat.threadId ? '_' + chat.threadId : '');
|
||||
|
||||
const chatPositions = sessionStorage.getFromCache('chatPositions');
|
||||
chatPositions[key] = {
|
||||
mid: +bubble.dataset.mid,
|
||||
top
|
||||
};
|
||||
sessionStorage.set({chatPositions});
|
||||
}
|
||||
}
|
||||
|
||||
public getChatSavedPosition(chat: Chat) {
|
||||
const key = chat.peerId + (chat.threadId ? '_' + chat.threadId : '');
|
||||
return sessionStorage.getFromCache('chatPositions')[key];
|
||||
} */
|
||||
|
||||
private setSettings() {
|
||||
document.documentElement.style.setProperty('--messages-text-size', rootScope.settings.messagesTextSize + 'px');
|
||||
|
||||
@ -469,7 +501,7 @@ export class AppImManager {
|
||||
}
|
||||
|
||||
private createNewChat() {
|
||||
const chat = new Chat(this, appChatsManager, appDocsManager, appInlineBotsManager, appMessagesManager, appPeersManager, appPhotosManager, appProfileManager, appStickersManager, appUsersManager, appWebPagesManager, appPollsManager, apiManager, appDraftsManager, serverTimeManager);
|
||||
const chat = new Chat(this, appChatsManager, appDocsManager, appInlineBotsManager, appMessagesManager, appPeersManager, appPhotosManager, appProfileManager, appStickersManager, appUsersManager, appWebPagesManager, appPollsManager, apiManager, appDraftsManager, serverTimeManager, sessionStorage);
|
||||
|
||||
this.chats.push(chat);
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import type { Dialog } from './appMessagesManager';
|
||||
import type { AppStickersManager } from './appStickersManager';
|
||||
import { App, MOUNT_CLASS_TO, UserAuth } from '../mtproto/mtproto_config';
|
||||
import EventListenerBase from '../../helpers/eventListenerBase';
|
||||
import rootScope from '../rootScope';
|
||||
|
@ -1,6 +1,7 @@
|
||||
import type { AppImManager } from './appManagers/appImManager';
|
||||
import type { State } from './appManagers/appStateManager';
|
||||
import { MOUNT_CLASS_TO } from './mtproto/mtproto_config';
|
||||
import AppStorage from './storage';
|
||||
import { State } from './appManagers/appStateManager';
|
||||
|
||||
const sessionStorage = new AppStorage<{
|
||||
dc: number,
|
||||
@ -11,7 +12,14 @@ const sessionStorage = new AppStorage<{
|
||||
dc4_auth_key: any,
|
||||
dc5_auth_key: any,
|
||||
max_seen_msg: number,
|
||||
server_time_offset: number
|
||||
server_time_offset: number,
|
||||
|
||||
chatPositions: {
|
||||
[peerId_threadId: string]: {
|
||||
mid: number,
|
||||
top: number
|
||||
}
|
||||
},
|
||||
} & State>({
|
||||
storeName: 'session'
|
||||
});
|
||||
|
@ -281,6 +281,10 @@ $bubble-margin: .25rem;
|
||||
opacity: .99999; // for safari
|
||||
pointer-events: none;
|
||||
|
||||
&:before, &:after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
body.animation-level-0 & {
|
||||
transition: none;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user