Fix mobile styles

This commit is contained in:
Robert Long 2021-12-10 10:54:18 -08:00
parent fc3960ce63
commit 9174369fb5
13 changed files with 277 additions and 260 deletions

View file

@ -1,12 +1,13 @@
.callTile { .callTile {
display: flex; display: flex;
width: 329px; min-width: 240px;
height: 94px; height: 94px;
padding: 12px; padding: 12px;
text-decoration: none; text-decoration: none;
background-color: var(--bgColor2); background-color: var(--bgColor2);
border-radius: 8px; border-radius: 8px;
overflow: hidden; overflow: hidden;
box-sizing: border-box;
} }
.avatar, .avatar,
@ -54,9 +55,7 @@
} }
.callList { .callList {
display: flex; display: grid;
flex-wrap: wrap; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
justify-content: flex-start;
gap: 24px; gap: 24px;
flex: 1;
} }

View file

@ -297,7 +297,6 @@ export function ClientProvider({ homeserverUrl, children }) {
loading: false, loading: false,
isGuest: false, isGuest: false,
isAuthenticated: true, isAuthenticated: true,
isGuest: false,
userName: client.getUserIdLocalpart(), userName: client.getUserIdLocalpart(),
}); });
@ -407,40 +406,21 @@ export async function createRoom(client, name) {
return room_alias || room_id; return room_alias || room_id;
} }
export function useCreateRoom(client) { export function useCreateRoom() {
const [creatingRoom, setCreatingRoom] = useState(false); const { register, client } = useClient();
const [createRoomError, setCreateRoomError] = useState();
const onCreateRoom = useCallback(
(roomName) => {
setCreateRoomError(undefined);
setCreatingRoom(true);
return createRoom(client, roomName).catch((error) => {
setCreateRoomError(error);
setCreatingRoom(false);
});
},
[client]
);
return {
creatingRoom,
createRoomError,
createRoom: onCreateRoom,
};
}
export function useCreateRoomAsPasswordlessUser() {
const { register } = useClient();
const [creatingRoom, setCreatingRoom] = useState(false); const [creatingRoom, setCreatingRoom] = useState(false);
const [createRoomError, setCreateRoomError] = useState(); const [createRoomError, setCreateRoomError] = useState();
const onCreateRoom = useCallback( const onCreateRoom = useCallback(
(roomName, userName) => { (roomName, userName) => {
async function onCreateRoom(roomName, userName) { async function onCreateRoom(roomName, userName) {
const client = await register(userName, randomString(16)); let _client = client;
return await createRoom(client, roomName);
if (!_client) {
_client = await register(userName, randomString(16));
}
return await createRoom(_client, roomName);
} }
setCreateRoomError(undefined); setCreateRoomError(undefined);
@ -451,7 +431,7 @@ export function useCreateRoomAsPasswordlessUser() {
setCreatingRoom(false); setCreatingRoom(false);
}); });
}, },
[register] [register, client]
); );
return { return {

View file

@ -3,16 +3,17 @@
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
height: 64px;
user-select: none; user-select: none;
flex-shrink: 0; flex-shrink: 0;
} }
.nav { .nav {
display: flex; display: flex;
flex: 1;
align-items: center; align-items: center;
white-space: nowrap; white-space: nowrap;
margin: 0 20px; padding: 0 20px;
height: 64px;
} }
.logo { .logo {
@ -25,6 +26,10 @@
margin-right: 12px; margin-right: 12px;
} }
.rightNav {
justify-content: flex-end;
}
.rightNav > * { .rightNav > * {
margin-right: 24px; margin-right: 24px;
} }
@ -88,7 +93,7 @@
} }
@media (min-width: 800px) { @media (min-width: 800px) {
.header { .nav {
height: 98px; height: 98px;
} }
} }

View file

