web/main: make room view and list separate screens on mobile

This commit is contained in:
Tulir Asokan 2024-10-15 13:54:22 +03:00
parent 747a015bcc
commit b31eb2ea75
5 changed files with 51 additions and 7 deletions

1
web/src/icons/back.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#5f6368"><path d="m313-440 224 224-57 56-320-320 320-320 57 56-224 224h487v80H313Z"/></svg>

After

Width:  |  Height:  |  Size: 190 B

View file

@ -4,4 +4,28 @@ main.matrix-main {
display: grid;
grid-template: "roomlist roomview" 1fr / 300px 1fr;
@media screen and (max-width: 1000px) {
grid-template: "roomlist roomview" 1fr / 250px 1fr;
}
@media screen and (max-width: 900px) {
grid-template: "roomlist roomview" 1fr / 200px 1fr;
}
@media screen and (max-width: 750px) {
&.room-selected {
grid-template: "roomview" 1fr / 1fr;
> div.room-list-wrapper {
display: none;
}
}
&:not(.room-selected) {
grid-template: "roomlist" 1fr / 1fr;
> div.room-view {
display: none;
}
}
}
}

View file

@ -14,7 +14,7 @@
// 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/>.
import { use, useCallback, useState } from "react"
import type { RoomID } from "../api/types"
import type { RoomID } from "@/api/types"
import { ClientContext } from "./ClientContext.ts"
import RoomView from "./RoomView.tsx"
import RoomList from "./roomlist/RoomList.tsx"
@ -31,9 +31,10 @@ const MainScreen = () => {
.catch(err => console.error("Failed to load room state", err))
}
}, [client])
return <main className="matrix-main">
const clearActiveRoom = useCallback(() => setActiveRoomID(null), [])
return <main className={`matrix-main ${activeRoom ? "room-selected" : ""}`}>
<RoomList setActiveRoom={setActiveRoom} activeRoomID={activeRoomID} />
{activeRoom && <RoomView key={activeRoomID} room={activeRoom} />}
{activeRoom && <RoomView key={activeRoomID} clearActiveRoom={clearActiveRoom} room={activeRoom} />}
</main>
}

View file

@ -13,11 +13,26 @@ div.room-view {
display: flex;
align-items: center;
gap: .5rem;
padding-left: 1rem;
margin-left: .5rem;
border-bottom: 1px solid #ccc;
> span.room-name {
font-weight: bold;
}
> button.back {
background: none;
border: none;
height: 2.5rem;
width: 2.5rem;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
&:hover, &:focus {
background-color: #eee;
}
}
}
}

View file

@ -21,15 +21,18 @@ import { useNonNullEventAsState } from "@/util/eventdispatcher.ts"
import { LightboxContext } from "./Lightbox.tsx"
import MessageComposer from "./MessageComposer.tsx"
import TimelineView from "./timeline/TimelineView.tsx"
import BackIcon from "@/icons/back.svg?react"
import "./RoomView.css"
interface RoomViewProps {
room: RoomStateStore
clearActiveRoom: () => void
}
const RoomHeader = ({ room }: RoomViewProps) => {
const RoomHeader = ({ room, clearActiveRoom }: RoomViewProps) => {
const roomMeta = useNonNullEventAsState(room.meta)
return <div className="room-header">
<button className="back" onClick={clearActiveRoom}><BackIcon/></button>
<img
className="avatar"
loading="lazy"
@ -49,12 +52,12 @@ const onKeyDownRoomView = (evt: React.KeyboardEvent) => {
}
}
const RoomView = ({ room }: RoomViewProps) => {
const RoomView = ({ room, clearActiveRoom }: RoomViewProps) => {
const [replyTo, setReplyTo] = useState<MemDBEvent | null>(null)
const [textRows, setTextRows] = useState(1)
const closeReply = useCallback(() => setReplyTo(null), [])
return <div className="room-view" onKeyDown={onKeyDownRoomView} tabIndex={-1}>
<RoomHeader room={room}/>
<RoomHeader room={room} clearActiveRoom={clearActiveRoom}/>
<TimelineView room={room} textRows={textRows} replyTo={replyTo} setReplyTo={setReplyTo}/>
<MessageComposer room={room} setTextRows={setTextRows} replyTo={replyTo} closeReply={closeReply}/>
</div>