web/mainscreen: add animation for entering rooms

This commit is contained in:
Tulir Asokan 2024-12-15 16:27:18 +02:00
parent 5455c88c2f
commit 5f880b2487
3 changed files with 43 additions and 23 deletions

View file

@ -162,6 +162,7 @@ body {
html { html {
touch-action: none; touch-action: none;
background-color: var(--background-color);
} }
#root { #root {

View file

@ -17,25 +17,24 @@ main.matrix-main {
} }
@media screen and (max-width: 45rem) { @media screen and (max-width: 45rem) {
&, &.right-panel-open {
grid-template:
"roomlist roomview rightpanel" 1fr
/ 100% 100% 100%;
}
/* Note: this timeout must match the one in MainScreen.tsx */
transition: .3s;
@media (prefers-reduced-motion: reduce) {
transition: none;
}
&.room-selected {
translate: -100% 0;
}
&.right-panel-open { &.right-panel-open {
grid-template: "rightpanel" 1fr / 1fr; translate: -200% 0;
> div.room-list-wrapper {
display: none;
}
> div.room-view {
display: none;
}
}
&.room-selected:not(.right-panel-open) {
grid-template: "roomview" 1fr / 1fr;
> div.room-list-wrapper {
display: none;
}
}
&:not(.room-selected):not(.right-panel-open) {
grid-template: "roomlist" 1fr / 1fr;
} }
} }

View file

@ -13,7 +13,7 @@
// //
// You should have received a copy of the GNU Affero General Public License // You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
import { JSX, use, useEffect, useInsertionEffect, useLayoutEffect, useMemo, useState } from "react" import { JSX, use, useEffect, useInsertionEffect, useLayoutEffect, useMemo, useReducer, useState } from "react"
import { SyncLoader } from "react-spinners" import { SyncLoader } from "react-spinners"
import Client from "@/api/client.ts" import Client from "@/api/client.ts"
import { RoomStateStore } from "@/api/statestore" import { RoomStateStore } from "@/api/statestore"
@ -208,8 +208,20 @@ const handleURLHash = (client: Client) => {
return history.state return history.state
} }
type ActiveRoomType = [RoomStateStore | null, RoomStateStore | null]
const activeRoomReducer = (prev: ActiveRoomType, active: RoomStateStore | "clear-animation" | null): ActiveRoomType => {
if (active === "clear-animation") {
return prev[1] === null ? [null, null] : prev
} else if (window.innerWidth > 720 || window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
return [null, active]
} else {
return [prev[1], active]
}
}
const MainScreen = () => { const MainScreen = () => {
const [activeRoom, directSetActiveRoom] = useState<RoomStateStore | null>(null) const [[prevActiveRoom, activeRoom], directSetActiveRoom] = useReducer(activeRoomReducer, [null, null] as const)
const [rightPanel, directSetRightPanel] = useState<RightPanelProps | null>(null) const [rightPanel, directSetRightPanel] = useState<RightPanelProps | null>(null)
const client = use(ClientContext)! const client = use(ClientContext)!
const syncStatus = useEventAsState(client.syncStatus) const syncStatus = useEventAsState(client.syncStatus)
@ -292,16 +304,24 @@ const MainScreen = () => {
Sync is failing Sync is failing
</div> </div>
} }
const renderedRoom = activeRoom ?? prevActiveRoom
useEffect(() => {
if (prevActiveRoom !== null && activeRoom === null) {
// Note: this timeout must match the one in MainScreen.css
const timeout = setTimeout(() => directSetActiveRoom("clear-animation"), 300)
return () => clearTimeout(timeout)
}
}, [activeRoom, prevActiveRoom])
return <MainScreenContext value={context}> return <MainScreenContext value={context}>
<ModalWrapper> <ModalWrapper>
<StylePreferences client={client} activeRoom={activeRoom}/> <StylePreferences client={client} activeRoom={activeRoom}/>
<main className={classNames.join(" ")} style={extraStyle}> <main className={classNames.join(" ")} style={extraStyle}>
<RoomList activeRoomID={activeRoom?.roomID ?? null}/> <RoomList activeRoomID={activeRoom?.roomID ?? null}/>
{resizeHandle1} {resizeHandle1}
{activeRoom {renderedRoom
? <RoomView ? <RoomView
key={activeRoom.roomID} key={renderedRoom.roomID}
room={activeRoom} room={renderedRoom}
rightPanel={rightPanel} rightPanel={rightPanel}
rightPanelResizeHandle={resizeHandle2} rightPanelResizeHandle={resizeHandle2}
/> />