From f4936f221fbf6cd6176422b1646751cfe875cd6c Mon Sep 17 00:00:00 2001 From: Robert Long Date: Tue, 4 Jan 2022 17:09:27 -0800 Subject: [PATCH] Clean up registration page --- src/App.jsx | 4 +- src/Home.module.css | 139 ---------------- src/{ => home}/CallList.jsx | 30 ++-- src/{ => home}/CallList.module.css | 32 ++-- src/{Home.jsx => home/HomePage.jsx} | 10 +- src/home/RegisteredView.jsx | 204 +++++++++++------------- src/home/RegisteredView.module.css | 14 ++ src/home/UnauthenticatedView.jsx | 14 +- src/home/UnauthenticatedView.module.css | 32 ---- src/home/common.module.css | 33 ++++ src/icons/Copy.svg | 4 +- src/typography/Typography.jsx | 118 ++++++++++++-- src/typography/Typography.module.css | 6 + 13 files changed, 299 insertions(+), 341 deletions(-) delete mode 100644 src/Home.module.css rename src/{ => home}/CallList.jsx (61%) rename src/{ => home}/CallList.module.css (61%) rename src/{Home.jsx => home/HomePage.jsx} (78%) create mode 100644 src/home/RegisteredView.module.css create mode 100644 src/home/common.module.css diff --git a/src/App.jsx b/src/App.jsx index cf2770e..d462330 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -24,7 +24,7 @@ import { } from "react-router-dom"; import * as Sentry from "@sentry/react"; import { OverlayProvider } from "@react-aria/overlays"; -import { Home } from "./Home"; +import { HomePage } from "./home/HomePage"; import { LoginPage } from "./LoginPage"; import { RegisterPage } from "./RegisterPage"; import { Room } from "./Room"; @@ -45,7 +45,7 @@ export default function App({ history }) { - + diff --git a/src/Home.module.css b/src/Home.module.css deleted file mode 100644 index 15e8534..0000000 --- a/src/Home.module.css +++ /dev/null @@ -1,139 +0,0 @@ -.home { - display: flex; - flex: 1; - flex-direction: column; - min-height: 100%; -} - -.splitContainer { - display: flex; - flex: 1; - flex-direction: column; -} - -.left, -.right { - display: flex; - flex-direction: column; - flex: 1; -} - -.fullWidth { - background-color: var(--bgColor1); -} - -.fullWidth .header { - background-color: var(--bgColor1); -} - -.centered { - display: flex; - flex-direction: column; - flex: 1; - width: 100%; - max-width: 512px; - min-width: 0; -} - -.content { - flex: 1; -} - -.left .content { - display: flex; - flex-direction: column; - align-items: center; -} - -.left .content form > * { - margin-top: 0; - margin-bottom: 24px; -} - -.left .content form > :last-child { - margin-bottom: 0; -} - -.left .content hr:after { - background-color: var(--bgColor1); - content: "OR"; - padding: 0 12px; - position: relative; - top: -12px; -} - -.left .content form { - display: flex; - flex-direction: column; - align-items: center; - padding: 40px 92px; -} - -.fieldRow { - width: 100%; -} - -.button { - height: 40px; - width: 100%; - font-size: 15px; - font-weight: 600; -} - -.left .content form:first-child { - padding-top: 0; -} - -.left .content form:last-child { - padding-bottom: 40px; -} - -.right .content { - padding: 0 40px 40px 40px; -} - -.right .content h3:first-child { - margin-top: 0; -} - -.authLinks { - display: flex; - flex-direction: column; - justify-content: flex-end; - align-items: center; -} - -.authLinks { - margin-bottom: 100px; - font-size: 15px; -} - -.authLinks a { - color: #0dbd8b; - font-weight: normal; - text-decoration: none; -} - -@media (min-width: 800px) { - .left { - background-color: var(--bgColor2); - } - - .home:not(.fullWidth) .left { - max-width: 50%; - } - - .home:not(.fullWidth) .leftNav { - background-color: var(--bgColor2); - } - - .splitContainer { - flex-direction: row; - } - - .fullWidth .content hr:after, - .left .content hr:after, - .fullWidth .header { - background-color: var(--bgColor2); - } -} diff --git a/src/CallList.jsx b/src/home/CallList.jsx similarity index 61% rename from src/CallList.jsx rename to src/home/CallList.jsx index 63cd8e5..8d8fc01 100644 --- a/src/CallList.jsx +++ b/src/home/CallList.jsx @@ -1,16 +1,16 @@ -import React, { useMemo } from "react"; +import React from "react"; import { Link } from "react-router-dom"; -import { CopyButton } from "./button"; -import { Facepile } from "./Facepile"; -import { Avatar } from "./Avatar"; -import { ReactComponent as VideoIcon } from "./icons/Video.svg"; +import { CopyButton } from "../button"; +import { Facepile } from "../Facepile"; +import { Avatar } from "../Avatar"; +import { ReactComponent as VideoIcon } from "../icons/Video.svg"; import styles from "./CallList.module.css"; -import { getRoomUrl } from "./ConferenceCallManagerHooks"; +import { getRoomUrl } from "../ConferenceCallManagerHooks"; +import { Body, Caption } from "../typography/Typography"; -export function CallList({ title, rooms, client }) { +export function CallList({ rooms, client }) { return ( <> -

{title}

{rooms.map(({ roomId, roomName, avatarUrl, participants }) => ( } className={styles.avatar} />
-
{name}
-

{getRoomUrl(roomId)}

+ + {name} + + {getRoomUrl(roomId)} {participants && ( - + )}
diff --git a/src/CallList.module.css b/src/home/CallList.module.css similarity index 61% rename from src/CallList.module.css rename to src/home/CallList.module.css index 1d2b62b..7c658a6 100644 --- a/src/CallList.module.css +++ b/src/home/CallList.module.css @@ -1,6 +1,6 @@ .callTile { - min-width: 240px; - height: 94px; + width: 329px; + height: 95px; padding: 12px; background-color: var(--bgColor2); border-radius: 8px; @@ -31,28 +31,11 @@ } .callInfo > * { - margin-top: 0; - margin-bottom: 8px; -} - -.callInfo > :last-child { margin-bottom: 0; } -.callInfo h5 { - font-size: 15px; - font-weight: 600; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.callInfo p { - font-weight: 400; - font-size: 12px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; +.facePile { + margin-top: 8px; } .copyButtonSpacer, @@ -69,6 +52,11 @@ .callList { display: grid; - grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); + grid-template-columns: repeat(auto-fill, 329px); + max-width: calc((329px + 24px) * 3); + width: calc(100% - 48px); gap: 24px; + padding: 0 24px; + justify-content: center; + margin-bottom: 24px; } diff --git a/src/Home.jsx b/src/home/HomePage.jsx similarity index 78% rename from src/Home.jsx rename to src/home/HomePage.jsx index d26878f..0c5a811 100644 --- a/src/Home.jsx +++ b/src/home/HomePage.jsx @@ -15,12 +15,12 @@ limitations under the License. */ import React from "react"; -import { useClient } from "./ConferenceCallManagerHooks"; -import { ErrorView, LoadingView } from "./FullScreenView"; -import { UnauthenticatedView } from "./home/UnauthenticatedView"; -import { RegisteredView } from "./home/RegisteredView"; +import { useClient } from "../ConferenceCallManagerHooks"; +import { ErrorView, LoadingView } from "../FullScreenView"; +import { UnauthenticatedView } from "./UnauthenticatedView"; +import { RegisteredView } from "./RegisteredView"; -export function Home() { +export function HomePage() { const { isAuthenticated, isPasswordlessUser, loading, error, client } = useClient(); diff --git a/src/home/RegisteredView.jsx b/src/home/RegisteredView.jsx index eabec9b..e17ef12 100644 --- a/src/home/RegisteredView.jsx +++ b/src/home/RegisteredView.jsx @@ -1,131 +1,117 @@ -import React from "react"; -import { Link } from "react-router-dom"; +import React, { useState, useCallback } from "react"; import { + createRoom, useGroupCallRooms, - usePublicRooms, + roomAliasFromRoomName, } from "../ConferenceCallManagerHooks"; import { Header, HeaderLogo, LeftNav, RightNav } from "../Header"; -import styles from "../Home.module.css"; +import commonStyles from "./common.module.css"; +import styles from "./RegisteredView.module.css"; import { FieldRow, InputField, ErrorMessage } from "../Input"; import { Button } from "../button"; -import { CallList } from "../CallList"; -import classNames from "classnames"; +import { CallList } from "./CallList"; import { UserMenuContainer } from "../UserMenuContainer"; +import { useModalTriggerState } from "../Modal"; +import { JoinExistingCallModal } from "../JoinExistingCallModal"; +import { useHistory } from "react-router-dom"; +import { Headline, Title } from "../typography/Typography"; +import { Form } from "../form/Form"; -export function RegisteredView({ - client, - isPasswordlessUser, - onCreateRoom, - createRoomError, - creatingRoom, - onJoinRoom, -}) { - const publicRooms = usePublicRooms( - client, - import.meta.env.VITE_PUBLIC_SPACE_ROOM_ID +export function RegisteredView({ client }) { + const [loading, setLoading] = useState(false); + const [error, setError] = useState(); + const onSubmit = useCallback( + (e) => { + e.preventDefault(); + const data = new FormData(e.target); + const roomName = data.get("roomName"); + + async function submit() { + setError(undefined); + setLoading(true); + + const roomIdOrAlias = await createRoom(client, roomName); + + if (roomIdOrAlias) { + history.push(`/room/${roomIdOrAlias}`); + } + } + + submit().catch((error) => { + if (error.errcode === "M_ROOM_IN_USE") { + setExistingRoomId(roomAliasFromRoomName(roomName)); + setError(undefined); + modalState.open(); + } else { + console.error(error); + setLoading(false); + setError(error); + reset(); + } + }); + }, + [client] ); + const recentRooms = useGroupCallRooms(client); - const hideCallList = publicRooms.length === 0 && recentRooms.length === 0; + const { modalState, modalProps } = useModalTriggerState(); + const [existingRoomId, setExistingRoomId] = useState(); + const history = useHistory(); + const onJoinExistingRoom = useCallback(() => { + history.push(`/${existingRoomId}`); + }, [history, existingRoomId]); return ( -
-
- + <> +
+
-
-
-
-
-
-

Join a call

- - - - - - -
-
-
-

Create a call

- - - - {createRoomError && ( - - {createRoomError.message} - - )} - - - -
- {isPasswordlessUser && ( -
-

- Not registered yet?{" "} - Create an account -

-
- )} -
-
-
- {!hideCallList && ( -
-
- {publicRooms.length > 0 && ( - - )} - {recentRooms.length > 0 && ( - - )} -
-
- )} +
+
+ + + Enter a call name + +
+ + + + + {error && ( + + {error.message} + + )} +
+ {recentRooms.length > 0 && ( + <> + + Your recent Calls + + + + )} +
-
+ {modalState.isOpen && ( + + )} + ); } diff --git a/src/home/RegisteredView.module.css b/src/home/RegisteredView.module.css new file mode 100644 index 0000000..03eff0a --- /dev/null +++ b/src/home/RegisteredView.module.css @@ -0,0 +1,14 @@ +.form { + padding: 0 24px; + justify-content: center; + width: 409px; + margin-bottom: 72px; +} + +.fieldRow { + margin-bottom: 0; +} + +.recentCallsTitle { + margin-bottom: 32px; +} diff --git a/src/home/UnauthenticatedView.jsx b/src/home/UnauthenticatedView.jsx index 8c0b684..c779817 100644 --- a/src/home/UnauthenticatedView.jsx +++ b/src/home/UnauthenticatedView.jsx @@ -8,13 +8,15 @@ import { randomString } from "matrix-js-sdk/src/randomstring"; import { createRoom, useInteractiveRegistration, + roomAliasFromRoomName, } from "../ConferenceCallManagerHooks"; import { useModalTriggerState } from "../Modal"; import { JoinExistingCallModal } from "../JoinExistingCallModal"; import { useRecaptcha } from "../useRecaptcha"; -import { Body, Caption, Title, Link, Headline } from "../typography/Typography"; +import { Body, Caption, Link, Headline } from "../typography/Typography"; import { Form } from "../form/Form"; import styles from "./UnauthenticatedView.module.css"; +import commonStyles from "./common.module.css"; export function UnauthenticatedView() { const [loading, setLoading] = useState(false); @@ -80,10 +82,12 @@ export function UnauthenticatedView() {
-
-
- - Enter a call name +
+
+ + + Enter a call name +
- + + diff --git a/src/typography/Typography.jsx b/src/typography/Typography.jsx index 9193a48..a1f6ec2 100644 --- a/src/typography/Typography.jsx +++ b/src/typography/Typography.jsx @@ -4,11 +4,25 @@ import { Link as RouterLink } from "react-router-dom"; import styles from "./Typography.module.css"; export const Headline = forwardRef( - ({ as: Component = "h1", children, className, fontWeight, ...rest }, ref) => { + ( + { + as: Component = "h1", + children, + className, + fontWeight, + overflowEllipsis, + ...rest + }, + ref + ) => { return ( {children} @@ -18,11 +32,25 @@ export const Headline = forwardRef( ); export const Title = forwardRef( - ({ as: Component = "h2", children, className, fontWeight, ...rest }, ref) => { + ( + { + as: Component = "h2", + children, + className, + fontWeight, + overflowEllipsis, + ...rest + }, + ref + ) => { return ( {children} @@ -32,11 +60,25 @@ export const Title = forwardRef( ); export const Subtitle = forwardRef( - ({ as: Component = "h3", children, className, fontWeight, ...rest }, ref) => { + ( + { + as: Component = "h3", + children, + className, + fontWeight, + overflowEllipsis, + ...rest + }, + ref + ) => { return ( {children} @@ -46,11 +88,25 @@ export const Subtitle = forwardRef( ); export const Body = forwardRef( - ({ as: Component = "p", children, className, fontWeight, ...rest }, ref) => { + ( + { + as: Component = "p", + children, + className, + fontWeight, + overflowEllipsis, + ...rest + }, + ref + ) => { return ( {children} @@ -60,11 +116,26 @@ export const Body = forwardRef( ); export const Caption = forwardRef( - ({ as: Component = "p", children, className, fontWeight, ...rest }, ref) => { + ( + { + as: Component = "p", + children, + className, + fontWeight, + overflowEllipsis, + ...rest + }, + ref + ) => { return ( {children} @@ -74,11 +145,26 @@ export const Caption = forwardRef( ); export const Micro = forwardRef( - ({ as: Component = "p", children, className, fontWeight, ...rest }, ref) => { + ( + { + as: Component = "p", + children, + className, + fontWeight, + overflowEllipsis, + ...rest + }, + ref + ) => { return ( {children} @@ -96,6 +182,7 @@ export const Link = forwardRef( color = "link", href, fontWeight, + overflowEllipsis, ...rest }, ref @@ -113,7 +200,12 @@ export const Link = forwardRef( {children} diff --git a/src/typography/Typography.module.css b/src/typography/Typography.module.css index ca6e354..0719fbf 100644 --- a/src/typography/Typography.module.css +++ b/src/typography/Typography.module.css @@ -27,3 +27,9 @@ .primary { color: var(--primaryColor); } + +.overflowEllipsis { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +}