Chat List: Introduce Archive item (#2566)
This commit is contained in:
parent
3cc27156cb
commit
5055f70f77
Binary file not shown.
Binary file not shown.
@ -235,7 +235,7 @@ const ChatOrUserPicker: FC<OwnProps> = ({
|
||||
<ListItem
|
||||
key={id}
|
||||
className="chat-item-clickable force-rounded-corners small-icon"
|
||||
style={`top: ${(viewportOffset + i) * CHAT_HEIGHT_PX}px;`}
|
||||
style={`height: ${CHAT_HEIGHT_PX}px; top: ${(viewportOffset + i) * CHAT_HEIGHT_PX}px;`}
|
||||
onClick={handleClick}
|
||||
clickArg={id}
|
||||
>
|
||||
|
||||
@ -28,4 +28,8 @@
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
|
||||
.archived-chats-more-menu {
|
||||
margin-left: auto !important;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,10 @@
|
||||
import React, { memo } from '../../lib/teact/teact';
|
||||
import React, { memo, useCallback } from '../../lib/teact/teact';
|
||||
import { getActions } from '../../global';
|
||||
|
||||
import type { FC } from '../../lib/teact/teact';
|
||||
import type { LeftColumnContent, SettingsScreens } from '../../types';
|
||||
import type { FolderEditDispatch } from '../../hooks/reducers/useFoldersReducer';
|
||||
import type { GlobalState } from '../../global/types';
|
||||
|
||||
import buildClassName from '../../util/buildClassName';
|
||||
import useLang from '../../hooks/useLang';
|
||||
@ -12,22 +16,33 @@ import useForumPanelRender from '../../hooks/useForumPanelRender';
|
||||
import Button from '../ui/Button';
|
||||
import ChatList from './main/ChatList';
|
||||
import ForumPanel from './main/ForumPanel';
|
||||
import DropdownMenu from '../ui/DropdownMenu';
|
||||
import MenuItem from '../ui/MenuItem';
|
||||
|
||||
import './ArchivedChats.scss';
|
||||
|
||||
export type OwnProps = {
|
||||
isActive: boolean;
|
||||
isForumPanelOpen?: boolean;
|
||||
archiveSettings: GlobalState['archiveSettings'];
|
||||
onReset: () => void;
|
||||
onTopicSearch: NoneToVoidFunction;
|
||||
isForumPanelOpen?: boolean;
|
||||
onSettingsScreenSelect: (screen: SettingsScreens) => void;
|
||||
foldersDispatch: FolderEditDispatch;
|
||||
onLeftColumnContentChange: (content: LeftColumnContent) => void;
|
||||
};
|
||||
|
||||
const ArchivedChats: FC<OwnProps> = ({
|
||||
isActive,
|
||||
isForumPanelOpen,
|
||||
archiveSettings,
|
||||
onReset,
|
||||
onTopicSearch,
|
||||
onSettingsScreenSelect,
|
||||
onLeftColumnContentChange,
|
||||
foldersDispatch,
|
||||
}) => {
|
||||
const { updateArchiveSettings } = getActions();
|
||||
const lang = useLang();
|
||||
|
||||
useHistoryBack({
|
||||
@ -35,6 +50,10 @@ const ArchivedChats: FC<OwnProps> = ({
|
||||
onBack: onReset,
|
||||
});
|
||||
|
||||
const handleDisplayArchiveInChats = useCallback(() => {
|
||||
updateArchiveSettings({ isHidden: false });
|
||||
}, [updateArchiveSettings]);
|
||||
|
||||
const {
|
||||
shouldDisableDropdownMenuTransitionRef,
|
||||
handleDropdownMenuTransitionEnd,
|
||||
@ -67,8 +86,27 @@ const ArchivedChats: FC<OwnProps> = ({
|
||||
<i className="icon-arrow-left" />
|
||||
</Button>
|
||||
{shouldRenderTitle && <h3 className={titleClassNames}>{lang('ArchivedChats')}</h3>}
|
||||
{archiveSettings.isHidden && (
|
||||
<DropdownMenu
|
||||
className="archived-chats-more-menu"
|
||||
positionX="right"
|
||||
onTransitionEnd={lang.isRtl ? handleDropdownMenuTransitionEnd : undefined}
|
||||
>
|
||||
<MenuItem icon="archive-from-main" onClick={handleDisplayArchiveInChats}>
|
||||
{lang('lng_context_archive_to_list')}
|
||||
</MenuItem>
|
||||
</DropdownMenu>
|
||||
)}
|
||||
</div>
|
||||
<ChatList folderType="archived" isActive={isActive} isForumPanelOpen={isForumPanelOpen} />
|
||||
<ChatList
|
||||
folderType="archived"
|
||||
isActive={isActive}
|
||||
isForumPanelOpen={isForumPanelOpen}
|
||||
onSettingsScreenSelect={onSettingsScreenSelect}
|
||||
onLeftColumnContentChange={onLeftColumnContentChange}
|
||||
foldersDispatch={foldersDispatch}
|
||||
archiveSettings={archiveSettings}
|
||||
/>
|
||||
{shouldRenderForumPanel && (
|
||||
<ForumPanel
|
||||
isOpen={isForumPanelOpen}
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import type { FC } from '../../lib/teact/teact';
|
||||
import React, {
|
||||
memo, useCallback, useEffect, useRef, useState,
|
||||
} from '../../lib/teact/teact';
|
||||
import { getActions, withGlobal } from '../../global';
|
||||
|
||||
import type { FC } from '../../lib/teact/teact';
|
||||
import type { GlobalState } from '../../global/types';
|
||||
import { LeftColumnContent, SettingsScreens } from '../../types';
|
||||
|
||||
import { IS_MAC_OS, IS_PWA, LAYERS_ANIMATION_NAME } from '../../util/environment';
|
||||
@ -36,6 +37,7 @@ type StateProps = {
|
||||
isForumPanelOpen?: boolean;
|
||||
forumPanelChatId?: string;
|
||||
isClosingSearch?: boolean;
|
||||
archiveSettings: GlobalState['archiveSettings'];
|
||||
};
|
||||
|
||||
enum ContentType {
|
||||
@ -66,6 +68,7 @@ const LeftColumn: FC<StateProps> = ({
|
||||
isForumPanelOpen,
|
||||
forumPanelChatId,
|
||||
isClosingSearch,
|
||||
archiveSettings,
|
||||
}) => {
|
||||
const {
|
||||
setGlobalSearchQuery,
|
||||
@ -352,6 +355,11 @@ const LeftColumn: FC<StateProps> = ({
|
||||
openChat({ id: currentUserId, shouldReplaceHistory: true });
|
||||
}, [currentUserId, openChat]);
|
||||
|
||||
const handleArchivedChats = useCallback((e: KeyboardEvent) => {
|
||||
e.preventDefault();
|
||||
setContent(LeftColumnContent.Archived);
|
||||
}, []);
|
||||
|
||||
const handleHotkeySettings = useCallback((e: KeyboardEvent) => {
|
||||
e.preventDefault();
|
||||
setContent(LeftColumnContent.Settings);
|
||||
@ -360,7 +368,10 @@ const LeftColumn: FC<StateProps> = ({
|
||||
useHotkeys({
|
||||
'Mod+Shift+F': handleHotkeySearch,
|
||||
'Mod+Shift+S': handleHotkeySavedMessages,
|
||||
'Mod+0': handleHotkeySavedMessages,
|
||||
...(IS_PWA && {
|
||||
'Mod+0': handleHotkeySavedMessages,
|
||||
'Mod+9': handleArchivedChats,
|
||||
}),
|
||||
...(IS_MAC_OS && IS_PWA && { 'Mod+,': handleHotkeySettings }),
|
||||
});
|
||||
|
||||
@ -411,7 +422,11 @@ const LeftColumn: FC<StateProps> = ({
|
||||
isActive={isActive}
|
||||
onReset={handleReset}
|
||||
onTopicSearch={handleTopicSearch}
|
||||
foldersDispatch={foldersDispatch}
|
||||
onSettingsScreenSelect={handleSettingsScreenSelect}
|
||||
onLeftColumnContentChange={setContent}
|
||||
isForumPanelOpen={isForumPanelOpen}
|
||||
archiveSettings={archiveSettings}
|
||||
/>
|
||||
);
|
||||
case ContentType.Settings:
|
||||
@ -458,7 +473,7 @@ const LeftColumn: FC<StateProps> = ({
|
||||
foldersDispatch={foldersDispatch}
|
||||
onContentChange={setContent}
|
||||
onSearchQuery={handleSearchQuery}
|
||||
onScreenSelect={handleSettingsScreenSelect}
|
||||
onSettingsScreenSelect={handleSettingsScreenSelect}
|
||||
onReset={handleReset}
|
||||
shouldSkipTransition={shouldSkipHistoryAnimations}
|
||||
isUpdateAvailable={isUpdateAvailable}
|
||||
@ -498,6 +513,7 @@ export default memo(withGlobal(
|
||||
hasPasscode,
|
||||
},
|
||||
isUpdateAvailable,
|
||||
archiveSettings,
|
||||
} = global;
|
||||
|
||||
const currentChat = selectCurrentChat(global);
|
||||
@ -519,6 +535,7 @@ export default memo(withGlobal(
|
||||
isForumPanelOpen,
|
||||
forumPanelChatId,
|
||||
isClosingSearch: tabState.globalSearch.isClosing,
|
||||
archiveSettings,
|
||||
};
|
||||
},
|
||||
)(LeftColumn));
|
||||
|
||||
90
src/components/left/main/Archive.module.scss
Normal file
90
src/components/left/main/Archive.module.scss
Normal file
@ -0,0 +1,90 @@
|
||||
.root {
|
||||
--background-color: var(--color-background);
|
||||
}
|
||||
|
||||
.minimized {
|
||||
background-color: var(--color-background-secondary);
|
||||
margin: -0.5rem -0.5rem 0 -0.5rem !important;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
.button {
|
||||
border-radius: 0;
|
||||
padding: 0.375rem !important;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
:global(body.is-ios) &,
|
||||
:global(body.is-android) & {
|
||||
.button {
|
||||
padding-bottom: 0.3125rem !important;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
justify-content: center !important;
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
.unread-count {
|
||||
position: absolute;
|
||||
right: 0.75rem;
|
||||
background-color: transparent;
|
||||
color: var(--color-text-secondary);
|
||||
font-size: 0.8125rem;
|
||||
}
|
||||
|
||||
.info {
|
||||
transform: none !important;
|
||||
}
|
||||
|
||||
.name {
|
||||
line-height: 1.25rem !important;
|
||||
font-size: 0.8125rem !important;
|
||||
}
|
||||
|
||||
&::after {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.info {
|
||||
transition: opacity 0.3s ease, transform var(--layer-transition);
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin-inline-end: 0.5rem;
|
||||
}
|
||||
|
||||
.name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.avatarWrapper {
|
||||
flex-shrink: 0;
|
||||
background-color: var(--background-color);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
font-size: 1.625rem;
|
||||
background: linear-gradient(var(--color-white) -125%, var(--color-archive)) !important;
|
||||
}
|
||||
|
||||
.title {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.chatsPreview {
|
||||
color: var(--color-text-secondary);
|
||||
flex-grow: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.unread {
|
||||
color: var(--color-text);
|
||||
}
|
||||
166
src/components/left/main/Archive.tsx
Normal file
166
src/components/left/main/Archive.tsx
Normal file
@ -0,0 +1,166 @@
|
||||
import React, { memo, useCallback, useMemo } from '../../../lib/teact/teact';
|
||||
import { getActions, getGlobal } from '../../../global';
|
||||
|
||||
import type { FC } from '../../../lib/teact/teact';
|
||||
import type { GlobalState } from '../../../global/types';
|
||||
|
||||
import { ARCHIVED_FOLDER_ID } from '../../../config';
|
||||
import buildClassName from '../../../util/buildClassName';
|
||||
import { compact } from '../../../util/iteratees';
|
||||
import { formatIntegerCompact } from '../../../util/textFormat';
|
||||
import renderText from '../../common/helpers/renderText';
|
||||
|
||||
import useLang from '../../../hooks/useLang';
|
||||
import { useFolderManagerForOrderedIds, useFolderManagerForUnreadCounters } from '../../../hooks/useFolderManager';
|
||||
|
||||
import ListItem from '../../ui/ListItem';
|
||||
import AnimatedCounter from '../../common/AnimatedCounter';
|
||||
|
||||
import styles from './Archive.module.scss';
|
||||
|
||||
type OwnProps = {
|
||||
archiveSettings: GlobalState['archiveSettings'];
|
||||
onDragEnter?: NoneToVoidFunction;
|
||||
onClick?: NoneToVoidFunction;
|
||||
};
|
||||
|
||||
const PREVIEW_SLICE = 5;
|
||||
|
||||
const Archive: FC<OwnProps> = ({
|
||||
archiveSettings,
|
||||
onDragEnter,
|
||||
onClick,
|
||||
}) => {
|
||||
const { updateArchiveSettings } = getActions();
|
||||
const lang = useLang();
|
||||
|
||||
const orderedChatIds = useFolderManagerForOrderedIds(ARCHIVED_FOLDER_ID);
|
||||
const unreadCounters = useFolderManagerForUnreadCounters();
|
||||
const archiveUnreadCount = unreadCounters[ARCHIVED_FOLDER_ID]?.chatsCount;
|
||||
|
||||
const previewItems = useMemo(() => {
|
||||
if (!orderedChatIds?.length) return lang('Loading');
|
||||
|
||||
const chatsById = getGlobal().chats.byId;
|
||||
|
||||
return orderedChatIds.slice(0, PREVIEW_SLICE).map((chatId, i, arr) => {
|
||||
const isLast = i === arr.length - 1;
|
||||
const chat = chatsById[chatId];
|
||||
if (!chat) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<span className={buildClassName(styles.chat, archiveUnreadCount && chat.unreadCount && styles.unread)}>
|
||||
{renderText(chat.title)}
|
||||
</span>
|
||||
{isLast ? '' : ', '}
|
||||
</>
|
||||
);
|
||||
});
|
||||
}, [orderedChatIds, lang, archiveUnreadCount]);
|
||||
|
||||
const contextActions = useMemo(() => {
|
||||
const actionMinimize = !archiveSettings.isMinimized && {
|
||||
title: lang('lng_context_archive_collapse'),
|
||||
icon: 'collapse',
|
||||
handler: () => {
|
||||
updateArchiveSettings({ isMinimized: true });
|
||||
},
|
||||
};
|
||||
|
||||
const actionExpand = archiveSettings.isMinimized && {
|
||||
title: lang('lng_context_archive_expand'),
|
||||
icon: 'expand',
|
||||
handler: () => {
|
||||
updateArchiveSettings({ isMinimized: false });
|
||||
},
|
||||
};
|
||||
|
||||
const actionHide = {
|
||||
title: lang('lng_context_archive_to_menu'),
|
||||
icon: 'archive-to-main',
|
||||
handler: () => {
|
||||
updateArchiveSettings({ isHidden: true });
|
||||
},
|
||||
};
|
||||
|
||||
return compact([actionMinimize, actionExpand, actionHide]);
|
||||
}, [archiveSettings.isMinimized, lang, updateArchiveSettings]);
|
||||
|
||||
const handleDragEnter = useCallback((e) => {
|
||||
e.preventDefault();
|
||||
onDragEnter?.();
|
||||
}, [onDragEnter]);
|
||||
|
||||
function renderCollapsed() {
|
||||
return (
|
||||
<div className={buildClassName(styles.info, 'info')}>
|
||||
<div className="info-row">
|
||||
<div className={buildClassName('title', styles.title)}>
|
||||
<h3 dir="auto" className={buildClassName(styles.name, 'fullName')}>
|
||||
<i className={buildClassName(styles.icon, 'icon-archive-filled')} />
|
||||
{lang('ArchivedChats')}
|
||||
</h3>
|
||||
</div>
|
||||
{Boolean(archiveUnreadCount) && (
|
||||
<div className={styles.unreadCount}>
|
||||
<AnimatedCounter text={formatIntegerCompact(archiveUnreadCount)} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function renderRegular() {
|
||||
return (
|
||||
<>
|
||||
<div className={buildClassName('status', styles.avatarWrapper)}>
|
||||
<div className={buildClassName('Avatar', styles.avatar)}>
|
||||
<i className="icon-archive-filled" />
|
||||
</div>
|
||||
</div>
|
||||
<div className={buildClassName(styles.info, 'info')}>
|
||||
<div className="info-row">
|
||||
<div className={buildClassName('title', styles.title)}>
|
||||
<h3 dir="auto" className={buildClassName(styles.name, 'fullName')}>{lang('ArchivedChats')}</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div className="subtitle">
|
||||
<div className={buildClassName('status', styles.chatsPreview)}>
|
||||
{previewItems}
|
||||
</div>
|
||||
{Boolean(archiveUnreadCount) && (
|
||||
<div className="Badge">
|
||||
<AnimatedCounter text={formatIntegerCompact(archiveUnreadCount)} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<ListItem
|
||||
onClick={onClick}
|
||||
onDragEnter={handleDragEnter}
|
||||
className={buildClassName(
|
||||
styles.root,
|
||||
archiveSettings.isMinimized && styles.minimized,
|
||||
'chat-item-clickable',
|
||||
'chat-item-archive',
|
||||
)}
|
||||
buttonClassName={styles.button}
|
||||
offsetCollapseDelta={0}
|
||||
contextActions={contextActions}
|
||||
withPortalForMenu
|
||||
>
|
||||
{archiveSettings.isMinimized ? renderCollapsed() : renderRegular()}
|
||||
</ListItem>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(Archive);
|
||||
@ -5,8 +5,9 @@ import React, {
|
||||
import { getActions, withGlobal } from '../../../global';
|
||||
|
||||
import type { ApiChatFolder } from '../../../api/types';
|
||||
import type { SettingsScreens } from '../../../types';
|
||||
import type { LeftColumnContent, SettingsScreens } from '../../../types';
|
||||
import type { FolderEditDispatch } from '../../../hooks/reducers/useFoldersReducer';
|
||||
import type { GlobalState } from '../../../global/types';
|
||||
|
||||
import { ALL_FOLDER_ID } from '../../../config';
|
||||
import { IS_TOUCH_ENV } from '../../../util/environment';
|
||||
@ -25,8 +26,9 @@ import TabList from '../../ui/TabList';
|
||||
import ChatList from './ChatList';
|
||||
|
||||
type OwnProps = {
|
||||
onScreenSelect: (screen: SettingsScreens) => void;
|
||||
onSettingsScreenSelect: (screen: SettingsScreens) => void;
|
||||
foldersDispatch: FolderEditDispatch;
|
||||
onLeftColumnContentChange: (content: LeftColumnContent) => void;
|
||||
shouldHideFolderTabs?: boolean;
|
||||
};
|
||||
|
||||
@ -39,6 +41,8 @@ type StateProps = {
|
||||
lastSyncTime?: number;
|
||||
shouldSkipHistoryAnimations?: boolean;
|
||||
maxFolders: number;
|
||||
hasArchivedChats?: boolean;
|
||||
archiveSettings: GlobalState['archiveSettings'];
|
||||
};
|
||||
|
||||
const SAVED_MESSAGES_HOTKEY = '0';
|
||||
@ -46,7 +50,8 @@ const FIRST_FOLDER_INDEX = 0;
|
||||
|
||||
const ChatFolders: FC<OwnProps & StateProps> = ({
|
||||
foldersDispatch,
|
||||
onScreenSelect,
|
||||
onSettingsScreenSelect,
|
||||
onLeftColumnContentChange,
|
||||
chatFoldersById,
|
||||
orderedFolderIds,
|
||||
activeChatFolder,
|
||||
@ -56,6 +61,8 @@ const ChatFolders: FC<OwnProps & StateProps> = ({
|
||||
shouldSkipHistoryAnimations,
|
||||
maxFolders,
|
||||
shouldHideFolderTabs,
|
||||
hasArchivedChats,
|
||||
archiveSettings,
|
||||
}) => {
|
||||
const {
|
||||
loadChatFolders,
|
||||
@ -122,7 +129,7 @@ const ChatFolders: FC<OwnProps & StateProps> = ({
|
||||
|
||||
// Prevent `activeTab` pointing at non-existing folder after update
|
||||
useEffect(() => {
|
||||
if (!folderTabs || !folderTabs.length) {
|
||||
if (!folderTabs?.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -211,7 +218,10 @@ const ChatFolders: FC<OwnProps & StateProps> = ({
|
||||
isForumPanelOpen={isForumPanelOpen}
|
||||
lastSyncTime={lastSyncTime}
|
||||
foldersDispatch={foldersDispatch}
|
||||
onScreenSelect={onScreenSelect}
|
||||
onSettingsScreenSelect={onSettingsScreenSelect}
|
||||
onLeftColumnContentChange={onLeftColumnContentChange}
|
||||
canDisplayArchive={hasArchivedChats && !archiveSettings.isHidden}
|
||||
archiveSettings={archiveSettings}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@ -249,8 +259,14 @@ export default memo(withGlobal<OwnProps>(
|
||||
byId: chatFoldersById,
|
||||
orderedIds: orderedFolderIds,
|
||||
},
|
||||
chats: {
|
||||
listIds: {
|
||||
archived,
|
||||
},
|
||||
},
|
||||
currentUserId,
|
||||
lastSyncTime,
|
||||
archiveSettings,
|
||||
} = global;
|
||||
const { shouldSkipHistoryAnimations, activeChatFolder } = selectTabState(global);
|
||||
|
||||
@ -262,7 +278,9 @@ export default memo(withGlobal<OwnProps>(
|
||||
isForumPanelOpen: selectIsForumPanelOpen(global),
|
||||
lastSyncTime,
|
||||
shouldSkipHistoryAnimations,
|
||||
hasArchivedChats: Boolean(archived?.length),
|
||||
maxFolders: selectCurrentLimit(global, 'dialogFilters'),
|
||||
archiveSettings,
|
||||
};
|
||||
},
|
||||
)(ChatFolders));
|
||||
|
||||
@ -4,12 +4,14 @@ import React, {
|
||||
import { getActions, getGlobal } from '../../../global';
|
||||
|
||||
import type { FC } from '../../../lib/teact/teact';
|
||||
import type { SettingsScreens } from '../../../types';
|
||||
import type { FolderEditDispatch } from '../../../hooks/reducers/useFoldersReducer';
|
||||
import { LeftColumnContent } from '../../../types';
|
||||
import type { SettingsScreens } from '../../../types';
|
||||
import type { GlobalState } from '../../../global/types';
|
||||
|
||||
import {
|
||||
ALL_FOLDER_ID,
|
||||
ARCHIVED_FOLDER_ID, CHAT_HEIGHT_FORUM_PX,
|
||||
ARCHIVED_FOLDER_ID, ARCHIVE_MINIMIZED_HEIGHT, CHAT_HEIGHT_FORUM_PX,
|
||||
CHAT_HEIGHT_PX,
|
||||
CHAT_LIST_SLICE,
|
||||
} from '../../../config';
|
||||
@ -24,35 +26,43 @@ import { useIntersectionObserver } from '../../../hooks/useIntersectionObserver'
|
||||
import { useHotkeys } from '../../../hooks/useHotkeys';
|
||||
import useDebouncedCallback from '../../../hooks/useDebouncedCallback';
|
||||
import useChatOrderDiff from './hooks/useChatOrderDiff';
|
||||
import useCollapseWithForumPanel from './hooks/useCollapseWithForumPanel';
|
||||
|
||||
import InfiniteScroll from '../../ui/InfiniteScroll';
|
||||
import Loading from '../../ui/Loading';
|
||||
import Chat from './Chat';
|
||||
import EmptyFolder from './EmptyFolder';
|
||||
import useCollapseWithForumPanel from './hooks/useCollapseWithForumPanel';
|
||||
import Archive from './Archive';
|
||||
|
||||
type OwnProps = {
|
||||
folderType: 'all' | 'archived' | 'folder';
|
||||
folderId?: number;
|
||||
isActive: boolean;
|
||||
canDisplayArchive?: boolean;
|
||||
archiveSettings: GlobalState['archiveSettings'];
|
||||
isForumPanelOpen?: boolean;
|
||||
lastSyncTime?: number;
|
||||
foldersDispatch?: FolderEditDispatch;
|
||||
onScreenSelect?: (screen: SettingsScreens) => void;
|
||||
foldersDispatch: FolderEditDispatch;
|
||||
onSettingsScreenSelect: (screen: SettingsScreens) => void;
|
||||
onLeftColumnContentChange: (content: LeftColumnContent) => void;
|
||||
};
|
||||
|
||||
const INTERSECTION_THROTTLE = 200;
|
||||
const DRAG_ENTER_DEBOUNCE = 500;
|
||||
const RESERVED_HOTKEYS = new Set(['9', '0']);
|
||||
|
||||
const ChatList: FC<OwnProps> = ({
|
||||
folderType,
|
||||
folderId,
|
||||
isActive,
|
||||
isForumPanelOpen,
|
||||
canDisplayArchive,
|
||||
archiveSettings,
|
||||
foldersDispatch,
|
||||
onScreenSelect,
|
||||
onSettingsScreenSelect,
|
||||
onLeftColumnContentChange,
|
||||
}) => {
|
||||
const { openChat, openNextChat } = getActions();
|
||||
const { openChat, openNextChat, closeForumPanel } = getActions();
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const shouldIgnoreDragRef = useRef(false);
|
||||
@ -61,8 +71,14 @@ const ChatList: FC<OwnProps> = ({
|
||||
folderType === 'all' ? ALL_FOLDER_ID : folderType === 'archived' ? ARCHIVED_FOLDER_ID : folderId!
|
||||
);
|
||||
|
||||
const shouldDisplayArchive = folderType === 'all' && canDisplayArchive;
|
||||
|
||||
const orderedIds = useFolderManagerForOrderedIds(resolvedFolderId);
|
||||
|
||||
const chatsHeight = (orderedIds?.length || 0) * CHAT_HEIGHT_PX;
|
||||
const archiveHeight = shouldDisplayArchive
|
||||
? archiveSettings.isMinimized ? ARCHIVE_MINIMIZED_HEIGHT : CHAT_HEIGHT_PX : 0;
|
||||
|
||||
const { orderDiffById, getAnimationType } = useChatOrderDiff(orderedIds);
|
||||
|
||||
const [viewportIds, getMore] = useInfiniteScroll(undefined, orderedIds, undefined, CHAT_LIST_SLICE);
|
||||
@ -88,10 +104,19 @@ const ChatList: FC<OwnProps> = ({
|
||||
function handleKeyDown(e: KeyboardEvent) {
|
||||
if (((IS_MAC_OS && e.metaKey) || (!IS_MAC_OS && e.ctrlKey)) && e.code.startsWith('Digit')) {
|
||||
const [, digit] = e.code.match(/Digit(\d)/) || [];
|
||||
if (!digit) return;
|
||||
if (!digit || RESERVED_HOTKEYS.has(digit)) return;
|
||||
|
||||
const position = Number(digit) - 1;
|
||||
if (position > orderedIds!.length - 1 || position < 0) return;
|
||||
const isArchiveInList = shouldDisplayArchive && !archiveSettings.isMinimized;
|
||||
|
||||
const shift = isArchiveInList ? -1 : 0;
|
||||
const position = Number(digit) + shift - 1;
|
||||
|
||||
if (isArchiveInList && position === -1) {
|
||||
onLeftColumnContentChange(LeftColumnContent.Archived);
|
||||
return;
|
||||
}
|
||||
|
||||
if (position > orderedIds!.length - 1) return;
|
||||
|
||||
openChat({ id: orderedIds![position], shouldReplaceHistory: true });
|
||||
}
|
||||
@ -102,7 +127,7 @@ const ChatList: FC<OwnProps> = ({
|
||||
return () => {
|
||||
document.removeEventListener('keydown', handleKeyDown);
|
||||
};
|
||||
}, [isActive, openChat, openNextChat, orderedIds]);
|
||||
}, [archiveSettings, isActive, onLeftColumnContentChange, openChat, openNextChat, orderedIds, shouldDisplayArchive]);
|
||||
|
||||
const { observe } = useIntersectionObserver({
|
||||
rootRef: containerRef,
|
||||
@ -111,6 +136,19 @@ const ChatList: FC<OwnProps> = ({
|
||||
|
||||
useCollapseWithForumPanel(containerRef, isForumPanelOpen);
|
||||
|
||||
const handleArchivedClick = useCallback(() => {
|
||||
onLeftColumnContentChange(LeftColumnContent.Archived);
|
||||
closeForumPanel();
|
||||
}, [closeForumPanel, onLeftColumnContentChange]);
|
||||
|
||||
const handleArchivedDragEnter = useCallback(() => {
|
||||
if (shouldIgnoreDragRef.current) {
|
||||
shouldIgnoreDragRef.current = false;
|
||||
return;
|
||||
}
|
||||
handleArchivedClick();
|
||||
}, [handleArchivedClick]);
|
||||
|
||||
const handleDragEnter = useDebouncedCallback((chatId: string) => {
|
||||
if (shouldIgnoreDragRef.current) {
|
||||
shouldIgnoreDragRef.current = false;
|
||||
@ -131,13 +169,13 @@ const ChatList: FC<OwnProps> = ({
|
||||
if (!viewportIds?.length) return 0;
|
||||
const global = getGlobal();
|
||||
const viewportOffset = orderedIds!.indexOf(viewportIds![0]);
|
||||
return orderedIds!.reduce((acc, id, i) => {
|
||||
return archiveHeight + orderedIds!.reduce((acc, id, i) => {
|
||||
if (i >= viewportOffset) {
|
||||
return acc;
|
||||
}
|
||||
return acc + (selectChat(global, id)!.isForum ? CHAT_HEIGHT_FORUM_PX : CHAT_HEIGHT_PX);
|
||||
}, 0);
|
||||
}, [orderedIds, viewportIds]);
|
||||
}, [archiveHeight, orderedIds, viewportIds]);
|
||||
|
||||
function renderChats() {
|
||||
const viewportOffset = orderedIds!.indexOf(viewportIds![0]);
|
||||
@ -150,7 +188,7 @@ const ChatList: FC<OwnProps> = ({
|
||||
return viewportIds!.map((id, i) => {
|
||||
const isPinned = viewportOffset + i < pinnedCount;
|
||||
const expendedOffsetTop = currentChatListHeight;
|
||||
const collapsedOffsetTop = (viewportOffset + i) * CHAT_HEIGHT_PX;
|
||||
const collapsedOffsetTop = archiveHeight + (viewportOffset + i) * CHAT_HEIGHT_PX;
|
||||
|
||||
currentChatListHeight += (selectChat(global, id)?.isForum ? CHAT_HEIGHT_FORUM_PX : CHAT_HEIGHT_PX);
|
||||
|
||||
@ -177,12 +215,21 @@ const ChatList: FC<OwnProps> = ({
|
||||
className={buildClassName('chat-list custom-scroll', isForumPanelOpen && 'forum-panel-open')}
|
||||
ref={containerRef}
|
||||
items={viewportIds}
|
||||
itemSelector=".ListItem:not(.chat-item-archive)"
|
||||
preloadBackwards={CHAT_LIST_SLICE}
|
||||
withAbsolutePositioning
|
||||
maxHeight={(orderedIds?.length || 0) * CHAT_HEIGHT_PX}
|
||||
maxHeight={chatsHeight + archiveHeight}
|
||||
onLoadMore={getMore}
|
||||
onDragLeave={handleDragLeave}
|
||||
>
|
||||
{shouldDisplayArchive && (
|
||||
<Archive
|
||||
key="archive"
|
||||
archiveSettings={archiveSettings}
|
||||
onClick={handleArchivedClick}
|
||||
onDragEnter={handleArchivedDragEnter}
|
||||
/>
|
||||
)}
|
||||
{viewportIds?.length ? (
|
||||
renderChats()
|
||||
) : viewportIds && !viewportIds.length ? (
|
||||
@ -191,7 +238,7 @@ const ChatList: FC<OwnProps> = ({
|
||||
folderId={folderId}
|
||||
folderType={folderType}
|
||||
foldersDispatch={foldersDispatch}
|
||||
onScreenSelect={onScreenSelect}
|
||||
onSettingsScreenSelect={onSettingsScreenSelect}
|
||||
/>
|
||||
)
|
||||
) : (
|
||||
|
||||
@ -18,8 +18,8 @@ import styles from './EmptyFolder.module.scss';
|
||||
type OwnProps = {
|
||||
folderId?: number;
|
||||
folderType: 'all' | 'archived' | 'folder';
|
||||
foldersDispatch?: FolderEditDispatch;
|
||||
onScreenSelect?: (screen: SettingsScreens) => void;
|
||||
foldersDispatch: FolderEditDispatch;
|
||||
onSettingsScreenSelect: (screen: SettingsScreens) => void;
|
||||
};
|
||||
|
||||
type StateProps = {
|
||||
@ -30,15 +30,15 @@ type StateProps = {
|
||||
const ICON_SIZE = 96;
|
||||
|
||||
const EmptyFolder: FC<OwnProps & StateProps> = ({
|
||||
chatFolder, animatedEmoji, foldersDispatch, onScreenSelect,
|
||||
chatFolder, animatedEmoji, foldersDispatch, onSettingsScreenSelect,
|
||||
}) => {
|
||||
const lang = useLang();
|
||||
const { isMobile } = useAppLayout();
|
||||
|
||||
const handleEditFolder = useCallback(() => {
|
||||
foldersDispatch!({ type: 'editFolder', payload: chatFolder });
|
||||
onScreenSelect!(SettingsScreens.FoldersEditFolderFromChatList);
|
||||
}, [chatFolder, foldersDispatch, onScreenSelect]);
|
||||
foldersDispatch({ type: 'editFolder', payload: chatFolder });
|
||||
onSettingsScreenSelect(SettingsScreens.FoldersEditFolderFromChatList);
|
||||
}, [chatFolder, foldersDispatch, onSettingsScreenSelect]);
|
||||
|
||||
return (
|
||||
<div className={styles.root}>
|
||||
@ -49,7 +49,7 @@ const EmptyFolder: FC<OwnProps & StateProps> = ({
|
||||
<p className={styles.description} dir="auto">
|
||||
{lang(chatFolder ? 'ChatList.EmptyChatListFilterText' : 'Chat.EmptyChat')}
|
||||
</p>
|
||||
{chatFolder && foldersDispatch && onScreenSelect && (
|
||||
{chatFolder && (
|
||||
<Button
|
||||
ripple={!isMobile}
|
||||
fluid
|
||||
|
||||
@ -23,6 +23,7 @@ import Button from '../../ui/Button';
|
||||
import ForumPanel from './ForumPanel';
|
||||
|
||||
import './LeftMain.scss';
|
||||
import { getActions } from '../../../global';
|
||||
|
||||
type OwnProps = {
|
||||
content: LeftColumnContent;
|
||||
@ -36,7 +37,7 @@ type OwnProps = {
|
||||
isClosingSearch?: boolean;
|
||||
onSearchQuery: (query: string) => void;
|
||||
onContentChange: (content: LeftColumnContent) => void;
|
||||
onScreenSelect: (screen: SettingsScreens) => void;
|
||||
onSettingsScreenSelect: (screen: SettingsScreens) => void;
|
||||
onTopicSearch: NoneToVoidFunction;
|
||||
onReset: () => void;
|
||||
};
|
||||
@ -58,10 +59,11 @@ const LeftMain: FC<OwnProps> = ({
|
||||
isForumPanelOpen,
|
||||
onSearchQuery,
|
||||
onContentChange,
|
||||
onScreenSelect,
|
||||
onSettingsScreenSelect,
|
||||
onReset,
|
||||
onTopicSearch,
|
||||
}) => {
|
||||
const { closeForumPanel } = getActions();
|
||||
const [isNewChatButtonShown, setIsNewChatButtonShown] = useState(IS_TOUCH_ENV);
|
||||
|
||||
const { shouldRenderForumPanel, handleForumPanelAnimationEnd } = useForumPanelRender(isForumPanelOpen);
|
||||
@ -107,7 +109,8 @@ const LeftMain: FC<OwnProps> = ({
|
||||
|
||||
const handleSelectArchived = useCallback(() => {
|
||||
onContentChange(LeftColumnContent.Archived);
|
||||
}, [onContentChange]);
|
||||
closeForumPanel();
|
||||
}, [closeForumPanel, onContentChange]);
|
||||
|
||||
const handleUpdateClick = useCallback(() => {
|
||||
window.location.reload();
|
||||
@ -172,7 +175,8 @@ const LeftMain: FC<OwnProps> = ({
|
||||
return (
|
||||
<ChatFolders
|
||||
shouldHideFolderTabs={isForumPanelVisible}
|
||||
onScreenSelect={onScreenSelect}
|
||||
onSettingsScreenSelect={onSettingsScreenSelect}
|
||||
onLeftColumnContentChange={onContentChange}
|
||||
foldersDispatch={foldersDispatch}
|
||||
/>
|
||||
);
|
||||
|
||||
@ -78,7 +78,7 @@ type StateProps =
|
||||
areChatsLoaded?: boolean;
|
||||
hasPasscode?: boolean;
|
||||
}
|
||||
& Pick<GlobalState, 'connectionState' | 'isSyncing'> & Pick<TabState, 'canInstall'>;
|
||||
& Pick<GlobalState, 'connectionState' | 'isSyncing' | 'archiveSettings'> & Pick<TabState, 'canInstall'>;
|
||||
|
||||
const ANIMATION_LEVEL_OPTIONS = [0, 1, 2];
|
||||
const WEBK_VERSION_URL = 'https://web.telegram.org/k/';
|
||||
@ -110,6 +110,7 @@ const LeftMainHeader: FC<OwnProps & StateProps> = ({
|
||||
areChatsLoaded,
|
||||
hasPasscode,
|
||||
canInstall,
|
||||
archiveSettings,
|
||||
}) => {
|
||||
const {
|
||||
openChat,
|
||||
@ -276,15 +277,17 @@ const LeftMainHeader: FC<OwnProps & StateProps> = ({
|
||||
>
|
||||
{lang('SavedMessages')}
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
icon="archive"
|
||||
onClick={onSelectArchived}
|
||||
>
|
||||
<span className="menu-item-name">{lang('ArchivedChats')}</span>
|
||||
{archivedUnreadChatsCount > 0 && (
|
||||
<div className="right-badge">{archivedUnreadChatsCount}</div>
|
||||
)}
|
||||
</MenuItem>
|
||||
{archiveSettings.isHidden && (
|
||||
<MenuItem
|
||||
icon="archive"
|
||||
onClick={onSelectArchived}
|
||||
>
|
||||
<span className="menu-item-name">{lang('ArchivedChats')}</span>
|
||||
{archivedUnreadChatsCount > 0 && (
|
||||
<div className="right-badge">{archivedUnreadChatsCount}</div>
|
||||
)}
|
||||
</MenuItem>
|
||||
)}
|
||||
<MenuItem
|
||||
icon="user"
|
||||
onClick={onSelectContacts}
|
||||
@ -359,9 +362,9 @@ const LeftMainHeader: FC<OwnProps & StateProps> = ({
|
||||
)}
|
||||
</>
|
||||
), [
|
||||
animationLevel, archivedUnreadChatsCount, canInstall, handleAnimationLevelChange, handleBugReportClick,
|
||||
handleChangelogClick, handleDarkModeToggle, handleOpenTipsChat, handleSelectSaved, handleSwitchToWebK, lang,
|
||||
onSelectArchived, onSelectContacts, onSelectSettings, theme, withOtherVersions,
|
||||
animationLevel, archiveSettings.isHidden, archivedUnreadChatsCount, canInstall, handleAnimationLevelChange,
|
||||
handleBugReportClick, handleChangelogClick, handleDarkModeToggle, handleOpenTipsChat, handleSelectSaved,
|
||||
handleSwitchToWebK, lang, onSelectArchived, onSelectContacts, onSelectSettings, theme, withOtherVersions,
|
||||
]);
|
||||
|
||||
return (
|
||||
@ -457,7 +460,9 @@ export default memo(withGlobal<OwnProps>(
|
||||
const {
|
||||
query: searchQuery, fetchingStatus, chatId, date,
|
||||
} = tabState.globalSearch;
|
||||
const { currentUserId, connectionState, isSyncing } = global;
|
||||
const {
|
||||
currentUserId, connectionState, isSyncing, archiveSettings,
|
||||
} = global;
|
||||
const { byId: chatsById } = global.chats;
|
||||
const { isConnectionStatusMinimized, animationLevel } = global.settings.byKey;
|
||||
|
||||
@ -478,6 +483,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
areChatsLoaded: Boolean(global.chats.listIds.active),
|
||||
hasPasscode: Boolean(global.passcode.hasPasscode),
|
||||
canInstall: Boolean(tabState.canInstall),
|
||||
archiveSettings,
|
||||
};
|
||||
},
|
||||
)(LeftMainHeader));
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { getActions } from '../../../../global';
|
||||
import { useMemo } from '../../../../lib/teact/teact';
|
||||
import { getActions } from '../../../../global';
|
||||
|
||||
import type { ApiChat, ApiTopic } from '../../../../api/types';
|
||||
import type { MenuItemContextAction } from '../../../ui/ListItem';
|
||||
|
||||
@ -18,6 +18,8 @@
|
||||
|
||||
.info {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.title {
|
||||
|
||||
@ -128,10 +128,11 @@
|
||||
|
||||
&.commonChats-list,
|
||||
&.members-list {
|
||||
padding: 0.5rem 1rem;
|
||||
padding: 0.5rem;
|
||||
|
||||
@media (max-width: 600px) {
|
||||
padding: 0.5rem 0;
|
||||
|
||||
.ListItem.chat-item-clickable {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@ -1,13 +1,17 @@
|
||||
import React, {
|
||||
useState, useRef, useCallback, useMemo,
|
||||
} from '../../lib/teact/teact';
|
||||
|
||||
import type { FC } from '../../lib/teact/teact';
|
||||
import React, { useState, useRef, useCallback } from '../../lib/teact/teact';
|
||||
|
||||
import Menu from './Menu';
|
||||
import Button from './Button';
|
||||
|
||||
import './DropdownMenu.scss';
|
||||
|
||||
type OwnProps = {
|
||||
className?: string;
|
||||
trigger: FC<{ onTrigger: () => void; isOpen?: boolean }>;
|
||||
trigger?: FC<{ onTrigger: () => void; isOpen?: boolean }>;
|
||||
positionX?: 'left' | 'right';
|
||||
positionY?: 'top' | 'bottom';
|
||||
footer?: string;
|
||||
@ -69,6 +73,23 @@ const DropdownMenu: FC<OwnProps> = ({
|
||||
onClose?.();
|
||||
}, [onClose]);
|
||||
|
||||
const triggerComponent: FC<{ onTrigger: () => void; isOpen?: boolean }> = useMemo(() => {
|
||||
if (trigger) return trigger;
|
||||
|
||||
return ({ onTrigger, isOpen: isMenuOpen }) => (
|
||||
<Button
|
||||
round
|
||||
size="smaller"
|
||||
color="translucent"
|
||||
className={isMenuOpen ? 'active' : ''}
|
||||
onClick={onTrigger}
|
||||
ariaLabel="More actions"
|
||||
>
|
||||
<i className="icon-more" />
|
||||
</Button>
|
||||
);
|
||||
}, [trigger]);
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={dropdownRef}
|
||||
@ -76,7 +97,7 @@ const DropdownMenu: FC<OwnProps> = ({
|
||||
onKeyDown={handleKeyDown}
|
||||
onTransitionEnd={onTransitionEnd}
|
||||
>
|
||||
{trigger({ onTrigger: toggleIsOpen, isOpen })}
|
||||
{triggerComponent({ onTrigger: toggleIsOpen, isOpen })}
|
||||
|
||||
<Menu
|
||||
ref={menuRef}
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
|
||||
.ListItem-button {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: var(--background-color);
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
|
||||
@ -61,8 +61,9 @@ export const MIN_PASSWORD_LENGTH = 1;
|
||||
export const MESSAGE_LIST_SLICE = isBigScreen ? 60 : 40;
|
||||
export const MESSAGE_LIST_VIEWPORT_LIMIT = MESSAGE_LIST_SLICE * 2;
|
||||
|
||||
export const ARCHIVE_MINIMIZED_HEIGHT = 36;
|
||||
export const CHAT_HEIGHT_PX = 72;
|
||||
export const CHAT_HEIGHT_FORUM_PX = 96;
|
||||
export const CHAT_HEIGHT_FORUM_PX = 94;
|
||||
export const TOPIC_HEIGHT_PX = 65;
|
||||
export const CHAT_LIST_SLICE = isBigScreen ? 30 : 25;
|
||||
export const CHAT_LIST_LOAD_SLICE = 100;
|
||||
|
||||
@ -561,6 +561,19 @@ addActionHandler('closeEditTopicPanel', (global, actions, payload): ActionReturn
|
||||
}, tabId);
|
||||
});
|
||||
|
||||
addActionHandler('updateArchiveSettings', (global, actions, payload): ActionReturnType => {
|
||||
const { archiveSettings } = global;
|
||||
const { isHidden = archiveSettings.isHidden, isMinimized = archiveSettings.isMinimized } = payload;
|
||||
|
||||
return {
|
||||
...global,
|
||||
archiveSettings: {
|
||||
isHidden,
|
||||
isMinimized,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
addActionHandler('checkAppVersion', (global): ActionReturnType => {
|
||||
const APP_VERSION_REGEX = /^\d+\.\d+(\.\d+)?$/;
|
||||
|
||||
|
||||
@ -195,10 +195,6 @@ function unsafeMigrateCache(cached: GlobalState, initialState: GlobalState) {
|
||||
cached.serviceNotifications = [];
|
||||
}
|
||||
|
||||
if (!cached.groupCalls) {
|
||||
cached.groupCalls = initialState.groupCalls;
|
||||
}
|
||||
|
||||
if (!cached.users.statusesById) {
|
||||
cached.users.statusesById = {};
|
||||
}
|
||||
@ -336,10 +332,6 @@ function unsafeMigrateCache(cached: GlobalState, initialState: GlobalState) {
|
||||
cached.availableReactions = cached.availableReactions
|
||||
.map((r) => ({ ...r, reaction: { emoticon: r.reaction as unknown as string } }));
|
||||
}
|
||||
|
||||
if (!cached.attachmentSettings) {
|
||||
cached.attachmentSettings = initialState.attachmentSettings;
|
||||
}
|
||||
}
|
||||
|
||||
function updateCache() {
|
||||
@ -390,6 +382,7 @@ export function serializeGlobal<T extends GlobalState>(global: T) {
|
||||
'attachmentSettings',
|
||||
'leftColumnWidth',
|
||||
'lastIsChatInfoShown',
|
||||
'archiveSettings',
|
||||
'mediaViewer',
|
||||
'audioPlayer',
|
||||
]),
|
||||
|
||||
@ -186,6 +186,11 @@ export const INITIAL_GLOBAL_STATE: GlobalState = {
|
||||
transcriptions: {},
|
||||
|
||||
byTabId: {},
|
||||
|
||||
archiveSettings: {
|
||||
isMinimized: false,
|
||||
isHidden: false,
|
||||
},
|
||||
};
|
||||
|
||||
export const INITIAL_TAB_STATE: TabState = {
|
||||
|
||||
@ -781,6 +781,11 @@ export type GlobalState = {
|
||||
serviceNotifications: ServiceNotification[];
|
||||
|
||||
byTabId: Record<number, TabState>;
|
||||
|
||||
archiveSettings: {
|
||||
isMinimized: boolean;
|
||||
isHidden: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
export type CallSound = (
|
||||
@ -2088,6 +2093,11 @@ export interface ActionPayloads {
|
||||
shouldSendGrouped?: boolean;
|
||||
};
|
||||
|
||||
updateArchiveSettings: {
|
||||
isMinimized?: boolean;
|
||||
isHidden?: boolean;
|
||||
};
|
||||
|
||||
openUrl: {
|
||||
url: string;
|
||||
shouldSkipModal?: boolean;
|
||||
|
||||
@ -332,6 +332,7 @@ export function typify<
|
||||
|
||||
if (DEBUG) {
|
||||
(window as any).getGlobal = getGlobal;
|
||||
(window as any).setGlobal = setGlobal;
|
||||
|
||||
document.addEventListener('dblclick', () => {
|
||||
// eslint-disable-next-line no-console
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -81,24 +81,22 @@
|
||||
.chat-list {
|
||||
background: var(--color-background);
|
||||
height: 100%;
|
||||
padding: 0.5rem 0.125rem 0.5rem 0.4375rem;
|
||||
padding: 0.5rem 0.4375rem 0.5rem 0.4375rem;
|
||||
|
||||
overflow-y: auto;
|
||||
body.is-android & {
|
||||
@include overflow-y-overlay();
|
||||
}
|
||||
@include overflow-y-overlay();
|
||||
|
||||
&.forum-panel-open {
|
||||
.info {
|
||||
transform: translateX(-25%);
|
||||
opacity: 0;
|
||||
transform: translateX(-25%);
|
||||
}
|
||||
|
||||
.Chat[dir="rtl"] .info {
|
||||
transform: translateX(25%);
|
||||
}
|
||||
|
||||
.ListItem-button {
|
||||
.group .ListItem-button {
|
||||
height: 4.5rem;
|
||||
}
|
||||
}
|
||||
@ -159,6 +157,6 @@
|
||||
}
|
||||
|
||||
&.deleted-account {
|
||||
--color-user: #9eaab5;
|
||||
--color-user: var(--color-deleted-account);
|
||||
}
|
||||
}
|
||||
|
||||
@ -180,6 +180,9 @@ $color-message-reaction-own-hover: #b5e0a4;
|
||||
--color-forum-hover-unread-topic: #e9e9e9;
|
||||
--color-forum-hover-unread-topic-hover: #dcdcdc;
|
||||
|
||||
--color-deleted-account: #9eaab5;
|
||||
--color-archive: #9eaab5;
|
||||
|
||||
--vh: 1vh;
|
||||
|
||||
--border-radius-default: 0.75rem;
|
||||
|
||||
@ -51,6 +51,21 @@
|
||||
.icon-volume-3:before {
|
||||
content: "\e991";
|
||||
}
|
||||
.icon-archive-filled:before {
|
||||
content: "\e9ba";
|
||||
}
|
||||
.icon-archive-from-main:before {
|
||||
content: "\e9bb";
|
||||
}
|
||||
.icon-archive-to-main:before {
|
||||
content: "\e9bc";
|
||||
}
|
||||
.icon-collapse:before {
|
||||
content: "\e9bd";
|
||||
}
|
||||
.icon-expand:before {
|
||||
content: "\e9be";
|
||||
}
|
||||
.icon-replies:before {
|
||||
content: "\e9b9";
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user