Settings / Folders: Fix layout in Settings Folders Chats Picker component (#4668)
This commit is contained in:
parent
0f2c670e0f
commit
8faa652eb6
@ -37,6 +37,7 @@ type OwnProps = {
|
||||
lockedUnselectedSubtitle?: string;
|
||||
filterValue?: string;
|
||||
filterPlaceholder?: string;
|
||||
categoryPlaceholderKey?: string;
|
||||
notFoundText?: string;
|
||||
searchInputId?: string;
|
||||
isLoading?: boolean;
|
||||
@ -65,6 +66,7 @@ const Picker: FC<OwnProps> = ({
|
||||
categories,
|
||||
itemIds,
|
||||
selectedCategories,
|
||||
categoryPlaceholderKey,
|
||||
selectedIds,
|
||||
filterValue,
|
||||
filterPlaceholder,
|
||||
@ -171,7 +173,9 @@ const Picker: FC<OwnProps> = ({
|
||||
onFilterChange?.(value);
|
||||
});
|
||||
|
||||
const [viewportIds, getMore] = useInfiniteScroll(onLoadMore, sortedItemIds, Boolean(filterValue));
|
||||
const [viewportIds, getMore] = useInfiniteScroll(
|
||||
onLoadMore, sortedItemIds, Boolean(filterValue),
|
||||
);
|
||||
|
||||
const lang = useOldLang();
|
||||
|
||||
@ -247,13 +251,15 @@ const Picker: FC<OwnProps> = ({
|
||||
return (
|
||||
<div key="categories">
|
||||
{Boolean(categories?.length) && (
|
||||
<div className="picker-category-title">{lang('PrivacyUserTypes')}</div>
|
||||
<>
|
||||
{categoryPlaceholderKey && <div className="picker-category-title">{lang(categoryPlaceholderKey)}</div>}
|
||||
{categories?.map((category) => renderItem(category.type, true))}
|
||||
<div className="picker-category-title">{lang('FilterChats')}</div>
|
||||
</>
|
||||
)}
|
||||
{categories?.map((category) => renderItem(category.type, true))}
|
||||
<div className="picker-category-title">{lang('FilterChats')}</div>
|
||||
</div>
|
||||
);
|
||||
}, [categories, lang, renderItem]);
|
||||
}, [categories, categoryPlaceholderKey, lang, renderItem]);
|
||||
|
||||
return (
|
||||
<div className={buildClassName('Picker', className)}>
|
||||
|
||||
@ -146,6 +146,7 @@ const SettingsPrivacyVisibilityExceptionList: FC<OwnProps & StateProps> = ({
|
||||
selectedCategories={newSelectedCategoryTypes}
|
||||
filterValue={searchQuery}
|
||||
filterPlaceholder={isAllowList ? lang('AlwaysAllowPlaceholder') : lang('NeverAllowPlaceholder')}
|
||||
categoryPlaceholderKey="PrivacyUserTypes"
|
||||
searchInputId="new-group-picker-search"
|
||||
isSearchable
|
||||
onSelectedIdsChange={handleSelectedContactIdsChange}
|
||||
|
||||
@ -94,3 +94,16 @@
|
||||
.settings-sortable-item .multiline-item {
|
||||
padding-inline-end: 3rem;
|
||||
}
|
||||
|
||||
.settings-folders-chat-list {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.picker-category-title {
|
||||
padding-top: 0.75rem;
|
||||
}
|
||||
|
||||
.down {
|
||||
font-size: 1.5rem;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
@ -1,25 +1,31 @@
|
||||
import type { FC } from '../../../../lib/teact/teact';
|
||||
import React, { memo, useCallback, useMemo } from '../../../../lib/teact/teact';
|
||||
import { getGlobal } from '../../../../global';
|
||||
import React, {
|
||||
memo, useEffect, useMemo, useState,
|
||||
} from '../../../../lib/teact/teact';
|
||||
import { getActions, getGlobal, withGlobal } from '../../../../global';
|
||||
|
||||
import type {
|
||||
FolderEditDispatch,
|
||||
FoldersState,
|
||||
} from '../../../../hooks/reducers/useFoldersReducer';
|
||||
import type { FolderEditDispatch, FoldersState } from '../../../../hooks/reducers/useFoldersReducer';
|
||||
|
||||
import { ALL_FOLDER_ID, ARCHIVED_FOLDER_ID } from '../../../../config';
|
||||
import { filterChatsByName } from '../../../../global/helpers';
|
||||
import { selectCurrentLimit } from '../../../../global/selectors/limits';
|
||||
import { unique } from '../../../../util/iteratees';
|
||||
import { CUSTOM_PEER_EXCLUDED_CHAT_TYPES, CUSTOM_PEER_INCLUDED_CHAT_TYPES } from '../../../../util/objects/customPeer';
|
||||
|
||||
import {
|
||||
selectChatFilters,
|
||||
} from '../../../../hooks/reducers/useFoldersReducer';
|
||||
import { selectChatFilters } from '../../../../hooks/reducers/useFoldersReducer';
|
||||
import { useFolderManagerForOrderedIds } from '../../../../hooks/useFolderManager';
|
||||
import useHistoryBack from '../../../../hooks/useHistoryBack';
|
||||
import useLastCallback from '../../../../hooks/useLastCallback';
|
||||
import useOldLang from '../../../../hooks/useOldLang';
|
||||
|
||||
import Icon from '../../../common/icons/Icon';
|
||||
import Picker from '../../../common/Picker';
|
||||
import FloatingActionButton from '../../../ui/FloatingActionButton';
|
||||
import Loading from '../../../ui/Loading';
|
||||
import SettingsFoldersChatsPicker from './SettingsFoldersChatsPicker';
|
||||
|
||||
type StateProps = {
|
||||
maxChats: number;
|
||||
};
|
||||
|
||||
type OwnProps = {
|
||||
mode: 'included' | 'excluded';
|
||||
@ -30,44 +36,62 @@ type OwnProps = {
|
||||
onSaveFilter: VoidFunction;
|
||||
};
|
||||
|
||||
const SettingsFoldersChatFilters: FC<OwnProps> = ({
|
||||
const SettingsFoldersChatFilters: FC<OwnProps & StateProps> = ({
|
||||
mode,
|
||||
state,
|
||||
dispatch,
|
||||
isActive,
|
||||
onReset,
|
||||
onSaveFilter,
|
||||
maxChats,
|
||||
}) => {
|
||||
const lang = useOldLang();
|
||||
|
||||
const { openLimitReachedModal } = getActions();
|
||||
|
||||
const { chatFilter } = state;
|
||||
const { selectedChatIds, selectedChatTypes } = selectChatFilters(state, mode, true);
|
||||
const chatTypes = mode === 'included' ? CUSTOM_PEER_INCLUDED_CHAT_TYPES : CUSTOM_PEER_EXCLUDED_CHAT_TYPES;
|
||||
|
||||
const lang = useOldLang();
|
||||
const [isTouched, setIsTouched] = useState(false);
|
||||
|
||||
const folderAllOrderedIds = useFolderManagerForOrderedIds(ALL_FOLDER_ID);
|
||||
const folderArchivedOrderedIds = useFolderManagerForOrderedIds(ARCHIVED_FOLDER_ID);
|
||||
|
||||
const shouldHideChatTypes = state.folder.isChatList;
|
||||
|
||||
useEffect(() => {
|
||||
if (!isActive) {
|
||||
setIsTouched(false);
|
||||
}
|
||||
}, [isActive]);
|
||||
|
||||
const displayedIds = useMemo(() => {
|
||||
// No need for expensive global updates on chats, so we avoid them
|
||||
const chatsById = getGlobal().chats.byId;
|
||||
|
||||
const chatIds = [...folderAllOrderedIds || [], ...folderArchivedOrderedIds || []];
|
||||
return unique([
|
||||
...selectedChatIds,
|
||||
...filterChatsByName(lang, chatIds, chatsById, chatFilter),
|
||||
]);
|
||||
}, [folderAllOrderedIds, folderArchivedOrderedIds, selectedChatIds, lang, chatFilter]);
|
||||
}, [folderAllOrderedIds, folderArchivedOrderedIds, lang, chatFilter]);
|
||||
|
||||
const handleFilterChange = useCallback((newFilter: string) => {
|
||||
const handleFilterChange = useLastCallback((newFilter: string) => {
|
||||
dispatch({
|
||||
type: 'setChatFilter',
|
||||
payload: newFilter,
|
||||
});
|
||||
}, [dispatch]);
|
||||
setIsTouched(true);
|
||||
});
|
||||
|
||||
const handleSelectedIdsChange = useCallback((ids: string[]) => {
|
||||
const handleSelectedIdsChange = useLastCallback((ids: string[]) => {
|
||||
if (mode === 'included') {
|
||||
if (ids.length >= maxChats) {
|
||||
openLimitReachedModal({
|
||||
limit: 'dialogFiltersChats',
|
||||
});
|
||||
return;
|
||||
}
|
||||
dispatch({
|
||||
type: 'setIncludeFilters',
|
||||
payload: { ...state.includeFilters, includedChatIds: ids },
|
||||
@ -78,9 +102,10 @@ const SettingsFoldersChatFilters: FC<OwnProps> = ({
|
||||
payload: { ...state.excludeFilters, excludedChatIds: ids },
|
||||
});
|
||||
}
|
||||
}, [mode, state, dispatch]);
|
||||
setIsTouched(true);
|
||||
});
|
||||
|
||||
const handleSelectedChatTypesChange = useCallback((keys: string[]) => {
|
||||
const handleSelectedChatTypesChange = useLastCallback((keys: string[]) => {
|
||||
const newFilters: Record<string, boolean> = {};
|
||||
keys.forEach((key) => {
|
||||
newFilters[key] = true;
|
||||
@ -103,7 +128,7 @@ const SettingsFoldersChatFilters: FC<OwnProps> = ({
|
||||
},
|
||||
});
|
||||
}
|
||||
}, [mode, selectedChatIds, dispatch]);
|
||||
});
|
||||
|
||||
useHistoryBack({
|
||||
isActive,
|
||||
@ -115,20 +140,38 @@ const SettingsFoldersChatFilters: FC<OwnProps> = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<SettingsFoldersChatsPicker
|
||||
mode={mode}
|
||||
chatIds={displayedIds}
|
||||
selectedIds={selectedChatIds}
|
||||
selectedChatTypes={selectedChatTypes}
|
||||
filterValue={chatFilter}
|
||||
shouldHideChatTypes={shouldHideChatTypes}
|
||||
onSelectedIdsChange={handleSelectedIdsChange}
|
||||
onSelectedChatTypesChange={handleSelectedChatTypesChange}
|
||||
onFilterChange={handleFilterChange}
|
||||
onSaveFilter={onSaveFilter}
|
||||
isActive={isActive}
|
||||
/>
|
||||
<div className="Picker settings-folders-chat-list">
|
||||
<Picker
|
||||
categories={shouldHideChatTypes ? undefined : chatTypes}
|
||||
itemIds={displayedIds}
|
||||
selectedIds={selectedChatIds}
|
||||
selectedCategories={selectedChatTypes}
|
||||
filterValue={chatFilter}
|
||||
filterPlaceholder={lang('Search')}
|
||||
categoryPlaceholderKey="FilterChatTypes"
|
||||
searchInputId="new-group-picker-search"
|
||||
isSearchable
|
||||
isRoundCheckbox
|
||||
onSelectedIdsChange={handleSelectedIdsChange}
|
||||
onSelectedCategoriesChange={handleSelectedChatTypesChange}
|
||||
onFilterChange={handleFilterChange}
|
||||
/>
|
||||
|
||||
<FloatingActionButton
|
||||
isShown={isTouched}
|
||||
onClick={onSaveFilter}
|
||||
ariaLabel={lang('Save')}
|
||||
>
|
||||
<Icon name="check" />
|
||||
</FloatingActionButton>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(SettingsFoldersChatFilters);
|
||||
export default memo(withGlobal<OwnProps>(
|
||||
(global): StateProps => {
|
||||
return {
|
||||
maxChats: selectCurrentLimit(global, 'dialogFiltersChats'),
|
||||
};
|
||||
},
|
||||
)(SettingsFoldersChatFilters));
|
||||
|
||||
@ -1,63 +0,0 @@
|
||||
.SettingsFoldersChatsPicker {
|
||||
height: calc(100% - var(--header-height));
|
||||
|
||||
.picker-header {
|
||||
box-shadow: 0 0 2px var(--color-default-shadow);
|
||||
|
||||
.max-items-reached {
|
||||
margin-bottom: 0.5rem;
|
||||
margin-left: 0.5rem;
|
||||
flex-grow: 1;
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
}
|
||||
|
||||
.picker-list {
|
||||
padding: 0 0.5rem 0.5rem;
|
||||
|
||||
.no-results {
|
||||
height: 10rem;
|
||||
}
|
||||
}
|
||||
|
||||
.ListItem.picker-list-item {
|
||||
&.chat-type-item .ListItem-button {
|
||||
padding: 0.875rem 0.75rem;
|
||||
}
|
||||
|
||||
&.chat-item .ListItem-button {
|
||||
padding: 0.5rem 0.75rem;
|
||||
}
|
||||
|
||||
.Checkbox {
|
||||
margin-left: auto;
|
||||
padding-left: 3.25rem;
|
||||
}
|
||||
|
||||
.chat-type {
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
&[dir="rtl"] {
|
||||
.Checkbox {
|
||||
margin-left: 0;
|
||||
margin-right: auto;
|
||||
padding-left: 0;
|
||||
padding-right: 3.25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.settings-item-header {
|
||||
margin-left: 0.75rem;
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.picker-list-divider {
|
||||
margin: 0.5rem -0.5rem 0;
|
||||
border-bottom: 1px solid var(--color-borders);
|
||||
}
|
||||
}
|
||||
@ -1,262 +0,0 @@
|
||||
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 { FolderChatType } from '../../../../hooks/reducers/useFoldersReducer';
|
||||
|
||||
import { requestMutation } from '../../../../lib/fasterdom/fasterdom';
|
||||
import { isUserId } from '../../../../global/helpers';
|
||||
import { selectCurrentLimit } from '../../../../global/selectors/limits';
|
||||
import buildClassName from '../../../../util/buildClassName';
|
||||
|
||||
import {
|
||||
EXCLUDED_CHAT_TYPES,
|
||||
INCLUDED_CHAT_TYPES,
|
||||
} from '../../../../hooks/reducers/useFoldersReducer';
|
||||
import useInfiniteScroll from '../../../../hooks/useInfiniteScroll';
|
||||
import useOldLang from '../../../../hooks/useOldLang';
|
||||
|
||||
import GroupChatInfo from '../../../common/GroupChatInfo';
|
||||
import PickerSelectedItem from '../../../common/PickerSelectedItem';
|
||||
import PrivateChatInfo from '../../../common/PrivateChatInfo';
|
||||
import Checkbox from '../../../ui/Checkbox';
|
||||
import FloatingActionButton from '../../../ui/FloatingActionButton';
|
||||
import InfiniteScroll from '../../../ui/InfiniteScroll';
|
||||
import InputText from '../../../ui/InputText';
|
||||
import ListItem from '../../../ui/ListItem';
|
||||
import Loading from '../../../ui/Loading';
|
||||
|
||||
import '../../../common/Picker.scss';
|
||||
import './SettingsFoldersChatsPicker.scss';
|
||||
|
||||
type OwnProps = {
|
||||
mode: 'included' | 'excluded';
|
||||
chatIds: string[];
|
||||
selectedIds: string[];
|
||||
selectedChatTypes: string[];
|
||||
filterValue?: string;
|
||||
shouldHideChatTypes?: boolean;
|
||||
onSelectedIdsChange: (ids: string[]) => void;
|
||||
onSelectedChatTypesChange: (types: string[]) => void;
|
||||
onFilterChange: (value: string) => void;
|
||||
onSaveFilter: VoidFunction;
|
||||
isActive?: boolean;
|
||||
};
|
||||
|
||||
// Focus slows down animation, also it breaks transition layout in Chrome
|
||||
const FOCUS_DELAY_MS = 500;
|
||||
|
||||
const MAX_FULL_ITEMS = 10;
|
||||
const ALWAYS_FULL_ITEMS_COUNT = 5;
|
||||
|
||||
type StateProps = {
|
||||
maxChats: number;
|
||||
};
|
||||
|
||||
const SettingsFoldersChatsPicker: FC<OwnProps & StateProps> = ({
|
||||
mode,
|
||||
chatIds,
|
||||
selectedIds,
|
||||
selectedChatTypes,
|
||||
filterValue,
|
||||
shouldHideChatTypes,
|
||||
onSelectedIdsChange,
|
||||
onSelectedChatTypesChange,
|
||||
onFilterChange,
|
||||
maxChats,
|
||||
onSaveFilter,
|
||||
isActive,
|
||||
}) => {
|
||||
const { openLimitReachedModal } = getActions();
|
||||
// eslint-disable-next-line no-null/no-null
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const chatTypes = mode === 'included' ? INCLUDED_CHAT_TYPES : EXCLUDED_CHAT_TYPES;
|
||||
const shouldMinimize = selectedIds.length + selectedChatTypes.length > MAX_FULL_ITEMS;
|
||||
const [isTouched, setIsTouched] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isActive) {
|
||||
setIsTouched(false);
|
||||
}
|
||||
}, [isActive]);
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
requestMutation(() => {
|
||||
inputRef.current!.focus();
|
||||
});
|
||||
}, FOCUS_DELAY_MS);
|
||||
}, []);
|
||||
|
||||
const handleItemClick = useCallback((id: string) => {
|
||||
const newSelectedIds = [...selectedIds];
|
||||
if (newSelectedIds.includes(id)) {
|
||||
newSelectedIds.splice(newSelectedIds.indexOf(id), 1);
|
||||
} else {
|
||||
if (selectedIds.length >= maxChats && mode === 'included') {
|
||||
openLimitReachedModal({
|
||||
limit: 'dialogFiltersChats',
|
||||
});
|
||||
return;
|
||||
}
|
||||
newSelectedIds.push(id);
|
||||
}
|
||||
setIsTouched(true);
|
||||
onSelectedIdsChange(newSelectedIds);
|
||||
}, [selectedIds, onSelectedIdsChange, maxChats, mode, openLimitReachedModal]);
|
||||
|
||||
const handleChatTypeClick = useCallback((key: FolderChatType['key']) => {
|
||||
const newSelectedChatTypes = [...selectedChatTypes];
|
||||
if (newSelectedChatTypes.includes(key)) {
|
||||
newSelectedChatTypes.splice(newSelectedChatTypes.indexOf(key), 1);
|
||||
} else {
|
||||
newSelectedChatTypes.push(key);
|
||||
}
|
||||
setIsTouched(true);
|
||||
onSelectedChatTypesChange(newSelectedChatTypes);
|
||||
}, [selectedChatTypes, onSelectedChatTypesChange]);
|
||||
|
||||
const handleFilterChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const { value } = e.currentTarget;
|
||||
onFilterChange(value);
|
||||
}, [onFilterChange]);
|
||||
|
||||
const lang = useOldLang();
|
||||
|
||||
function renderSelectedChatType(key: string) {
|
||||
const selectedType = chatTypes.find(({ key: typeKey }) => key === typeKey);
|
||||
if (!selectedType) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return (
|
||||
<PickerSelectedItem
|
||||
icon={selectedType.icon}
|
||||
title={lang(selectedType.title)}
|
||||
isMinimized={shouldMinimize}
|
||||
canClose
|
||||
onClick={handleChatTypeClick}
|
||||
clickArg={selectedType.key}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function renderChatType(type: FolderChatType) {
|
||||
return (
|
||||
<ListItem
|
||||
key={type.key}
|
||||
className="chat-item-clickable picker-list-item chat-type-item"
|
||||
// eslint-disable-next-line react/jsx-no-bind
|
||||
onClick={() => handleChatTypeClick(type.key)}
|
||||
ripple
|
||||
>
|
||||
<i className={buildClassName('icon', `icon-${type.icon}`)} />
|
||||
<h3 className="chat-type" dir="auto">{lang(type.title)}</h3>
|
||||
<Checkbox
|
||||
label=""
|
||||
checked={selectedChatTypes.includes(type.key)}
|
||||
round
|
||||
/>
|
||||
</ListItem>
|
||||
);
|
||||
}
|
||||
|
||||
function renderItem(id: string) {
|
||||
const isSelected = selectedIds.includes(id);
|
||||
|
||||
return (
|
||||
<ListItem
|
||||
key={id}
|
||||
className="chat-item-clickable picker-list-item chat-item"
|
||||
// eslint-disable-next-line react/jsx-no-bind
|
||||
onClick={() => handleItemClick(id)}
|
||||
ripple
|
||||
>
|
||||
{isUserId(id) ? (
|
||||
<PrivateChatInfo userId={id} />
|
||||
) : (
|
||||
<GroupChatInfo chatId={id} withChatType />
|
||||
)}
|
||||
<Checkbox
|
||||
label=""
|
||||
checked={isSelected}
|
||||
round
|
||||
/>
|
||||
</ListItem>
|
||||
);
|
||||
}
|
||||
|
||||
const [viewportIds, getMore] = useInfiniteScroll(undefined, chatIds, Boolean(filterValue));
|
||||
|
||||
return (
|
||||
<div className="Picker SettingsFoldersChatsPicker">
|
||||
<div className="picker-header custom-scroll">
|
||||
{selectedChatTypes.map(renderSelectedChatType)}
|
||||
{selectedIds.map((id, i) => (
|
||||
<PickerSelectedItem
|
||||
peerId={id}
|
||||
isMinimized={shouldMinimize && i < selectedIds.length - ALWAYS_FULL_ITEMS_COUNT}
|
||||
canClose
|
||||
onClick={handleItemClick}
|
||||
clickArg={id}
|
||||
/>
|
||||
))}
|
||||
<InputText
|
||||
ref={inputRef}
|
||||
value={filterValue}
|
||||
onChange={handleFilterChange}
|
||||
placeholder={lang('Search')}
|
||||
/>
|
||||
</div>
|
||||
<InfiniteScroll
|
||||
className="picker-list custom-scroll fab-padding-bottom"
|
||||
itemSelector=".chat-item"
|
||||
items={viewportIds}
|
||||
onLoadMore={getMore}
|
||||
>
|
||||
{(!viewportIds || !viewportIds.length || viewportIds.includes(chatIds[0])) && (
|
||||
<div key="header">
|
||||
{!shouldHideChatTypes && (
|
||||
<>
|
||||
<h4 className="settings-item-header" dir={lang.isRtl ? 'rtl' : undefined}>
|
||||
{lang('FilterChatTypes')}
|
||||
</h4>
|
||||
{chatTypes.map(renderChatType)}
|
||||
<div className="picker-list-divider" />
|
||||
</>
|
||||
)}
|
||||
<h4 className="settings-item-header" dir={lang.isRtl ? 'rtl' : undefined}>
|
||||
{lang('FilterChats')}
|
||||
</h4>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{viewportIds?.length ? (
|
||||
viewportIds.map(renderItem)
|
||||
) : viewportIds && !viewportIds.length ? (
|
||||
<p className="no-results" key="no-results">Sorry, nothing found.</p>
|
||||
) : (
|
||||
<Loading key="loading" />
|
||||
)}
|
||||
</InfiniteScroll>
|
||||
|
||||
<FloatingActionButton
|
||||
isShown={isTouched}
|
||||
onClick={onSaveFilter}
|
||||
ariaLabel={lang('Save')}
|
||||
>
|
||||
<i className="icon icon-check" />
|
||||
</FloatingActionButton>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(withGlobal<OwnProps>(
|
||||
(global): StateProps => {
|
||||
return {
|
||||
maxChats: selectCurrentLimit(global, 'dialogFiltersChats'),
|
||||
};
|
||||
},
|
||||
)(SettingsFoldersChatsPicker));
|
||||
@ -28,11 +28,11 @@ import useOldLang from '../../../../hooks/useOldLang';
|
||||
|
||||
import AnimatedIcon from '../../../common/AnimatedIcon';
|
||||
import GroupChatInfo from '../../../common/GroupChatInfo';
|
||||
import Icon from '../../../common/icons/Icon';
|
||||
import PrivateChatInfo from '../../../common/PrivateChatInfo';
|
||||
import FloatingActionButton from '../../../ui/FloatingActionButton';
|
||||
import InputText from '../../../ui/InputText';
|
||||
import ListItem from '../../../ui/ListItem';
|
||||
import ShowMoreButton from '../../../ui/ShowMoreButton';
|
||||
import Spinner from '../../../ui/Spinner';
|
||||
|
||||
type OwnProps = {
|
||||
@ -265,12 +265,14 @@ const SettingsFoldersEdit: FC<OwnProps & StateProps> = ({
|
||||
</ListItem>
|
||||
))}
|
||||
{(!isExpanded && leftChatsCount > 0) && (
|
||||
<ShowMoreButton
|
||||
count={leftChatsCount}
|
||||
itemName="chat"
|
||||
<ListItem
|
||||
key="load-more"
|
||||
// eslint-disable-next-line react/jsx-no-bind
|
||||
onClick={clickHandler}
|
||||
/>
|
||||
>
|
||||
<Icon name="down" className="down" />
|
||||
{lang('FilterShowMoreChats', leftChatsCount, 'i')}
|
||||
</ListItem>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
@ -483,7 +483,8 @@ export type InlineBotSettings = {
|
||||
cacheTime: number;
|
||||
};
|
||||
|
||||
export type CustomPeerType = 'premium' | 'toBeDistributed';
|
||||
export type CustomPeerType = 'premium' | 'toBeDistributed' | 'contacts' | 'nonContacts'
|
||||
| 'groups' | 'channels' | 'bots' | 'excludeMuted' | 'excludeArchived' | 'excludeRead';
|
||||
|
||||
export interface CustomPeer {
|
||||
isCustomPeer: true;
|
||||
|
||||
@ -17,3 +17,73 @@ export const CUSTOM_PEER_TO_BE_DISTRIBUTED: UniqueCustomPeer = {
|
||||
avatarIcon: 'user',
|
||||
withPremiumGradient: true,
|
||||
};
|
||||
|
||||
export const CUSTOM_PEER_INCLUDED_CHAT_TYPES: UniqueCustomPeer[] = [
|
||||
{
|
||||
isCustomPeer: true,
|
||||
type: 'contacts',
|
||||
titleKey: 'FilterContacts',
|
||||
avatarIcon: 'user',
|
||||
isAvatarSquare: true,
|
||||
peerColorId: 5,
|
||||
},
|
||||
{
|
||||
isCustomPeer: true,
|
||||
type: 'nonContacts',
|
||||
titleKey: 'FilterNonContacts',
|
||||
avatarIcon: 'non-contacts',
|
||||
isAvatarSquare: true,
|
||||
peerColorId: 4,
|
||||
},
|
||||
{
|
||||
isCustomPeer: true,
|
||||
type: 'groups',
|
||||
titleKey: 'FilterGroups',
|
||||
avatarIcon: 'group',
|
||||
isAvatarSquare: true,
|
||||
peerColorId: 3,
|
||||
},
|
||||
{
|
||||
isCustomPeer: true,
|
||||
type: 'channels',
|
||||
titleKey: 'FilterChannels',
|
||||
avatarIcon: 'channel',
|
||||
isAvatarSquare: true,
|
||||
peerColorId: 1,
|
||||
},
|
||||
{
|
||||
isCustomPeer: true,
|
||||
type: 'bots',
|
||||
titleKey: 'FilterBots',
|
||||
avatarIcon: 'bots',
|
||||
isAvatarSquare: true,
|
||||
peerColorId: 6,
|
||||
},
|
||||
];
|
||||
|
||||
export const CUSTOM_PEER_EXCLUDED_CHAT_TYPES: UniqueCustomPeer[] = [
|
||||
{
|
||||
isCustomPeer: true,
|
||||
type: 'excludeMuted',
|
||||
titleKey: 'FilterMuted',
|
||||
avatarIcon: 'mute',
|
||||
isAvatarSquare: true,
|
||||
peerColorId: 6,
|
||||
},
|
||||
{
|
||||
isCustomPeer: true,
|
||||
type: 'excludeRead',
|
||||
titleKey: 'FilterRead',
|
||||
avatarIcon: 'readchats',
|
||||
isAvatarSquare: true,
|
||||
peerColorId: 4,
|
||||
},
|
||||
{
|
||||
isCustomPeer: true,
|
||||
type: 'excludeArchived',
|
||||
titleKey: 'FilterArchived',
|
||||
avatarIcon: 'archive',
|
||||
isAvatarSquare: true,
|
||||
peerColorId: 5,
|
||||
},
|
||||
];
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user