mirror of
https://github.com/tulir/gomuks.git
synced 2025-04-20 10:33:41 -05:00
web/mainscreen: add animation for entering rooms
This commit is contained in:
parent
5455c88c2f
commit
5f880b2487
3 changed files with 43 additions and 23 deletions
|
@ -162,6 +162,7 @@ body {
|
||||||
|
|
||||||
html {
|
html {
|
||||||
touch-action: none;
|
touch-action: none;
|
||||||
|
background-color: var(--background-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
#root {
|
#root {
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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}
|
||||||
/>
|
/>
|
||||||
|
|
Loading…
Add table
Reference in a new issue