[Perf] TeactN: Get rid of redundant iterations for global actions

This commit is contained in:
Alexander Zinchuk 2021-12-31 18:17:27 +01:00
parent d12c9d384d
commit 3ef7136621
133 changed files with 1116 additions and 1797 deletions

View File

@ -1,7 +1,7 @@
import { FC, useEffect } from './lib/teact/teact'; import { FC, useEffect } from './lib/teact/teact';
import React, { withGlobal } from './lib/teact/teactn'; import React, { getDispatch, withGlobal } from './lib/teact/teactn';
import { GlobalActions, GlobalState } from './global/types'; import { GlobalState } from './global/types';
import { INACTIVE_MARKER, PAGE_TITLE } from './config'; import { INACTIVE_MARKER, PAGE_TITLE } from './config';
import { pick } from './util/iteratees'; import { pick } from './util/iteratees';
@ -17,9 +17,10 @@ import { hasStoredSession } from './util/sessions';
// import Test from './components/test/TestNoRedundancy'; // import Test from './components/test/TestNoRedundancy';
type StateProps = Pick<GlobalState, 'authState'>; type StateProps = Pick<GlobalState, 'authState'>;
type DispatchProps = Pick<GlobalActions, 'disconnect'>;
const App: FC<StateProps & DispatchProps> = ({ authState, disconnect }) => { const App: FC<StateProps> = ({ authState }) => {
const { disconnect } = getDispatch();
const [isInactive, markInactive] = useFlag(false); const [isInactive, markInactive] = useFlag(false);
useEffect(() => { useEffect(() => {
@ -67,5 +68,4 @@ function renderMain() {
export default withGlobal( export default withGlobal(
(global): StateProps => pick(global, ['authState']), (global): StateProps => pick(global, ['authState']),
(setGlobal, actions): DispatchProps => pick(actions, ['disconnect']),
)(App); )(App);

View File

@ -1,7 +1,7 @@
import React, { FC, useEffect, memo } from '../../lib/teact/teact'; import React, { FC, useEffect, memo } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { GlobalActions, GlobalState } from '../../global/types'; import { GlobalState } from '../../global/types';
import '../../modules/actions/initial'; import '../../modules/actions/initial';
import { pick } from '../../util/iteratees'; import { pick } from '../../util/iteratees';
@ -19,11 +19,14 @@ import AuthQrCode from './AuthQrCode';
import './Auth.scss'; import './Auth.scss';
type StateProps = Pick<GlobalState, 'authState'>; type StateProps = Pick<GlobalState, 'authState'>;
type DispatchProps = Pick<GlobalActions, 'reset' | 'initApi' | 'returnToAuthPhoneNumber' | 'goToAuthQrCode'>;
const Auth: FC<StateProps & DispatchProps> = ({ const Auth: FC<StateProps> = ({
authState, reset, initApi, returnToAuthPhoneNumber, goToAuthQrCode, authState,
}) => { }) => {
const {
reset, initApi, returnToAuthPhoneNumber, goToAuthQrCode,
} = getDispatch();
useEffect(() => { useEffect(() => {
reset(); reset();
initApi(); initApi();
@ -73,5 +76,4 @@ const Auth: FC<StateProps & DispatchProps> = ({
export default memo(withGlobal( export default memo(withGlobal(
(global): StateProps => pick(global, ['authState']), (global): StateProps => pick(global, ['authState']),
(global, actions): DispatchProps => pick(actions, ['reset', 'initApi', 'returnToAuthPhoneNumber', 'goToAuthQrCode']),
)(Auth)); )(Auth));

View File

@ -2,8 +2,8 @@ import { FormEvent } from 'react';
import React, { import React, {
FC, useState, useEffect, useCallback, memo, useRef, FC, useState, useEffect, useCallback, memo, useRef,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { GlobalState, GlobalActions } from '../../global/types'; import { GlobalState } from '../../global/types';
import { IS_TOUCH_ENV } from '../../util/environment'; import { IS_TOUCH_ENV } from '../../util/environment';
import { pick } from '../../util/iteratees'; import { pick } from '../../util/iteratees';
@ -16,21 +16,21 @@ import Loading from '../ui/Loading';
import TrackingMonkey from '../common/TrackingMonkey'; import TrackingMonkey from '../common/TrackingMonkey';
type StateProps = Pick<GlobalState, 'authPhoneNumber' | 'authIsCodeViaApp' | 'authIsLoading' | 'authError'>; type StateProps = Pick<GlobalState, 'authPhoneNumber' | 'authIsCodeViaApp' | 'authIsLoading' | 'authError'>;
type DispatchProps = Pick<GlobalActions, (
'setAuthCode' | 'returnToAuthPhoneNumber' | 'clearAuthError'
)>;
const CODE_LENGTH = 5; const CODE_LENGTH = 5;
const AuthCode: FC<StateProps & DispatchProps> = ({ const AuthCode: FC<StateProps> = ({
authPhoneNumber, authPhoneNumber,
authIsCodeViaApp, authIsCodeViaApp,
authIsLoading, authIsLoading,
authError, authError,
setAuthCode,
returnToAuthPhoneNumber,
clearAuthError,
}) => { }) => {
const {
setAuthCode,
returnToAuthPhoneNumber,
clearAuthError,
} = getDispatch();
const lang = useLang(); const lang = useLang();
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
const inputRef = useRef<HTMLInputElement>(null); const inputRef = useRef<HTMLInputElement>(null);
@ -120,9 +120,4 @@ const AuthCode: FC<StateProps & DispatchProps> = ({
export default memo(withGlobal( export default memo(withGlobal(
(global): StateProps => pick(global, ['authPhoneNumber', 'authIsCodeViaApp', 'authIsLoading', 'authError']), (global): StateProps => pick(global, ['authPhoneNumber', 'authIsCodeViaApp', 'authIsLoading', 'authError']),
(setGlobal, actions): DispatchProps => pick(actions, [
'setAuthCode',
'returnToAuthPhoneNumber',
'clearAuthError',
]),
)(AuthCode)); )(AuthCode));

View File

@ -1,9 +1,9 @@
import React, { import React, {
FC, memo, useCallback, useState, FC, memo, useCallback, useState,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { GlobalState, GlobalActions } from '../../global/types'; import { GlobalState } from '../../global/types';
import { pick } from '../../util/iteratees'; import { pick } from '../../util/iteratees';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
@ -12,11 +12,12 @@ import MonkeyPassword from '../common/PasswordMonkey';
import PasswordForm from '../common/PasswordForm'; import PasswordForm from '../common/PasswordForm';
type StateProps = Pick<GlobalState, 'authIsLoading' | 'authError' | 'authHint'>; type StateProps = Pick<GlobalState, 'authIsLoading' | 'authError' | 'authHint'>;
type DispatchProps = Pick<GlobalActions, 'setAuthPassword' | 'clearAuthError'>;
const AuthPassword: FC<StateProps & DispatchProps> = ({ const AuthPassword: FC<StateProps> = ({
authIsLoading, authError, authHint, setAuthPassword, clearAuthError, authIsLoading, authError, authHint,
}) => { }) => {
const { setAuthPassword, clearAuthError } = getDispatch();
const lang = useLang(); const lang = useLang();
const [showPassword, setShowPassword] = useState(false); const [showPassword, setShowPassword] = useState(false);
@ -50,5 +51,4 @@ const AuthPassword: FC<StateProps & DispatchProps> = ({
export default memo(withGlobal( export default memo(withGlobal(
(global): StateProps => pick(global, ['authIsLoading', 'authError', 'authHint']), (global): StateProps => pick(global, ['authIsLoading', 'authError', 'authHint']),
(setGlobal, actions): DispatchProps => pick(actions, ['setAuthPassword', 'clearAuthError']),
)(AuthPassword)); )(AuthPassword));

View File

@ -6,9 +6,9 @@ import monkeyPath from '../../assets/monkey.svg';
import React, { import React, {
FC, memo, useCallback, useEffect, useLayoutEffect, useRef, useState, FC, memo, useCallback, useEffect, useLayoutEffect, useRef, useState,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { GlobalActions, GlobalState } from '../../global/types'; import { GlobalState } from '../../global/types';
import { LangCode } from '../../types'; import { LangCode } from '../../types';
import { ApiCountryCode } from '../../api/types'; import { ApiCountryCode } from '../../api/types';
@ -38,16 +38,12 @@ type StateProps = Pick<GlobalState, (
language?: LangCode; language?: LangCode;
phoneCodeList: ApiCountryCode[]; phoneCodeList: ApiCountryCode[];
}; };
type DispatchProps = Pick<GlobalActions, (
'setAuthPhoneNumber' | 'setAuthRememberMe' | 'loadNearestCountry' | 'loadCountryList' | 'clearAuthError' |
'goToAuthQrCode' | 'setSettingOption'
)>;
const MIN_NUMBER_LENGTH = 7; const MIN_NUMBER_LENGTH = 7;
let isPreloadInitiated = false; let isPreloadInitiated = false;
const AuthPhoneNumber: FC<StateProps & DispatchProps> = ({ const AuthPhoneNumber: FC<StateProps> = ({
connectionState, connectionState,
authState, authState,
authPhoneNumber, authPhoneNumber,
@ -58,14 +54,17 @@ const AuthPhoneNumber: FC<StateProps & DispatchProps> = ({
authNearestCountry, authNearestCountry,
phoneCodeList, phoneCodeList,
language, language,
setAuthPhoneNumber,
setAuthRememberMe,
loadNearestCountry,
loadCountryList,
clearAuthError,
goToAuthQrCode,
setSettingOption,
}) => { }) => {
const {
setAuthPhoneNumber,
setAuthRememberMe,
loadNearestCountry,
loadCountryList,
clearAuthError,
goToAuthQrCode,
setSettingOption,
} = getDispatch();
const lang = useLang(); const lang = useLang();
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
const inputRef = useRef<HTMLInputElement>(null); const inputRef = useRef<HTMLInputElement>(null);
@ -278,13 +277,4 @@ export default memo(withGlobal(
phoneCodeList, phoneCodeList,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'setAuthPhoneNumber',
'setAuthRememberMe',
'clearAuthError',
'loadNearestCountry',
'loadCountryList',
'goToAuthQrCode',
'setSettingOption',
]),
)(AuthPhoneNumber)); )(AuthPhoneNumber));

View File

@ -2,13 +2,12 @@ import QrCreator from 'qr-creator';
import React, { import React, {
FC, useEffect, useRef, memo, useCallback, FC, useEffect, useRef, memo, useCallback,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { GlobalState, GlobalActions } from '../../global/types'; import { GlobalState } from '../../global/types';
import { LangCode } from '../../types'; import { LangCode } from '../../types';
import { DEFAULT_LANG_CODE } from '../../config'; import { DEFAULT_LANG_CODE } from '../../config';
import { pick } from '../../util/iteratees';
import { setLanguage } from '../../util/langProvider'; import { setLanguage } from '../../util/langProvider';
import renderText from '../common/helpers/renderText'; import renderText from '../common/helpers/renderText';
import useLangString from '../../hooks/useLangString'; import useLangString from '../../hooks/useLangString';
@ -19,23 +18,25 @@ import { getSuggestedLanguage } from './helpers/getSuggestedLanguage';
import Loading from '../ui/Loading'; import Loading from '../ui/Loading';
import Button from '../ui/Button'; import Button from '../ui/Button';
type StateProps = Pick<GlobalState, 'connectionState' | 'authState' | 'authQrCode'> & { type StateProps =
language?: LangCode; Pick<GlobalState, 'connectionState' | 'authState' | 'authQrCode'>
}; & {
type DispatchProps = Pick<GlobalActions, ( language?: LangCode;
'returnToAuthPhoneNumber' | 'setSettingOption' };
)>;
const DATA_PREFIX = 'tg://login?token='; const DATA_PREFIX = 'tg://login?token=';
const AuthCode: FC<StateProps & DispatchProps> = ({ const AuthCode: FC<StateProps> = ({
connectionState, connectionState,
authState, authState,
authQrCode, authQrCode,
language, language,
returnToAuthPhoneNumber,
setSettingOption,
}) => { }) => {
const {
returnToAuthPhoneNumber,
setSettingOption,
} = getDispatch();
const suggestedLanguage = getSuggestedLanguage(); const suggestedLanguage = getSuggestedLanguage();
const lang = useLang(); const lang = useLang();
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
@ -118,7 +119,4 @@ export default memo(withGlobal(
language, language,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'returnToAuthPhoneNumber', 'setSettingOption',
]),
)(AuthCode)); )(AuthCode));

View File

@ -1,8 +1,8 @@
import { ChangeEvent } from 'react'; import { ChangeEvent } from 'react';
import React, { FC, useState, memo } from '../../lib/teact/teact'; import React, { FC, useState, memo } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { GlobalState, GlobalActions } from '../../global/types'; import { GlobalState } from '../../global/types';
import { pick } from '../../util/iteratees'; import { pick } from '../../util/iteratees';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
@ -12,11 +12,12 @@ import InputText from '../ui/InputText';
import AvatarEditable from '../ui/AvatarEditable'; import AvatarEditable from '../ui/AvatarEditable';
type StateProps = Pick<GlobalState, 'authIsLoading' | 'authError'>; type StateProps = Pick<GlobalState, 'authIsLoading' | 'authError'>;
type DispatchProps = Pick<GlobalActions, 'signUp' | 'clearAuthError' | 'uploadProfilePhoto'>;
const AuthRegister: FC<StateProps & DispatchProps> = ({ const AuthRegister: FC<StateProps> = ({
authIsLoading, authError, signUp, clearAuthError, uploadProfilePhoto, authIsLoading, authError,
}) => { }) => {
const { signUp, clearAuthError, uploadProfilePhoto } = getDispatch();
const lang = useLang(); const lang = useLang();
const [isButtonShown, setIsButtonShown] = useState(false); const [isButtonShown, setIsButtonShown] = useState(false);
const [croppedFile, setCroppedFile] = useState<File | undefined>(); const [croppedFile, setCroppedFile] = useState<File | undefined>();
@ -83,5 +84,4 @@ const AuthRegister: FC<StateProps & DispatchProps> = ({
export default memo(withGlobal( export default memo(withGlobal(
(global): StateProps => pick(global, ['authIsLoading', 'authError']), (global): StateProps => pick(global, ['authIsLoading', 'authError']),
(setGlobal, actions): DispatchProps => pick(actions, ['signUp', 'clearAuthError', 'uploadProfilePhoto']),
)(AuthRegister)); )(AuthRegister));

View File

@ -2,13 +2,11 @@ import { GroupCallParticipant } from '../../lib/secret-sauce';
import React, { import React, {
FC, memo, useEffect, FC, memo, useEffect,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { GlobalActions } from '../../global/types';
import { ApiGroupCall } from '../../api/types'; import { ApiGroupCall } from '../../api/types';
import { selectActiveGroupCall, selectGroupCallParticipant } from '../../modules/selectors/calls'; import { selectActiveGroupCall, selectGroupCallParticipant } from '../../modules/selectors/calls';
import { pick } from '../../util/iteratees';
import buildClassName from '../../util/buildClassName'; import buildClassName from '../../util/buildClassName';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
@ -20,14 +18,13 @@ type StateProps = {
groupCall?: ApiGroupCall; groupCall?: ApiGroupCall;
}; };
type DispatchProps = Pick<GlobalActions, 'toggleGroupCallPanel'>; const ActiveCallHeader: FC<StateProps> = ({
const ActiveCallHeader: FC<StateProps & DispatchProps> = ({
groupCall, groupCall,
meParticipant, meParticipant,
isGroupCallPanelHidden, isGroupCallPanelHidden,
toggleGroupCallPanel,
}) => { }) => {
const { toggleGroupCallPanel } = getDispatch();
const lang = useLang(); const lang = useLang();
useEffect(() => { useEffect(() => {
@ -61,7 +58,4 @@ export default memo(withGlobal(
meParticipant: selectGroupCallParticipant(global, global.groupCalls.activeGroupCallId!, global.currentUserId!), meParticipant: selectGroupCallParticipant(global, global.groupCalls.activeGroupCallId!, global.currentUserId!),
}; };
}, },
(setGlobal, actions) => pick(actions, [
'toggleGroupCallPanel',
]),
)(ActiveCallHeader)); )(ActiveCallHeader));

View File

@ -1,9 +1,5 @@
import React, { FC, memo, useState } from '../../lib/teact/teact'; import React, { FC, memo, useState } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { GlobalActions } from '../../global/types';
import { pick } from '../../util/iteratees';
import ConfirmDialog from '../ui/ConfirmDialog'; import ConfirmDialog from '../ui/ConfirmDialog';
import Checkbox from '../ui/Checkbox'; import Checkbox from '../ui/Checkbox';
@ -21,15 +17,16 @@ interface StateProps {
channelTitle: string; channelTitle: string;
} }
type DispatchProps = Pick<GlobalActions, 'closeCallFallbackConfirm' | 'inviteToCallFallback'>; const CallFallbackConfirm: FC<OwnProps & StateProps> = ({
const CallFallbackConfirm: FC<OwnProps & StateProps & DispatchProps> = ({
isOpen, isOpen,
channelTitle, channelTitle,
userFullName, userFullName,
closeCallFallbackConfirm,
inviteToCallFallback,
}) => { }) => {
const {
closeCallFallbackConfirm,
inviteToCallFallback,
} = getDispatch();
const [shouldRemove, setShouldRemove] = useState(true); const [shouldRemove, setShouldRemove] = useState(true);
const renderingUserFullName = useCurrentOrPrev(userFullName, true); const renderingUserFullName = useCurrentOrPrev(userFullName, true);
@ -62,7 +59,4 @@ export default memo(withGlobal<OwnProps>(
channelTitle: selectCallFallbackChannelTitle(global), channelTitle: selectCallFallbackChannelTitle(global),
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'closeCallFallbackConfirm', 'inviteToCallFallback',
]),
)(CallFallbackConfirm)); )(CallFallbackConfirm));

View File

@ -5,10 +5,9 @@ import {
import React, { import React, {
FC, memo, useCallback, useEffect, useMemo, useRef, useState, FC, memo, useCallback, useEffect, useMemo, useRef, useState,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import '../../../modules/actions/calls'; import '../../../modules/actions/calls';
import { GlobalActions } from '../../../global/types';
import { IAnchorPosition } from '../../../types'; import { IAnchorPosition } from '../../../types';
import { import {
@ -17,7 +16,6 @@ import {
IS_REQUEST_FULLSCREEN_SUPPORTED, IS_REQUEST_FULLSCREEN_SUPPORTED,
IS_SINGLE_COLUMN_LAYOUT, IS_SINGLE_COLUMN_LAYOUT,
} from '../../../util/environment'; } from '../../../util/environment';
import { pick } from '../../../util/iteratees';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
import { import {
selectGroupCall, selectGroupCall,
@ -59,12 +57,7 @@ type StateProps = {
participants: Record<string, TypeGroupCallParticipant>; participants: Record<string, TypeGroupCallParticipant>;
}; };
type DispatchProps = Pick<GlobalActions, ( const GroupCall: FC<OwnProps & StateProps> = ({
'toggleGroupCallVideo' | 'leaveGroupCall' | 'toggleGroupCallPresentation' | 'toggleGroupCallPanel' |
'connectToActiveGroupCall' | 'playGroupCallSound'
)>;
const GroupCall: FC<OwnProps & StateProps & DispatchProps> = ({
groupCallId, groupCallId,
isGroupCallPanelHidden, isGroupCallPanelHidden,
connectionState, connectionState,
@ -74,13 +67,16 @@ const GroupCall: FC<OwnProps & StateProps & DispatchProps> = ({
isAdmin, isAdmin,
participants, participants,
toggleGroupCallVideo,
toggleGroupCallPresentation,
leaveGroupCall,
toggleGroupCallPanel,
connectToActiveGroupCall,
playGroupCallSound,
}) => { }) => {
const {
toggleGroupCallVideo,
toggleGroupCallPresentation,
leaveGroupCall,
toggleGroupCallPanel,
connectToActiveGroupCall,
playGroupCallSound,
} = getDispatch();
const lang = useLang(); const lang = useLang();
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
@ -411,12 +407,4 @@ export default memo(withGlobal<OwnProps>(
participants, participants,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'toggleGroupCallVideo',
'leaveGroupCall',
'toggleGroupCallPresentation',
'toggleGroupCallPanel',
'connectToActiveGroupCall',
'playGroupCallSound',
]),
)(GroupCall)); )(GroupCall));

View File

@ -1,10 +1,7 @@
import { GroupCallParticipant as TypeGroupCallParticipant } from '../../../lib/secret-sauce'; import { GroupCallParticipant as TypeGroupCallParticipant } from '../../../lib/secret-sauce';
import React, { FC, memo, useMemo } from '../../../lib/teact/teact'; import React, { FC, memo, useMemo } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { pick } from '../../../util/iteratees';
import useLang from '../../../hooks/useLang'; import useLang from '../../../hooks/useLang';
import { selectActiveGroupCall } from '../../../modules/selectors/calls'; import { selectActiveGroupCall } from '../../../modules/selectors/calls';
import useInfiniteScroll from '../../../hooks/useInfiniteScroll'; import useInfiniteScroll from '../../../hooks/useInfiniteScroll';
@ -22,15 +19,16 @@ type StateProps = {
canInvite?: boolean; canInvite?: boolean;
}; };
type DispatchProps = Pick<GlobalActions, 'createGroupCallInviteLink' | 'loadMoreGroupCallParticipants'>; const GroupCallParticipantList: FC<OwnProps & StateProps> = ({
const GroupCallParticipantList: FC<OwnProps & StateProps & DispatchProps> = ({
createGroupCallInviteLink,
loadMoreGroupCallParticipants,
participants, participants,
participantsCount, participantsCount,
openParticipantMenu, openParticipantMenu,
}) => { }) => {
const {
createGroupCallInviteLink,
loadMoreGroupCallParticipants,
} = getDispatch();
const lang = useLang(); const lang = useLang();
const participantsIds = useMemo(() => { const participantsIds = useMemo(() => {
@ -82,8 +80,4 @@ export default memo(withGlobal<OwnProps>(
participantsCount: participantsCount || 0, participantsCount: participantsCount || 0,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'createGroupCallInviteLink',
'loadMoreGroupCallParticipants',
]),
)(GroupCallParticipantList)); )(GroupCallParticipantList));

View File

@ -2,17 +2,15 @@ import { GroupCallParticipant } from '../../../lib/secret-sauce';
import React, { import React, {
FC, memo, useCallback, useEffect, useState, FC, memo, useCallback, useEffect, useState,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { IAnchorPosition } from '../../../types'; import { IAnchorPosition } from '../../../types';
import { GlobalActions } from '../../../global/types';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
import useThrottle from '../../../hooks/useThrottle'; import useThrottle from '../../../hooks/useThrottle';
import useFlag from '../../../hooks/useFlag'; import useFlag from '../../../hooks/useFlag';
import useLang from '../../../hooks/useLang'; import useLang from '../../../hooks/useLang';
import { selectIsAdminInActiveGroupCall } from '../../../modules/selectors/calls'; import { selectIsAdminInActiveGroupCall } from '../../../modules/selectors/calls';
import { pick } from '../../../util/iteratees';
import { GROUP_CALL_DEFAULT_VOLUME, GROUP_CALL_VOLUME_MULTIPLIER } from '../../../config'; import { GROUP_CALL_DEFAULT_VOLUME, GROUP_CALL_VOLUME_MULTIPLIER } from '../../../config';
import Menu from '../../ui/Menu'; import Menu from '../../ui/Menu';
@ -36,10 +34,6 @@ type StateProps = {
isAdmin: boolean; isAdmin: boolean;
}; };
type DispatchProps = Pick<GlobalActions, (
'toggleGroupCallMute' | 'setGroupCallParticipantVolume' | 'toggleGroupCallPanel' | 'openChat' | 'requestToSpeak'
)>;
const VOLUME_ZERO = 0; const VOLUME_ZERO = 0;
const VOLUME_LOW = 50; const VOLUME_LOW = 50;
const VOLUME_MEDIUM = 100; const VOLUME_MEDIUM = 100;
@ -49,19 +43,21 @@ const VOLUME_CHANGE_THROTTLE = 500;
const SPEAKER_ICON_SIZE = 24; const SPEAKER_ICON_SIZE = 24;
const GroupCallParticipantMenu: FC<OwnProps & StateProps & DispatchProps> = ({ const GroupCallParticipantMenu: FC<OwnProps & StateProps> = ({
participant, participant,
closeDropdown, closeDropdown,
isDropdownOpen, isDropdownOpen,
anchor, anchor,
isAdmin, isAdmin,
toggleGroupCallMute,
setGroupCallParticipantVolume,
toggleGroupCallPanel,
openChat,
requestToSpeak,
}) => { }) => {
const {
toggleGroupCallMute,
setGroupCallParticipantVolume,
toggleGroupCallPanel,
openChat,
requestToSpeak,
} = getDispatch();
const lang = useLang(); const lang = useLang();
const [isDeleteUserModalOpen, openDeleteUserModal, closeDeleteUserModal] = useFlag(); const [isDeleteUserModalOpen, openDeleteUserModal, closeDeleteUserModal] = useFlag();
@ -229,11 +225,4 @@ export default memo(withGlobal<OwnProps>(
isAdmin: selectIsAdminInActiveGroupCall(global), isAdmin: selectIsAdminInActiveGroupCall(global),
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'setGroupCallParticipantVolume',
'toggleGroupCallMute',
'openChat',
'toggleGroupCallPanel',
'requestToSpeak',
]),
)(GroupCallParticipantMenu)); )(GroupCallParticipantMenu));

View File

@ -1,12 +1,10 @@
import React, { import React, {
FC, memo, useCallback, useEffect, useMemo, FC, memo, useCallback, useEffect, useMemo,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { ApiChat, ApiGroupCall, ApiUser } from '../../../api/types'; import { ApiChat, ApiGroupCall, ApiUser } from '../../../api/types';
import { pick } from '../../../util/iteratees';
import { selectChatGroupCall } from '../../../modules/selectors/calls'; import { selectChatGroupCall } from '../../../modules/selectors/calls';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
import { selectChat } from '../../../modules/selectors'; import { selectChat } from '../../../modules/selectors';
@ -29,18 +27,19 @@ type StateProps = {
chatsById: Record<string, ApiChat>; chatsById: Record<string, ApiChat>;
}; };
type DispatchProps = Pick<GlobalActions, 'joinGroupCall' | 'subscribeToGroupCallUpdates'>; const GroupCallTopPane: FC<OwnProps & StateProps> = ({
const GroupCallTopPane: FC<OwnProps & StateProps & DispatchProps> = ({
chatId, chatId,
isActive, isActive,
groupCall, groupCall,
hasPinnedOffset, hasPinnedOffset,
joinGroupCall,
subscribeToGroupCallUpdates,
usersById, usersById,
chatsById, chatsById,
}) => { }) => {
const {
joinGroupCall,
subscribeToGroupCallUpdates,
} = getDispatch();
const lang = useLang(); const lang = useLang();
const handleJoinGroupCall = useCallback(() => { const handleJoinGroupCall = useCallback(() => {
@ -132,8 +131,4 @@ export default memo(withGlobal<OwnProps>(
&& (global.groupCalls.activeGroupCallId !== groupCall?.id), && (global.groupCalls.activeGroupCallId !== groupCall?.id),
}; };
}, },
(setGlobal, actions) => pick(actions, [
'joinGroupCall',
'subscribeToGroupCallUpdates',
]),
)(GroupCallTopPane)); )(GroupCallTopPane));

View File

@ -2,13 +2,10 @@ import { GroupCallConnectionState } from '../../../lib/secret-sauce';
import React, { import React, {
FC, memo, useEffect, useMemo, useRef, useState, FC, memo, useEffect, useMemo, useRef, useState,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
import { vibrateShort } from '../../../util/vibrate'; import { vibrateShort } from '../../../util/vibrate';
import { pick } from '../../../util/iteratees';
import usePrevious from '../../../hooks/usePrevious'; import usePrevious from '../../../hooks/usePrevious';
import { selectActiveGroupCall, selectGroupCallParticipant } from '../../../modules/selectors/calls'; import { selectActiveGroupCall, selectGroupCallParticipant } from '../../../modules/selectors/calls';
import useLang from '../../../hooks/useLang'; import useLang from '../../../hooks/useLang';
@ -27,22 +24,23 @@ type StateProps = {
noAudioStream: boolean; noAudioStream: boolean;
}; };
type DispatchProps = Pick<GlobalActions, 'toggleGroupCallMute' | 'requestToSpeak' | 'playGroupCallSound'>;
const REQUEST_TO_SPEAK_THROTTLE = 3000; const REQUEST_TO_SPEAK_THROTTLE = 3000;
const HOLD_TO_SPEAK_TIME = 200; const HOLD_TO_SPEAK_TIME = 200;
const ICON_SIZE = 48; const ICON_SIZE = 48;
const MicrophoneButton: FC<StateProps & DispatchProps> = ({ const MicrophoneButton: FC<StateProps> = ({
noAudioStream, noAudioStream,
canSelfUnmute, canSelfUnmute,
isMuted, isMuted,
hasRequestedToSpeak, hasRequestedToSpeak,
connectionState, connectionState,
toggleGroupCallMute,
requestToSpeak,
playGroupCallSound,
}) => { }) => {
const {
toggleGroupCallMute,
requestToSpeak,
playGroupCallSound,
} = getDispatch();
const lang = useLang(); const lang = useLang();
const muteMouseDownState = useRef('up'); const muteMouseDownState = useRef('up');
@ -179,9 +177,4 @@ export default memo(withGlobal(
isMuted, isMuted,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'toggleGroupCallMute',
'requestToSpeak',
'playGroupCallSound',
]),
)(MicrophoneButton)); )(MicrophoneButton));

View File

@ -1,9 +1,9 @@
import React, { import React, {
FC, memo, useCallback, useEffect, FC, memo, useCallback, useEffect,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { GlobalActions, GlobalState } from '../../global/types'; import { GlobalState } from '../../global/types';
import { ApiChat, ApiCountryCode, ApiUser } from '../../api/types'; import { ApiChat, ApiCountryCode, ApiUser } from '../../api/types';
import { import {
@ -13,7 +13,6 @@ import {
getChatDescription, getChatLink, getHasAdminRight, isChatChannel, isUserId, isUserRightBanned, selectIsChatMuted, getChatDescription, getChatLink, getHasAdminRight, isChatChannel, isUserId, isUserRightBanned, selectIsChatMuted,
} from '../../modules/helpers'; } from '../../modules/helpers';
import renderText from './helpers/renderText'; import renderText from './helpers/renderText';
import { pick } from '../../util/iteratees';
import { copyTextToClipboard } from '../../util/clipboard'; import { copyTextToClipboard } from '../../util/clipboard';
import { formatPhoneNumberWithCode } from '../../util/phoneNumber'; import { formatPhoneNumberWithCode } from '../../util/phoneNumber';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
@ -26,17 +25,17 @@ type OwnProps = {
forceShowSelf?: boolean; forceShowSelf?: boolean;
}; };
type StateProps = { type StateProps =
user?: ApiUser; {
chat?: ApiChat; user?: ApiUser;
canInviteUsers?: boolean; chat?: ApiChat;
isMuted?: boolean; canInviteUsers?: boolean;
phoneCodeList: ApiCountryCode[]; isMuted?: boolean;
} & Pick<GlobalState, 'lastSyncTime'>; phoneCodeList: ApiCountryCode[];
}
& Pick<GlobalState, 'lastSyncTime'>;
type DispatchProps = Pick<GlobalActions, 'loadFullUser' | 'updateChatMutedState' | 'showNotification'>; const ChatExtra: FC<OwnProps & StateProps> = ({
const ChatExtra: FC<OwnProps & StateProps & DispatchProps> = ({
lastSyncTime, lastSyncTime,
user, user,
chat, chat,
@ -44,10 +43,13 @@ const ChatExtra: FC<OwnProps & StateProps & DispatchProps> = ({
canInviteUsers, canInviteUsers,
isMuted, isMuted,
phoneCodeList, phoneCodeList,
loadFullUser,
showNotification,
updateChatMutedState,
}) => { }) => {
const {
loadFullUser,
showNotification,
updateChatMutedState,
} = getDispatch();
const { const {
id: userId, id: userId,
fullInfo, fullInfo,
@ -152,7 +154,4 @@ export default memo(withGlobal<OwnProps>(
lastSyncTime, phoneCodeList, chat, user, canInviteUsers, isMuted, lastSyncTime, phoneCodeList, chat, user, canInviteUsers, isMuted,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'loadFullUser', 'updateChatMutedState', 'showNotification',
]),
)(ChatExtra)); )(ChatExtra));

View File

@ -1,9 +1,6 @@
import React, { FC, useCallback } from '../../lib/teact/teact'; import React, { FC, useCallback } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch } from '../../lib/teact/teactn';
import { GlobalActions } from '../../global/types';
import { pick } from '../../util/iteratees';
import buildClassName from '../../util/buildClassName'; import buildClassName from '../../util/buildClassName';
import Link from '../ui/Link'; import Link from '../ui/Link';
@ -14,11 +11,11 @@ type OwnProps = {
children: any; children: any;
}; };
type DispatchProps = Pick<GlobalActions, 'openChat'>; const ChatLink: FC<OwnProps> = ({
className, chatId, children,
const ChatLink: FC<OwnProps & DispatchProps> = ({
className, chatId, openChat, children,
}) => { }) => {
const { openChat } = getDispatch();
const handleClick = useCallback(() => { const handleClick = useCallback(() => {
if (chatId) { if (chatId) {
openChat({ id: chatId }); openChat({ id: chatId });
@ -34,7 +31,4 @@ const ChatLink: FC<OwnProps & DispatchProps> = ({
); );
}; };
export default withGlobal<OwnProps>( export default ChatLink;
undefined,
(setGlobal, actions): DispatchProps => pick(actions, ['openChat']),
)(ChatLink);

View File

@ -1,8 +1,7 @@
import React, { FC, useCallback, memo } from '../../lib/teact/teact'; import React, { FC, useCallback, memo } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { ApiChat } from '../../api/types'; import { ApiChat } from '../../api/types';
import { GlobalActions } from '../../global/types';
import { selectIsChatWithSelf, selectUser } from '../../modules/selectors'; import { selectIsChatWithSelf, selectUser } from '../../modules/selectors';
import { import {
@ -15,7 +14,6 @@ import {
isChatChannel, isChatChannel,
getChatTitle, getChatTitle,
} from '../../modules/helpers'; } from '../../modules/helpers';
import { pick } from '../../util/iteratees';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
import renderText from './helpers/renderText'; import renderText from './helpers/renderText';
@ -44,11 +42,7 @@ type StateProps = {
contactName?: string; contactName?: string;
}; };
type DispatchProps = Pick<GlobalActions, ( const DeleteChatModal: FC<OwnProps & StateProps> = ({
'leaveChannel' | 'deleteHistory' | 'deleteChannel' | 'deleteChatUser' | 'blockContact'
)>;
const DeleteChatModal: FC<OwnProps & StateProps & DispatchProps> = ({
isOpen, isOpen,
chat, chat,
isChannel, isChannel,
@ -62,12 +56,15 @@ const DeleteChatModal: FC<OwnProps & StateProps & DispatchProps> = ({
contactName, contactName,
onClose, onClose,
onCloseAnimationEnd, onCloseAnimationEnd,
leaveChannel,
deleteHistory,
deleteChannel,
deleteChatUser,
blockContact,
}) => { }) => {
const {
leaveChannel,
deleteHistory,
deleteChannel,
deleteChatUser,
blockContact,
} = getDispatch();
const lang = useLang(); const lang = useLang();
const chatTitle = getChatTitle(lang, chat); const chatTitle = getChatTitle(lang, chat);
@ -217,6 +214,4 @@ export default memo(withGlobal<OwnProps>(
contactName, contactName,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions,
['leaveChannel', 'deleteHistory', 'deleteChannel', 'deleteChatUser', 'blockContact']),
)(DeleteChatModal)); )(DeleteChatModal));

View File

@ -1,11 +1,9 @@
import React, { FC, useCallback, memo } from '../../lib/teact/teact'; import React, { FC, useCallback, memo } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { ApiMessage } from '../../api/types'; import { ApiMessage } from '../../api/types';
import { IAlbum } from '../../types'; import { IAlbum } from '../../types';
import { GlobalActions } from '../../global/types';
import { import {
selectAllowedMessageActions, selectAllowedMessageActions,
selectChat, selectChat,
@ -20,7 +18,6 @@ import {
isChatSuperGroup, isChatSuperGroup,
} from '../../modules/helpers'; } from '../../modules/helpers';
import renderText from './helpers/renderText'; import renderText from './helpers/renderText';
import { pick } from '../../util/iteratees';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
import Modal from '../ui/Modal'; import Modal from '../ui/Modal';
@ -41,9 +38,7 @@ type StateProps = {
willDeleteForAll?: boolean; willDeleteForAll?: boolean;
}; };
type DispatchProps = Pick<GlobalActions, 'deleteMessages' | 'deleteScheduledMessages'>; const DeleteMessageModal: FC<OwnProps & StateProps> = ({
const DeleteMessageModal: FC<OwnProps & StateProps & DispatchProps> = ({
isOpen, isOpen,
isSchedule, isSchedule,
message, message,
@ -53,9 +48,12 @@ const DeleteMessageModal: FC<OwnProps & StateProps & DispatchProps> = ({
willDeleteForCurrentUserOnly, willDeleteForCurrentUserOnly,
willDeleteForAll, willDeleteForAll,
onClose, onClose,
deleteMessages,
deleteScheduledMessages,
}) => { }) => {
const {
deleteMessages,
deleteScheduledMessages,
} = getDispatch();
const handleDeleteMessageForAll = useCallback(() => { const handleDeleteMessageForAll = useCallback(() => {
const messageIds = album?.messages const messageIds = album?.messages
? album.messages.map(({ id }) => id) ? album.messages.map(({ id }) => id)
@ -129,7 +127,4 @@ export default memo(withGlobal<OwnProps>(
willDeleteForAll, willDeleteForAll,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'deleteMessages', 'deleteScheduledMessages',
]),
)(DeleteMessageModal)); )(DeleteMessageModal));

View File

@ -1,13 +1,11 @@
import React, { FC, useCallback } from '../../lib/teact/teact'; import React, { FC, useCallback } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn';
import { GlobalActions } from '../../global/types';
import { ApiGroupCall } from '../../api/types'; import { ApiGroupCall } from '../../api/types';
import { pick } from '../../util/iteratees';
import buildClassName from '../../util/buildClassName'; import buildClassName from '../../util/buildClassName';
import Link from '../ui/Link'; import Link from '../ui/Link';
import { getDispatch } from '../../lib/teact/teactn';
type OwnProps = { type OwnProps = {
className?: string; className?: string;
@ -15,11 +13,11 @@ type OwnProps = {
children: any; children: any;
}; };
type DispatchProps = Pick<GlobalActions, 'joinGroupCall'>; const GroupCallLink: FC<OwnProps> = ({
className, groupCall, children,
const GroupCallLink: FC<OwnProps & DispatchProps> = ({
className, groupCall, joinGroupCall, children,
}) => { }) => {
const { joinGroupCall } = getDispatch();
const handleClick = useCallback(() => { const handleClick = useCallback(() => {
if (groupCall) { if (groupCall) {
joinGroupCall({ id: groupCall.id, accessHash: groupCall.accessHash }); joinGroupCall({ id: groupCall.id, accessHash: groupCall.accessHash });
@ -35,7 +33,4 @@ const GroupCallLink: FC<OwnProps & DispatchProps> = ({
); );
}; };
export default withGlobal<OwnProps>( export default GroupCallLink;
undefined,
(setGlobal, actions): DispatchProps => pick(actions, ['joinGroupCall']),
)(GroupCallLink);

View File

@ -2,10 +2,10 @@ import { MouseEvent as ReactMouseEvent } from 'react';
import React, { import React, {
FC, useEffect, useCallback, memo, FC, useEffect, useCallback, memo,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { ApiChat, ApiTypingStatus } from '../../api/types'; import { ApiChat, ApiTypingStatus } from '../../api/types';
import { GlobalActions, GlobalState } from '../../global/types'; import { GlobalState } from '../../global/types';
import { MediaViewerOrigin } from '../../types'; import { MediaViewerOrigin } from '../../types';
import { import {
@ -15,7 +15,6 @@ import {
} from '../../modules/helpers'; } from '../../modules/helpers';
import { selectChat, selectChatMessages, selectChatOnlineCount } from '../../modules/selectors'; import { selectChat, selectChatMessages, selectChatOnlineCount } from '../../modules/selectors';
import renderText from './helpers/renderText'; import renderText from './helpers/renderText';
import { pick } from '../../util/iteratees';
import useLang, { LangFn } from '../../hooks/useLang'; import useLang, { LangFn } from '../../hooks/useLang';
import Avatar from './Avatar'; import Avatar from './Avatar';
@ -34,15 +33,15 @@ type OwnProps = {
noRtl?: boolean; noRtl?: boolean;
}; };
type StateProps = { type StateProps =
chat?: ApiChat; {
onlineCount?: number; chat?: ApiChat;
areMessagesLoaded: boolean; onlineCount?: number;
} & Pick<GlobalState, 'lastSyncTime'>; areMessagesLoaded: boolean;
}
& Pick<GlobalState, 'lastSyncTime'>;
type DispatchProps = Pick<GlobalActions, 'loadFullChat' | 'openMediaViewer'>; const GroupChatInfo: FC<OwnProps & StateProps> = ({
const GroupChatInfo: FC<OwnProps & StateProps & DispatchProps> = ({
typingStatus, typingStatus,
avatarSize = 'medium', avatarSize = 'medium',
withMediaViewer, withMediaViewer,
@ -55,9 +54,12 @@ const GroupChatInfo: FC<OwnProps & StateProps & DispatchProps> = ({
onlineCount, onlineCount,
areMessagesLoaded, areMessagesLoaded,
lastSyncTime, lastSyncTime,
loadFullChat,
openMediaViewer,
}) => { }) => {
const {
loadFullChat,
openMediaViewer,
} = getDispatch();
const isSuperGroup = chat && isChatSuperGroup(chat); const isSuperGroup = chat && isChatSuperGroup(chat);
const { id: chatId, isMin, isRestricted } = chat || {}; const { id: chatId, isMin, isRestricted } = chat || {};
@ -164,5 +166,4 @@ export default memo(withGlobal<OwnProps>(
lastSyncTime, chat, onlineCount, areMessagesLoaded, lastSyncTime, chat, onlineCount, areMessagesLoaded,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, ['loadFullChat', 'openMediaViewer']),
)(GroupChatInfo)); )(GroupChatInfo));

View File

@ -1,10 +1,8 @@
import React, { FC, useCallback } from '../../lib/teact/teact'; import React, { FC, useCallback } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch } from '../../lib/teact/teactn';
import { GlobalActions } from '../../global/types';
import { ApiMessage } from '../../api/types'; import { ApiMessage } from '../../api/types';
import { pick } from '../../util/iteratees';
import buildClassName from '../../util/buildClassName'; import buildClassName from '../../util/buildClassName';
import Link from '../ui/Link'; import Link from '../ui/Link';
@ -15,11 +13,11 @@ type OwnProps = {
children: any; children: any;
}; };
type DispatchProps = Pick<GlobalActions, 'focusMessage'>; const MessageLink: FC<OwnProps> = ({
className, message, children,
const MessageLink: FC<OwnProps & DispatchProps> = ({
className, message, children, focusMessage,
}) => { }) => {
const { focusMessage } = getDispatch();
const handleMessageClick = useCallback((): void => { const handleMessageClick = useCallback((): void => {
if (message) { if (message) {
focusMessage({ chatId: message.chatId, messageId: message.id }); focusMessage({ chatId: message.chatId, messageId: message.id });
@ -35,7 +33,4 @@ const MessageLink: FC<OwnProps & DispatchProps> = ({
); );
}; };
export default withGlobal<OwnProps>( export default MessageLink;
undefined,
(setGlobal, actions): DispatchProps => pick(actions, ['focusMessage']),
)(MessageLink);

View File

@ -1,7 +1,5 @@
import React, { FC, useCallback, memo } from '../../lib/teact/teact'; import React, { FC, useCallback, memo } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { GlobalActions } from '../../global/types';
import { selectChat, selectIsChatWithSelf, selectUser } from '../../modules/selectors'; import { selectChat, selectIsChatWithSelf, selectUser } from '../../modules/selectors';
import { import {
@ -12,7 +10,6 @@ import {
isChatSuperGroup, isChatSuperGroup,
isChatChannel, isChatChannel,
} from '../../modules/helpers'; } from '../../modules/helpers';
import { pick } from '../../util/iteratees';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
import renderText from './helpers/renderText'; import renderText from './helpers/renderText';
@ -36,9 +33,7 @@ type StateProps = {
contactName?: string; contactName?: string;
}; };
type DispatchProps = Pick<GlobalActions, 'pinMessage'>; const PinMessageModal: FC<OwnProps & StateProps> = ({
const PinMessageModal: FC<OwnProps & StateProps & DispatchProps> = ({
isOpen, isOpen,
messageId, messageId,
chatId, chatId,
@ -48,8 +43,9 @@ const PinMessageModal: FC<OwnProps & StateProps & DispatchProps> = ({
canPinForAll, canPinForAll,
contactName, contactName,
onClose, onClose,
pinMessage,
}) => { }) => {
const { pinMessage } = getDispatch();
const handlePinMessageForAll = useCallback(() => { const handlePinMessageForAll = useCallback(() => {
pinMessage({ pinMessage({
chatId, messageId, isUnpin: false, chatId, messageId, isUnpin: false,
@ -124,5 +120,4 @@ export default memo(withGlobal<OwnProps>(
contactName, contactName,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, ['pinMessage']),
)(PinMessageModal)); )(PinMessageModal));

View File

@ -2,16 +2,15 @@ import { MouseEvent as ReactMouseEvent } from 'react';
import React, { import React, {
FC, useEffect, useCallback, memo, FC, useEffect, useCallback, memo,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { ApiUser, ApiTypingStatus, ApiUserStatus } from '../../api/types'; import { ApiUser, ApiTypingStatus, ApiUserStatus } from '../../api/types';
import { GlobalActions, GlobalState } from '../../global/types'; import { GlobalState } from '../../global/types';
import { MediaViewerOrigin } from '../../types'; import { MediaViewerOrigin } from '../../types';
import { selectChatMessages, selectUser, selectUserStatus } from '../../modules/selectors'; import { selectChatMessages, selectUser, selectUserStatus } from '../../modules/selectors';
import { getUserFullName, getUserStatus, isUserOnline } from '../../modules/helpers'; import { getUserFullName, getUserStatus, isUserOnline } from '../../modules/helpers';
import renderText from './helpers/renderText'; import renderText from './helpers/renderText';
import { pick } from '../../util/iteratees';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
import Avatar from './Avatar'; import Avatar from './Avatar';
@ -32,17 +31,17 @@ type OwnProps = {
noRtl?: boolean; noRtl?: boolean;
}; };
type StateProps = { type StateProps =
user?: ApiUser; {
userStatus?: ApiUserStatus; user?: ApiUser;
isSavedMessages?: boolean; userStatus?: ApiUserStatus;
areMessagesLoaded: boolean; isSavedMessages?: boolean;
serverTimeOffset: number; areMessagesLoaded: boolean;
} & Pick<GlobalState, 'lastSyncTime'>; serverTimeOffset: number;
}
& Pick<GlobalState, 'lastSyncTime'>;
type DispatchProps = Pick<GlobalActions, 'loadFullUser' | 'openMediaViewer'>; const PrivateChatInfo: FC<OwnProps & StateProps> = ({
const PrivateChatInfo: FC<OwnProps & StateProps & DispatchProps> = ({
typingStatus, typingStatus,
avatarSize = 'medium', avatarSize = 'medium',
status, status,
@ -58,9 +57,12 @@ const PrivateChatInfo: FC<OwnProps & StateProps & DispatchProps> = ({
areMessagesLoaded, areMessagesLoaded,
lastSyncTime, lastSyncTime,
serverTimeOffset, serverTimeOffset,
loadFullUser,
openMediaViewer,
}) => { }) => {
const {
loadFullUser,
openMediaViewer,
} = getDispatch();
const { id: userId } = user || {}; const { id: userId } = user || {};
const fullName = getUserFullName(user); const fullName = getUserFullName(user);
@ -153,5 +155,4 @@ export default memo(withGlobal<OwnProps>(
lastSyncTime, user, userStatus, isSavedMessages, areMessagesLoaded, serverTimeOffset, lastSyncTime, user, userStatus, isSavedMessages, areMessagesLoaded, serverTimeOffset,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, ['loadFullUser', 'openMediaViewer']),
)(PrivateChatInfo)); )(PrivateChatInfo));

View File

@ -1,10 +1,10 @@
import React, { import React, {
FC, useEffect, useCallback, memo, useState, FC, useEffect, useCallback, memo, useState,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { ApiUser, ApiChat, ApiUserStatus } from '../../api/types'; import { ApiUser, ApiChat, ApiUserStatus } from '../../api/types';
import { GlobalActions, GlobalState } from '../../global/types'; import { GlobalState } from '../../global/types';
import { MediaViewerOrigin } from '../../types'; import { MediaViewerOrigin } from '../../types';
import { IS_TOUCH_ENV } from '../../util/environment'; import { IS_TOUCH_ENV } from '../../util/environment';
@ -13,7 +13,6 @@ import {
getUserFullName, getUserStatus, isChatChannel, isUserOnline, getUserFullName, getUserStatus, isChatChannel, isUserOnline,
} from '../../modules/helpers'; } from '../../modules/helpers';
import renderText from './helpers/renderText'; import renderText from './helpers/renderText';
import { pick } from '../../util/iteratees';
import { captureEvents, SwipeDirection } from '../../util/captureEvents'; import { captureEvents, SwipeDirection } from '../../util/captureEvents';
import buildClassName from '../../util/buildClassName'; import buildClassName from '../../util/buildClassName';
import usePhotosPreload from './hooks/usePhotosPreload'; import usePhotosPreload from './hooks/usePhotosPreload';
@ -30,18 +29,18 @@ type OwnProps = {
forceShowSelf?: boolean; forceShowSelf?: boolean;
}; };
type StateProps = { type StateProps =
user?: ApiUser; {
userStatus?: ApiUserStatus; user?: ApiUser;
chat?: ApiChat; userStatus?: ApiUserStatus;
isSavedMessages?: boolean; chat?: ApiChat;
animationLevel: 0 | 1 | 2; isSavedMessages?: boolean;
serverTimeOffset: number; animationLevel: 0 | 1 | 2;
} & Pick<GlobalState, 'connectionState'>; serverTimeOffset: number;
}
& Pick<GlobalState, 'connectionState'>;
type DispatchProps = Pick<GlobalActions, 'loadFullUser' | 'openMediaViewer'>; const ProfileInfo: FC<OwnProps & StateProps> = ({
const ProfileInfo: FC<OwnProps & StateProps & DispatchProps> = ({
forceShowSelf, forceShowSelf,
user, user,
userStatus, userStatus,
@ -50,9 +49,12 @@ const ProfileInfo: FC<OwnProps & StateProps & DispatchProps> = ({
connectionState, connectionState,
animationLevel, animationLevel,
serverTimeOffset, serverTimeOffset,
loadFullUser,
openMediaViewer,
}) => { }) => {
const {
loadFullUser,
openMediaViewer,
} = getDispatch();
const lang = useLang(); const lang = useLang();
const { id: userId } = user || {}; const { id: userId } = user || {};
@ -246,5 +248,4 @@ export default memo(withGlobal<OwnProps>(
serverTimeOffset, serverTimeOffset,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, ['loadFullUser', 'openMediaViewer']),
)(ProfileInfo)); )(ProfileInfo));

View File

@ -3,13 +3,10 @@ import { ChangeEvent } from 'react';
import React, { import React, {
FC, memo, useCallback, useState, FC, memo, useCallback, useState,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch } from '../../lib/teact/teactn';
import { ApiReportReason } from '../../api/types'; import { ApiReportReason } from '../../api/types';
import { GlobalActions } from '../../global/types';
import { pick } from '../../util/iteratees';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
import Modal from '../ui/Modal'; import Modal from '../ui/Modal';
@ -23,15 +20,16 @@ export type OwnProps = {
onClose: () => void; onClose: () => void;
}; };
type DispatchProps = Pick<GlobalActions, 'reportMessages' | 'exitMessageSelectMode'>; const ReportMessageModal: FC<OwnProps> = ({
const ReportMessageModal: FC<OwnProps & DispatchProps> = ({
isOpen, isOpen,
messageIds, messageIds,
reportMessages,
exitMessageSelectMode,
onClose, onClose,
}) => { }) => {
const {
reportMessages,
exitMessageSelectMode,
} = getDispatch();
const [selectedReason, setSelectedReason] = useState<ApiReportReason>('spam'); const [selectedReason, setSelectedReason] = useState<ApiReportReason>('spam');
const [description, setDescription] = useState(''); const [description, setDescription] = useState('');
@ -91,8 +89,4 @@ const ReportMessageModal: FC<OwnProps & DispatchProps> = ({
); );
}; };
export default memo(withGlobal<OwnProps>( export default memo(ReportMessageModal);
undefined, (setGlobal, actions): DispatchProps => pick(actions, [
'reportMessages', 'exitMessageSelectMode',
]),
)(ReportMessageModal));

View File

@ -1,9 +1,6 @@
import React, { FC, useCallback, memo } from '../../lib/teact/teact'; import React, { FC, useCallback, memo } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { GlobalActions } from '../../global/types';
import { pick } from '../../util/iteratees';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
import { selectChatMessage } from '../../modules/selectors'; import { selectChatMessage } from '../../modules/selectors';
import useCurrentOrPrev from '../../hooks/useCurrentOrPrev'; import useCurrentOrPrev from '../../hooks/useCurrentOrPrev';
@ -21,16 +18,17 @@ export type StateProps = {
memberIds?: string[]; memberIds?: string[];
}; };
type DispatchProps = Pick<GlobalActions, 'openChat' | 'closeSeenByModal'>;
const CLOSE_ANIMATION_DURATION = 100; const CLOSE_ANIMATION_DURATION = 100;
const SeenByModal: FC<OwnProps & StateProps & DispatchProps> = ({ const SeenByModal: FC<OwnProps & StateProps> = ({
isOpen, isOpen,
memberIds, memberIds,
openChat,
closeSeenByModal,
}) => { }) => {
const {
openChat,
closeSeenByModal,
} = getDispatch();
const lang = useLang(); const lang = useLang();
const handleClick = useCallback((userId: string) => { const handleClick = useCallback((userId: string) => {
@ -83,5 +81,4 @@ export default memo(withGlobal<OwnProps>(
memberIds: selectChatMessage(global, chatId, messageId)?.seenByUserIds, memberIds: selectChatMessage(global, chatId, messageId)?.seenByUserIds,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, ['openChat', 'closeSeenByModal']),
)(SeenByModal)); )(SeenByModal));

View File

@ -1,13 +1,11 @@
import React, { import React, {
FC, memo, useCallback, useEffect, useRef, FC, memo, useCallback, useEffect, useRef,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { ApiSticker, ApiStickerSet } from '../../api/types'; import { ApiSticker, ApiStickerSet } from '../../api/types';
import { GlobalActions } from '../../global/types';
import { STICKER_SIZE_MODAL } from '../../config'; import { STICKER_SIZE_MODAL } from '../../config';
import { pick } from '../../util/iteratees';
import { import {
selectChat, selectCurrentMessageList, selectStickerSet, selectStickerSetByShortName, selectChat, selectCurrentMessageList, selectStickerSet, selectStickerSetByShortName,
} from '../../modules/selectors'; } from '../../modules/selectors';
@ -35,21 +33,22 @@ type StateProps = {
stickerSet?: ApiStickerSet; stickerSet?: ApiStickerSet;
}; };
type DispatchProps = Pick<GlobalActions, 'loadStickers' | 'toggleStickerSet' | 'sendMessage'>;
const INTERSECTION_THROTTLE = 200; const INTERSECTION_THROTTLE = 200;
const StickerSetModal: FC<OwnProps & StateProps & DispatchProps> = ({ const StickerSetModal: FC<OwnProps & StateProps> = ({
isOpen, isOpen,
fromSticker, fromSticker,
stickerSetShortName, stickerSetShortName,
stickerSet, stickerSet,
canSendStickers, canSendStickers,
onClose, onClose,
loadStickers,
toggleStickerSet,
sendMessage,
}) => { }) => {
const {
loadStickers,
toggleStickerSet,
sendMessage,
} = getDispatch();
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
const lang = useLang(); const lang = useLang();
@ -153,9 +152,4 @@ export default memo(withGlobal<OwnProps>(
: undefined, : undefined,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'loadStickers',
'toggleStickerSet',
'sendMessage',
]),
)(StickerSetModal)); )(StickerSetModal));

View File

@ -1,8 +1,8 @@
import React, { FC, useEffect } from '../../lib/teact/teact'; import React, { FC, useEffect } from '../../lib/teact/teact';
import { getGlobal, withGlobal } from '../../lib/teact/teactn'; import { getDispatch, getGlobal, withGlobal } from '../../lib/teact/teactn';
import { ApiMediaFormat } from '../../api/types'; import { ApiMediaFormat } from '../../api/types';
import { GlobalActions, GlobalState } from '../../global/types'; import { GlobalState } from '../../global/types';
import { getChatAvatarHash } from '../../modules/helpers/chats'; // Direct import for better module splitting import { getChatAvatarHash } from '../../modules/helpers/chats'; // Direct import for better module splitting
import useFlag from '../../hooks/useFlag'; import useFlag from '../../hooks/useFlag';
@ -12,7 +12,6 @@ import { preloadImage } from '../../util/files';
import preloadFonts from '../../util/fonts'; import preloadFonts from '../../util/fonts';
import * as mediaLoader from '../../util/mediaLoader'; import * as mediaLoader from '../../util/mediaLoader';
import { Bundles, loadModule } from '../../util/moduleLoader'; import { Bundles, loadModule } from '../../util/moduleLoader';
import { pick } from '../../util/iteratees';
import buildClassName from '../../util/buildClassName'; import buildClassName from '../../util/buildClassName';
import './UiLoader.scss'; import './UiLoader.scss';
@ -28,14 +27,14 @@ type OwnProps = {
children: any; children: any;
}; };
type StateProps = Pick<GlobalState, 'uiReadyState' | 'shouldSkipHistoryAnimations'> & { type StateProps =
hasCustomBackground?: boolean; Pick<GlobalState, 'uiReadyState' | 'shouldSkipHistoryAnimations'>
hasCustomBackgroundColor: boolean; & {
isRightColumnShown?: boolean; hasCustomBackground?: boolean;
leftColumnWidth?: number; hasCustomBackgroundColor: boolean;
}; isRightColumnShown?: boolean;
leftColumnWidth?: number;
type DispatchProps = Pick<GlobalActions, 'setIsUiReady'>; };
const MAX_PRELOAD_DELAY = 700; const MAX_PRELOAD_DELAY = 700;
const SECOND_STATE_DELAY = 1000; const SECOND_STATE_DELAY = 1000;
@ -77,7 +76,7 @@ const preloadTasks = {
authQrCode: preloadFonts, authQrCode: preloadFonts,
}; };
const UiLoader: FC<OwnProps & StateProps & DispatchProps> = ({ const UiLoader: FC<OwnProps & StateProps> = ({
page, page,
children, children,
hasCustomBackground, hasCustomBackground,
@ -85,8 +84,9 @@ const UiLoader: FC<OwnProps & StateProps & DispatchProps> = ({
isRightColumnShown, isRightColumnShown,
shouldSkipHistoryAnimations, shouldSkipHistoryAnimations,
leftColumnWidth, leftColumnWidth,
setIsUiReady,
}) => { }) => {
const { setIsUiReady } = getDispatch();
const [isReady, markReady] = useFlag(); const [isReady, markReady] = useFlag();
const { const {
shouldRender: shouldRenderMask, transitionClassNames, shouldRender: shouldRenderMask, transitionClassNames,
@ -171,5 +171,4 @@ export default withGlobal<OwnProps>(
leftColumnWidth: global.leftColumnWidth, leftColumnWidth: global.leftColumnWidth,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, ['setIsUiReady']),
)(UiLoader); )(UiLoader);

View File

@ -1,13 +1,11 @@
import React, { FC, useCallback } from '../../lib/teact/teact'; import React, { FC, useCallback } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn';
import { GlobalActions } from '../../global/types';
import { ApiChat, ApiUser } from '../../api/types'; import { ApiChat, ApiUser } from '../../api/types';
import { pick } from '../../util/iteratees';
import buildClassName from '../../util/buildClassName'; import buildClassName from '../../util/buildClassName';
import Link from '../ui/Link'; import Link from '../ui/Link';
import { getDispatch } from '../../lib/teact/teactn';
type OwnProps = { type OwnProps = {
className?: string; className?: string;
@ -15,11 +13,11 @@ type OwnProps = {
children: any; children: any;
}; };
type DispatchProps = Pick<GlobalActions, 'openUserInfo'>; const UserLink: FC<OwnProps> = ({
className, sender, children,
const UserLink: FC<OwnProps & DispatchProps> = ({
className, sender, openUserInfo, children,
}) => { }) => {
const { openUserInfo } = getDispatch();
const handleClick = useCallback(() => { const handleClick = useCallback(() => {
if (sender) { if (sender) {
openUserInfo({ id: sender.id }); openUserInfo({ id: sender.id });
@ -35,7 +33,4 @@ const UserLink: FC<OwnProps & DispatchProps> = ({
); );
}; };
export default withGlobal<OwnProps>( export default UserLink;
undefined,
(setGlobal, actions): DispatchProps => pick(actions, ['openUserInfo']),
)(UserLink);

View File

@ -1,12 +1,10 @@
import React, { import React, {
FC, useCallback, memo, useMemo, useState, FC, useCallback, memo, useMemo, useState,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { GlobalActions } from '../../global/types';
import { ApiChatFolder } from '../../api/types'; import { ApiChatFolder } from '../../api/types';
import { pick } from '../../util/iteratees';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
import Modal from '../ui/Modal'; import Modal from '../ui/Modal';
@ -25,17 +23,16 @@ type StateProps = {
folderOrderedIds?: number[]; folderOrderedIds?: number[];
}; };
type DispatchProps = Pick<GlobalActions, 'editChatFolders'>; const ChatFolderModal: FC<OwnProps & StateProps> = ({
const ChatFolderModal: FC<OwnProps & StateProps & DispatchProps> = ({
isOpen, isOpen,
chatId, chatId,
foldersById, foldersById,
folderOrderedIds, folderOrderedIds,
onClose, onClose,
onCloseAnimationEnd, onCloseAnimationEnd,
editChatFolders,
}) => { }) => {
const { editChatFolders } = getDispatch();
const lang = useLang(); const lang = useLang();
const initialSelectedFolderIds = useMemo(() => { const initialSelectedFolderIds = useMemo(() => {
@ -106,5 +103,4 @@ export default memo(withGlobal<OwnProps>(
folderOrderedIds, folderOrderedIds,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, ['editChatFolders']),
)(ChatFolderModal)); )(ChatFolderModal));

View File

@ -1,14 +1,12 @@
import React, { import React, {
FC, memo, useCallback, useEffect, useRef, useState, FC, memo, useCallback, useEffect, useRef, useState,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { GlobalActions } from '../../global/types';
import { LeftColumnContent, SettingsScreens } from '../../types'; import { LeftColumnContent, SettingsScreens } from '../../types';
import { LAYERS_ANIMATION_NAME } from '../../util/environment'; import { LAYERS_ANIMATION_NAME } from '../../util/environment';
import captureEscKeyListener from '../../util/captureEscKeyListener'; import captureEscKeyListener from '../../util/captureEscKeyListener';
import { pick } from '../../util/iteratees';
import useFoldersReducer from '../../hooks/reducers/useFoldersReducer'; import useFoldersReducer from '../../hooks/reducers/useFoldersReducer';
import { useResize } from '../../hooks/useResize'; import { useResize } from '../../hooks/useResize';
@ -28,11 +26,6 @@ type StateProps = {
leftColumnWidth?: number; leftColumnWidth?: number;
}; };
type DispatchProps = Pick<GlobalActions, (
'setGlobalSearchQuery' | 'setGlobalSearchChatId' | 'resetChatCreation' | 'setGlobalSearchDate' |
'loadPasswordInfo' | 'clearTwoFaError' | 'setLeftColumnWidth' | 'resetLeftColumnWidth'
)>;
enum ContentType { enum ContentType {
Main, Main,
// eslint-disable-next-line @typescript-eslint/no-shadow // eslint-disable-next-line @typescript-eslint/no-shadow
@ -47,21 +40,24 @@ enum ContentType {
const RENDER_COUNT = Object.keys(ContentType).length / 2; const RENDER_COUNT = Object.keys(ContentType).length / 2;
const RESET_TRANSITION_DELAY_MS = 250; const RESET_TRANSITION_DELAY_MS = 250;
const LeftColumn: FC<StateProps & DispatchProps> = ({ const LeftColumn: FC<StateProps> = ({
searchQuery, searchQuery,
searchDate, searchDate,
activeChatFolder, activeChatFolder,
shouldSkipHistoryAnimations, shouldSkipHistoryAnimations,
leftColumnWidth, leftColumnWidth,
setGlobalSearchQuery,
setGlobalSearchChatId,
resetChatCreation,
setGlobalSearchDate,
loadPasswordInfo,
clearTwoFaError,
setLeftColumnWidth,
resetLeftColumnWidth,
}) => { }) => {
const {
setGlobalSearchQuery,
setGlobalSearchChatId,
resetChatCreation,
setGlobalSearchDate,
loadPasswordInfo,
clearTwoFaError,
setLeftColumnWidth,
resetLeftColumnWidth,
} = getDispatch();
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
const resizeRef = useRef<HTMLDivElement>(null); const resizeRef = useRef<HTMLDivElement>(null);
const [content, setContent] = useState<LeftColumnContent>(LeftColumnContent.ChatList); const [content, setContent] = useState<LeftColumnContent>(LeftColumnContent.ChatList);
@ -374,8 +370,4 @@ export default memo(withGlobal(
searchQuery: query, searchDate: date, activeChatFolder, shouldSkipHistoryAnimations, leftColumnWidth, searchQuery: query, searchDate: date, activeChatFolder, shouldSkipHistoryAnimations, leftColumnWidth,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'setGlobalSearchQuery', 'setGlobalSearchChatId', 'resetChatCreation', 'setGlobalSearchDate',
'loadPasswordInfo', 'clearTwoFaError', 'setLeftColumnWidth', 'resetLeftColumnWidth',
]),
)(LeftColumn)); )(LeftColumn));

View File

@ -1,11 +1,10 @@
import React, { import React, {
FC, memo, useCallback, useLayoutEffect, useMemo, useRef, FC, memo, useCallback, useLayoutEffect, useMemo, useRef,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import useLang, { LangFn } from '../../../hooks/useLang'; import useLang, { LangFn } from '../../../hooks/useLang';
import { GlobalActions } from '../../../global/types';
import { import {
ApiChat, ApiUser, ApiMessage, ApiMessageOutgoingStatus, ApiFormattedText, MAIN_THREAD_ID, ApiUserStatus, ApiChat, ApiUser, ApiMessage, ApiMessageOutgoingStatus, ApiFormattedText, MAIN_THREAD_ID, ApiUserStatus,
} from '../../../api/types'; } from '../../../api/types';
@ -36,7 +35,6 @@ import { renderActionMessageText } from '../../common/helpers/renderActionMessag
import renderText from '../../common/helpers/renderText'; import renderText from '../../common/helpers/renderText';
import { fastRaf } from '../../../util/schedulers'; import { fastRaf } from '../../../util/schedulers';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
import { pick } from '../../../util/iteratees';
import useEnsureMessage from '../../../hooks/useEnsureMessage'; import useEnsureMessage from '../../../hooks/useEnsureMessage';
import useChatContextActions from '../../../hooks/useChatContextActions'; import useChatContextActions from '../../../hooks/useChatContextActions';
import useFlag from '../../../hooks/useFlag'; import useFlag from '../../../hooks/useFlag';
@ -83,11 +81,9 @@ type StateProps = {
lastSyncTime?: number; lastSyncTime?: number;
}; };
type DispatchProps = Pick<GlobalActions, 'openChat' | 'focusLastMessage'>;
const ANIMATION_DURATION = 200; const ANIMATION_DURATION = 200;
const Chat: FC<OwnProps & StateProps & DispatchProps> = ({ const Chat: FC<OwnProps & StateProps> = ({
style, style,
chatId, chatId,
folderId, folderId,
@ -110,9 +106,12 @@ const Chat: FC<OwnProps & StateProps & DispatchProps> = ({
canScrollDown, canScrollDown,
canChangeFolder, canChangeFolder,
lastSyncTime, lastSyncTime,
openChat,
focusLastMessage,
}) => { }) => {
const {
openChat,
focusLastMessage,
} = getDispatch();
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
const ref = useRef<HTMLDivElement>(null); const ref = useRef<HTMLDivElement>(null);
@ -390,8 +389,4 @@ export default memo(withGlobal<OwnProps>(
...(actionTargetUserIds && { usersById }), ...(actionTargetUserIds && { usersById }),
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'openChat',
'focusLastMessage',
]),
)(Chat)); )(Chat));

View File

@ -1,15 +1,15 @@
import React, { import React, {
FC, memo, useCallback, useEffect, useMemo, useRef, FC, memo, useCallback, useEffect, useMemo, useRef,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { ApiChat, ApiChatFolder, ApiUser } from '../../../api/types'; import { ApiChat, ApiChatFolder, ApiUser } from '../../../api/types';
import { GlobalActions, GlobalState } from '../../../global/types'; import { GlobalState } from '../../../global/types';
import { NotifyException, NotifySettings, SettingsScreens } from '../../../types'; import { NotifyException, NotifySettings, SettingsScreens } from '../../../types';
import { FolderEditDispatch } from '../../../hooks/reducers/useFoldersReducer'; import { FolderEditDispatch } from '../../../hooks/reducers/useFoldersReducer';
import { IS_TOUCH_ENV } from '../../../util/environment'; import { IS_TOUCH_ENV } from '../../../util/environment';
import { buildCollectionByKey, pick } from '../../../util/iteratees'; import { buildCollectionByKey } from '../../../util/iteratees';
import { captureEvents, SwipeDirection } from '../../../util/captureEvents'; import { captureEvents, SwipeDirection } from '../../../util/captureEvents';
import { getFolderUnreadDialogs } from '../../../modules/helpers'; import { getFolderUnreadDialogs } from '../../../modules/helpers';
import { selectNotifyExceptions, selectNotifySettings } from '../../../modules/selectors'; import { selectNotifyExceptions, selectNotifySettings } from '../../../modules/selectors';
@ -43,12 +43,10 @@ type StateProps = {
shouldSkipHistoryAnimations?: boolean; shouldSkipHistoryAnimations?: boolean;
}; };
type DispatchProps = Pick<GlobalActions, 'loadChatFolders' | 'setActiveChatFolder' | 'openChat'>;
const INFO_THROTTLE = 3000; const INFO_THROTTLE = 3000;
const SAVED_MESSAGES_HOTKEY = '0'; const SAVED_MESSAGES_HOTKEY = '0';
const ChatFolders: FC<OwnProps & StateProps & DispatchProps> = ({ const ChatFolders: FC<OwnProps & StateProps> = ({
allListIds, allListIds,
chatsById, chatsById,
usersById, usersById,
@ -62,10 +60,13 @@ const ChatFolders: FC<OwnProps & StateProps & DispatchProps> = ({
shouldSkipHistoryAnimations, shouldSkipHistoryAnimations,
foldersDispatch, foldersDispatch,
onScreenSelect, onScreenSelect,
loadChatFolders,
setActiveChatFolder,
openChat,
}) => { }) => {
const {
loadChatFolders,
setActiveChatFolder,
openChat,
} = getDispatch();
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
const transitionRef = useRef<HTMLDivElement>(null); const transitionRef = useRef<HTMLDivElement>(null);
@ -267,9 +268,4 @@ export default memo(withGlobal<OwnProps>(
shouldSkipHistoryAnimations, shouldSkipHistoryAnimations,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'loadChatFolders',
'setActiveChatFolder',
'openChat',
]),
)(ChatFolders)); )(ChatFolders));

View File

@ -1,9 +1,9 @@
import React, { import React, {
FC, memo, useMemo, useCallback, useEffect, FC, memo, useMemo, useCallback, useEffect,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions, GlobalState } from '../../../global/types'; import { GlobalState } from '../../../global/types';
import { import {
ApiChat, ApiChatFolder, ApiUser, ApiChat, ApiChatFolder, ApiUser,
} from '../../../api/types'; } from '../../../api/types';
@ -13,7 +13,7 @@ import { FolderEditDispatch } from '../../../hooks/reducers/useFoldersReducer';
import { ALL_CHATS_PRELOAD_DISABLED, CHAT_HEIGHT_PX, CHAT_LIST_SLICE } from '../../../config'; import { ALL_CHATS_PRELOAD_DISABLED, CHAT_HEIGHT_PX, CHAT_LIST_SLICE } from '../../../config';
import { IS_ANDROID, IS_MAC_OS, IS_PWA } from '../../../util/environment'; import { IS_ANDROID, IS_MAC_OS, IS_PWA } from '../../../util/environment';
import usePrevious from '../../../hooks/usePrevious'; import usePrevious from '../../../hooks/usePrevious';
import { mapValues, pick } from '../../../util/iteratees'; import { mapValues } from '../../../util/iteratees';
import { import {
getChatOrder, prepareChatList, prepareFolderListIds, reduceChatList, getChatOrder, prepareChatList, prepareFolderListIds, reduceChatList,
} from '../../../modules/helpers'; } from '../../../modules/helpers';
@ -48,16 +48,12 @@ type StateProps = {
notifyExceptions?: Record<number, NotifyException>; notifyExceptions?: Record<number, NotifyException>;
}; };
type DispatchProps = Pick<GlobalActions, (
'loadMoreChats' | 'preloadTopChatMessages' | 'preloadArchivedChats' | 'openChat' | 'openNextChat'
)>;
enum FolderTypeToListType { enum FolderTypeToListType {
'all' = 'active', 'all' = 'active',
'archived' = 'archived', 'archived' = 'archived',
} }
const ChatList: FC<OwnProps & StateProps & DispatchProps> = ({ const ChatList: FC<OwnProps & StateProps> = ({
folderType, folderType,
folderId, folderId,
isActive, isActive,
@ -72,12 +68,15 @@ const ChatList: FC<OwnProps & StateProps & DispatchProps> = ({
notifyExceptions, notifyExceptions,
foldersDispatch, foldersDispatch,
onScreenSelect, onScreenSelect,
loadMoreChats,
preloadTopChatMessages,
preloadArchivedChats,
openChat,
openNextChat,
}) => { }) => {
const {
loadMoreChats,
preloadTopChatMessages,
preloadArchivedChats,
openChat,
openNextChat,
} = getDispatch();
const [currentListIds, currentPinnedIds] = useMemo(() => { const [currentListIds, currentPinnedIds] = useMemo(() => {
return folderType === 'folder' && chatFolder return folderType === 'folder' && chatFolder
? prepareFolderListIds(allListIds, chatsById, usersById, chatFolder, notifySettings, notifyExceptions) ? prepareFolderListIds(allListIds, chatsById, usersById, chatFolder, notifySettings, notifyExceptions)
@ -273,11 +272,4 @@ export default memo(withGlobal<OwnProps>(
}), }),
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'loadMoreChats',
'preloadTopChatMessages',
'preloadArchivedChats',
'openChat',
'openNextChat',
]),
)(ChatList)); )(ChatList));

View File

@ -1,14 +1,12 @@
import React, { import React, {
FC, useEffect, useCallback, useMemo, memo, FC, useEffect, useCallback, useMemo, memo,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { ApiUser, ApiUserStatus } from '../../../api/types'; import { ApiUser, ApiUserStatus } from '../../../api/types';
import { IS_SINGLE_COLUMN_LAYOUT } from '../../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../../util/environment';
import { throttle } from '../../../util/schedulers'; import { throttle } from '../../../util/schedulers';
import { pick } from '../../../util/iteratees';
import { filterUsersByName, sortUserIds } from '../../../modules/helpers'; import { filterUsersByName, sortUserIds } from '../../../modules/helpers';
import useInfiniteScroll from '../../../hooks/useInfiniteScroll'; import useInfiniteScroll from '../../../hooks/useInfiniteScroll';
import useHistoryBack from '../../../hooks/useHistoryBack'; import useHistoryBack from '../../../hooks/useHistoryBack';
@ -31,11 +29,9 @@ type StateProps = {
serverTimeOffset: number; serverTimeOffset: number;
}; };
type DispatchProps = Pick<GlobalActions, 'loadContactList' | 'openChat'>;
const runThrottled = throttle((cb) => cb(), 60000, true); const runThrottled = throttle((cb) => cb(), 60000, true);
const ContactList: FC<OwnProps & StateProps & DispatchProps> = ({ const ContactList: FC<OwnProps & StateProps> = ({
isActive, isActive,
filter, filter,
usersById, usersById,
@ -43,9 +39,12 @@ const ContactList: FC<OwnProps & StateProps & DispatchProps> = ({
contactIds, contactIds,
serverTimeOffset, serverTimeOffset,
onReset, onReset,
loadContactList,
openChat,
}) => { }) => {
const {
loadContactList,
openChat,
} = getDispatch();
// Due to the parent Transition, this component never gets unmounted, // Due to the parent Transition, this component never gets unmounted,
// that's why we use throttled API call on every update. // that's why we use throttled API call on every update.
useEffect(() => { useEffect(() => {
@ -108,5 +107,4 @@ export default memo(withGlobal<OwnProps>(
serverTimeOffset: global.serverTimeOffset, serverTimeOffset: global.serverTimeOffset,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, ['loadContactList', 'openChat']),
)(ContactList)); )(ContactList));

View File

@ -1,9 +1,8 @@
import React, { import React, {
FC, useCallback, useMemo, memo, FC, useCallback, useMemo, memo,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { LeftColumnContent, ISettings } from '../../../types'; import { LeftColumnContent, ISettings } from '../../../types';
import { ApiChat } from '../../../api/types'; import { ApiChat } from '../../../api/types';
@ -12,7 +11,6 @@ import {
} from '../../../config'; } from '../../../config';
import { IS_SINGLE_COLUMN_LAYOUT } from '../../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../../util/environment';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
import { pick } from '../../../util/iteratees';
import { isChatArchived } from '../../../modules/helpers'; import { isChatArchived } from '../../../modules/helpers';
import { formatDateToString } from '../../../util/dateFormat'; import { formatDateToString } from '../../../util/dateFormat';
import { selectTheme } from '../../../modules/selectors'; import { selectTheme } from '../../../modules/selectors';
@ -51,10 +49,6 @@ type StateProps = {
chatsById?: Record<string, ApiChat>; chatsById?: Record<string, ApiChat>;
}; };
type DispatchProps = Pick<GlobalActions, (
'openChat' | 'openTipsChat' | 'setGlobalSearchDate' | 'setGlobalSearchChatId' | 'setSettingOption'
)>;
const ANIMATION_LEVEL_OPTIONS = [0, 1, 2]; const ANIMATION_LEVEL_OPTIONS = [0, 1, 2];
const PRODUCTION_HOSTNAME = 'web.telegram.org'; const PRODUCTION_HOSTNAME = 'web.telegram.org';
@ -62,14 +56,13 @@ const LEGACY_VERSION_URL = 'https://web.telegram.org/?legacy=1';
const WEBK_VERSION_URL = 'https://web.telegram.org/k/'; const WEBK_VERSION_URL = 'https://web.telegram.org/k/';
const PERMANENT_VERSION_KEY = 'kz_version'; const PERMANENT_VERSION_KEY = 'kz_version';
const LeftMainHeader: FC<OwnProps & StateProps & DispatchProps> = ({ const LeftMainHeader: FC<OwnProps & StateProps> = ({
content, content,
contactsFilter, contactsFilter,
onSearchQuery, onSearchQuery,
onSelectSettings, onSelectSettings,
onSelectContacts, onSelectContacts,
onSelectArchived, onSelectArchived,
setGlobalSearchChatId,
onReset, onReset,
searchQuery, searchQuery,
isLoading, isLoading,
@ -80,11 +73,14 @@ const LeftMainHeader: FC<OwnProps & StateProps & DispatchProps> = ({
theme, theme,
animationLevel, animationLevel,
chatsById, chatsById,
openChat,
openTipsChat,
setGlobalSearchDate,
setSettingOption,
}) => { }) => {
const {
openChat,
openTipsChat,
setGlobalSearchDate,
setSettingOption, setGlobalSearchChatId,
} = getDispatch();
const lang = useLang(); const lang = useLang();
const hasMenu = content === LeftColumnContent.ChatList; const hasMenu = content === LeftColumnContent.ChatList;
const clearedDateSearchParam = { date: undefined }; const clearedDateSearchParam = { date: undefined };
@ -327,11 +323,4 @@ export default memo(withGlobal<OwnProps>(
animationLevel, animationLevel,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'openChat',
'openTipsChat',
'setGlobalSearchDate',
'setGlobalSearchChatId',
'setSettingOption',
]),
)(LeftMainHeader)); )(LeftMainHeader));

View File

@ -1,12 +1,11 @@
import React, { import React, {
FC, useCallback, useEffect, useMemo, memo, FC, useCallback, useEffect, useMemo, memo,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { getGlobal, withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, getGlobal, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { ApiChat } from '../../../api/types'; import { ApiChat } from '../../../api/types';
import { pick, unique } from '../../../util/iteratees'; import { unique } from '../../../util/iteratees';
import { throttle } from '../../../util/schedulers'; import { throttle } from '../../../util/schedulers';
import { filterUsersByName, isUserBot, sortChatIds } from '../../../modules/helpers'; import { filterUsersByName, isUserBot, sortChatIds } from '../../../modules/helpers';
import useLang from '../../../hooks/useLang'; import useLang from '../../../hooks/useLang';
@ -34,11 +33,9 @@ type StateProps = {
globalUserIds?: string[]; globalUserIds?: string[];
}; };
type DispatchProps = Pick<GlobalActions, 'loadContactList' | 'setGlobalSearchQuery'>;
const runThrottled = throttle((cb) => cb(), 60000, true); const runThrottled = throttle((cb) => cb(), 60000, true);
const NewChatStep1: FC<OwnProps & StateProps & DispatchProps> = ({ const NewChatStep1: FC<OwnProps & StateProps> = ({
isChannel, isChannel,
isActive, isActive,
selectedMemberIds, selectedMemberIds,
@ -51,9 +48,12 @@ const NewChatStep1: FC<OwnProps & StateProps & DispatchProps> = ({
isSearching, isSearching,
localUserIds, localUserIds,
globalUserIds, globalUserIds,
loadContactList,
setGlobalSearchQuery,
}) => { }) => {
const {
loadContactList,
setGlobalSearchQuery,
} = getDispatch();
// Due to the parent Transition, this component never gets unmounted, // Due to the parent Transition, this component never gets unmounted,
// that's why we use throttled API call on every update. // that's why we use throttled API call on every update.
useEffect(() => { useEffect(() => {
@ -162,5 +162,4 @@ export default memo(withGlobal<OwnProps>(
localUserIds, localUserIds,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, ['loadContactList', 'setGlobalSearchQuery']),
)(NewChatStep1)); )(NewChatStep1));

View File

@ -1,12 +1,10 @@
import React, { import React, {
FC, useState, useCallback, useEffect, memo, FC, useState, useCallback, useEffect, memo,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { ChatCreationProgress } from '../../../types'; import { ChatCreationProgress } from '../../../types';
import { pick } from '../../../util/iteratees';
import useLang from '../../../hooks/useLang'; import useLang from '../../../hooks/useLang';
import useHistoryBack from '../../../hooks/useHistoryBack'; import useHistoryBack from '../../../hooks/useHistoryBack';
@ -30,21 +28,22 @@ type StateProps = {
creationError?: string; creationError?: string;
}; };
type DispatchProps = Pick<GlobalActions, 'createGroupChat' | 'createChannel'>;
// TODO @implement // TODO @implement
const MAX_USERS_FOR_LEGACY_CHAT = 199; // Accounting for current user const MAX_USERS_FOR_LEGACY_CHAT = 199; // Accounting for current user
const NewChatStep2: FC<OwnProps & StateProps & DispatchProps> = ({ const NewChatStep2: FC<OwnProps & StateProps > = ({
isChannel, isChannel,
isActive, isActive,
memberIds, memberIds,
onReset, onReset,
creationProgress, creationProgress,
creationError, creationError,
createGroupChat,
createChannel,
}) => { }) => {
const {
createGroupChat,
createChannel,
} = getDispatch();
const lang = useLang(); const lang = useLang();
useHistoryBack(isActive, onReset); useHistoryBack(isActive, onReset);
@ -202,7 +201,4 @@ export default memo(withGlobal<OwnProps>(
creationError, creationError,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'createGroupChat', 'createChannel',
]),
)(NewChatStep2)); )(NewChatStep2));

View File

@ -1,15 +1,13 @@
import React, { import React, {
FC, memo, useCallback, useMemo, FC, memo, useCallback, useMemo,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { AudioOrigin, LoadMoreDirection } from '../../../types'; import { AudioOrigin, LoadMoreDirection } from '../../../types';
import { SLIDE_TRANSITION_DURATION } from '../../../config'; import { SLIDE_TRANSITION_DURATION } from '../../../config';
import { MEMO_EMPTY_ARRAY } from '../../../util/memo'; import { MEMO_EMPTY_ARRAY } from '../../../util/memo';
import { createMapStateToProps, StateProps } from './helpers/createMapStateToProps'; import { createMapStateToProps, StateProps } from './helpers/createMapStateToProps';
import { pick } from '../../../util/iteratees';
import { formatMonthAndYear, toYearMonth } from '../../../util/dateFormat'; import { formatMonthAndYear, toYearMonth } from '../../../util/dateFormat';
import { getSenderName } from './helpers/getSenderName'; import { getSenderName } from './helpers/getSenderName';
import { throttle } from '../../../util/schedulers'; import { throttle } from '../../../util/schedulers';
@ -26,11 +24,9 @@ export type OwnProps = {
searchQuery?: string; searchQuery?: string;
}; };
type DispatchProps = Pick<GlobalActions, ('searchMessagesGlobal' | 'focusMessage' | 'openAudioPlayer')>;
const runThrottled = throttle((cb) => cb(), 500, true); const runThrottled = throttle((cb) => cb(), 500, true);
const AudioResults: FC<OwnProps & StateProps & DispatchProps> = ({ const AudioResults: FC<OwnProps & StateProps> = ({
theme, theme,
isVoice, isVoice,
searchQuery, searchQuery,
@ -42,10 +38,13 @@ const AudioResults: FC<OwnProps & StateProps & DispatchProps> = ({
foundIds, foundIds,
lastSyncTime, lastSyncTime,
activeDownloads, activeDownloads,
searchMessagesGlobal,
focusMessage,
openAudioPlayer,
}) => { }) => {
const {
searchMessagesGlobal,
focusMessage,
openAudioPlayer,
} = getDispatch();
const lang = useLang(); const lang = useLang();
const currentType = isVoice ? 'voice' : 'audio'; const currentType = isVoice ? 'voice' : 'audio';
const handleLoadMore = useCallback(({ direction }: { direction: LoadMoreDirection }) => { const handleLoadMore = useCallback(({ direction }: { direction: LoadMoreDirection }) => {
@ -137,9 +136,4 @@ const AudioResults: FC<OwnProps & StateProps & DispatchProps> = ({
export default memo(withGlobal<OwnProps>( export default memo(withGlobal<OwnProps>(
createMapStateToProps('audio'), createMapStateToProps('audio'),
(setGlobal, actions): DispatchProps => pick(actions, [
'searchMessagesGlobal',
'focusMessage',
'openAudioPlayer',
]),
)(AudioResults)); )(AudioResults));

View File

@ -1,9 +1,8 @@
import React, { import React, {
FC, memo, useCallback, FC, memo, useCallback,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { import {
ApiChat, ApiUser, ApiMessage, ApiMessageOutgoingStatus, ApiChat, ApiUser, ApiMessage, ApiMessageOutgoingStatus,
} from '../../../api/types'; } from '../../../api/types';
@ -20,7 +19,6 @@ import {
} from '../../../modules/helpers'; } from '../../../modules/helpers';
import { selectChat, selectUser } from '../../../modules/selectors'; import { selectChat, selectUser } from '../../../modules/selectors';
import renderText from '../../common/helpers/renderText'; import renderText from '../../common/helpers/renderText';
import { pick } from '../../../util/iteratees';
import useMedia from '../../../hooks/useMedia'; import useMedia from '../../../hooks/useMedia';
import { formatPastTimeShort } from '../../../util/dateFormat'; import { formatPastTimeShort } from '../../../util/dateFormat';
import useLang, { LangFn } from '../../../hooks/useLang'; import useLang, { LangFn } from '../../../hooks/useLang';
@ -46,17 +44,16 @@ type StateProps = {
lastSyncTime?: number; lastSyncTime?: number;
}; };
type DispatchProps = Pick<GlobalActions, 'focusMessage'>; const ChatMessage: FC<OwnProps & StateProps> = ({
const ChatMessage: FC<OwnProps & StateProps & DispatchProps> = ({
message, message,
searchQuery, searchQuery,
chatId, chatId,
chat, chat,
privateChatUser, privateChatUser,
focusMessage,
lastSyncTime, lastSyncTime,
}) => { }) => {
const { focusMessage } = getDispatch();
const mediaThumbnail = getMessageMediaThumbDataUri(message); const mediaThumbnail = getMessageMediaThumbDataUri(message);
const mediaBlobUrl = useMedia(getMessageMediaHash(message, 'micro')); const mediaBlobUrl = useMedia(getMessageMediaHash(message, 'micro'));
const isRoundVideo = Boolean(getMessageRoundVideo(message)); const isRoundVideo = Boolean(getMessageRoundVideo(message));
@ -140,7 +137,4 @@ export default memo(withGlobal<OwnProps>(
...(privateChatUserId && { privateChatUser: selectUser(global, privateChatUserId) }), ...(privateChatUserId && { privateChatUser: selectUser(global, privateChatUserId) }),
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'focusMessage',
]),
)(ChatMessage)); )(ChatMessage));

View File

@ -1,13 +1,11 @@
import React, { import React, {
FC, memo, useCallback, useMemo, FC, memo, useCallback, useMemo,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { ApiChat, ApiMessage } from '../../../api/types'; import { ApiChat, ApiMessage } from '../../../api/types';
import { GlobalActions } from '../../../global/types';
import { LoadMoreDirection } from '../../../types'; import { LoadMoreDirection } from '../../../types';
import { pick } from '../../../util/iteratees';
import { getMessageSummaryText } from '../../../modules/helpers'; import { getMessageSummaryText } from '../../../modules/helpers';
import { MEMO_EMPTY_ARRAY } from '../../../util/memo'; import { MEMO_EMPTY_ARRAY } from '../../../util/memo';
import { throttle } from '../../../util/schedulers'; import { throttle } from '../../../util/schedulers';
@ -34,11 +32,9 @@ type StateProps = {
lastSyncTime?: number; lastSyncTime?: number;
}; };
type DispatchProps = Pick<GlobalActions, ('searchMessagesGlobal')>;
const runThrottled = throttle((cb) => cb(), 500, true); const runThrottled = throttle((cb) => cb(), 500, true);
const ChatMessageResults: FC<OwnProps & StateProps & DispatchProps> = ({ const ChatMessageResults: FC<OwnProps & StateProps> = ({
searchQuery, searchQuery,
currentUserId, currentUserId,
dateSearchQuery, dateSearchQuery,
@ -47,9 +43,10 @@ const ChatMessageResults: FC<OwnProps & StateProps & DispatchProps> = ({
chatsById, chatsById,
fetchingStatus, fetchingStatus,
lastSyncTime, lastSyncTime,
searchMessagesGlobal,
onSearchDateSelect, onSearchDateSelect,
}) => { }) => {
const { searchMessagesGlobal } = getDispatch();
const lang = useLang(); const lang = useLang();
const handleLoadMore = useCallback(({ direction }: { direction: LoadMoreDirection }) => { const handleLoadMore = useCallback(({ direction }: { direction: LoadMoreDirection }) => {
if (lastSyncTime && direction === LoadMoreDirection.Backwards) { if (lastSyncTime && direction === LoadMoreDirection.Backwards) {
@ -142,5 +139,4 @@ export default memo(withGlobal<OwnProps>(
lastSyncTime, lastSyncTime,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, ['searchMessagesGlobal']),
)(ChatMessageResults)); )(ChatMessageResults));

View File

@ -1,14 +1,13 @@
import React, { import React, {
FC, memo, useCallback, useMemo, useState, FC, memo, useCallback, useMemo, useState,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { getGlobal, withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, getGlobal, withGlobal } from '../../../lib/teact/teactn';
import { ApiChat, ApiMessage } from '../../../api/types'; import { ApiChat, ApiMessage } from '../../../api/types';
import { GlobalActions } from '../../../global/types';
import { LoadMoreDirection } from '../../../types'; import { LoadMoreDirection } from '../../../types';
import { IS_SINGLE_COLUMN_LAYOUT } from '../../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../../util/environment';
import { unique, pick } from '../../../util/iteratees'; import { unique } from '../../../util/iteratees';
import { getMessageSummaryText, sortChatIds, filterUsersByName } from '../../../modules/helpers'; import { getMessageSummaryText, sortChatIds, filterUsersByName } from '../../../modules/helpers';
import { MEMO_EMPTY_ARRAY } from '../../../util/memo'; import { MEMO_EMPTY_ARRAY } from '../../../util/memo';
import { throttle } from '../../../util/schedulers'; import { throttle } from '../../../util/schedulers';
@ -45,21 +44,21 @@ type StateProps = {
lastSyncTime?: number; lastSyncTime?: number;
}; };
type DispatchProps = Pick<GlobalActions, (
'openChat' | 'addRecentlyFoundChatId' | 'searchMessagesGlobal' | 'setGlobalSearchChatId'
)>;
const MIN_QUERY_LENGTH_FOR_GLOBAL_SEARCH = 4; const MIN_QUERY_LENGTH_FOR_GLOBAL_SEARCH = 4;
const LESS_LIST_ITEMS_AMOUNT = 5; const LESS_LIST_ITEMS_AMOUNT = 5;
const runThrottled = throttle((cb) => cb(), 500, true); const runThrottled = throttle((cb) => cb(), 500, true);
const ChatResults: FC<OwnProps & StateProps & DispatchProps> = ({ const ChatResults: FC<OwnProps & StateProps> = ({
searchQuery, searchDate, dateSearchQuery, currentUserId, searchQuery, searchDate, dateSearchQuery, currentUserId,
localContactIds, localChatIds, localUserIds, globalChatIds, globalUserIds, localContactIds, localChatIds, localUserIds, globalChatIds, globalUserIds,
foundIds, globalMessagesByChatId, chatsById, fetchingStatus, lastSyncTime, foundIds, globalMessagesByChatId, chatsById, fetchingStatus, lastSyncTime,
onReset, onSearchDateSelect, openChat, addRecentlyFoundChatId, searchMessagesGlobal, setGlobalSearchChatId, onReset, onSearchDateSelect,
}) => { }) => {
const {
openChat, addRecentlyFoundChatId, searchMessagesGlobal, setGlobalSearchChatId,
} = getDispatch();
const lang = useLang(); const lang = useLang();
const [shouldShowMoreLocal, setShouldShowMoreLocal] = useState<boolean>(false); const [shouldShowMoreLocal, setShouldShowMoreLocal] = useState<boolean>(false);
@ -306,10 +305,4 @@ export default memo(withGlobal<OwnProps>(
lastSyncTime, lastSyncTime,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'openChat',
'addRecentlyFoundChatId',
'searchMessagesGlobal',
'setGlobalSearchChatId',
]),
)(ChatResults)); )(ChatResults));

View File

@ -1,16 +1,14 @@
import React, { import React, {
FC, memo, useCallback, useMemo, FC, memo, useCallback, useMemo,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { ApiMessage } from '../../../api/types'; import { ApiMessage } from '../../../api/types';
import { GlobalActions } from '../../../global/types';
import { LoadMoreDirection } from '../../../types'; import { LoadMoreDirection } from '../../../types';
import { SLIDE_TRANSITION_DURATION } from '../../../config'; import { SLIDE_TRANSITION_DURATION } from '../../../config';
import { MEMO_EMPTY_ARRAY } from '../../../util/memo'; import { MEMO_EMPTY_ARRAY } from '../../../util/memo';
import { createMapStateToProps, StateProps } from './helpers/createMapStateToProps'; import { createMapStateToProps, StateProps } from './helpers/createMapStateToProps';
import { pick } from '../../../util/iteratees';
import { formatMonthAndYear, toYearMonth } from '../../../util/dateFormat'; import { formatMonthAndYear, toYearMonth } from '../../../util/dateFormat';
import { getSenderName } from './helpers/getSenderName'; import { getSenderName } from './helpers/getSenderName';
import { throttle } from '../../../util/schedulers'; import { throttle } from '../../../util/schedulers';
@ -27,12 +25,10 @@ export type OwnProps = {
searchQuery?: string; searchQuery?: string;
}; };
type DispatchProps = Pick<GlobalActions, ('searchMessagesGlobal' | 'focusMessage')>;
const CURRENT_TYPE = 'documents'; const CURRENT_TYPE = 'documents';
const runThrottled = throttle((cb) => cb(), 500, true); const runThrottled = throttle((cb) => cb(), 500, true);
const FileResults: FC<OwnProps & StateProps & DispatchProps> = ({ const FileResults: FC<OwnProps & StateProps> = ({
searchQuery, searchQuery,
searchChatId, searchChatId,
isLoading, isLoading,
@ -42,9 +38,12 @@ const FileResults: FC<OwnProps & StateProps & DispatchProps> = ({
foundIds, foundIds,
activeDownloads, activeDownloads,
lastSyncTime, lastSyncTime,
searchMessagesGlobal,
focusMessage,
}) => { }) => {
const {
searchMessagesGlobal,
focusMessage,
} = getDispatch();
const lang = useLang(); const lang = useLang();
const handleLoadMore = useCallback(({ direction }: { direction: LoadMoreDirection }) => { const handleLoadMore = useCallback(({ direction }: { direction: LoadMoreDirection }) => {
if (lastSyncTime && direction === LoadMoreDirection.Backwards) { if (lastSyncTime && direction === LoadMoreDirection.Backwards) {
@ -127,8 +126,4 @@ const FileResults: FC<OwnProps & StateProps & DispatchProps> = ({
export default memo(withGlobal<OwnProps>( export default memo(withGlobal<OwnProps>(
createMapStateToProps(CURRENT_TYPE), createMapStateToProps(CURRENT_TYPE),
(setGlobal, actions): DispatchProps => pick(actions, [
'searchMessagesGlobal',
'focusMessage',
]),
)(FileResults)); )(FileResults));

View File

@ -1,12 +1,10 @@
import React, { import React, {
FC, memo, useCallback, useState, useMemo, useRef, FC, memo, useCallback, useState, useMemo, useRef,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { GlobalSearchContent } from '../../../types'; import { GlobalSearchContent } from '../../../types';
import { pick } from '../../../util/iteratees';
import { parseDateString } from '../../../util/dateFormat'; import { parseDateString } from '../../../util/dateFormat';
import useKeyboardListNavigation from '../../../hooks/useKeyboardListNavigation'; import useKeyboardListNavigation from '../../../hooks/useKeyboardListNavigation';
import useLang from '../../../hooks/useLang'; import useLang from '../../../hooks/useLang';
@ -35,8 +33,6 @@ type StateProps = {
chatId?: string; chatId?: string;
}; };
type DispatchProps = Pick<GlobalActions, ('setGlobalSearchContent' | 'setGlobalSearchDate')>;
const TABS = [ const TABS = [
{ type: GlobalSearchContent.ChatList, title: 'SearchAllChatsShort' }, { type: GlobalSearchContent.ChatList, title: 'SearchAllChatsShort' },
{ type: GlobalSearchContent.Media, title: 'SharedMediaTab2' }, { type: GlobalSearchContent.Media, title: 'SharedMediaTab2' },
@ -53,16 +49,19 @@ const CHAT_TABS = [
const TRANSITION_RENDER_COUNT = Object.keys(GlobalSearchContent).length / 2; const TRANSITION_RENDER_COUNT = Object.keys(GlobalSearchContent).length / 2;
const LeftSearch: FC<OwnProps & StateProps & DispatchProps> = ({ const LeftSearch: FC<OwnProps & StateProps> = ({
searchQuery, searchQuery,
searchDate, searchDate,
isActive, isActive,
currentContent = GlobalSearchContent.ChatList, currentContent = GlobalSearchContent.ChatList,
chatId, chatId,
setGlobalSearchContent,
setGlobalSearchDate,
onReset, onReset,
}) => { }) => {
const {
setGlobalSearchContent,
setGlobalSearchDate,
} = getDispatch();
const lang = useLang(); const lang = useLang();
const [activeTab, setActiveTab] = useState(currentContent); const [activeTab, setActiveTab] = useState(currentContent);
const dateSearchQuery = useMemo(() => parseDateString(searchQuery), [searchQuery]); const dateSearchQuery = useMemo(() => parseDateString(searchQuery), [searchQuery]);
@ -149,5 +148,4 @@ export default memo(withGlobal<OwnProps>(
return { currentContent, chatId }; return { currentContent, chatId };
}, },
(setGlobal, actions): DispatchProps => pick(actions, ['setGlobalSearchContent', 'setGlobalSearchDate']),
)(LeftSearch)); )(LeftSearch));

View File

@ -1,15 +1,13 @@
import React, { import React, {
FC, memo, useCallback, useMemo, FC, memo, useCallback, useMemo,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { LoadMoreDirection } from '../../../types'; import { LoadMoreDirection } from '../../../types';
import { SLIDE_TRANSITION_DURATION } from '../../../config'; import { SLIDE_TRANSITION_DURATION } from '../../../config';
import { MEMO_EMPTY_ARRAY } from '../../../util/memo'; import { MEMO_EMPTY_ARRAY } from '../../../util/memo';
import { createMapStateToProps, StateProps } from './helpers/createMapStateToProps'; import { createMapStateToProps, StateProps } from './helpers/createMapStateToProps';
import { pick } from '../../../util/iteratees';
import { formatMonthAndYear, toYearMonth } from '../../../util/dateFormat'; import { formatMonthAndYear, toYearMonth } from '../../../util/dateFormat';
import { getSenderName } from './helpers/getSenderName'; import { getSenderName } from './helpers/getSenderName';
import { throttle } from '../../../util/schedulers'; import { throttle } from '../../../util/schedulers';
@ -25,12 +23,10 @@ export type OwnProps = {
searchQuery?: string; searchQuery?: string;
}; };
type DispatchProps = Pick<GlobalActions, ('searchMessagesGlobal' | 'focusMessage')>;
const CURRENT_TYPE = 'links'; const CURRENT_TYPE = 'links';
const runThrottled = throttle((cb) => cb(), 500, true); const runThrottled = throttle((cb) => cb(), 500, true);
const LinkResults: FC<OwnProps & StateProps & DispatchProps> = ({ const LinkResults: FC<OwnProps & StateProps> = ({
searchQuery, searchQuery,
searchChatId, searchChatId,
isLoading, isLoading,
@ -39,9 +35,12 @@ const LinkResults: FC<OwnProps & StateProps & DispatchProps> = ({
globalMessagesByChatId, globalMessagesByChatId,
foundIds, foundIds,
lastSyncTime, lastSyncTime,
searchMessagesGlobal,
focusMessage,
}) => { }) => {
const {
searchMessagesGlobal,
focusMessage,
} = getDispatch();
const lang = useLang(); const lang = useLang();
const handleLoadMore = useCallback(({ direction }: { direction: LoadMoreDirection }) => { const handleLoadMore = useCallback(({ direction }: { direction: LoadMoreDirection }) => {
if (lastSyncTime && direction === LoadMoreDirection.Backwards) { if (lastSyncTime && direction === LoadMoreDirection.Backwards) {
@ -122,8 +121,4 @@ const LinkResults: FC<OwnProps & StateProps & DispatchProps> = ({
export default memo(withGlobal<OwnProps>( export default memo(withGlobal<OwnProps>(
createMapStateToProps(CURRENT_TYPE), createMapStateToProps(CURRENT_TYPE),
(setGlobal, actions): DispatchProps => pick(actions, [
'searchMessagesGlobal',
'focusMessage',
]),
)(LinkResults)); )(LinkResults));

View File

@ -1,15 +1,13 @@
import React, { import React, {
FC, memo, useCallback, useMemo, FC, memo, useCallback, useMemo,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { LoadMoreDirection, MediaViewerOrigin } from '../../../types'; import { LoadMoreDirection, MediaViewerOrigin } from '../../../types';
import { MEMO_EMPTY_ARRAY } from '../../../util/memo'; import { MEMO_EMPTY_ARRAY } from '../../../util/memo';
import { SLIDE_TRANSITION_DURATION } from '../../../config'; import { SLIDE_TRANSITION_DURATION } from '../../../config';
import { createMapStateToProps, StateProps } from './helpers/createMapStateToProps'; import { createMapStateToProps, StateProps } from './helpers/createMapStateToProps';
import { pick } from '../../../util/iteratees';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
import { throttle } from '../../../util/schedulers'; import { throttle } from '../../../util/schedulers';
import useLang from '../../../hooks/useLang'; import useLang from '../../../hooks/useLang';
@ -25,21 +23,22 @@ export type OwnProps = {
searchQuery?: string; searchQuery?: string;
}; };
type DispatchProps = Pick<GlobalActions, ('searchMessagesGlobal' | 'openMediaViewer')>;
const CURRENT_TYPE = 'media'; const CURRENT_TYPE = 'media';
const runThrottled = throttle((cb) => cb(), 500, true); const runThrottled = throttle((cb) => cb(), 500, true);
const MediaResults: FC<OwnProps & StateProps & DispatchProps> = ({ const MediaResults: FC<OwnProps & StateProps> = ({
searchQuery, searchQuery,
searchChatId, searchChatId,
isLoading, isLoading,
globalMessagesByChatId, globalMessagesByChatId,
foundIds, foundIds,
lastSyncTime, lastSyncTime,
searchMessagesGlobal,
openMediaViewer,
}) => { }) => {
const {
searchMessagesGlobal,
openMediaViewer,
} = getDispatch();
const lang = useLang(); const lang = useLang();
const handleLoadMore = useCallback(({ direction }: { direction: LoadMoreDirection }) => { const handleLoadMore = useCallback(({ direction }: { direction: LoadMoreDirection }) => {
@ -133,8 +132,4 @@ const MediaResults: FC<OwnProps & StateProps & DispatchProps> = ({
export default memo(withGlobal<OwnProps>( export default memo(withGlobal<OwnProps>(
createMapStateToProps(CURRENT_TYPE), createMapStateToProps(CURRENT_TYPE),
(setGlobal, actions): DispatchProps => pick(actions, [
'searchMessagesGlobal',
'openMediaViewer',
]),
)(MediaResults)); )(MediaResults));

View File

@ -1,15 +1,13 @@
import React, { import React, {
FC, useEffect, useCallback, useRef, memo, FC, useEffect, useCallback, useRef, memo,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { ApiUser } from '../../../api/types'; import { ApiUser } from '../../../api/types';
import { getUserFirstOrLastName } from '../../../modules/helpers'; import { getUserFirstOrLastName } from '../../../modules/helpers';
import renderText from '../../common/helpers/renderText'; import renderText from '../../common/helpers/renderText';
import { throttle } from '../../../util/schedulers'; import { throttle } from '../../../util/schedulers';
import { pick } from '../../../util/iteratees';
import useHorizontalScroll from '../../../hooks/useHorizontalScroll'; import useHorizontalScroll from '../../../hooks/useHorizontalScroll';
import useLang from '../../../hooks/useLang'; import useLang from '../../../hooks/useLang';
@ -29,20 +27,20 @@ type StateProps = {
recentlyFoundChatIds?: string[]; recentlyFoundChatIds?: string[];
}; };
type DispatchProps = Pick<GlobalActions, (
'loadTopUsers' | 'loadContactList' | 'openChat' | 'addRecentlyFoundChatId' | 'clearRecentlyFoundChats'
)>;
const SEARCH_CLOSE_TIMEOUT_MS = 250; const SEARCH_CLOSE_TIMEOUT_MS = 250;
const NBSP = '\u00A0'; const NBSP = '\u00A0';
const runThrottled = throttle((cb) => cb(), 60000, true); const runThrottled = throttle((cb) => cb(), 60000, true);
const RecentContacts: FC<OwnProps & StateProps & DispatchProps> = ({ const RecentContacts: FC<OwnProps & StateProps> = ({
topUserIds, usersById, recentlyFoundChatIds, topUserIds, usersById, recentlyFoundChatIds,
onReset, loadTopUsers, loadContactList, openChat, onReset,
addRecentlyFoundChatId, clearRecentlyFoundChats,
}) => { }) => {
const {
loadTopUsers, loadContactList, openChat,
addRecentlyFoundChatId, clearRecentlyFoundChats,
} = getDispatch();
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
const topUsersRef = useRef<HTMLDivElement>(null); const topUsersRef = useRef<HTMLDivElement>(null);
@ -122,11 +120,4 @@ export default memo(withGlobal<OwnProps>(
recentlyFoundChatIds, recentlyFoundChatIds,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'loadTopUsers',
'loadContactList',
'openChat',
'addRecentlyFoundChatId',
'clearRecentlyFoundChats',
]),
)(RecentContacts)); )(RecentContacts));

View File

@ -1,13 +1,12 @@
import React, { import React, {
FC, useMemo, useState, memo, useRef, useCallback, useEffect, FC, useMemo, useState, memo, useRef, useCallback, useEffect,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { ApiUser } from '../../../api/types'; import { ApiUser } from '../../../api/types';
import { filterUsersByName, getUserFullName } from '../../../modules/helpers'; import { filterUsersByName, getUserFullName } from '../../../modules/helpers';
import { pick, unique } from '../../../util/iteratees'; import { unique } from '../../../util/iteratees';
import useLang from '../../../hooks/useLang'; import useLang from '../../../hooks/useLang';
import ChatOrUserPicker from '../../common/ChatOrUserPicker'; import ChatOrUserPicker from '../../common/ChatOrUserPicker';
@ -25,9 +24,7 @@ type StateProps = {
currentUserId?: string; currentUserId?: string;
}; };
type DispatchProps = Pick<GlobalActions, 'loadContactList' | 'setUserSearchQuery' | 'blockContact'>; const BlockUserModal: FC<OwnProps & StateProps> = ({
const BlockUserModal: FC<OwnProps & StateProps & DispatchProps> = ({
usersById, usersById,
blockedIds, blockedIds,
contactIds, contactIds,
@ -35,10 +32,13 @@ const BlockUserModal: FC<OwnProps & StateProps & DispatchProps> = ({
currentUserId, currentUserId,
isOpen, isOpen,
onClose, onClose,
loadContactList,
setUserSearchQuery,
blockContact,
}) => { }) => {
const {
loadContactList,
setUserSearchQuery,
blockContact,
} = getDispatch();
const lang = useLang(); const lang = useLang();
const [filter, setFilter] = useState(''); const [filter, setFilter] = useState('');
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
@ -110,7 +110,4 @@ export default memo(withGlobal<OwnProps>(
currentUserId, currentUserId,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'loadContactList', 'setUserSearchQuery', 'blockContact',
]),
)(BlockUserModal)); )(BlockUserModal));

View File

@ -1,7 +1,6 @@
import React, { FC, memo, useCallback } from '../../../lib/teact/teact'; import React, { FC, memo, useCallback } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { SettingsScreens, ISettings } from '../../../types'; import { SettingsScreens, ISettings } from '../../../types';
import { AUTODOWNLOAD_FILESIZE_MB_LIMITS } from '../../../config'; import { AUTODOWNLOAD_FILESIZE_MB_LIMITS } from '../../../config';
@ -36,11 +35,7 @@ type StateProps = Pick<ISettings, (
'autoLoadFileMaxSizeMb' 'autoLoadFileMaxSizeMb'
)>; )>;
type DispatchProps = Pick<GlobalActions, ( const SettingsDataStorage: FC<OwnProps & StateProps> = ({
'setSettingOption'
)>;
const SettingsDataStorage: FC<OwnProps & StateProps & DispatchProps> = ({
isActive, isActive,
onScreenSelect, onScreenSelect,
onReset, onReset,
@ -59,8 +54,9 @@ const SettingsDataStorage: FC<OwnProps & StateProps & DispatchProps> = ({
canAutoPlayGifs, canAutoPlayGifs,
canAutoPlayVideos, canAutoPlayVideos,
autoLoadFileMaxSizeMb, autoLoadFileMaxSizeMb,
setSettingOption,
}) => { }) => {
const { setSettingOption } = getDispatch();
const lang = useLang(); const lang = useLang();
useHistoryBack(isActive, onReset, onScreenSelect, SettingsScreens.General); useHistoryBack(isActive, onReset, onScreenSelect, SettingsScreens.General);
@ -193,7 +189,4 @@ export default memo(withGlobal<OwnProps>(
'autoLoadFileMaxSizeMb', 'autoLoadFileMaxSizeMb',
]); ]);
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'setSettingOption',
]),
)(SettingsDataStorage)); )(SettingsDataStorage));

View File

@ -2,14 +2,12 @@ import { ChangeEvent } from 'react';
import React, { import React, {
FC, useState, useCallback, memo, useEffect, useMemo, FC, useState, useCallback, memo, useEffect, useMemo,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { ApiMediaFormat } from '../../../api/types'; import { ApiMediaFormat } from '../../../api/types';
import { GlobalActions } from '../../../global/types';
import { ProfileEditProgress, SettingsScreens } from '../../../types'; import { ProfileEditProgress, SettingsScreens } from '../../../types';
import { throttle } from '../../../util/schedulers'; import { throttle } from '../../../util/schedulers';
import { pick } from '../../../util/iteratees';
import { selectUser } from '../../../modules/selectors'; import { selectUser } from '../../../modules/selectors';
import { getChatAvatarHash } from '../../../modules/helpers'; import { getChatAvatarHash } from '../../../modules/helpers';
import useMedia from '../../../hooks/useMedia'; import useMedia from '../../../hooks/useMedia';
@ -39,10 +37,6 @@ type StateProps = {
isUsernameAvailable?: boolean; isUsernameAvailable?: boolean;
}; };
type DispatchProps = Pick<GlobalActions, (
'loadCurrentUser' | 'updateProfile' | 'checkUsername'
)>;
const runThrottled = throttle((cb) => cb(), 60000, true); const runThrottled = throttle((cb) => cb(), 60000, true);
const MAX_BIO_LENGTH = 70; const MAX_BIO_LENGTH = 70;
@ -50,7 +44,7 @@ const MAX_BIO_LENGTH = 70;
const ERROR_FIRST_NAME_MISSING = 'Please provide your first name'; const ERROR_FIRST_NAME_MISSING = 'Please provide your first name';
const ERROR_BIO_TOO_LONG = 'Bio can\' be longer than 70 characters'; const ERROR_BIO_TOO_LONG = 'Bio can\' be longer than 70 characters';
const SettingsEditProfile: FC<OwnProps & StateProps & DispatchProps> = ({ const SettingsEditProfile: FC<OwnProps & StateProps> = ({
isActive, isActive,
onScreenSelect, onScreenSelect,
onReset, onReset,
@ -61,10 +55,13 @@ const SettingsEditProfile: FC<OwnProps & StateProps & DispatchProps> = ({
currentUsername, currentUsername,
progress, progress,
isUsernameAvailable, isUsernameAvailable,
loadCurrentUser,
updateProfile,
checkUsername,
}) => { }) => {
const {
loadCurrentUser,
updateProfile,
checkUsername,
} = getDispatch();
const lang = useLang(); const lang = useLang();
const [isUsernameTouched, setIsUsernameTouched] = useState(false); const [isUsernameTouched, setIsUsernameTouched] = useState(false);
@ -286,9 +283,4 @@ export default memo(withGlobal<OwnProps>(
isUsernameAvailable, isUsernameAvailable,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'loadCurrentUser',
'updateProfile',
'checkUsername',
]),
)(SettingsEditProfile)); )(SettingsEditProfile));

View File

@ -1,9 +1,8 @@
import React, { import React, {
FC, useCallback, memo, useEffect, useRef, useState, FC, useCallback, memo, useEffect, useRef, useState,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { SettingsScreens, ISettings, TimeFormat } from '../../../types'; import { SettingsScreens, ISettings, TimeFormat } from '../../../types';
import { ApiSticker, ApiStickerSet } from '../../../api/types'; import { ApiSticker, ApiStickerSet } from '../../../api/types';
@ -28,21 +27,18 @@ type OwnProps = {
onReset: () => void; onReset: () => void;
}; };
type StateProps = Pick<ISettings, ( type StateProps =
'messageTextSize' | Pick<ISettings, (
'animationLevel' | 'messageTextSize' |
'messageSendKeyCombo' | 'animationLevel' |
'shouldSuggestStickers' | 'messageSendKeyCombo' |
'shouldLoopStickers' | 'shouldSuggestStickers' |
'timeFormat' 'shouldLoopStickers' |
)> & { 'timeFormat'
stickerSetIds?: string[]; )> & {
stickerSetsById?: Record<string, ApiStickerSet>; stickerSetIds?: string[];
}; stickerSetsById?: Record<string, ApiStickerSet>;
};
type DispatchProps = Pick<GlobalActions, (
'setSettingOption' | 'loadStickerSets' | 'loadAddedStickers'
)>;
const ANIMATION_LEVEL_OPTIONS = [ const ANIMATION_LEVEL_OPTIONS = [
'Solid and Steady', 'Solid and Steady',
@ -58,7 +54,7 @@ const TIME_FORMAT_OPTIONS: IRadioOption[] = [{
value: '24h', value: '24h',
}]; }];
const SettingsGeneral: FC<OwnProps & StateProps & DispatchProps> = ({ const SettingsGeneral: FC<OwnProps & StateProps> = ({
isActive, isActive,
onScreenSelect, onScreenSelect,
onReset, onReset,
@ -70,10 +66,13 @@ const SettingsGeneral: FC<OwnProps & StateProps & DispatchProps> = ({
shouldSuggestStickers, shouldSuggestStickers,
shouldLoopStickers, shouldLoopStickers,
timeFormat, timeFormat,
setSettingOption,
loadStickerSets,
loadAddedStickers,
}) => { }) => {
const {
setSettingOption,
loadStickerSets,
loadAddedStickers,
} = getDispatch();
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
const stickerSettingsRef = useRef<HTMLDivElement>(null); const stickerSettingsRef = useRef<HTMLDivElement>(null);
const { observe: observeIntersectionForCovers } = useIntersectionObserver({ rootRef: stickerSettingsRef }); const { observe: observeIntersectionForCovers } = useIntersectionObserver({ rootRef: stickerSettingsRef });
@ -252,7 +251,4 @@ export default memo(withGlobal<OwnProps>(
stickerSetsById: global.stickers.setsById, stickerSetsById: global.stickers.setsById,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'setSettingOption', 'loadStickerSets', 'loadAddedStickers',
]),
)(SettingsGeneral)); )(SettingsGeneral));

View File

@ -1,14 +1,12 @@
import React, { import React, {
FC, memo, useEffect, useCallback, useRef, FC, memo, useEffect, useCallback, useRef,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { SettingsScreens, ThemeKey, UPLOADING_WALLPAPER_SLUG } from '../../../types'; import { SettingsScreens, ThemeKey, UPLOADING_WALLPAPER_SLUG } from '../../../types';
import { ApiWallpaper } from '../../../api/types'; import { ApiWallpaper } from '../../../api/types';
import { DARK_THEME_PATTERN_COLOR, DEFAULT_PATTERN_COLOR } from '../../../config'; import { DARK_THEME_PATTERN_COLOR, DEFAULT_PATTERN_COLOR } from '../../../config';
import { pick } from '../../../util/iteratees';
import { throttle } from '../../../util/schedulers'; import { throttle } from '../../../util/schedulers';
import { openSystemFilesDialog } from '../../../util/systemFilesDialog'; import { openSystemFilesDialog } from '../../../util/systemFilesDialog';
import { getAverageColor, getPatternColor, rgb2hex } from '../../../util/colors'; import { getAverageColor, getPatternColor, rgb2hex } from '../../../util/colors';
@ -36,15 +34,11 @@ type StateProps = {
theme: ThemeKey; theme: ThemeKey;
}; };
type DispatchProps = Pick<GlobalActions, (
'loadWallpapers' | 'uploadWallpaper' | 'setThemeSettings'
)>;
const SUPPORTED_TYPES = 'image/jpeg'; const SUPPORTED_TYPES = 'image/jpeg';
const runThrottled = throttle((cb) => cb(), 60000, true); const runThrottled = throttle((cb) => cb(), 60000, true);
const SettingsGeneralBackground: FC<OwnProps & StateProps & DispatchProps> = ({ const SettingsGeneralBackground: FC<OwnProps & StateProps> = ({
isActive, isActive,
onScreenSelect, onScreenSelect,
onReset, onReset,
@ -52,10 +46,13 @@ const SettingsGeneralBackground: FC<OwnProps & StateProps & DispatchProps> = ({
isBlurred, isBlurred,
loadedWallpapers, loadedWallpapers,
theme, theme,
loadWallpapers,
uploadWallpaper,
setThemeSettings,
}) => { }) => {
const {
loadWallpapers,
uploadWallpaper,
setThemeSettings,
} = getDispatch();
const themeRef = useRef<string>(); const themeRef = useRef<string>();
themeRef.current = theme; themeRef.current = theme;
// Due to the parent Transition, this component never gets unmounted, // Due to the parent Transition, this component never gets unmounted,
@ -177,7 +174,4 @@ export default memo(withGlobal<OwnProps>(
theme, theme,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'loadWallpapers', 'uploadWallpaper', 'setThemeSettings',
]),
)(SettingsGeneralBackground)); )(SettingsGeneralBackground));

View File

@ -2,9 +2,8 @@ import { ChangeEvent, MutableRefObject, RefObject } from 'react';
import React, { import React, {
FC, memo, useCallback, useEffect, useRef, useState, FC, memo, useCallback, useEffect, useRef, useState,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { SettingsScreens, ThemeKey } from '../../../types'; import { SettingsScreens, ThemeKey } from '../../../types';
import { pick } from '../../../util/iteratees'; import { pick } from '../../../util/iteratees';
@ -32,8 +31,6 @@ type StateProps = {
theme: ThemeKey; theme: ThemeKey;
}; };
type DispatchProps = Pick<GlobalActions, 'setThemeSettings'>;
interface CanvasRects { interface CanvasRects {
colorRect: { colorRect: {
offsetLeft: number; offsetLeft: number;
@ -53,14 +50,15 @@ const PREDEFINED_COLORS = [
'#ccd0af', '#a6a997', '#7a7072', '#fdd7af', '#fdb76e', '#dd8851', '#ccd0af', '#a6a997', '#7a7072', '#fdd7af', '#fdb76e', '#dd8851',
]; ];
const SettingsGeneralBackground: FC<OwnProps & StateProps & DispatchProps> = ({ const SettingsGeneralBackground: FC<OwnProps & StateProps> = ({
isActive, isActive,
onScreenSelect, onScreenSelect,
onReset, onReset,
theme, theme,
backgroundColor, backgroundColor,
setThemeSettings,
}) => { }) => {
const { setThemeSettings } = getDispatch();
const themeRef = useRef<string>(); const themeRef = useRef<string>();
themeRef.current = theme; themeRef.current = theme;
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
@ -358,5 +356,4 @@ export default memo(withGlobal<OwnProps>(
theme, theme,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, ['setThemeSettings']),
)(SettingsGeneralBackground)); )(SettingsGeneralBackground));

View File

@ -1,13 +1,11 @@
import React, { import React, {
FC, memo, useCallback, useMemo, useState, FC, memo, useCallback, useMemo, useState,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { SettingsScreens } from '../../../types'; import { SettingsScreens } from '../../../types';
import { IS_SINGLE_COLUMN_LAYOUT } from '../../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../../util/environment';
import { pick } from '../../../util/iteratees';
import useLang from '../../../hooks/useLang'; import useLang from '../../../hooks/useLang';
import DropdownMenu from '../../ui/DropdownMenu'; import DropdownMenu from '../../ui/DropdownMenu';
@ -23,17 +21,18 @@ type OwnProps = {
onScreenSelect: (screen: SettingsScreens) => void; onScreenSelect: (screen: SettingsScreens) => void;
}; };
type DispatchProps = Pick<GlobalActions, 'signOut' | 'deleteChatFolder'>; const SettingsHeader: FC<OwnProps> = ({
const SettingsHeader: FC<OwnProps & DispatchProps> = ({
currentScreen, currentScreen,
editedFolderId, editedFolderId,
onReset, onReset,
onSaveFilter, onSaveFilter,
signOut,
deleteChatFolder,
onScreenSelect, onScreenSelect,
}) => { }) => {
const {
signOut,
deleteChatFolder,
} = getDispatch();
const [isSignOutDialogOpen, setIsSignOutDialogOpen] = useState(false); const [isSignOutDialogOpen, setIsSignOutDialogOpen] = useState(false);
const [isDeleteFolderDialogOpen, setIsDeleteFolderDialogOpen] = useState(false); const [isDeleteFolderDialogOpen, setIsDeleteFolderDialogOpen] = useState(false);
@ -263,7 +262,4 @@ const SettingsHeader: FC<OwnProps & DispatchProps> = ({
); );
}; };
export default memo(withGlobal<OwnProps>( export default memo(SettingsHeader);
undefined,
(setGlobal, actions): DispatchProps => pick(actions, ['signOut', 'deleteChatFolder']),
)(SettingsHeader));

View File

@ -1,14 +1,12 @@
import React, { import React, {
FC, memo, useCallback, useEffect, useMemo, useState, FC, memo, useCallback, useEffect, useMemo, useState,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { ISettings, LangCode, SettingsScreens } from '../../../types'; import { ISettings, LangCode, SettingsScreens } from '../../../types';
import { ApiLanguage } from '../../../api/types'; import { ApiLanguage } from '../../../api/types';
import { setLanguage } from '../../../util/langProvider'; import { setLanguage } from '../../../util/langProvider';
import { pick } from '../../../util/iteratees';
import RadioGroup from '../../ui/RadioGroup'; import RadioGroup from '../../ui/RadioGroup';
import Loading from '../../ui/Loading'; import Loading from '../../ui/Loading';
@ -23,17 +21,18 @@ type OwnProps = {
type StateProps = Pick<ISettings, 'languages' | 'language'>; type StateProps = Pick<ISettings, 'languages' | 'language'>;
type DispatchProps = Pick<GlobalActions, 'loadLanguages' | 'setSettingOption'>; const SettingsLanguage: FC<OwnProps & StateProps> = ({
const SettingsLanguage: FC<OwnProps & StateProps & DispatchProps> = ({
isActive, isActive,
onScreenSelect, onScreenSelect,
onReset, onReset,
languages, languages,
language, language,
loadLanguages,
setSettingOption,
}) => { }) => {
const {
loadLanguages,
setSettingOption,
} = getDispatch();
const [selectedLanguage, setSelectedLanguage] = useState<string>(language); const [selectedLanguage, setSelectedLanguage] = useState<string>(language);
const [isLoading, markIsLoading, unmarkIsLoading] = useFlag(); const [isLoading, markIsLoading, unmarkIsLoading] = useFlag();
@ -96,7 +95,4 @@ export default memo(withGlobal<OwnProps>(
language: global.settings.byKey.language, language: global.settings.byKey.language,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'loadLanguages', 'setSettingOption',
]),
)(SettingsLanguage)); )(SettingsLanguage));

View File

@ -1,12 +1,10 @@
import React, { FC, memo, useEffect } from '../../../lib/teact/teact'; import React, { FC, memo, useEffect } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { SettingsScreens } from '../../../types'; import { SettingsScreens } from '../../../types';
import { ApiUser } from '../../../api/types'; import { ApiUser } from '../../../api/types';
import { selectUser } from '../../../modules/selectors'; import { selectUser } from '../../../modules/selectors';
import { pick } from '../../../util/iteratees';
import useLang from '../../../hooks/useLang'; import useLang from '../../../hooks/useLang';
import useHistoryBack from '../../../hooks/useHistoryBack'; import useHistoryBack from '../../../hooks/useHistoryBack';
@ -25,16 +23,15 @@ type StateProps = {
lastSyncTime?: number; lastSyncTime?: number;
}; };
type DispatchProps = Pick<GlobalActions, 'loadProfilePhotos'>; const SettingsMain: FC<OwnProps & StateProps> = ({
const SettingsMain: FC<OwnProps & StateProps & DispatchProps> = ({
isActive, isActive,
onScreenSelect, onScreenSelect,
onReset, onReset,
loadProfilePhotos,
currentUser, currentUser,
lastSyncTime, lastSyncTime,
}) => { }) => {
const { loadProfilePhotos } = getDispatch();
const lang = useLang(); const lang = useLang();
const profileId = currentUser?.id; const profileId = currentUser?.id;
@ -111,5 +108,4 @@ export default memo(withGlobal<OwnProps>(
lastSyncTime, lastSyncTime,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, ['loadProfilePhotos']),
)(SettingsMain)); )(SettingsMain));

View File

@ -3,12 +3,10 @@ import useDebounce from '../../../hooks/useDebounce';
import React, { import React, {
FC, memo, useCallback, useEffect, FC, memo, useCallback, useEffect,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { SettingsScreens } from '../../../types'; import { SettingsScreens } from '../../../types';
import { pick } from '../../../util/iteratees';
import useLang from '../../../hooks/useLang'; import useLang from '../../../hooks/useLang';
import useHistoryBack from '../../../hooks/useHistoryBack'; import useHistoryBack from '../../../hooks/useHistoryBack';
import { playNotifySound } from '../../../util/notifications'; import { playNotifySound } from '../../../util/notifications';
@ -35,12 +33,7 @@ type StateProps = {
notificationSoundVolume: number; notificationSoundVolume: number;
}; };
type DispatchProps = Pick<GlobalActions, ( const SettingsNotifications: FC<OwnProps & StateProps> = ({
'loadNotificationSettings' | 'updateContactSignUpNotification' |
'updateNotificationSettings' | 'updateWebNotificationSettings'
)>;
const SettingsNotifications: FC<OwnProps & StateProps & DispatchProps> = ({
isActive, isActive,
onScreenSelect, onScreenSelect,
onReset, onReset,
@ -54,11 +47,14 @@ const SettingsNotifications: FC<OwnProps & StateProps & DispatchProps> = ({
hasPushNotifications, hasPushNotifications,
hasWebNotifications, hasWebNotifications,
notificationSoundVolume, notificationSoundVolume,
loadNotificationSettings,
updateContactSignUpNotification,
updateNotificationSettings,
updateWebNotificationSettings,
}) => { }) => {
const {
loadNotificationSettings,
updateContactSignUpNotification,
updateNotificationSettings,
updateWebNotificationSettings,
} = getDispatch();
useEffect(() => { useEffect(() => {
loadNotificationSettings(); loadNotificationSettings();
}, [loadNotificationSettings]); }, [loadNotificationSettings]);
@ -147,7 +143,9 @@ const SettingsNotifications: FC<OwnProps & StateProps & DispatchProps> = ({
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
subLabel={lang(hasPrivateChatsNotifications ? 'UserInfo.NotificationsEnabled' : 'UserInfo.NotificationsDisabled')} subLabel={lang(hasPrivateChatsNotifications ? 'UserInfo.NotificationsEnabled' : 'UserInfo.NotificationsDisabled')}
checked={hasPrivateChatsNotifications} checked={hasPrivateChatsNotifications}
onChange={(e) => { handleSettingsChange(e, 'contact', 'silent'); }} onChange={(e) => {
handleSettingsChange(e, 'contact', 'silent');
}}
/> />
<Checkbox <Checkbox
label={lang('MessagePreview')} label={lang('MessagePreview')}
@ -155,7 +153,9 @@ const SettingsNotifications: FC<OwnProps & StateProps & DispatchProps> = ({
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
subLabel={lang(hasPrivateChatsMessagePreview ? 'UserInfo.NotificationsEnabled' : 'UserInfo.NotificationsDisabled')} subLabel={lang(hasPrivateChatsMessagePreview ? 'UserInfo.NotificationsEnabled' : 'UserInfo.NotificationsDisabled')}
checked={hasPrivateChatsMessagePreview} checked={hasPrivateChatsMessagePreview}
onChange={(e) => { handleSettingsChange(e, 'contact', 'showPreviews'); }} onChange={(e) => {
handleSettingsChange(e, 'contact', 'showPreviews');
}}
/> />
</div> </div>
@ -166,14 +166,18 @@ const SettingsNotifications: FC<OwnProps & StateProps & DispatchProps> = ({
label={lang('NotificationsForGroups')} label={lang('NotificationsForGroups')}
subLabel={lang(hasGroupNotifications ? 'UserInfo.NotificationsEnabled' : 'UserInfo.NotificationsDisabled')} subLabel={lang(hasGroupNotifications ? 'UserInfo.NotificationsEnabled' : 'UserInfo.NotificationsDisabled')}
checked={hasGroupNotifications} checked={hasGroupNotifications}
onChange={(e) => { handleSettingsChange(e, 'group', 'silent'); }} onChange={(e) => {
handleSettingsChange(e, 'group', 'silent');
}}
/> />
<Checkbox <Checkbox
label={lang('MessagePreview')} label={lang('MessagePreview')}
disabled={!hasGroupNotifications} disabled={!hasGroupNotifications}
subLabel={lang(hasGroupMessagePreview ? 'UserInfo.NotificationsEnabled' : 'UserInfo.NotificationsDisabled')} subLabel={lang(hasGroupMessagePreview ? 'UserInfo.NotificationsEnabled' : 'UserInfo.NotificationsDisabled')}
checked={hasGroupMessagePreview} checked={hasGroupMessagePreview}
onChange={(e) => { handleSettingsChange(e, 'group', 'showPreviews'); }} onChange={(e) => {
handleSettingsChange(e, 'group', 'showPreviews');
}}
/> />
</div> </div>
@ -185,7 +189,9 @@ const SettingsNotifications: FC<OwnProps & StateProps & DispatchProps> = ({
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
subLabel={lang(hasBroadcastNotifications ? 'UserInfo.NotificationsEnabled' : 'UserInfo.NotificationsDisabled')} subLabel={lang(hasBroadcastNotifications ? 'UserInfo.NotificationsEnabled' : 'UserInfo.NotificationsDisabled')}
checked={hasBroadcastNotifications} checked={hasBroadcastNotifications}
onChange={(e) => { handleSettingsChange(e, 'broadcast', 'silent'); }} onChange={(e) => {
handleSettingsChange(e, 'broadcast', 'silent');
}}
/> />
<Checkbox <Checkbox
label={lang('MessagePreview')} label={lang('MessagePreview')}
@ -193,7 +199,9 @@ const SettingsNotifications: FC<OwnProps & StateProps & DispatchProps> = ({
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
subLabel={lang(hasBroadcastMessagePreview ? 'UserInfo.NotificationsEnabled' : 'UserInfo.NotificationsDisabled')} subLabel={lang(hasBroadcastMessagePreview ? 'UserInfo.NotificationsEnabled' : 'UserInfo.NotificationsDisabled')}
checked={hasBroadcastMessagePreview} checked={hasBroadcastMessagePreview}
onChange={(e) => { handleSettingsChange(e, 'broadcast', 'showPreviews'); }} onChange={(e) => {
handleSettingsChange(e, 'broadcast', 'showPreviews');
}}
/> />
</div> </div>
@ -210,23 +218,19 @@ const SettingsNotifications: FC<OwnProps & StateProps & DispatchProps> = ({
); );
}; };
export default memo(withGlobal<OwnProps>((global): StateProps => { export default memo(withGlobal<OwnProps>(
return { (global): StateProps => {
hasPrivateChatsNotifications: Boolean(global.settings.byKey.hasPrivateChatsNotifications), return {
hasPrivateChatsMessagePreview: Boolean(global.settings.byKey.hasPrivateChatsMessagePreview), hasPrivateChatsNotifications: Boolean(global.settings.byKey.hasPrivateChatsNotifications),
hasGroupNotifications: Boolean(global.settings.byKey.hasGroupNotifications), hasPrivateChatsMessagePreview: Boolean(global.settings.byKey.hasPrivateChatsMessagePreview),
hasGroupMessagePreview: Boolean(global.settings.byKey.hasGroupMessagePreview), hasGroupNotifications: Boolean(global.settings.byKey.hasGroupNotifications),
hasBroadcastNotifications: Boolean(global.settings.byKey.hasBroadcastNotifications), hasGroupMessagePreview: Boolean(global.settings.byKey.hasGroupMessagePreview),
hasBroadcastMessagePreview: Boolean(global.settings.byKey.hasBroadcastMessagePreview), hasBroadcastNotifications: Boolean(global.settings.byKey.hasBroadcastNotifications),
hasContactJoinedNotifications: Boolean(global.settings.byKey.hasContactJoinedNotifications), hasBroadcastMessagePreview: Boolean(global.settings.byKey.hasBroadcastMessagePreview),
hasWebNotifications: global.settings.byKey.hasWebNotifications, hasContactJoinedNotifications: Boolean(global.settings.byKey.hasContactJoinedNotifications),
hasPushNotifications: global.settings.byKey.hasPushNotifications, hasWebNotifications: global.settings.byKey.hasWebNotifications,
notificationSoundVolume: global.settings.byKey.notificationSoundVolume, hasPushNotifications: global.settings.byKey.hasPushNotifications,
}; notificationSoundVolume: global.settings.byKey.notificationSoundVolume,
}, };
(setGlobal, actions): DispatchProps => pick(actions, [ },
'loadNotificationSettings', )(SettingsNotifications));
'updateContactSignUpNotification',
'updateNotificationSettings',
'updateWebNotificationSettings',
]))(SettingsNotifications));

View File

@ -1,10 +1,8 @@
import React, { FC, memo, useEffect } from '../../../lib/teact/teact'; import React, { FC, memo, useEffect } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { PrivacyVisibility, SettingsScreens } from '../../../types'; import { PrivacyVisibility, SettingsScreens } from '../../../types';
import { pick } from '../../../util/iteratees';
import useLang from '../../../hooks/useLang'; import useLang from '../../../hooks/useLang';
import useHistoryBack from '../../../hooks/useHistoryBack'; import useHistoryBack from '../../../hooks/useHistoryBack';
@ -30,11 +28,7 @@ type StateProps = {
visibilityPrivacyGroupChats?: PrivacyVisibility; visibilityPrivacyGroupChats?: PrivacyVisibility;
}; };
type DispatchProps = Pick<GlobalActions, ( const SettingsPrivacy: FC<OwnProps & StateProps> = ({
'loadBlockedContacts' | 'loadAuthorizations' | 'loadPrivacySettings' | 'loadContentSettings' | 'updateContentSettings'
)>;
const SettingsPrivacy: FC<OwnProps & StateProps & DispatchProps> = ({
isActive, isActive,
onScreenSelect, onScreenSelect,
onReset, onReset,
@ -48,12 +42,16 @@ const SettingsPrivacy: FC<OwnProps & StateProps & DispatchProps> = ({
visibilityPrivacyProfilePhoto, visibilityPrivacyProfilePhoto,
visibilityPrivacyForwarding, visibilityPrivacyForwarding,
visibilityPrivacyGroupChats, visibilityPrivacyGroupChats,
loadPrivacySettings,
loadBlockedContacts,
loadAuthorizations,
loadContentSettings,
updateContentSettings,
}) => { }) => {
const {
loadPrivacySettings,
loadBlockedContacts,
loadAuthorizations,
loadContentSettings,
updateContentSettings,
} = getDispatch();
useEffect(() => { useEffect(() => {
loadBlockedContacts(); loadBlockedContacts();
loadAuthorizations(); loadAuthorizations();
@ -234,7 +232,4 @@ export default memo(withGlobal<OwnProps>(
visibilityPrivacyGroupChats: privacy.chatInvite?.visibility, visibilityPrivacyGroupChats: privacy.chatInvite?.visibility,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'loadBlockedContacts', 'loadAuthorizations', 'loadPrivacySettings', 'loadContentSettings', 'updateContentSettings',
]),
)(SettingsPrivacy)); )(SettingsPrivacy));

View File

@ -1,13 +1,11 @@
import React, { import React, {
FC, memo, useCallback, useEffect, useMemo, FC, memo, useCallback, useEffect, useMemo,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { ApiSession } from '../../../api/types'; import { ApiSession } from '../../../api/types';
import { SettingsScreens } from '../../../types'; import { SettingsScreens } from '../../../types';
import { pick } from '../../../util/iteratees';
import { formatPastTimeShort } from '../../../util/dateFormat'; import { formatPastTimeShort } from '../../../util/dateFormat';
import useFlag from '../../../hooks/useFlag'; import useFlag from '../../../hooks/useFlag';
import useLang from '../../../hooks/useLang'; import useLang from '../../../hooks/useLang';
@ -26,19 +24,18 @@ type StateProps = {
activeSessions: ApiSession[]; activeSessions: ApiSession[];
}; };
type DispatchProps = Pick<GlobalActions, ( const SettingsPrivacyActiveSessions: FC<OwnProps & StateProps> = ({
'loadAuthorizations' | 'terminateAuthorization' | 'terminateAllAuthorizations'
)>;
const SettingsPrivacyActiveSessions: FC<OwnProps & StateProps & DispatchProps> = ({
isActive, isActive,
onScreenSelect, onScreenSelect,
onReset, onReset,
activeSessions, activeSessions,
loadAuthorizations,
terminateAuthorization,
terminateAllAuthorizations,
}) => { }) => {
const {
loadAuthorizations,
terminateAuthorization,
terminateAllAuthorizations,
} = getDispatch();
const [isConfirmTerminateAllDialogOpen, openConfirmTerminateAllDialog, closeConfirmTerminateAllDialog] = useFlag(); const [isConfirmTerminateAllDialogOpen, openConfirmTerminateAllDialog, closeConfirmTerminateAllDialog] = useFlag();
useEffect(() => { useEffect(() => {
loadAuthorizations(); loadAuthorizations();
@ -162,7 +159,4 @@ export default memo(withGlobal<OwnProps>(
activeSessions: global.activeSessions, activeSessions: global.activeSessions,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'loadAuthorizations', 'terminateAuthorization', 'terminateAllAuthorizations',
]),
)(SettingsPrivacyActiveSessions)); )(SettingsPrivacyActiveSessions));

View File

@ -1,15 +1,13 @@
import React, { import React, {
FC, memo, useCallback, FC, memo, useCallback,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { ApiChat, ApiCountryCode, ApiUser } from '../../../api/types'; import { ApiChat, ApiCountryCode, ApiUser } from '../../../api/types';
import { SettingsScreens } from '../../../types'; import { SettingsScreens } from '../../../types';
import { CHAT_HEIGHT_PX } from '../../../config'; import { CHAT_HEIGHT_PX } from '../../../config';
import { formatPhoneNumberWithCode } from '../../../util/phoneNumber'; import { formatPhoneNumberWithCode } from '../../../util/phoneNumber';
import { pick } from '../../../util/iteratees';
import { import {
getChatTitle, getUserFullName, isUserId, getChatTitle, getUserFullName, isUserId,
} from '../../../modules/helpers'; } from '../../../modules/helpers';
@ -38,9 +36,7 @@ type StateProps = {
phoneCodeList: ApiCountryCode[]; phoneCodeList: ApiCountryCode[];
}; };
type DispatchProps = Pick<GlobalActions, 'unblockContact'>; const SettingsPrivacyBlockedUsers: FC<OwnProps & StateProps> = ({
const SettingsPrivacyBlockedUsers: FC<OwnProps & StateProps & DispatchProps> = ({
isActive, isActive,
onScreenSelect, onScreenSelect,
onReset, onReset,
@ -48,8 +44,9 @@ const SettingsPrivacyBlockedUsers: FC<OwnProps & StateProps & DispatchProps> = (
usersByIds, usersByIds,
blockedIds, blockedIds,
phoneCodeList, phoneCodeList,
unblockContact,
}) => { }) => {
const { unblockContact } = getDispatch();
const lang = useLang(); const lang = useLang();
const [isBlockUserModalOpen, openBlockUserModal, closeBlockUserModal] = useFlag(); const [isBlockUserModalOpen, openBlockUserModal, closeBlockUserModal] = useFlag();
const handleUnblockClick = useCallback((contactId: string) => { const handleUnblockClick = useCallback((contactId: string) => {
@ -158,5 +155,4 @@ export default memo(withGlobal<OwnProps>(
phoneCodeList, phoneCodeList,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, ['unblockContact']),
)(SettingsPrivacyBlockedUsers)); )(SettingsPrivacyBlockedUsers));

View File

@ -1,14 +1,12 @@
import React, { import React, {
FC, memo, useCallback, useMemo, FC, memo, useCallback, useMemo,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { ApiChat, ApiUser } from '../../../api/types'; import { ApiChat, ApiUser } from '../../../api/types';
import { ApiPrivacySettings, SettingsScreens } from '../../../types'; import { ApiPrivacySettings, SettingsScreens } from '../../../types';
import useLang from '../../../hooks/useLang'; import useLang from '../../../hooks/useLang';
import { pick } from '../../../util/iteratees';
import useHistoryBack from '../../../hooks/useHistoryBack'; import useHistoryBack from '../../../hooks/useHistoryBack';
import ListItem from '../../ui/ListItem'; import ListItem from '../../ui/ListItem';
@ -22,14 +20,13 @@ type OwnProps = {
onReset: () => void; onReset: () => void;
}; };
type StateProps = Partial<ApiPrivacySettings> & { type StateProps =
chatsById?: Record<string, ApiChat>; Partial<ApiPrivacySettings> & {
usersById?: Record<string, ApiUser>; chatsById?: Record<string, ApiChat>;
}; usersById?: Record<string, ApiUser>;
};
type DispatchProps = Pick<GlobalActions, 'setPrivacyVisibility'>; const SettingsPrivacyVisibility: FC<OwnProps & StateProps> = ({
const SettingsPrivacyVisibility: FC<OwnProps & StateProps & DispatchProps> = ({
screen, screen,
isActive, isActive,
onScreenSelect, onScreenSelect,
@ -40,8 +37,9 @@ const SettingsPrivacyVisibility: FC<OwnProps & StateProps & DispatchProps> = ({
blockUserIds, blockUserIds,
blockChatIds, blockChatIds,
chatsById, chatsById,
setPrivacyVisibility,
}) => { }) => {
const { setPrivacyVisibility } = getDispatch();
const lang = useLang(); const lang = useLang();
const visibilityOptions = useMemo(() => { const visibilityOptions = useMemo(() => {
@ -178,7 +176,9 @@ const SettingsPrivacyVisibility: FC<OwnProps & StateProps & DispatchProps> = ({
<ListItem <ListItem
narrow narrow
icon="add-user" icon="add-user"
onClick={() => { onScreenSelect(allowedContactsScreen); }} onClick={() => {
onScreenSelect(allowedContactsScreen);
}}
> >
<div className="multiline-menu-item full-size"> <div className="multiline-menu-item full-size">
{allowedCount > 0 && <span className="date" dir="auto">+{allowedCount}</span>} {allowedCount > 0 && <span className="date" dir="auto">+{allowedCount}</span>}
@ -191,7 +191,9 @@ const SettingsPrivacyVisibility: FC<OwnProps & StateProps & DispatchProps> = ({
<ListItem <ListItem
narrow narrow
icon="delete-user" icon="delete-user"
onClick={() => { onScreenSelect(deniedContactsScreen); }} onClick={() => {
onScreenSelect(deniedContactsScreen);
}}
> >
<div className="multiline-menu-item full-size"> <div className="multiline-menu-item full-size">
{blockCount > 0 && <span className="date" dir="auto">&minus;{blockCount}</span>} {blockCount > 0 && <span className="date" dir="auto">&minus;{blockCount}</span>}
@ -245,5 +247,4 @@ export default memo(withGlobal<OwnProps>(
chatsById, chatsById,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, ['setPrivacyVisibility']),
)(SettingsPrivacyVisibility)); )(SettingsPrivacyVisibility));

View File

@ -1,14 +1,13 @@
import React, { import React, {
FC, memo, useCallback, useMemo, useState, FC, memo, useCallback, useMemo, useState,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions, GlobalState } from '../../../global/types'; import { GlobalState } from '../../../global/types';
import { ApiChat } from '../../../api/types'; import { ApiChat } from '../../../api/types';
import { ApiPrivacySettings, SettingsScreens } from '../../../types'; import { ApiPrivacySettings, SettingsScreens } from '../../../types';
import useLang from '../../../hooks/useLang'; import useLang from '../../../hooks/useLang';
import { pick } from '../../../util/iteratees';
import searchWords from '../../../util/searchWords'; import searchWords from '../../../util/searchWords';
import { getPrivacyKey } from './helper/privacy'; import { getPrivacyKey } from './helper/privacy';
import { import {
@ -37,9 +36,7 @@ type StateProps = {
settings?: ApiPrivacySettings; settings?: ApiPrivacySettings;
}; };
type DispatchProps = Pick<GlobalActions, 'setPrivacySettings'>; const SettingsPrivacyVisibilityExceptionList: FC<OwnProps & StateProps> = ({
const SettingsPrivacyVisibilityExceptionList: FC<OwnProps & StateProps & DispatchProps> = ({
currentUserId, currentUserId,
isAllowList, isAllowList,
screen, screen,
@ -49,11 +46,12 @@ const SettingsPrivacyVisibilityExceptionList: FC<OwnProps & StateProps & Dispatc
orderedPinnedIds, orderedPinnedIds,
archivedListIds, archivedListIds,
archivedPinnedIds, archivedPinnedIds,
setPrivacySettings,
isActive, isActive,
onScreenSelect, onScreenSelect,
onReset, onReset,
}) => { }) => {
const { setPrivacySettings } = getDispatch();
const lang = useLang(); const lang = useLang();
const selectedContactIds = useMemo(() => { const selectedContactIds = useMemo(() => {
@ -105,8 +103,8 @@ const SettingsPrivacyVisibilityExceptionList: FC<OwnProps & StateProps & Dispatc
((isUserId(chat.id) && chat.id !== currentUserId) || isChatGroup(chat)) ((isUserId(chat.id) && chat.id !== currentUserId) || isChatGroup(chat))
&& ( && (
!searchQuery !searchQuery
|| searchWords(getChatTitle(lang, chat), searchQuery) || searchWords(getChatTitle(lang, chat), searchQuery)
|| selectedContactIds.includes(chat.id) || selectedContactIds.includes(chat.id)
) )
)) ))
.map(({ id }) => id); .map(({ id }) => id);
@ -196,5 +194,4 @@ export default memo(withGlobal<OwnProps>(
settings: getCurrentPrivacySettings(global, screen), settings: getCurrentPrivacySettings(global, screen),
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, ['setPrivacySettings']),
)(SettingsPrivacyVisibilityExceptionList)); )(SettingsPrivacyVisibilityExceptionList));

View File

@ -1,14 +1,12 @@
import React, { import React, {
FC, memo, useMemo, useCallback, FC, memo, useMemo, useCallback,
} from '../../../../lib/teact/teact'; } from '../../../../lib/teact/teact';
import { withGlobal } from '../../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../../lib/teact/teactn';
import { GlobalActions } from '../../../../global/types';
import { ApiChat } from '../../../../api/types'; import { ApiChat } from '../../../../api/types';
import { SettingsScreens } from '../../../../types'; import { SettingsScreens } from '../../../../types';
import useLang from '../../../../hooks/useLang'; import useLang from '../../../../hooks/useLang';
import { pick } from '../../../../util/iteratees';
import searchWords from '../../../../util/searchWords'; import searchWords from '../../../../util/searchWords';
import { prepareChatList, getChatTitle } from '../../../../modules/helpers'; import { prepareChatList, getChatTitle } from '../../../../modules/helpers';
import { import {
@ -39,9 +37,7 @@ type StateProps = {
archivedPinnedIds?: string[]; archivedPinnedIds?: string[];
}; };
type DispatchProps = Pick<GlobalActions, 'loadMoreChats'>; const SettingsFoldersChatFilters: FC<OwnProps & StateProps> = ({
const SettingsFoldersChatFilters: FC<OwnProps & StateProps & DispatchProps> = ({
isActive, isActive,
onScreenSelect, onScreenSelect,
onReset, onReset,
@ -53,8 +49,9 @@ const SettingsFoldersChatFilters: FC<OwnProps & StateProps & DispatchProps> = ({
orderedPinnedIds, orderedPinnedIds,
archivedListIds, archivedListIds,
archivedPinnedIds, archivedPinnedIds,
loadMoreChats,
}) => { }) => {
const { loadMoreChats } = getDispatch();
const { chatFilter } = state; const { chatFilter } = state;
const { selectedChatIds, selectedChatTypes } = selectChatFilters(state, mode, true); const { selectedChatIds, selectedChatTypes } = selectChatFilters(state, mode, true);
@ -180,5 +177,4 @@ export default memo(withGlobal<OwnProps>(
archivedListIds: listIds.archived, archivedListIds: listIds.archived,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, ['loadMoreChats']),
)(SettingsFoldersChatFilters)); )(SettingsFoldersChatFilters));

View File

@ -1,13 +1,12 @@
import React, { import React, {
FC, memo, useCallback, useEffect, useMemo, useState, FC, memo, useCallback, useEffect, useMemo, useState,
} from '../../../../lib/teact/teact'; } from '../../../../lib/teact/teact';
import { withGlobal } from '../../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../../lib/teact/teactn';
import { GlobalActions } from '../../../../global/types';
import { SettingsScreens } from '../../../../types'; import { SettingsScreens } from '../../../../types';
import { STICKER_SIZE_FOLDER_SETTINGS } from '../../../../config'; import { STICKER_SIZE_FOLDER_SETTINGS } from '../../../../config';
import { findIntersectionWithSet, pick } from '../../../../util/iteratees'; import { findIntersectionWithSet } from '../../../../util/iteratees';
import { isUserId } from '../../../../modules/helpers'; import { isUserId } from '../../../../modules/helpers';
import getAnimationData from '../../../common/helpers/animatedAssets'; import getAnimationData from '../../../common/helpers/animatedAssets';
import { import {
@ -45,8 +44,6 @@ type StateProps = {
loadedArchivedChatIds?: string[]; loadedArchivedChatIds?: string[];
}; };
type DispatchProps = Pick<GlobalActions, 'editChatFolder' | 'addChatFolder' | 'loadMoreChats'>;
const SUBMIT_TIMEOUT = 500; const SUBMIT_TIMEOUT = 500;
const INITIAL_CHATS_LIMIT = 5; const INITIAL_CHATS_LIMIT = 5;
@ -54,7 +51,7 @@ const INITIAL_CHATS_LIMIT = 5;
const ERROR_NO_TITLE = 'Please provide a title for this folder.'; const ERROR_NO_TITLE = 'Please provide a title for this folder.';
const ERROR_NO_CHATS = 'ChatList.Filter.Error.Empty'; const ERROR_NO_CHATS = 'ChatList.Filter.Error.Empty';
const SettingsFoldersEdit: FC<OwnProps & StateProps & DispatchProps> = ({ const SettingsFoldersEdit: FC<OwnProps & StateProps> = ({
state, state,
dispatch, dispatch,
onAddIncludedChats, onAddIncludedChats,
@ -65,10 +62,13 @@ const SettingsFoldersEdit: FC<OwnProps & StateProps & DispatchProps> = ({
onBack, onBack,
loadedActiveChatIds, loadedActiveChatIds,
loadedArchivedChatIds, loadedArchivedChatIds,
editChatFolder,
addChatFolder,
loadMoreChats,
}) => { }) => {
const {
editChatFolder,
addChatFolder,
loadMoreChats,
} = getDispatch();
const [animationData, setAnimationData] = useState<Record<string, any>>(); const [animationData, setAnimationData] = useState<Record<string, any>>();
const [isAnimationLoaded, setIsAnimationLoaded] = useState(false); const [isAnimationLoaded, setIsAnimationLoaded] = useState(false);
const handleAnimationLoad = useCallback(() => setIsAnimationLoaded(true), []); const handleAnimationLoad = useCallback(() => setIsAnimationLoaded(true), []);
@ -322,5 +322,4 @@ export default memo(withGlobal<OwnProps>(
loadedArchivedChatIds: listIds.archived, loadedArchivedChatIds: listIds.archived,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, ['editChatFolder', 'addChatFolder', 'loadMoreChats']),
)(SettingsFoldersEdit)); )(SettingsFoldersEdit));

View File

@ -1,14 +1,13 @@
import React, { import React, {
FC, memo, useMemo, useCallback, useState, useEffect, FC, memo, useMemo, useCallback, useState, useEffect,
} from '../../../../lib/teact/teact'; } from '../../../../lib/teact/teact';
import { withGlobal } from '../../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../../lib/teact/teactn';
import { GlobalActions, GlobalState } from '../../../../global/types'; import { GlobalState } from '../../../../global/types';
import { ApiChatFolder, ApiChat, ApiUser } from '../../../../api/types'; import { ApiChatFolder, ApiChat, ApiUser } from '../../../../api/types';
import { NotifyException, NotifySettings, SettingsScreens } from '../../../../types'; import { NotifyException, NotifySettings, SettingsScreens } from '../../../../types';
import { STICKER_SIZE_FOLDER_SETTINGS } from '../../../../config'; import { STICKER_SIZE_FOLDER_SETTINGS } from '../../../../config';
import { pick } from '../../../../util/iteratees';
import { selectNotifyExceptions, selectNotifySettings } from '../../../../modules/selectors'; import { selectNotifyExceptions, selectNotifySettings } from '../../../../modules/selectors';
import { throttle } from '../../../../util/schedulers'; import { throttle } from '../../../../util/schedulers';
import getAnimationData from '../../../common/helpers/animatedAssets'; import getAnimationData from '../../../common/helpers/animatedAssets';
@ -40,13 +39,11 @@ type StateProps = {
notifyExceptions?: Record<number, NotifyException>; notifyExceptions?: Record<number, NotifyException>;
}; };
type DispatchProps = Pick<GlobalActions, 'loadRecommendedChatFolders' | 'addChatFolder' | 'showDialog'>;
const runThrottledForLoadRecommended = throttle((cb) => cb(), 60000, true); const runThrottledForLoadRecommended = throttle((cb) => cb(), 60000, true);
const MAX_ALLOWED_FOLDERS = 10; const MAX_ALLOWED_FOLDERS = 10;
const SettingsFoldersMain: FC<OwnProps & StateProps & DispatchProps> = ({ const SettingsFoldersMain: FC<OwnProps & StateProps> = ({
isActive, isActive,
allListIds, allListIds,
chatsById, chatsById,
@ -60,10 +57,13 @@ const SettingsFoldersMain: FC<OwnProps & StateProps & DispatchProps> = ({
onEditFolder, onEditFolder,
onScreenSelect, onScreenSelect,
onReset, onReset,
loadRecommendedChatFolders,
addChatFolder,
showDialog,
}) => { }) => {
const {
loadRecommendedChatFolders,
addChatFolder,
showDialog,
} = getDispatch();
const [animationData, setAnimationData] = useState<Record<string, any>>(); const [animationData, setAnimationData] = useState<Record<string, any>>();
const [isAnimationLoaded, setIsAnimationLoaded] = useState(false); const [isAnimationLoaded, setIsAnimationLoaded] = useState(false);
const handleAnimationLoad = useCallback(() => setIsAnimationLoaded(true), []); const handleAnimationLoad = useCallback(() => setIsAnimationLoaded(true), []);
@ -250,5 +250,4 @@ export default memo(withGlobal<OwnProps>(
notifyExceptions: selectNotifyExceptions(global), notifyExceptions: selectNotifyExceptions(global),
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, ['loadRecommendedChatFolders', 'addChatFolder', 'showDialog']),
)(SettingsFoldersMain)); )(SettingsFoldersMain));

View File

@ -1,12 +1,11 @@
import React, { import React, {
FC, memo, useCallback, useEffect, FC, memo, useCallback, useEffect,
} from '../../../../lib/teact/teact'; } from '../../../../lib/teact/teact';
import { withGlobal } from '../../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../../lib/teact/teactn';
import { GlobalActions, GlobalState } from '../../../../global/types'; import { GlobalState } from '../../../../global/types';
import { SettingsScreens } from '../../../../types'; import { SettingsScreens } from '../../../../types';
import { pick } from '../../../../util/iteratees';
import { TwoFaDispatch, TwoFaState } from '../../../../hooks/reducers/useTwoFaReducer'; import { TwoFaDispatch, TwoFaState } from '../../../../hooks/reducers/useTwoFaReducer';
import useLang from '../../../../hooks/useLang'; import useLang from '../../../../hooks/useLang';
@ -29,12 +28,7 @@ export type OwnProps = {
type StateProps = GlobalState['twoFaSettings']; type StateProps = GlobalState['twoFaSettings'];
type DispatchProps = Pick<GlobalActions, ( const SettingsTwoFa: FC<OwnProps & StateProps> = ({
'updatePassword' | 'updateRecoveryEmail' | 'clearPassword' | 'provideTwoFaEmailCode' |
'checkPassword' | 'clearTwoFaError'
)>;
const SettingsTwoFa: FC<OwnProps & StateProps & DispatchProps> = ({
currentScreen, currentScreen,
shownScreen, shownScreen,
state, state,
@ -46,13 +40,16 @@ const SettingsTwoFa: FC<OwnProps & StateProps & DispatchProps> = ({
isActive, isActive,
onScreenSelect, onScreenSelect,
onReset, onReset,
updatePassword,
checkPassword,
clearTwoFaError,
updateRecoveryEmail,
provideTwoFaEmailCode,
clearPassword,
}) => { }) => {
const {
updatePassword,
checkPassword,
clearTwoFaError,
updateRecoveryEmail,
provideTwoFaEmailCode,
clearPassword,
} = getDispatch();
useEffect(() => { useEffect(() => {
if (waitingEmailCodeLength) { if (waitingEmailCodeLength) {
if (currentScreen === SettingsScreens.TwoFaNewPasswordEmail) { if (currentScreen === SettingsScreens.TwoFaNewPasswordEmail) {
@ -435,8 +432,4 @@ const SettingsTwoFa: FC<OwnProps & StateProps & DispatchProps> = ({
export default memo(withGlobal<OwnProps>( export default memo(withGlobal<OwnProps>(
(global): StateProps => ({ ...global.twoFaSettings }), (global): StateProps => ({ ...global.twoFaSettings }),
(setGlobal, actions): DispatchProps => pick(actions, [
'updatePassword', 'updateRecoveryEmail', 'clearPassword', 'provideTwoFaEmailCode',
'checkPassword', 'clearTwoFaError',
]),
)(SettingsTwoFa)); )(SettingsTwoFa));

View File

@ -1,7 +1,6 @@
import React, { FC, memo } from '../../lib/teact/teact'; import React, { FC, memo } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { GlobalActions } from '../../global/types';
import { ApiError, ApiInviteInfo } from '../../api/types'; import { ApiError, ApiInviteInfo } from '../../api/types';
import getReadableErrorText from '../../util/getReadableErrorText'; import getReadableErrorText from '../../util/getReadableErrorText';
@ -18,9 +17,9 @@ type StateProps = {
dialogs: (ApiError | ApiInviteInfo)[]; dialogs: (ApiError | ApiInviteInfo)[];
}; };
type DispatchProps = Pick<GlobalActions, 'dismissDialog' | 'acceptInviteConfirmation'>; const Dialogs: FC<StateProps> = ({ dialogs }) => {
const { dismissDialog, acceptInviteConfirmation } = getDispatch();
const Dialogs: FC<StateProps & DispatchProps> = ({ dialogs, dismissDialog, acceptInviteConfirmation }) => {
const lang = useLang(); const lang = useLang();
if (!dialogs.length) { if (!dialogs.length) {
@ -104,5 +103,4 @@ function getErrorHeader(error: ApiError) {
export default memo(withGlobal( export default memo(withGlobal(
(global): StateProps => pick(global, ['dialogs']), (global): StateProps => pick(global, ['dialogs']),
(setGlobal, actions): DispatchProps => pick(actions, ['dismissDialog', 'acceptInviteConfirmation']),
)(Dialogs)); )(Dialogs));

View File

@ -1,7 +1,7 @@
import { FC, memo, useEffect } from '../../lib/teact/teact'; import { FC, memo, useEffect } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { GlobalActions, Thread } from '../../global/types'; import { Thread } from '../../global/types';
import { ApiMediaFormat, ApiMessage } from '../../api/types'; import { ApiMediaFormat, ApiMessage } from '../../api/types';
import * as mediaLoader from '../../util/mediaLoader'; import * as mediaLoader from '../../util/mediaLoader';
@ -9,7 +9,6 @@ import download from '../../util/download';
import { import {
getMessageContentFilename, getMessageMediaHash, getMessageContentFilename, getMessageMediaHash,
} from '../../modules/helpers'; } from '../../modules/helpers';
import { pick } from '../../util/iteratees';
type StateProps = { type StateProps = {
activeDownloads: Record<number, number[]>; activeDownloads: Record<number, number[]>;
@ -19,15 +18,14 @@ type StateProps = {
}>; }>;
}; };
type DispatchProps = Pick<GlobalActions, 'cancelMessageMediaDownload'>;
const startedDownloads = new Set<string>(); const startedDownloads = new Set<string>();
const DownloadManager: FC<StateProps & DispatchProps> = ({ const DownloadManager: FC<StateProps> = ({
activeDownloads, activeDownloads,
messages, messages,
cancelMessageMediaDownload,
}) => { }) => {
const { cancelMessageMediaDownload } = getDispatch();
useEffect(() => { useEffect(() => {
Object.entries(activeDownloads).forEach(([chatId, messageIds]) => { Object.entries(activeDownloads).forEach(([chatId, messageIds]) => {
const activeMessages = messageIds.map((id) => messages[Number(chatId)].byId[id]); const activeMessages = messageIds.map((id) => messages[Number(chatId)].byId[id]);
@ -77,5 +75,4 @@ export default memo(withGlobal(
messages, messages,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, ['cancelMessageMediaDownload']),
)(DownloadManager)); )(DownloadManager));

View File

@ -1,9 +1,8 @@
import React, { import React, {
FC, useMemo, useState, memo, useRef, useCallback, FC, useMemo, useState, memo, useRef, useCallback,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { getGlobal, withGlobal } from '../../lib/teact/teactn'; import { getDispatch, getGlobal, withGlobal } from '../../lib/teact/teactn';
import { GlobalActions } from '../../global/types';
import { ApiChat, MAIN_THREAD_ID } from '../../api/types'; import { ApiChat, MAIN_THREAD_ID } from '../../api/types';
import { import {
@ -12,7 +11,7 @@ import {
getCanPostInChat, getCanPostInChat,
sortChatIds, sortChatIds,
} from '../../modules/helpers'; } from '../../modules/helpers';
import { pick, unique } from '../../util/iteratees'; import { unique } from '../../util/iteratees';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
import useCurrentOrPrev from '../../hooks/useCurrentOrPrev'; import useCurrentOrPrev from '../../hooks/useCurrentOrPrev';
@ -31,9 +30,7 @@ type StateProps = {
currentUserId?: string; currentUserId?: string;
}; };
type DispatchProps = Pick<GlobalActions, 'setForwardChatId' | 'exitForwardMode' | 'loadMoreChats'>; const ForwardPicker: FC<OwnProps & StateProps> = ({
const ForwardPicker: FC<OwnProps & StateProps & DispatchProps> = ({
chatsById, chatsById,
activeListIds, activeListIds,
archivedListIds, archivedListIds,
@ -41,10 +38,13 @@ const ForwardPicker: FC<OwnProps & StateProps & DispatchProps> = ({
contactIds, contactIds,
currentUserId, currentUserId,
isOpen, isOpen,
setForwardChatId,
exitForwardMode,
loadMoreChats,
}) => { }) => {
const {
setForwardChatId,
exitForwardMode,
loadMoreChats,
} = getDispatch();
const lang = useLang(); const lang = useLang();
const [filter, setFilter] = useState(''); const [filter, setFilter] = useState('');
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
@ -120,5 +120,4 @@ export default memo(withGlobal<OwnProps>(
currentUserId, currentUserId,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, ['setForwardChatId', 'exitForwardMode', 'loadMoreChats']),
)(ForwardPicker)); )(ForwardPicker));

View File

@ -1,9 +1,6 @@
import React, { FC, memo, useCallback } from '../../lib/teact/teact'; import React, { FC, memo, useCallback } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { GlobalActions } from '../../global/types';
import { pick } from '../../util/iteratees';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
import CalendarModal from '../common/CalendarModal'; import CalendarModal from '../common/CalendarModal';
@ -16,11 +13,11 @@ type StateProps = {
selectedAt?: number; selectedAt?: number;
}; };
type DispatchProps = Pick<GlobalActions, 'searchMessagesByDate' | 'closeHistoryCalendar'>; const HistoryCalendar: FC<OwnProps & StateProps> = ({
isOpen, selectedAt,
const HistoryCalendar: FC<OwnProps & StateProps & DispatchProps> = ({
isOpen, selectedAt, searchMessagesByDate, closeHistoryCalendar,
}) => { }) => {
const { searchMessagesByDate, closeHistoryCalendar } = getDispatch();
const handleJumpToDate = useCallback((date: Date) => { const handleJumpToDate = useCallback((date: Date) => {
searchMessagesByDate({ timestamp: date.valueOf() / 1000 }); searchMessagesByDate({ timestamp: date.valueOf() / 1000 });
closeHistoryCalendar(); closeHistoryCalendar();
@ -44,7 +41,4 @@ export default memo(withGlobal<OwnProps>(
(global): StateProps => { (global): StateProps => {
return { selectedAt: global.historyCalendarSelectedAt }; return { selectedAt: global.historyCalendarSelectedAt };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'searchMessagesByDate', 'closeHistoryCalendar',
]),
)(HistoryCalendar)); )(HistoryCalendar));

View File

@ -1,17 +1,15 @@
import React, { import React, {
FC, useEffect, memo, useCallback, FC, useEffect, memo, useCallback,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { getGlobal, withGlobal } from '../../lib/teact/teactn'; import { getDispatch, getGlobal, withGlobal } from '../../lib/teact/teactn';
import { LangCode } from '../../types'; import { LangCode } from '../../types';
import { GlobalActions } from '../../global/types';
import { ApiMessage } from '../../api/types'; import { ApiMessage } from '../../api/types';
import '../../modules/actions/all'; import '../../modules/actions/all';
import { import {
BASE_EMOJI_KEYWORD_LANG, DEBUG, INACTIVE_MARKER, PAGE_TITLE, BASE_EMOJI_KEYWORD_LANG, DEBUG, INACTIVE_MARKER, PAGE_TITLE,
} from '../../config'; } from '../../config';
import { pick } from '../../util/iteratees';
import { import {
selectChatMessage, selectChatMessage,
selectCountNotMutedUnread, selectCountNotMutedUnread,
@ -72,12 +70,6 @@ type StateProps = {
isCallFallbackConfirmOpen: boolean; isCallFallbackConfirmOpen: boolean;
}; };
type DispatchProps = Pick<GlobalActions, (
'loadAnimatedEmojis' | 'loadNotificationSettings' | 'loadNotificationExceptions' | 'updateIsOnline' |
'loadTopInlineBots' | 'loadEmojiKeywords' | 'openStickerSetShortName' |
'loadCountryList' | 'ensureTimeFormat' | 'checkVersionNotification'
)>;
const NOTIFICATION_INTERVAL = 1000; const NOTIFICATION_INTERVAL = 1000;
let notificationInterval: number | undefined; let notificationInterval: number | undefined;
@ -85,7 +77,7 @@ let notificationInterval: number | undefined;
// eslint-disable-next-line @typescript-eslint/naming-convention // eslint-disable-next-line @typescript-eslint/naming-convention
let DEBUG_isLogged = false; let DEBUG_isLogged = false;
const Main: FC<StateProps & DispatchProps> = ({ const Main: FC<StateProps> = ({
lastSyncTime, lastSyncTime,
isLeftColumnShown, isLeftColumnShown,
isRightColumnShown, isRightColumnShown,
@ -104,17 +96,20 @@ const Main: FC<StateProps & DispatchProps> = ({
language, language,
wasTimeFormatSetManually, wasTimeFormatSetManually,
isCallFallbackConfirmOpen, isCallFallbackConfirmOpen,
loadAnimatedEmojis,
loadNotificationSettings,
loadNotificationExceptions,
updateIsOnline,
loadTopInlineBots,
loadEmojiKeywords,
loadCountryList,
ensureTimeFormat,
openStickerSetShortName,
checkVersionNotification,
}) => { }) => {
const {
loadAnimatedEmojis,
loadNotificationSettings,
loadNotificationExceptions,
updateIsOnline,
loadTopInlineBots,
loadEmojiKeywords,
loadCountryList,
ensureTimeFormat,
openStickerSetShortName,
checkVersionNotification,
} = getDispatch();
if (DEBUG && !DEBUG_isLogged) { if (DEBUG && !DEBUG_isLogged) {
DEBUG_isLogged = true; DEBUG_isLogged = true;
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
@ -362,9 +357,4 @@ export default memo(withGlobal(
isCallFallbackConfirmOpen: Boolean(global.groupCalls.isFallbackConfirmOpen), isCallFallbackConfirmOpen: Boolean(global.groupCalls.isFallbackConfirmOpen),
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'loadAnimatedEmojis', 'loadNotificationSettings', 'loadNotificationExceptions', 'updateIsOnline',
'loadTopInlineBots', 'loadEmojiKeywords', 'openStickerSetShortName', 'loadCountryList', 'ensureTimeFormat',
'checkVersionNotification',
]),
)(Main)); )(Main));

View File

@ -1,7 +1,6 @@
import React, { FC, memo } from '../../lib/teact/teact'; import React, { FC, memo } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { GlobalActions } from '../../global/types';
import { ApiNotification } from '../../api/types'; import { ApiNotification } from '../../api/types';
import { pick } from '../../util/iteratees'; import { pick } from '../../util/iteratees';
@ -13,9 +12,9 @@ type StateProps = {
notifications: ApiNotification[]; notifications: ApiNotification[];
}; };
type DispatchProps = Pick<GlobalActions, 'dismissNotification'>; const Notifications: FC<StateProps> = ({ notifications }) => {
const { dismissNotification } = getDispatch();
const Notifications: FC<StateProps & DispatchProps> = ({ notifications, dismissNotification }) => {
if (!notifications.length) { if (!notifications.length) {
return undefined; return undefined;
} }
@ -34,5 +33,4 @@ const Notifications: FC<StateProps & DispatchProps> = ({ notifications, dismissN
export default memo(withGlobal( export default memo(withGlobal(
(global): StateProps => pick(global, ['notifications']), (global): StateProps => pick(global, ['notifications']),
(setGlobal, actions): DispatchProps => pick(actions, ['dismissNotification']),
)(Notifications)); )(Notifications));

View File

@ -1,9 +1,6 @@
import React, { FC, memo, useCallback } from '../../lib/teact/teact'; import React, { FC, memo, useCallback } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch } from '../../lib/teact/teactn';
import { GlobalActions } from '../../global/types';
import { pick } from '../../util/iteratees';
import { ensureProtocol } from '../../util/ensureProtocol'; import { ensureProtocol } from '../../util/ensureProtocol';
import renderText from '../common/helpers/renderText'; import renderText from '../common/helpers/renderText';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
@ -15,9 +12,9 @@ export type OwnProps = {
url?: string; url?: string;
}; };
type DispatchProps = Pick<GlobalActions, 'toggleSafeLinkModal'>; const SafeLinkModal: FC<OwnProps> = ({ url }) => {
const { toggleSafeLinkModal } = getDispatch();
const SafeLinkModal: FC<OwnProps & DispatchProps> = ({ url, toggleSafeLinkModal }) => {
const lang = useLang(); const lang = useLang();
const handleOpen = useCallback(() => { const handleOpen = useCallback(() => {
@ -43,7 +40,4 @@ const SafeLinkModal: FC<OwnProps & DispatchProps> = ({ url, toggleSafeLinkModal
); );
}; };
export default memo(withGlobal<OwnProps>( export default memo(SafeLinkModal);
undefined,
(setGlobal, actions): DispatchProps => pick(actions, ['toggleSafeLinkModal']),
)(SafeLinkModal));

View File

@ -1,9 +1,8 @@
import React, { import React, {
FC, memo, useCallback, useEffect, useMemo, useRef, useState, FC, memo, useCallback, useEffect, useMemo, useRef, useState,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { GlobalActions } from '../../global/types';
import { import {
ApiChat, ApiDimensions, ApiMediaFormat, ApiMessage, ApiUser, ApiChat, ApiDimensions, ApiMediaFormat, ApiMessage, ApiUser,
} from '../../api/types'; } from '../../api/types';
@ -51,7 +50,6 @@ import { stopCurrentAudio } from '../../util/audioPlayer';
import captureEscKeyListener from '../../util/captureEscKeyListener'; import captureEscKeyListener from '../../util/captureEscKeyListener';
import { captureEvents } from '../../util/captureEvents'; import { captureEvents } from '../../util/captureEvents';
import { IS_IOS, IS_SINGLE_COLUMN_LAYOUT, IS_TOUCH_ENV } from '../../util/environment'; import { IS_IOS, IS_SINGLE_COLUMN_LAYOUT, IS_TOUCH_ENV } from '../../util/environment';
import { pick } from '../../util/iteratees';
import windowSize from '../../util/windowSize'; import windowSize from '../../util/windowSize';
import { AVATAR_FULL_DIMENSIONS, MEDIA_VIEWER_MEDIA_QUERY } from '../common/helpers/mediaDimensions'; import { AVATAR_FULL_DIMENSIONS, MEDIA_VIEWER_MEDIA_QUERY } from '../common/helpers/mediaDimensions';
import { renderMessageText } from '../common/helpers/renderMessageText'; import { renderMessageText } from '../common/helpers/renderMessageText';
@ -83,11 +81,9 @@ type StateProps = {
animationLevel: 0 | 1 | 2; animationLevel: 0 | 1 | 2;
}; };
type DispatchProps = Pick<GlobalActions, 'openMediaViewer' | 'closeMediaViewer' | 'openForwardMenu' | 'focusMessage'>;
const ANIMATION_DURATION = 350; const ANIMATION_DURATION = 350;
const MediaViewer: FC<StateProps & DispatchProps> = ({ const MediaViewer: FC<StateProps> = ({
chatId, chatId,
threadId, threadId,
messageId, messageId,
@ -98,12 +94,15 @@ const MediaViewer: FC<StateProps & DispatchProps> = ({
message, message,
chatMessages, chatMessages,
collectionIds, collectionIds,
openMediaViewer,
closeMediaViewer,
openForwardMenu,
focusMessage,
animationLevel, animationLevel,
}) => { }) => {
const {
openMediaViewer,
closeMediaViewer,
openForwardMenu,
focusMessage,
} = getDispatch();
const isOpen = Boolean(avatarOwner || messageId); const isOpen = Boolean(avatarOwner || messageId);
const isFromSharedMedia = origin === MediaViewerOrigin.SharedMedia; const isFromSharedMedia = origin === MediaViewerOrigin.SharedMedia;
@ -641,7 +640,4 @@ export default memo(withGlobal(
animationLevel, animationLevel,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'openMediaViewer', 'closeMediaViewer', 'openForwardMenu', 'focusMessage',
]),
)(MediaViewer)); )(MediaViewer));

View File

@ -4,9 +4,8 @@ import React, {
useCallback, useCallback,
useMemo, useMemo,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { GlobalActions } from '../../global/types';
import { ApiMessage } from '../../api/types'; import { ApiMessage } from '../../api/types';
import { IS_SINGLE_COLUMN_LAYOUT } from '../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT } from '../../util/environment';
@ -14,7 +13,6 @@ import { getMessageMediaHash } from '../../modules/helpers';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
import useMediaWithLoadProgress from '../../hooks/useMediaWithLoadProgress'; import useMediaWithLoadProgress from '../../hooks/useMediaWithLoadProgress';
import { selectIsDownloading } from '../../modules/selectors'; import { selectIsDownloading } from '../../modules/selectors';
import { pick } from '../../util/iteratees';
import Button from '../ui/Button'; import Button from '../ui/Button';
import DropdownMenu from '../ui/DropdownMenu'; import DropdownMenu from '../ui/DropdownMenu';
@ -39,9 +37,7 @@ type OwnProps = {
onZoomToggle: NoneToVoidFunction; onZoomToggle: NoneToVoidFunction;
}; };
type DispatchProps = Pick<GlobalActions, 'downloadMessageMedia' | 'cancelMessageMediaDownload'>; const MediaViewerActions: FC<OwnProps & StateProps> = ({
const MediaViewerActions: FC<OwnProps & StateProps & DispatchProps> = ({
mediaData, mediaData,
isVideo, isVideo,
isZoomed, isZoomed,
@ -52,9 +48,12 @@ const MediaViewerActions: FC<OwnProps & StateProps & DispatchProps> = ({
onCloseMediaViewer, onCloseMediaViewer,
onForward, onForward,
onZoomToggle, onZoomToggle,
downloadMessageMedia,
cancelMessageMediaDownload,
}) => { }) => {
const {
downloadMessageMedia,
cancelMessageMediaDownload,
} = getDispatch();
const { loadProgress: downloadProgress } = useMediaWithLoadProgress( const { loadProgress: downloadProgress } = useMediaWithLoadProgress(
message && getMessageMediaHash(message, 'download'), message && getMessageMediaHash(message, 'download'),
!isDownloading, !isDownloading,
@ -193,8 +192,4 @@ export default memo(withGlobal<OwnProps>(
isDownloading, isDownloading,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'downloadMessageMedia',
'cancelMessageMediaDownload',
]),
)(MediaViewerActions)); )(MediaViewerActions));

View File

@ -1,7 +1,6 @@
import React, { FC, useCallback } from '../../lib/teact/teact'; import React, { FC, useCallback } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { GlobalActions } from '../../global/types';
import { ApiChat, ApiMessage, ApiUser } from '../../api/types'; import { ApiChat, ApiMessage, ApiUser } from '../../api/types';
import { getSenderTitle, isUserId } from '../../modules/helpers'; import { getSenderTitle, isUserId } from '../../modules/helpers';
@ -13,7 +12,6 @@ import {
selectSender, selectSender,
selectUser, selectUser,
} from '../../modules/selectors'; } from '../../modules/selectors';
import { pick } from '../../util/iteratees';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
import Avatar from '../common/Avatar'; import Avatar from '../common/Avatar';
@ -31,17 +29,18 @@ type StateProps = {
message?: ApiMessage; message?: ApiMessage;
}; };
type DispatchProps = Pick<GlobalActions, 'closeMediaViewer' | 'focusMessage'>; const SenderInfo: FC<OwnProps & StateProps> = ({
const SenderInfo: FC<OwnProps & StateProps & DispatchProps> = ({
chatId, chatId,
messageId, messageId,
sender, sender,
isAvatar, isAvatar,
message, message,
closeMediaViewer,
focusMessage,
}) => { }) => {
const {
closeMediaViewer,
focusMessage,
} = getDispatch();
const handleFocusMessage = useCallback(() => { const handleFocusMessage = useCallback(() => {
closeMediaViewer(); closeMediaViewer();
focusMessage({ chatId, messageId }); focusMessage({ chatId, messageId });
@ -95,5 +94,4 @@ export default withGlobal<OwnProps>(
sender: message && selectSender(global, message), sender: message && selectSender(global, message),
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, ['closeMediaViewer', 'focusMessage']),
)(SenderInfo); )(SenderInfo);

View File

@ -1,10 +1,9 @@
import React, { import React, {
FC, useCallback, useEffect, useMemo, FC, useCallback, useEffect, useMemo,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { AudioOrigin } from '../../types'; import { AudioOrigin } from '../../types';
import { GlobalActions } from '../../global/types';
import { import {
ApiAudio, ApiChat, ApiMessage, ApiUser, ApiAudio, ApiChat, ApiMessage, ApiUser,
} from '../../api/types'; } from '../../api/types';
@ -16,7 +15,6 @@ import {
getMediaDuration, getMessageContent, getMessageMediaHash, getSenderTitle, isMessageLocal, getMediaDuration, getMessageContent, getMessageMediaHash, getSenderTitle, isMessageLocal,
} from '../../modules/helpers'; } from '../../modules/helpers';
import { selectChat, selectSender } from '../../modules/selectors'; import { selectChat, selectSender } from '../../modules/selectors';
import { pick } from '../../util/iteratees';
import buildClassName from '../../util/buildClassName'; import buildClassName from '../../util/buildClassName';
import { makeTrackId } from '../../util/audioPlayer'; import { makeTrackId } from '../../util/audioPlayer';
import { clearMediaSession } from '../../util/mediaSession'; import { clearMediaSession } from '../../util/mediaSession';
@ -47,17 +45,9 @@ type StateProps = {
isMuted: boolean; isMuted: boolean;
}; };
type DispatchProps = Pick<GlobalActions, (
'focusMessage' |
'closeAudioPlayer' |
'setAudioPlayerVolume' |
'setAudioPlayerPlaybackRate' |
'setAudioPlayerMuted'
)>;
const FAST_PLAYBACK_RATE = 1.8; const FAST_PLAYBACK_RATE = 1.8;
const AudioPlayer: FC<OwnProps & StateProps & DispatchProps> = ({ const AudioPlayer: FC<OwnProps & StateProps> = ({
message, message,
className, className,
noUi, noUi,
@ -66,12 +56,15 @@ const AudioPlayer: FC<OwnProps & StateProps & DispatchProps> = ({
volume, volume,
playbackRate, playbackRate,
isMuted, isMuted,
setAudioPlayerVolume,
setAudioPlayerPlaybackRate,
setAudioPlayerMuted,
focusMessage,
closeAudioPlayer,
}) => { }) => {
const {
setAudioPlayerVolume,
setAudioPlayerPlaybackRate,
setAudioPlayerMuted,
focusMessage,
closeAudioPlayer,
} = getDispatch();
const lang = useLang(); const lang = useLang();
const { audio, voice, video } = getMessageContent(message); const { audio, voice, video } = getMessageContent(message);
const isVoice = Boolean(voice || video); const isVoice = Boolean(voice || video);
@ -293,8 +286,4 @@ export default withGlobal<OwnProps>(
isMuted, isMuted,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(
actions,
['focusMessage', 'closeAudioPlayer', 'setAudioPlayerVolume', 'setAudioPlayerPlaybackRate', 'setAudioPlayerMuted'],
),
)(AudioPlayer); )(AudioPlayer);

View File

@ -1,12 +1,10 @@
import React, { import React, {
FC, memo, useCallback, useEffect, useRef, FC, memo, useCallback, useEffect, useRef,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { GlobalActions } from '../../global/types';
import { ApiSticker, ApiUpdateConnectionStateType } from '../../api/types'; import { ApiSticker, ApiUpdateConnectionStateType } from '../../api/types';
import { pick } from '../../util/iteratees';
import { selectChat } from '../../modules/selectors'; import { selectChat } from '../../modules/selectors';
import { useIntersectionObserver } from '../../hooks/useIntersectionObserver'; import { useIntersectionObserver } from '../../hooks/useIntersectionObserver';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
@ -26,18 +24,19 @@ type StateProps = {
connectionState?: ApiUpdateConnectionStateType; connectionState?: ApiUpdateConnectionStateType;
}; };
type DispatchProps = Pick<GlobalActions, 'loadGreetingStickers' | 'sendMessage' | 'markMessageListRead'>;
const INTERSECTION_DEBOUNCE_MS = 200; const INTERSECTION_DEBOUNCE_MS = 200;
const ContactGreeting: FC<OwnProps & StateProps & DispatchProps> = ({ const ContactGreeting: FC<OwnProps & StateProps> = ({
sticker, sticker,
connectionState, connectionState,
lastUnreadMessageId, lastUnreadMessageId,
loadGreetingStickers,
sendMessage,
markMessageListRead,
}) => { }) => {
const {
loadGreetingStickers,
sendMessage,
markMessageListRead,
} = getDispatch();
const lang = useLang(); const lang = useLang();
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
@ -110,7 +109,4 @@ export default memo(withGlobal<OwnProps>(
connectionState: global.connectionState, connectionState: global.connectionState,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'loadGreetingStickers', 'sendMessage', 'markMessageListRead',
]),
)(ContactGreeting)); )(ContactGreeting));

View File

@ -1,9 +1,7 @@
import React, { import React, {
FC, useCallback, memo, useEffect, FC, useCallback, memo, useEffect,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { GlobalActions } from '../../global/types';
import { selectCanDeleteSelectedMessages, selectCurrentChat, selectUser } from '../../modules/selectors'; import { selectCanDeleteSelectedMessages, selectCurrentChat, selectUser } from '../../modules/selectors';
import { import {
@ -14,7 +12,6 @@ import {
isChatSuperGroup, isChatSuperGroup,
} from '../../modules/helpers'; } from '../../modules/helpers';
import renderText from '../common/helpers/renderText'; import renderText from '../common/helpers/renderText';
import { pick } from '../../util/iteratees';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
import usePrevious from '../../hooks/usePrevious'; import usePrevious from '../../hooks/usePrevious';
@ -35,9 +32,7 @@ type StateProps = {
willDeleteForAll?: boolean; willDeleteForAll?: boolean;
}; };
type DispatchProps = Pick<GlobalActions, 'deleteMessages' | 'exitMessageSelectMode' | 'deleteScheduledMessages'>; const DeleteSelectedMessageModal: FC<OwnProps & StateProps> = ({
const DeleteSelectedMessageModal: FC<OwnProps & StateProps & DispatchProps> = ({
isOpen, isOpen,
isSchedule, isSchedule,
selectedMessageIds, selectedMessageIds,
@ -46,10 +41,13 @@ const DeleteSelectedMessageModal: FC<OwnProps & StateProps & DispatchProps> = ({
willDeleteForCurrentUserOnly, willDeleteForCurrentUserOnly,
willDeleteForAll, willDeleteForAll,
onClose, onClose,
deleteMessages,
deleteScheduledMessages,
exitMessageSelectMode,
}) => { }) => {
const {
deleteMessages,
deleteScheduledMessages,
exitMessageSelectMode,
} = getDispatch();
const prevIsOpen = usePrevious(isOpen); const prevIsOpen = usePrevious(isOpen);
const handleDeleteMessageForAll = useCallback(() => { const handleDeleteMessageForAll = useCallback(() => {
@ -130,9 +128,4 @@ export default memo(withGlobal<OwnProps>(
willDeleteForAll, willDeleteForAll,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'deleteMessages',
'deleteScheduledMessages',
'exitMessageSelectMode',
]),
)(DeleteSelectedMessageModal)); )(DeleteSelectedMessageModal));

View File

@ -5,14 +5,13 @@ import React, {
useCallback, useCallback,
useState, useState,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { GlobalActions, MessageListType } from '../../global/types'; import { MessageListType } from '../../global/types';
import { MAIN_THREAD_ID } from '../../api/types'; import { MAIN_THREAD_ID } from '../../api/types';
import { IAnchorPosition } from '../../types'; import { IAnchorPosition } from '../../types';
import { ARE_CALLS_SUPPORTED, IS_SINGLE_COLUMN_LAYOUT } from '../../util/environment'; import { ARE_CALLS_SUPPORTED, IS_SINGLE_COLUMN_LAYOUT } from '../../util/environment';
import { pick } from '../../util/iteratees';
import { import {
isChatBasicGroup, isChatChannel, isChatSuperGroup, isUserId, isChatBasicGroup, isChatChannel, isChatSuperGroup, isUserId,
} from '../../modules/helpers'; } from '../../modules/helpers';
@ -52,14 +51,10 @@ interface StateProps {
canCreateVoiceChat?: boolean; canCreateVoiceChat?: boolean;
} }
type DispatchProps = Pick<GlobalActions, (
'joinChannel' | 'sendBotCommand' | 'openLocalTextSearch' | 'restartBot' | 'openCallFallbackConfirm'
)>;
// Chrome breaks layout when focusing input during transition // Chrome breaks layout when focusing input during transition
const SEARCH_FOCUS_DELAY_MS = 400; const SEARCH_FOCUS_DELAY_MS = 400;
const HeaderActions: FC<OwnProps & StateProps & DispatchProps> = ({ const HeaderActions: FC<OwnProps & StateProps> = ({
chatId, chatId,
threadId, threadId,
noMenu, noMenu,
@ -75,12 +70,15 @@ const HeaderActions: FC<OwnProps & StateProps & DispatchProps> = ({
canCreateVoiceChat, canCreateVoiceChat,
isRightColumnShown, isRightColumnShown,
canExpandActions, canExpandActions,
joinChannel,
sendBotCommand,
openLocalTextSearch,
restartBot,
openCallFallbackConfirm,
}) => { }) => {
const {
joinChannel,
sendBotCommand,
openLocalTextSearch,
restartBot,
openCallFallbackConfirm,
} = getDispatch();
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
const menuButtonRef = useRef<HTMLButtonElement>(null); const menuButtonRef = useRef<HTMLButtonElement>(null);
const [isMenuOpen, setIsMenuOpen] = useState(false); const [isMenuOpen, setIsMenuOpen] = useState(false);
@ -275,7 +273,4 @@ export default memo(withGlobal<OwnProps>(
canCreateVoiceChat, canCreateVoiceChat,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'joinChannel', 'sendBotCommand', 'openLocalTextSearch', 'restartBot', 'openCallFallbackConfirm',
]),
)(HeaderActions)); )(HeaderActions));

View File

@ -1,9 +1,8 @@
import React, { import React, {
FC, memo, useCallback, useEffect, useState, FC, memo, useCallback, useEffect, useState,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { GlobalActions } from '../../global/types';
import { ApiChat } from '../../api/types'; import { ApiChat } from '../../api/types';
import { IAnchorPosition } from '../../types'; import { IAnchorPosition } from '../../types';
@ -12,7 +11,6 @@ import { disableScrolling, enableScrolling } from '../../util/scrollLock';
import { import {
selectChat, selectNotifySettings, selectNotifyExceptions, selectUser, selectChat, selectNotifySettings, selectNotifyExceptions, selectUser,
} from '../../modules/selectors'; } from '../../modules/selectors';
import { pick } from '../../util/iteratees';
import { import {
isUserId, getCanDeleteChat, selectIsChatMuted, getCanAddContact, isUserId, getCanDeleteChat, selectIsChatMuted, getCanAddContact,
} from '../../modules/helpers'; } from '../../modules/helpers';
@ -26,11 +24,6 @@ import DeleteChatModal from '../common/DeleteChatModal';
import './HeaderMenuContainer.scss'; import './HeaderMenuContainer.scss';
type DispatchProps = Pick<GlobalActions, (
'updateChatMutedState' | 'enterMessageSelectMode' | 'sendBotCommand' | 'restartBot' | 'openLinkedChat' |
'joinGroupCall' | 'createGroupCall' | 'addContact' | 'openCallFallbackConfirm'
)>;
export type OwnProps = { export type OwnProps = {
chatId: string; chatId: string;
threadId: number; threadId: number;
@ -62,7 +55,7 @@ type StateProps = {
hasLinkedChat?: boolean; hasLinkedChat?: boolean;
}; };
const HeaderMenuContainer: FC<OwnProps & StateProps & DispatchProps> = ({ const HeaderMenuContainer: FC<OwnProps & StateProps> = ({
chatId, chatId,
isOpen, isOpen,
withExtraActions, withExtraActions,
@ -87,16 +80,19 @@ const HeaderMenuContainer: FC<OwnProps & StateProps & DispatchProps> = ({
onSearchClick, onSearchClick,
onClose, onClose,
onCloseAnimationEnd, onCloseAnimationEnd,
updateChatMutedState,
enterMessageSelectMode,
sendBotCommand,
restartBot,
joinGroupCall,
createGroupCall,
openLinkedChat,
addContact,
openCallFallbackConfirm,
}) => { }) => {
const {
updateChatMutedState,
enterMessageSelectMode,
sendBotCommand,
restartBot,
joinGroupCall,
createGroupCall,
openLinkedChat,
addContact,
openCallFallbackConfirm,
} = getDispatch();
const [isMenuOpen, setIsMenuOpen] = useState(true); const [isMenuOpen, setIsMenuOpen] = useState(true);
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
const { x, y } = anchor; const { x, y } = anchor;
@ -313,15 +309,4 @@ export default memo(withGlobal<OwnProps>(
hasLinkedChat: Boolean(chat?.fullInfo?.linkedChatId), hasLinkedChat: Boolean(chat?.fullInfo?.linkedChatId),
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'updateChatMutedState',
'enterMessageSelectMode',
'sendBotCommand',
'restartBot',
'joinGroupCall',
'createGroupCall',
'openLinkedChat',
'addContact',
'openCallFallbackConfirm',
]),
)(HeaderMenuContainer)); )(HeaderMenuContainer));

View File

@ -1,12 +1,12 @@
import React, { import React, {
FC, memo, useCallback, useEffect, useMemo, useRef, useState, FC, memo, useCallback, useEffect, useMemo, useRef, useState,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { getGlobal, withGlobal } from '../../lib/teact/teactn'; import { getDispatch, getGlobal, withGlobal } from '../../lib/teact/teactn';
import { import {
ApiMessage, ApiRestrictionReason, MAIN_THREAD_ID, ApiMessage, ApiRestrictionReason, MAIN_THREAD_ID,
} from '../../api/types'; } from '../../api/types';
import { GlobalActions, MessageListType } from '../../global/types'; import { MessageListType } from '../../global/types';
import { LoadMoreDirection } from '../../types'; import { LoadMoreDirection } from '../../types';
import { ANIMATION_END_DELAY, LOCAL_MESSAGE_ID_BASE, MESSAGE_LIST_SLICE } from '../../config'; import { ANIMATION_END_DELAY, LOCAL_MESSAGE_ID_BASE, MESSAGE_LIST_SLICE } from '../../config';
@ -32,7 +32,7 @@ import {
isChatWithRepliesBot, isChatWithRepliesBot,
isChatGroup, isChatGroup,
} from '../../modules/helpers'; } from '../../modules/helpers';
import { orderBy, pick } from '../../util/iteratees'; import { orderBy } from '../../util/iteratees';
import { fastRaf, debounce, onTickEnd } from '../../util/schedulers'; import { fastRaf, debounce, onTickEnd } from '../../util/schedulers';
import useLayoutEffectWithPrevDeps from '../../hooks/useLayoutEffectWithPrevDeps'; import useLayoutEffectWithPrevDeps from '../../hooks/useLayoutEffectWithPrevDeps';
import useEffectWithPrevDeps from '../../hooks/useEffectWithPrevDeps'; import useEffectWithPrevDeps from '../../hooks/useEffectWithPrevDeps';
@ -91,8 +91,6 @@ type StateProps = {
hasLinkedChat?: boolean; hasLinkedChat?: boolean;
}; };
type DispatchProps = Pick<GlobalActions, 'loadViewportMessages' | 'setScrollOffset' | 'openHistoryCalendar'>;
const BOTTOM_THRESHOLD = 20; const BOTTOM_THRESHOLD = 20;
const UNREAD_DIVIDER_TOP = 10; const UNREAD_DIVIDER_TOP = 10;
const UNREAD_DIVIDER_TOP_WITH_TOOLS = 60; const UNREAD_DIVIDER_TOP_WITH_TOOLS = 60;
@ -104,7 +102,7 @@ const UNREAD_DIVIDER_CLASS = 'unread-divider';
const runDebouncedForScroll = debounce((cb) => cb(), SCROLL_DEBOUNCE, false); const runDebouncedForScroll = debounce((cb) => cb(), SCROLL_DEBOUNCE, false);
const MessageList: FC<OwnProps & StateProps & DispatchProps> = ({ const MessageList: FC<OwnProps & StateProps> = ({
chatId, chatId,
threadId, threadId,
type, type,
@ -129,15 +127,14 @@ const MessageList: FC<OwnProps & StateProps & DispatchProps> = ({
restrictionReason, restrictionReason,
focusingId, focusingId,
isSelectModeActive, isSelectModeActive,
loadViewportMessages,
setScrollOffset,
lastMessage, lastMessage,
botDescription, botDescription,
threadTopMessageId, threadTopMessageId,
hasLinkedChat, hasLinkedChat,
withBottomShift, withBottomShift,
openHistoryCalendar,
}) => { }) => {
const { loadViewportMessages, setScrollOffset } = getDispatch();
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
@ -530,7 +527,6 @@ const MessageList: FC<OwnProps & StateProps & DispatchProps> = ({
noAppearanceAnimation={!messageGroups || !shouldAnimateAppearanceRef.current} noAppearanceAnimation={!messageGroups || !shouldAnimateAppearanceRef.current}
onFabToggle={onFabToggle} onFabToggle={onFabToggle}
onNotchToggle={onNotchToggle} onNotchToggle={onNotchToggle}
openHistoryCalendar={openHistoryCalendar}
/> />
) : ( ) : (
<Loading color="white" /> <Loading color="white" />
@ -602,9 +598,4 @@ export default memo(withGlobal<OwnProps>(
...(withLastMessageWhenPreloading && { lastMessage }), ...(withLastMessageWhenPreloading && { lastMessage }),
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'loadViewportMessages',
'setScrollOffset',
'openHistoryCalendar',
]),
)(MessageList)); )(MessageList));

View File

@ -16,6 +16,7 @@ import useMessageObservers from './hooks/useMessageObservers';
import Message from './message/Message'; import Message from './message/Message';
import ActionMessage from './ActionMessage'; import ActionMessage from './ActionMessage';
import { getDispatch } from '../../lib/teact/teactn';
interface OwnProps { interface OwnProps {
messageIds: number[]; messageIds: number[];
@ -39,7 +40,6 @@ interface OwnProps {
noAppearanceAnimation: boolean; noAppearanceAnimation: boolean;
onFabToggle: AnyToVoidFunction; onFabToggle: AnyToVoidFunction;
onNotchToggle: AnyToVoidFunction; onNotchToggle: AnyToVoidFunction;
openHistoryCalendar: Function;
} }
const UNREAD_DIVIDER_CLASS = 'unread-divider'; const UNREAD_DIVIDER_CLASS = 'unread-divider';
@ -66,8 +66,9 @@ const MessageListContent: FC<OwnProps> = ({
noAppearanceAnimation, noAppearanceAnimation,
onFabToggle, onFabToggle,
onNotchToggle, onNotchToggle,
openHistoryCalendar,
}) => { }) => {
const { openHistoryCalendar } = getDispatch();
const { const {
observeIntersectionForMedia, observeIntersectionForMedia,
observeIntersectionForReading, observeIntersectionForReading,

View File

@ -1,9 +1,9 @@
import React, { import React, {
FC, memo, useCallback, useEffect, FC, memo, useCallback, useEffect,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { GlobalActions, MessageListType } from '../../global/types'; import { MessageListType } from '../../global/types';
import { import {
selectCanDeleteSelectedMessages, selectCanDeleteSelectedMessages,
@ -12,7 +12,6 @@ import {
selectCurrentMessageList, selectCurrentMessageList,
selectSelectedMessagesCount, selectSelectedMessagesCount,
} from '../../modules/selectors'; } from '../../modules/selectors';
import { pick } from '../../util/iteratees';
import useFlag from '../../hooks/useFlag'; import useFlag from '../../hooks/useFlag';
import captureKeyboardListeners from '../../util/captureKeyboardListeners'; import captureKeyboardListeners from '../../util/captureKeyboardListeners';
import buildClassName from '../../util/buildClassName'; import buildClassName from '../../util/buildClassName';
@ -41,11 +40,7 @@ type StateProps = {
selectedMessageIds?: number[]; selectedMessageIds?: number[];
}; };
type DispatchProps = Pick<GlobalActions, ( const MessageSelectToolbar: FC<OwnProps & StateProps> = ({
'exitMessageSelectMode' | 'openForwardMenuForSelectedMessages' | 'downloadSelectedMessages'
)>;
const MessageSelectToolbar: FC<OwnProps & StateProps & DispatchProps> = ({
canPost, canPost,
isActive, isActive,
messageListType, messageListType,
@ -55,10 +50,13 @@ const MessageSelectToolbar: FC<OwnProps & StateProps & DispatchProps> = ({
canReportMessages, canReportMessages,
canDownloadMessages, canDownloadMessages,
selectedMessageIds, selectedMessageIds,
exitMessageSelectMode,
openForwardMenuForSelectedMessages,
downloadSelectedMessages,
}) => { }) => {
const {
exitMessageSelectMode,
openForwardMenuForSelectedMessages,
downloadSelectedMessages,
} = getDispatch();
const [isDeleteModalOpen, openDeleteModal, closeDeleteModal] = useFlag(); const [isDeleteModalOpen, openDeleteModal, closeDeleteModal] = useFlag();
const [isReportModalOpen, openReportModal, closeReportModal] = useFlag(); const [isReportModalOpen, openReportModal, closeReportModal] = useFlag();
@ -171,7 +169,4 @@ export default memo(withGlobal<OwnProps>(
selectedMessageIds, selectedMessageIds,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'exitMessageSelectMode', 'openForwardMenuForSelectedMessages', 'downloadSelectedMessages',
]),
)(MessageSelectToolbar)); )(MessageSelectToolbar));

View File

@ -1,10 +1,10 @@
import React, { import React, {
FC, useEffect, useState, memo, useMemo, useCallback, FC, useEffect, useState, memo, useMemo, useCallback,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { ApiChatBannedRights, MAIN_THREAD_ID } from '../../api/types'; import { ApiChatBannedRights, MAIN_THREAD_ID } from '../../api/types';
import { GlobalActions, MessageListType, MessageList as GlobalMessageList } from '../../global/types'; import { MessageListType, MessageList as GlobalMessageList } from '../../global/types';
import { ThemeKey } from '../../types'; import { ThemeKey } from '../../types';
import { import {
@ -43,7 +43,6 @@ import {
getCanPostInChat, getMessageSendingRestrictionReason, isChatChannel, isChatSuperGroup, isUserId, getCanPostInChat, getMessageSendingRestrictionReason, isChatChannel, isChatSuperGroup, isUserId,
} from '../../modules/helpers'; } from '../../modules/helpers';
import captureEscKeyListener from '../../util/captureEscKeyListener'; import captureEscKeyListener from '../../util/captureEscKeyListener';
import { pick } from '../../util/iteratees';
import buildClassName from '../../util/buildClassName'; import buildClassName from '../../util/buildClassName';
import { createMessageHash } from '../../util/routing'; import { createMessageHash } from '../../util/routing';
import useCustomBackground from '../../hooks/useCustomBackground'; import useCustomBackground from '../../hooks/useCustomBackground';
@ -104,18 +103,13 @@ type StateProps = {
canRestartBot?: boolean; canRestartBot?: boolean;
}; };
type DispatchProps = Pick<GlobalActions, (
'openChat' | 'unpinAllMessages' | 'loadUser' | 'closeLocalTextSearch' | 'exitMessageSelectMode' |
'closePaymentModal' | 'clearReceipt' | 'joinChannel' | 'sendBotCommand' | 'restartBot'
)>;
const CLOSE_ANIMATION_DURATION = IS_SINGLE_COLUMN_LAYOUT ? 450 + ANIMATION_END_DELAY : undefined; const CLOSE_ANIMATION_DURATION = IS_SINGLE_COLUMN_LAYOUT ? 450 + ANIMATION_END_DELAY : undefined;
function isImage(item: DataTransferItem) { function isImage(item: DataTransferItem) {
return item.kind === 'file' && item.type && SUPPORTED_IMAGE_CONTENT_TYPES.has(item.type); return item.kind === 'file' && item.type && SUPPORTED_IMAGE_CONTENT_TYPES.has(item.type);
} }
const MiddleColumn: FC<StateProps & DispatchProps> = ({ const MiddleColumn: FC<StateProps> = ({
chatId, chatId,
threadId, threadId,
messageListType, messageListType,
@ -146,17 +140,20 @@ const MiddleColumn: FC<StateProps & DispatchProps> = ({
canSubscribe, canSubscribe,
canStartBot, canStartBot,
canRestartBot, canRestartBot,
openChat,
unpinAllMessages,
loadUser,
closeLocalTextSearch,
exitMessageSelectMode,
closePaymentModal,
clearReceipt,
joinChannel,
sendBotCommand,
restartBot,
}) => { }) => {
const {
openChat,
unpinAllMessages,
loadUser,
closeLocalTextSearch,
exitMessageSelectMode,
closePaymentModal,
clearReceipt,
joinChannel,
sendBotCommand,
restartBot,
} = getDispatch();
const { width: windowWidth } = useWindowSize(); const { width: windowWidth } = useWindowSize();
const lang = useLang(); const lang = useLang();
@ -588,10 +585,6 @@ export default memo(withGlobal(
canRestartBot, canRestartBot,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'openChat', 'unpinAllMessages', 'loadUser', 'closeLocalTextSearch', 'exitMessageSelectMode',
'closePaymentModal', 'clearReceipt', 'joinChannel', 'sendBotCommand', 'restartBot',
]),
)(MiddleColumn)); )(MiddleColumn));
function useIsReady( function useIsReady(

View File

@ -1,10 +1,10 @@
import React, { import React, {
FC, useCallback, useMemo, memo, useEffect, useRef, useState, FC, useCallback, useMemo, memo, useEffect, useRef, useState,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { getGlobal, withGlobal } from '../../lib/teact/teactn'; import { getDispatch, getGlobal, withGlobal } from '../../lib/teact/teactn';
import cycleRestrict from '../../util/cycleRestrict'; import cycleRestrict from '../../util/cycleRestrict';
import { GlobalActions, MessageListType } from '../../global/types'; import { MessageListType } from '../../global/types';
import { import {
ApiMessage, ApiMessage,
ApiChat, ApiChat,
@ -48,7 +48,6 @@ import useEnsureMessage from '../../hooks/useEnsureMessage';
import useWindowSize from '../../hooks/useWindowSize'; import useWindowSize from '../../hooks/useWindowSize';
import useShowTransition from '../../hooks/useShowTransition'; import useShowTransition from '../../hooks/useShowTransition';
import useCurrentOrPrev from '../../hooks/useCurrentOrPrev'; import useCurrentOrPrev from '../../hooks/useCurrentOrPrev';
import { pick } from '../../util/iteratees';
import { formatIntegerCompact } from '../../util/textFormat'; import { formatIntegerCompact } from '../../util/textFormat';
import buildClassName from '../../util/buildClassName'; import buildClassName from '../../util/buildClassName';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
@ -96,12 +95,7 @@ type StateProps = {
connectionState?: ApiUpdateConnectionStateType; connectionState?: ApiUpdateConnectionStateType;
}; };
type DispatchProps = Pick<GlobalActions, ( const MiddleHeader: FC<OwnProps & StateProps> = ({
'openChatWithInfo' | 'pinMessage' | 'focusMessage' | 'openChat' | 'openPreviousChat' | 'loadPinnedMessages' |
'toggleLeftColumn' | 'exitMessageSelectMode'
)>;
const MiddleHeader: FC<OwnProps & StateProps & DispatchProps> = ({
chatId, chatId,
threadId, threadId,
messageListType, messageListType,
@ -124,15 +118,18 @@ const MiddleHeader: FC<OwnProps & StateProps & DispatchProps> = ({
shouldSkipHistoryAnimations, shouldSkipHistoryAnimations,
currentTransitionKey, currentTransitionKey,
connectionState, connectionState,
openChatWithInfo,
pinMessage,
focusMessage,
openChat,
openPreviousChat,
loadPinnedMessages,
toggleLeftColumn,
exitMessageSelectMode,
}) => { }) => {
const {
openChatWithInfo,
pinMessage,
focusMessage,
openChat,
openPreviousChat,
loadPinnedMessages,
toggleLeftColumn,
exitMessageSelectMode,
} = getDispatch();
const lang = useLang(); const lang = useLang();
const isBackButtonActive = useRef(true); const isBackButtonActive = useRef(true);
@ -523,14 +520,4 @@ export default memo(withGlobal<OwnProps>(
return state; return state;
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'openChatWithInfo',
'pinMessage',
'focusMessage',
'openChat',
'openPreviousChat',
'loadPinnedMessages',
'toggleLeftColumn',
'exitMessageSelectMode',
]),
)(MiddleHeader)); )(MiddleHeader));

View File

@ -1,14 +1,12 @@
import React, { import React, {
FC, memo, useCallback, useEffect, useRef, useState, useLayoutEffect, FC, memo, useCallback, useEffect, useRef, useState, useLayoutEffect,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { ApiChat } from '../../api/types'; import { ApiChat } from '../../api/types';
import { GlobalActions } from '../../global/types';
import { debounce } from '../../util/schedulers'; import { debounce } from '../../util/schedulers';
import { selectCurrentTextSearch, selectCurrentChat } from '../../modules/selectors'; import { selectCurrentTextSearch, selectCurrentChat } from '../../modules/selectors';
import { pick } from '../../util/iteratees';
import { getDayStartAt } from '../../util/dateFormat'; import { getDayStartAt } from '../../util/dateFormat';
import Button from '../ui/Button'; import Button from '../ui/Button';
@ -29,26 +27,24 @@ type StateProps = {
isHistoryCalendarOpen?: boolean; isHistoryCalendarOpen?: boolean;
}; };
type DispatchProps = Pick<GlobalActions, (
'setLocalTextSearchQuery' | 'searchTextMessagesLocal' | 'closeLocalTextSearch' | 'openHistoryCalendar' |
'focusMessage'
)>;
const runDebouncedForSearch = debounce((cb) => cb(), 200, false); const runDebouncedForSearch = debounce((cb) => cb(), 200, false);
const MobileSearchFooter: FC<StateProps & DispatchProps> = ({ const MobileSearchFooter: FC<StateProps> = ({
isActive, isActive,
chat, chat,
query, query,
totalCount, totalCount,
foundIds, foundIds,
isHistoryCalendarOpen, isHistoryCalendarOpen,
setLocalTextSearchQuery,
searchTextMessagesLocal,
focusMessage,
closeLocalTextSearch,
openHistoryCalendar,
}) => { }) => {
const {
setLocalTextSearchQuery,
searchTextMessagesLocal,
focusMessage,
closeLocalTextSearch,
openHistoryCalendar,
} = getDispatch();
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
const inputRef = useRef<HTMLInputElement>(null); const inputRef = useRef<HTMLInputElement>(null);
const [focusedIndex, setFocusedIndex] = useState(0); const [focusedIndex, setFocusedIndex] = useState(0);
@ -218,11 +214,4 @@ export default memo(withGlobal<OwnProps>(
isHistoryCalendarOpen: Boolean(global.historyCalendarSelectedAt), isHistoryCalendarOpen: Boolean(global.historyCalendarSelectedAt),
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'setLocalTextSearchQuery',
'searchTextMessagesLocal',
'focusMessage',
'closeLocalTextSearch',
'openHistoryCalendar',
]),
)(MobileSearchFooter)); )(MobileSearchFooter));

View File

@ -1,15 +1,14 @@
import React, { import React, {
FC, useCallback, memo, useRef, FC, useCallback, memo, useRef,
} from '../../lib/teact/teact'; } from '../../lib/teact/teact';
import { withGlobal } from '../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { GlobalActions, MessageListType } from '../../global/types'; import { MessageListType } from '../../global/types';
import { MAIN_THREAD_ID } from '../../api/types'; import { MAIN_THREAD_ID } from '../../api/types';
import { selectChat, selectCurrentMessageList } from '../../modules/selectors'; import { selectChat, selectCurrentMessageList } from '../../modules/selectors';
import { formatIntegerCompact } from '../../util/textFormat'; import { formatIntegerCompact } from '../../util/textFormat';
import buildClassName from '../../util/buildClassName'; import buildClassName from '../../util/buildClassName';
import { pick } from '../../util/iteratees';
import fastSmoothScroll from '../../util/fastSmoothScroll'; import fastSmoothScroll from '../../util/fastSmoothScroll';
import useLang from '../../hooks/useLang'; import useLang from '../../hooks/useLang';
@ -28,18 +27,17 @@ type StateProps = {
unreadCount?: number; unreadCount?: number;
}; };
type DispatchProps = Pick<GlobalActions, 'focusNextReply'>;
const FOCUS_MARGIN = 20; const FOCUS_MARGIN = 20;
const ScrollDownButton: FC<OwnProps & StateProps & DispatchProps> = ({ const ScrollDownButton: FC<OwnProps & StateProps> = ({
isShown, isShown,
canPost, canPost,
messageListType, messageListType,
unreadCount, unreadCount,
withExtraShift, withExtraShift,
focusNextReply,
}) => { }) => {
const { focusNextReply } = getDispatch();
const lang = useLang(); const lang = useLang();
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
const elementRef = useRef<HTMLDivElement>(null); const elementRef = useRef<HTMLDivElement>(null);
@ -104,5 +102,4 @@ export default memo(withGlobal<OwnProps>(
unreadCount: chat && threadId === MAIN_THREAD_ID && messageListType === 'thread' ? chat.unreadCount : undefined, unreadCount: chat && threadId === MAIN_THREAD_ID && messageListType === 'thread' ? chat.unreadCount : undefined,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, ['focusNextReply']),
)(ScrollDownButton)); )(ScrollDownButton));

View File

@ -1,17 +1,15 @@
import React, { FC, memo, useCallback } from '../../../lib/teact/teact'; import React, { FC, memo, useCallback } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { ApiBotCommand } from '../../../api/types'; import { ApiBotCommand } from '../../../api/types';
import { IS_SINGLE_COLUMN_LAYOUT, IS_TOUCH_ENV } from '../../../util/environment'; import { IS_SINGLE_COLUMN_LAYOUT, IS_TOUCH_ENV } from '../../../util/environment';
import { pick } from '../../../util/iteratees';
import useMouseInside from '../../../hooks/useMouseInside'; import useMouseInside from '../../../hooks/useMouseInside';
import Menu from '../../ui/Menu'; import Menu from '../../ui/Menu';
import BotCommand from './BotCommand'; import BotCommand from './BotCommand';
import './BotCommandMenu.scss'; import './BotCommandMenu.scss';
import { getDispatch } from '../../../lib/teact/teactn';
export type OwnProps = { export type OwnProps = {
isOpen: boolean; isOpen: boolean;
@ -19,11 +17,11 @@ export type OwnProps = {
onClose: NoneToVoidFunction; onClose: NoneToVoidFunction;
}; };
type DispatchProps = Pick<GlobalActions, 'sendBotCommand'>; const BotCommandMenu: FC<OwnProps> = ({
isOpen, botCommands, onClose,
const BotCommandMenu: FC<OwnProps & DispatchProps> = ({
isOpen, botCommands, onClose, sendBotCommand,
}) => { }) => {
const { sendBotCommand } = getDispatch();
const [handleMouseEnter, handleMouseLeave] = useMouseInside(isOpen, onClose, undefined, IS_SINGLE_COLUMN_LAYOUT); const [handleMouseEnter, handleMouseLeave] = useMouseInside(isOpen, onClose, undefined, IS_SINGLE_COLUMN_LAYOUT);
const handleClick = useCallback((botCommand: ApiBotCommand) => { const handleClick = useCallback((botCommand: ApiBotCommand) => {
@ -57,7 +55,4 @@ const BotCommandMenu: FC<OwnProps & DispatchProps> = ({
); );
}; };
export default memo(withGlobal<OwnProps>( export default memo(BotCommandMenu);
undefined,
(setGlobal, actions): DispatchProps => pick(actions, ['sendBotCommand']),
)(BotCommandMenu));

View File

@ -1,12 +1,10 @@
import React, { import React, {
FC, useCallback, useEffect, useRef, memo, FC, useCallback, useEffect, useRef, memo,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { ApiBotCommand, ApiUser } from '../../../api/types'; import { ApiBotCommand, ApiUser } from '../../../api/types';
import { GlobalActions } from '../../../global/types';
import { pick } from '../../../util/iteratees';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
import setTooltipItemVisible from '../../../util/setTooltipItemVisible'; import setTooltipItemVisible from '../../../util/setTooltipItemVisible';
import useShowTransition from '../../../hooks/useShowTransition'; import useShowTransition from '../../../hooks/useShowTransition';
@ -29,17 +27,16 @@ type StateProps = {
usersById: Record<string, ApiUser>; usersById: Record<string, ApiUser>;
}; };
type DispatchProps = Pick<GlobalActions, 'sendBotCommand'>; const BotCommandTooltip: FC<OwnProps & StateProps> = ({
const BotCommandTooltip: FC<OwnProps & StateProps & DispatchProps> = ({
usersById, usersById,
isOpen, isOpen,
withUsername, withUsername,
botCommands, botCommands,
onClick, onClick,
onClose, onClose,
sendBotCommand,
}) => { }) => {
const { sendBotCommand } = getDispatch();
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
const { shouldRender, transitionClassNames } = useShowTransition(isOpen, undefined, undefined, false); const { shouldRender, transitionClassNames } = useShowTransition(isOpen, undefined, undefined, false);
@ -102,5 +99,4 @@ export default memo(withGlobal<OwnProps>(
(global): StateProps => ({ (global): StateProps => ({
usersById: global.users.byId, usersById: global.users.byId,
}), }),
(setGlobal, actions): DispatchProps => pick(actions, ['sendBotCommand']),
)(BotCommandTooltip)); )(BotCommandTooltip));

View File

@ -1,11 +1,9 @@
import React, { FC, memo, useEffect } from '../../../lib/teact/teact'; import React, { FC, memo, useEffect } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { ApiMessage } from '../../../api/types'; import { ApiMessage } from '../../../api/types';
import { IS_TOUCH_ENV } from '../../../util/environment'; import { IS_TOUCH_ENV } from '../../../util/environment';
import { pick } from '../../../util/iteratees';
import { selectChatMessage, selectCurrentMessageList } from '../../../modules/selectors'; import { selectChatMessage, selectCurrentMessageList } from '../../../modules/selectors';
import useMouseInside from '../../../hooks/useMouseInside'; import useMouseInside from '../../../hooks/useMouseInside';
import useFlag from '../../../hooks/useFlag'; import useFlag from '../../../hooks/useFlag';
@ -25,11 +23,11 @@ type StateProps = {
message?: ApiMessage; message?: ApiMessage;
}; };
type DispatchProps = Pick<GlobalActions, ('clickInlineButton')>; const BotKeyboardMenu: FC<OwnProps & StateProps> = ({
isOpen, message, onClose,
const BotKeyboardMenu: FC<OwnProps & StateProps & DispatchProps> = ({
isOpen, message, onClose, clickInlineButton,
}) => { }) => {
const { clickInlineButton } = getDispatch();
const [handleMouseEnter, handleMouseLeave] = useMouseInside(isOpen, onClose); const [handleMouseEnter, handleMouseLeave] = useMouseInside(isOpen, onClose);
const { isKeyboardSingleUse } = message || {}; const { isKeyboardSingleUse } = message || {};
const [forceOpen, markForceOpen, unmarkForceOpen] = useFlag(true); const [forceOpen, markForceOpen, unmarkForceOpen] = useFlag(true);
@ -87,7 +85,4 @@ export default memo(withGlobal<OwnProps>(
return { message: selectChatMessage(global, chatId, messageId) }; return { message: selectChatMessage(global, chatId, messageId) };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'clickInlineButton',
]),
)(BotKeyboardMenu)); )(BotKeyboardMenu));

View File

@ -1,9 +1,9 @@
import React, { import React, {
FC, memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, FC, memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions, GlobalState, MessageListType } from '../../../global/types'; import { GlobalState, MessageListType } from '../../../global/types';
import { import {
ApiAttachment, ApiAttachment,
ApiBotInlineResult, ApiBotInlineResult,
@ -52,7 +52,6 @@ import buildAttachment from './helpers/buildAttachment';
import renderText from '../../common/helpers/renderText'; import renderText from '../../common/helpers/renderText';
import insertHtmlInSelection from '../../../util/insertHtmlInSelection'; import insertHtmlInSelection from '../../../util/insertHtmlInSelection';
import deleteLastCharacterOutsideSelection from '../../../util/deleteLastCharacterOutsideSelection'; import deleteLastCharacterOutsideSelection from '../../../util/deleteLastCharacterOutsideSelection';
import { pick } from '../../../util/iteratees';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
import windowSize from '../../../util/windowSize'; import windowSize from '../../../util/windowSize';
import { isSelectionInsideInput } from './helpers/selection'; import { isSelectionInsideInput } from './helpers/selection';
@ -142,13 +141,6 @@ type StateProps =
} }
& Pick<GlobalState, 'connectionState'>; & Pick<GlobalState, 'connectionState'>;
type DispatchProps = Pick<GlobalActions, (
'sendMessage' | 'editMessage' | 'saveDraft' | 'forwardMessages' |
'clearDraft' | 'showDialog' | 'setStickerSearchQuery' | 'setGifSearchQuery' |
'openPollModal' | 'closePollModal' | 'loadScheduledHistory' | 'openChat' |
'addRecentEmoji' | 'sendInlineBotResult'
)>;
enum MainButtonState { enum MainButtonState {
Send = 'send', Send = 'send',
Record = 'record', Record = 'record',
@ -167,7 +159,7 @@ const SENDING_ANIMATION_DURATION = 350;
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
const APPENDIX = '<svg width="9" height="20" xmlns="http://www.w3.org/2000/svg"><defs><filter x="-50%" y="-14.7%" width="200%" height="141.2%" filterUnits="objectBoundingBox" id="a"><feOffset dy="1" in="SourceAlpha" result="shadowOffsetOuter1"/><feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"/><feColorMatrix values="0 0 0 0 0.0621962482 0 0 0 0 0.138574144 0 0 0 0 0.185037364 0 0 0 0.15 0" in="shadowBlurOuter1"/></filter></defs><g fill="none" fill-rule="evenodd"><path d="M6 17H0V0c.193 2.84.876 5.767 2.05 8.782.904 2.325 2.446 4.485 4.625 6.48A1 1 0 016 17z" fill="#000" filter="url(#a)"/><path d="M6 17H0V0c.193 2.84.876 5.767 2.05 8.782.904 2.325 2.446 4.485 4.625 6.48A1 1 0 016 17z" fill="#FFF" class="corner"/></g></svg>'; const APPENDIX = '<svg width="9" height="20" xmlns="http://www.w3.org/2000/svg"><defs><filter x="-50%" y="-14.7%" width="200%" height="141.2%" filterUnits="objectBoundingBox" id="a"><feOffset dy="1" in="SourceAlpha" result="shadowOffsetOuter1"/><feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"/><feColorMatrix values="0 0 0 0 0.0621962482 0 0 0 0 0.138574144 0 0 0 0 0.185037364 0 0 0 0.15 0" in="shadowBlurOuter1"/></filter></defs><g fill="none" fill-rule="evenodd"><path d="M6 17H0V0c.193 2.84.876 5.767 2.05 8.782.904 2.325 2.446 4.485 4.625 6.48A1 1 0 016 17z" fill="#000" filter="url(#a)"/><path d="M6 17H0V0c.193 2.84.876 5.767 2.05 8.782.904 2.325 2.446 4.485 4.625 6.48A1 1 0 016 17z" fill="#FFF" class="corner"/></g></svg>';
const Composer: FC<OwnProps & StateProps & DispatchProps> = ({ const Composer: FC<OwnProps & StateProps> = ({
dropAreaState, dropAreaState,
shouldSchedule, shouldSchedule,
canScheduleUntilOnline, canScheduleUntilOnline,
@ -205,21 +197,22 @@ const Composer: FC<OwnProps & StateProps & DispatchProps> = ({
isInlineBotLoading, isInlineBotLoading,
botCommands, botCommands,
chatBotCommands, chatBotCommands,
sendMessage,
editMessage,
saveDraft,
clearDraft,
showDialog,
setStickerSearchQuery,
setGifSearchQuery,
forwardMessages,
openPollModal,
closePollModal,
loadScheduledHistory,
openChat,
addRecentEmoji,
sendInlineBotResult,
}) => { }) => {
const {
sendMessage,
clearDraft,
showDialog,
setStickerSearchQuery,
setGifSearchQuery,
forwardMessages,
openPollModal,
closePollModal,
loadScheduledHistory,
openChat,
addRecentEmoji,
sendInlineBotResult,
} = getDispatch();
const lang = useLang(); const lang = useLang();
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
@ -428,8 +421,8 @@ const Composer: FC<OwnProps & StateProps & DispatchProps> = ({
}; };
}, [chatId, resetComposer, stopRecordingVoiceRef]); }, [chatId, resetComposer, stopRecordingVoiceRef]);
const handleEditComplete = useEditing(htmlRef, setHtml, editingMessage, resetComposer, openDeleteModal, editMessage); const handleEditComplete = useEditing(htmlRef, setHtml, editingMessage, resetComposer, openDeleteModal);
useDraft(draft, chatId, threadId, html, htmlRef, setHtml, editingMessage, saveDraft, clearDraft); useDraft(draft, chatId, threadId, html, htmlRef, setHtml, editingMessage);
useClipboardPaste(insertTextAndUpdateCursor, setAttachments, editingMessage); useClipboardPaste(insertTextAndUpdateCursor, setAttachments, editingMessage);
const handleFileSelect = useCallback(async (files: File[], isQuick: boolean) => { const handleFileSelect = useCallback(async (files: File[], isQuick: boolean) => {
@ -1111,20 +1104,4 @@ export default memo(withGlobal<OwnProps>(
botCommands: chatBot && chatBot.fullInfo ? (chatBot.fullInfo.botCommands || false) : undefined, botCommands: chatBot && chatBot.fullInfo ? (chatBot.fullInfo.botCommands || false) : undefined,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'sendMessage',
'editMessage',
'saveDraft',
'clearDraft',
'showDialog',
'setStickerSearchQuery',
'setGifSearchQuery',
'forwardMessages',
'openPollModal',
'closePollModal',
'loadScheduledHistory',
'openChat',
'addRecentEmoji',
'sendInlineBotResult',
]),
)(Composer)); )(Composer));

View File

@ -1,9 +1,8 @@
import React, { import React, {
FC, memo, useCallback, useEffect, FC, memo, useCallback, useEffect,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { ApiChat, ApiMessage, ApiUser } from '../../../api/types'; import { ApiChat, ApiMessage, ApiUser } from '../../../api/types';
import { import {
@ -19,7 +18,6 @@ import {
selectEditingMessage, selectEditingMessage,
} from '../../../modules/selectors'; } from '../../../modules/selectors';
import captureEscKeyListener from '../../../util/captureEscKeyListener'; import captureEscKeyListener from '../../../util/captureEscKeyListener';
import { pick } from '../../../util/iteratees';
import useAsyncRendering from '../../right/hooks/useAsyncRendering'; import useAsyncRendering from '../../right/hooks/useAsyncRendering';
import useShowTransition from '../../../hooks/useShowTransition'; import useShowTransition from '../../../hooks/useShowTransition';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
@ -39,22 +37,23 @@ type StateProps = {
forwardedMessagesCount?: number; forwardedMessagesCount?: number;
}; };
type DispatchProps = Pick<GlobalActions, 'setReplyingToId' | 'setEditingId' | 'focusMessage' | 'exitForwardMode'>;
const FORWARD_RENDERING_DELAY = 300; const FORWARD_RENDERING_DELAY = 300;
const ComposerEmbeddedMessage: FC<StateProps & DispatchProps> = ({ const ComposerEmbeddedMessage: FC<StateProps> = ({
replyingToId, replyingToId,
editingId, editingId,
message, message,
sender, sender,
shouldAnimate, shouldAnimate,
forwardedMessagesCount, forwardedMessagesCount,
setReplyingToId,
setEditingId,
focusMessage,
exitForwardMode,
}) => { }) => {
const {
setReplyingToId,
setEditingId,
focusMessage,
exitForwardMode,
} = getDispatch();
const isShown = Boolean( const isShown = Boolean(
((replyingToId || editingId) && message) ((replyingToId || editingId) && message)
|| (sender && forwardedMessagesCount), || (sender && forwardedMessagesCount),
@ -166,10 +165,4 @@ export default memo(withGlobal(
forwardedMessagesCount: isForwarding ? forwardMessageIds!.length : undefined, forwardedMessagesCount: isForwarding ? forwardMessageIds!.length : undefined,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'setReplyingToId',
'setEditingId',
'focusMessage',
'exitForwardMode',
]),
)(ComposerEmbeddedMessage)); )(ComposerEmbeddedMessage));

View File

@ -1,15 +1,13 @@
import React, { import React, {
FC, useEffect, memo, useRef, FC, useEffect, memo, useRef,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { ApiVideo } from '../../../api/types'; import { ApiVideo } from '../../../api/types';
import { SLIDE_TRANSITION_DURATION } from '../../../config'; import { SLIDE_TRANSITION_DURATION } from '../../../config';
import { IS_TOUCH_ENV } from '../../../util/environment'; import { IS_TOUCH_ENV } from '../../../util/environment';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
import { pick } from '../../../util/iteratees';
import { useIntersectionObserver } from '../../../hooks/useIntersectionObserver'; import { useIntersectionObserver } from '../../../hooks/useIntersectionObserver';
import useAsyncRendering from '../../right/hooks/useAsyncRendering'; import useAsyncRendering from '../../right/hooks/useAsyncRendering';
@ -29,18 +27,17 @@ type StateProps = {
savedGifs?: ApiVideo[]; savedGifs?: ApiVideo[];
}; };
type DispatchProps = Pick<GlobalActions, 'loadSavedGifs'>;
const INTERSECTION_DEBOUNCE = 300; const INTERSECTION_DEBOUNCE = 300;
const GifPicker: FC<OwnProps & StateProps & DispatchProps> = ({ const GifPicker: FC<OwnProps & StateProps> = ({
className, className,
loadAndPlay, loadAndPlay,
canSendGifs, canSendGifs,
savedGifs, savedGifs,
onGifSelect, onGifSelect,
loadSavedGifs,
}) => { }) => {
const { loadSavedGifs } = getDispatch();
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
@ -88,5 +85,4 @@ export default memo(withGlobal<OwnProps>(
savedGifs: global.gifs.saved.gifs, savedGifs: global.gifs.saved.gifs,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, ['loadSavedGifs']),
)(GifPicker)); )(GifPicker));

View File

@ -1,9 +1,7 @@
import React, { import React, {
FC, memo, useCallback, useEffect, useRef, FC, memo, useCallback, useEffect, useRef,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { ApiBotInlineMediaResult, ApiBotInlineResult, ApiBotInlineSwitchPm } from '../../../api/types'; import { ApiBotInlineMediaResult, ApiBotInlineResult, ApiBotInlineSwitchPm } from '../../../api/types';
import { IAllowedAttachmentOptions } from '../../../modules/helpers'; import { IAllowedAttachmentOptions } from '../../../modules/helpers';
import { LoadMoreDirection } from '../../../types'; import { LoadMoreDirection } from '../../../types';
@ -13,7 +11,6 @@ import setTooltipItemVisible from '../../../util/setTooltipItemVisible';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
import useShowTransition from '../../../hooks/useShowTransition'; import useShowTransition from '../../../hooks/useShowTransition';
import { throttle } from '../../../util/schedulers'; import { throttle } from '../../../util/schedulers';
import { pick } from '../../../util/iteratees';
import { useIntersectionObserver } from '../../../hooks/useIntersectionObserver'; import { useIntersectionObserver } from '../../../hooks/useIntersectionObserver';
import usePrevious from '../../../hooks/usePrevious'; import usePrevious from '../../../hooks/usePrevious';
import { useKeyboardNavigation } from './hooks/useKeyboardNavigation'; import { useKeyboardNavigation } from './hooks/useKeyboardNavigation';
@ -26,6 +23,7 @@ import ListItem from '../../ui/ListItem';
import InfiniteScroll from '../../ui/InfiniteScroll'; import InfiniteScroll from '../../ui/InfiniteScroll';
import './InlineBotTooltip.scss'; import './InlineBotTooltip.scss';
import { getDispatch } from '../../../lib/teact/teactn';
const INTERSECTION_DEBOUNCE_MS = 200; const INTERSECTION_DEBOUNCE_MS = 200;
const runThrottled = throttle((cb) => cb(), 500, true); const runThrottled = throttle((cb) => cb(), 500, true);
@ -42,9 +40,7 @@ export type OwnProps = {
onClose: NoneToVoidFunction; onClose: NoneToVoidFunction;
}; };
type DispatchProps = Pick<GlobalActions, ('startBot' | 'openChat' | 'sendInlineBotResult')>; const InlineBotTooltip: FC<OwnProps> = ({
const InlineBotTooltip: FC<OwnProps & DispatchProps> = ({
isOpen, isOpen,
botId, botId,
isGallery, isGallery,
@ -52,10 +48,13 @@ const InlineBotTooltip: FC<OwnProps & DispatchProps> = ({
switchPm, switchPm,
loadMore, loadMore,
onClose, onClose,
openChat,
startBot,
onSelectResult, onSelectResult,
}) => { }) => {
const {
openChat,
startBot,
} = getDispatch();
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
const { shouldRender, transitionClassNames } = useShowTransition(isOpen, undefined, undefined, false); const { shouldRender, transitionClassNames } = useShowTransition(isOpen, undefined, undefined, false);
@ -196,9 +195,4 @@ const InlineBotTooltip: FC<OwnProps & DispatchProps> = ({
); );
}; };
export default memo(withGlobal<OwnProps>( export default memo(InlineBotTooltip);
undefined,
(setGlobal, actions): DispatchProps => pick(actions, [
'startBot', 'openChat', 'sendInlineBotResult',
]),
)(InlineBotTooltip));

View File

@ -2,9 +2,8 @@ import { ChangeEvent } from 'react';
import React, { import React, {
FC, useEffect, useRef, memo, useState, useCallback, FC, useEffect, useRef, memo, useState, useCallback,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { IAnchorPosition, ISettings } from '../../../types'; import { IAnchorPosition, ISettings } from '../../../types';
import { EDITABLE_INPUT_ID } from '../../../config'; import { EDITABLE_INPUT_ID } from '../../../config';
@ -12,7 +11,6 @@ import { selectReplyingToId } from '../../../modules/selectors';
import { debounce } from '../../../util/schedulers'; import { debounce } from '../../../util/schedulers';
import focusEditableElement from '../../../util/focusEditableElement'; import focusEditableElement from '../../../util/focusEditableElement';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
import { pick } from '../../../util/iteratees';
import { import {
IS_ANDROID, IS_EMOJI_SUPPORTED, IS_IOS, IS_SINGLE_COLUMN_LAYOUT, IS_TOUCH_ENV, IS_ANDROID, IS_EMOJI_SUPPORTED, IS_IOS, IS_SINGLE_COLUMN_LAYOUT, IS_TOUCH_ENV,
} from '../../../util/environment'; } from '../../../util/environment';
@ -56,8 +54,6 @@ type StateProps = {
messageSendKeyCombo?: ISettings['messageSendKeyCombo']; messageSendKeyCombo?: ISettings['messageSendKeyCombo'];
}; };
type DispatchProps = Pick<GlobalActions, 'editLastMessage' | 'replyToNextMessage'>;
const MAX_INPUT_HEIGHT = IS_SINGLE_COLUMN_LAYOUT ? 256 : 416; const MAX_INPUT_HEIGHT = IS_SINGLE_COLUMN_LAYOUT ? 256 : 416;
const TAB_INDEX_PRIORITY_TIMEOUT = 2000; const TAB_INDEX_PRIORITY_TIMEOUT = 2000;
const TEXT_FORMATTER_SAFE_AREA_PX = 90; const TEXT_FORMATTER_SAFE_AREA_PX = 90;
@ -77,7 +73,7 @@ function clearSelection() {
} }
} }
const MessageInput: FC<OwnProps & StateProps & DispatchProps> = ({ const MessageInput: FC<OwnProps & StateProps> = ({
id, id,
chatId, chatId,
isAttachmentModalInput, isAttachmentModalInput,
@ -94,9 +90,12 @@ const MessageInput: FC<OwnProps & StateProps & DispatchProps> = ({
replyingToId, replyingToId,
noTabCapture, noTabCapture,
messageSendKeyCombo, messageSendKeyCombo,
editLastMessage,
replyToNextMessage,
}) => { }) => {
const {
editLastMessage,
replyToNextMessage,
} = getDispatch();
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
const inputRef = useRef<HTMLDivElement>(null); const inputRef = useRef<HTMLDivElement>(null);
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
@ -420,5 +419,4 @@ export default memo(withGlobal<OwnProps>(
noTabCapture: global.isPollModalOpen || global.payment.isPaymentModalOpen, noTabCapture: global.isPollModalOpen || global.payment.isPaymentModalOpen,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, ['editLastMessage', 'replyToNextMessage']),
)(MessageInput)); )(MessageInput));

View File

@ -1,9 +1,8 @@
import React, { import React, {
FC, useState, useEffect, memo, useRef, useMemo, useCallback, FC, useState, useEffect, memo, useRef, useMemo, useCallback,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { ApiStickerSet, ApiSticker } from '../../../api/types'; import { ApiStickerSet, ApiSticker } from '../../../api/types';
import { StickerSetOrRecent } from '../../../types'; import { StickerSetOrRecent } from '../../../types';
@ -12,7 +11,6 @@ import { IS_TOUCH_ENV } from '../../../util/environment';
import { MEMO_EMPTY_ARRAY } from '../../../util/memo'; import { MEMO_EMPTY_ARRAY } from '../../../util/memo';
import fastSmoothScroll from '../../../util/fastSmoothScroll'; import fastSmoothScroll from '../../../util/fastSmoothScroll';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
import { pick } from '../../../util/iteratees';
import fastSmoothScrollHorizontal from '../../../util/fastSmoothScrollHorizontal'; import fastSmoothScrollHorizontal from '../../../util/fastSmoothScrollHorizontal';
import useAsyncRendering from '../../right/hooks/useAsyncRendering'; import useAsyncRendering from '../../right/hooks/useAsyncRendering';
import { useIntersectionObserver } from '../../../hooks/useIntersectionObserver'; import { useIntersectionObserver } from '../../../hooks/useIntersectionObserver';
@ -43,18 +41,13 @@ type StateProps = {
shouldPlay?: boolean; shouldPlay?: boolean;
}; };
type DispatchProps = Pick<GlobalActions, (
'loadStickerSets' | 'loadRecentStickers' | 'loadFavoriteStickers' |
'addRecentSticker' | 'loadAddedStickers' | 'unfaveSticker'
)>;
const SMOOTH_SCROLL_DISTANCE = 500; const SMOOTH_SCROLL_DISTANCE = 500;
const HEADER_BUTTON_WIDTH = 52; // px (including margin) const HEADER_BUTTON_WIDTH = 52; // px (including margin)
const STICKER_INTERSECTION_THROTTLE = 200; const STICKER_INTERSECTION_THROTTLE = 200;
const stickerSetIntersections: boolean[] = []; const stickerSetIntersections: boolean[] = [];
const StickerPicker: FC<OwnProps & StateProps & DispatchProps> = ({ const StickerPicker: FC<OwnProps & StateProps> = ({
className, className,
loadAndPlay, loadAndPlay,
canSendStickers, canSendStickers,
@ -64,13 +57,16 @@ const StickerPicker: FC<OwnProps & StateProps & DispatchProps> = ({
stickerSetsById, stickerSetsById,
shouldPlay, shouldPlay,
onStickerSelect, onStickerSelect,
loadStickerSets,
loadRecentStickers,
loadFavoriteStickers,
loadAddedStickers,
addRecentSticker,
unfaveSticker,
}) => { }) => {
const {
loadStickerSets,
loadRecentStickers,
loadFavoriteStickers,
loadAddedStickers,
addRecentSticker,
unfaveSticker,
} = getDispatch();
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
@ -296,12 +292,4 @@ export default memo(withGlobal<OwnProps>(
shouldPlay: global.settings.byKey.shouldLoopStickers, shouldPlay: global.settings.byKey.shouldLoopStickers,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'loadStickerSets',
'loadRecentStickers',
'loadFavoriteStickers',
'loadAddedStickers',
'addRecentSticker',
'unfaveSticker',
]),
)(StickerPicker)); )(StickerPicker));

View File

@ -1,16 +1,14 @@
import React, { import React, {
FC, memo, useEffect, useRef, FC, memo, useEffect, useRef,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { ApiSticker } from '../../../api/types'; import { ApiSticker } from '../../../api/types';
import { GlobalActions } from '../../../global/types';
import { STICKER_SIZE_PICKER } from '../../../config'; import { STICKER_SIZE_PICKER } from '../../../config';
import { IS_TOUCH_ENV } from '../../../util/environment'; import { IS_TOUCH_ENV } from '../../../util/environment';
import buildClassName from '../../../util/buildClassName'; import buildClassName from '../../../util/buildClassName';
import captureEscKeyListener from '../../../util/captureEscKeyListener'; import captureEscKeyListener from '../../../util/captureEscKeyListener';
import { pick } from '../../../util/iteratees';
import { useIntersectionObserver } from '../../../hooks/useIntersectionObserver'; import { useIntersectionObserver } from '../../../hooks/useIntersectionObserver';
import useShowTransition from '../../../hooks/useShowTransition'; import useShowTransition from '../../../hooks/useShowTransition';
import usePrevious from '../../../hooks/usePrevious'; import usePrevious from '../../../hooks/usePrevious';
@ -29,16 +27,15 @@ type StateProps = {
stickers?: ApiSticker[]; stickers?: ApiSticker[];
}; };
type DispatchProps = Pick<GlobalActions, 'clearStickersForEmoji'>;
const INTERSECTION_THROTTLE = 200; const INTERSECTION_THROTTLE = 200;
const StickerTooltip: FC<OwnProps & StateProps & DispatchProps> = ({ const StickerTooltip: FC<OwnProps & StateProps> = ({
isOpen, isOpen,
onStickerSelect, onStickerSelect,
stickers, stickers,
clearStickersForEmoji,
}) => { }) => {
const { clearStickersForEmoji } = getDispatch();
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
const { shouldRender, transitionClassNames } = useShowTransition(isOpen, undefined, undefined, false); const { shouldRender, transitionClassNames } = useShowTransition(isOpen, undefined, undefined, false);
@ -96,5 +93,4 @@ export default memo(withGlobal<OwnProps>(
return { stickers }; return { stickers };
}, },
(setGlobal, actions): DispatchProps => pick(actions, ['clearStickersForEmoji']),
)(StickerTooltip)); )(StickerTooltip));

View File

@ -1,15 +1,13 @@
import React, { import React, {
FC, memo, useEffect, useMemo, FC, memo, useEffect, useMemo,
} from '../../../lib/teact/teact'; } from '../../../lib/teact/teact';
import { withGlobal } from '../../../lib/teact/teactn'; import { getDispatch, withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { ApiMessage, ApiMessageEntityTypes, ApiWebPage } from '../../../api/types'; import { ApiMessage, ApiMessageEntityTypes, ApiWebPage } from '../../../api/types';
import { ISettings } from '../../../types'; import { ISettings } from '../../../types';
import { RE_LINK_TEMPLATE } from '../../../config'; import { RE_LINK_TEMPLATE } from '../../../config';
import { selectNoWebPage, selectTheme } from '../../../modules/selectors'; import { selectNoWebPage, selectTheme } from '../../../modules/selectors';
import { pick } from '../../../util/iteratees';
import parseMessageInput from '../../../util/parseMessageInput'; import parseMessageInput from '../../../util/parseMessageInput';
import useOnChange from '../../../hooks/useOnChange'; import useOnChange from '../../../hooks/useOnChange';
import useShowTransition from '../../../hooks/useShowTransition'; import useShowTransition from '../../../hooks/useShowTransition';
@ -33,11 +31,10 @@ type StateProps = {
noWebPage?: boolean; noWebPage?: boolean;
theme: ISettings['theme']; theme: ISettings['theme'];
}; };
type DispatchProps = Pick<GlobalActions, 'loadWebPagePreview' | 'clearWebPagePreview' | 'toggleMessageWebPage'>;
const RE_LINK = new RegExp(RE_LINK_TEMPLATE, 'i'); const RE_LINK = new RegExp(RE_LINK_TEMPLATE, 'i');
const WebPagePreview: FC<OwnProps & StateProps & DispatchProps> = ({ const WebPagePreview: FC<OwnProps & StateProps> = ({
chatId, chatId,
threadId, threadId,
messageText, messageText,
@ -45,10 +42,13 @@ const WebPagePreview: FC<OwnProps & StateProps & DispatchProps> = ({
webPagePreview, webPagePreview,
noWebPage, noWebPage,
theme, theme,
loadWebPagePreview,
clearWebPagePreview,
toggleMessageWebPage,
}) => { }) => {
const {
loadWebPagePreview,
clearWebPagePreview,
toggleMessageWebPage,
} = getDispatch();
const link = useMemo(() => { const link = useMemo(() => {
const { text, entities } = parseMessageInput(messageText); const { text, entities } = parseMessageInput(messageText);
@ -121,7 +121,4 @@ export default memo(withGlobal<OwnProps>(
noWebPage, noWebPage,
}; };
}, },
(setGlobal, actions): DispatchProps => pick(actions, [
'loadWebPagePreview', 'clearWebPagePreview', 'toggleMessageWebPage',
]),
)(WebPagePreview)); )(WebPagePreview));

View File

@ -1,7 +1,7 @@
import { useCallback, useEffect, useMemo } from '../../../../lib/teact/teact'; import { useCallback, useEffect, useMemo } from '../../../../lib/teact/teact';
import { getDispatch } from '../../../../lib/teact/teactn';
import { ApiFormattedText, ApiMessage } from '../../../../api/types'; import { ApiFormattedText, ApiMessage } from '../../../../api/types';
import { GlobalActions } from '../../../../global/types';
import { DRAFT_DEBOUNCE, EDITABLE_INPUT_ID } from '../../../../config'; import { DRAFT_DEBOUNCE, EDITABLE_INPUT_ID } from '../../../../config';
import usePrevious from '../../../../hooks/usePrevious'; import usePrevious from '../../../../hooks/usePrevious';
@ -25,9 +25,9 @@ export default (
htmlRef: { current: string }, htmlRef: { current: string },
setHtml: (html: string) => void, setHtml: (html: string) => void,
editedMessage: ApiMessage | undefined, editedMessage: ApiMessage | undefined,
saveDraft: GlobalActions['saveDraft'],
clearDraft: GlobalActions['clearDraft'],
) => { ) => {
const { saveDraft, clearDraft } = getDispatch();
const updateDraft = useCallback((draftChatId: string, draftThreadId: number) => { const updateDraft = useCallback((draftChatId: string, draftThreadId: number) => {
if (htmlRef.current.length && !editedMessage) { if (htmlRef.current.length && !editedMessage) {
saveDraft({ chatId: draftChatId, threadId: draftThreadId, draft: parseMessageInput(htmlRef.current!) }); saveDraft({ chatId: draftChatId, threadId: draftThreadId, draft: parseMessageInput(htmlRef.current!) });

Some files were not shown because too many files have changed in this diff Show More