@ -21,7 +21,6 @@ import {
useGroupCallRooms, useGroupCallRooms,
usePublicRooms, usePublicRooms,
useCreateRoom, useCreateRoom,
useCreateRoomAsPasswordlessUser,
} from "./ConferenceCallManagerHooks"; } from "./ConferenceCallManagerHooks";
import { Header, HeaderLogo, LeftNav, RightNav } from "./Header"; import { Header, HeaderLogo, LeftNav, RightNav } from "./Header";
import styles from "./Home.module.css"; import styles from "./Home.module.css";
@ -35,21 +34,8 @@ import { ErrorModal } from "./ErrorModal";
export function Home() { export function Home() {
const { isAuthenticated, isGuest, loading, error, client } = useClient(); const { isAuthenticated, isGuest, loading, error, client } = useClient();
if (loading) {
return <div>Loading...</div>;
} else if (error) {
return <ErrorModal error={error} />;
} else if (!isAuthenticated || isGuest) {
return <UnregisteredView />;
} else {
return <RegisteredView client={client} />;
}
}
function UnregisteredView() {
const history = useHistory(); const history = useHistory();
const { createRoomError, creatingRoom, createRoom } = const { createRoomError, creatingRoom, createRoom } = useCreateRoom();
useCreateRoomAsPasswordlessUser();
const onCreateRoom = useCallback( const onCreateRoom = useCallback(
(e) => { (e) => {
@ -59,7 +45,9 @@ function UnregisteredView() {
const userName = data.get("userName"); const userName = data.get("userName");
createRoom(roomName, userName).then((roomIdOrAlias) => { createRoom(roomName, userName).then((roomIdOrAlias) => {
history.push(`/room/${roomIdOrAlias}`); if (roomIdOrAlias) {
history.push(`/room/${roomIdOrAlias}`);
}
}); });
}, },
[history] [history]
@ -75,78 +63,112 @@ function UnregisteredView() {
[history] [history]
); );
if (loading) {
return <div>Loading...</div>;
} else if (error) {
return <ErrorModal error={error} />;
} else if (!isAuthenticated || isGuest) {
return (
<UnregisteredView
onCreateRoom={onCreateRoom}
createRoomError={createRoomError}
creatingRoom={creatingRoom}
onJoinRoom={onJoinRoom}
/>
);
} else {
return (
<RegisteredView
client={client}
onCreateRoom={onCreateRoom}
createRoomError={createRoomError}
creatingRoom={creatingRoom}
onJoinRoom={onJoinRoom}
/>
);
}
}
function UnregisteredView({
onCreateRoom,
createRoomError,
creatingRoom,
onJoinRoom,
}) {
return ( return (
<div className={styles.home}> <div className={classNames(styles.home, styles.fullWidth)}>
<div className={classNames(styles.left, styles.fullWidth)}> <Header>
<Header> <LeftNav>
<LeftNav> <HeaderLogo />
<HeaderLogo /> </LeftNav>
</LeftNav> <RightNav>
<RightNav> <UserMenu />
<UserMenu /> </RightNav>
</RightNav> </Header>
</Header> <div className={styles.splitContainer}>
<div className={styles.content}> <div className={styles.left}>
<div className={styles.centered}> <div className={styles.content}>
<form onSubmit={onJoinRoom}> <div className={styles.centered}>
<h1>Join a call</h1> <form onSubmit={onJoinRoom}>
<FieldRow className={styles.fieldRow}> <h1>Join a call</h1>
<InputField
id="roomId"
name="roomId"
label="Call ID"
type="text"
required
autoComplete="off"
placeholder="Call ID"
/>
</FieldRow>
<FieldRow className={styles.fieldRow}>
<Button className={styles.button} type="submit">
Join call
</Button>
</FieldRow>
</form>
<hr />
<form onSubmit={onCreateRoom}>
<h1>Create a call</h1>
<FieldRow className={styles.fieldRow}>
<InputField
id="userName"
name="userName"
label="Username"
type="text"
required
autoComplete="off"
placeholder="Username"
/>
</FieldRow>
<FieldRow className={styles.fieldRow}>
<InputField
id="roomName"
name="roomName"
label="Room Name"
type="text"
required
autoComplete="off"
placeholder="Room Name"
/>
</FieldRow>
{createRoomError && (
<FieldRow className={styles.fieldRow}> <FieldRow className={styles.fieldRow}>
<ErrorMessage>{createRoomError.message}</ErrorMessage> <InputField
id="roomId"
name="roomId"
label="Call ID"
type="text"
required
autoComplete="off"
placeholder="Call ID"
/>
</FieldRow> </FieldRow>
)} <FieldRow className={styles.fieldRow}>
<FieldRow className={styles.fieldRow}> <Button className={styles.button} type="submit">
<Button Join call
className={styles.button} </Button>
type="submit" </FieldRow>
disabled={creatingRoom} </form>
> <hr />
{creatingRoom ? "Creating call..." : "Create call"} <form onSubmit={onCreateRoom}>
</Button> <h1>Create a call</h1>
</FieldRow> <FieldRow className={styles.fieldRow}>
</form> <InputField
id="userName"
name="userName"
label="Username"
type="text"
required
autoComplete="off"
placeholder="Username"
/>
</FieldRow>
<FieldRow className={styles.fieldRow}>
<InputField
id="roomName"
name="roomName"
label="Room Name"
type="text"
required
autoComplete="off"
placeholder="Room Name"
/>
</FieldRow>
{createRoomError && (
<FieldRow className={styles.fieldRow}>
<ErrorMessage>{createRoomError.message}</ErrorMessage>
</FieldRow>
)}
<FieldRow className={styles.fieldRow}>
<Button
className={styles.button}
type="submit"
disabled={creatingRoom}
>
{creatingRoom ? "Creating call..." : "Create call"}
</Button>
</FieldRow>
</form>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -154,32 +176,13 @@ function UnregisteredView() {
); );
} }
function RegisteredView({ client }) { function RegisteredView({
const history = useHistory(); client,
const { createRoomError, creatingRoom, createRoom } = useCreateRoom(client); onCreateRoom,
createRoomError,
const onCreateRoom = useCallback( creatingRoom,
(e) => { onJoinRoom,
e.preventDefault(); }) {
const data = new FormData(e.target);
const roomName = data.get("roomName");
createRoom(roomName).then((roomIdOrAlias) => {
history.push(`/room/${roomIdOrAlias}`);
});
},
[history]
);
const onJoinRoom = useCallback(
(e) => {
e.preventDefault();
const data = new FormData(e.target);
const roomId = data.get("roomId");
history.push(`/room/${roomId}`);
},
[history]
);
const publicRooms = usePublicRooms( const publicRooms = usePublicRooms(
client, client,
import.meta.env.VITE_PUBLIC_SPACE_ROOM_ID import.meta.env.VITE_PUBLIC_SPACE_ROOM_ID
@ -189,93 +192,87 @@ function RegisteredView({ client }) {
const hideCallList = publicRooms.length === 0 && recentRooms.length === 0; const hideCallList = publicRooms.length === 0 && recentRooms.length === 0;
return ( return (
<div className={styles.home}> <div
<div className={classNames(styles.home, {
className={classNames(styles.left, { [styles.fullWidth]: hideCallList,
[styles.fullWidth]: hideCallList, })}
})} >
> <Header>
<Header> <LeftNav>
<LeftNav> <HeaderLogo />
<HeaderLogo /> </LeftNav>
</LeftNav> <RightNav>
{hideCallList && ( <UserMenu />
<RightNav> </RightNav>
<UserMenu /> </Header>
</RightNav> <div className={styles.splitContainer}>
)} <div className={styles.left}>
</Header>
<div className={styles.content}>
<div className={styles.centered}>
<form onSubmit={onJoinRoom}>
<h1>Join a call</h1>
<FieldRow className={styles.fieldRow}>
<InputField
id="roomId"
name="roomId"
label="Call ID"
type="text"
required
autoComplete="off"
placeholder="Call ID"
/>
</FieldRow>
<FieldRow className={styles.fieldRow}>
<Button className={styles.button} type="submit">
Join call
</Button>
</FieldRow>
</form>
<hr />
<form onSubmit={onCreateRoom}>
<h1>Create a call</h1>
<FieldRow className={styles.fieldRow}>
<InputField
id="roomName"
name="roomName"
label="Room Name"
type="text"
required
autoComplete="off"
placeholder="Room Name"
/>
</FieldRow>
{createRoomError && (
<FieldRow className={styles.fieldRow}>
<ErrorMessage>{createRoomError.message}</ErrorMessage>
</FieldRow>
)}
<FieldRow className={styles.fieldRow}>
<Button
className={styles.button}
type="submit"
disabled={creatingRoom}
>
{creatingRoom ? "Creating call..." : "Create call"}
</Button>
</FieldRow>
</form>
</div>
</div>
</div>
{!hideCallList && (
<div className={styles.right}>
<Header>
<LeftNav />
<RightNav>
<UserMenu />
</RightNav>
</Header>
<div className={styles.content}> <div className={styles.content}>
{publicRooms.length > 0 && ( <div className={styles.centered}>
<CallList title="Public Calls" rooms={publicRooms} /> <form onSubmit={onJoinRoom}>
)} <h1>Join a call</h1>
{recentRooms.length > 0 && ( <FieldRow className={styles.fieldRow}>
<CallList title="Recent Calls" rooms={recentRooms} /> <InputField
)} id="roomId"
name="roomId"
label="Call ID"
type="text"
required
autoComplete="off"
placeholder="Call ID"
/>
</FieldRow>
<FieldRow className={styles.fieldRow}>
<Button className={styles.button} type="submit">
Join call
</Button>
</FieldRow>
</form>
<hr />
<form onSubmit={onCreateRoom}>
<h1>Create a call</h1>
<FieldRow className={styles.fieldRow}>
<InputField
id="roomName"
name="roomName"
label="Room Name"
type="text"
required
autoComplete="off"
placeholder="Room Name"
/>
</FieldRow>
{createRoomError && (
<FieldRow className={styles.fieldRow}>
<ErrorMessage>{createRoomError.message}</ErrorMessage>
</FieldRow>
)}
<FieldRow className={styles.fieldRow}>
<Button
className={styles.button}
type="submit"
disabled={creatingRoom}
>
{creatingRoom ? "Creating call..." : "Create call"}
</Button>
</FieldRow>
</form>
</div>
</div> </div>
</div> </div>
)} {!hideCallList && (
<div className={styles.right}>
<div className={styles.content}>
{publicRooms.length > 0 && (
<CallList title="Public Calls" rooms={publicRooms} />
)}
{recentRooms.length > 0 && (
<CallList title="Recent Calls" rooms={recentRooms} />
)}
</div>
</div>
)}
</div>
</div> </div>
); );
} }

View file

@ -1,7 +1,14 @@
.home { .home {
display: flex; display: flex;
flex: 1; flex: 1;
height: 100%; flex-direction: column;
min-height: 100vh;
}
.splitContainer {
display: flex;
flex: 1;
flex-direction: column;
} }
.left, .left,
@ -11,13 +18,8 @@
flex: 1; flex: 1;
} }
.left {
background-color: var(--bgColor2);
}
.fullWidth { .fullWidth {
background-color: var(--bgColor1); background-color: var(--bgColor1);
overflow-y: auto;
} }
.centered { .centered {
@ -50,7 +52,7 @@
} }
.left .content hr { .left .content hr {
width: 100%; width: calc(100% - 24px);
border: none; border: none;
border-top: 1px solid var(--bgColor4); border-top: 1px solid var(--bgColor4);
color: var(--textColor2); color: var(--textColor2);
@ -60,20 +62,17 @@
font-weight: 600; font-weight: 600;
font-size: 15px; font-size: 15px;
line-height: 24px; line-height: 24px;
margin: 0 12px;
} }
.left .content hr:after { .left .content hr:after {
background-color: var(--bgColor2); background-color: var(--bgColor1);
content: "OR"; content: "OR";
padding: 0 12px; padding: 0 12px;
position: relative; position: relative;
top: -12px; top: -12px;
} }
.fullWidth .content hr:after {
background-color: var(--bgColor1);
}
.left .content form { .left .content form {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -97,14 +96,32 @@
} }
.left .content form:last-child { .left .content form:last-child {
padding-bottom: 0; padding-bottom: 40px;
} }
.right .content { .right .content {
padding: 113px 40px 40px 40px; padding: 113px 40px 40px 40px;
overflow-y: auto;
} }
.right .content h3:first-child { .right .content h3:first-child {
margin-top: 0; margin-top: 0;
} }
@media (min-width: 800px) {
.left {
background-color: var(--bgColor2);
}
.leftNav:not(.fullWidth) {
background-color: var(--bgColor2);
}
.splitContainer {
flex-direction: row;
}
.fullWidth .content hr:after,
.left .content hr:after {
background-color: var(--bgColor2);
}
}

View file

@ -14,7 +14,7 @@ import styles from "./Modal.module.css";
import classNames from "classnames"; import classNames from "classnames";
export function Modal(props) { export function Modal(props) {
const { title, children, className } = props; const { title, children, className, mobileFullScreen } = props;
const modalRef = useRef(); const modalRef = useRef();
const { overlayProps, underlayProps } = useOverlay(props, modalRef); const { overlayProps, underlayProps } = useOverlay(props, modalRef);
usePreventScroll(); usePreventScroll();
@ -34,7 +34,11 @@ export function Modal(props) {
{...dialogProps} {...dialogProps}
{...modalProps} {...modalProps}
ref={modalRef} ref={modalRef}
className={classNames(styles.modal, className)} className={classNames(
styles.modal,
{ [styles.mobileFullScreen]: mobileFullScreen },
className
)}
> >
<div className={styles.modalHeader}> <div className={styles.modalHeader}>
<h3 {...titleProps}>{title}</h3> <h3 {...titleProps}>{title}</h3>

View file

@ -15,7 +15,8 @@
background: #21262c; background: #21262c;
box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.15); box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.15);
border-radius: 8px; border-radius: 8px;
width: 420px; max-width: 90vw;
min-width: 288px;
} }
.modalHeader { .modalHeader {
@ -47,3 +48,18 @@
.content p { .content p {
margin-top: 0; margin-top: 0;
} }
@media (max-width: 799px) {
.modal.mobileFullScreen {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
width: 100%;
height: 100%;
max-width: none;
max-height: none;
border-radius: 0;
}
}

View file

@ -40,7 +40,6 @@ limitations under the License.
.preview { .preview {
position: relative; position: relative;
width: 100%;
max-width: 816px; max-width: 816px;
border-radius: 24px; border-radius: 24px;
overflow: hidden; overflow: hidden;

View file

@ -22,7 +22,7 @@
font-size: 15px; font-size: 15px;
color: var(--textColor1); color: var(--textColor1);
height: 40px; height: 40px;
width: 320px; max-width: 100%;
} }
.selectedItem { .selectedItem {
@ -33,7 +33,6 @@
} }
.popover { .popover {
width: 320px;
} }
.option:first-child { .option:first-child {

View file

@ -29,6 +29,7 @@ export function SettingsModal({
<Modal <Modal
title="Settings" title="Settings"
isDismissable isDismissable
mobileFullScreen
className={styles.settingsModal} className={styles.settingsModal}
{...rest} {...rest}
> >

View file

@ -6,13 +6,14 @@
.tabList { .tabList {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
width: 190px;
list-style: none; list-style: none;
padding: 0; padding: 0;
margin: 0; margin: 0;
} }
.tab { .tab {
max-width: 190px;
min-width: fit-content;
height: 32px; height: 32px;
border-radius: 8px; border-radius: 8px;
background-color: transparent; background-color: transparent;
@ -56,4 +57,5 @@
flex-direction: column; flex-direction: column;
flex: 1; flex: 1;
padding: 0 40px; padding: 0 40px;
overflow-y: auto;
} }

View file

@ -124,6 +124,7 @@ limitations under the License.
height: 40px; height: 40px;
transition: border-color 250ms, background-color 250ms; transition: border-color 250ms, background-color 250ms;
padding: 0 20px; padding: 0 20px;
flex-shrink: 0;
} }
.copyButton span { .copyButton span {

View file

@ -159,10 +159,7 @@ details[open] > summary {
margin-bottom: 16px; margin-bottom: 16px;
} }
*[data-overlay-container] { #root > [data-overlay-container] {
position: fixed; position: relative;
top: 0; height: 100%;
left: 0;
right: 0;
bottom: 0;
} }