BREAKING CHANGE: make back button handler perfect

This commit is contained in:
OfficialDakari 2024-10-25 09:55:46 +05:00
parent 693aba99f4
commit ef02b16828
14 changed files with 66 additions and 24 deletions

View file

@ -43,6 +43,36 @@
<body id="appBody">
<script>
window.global ||= window;
(function () {
let stateSymbol = "__state__index__";
history.stateIndex = -1;
history.states = [];
let pushState = history.pushState;
function add(data, title, url) {
if (data == null) data = {};
if (typeof data != "object") data = { data: data };
data[stateSymbol] = (history.stateIndex + 1);
history.states.splice(history.stateIndex + 1, 0, [data, title, url])
history.states.splice(history.stateIndex + 2)
history.stateIndex++;
}
history.pushState = function (data, title, url = null) {
add(data, title, url);
pushState.bind(history)(data, title, url);
}
addEventListener("popstate", function (e) {
var eventObject = {};
var newStateIndex = e.state != null ? e.state[stateSymbol] : -1;
eventObject.from = history.states[history.stateIndex];
eventObject.to = newStateIndex > -1 ? history.states[newStateIndex] : null;
eventObject.side = history.stateIndex > newStateIndex ? "back" : "forward";
if (newStateIndex > -1 && !(newStateIndex in history.states)) {
add(history.state, "", window.location.href);
}
window.dispatchEvent(new CustomEvent("historyChange", { detail: eventObject }))
history.stateIndex = e.state != null ? e.state[stateSymbol] : -1;
});
})();
</script>
<div id="root"></div>
<script type="module" src="./src/index.tsx"></script>

View file

@ -36,7 +36,7 @@ export const ImageViewer = as<'div', ImageViewerProps>(
{...props}
ref={ref}
>
<BackButtonHandler callback={requestClose} />
<BackButtonHandler callback={requestClose} id='image-viewer' />
<AppBar position='static'>
<Toolbar>
<IconButton onClick={requestClose}>

View file

@ -178,7 +178,7 @@ export const MessageReadReceiptItem = as<
open={open}
onClose={handleClose}
>
{open && <BackButtonHandler callback={handleClose} />}
{open && <BackButtonHandler callback={handleClose} id='msg-readers-list' />}
<AppBar position='relative'>
<Toolbar>
<Typography
@ -255,7 +255,7 @@ export const MessageSourceCodeItem = as<
onClose?.();
};
useBackButton(handleClose);
useBackButton(handleClose, 'source-code');
return (
<>
@ -531,7 +531,7 @@ export const MessageRecoverItem = as<
open={open}
onClose={handleClose}
>
{open && <BackButtonHandler callback={handleClose} />}
{open && <BackButtonHandler callback={handleClose} id='msg-recover' />}
<DialogTitle>{getText('recovered.title')}</DialogTitle>
<DialogContent>
{message}
@ -662,7 +662,7 @@ export const MessageTranslateItem = as<
open={open}
onClose={handleClose}
>
{open && <BackButtonHandler callback={handleClose} />}
{open && <BackButtonHandler callback={handleClose} id='msg-translated' />}
<DialogTitle>{getText('translated.title')}</DialogTitle>
<DialogContent>
{message}
@ -847,7 +847,7 @@ export const MessageDeleteItem = as<
onSubmit: handleSubmit
}}
>
{open && <BackButtonHandler callback={handleClose} />}
{open && <BackButtonHandler callback={handleClose} id='meg-delete' />}
<DialogTitle>
{getText('msg_redact.title')}
</DialogTitle>

View file

