diff --git a/src/components/auth/AuthCode.tsx b/src/components/auth/AuthCode.tsx index 0d144bc40..c8d22d103 100644 --- a/src/components/auth/AuthCode.tsx +++ b/src/components/auth/AuthCode.tsx @@ -11,6 +11,7 @@ import { pick } from '../../util/iteratees'; import InputText from '../ui/InputText'; import Loading from '../ui/Loading'; import TrackingMonkey from '../common/TrackingMonkey'; +import useHistoryBack from '../../hooks/useHistoryBack'; type StateProps = Pick; type DispatchProps = Pick; @@ -33,6 +34,8 @@ const AuthCode: FC = ({ } }, []); + useHistoryBack(returnToAuthPhoneNumber); + const onCodeChange = useCallback((e: FormEvent) => { if (authError) { clearAuthError(); @@ -77,7 +80,7 @@ const AuthCode: FC = ({ {authPhoneNumber}
returnToAuthPhoneNumber()} + onClick={returnToAuthPhoneNumber} role="button" tabIndex={0} title="Sign In with another phone number" diff --git a/src/components/auth/AuthQrCode.tsx b/src/components/auth/AuthQrCode.tsx index d3f99dca6..ae4e3a029 100644 --- a/src/components/auth/AuthQrCode.tsx +++ b/src/components/auth/AuthQrCode.tsx @@ -10,6 +10,7 @@ import { pick } from '../../util/iteratees'; import Loading from '../ui/Loading'; import Button from '../ui/Button'; import buildClassName from '../../util/buildClassName'; +import useHistoryBack from '../../hooks/useHistoryBack'; type StateProps = Pick; type DispatchProps = Pick; @@ -40,6 +41,8 @@ const AuthCode: FC = ({ }, container); }, [connectionState, authQrCode]); + useHistoryBack(returnToAuthPhoneNumber); + return (
diff --git a/src/global/index.ts b/src/global/index.ts index abdceccc1..269986a0c 100644 --- a/src/global/index.ts +++ b/src/global/index.ts @@ -3,10 +3,16 @@ import { addReducer } from '../lib/teact/teactn'; import { INITIAL_STATE } from './initial'; import { initCache, loadCache } from './cache'; import { cloneDeep } from '../util/iteratees'; +import { selectCurrentMessageList } from '../modules/selectors'; initCache(); addReducer('init', () => { const initial = cloneDeep(INITIAL_STATE); - return loadCache(initial) || initial; + const newGlobal = loadCache(initial) || initial; + + const currentMessageList = selectCurrentMessageList(newGlobal) || {}; + window.history.replaceState(currentMessageList, ''); + + return newGlobal; }); diff --git a/src/hooks/useHistoryBack.ts b/src/hooks/useHistoryBack.ts new file mode 100644 index 000000000..f051e99f8 --- /dev/null +++ b/src/hooks/useHistoryBack.ts @@ -0,0 +1,15 @@ +// This is unsafe and can be not chained as `popstate` event is asynchronous + +export default function useHistoryBack(handler: NoneToVoidFunction) { + function handlePopState() { + handler(); + } + + window.addEventListener('popstate', handlePopState); + window.history.pushState({}, ''); + + return () => { + window.removeEventListener('popstate', handlePopState); + window.history.back(); + }; +} diff --git a/src/modules/actions/ui/chats.ts b/src/modules/actions/ui/chats.ts index 8b8b2d7ce..a6f504772 100644 --- a/src/modules/actions/ui/chats.ts +++ b/src/modules/actions/ui/chats.ts @@ -1,12 +1,26 @@ -import { addReducer, setGlobal } from '../../../lib/teact/teactn'; +import { addReducer, getDispatch, setGlobal } from '../../../lib/teact/teactn'; import { exitMessageSelectMode, updateCurrentMessageList, } from '../../reducers'; import { selectCurrentMessageList } from '../../selectors'; +window.addEventListener('popstate', (e) => { + if (!e.state) { + return; + } + + const { chatId: id, threadId, messageListType: type } = e.state; + + getDispatch().openChat({ + id, threadId, type, noPushState: true, + }); +}); + addReducer('openChat', (global, actions, payload) => { - const { id, threadId, type } = payload!; + const { + id, threadId = -1, type = 'thread', noPushState, + } = payload!; const currentMessageList = selectCurrentMessageList(global); @@ -30,6 +44,10 @@ addReducer('openChat', (global, actions, payload) => { }; setGlobal(global); + + if (!noPushState) { + window.history.pushState({ chatId: id, threadId, messageListType: type }, ''); + } } return updateCurrentMessageList(global, id, threadId, type);