@ -1,21 +1,33 @@
import { useCallback, useEffect } from "react";
import { useCallback, useEffect, useState } from "react";
import { v4 } from "uuid";
export const useBackButton = (callback) => {
const cb = useCallback((evt) => {
evt.preventDefault();
callback();
}, [callback]);
export const useBackButton = (callback, fakeId) => {
const fi2 = `${fakeId}-2`;
const cb = (evt) => {
console.log(`popstate`, evt, evt.state, history.state, fakeId);
if (history.state === fakeId) {
callback();
}
};
useEffect(() => {
addEventListener('popstate', cb);
history.pushState(fakeId, document.title, location.href);
history.pushState(fi2, document.title, location.href);
return () => {
removeEventListener('popstate', cb);
if (history.state === fi2) {
history.go(-2);
} else if (history.state == fakeId) {
history.back();
}
};
}, []);
};
export const BackButtonHandler = ({ callback }) => {
useBackButton(callback);
export const BackButtonHandler = ({ callback, id }) => {
useBackButton(callback, id ?? 'fake-route');
return null;
};

View file

@ -261,7 +261,7 @@ function CreateRoom() {
open={create !== null}
onRequestClose={onRequestClose}
>
{create !== null && <BackButtonHandler callback={onRequestClose} />}
{create !== null && <BackButtonHandler callback={onRequestClose} id='create-room' />}
<AppBar position='relative'>
<Toolbar>
<Typography variant='h6' component='div' flexGrow={1}>

View file

@ -114,7 +114,7 @@ function HiddenRooms() {
onRequestClose={requestClose}
size="small"
>
{isOpen && <BackButtonHandler callback={requestClose} />}
{isOpen && <BackButtonHandler callback={requestClose} id='hidden-rooms' />}
<div className="hidden-rooms-dialog">
<div className="hidden-rooms-dialog__content-wrapper">
<ScrollView autoHide>

View file

@ -250,7 +250,7 @@ function InviteUser({ isOpen, roomId, searchTerm, onRequestClose }) {
open={isOpen}
onClose={onRequestClose}
>
{isOpen && <BackButtonHandler callback={onRequestClose} />}
{isOpen && <BackButtonHandler callback={onRequestClose} id='invite-user' />}
<AppBar position='relative'>
<Toolbar>
<Typography

View file

@ -137,7 +137,7 @@ function JoinAlias() {
contentOptions={<IconButton src={mdiClose} onClick={requestClose} tooltip="Close" />}
onRequestClose={requestClose}
>
{data !== null && <BackButtonHandler callback={requestClose} />}
{data !== null && <BackButtonHandler callback={requestClose} id='join-alias' />}
{data ? <JoinAliasContent term={data.term} requestClose={requestClose} /> : <div />}
</Dialog>
);

View file

@ -626,7 +626,7 @@ function ProfileViewer() {
open={isOpen}
onClose={closeDialog}
>
{isOpen && <BackButtonHandler callback={closeDialog} />}
{isOpen && <BackButtonHandler callback={closeDialog} id='profile-viewer' />}
{roomId ? renderProfile() : <div />}
</Dialog>
);

View file

@ -143,7 +143,7 @@ function RoomSettings() {
scroll='body'
sx={{ backdropFilter: 'blur(3px)' }}
>
{window !== null && <BackButtonHandler callback={requestClose} />}
{window !== null && <BackButtonHandler callback={requestClose} id='room-settings' />}
{window !== null && (
<AppBar position='relative'>
<ProminientToolbar>

View file

@ -209,7 +209,7 @@ function Search() {
onRequestClose={requestClose}
size="small"
>
{isOpen && <BackButtonHandler callback={requestClose} />}
{isOpen && <BackButtonHandler callback={requestClose} id='ck-search' />}
<div className="search-dialog">
<form
className="search-dialog__input"

View file

@ -901,7 +901,7 @@ function Settings() {
scroll='body'
sx={{ overscrollBehaviorY: 'none', backdropFilter: 'blur(3px)' }}
>
{isOpen && <BackButtonHandler callback={requestClose} />}
{isOpen && <BackButtonHandler callback={requestClose} id='settings' />}
<input type='file' accept='image/*' onChange={uploadImage} ref={uploadImageRef} style={{ display: 'none' }} />
{isOpen && (
<AppBar

View file

@ -168,7 +168,7 @@ function ShareMenu() {
open={isOpen}
onClose={requestClose}
>
{isOpen && <BackButtonHandler callback={requestClose} />}
{isOpen && <BackButtonHandler callback={requestClose} id='share-menu' />}
<ScrollView autoHide>
<div className="share-menu-dialog__content">
{Array.isArray(result) && result.map(renderRoomSelector)}

View file

@ -122,7 +122,7 @@ function SpaceSettings() {
fullScreen={screenSize === ScreenSize.Mobile}
sx={{ backdropFilter: 'blur(3px)' }}
>
{isOpen && <BackButtonHandler callback={requestClose} />}
{isOpen && <BackButtonHandler callback={requestClose} id='space-settings' />}
<AppBar sx={{ position: 'relative' }}>
<ProminientToolbar>
<div style={{ flexGrow: 1, alignSelf: 'flex-end' }}>