Redesign homepage WIP
This commit is contained in:
394
src/Home.jsx
394
src/Home.jsx
@@ -14,399 +14,25 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React, { useCallback, useState, useRef, useEffect } from "react";
|
||||
import { useHistory, Link } from "react-router-dom";
|
||||
import {
|
||||
useClient,
|
||||
useGroupCallRooms,
|
||||
usePublicRooms,
|
||||
createRoom,
|
||||
roomAliasFromRoomName,
|
||||
useInteractiveRegistration,
|
||||
} from "./ConferenceCallManagerHooks";
|
||||
import { Header, HeaderLogo, LeftNav, RightNav } from "./Header";
|
||||
import styles from "./Home.module.css";
|
||||
import { FieldRow, InputField, ErrorMessage } from "./Input";
|
||||
import { UserMenu } from "./UserMenu";
|
||||
import { Button } from "./button";
|
||||
import { CallList } from "./CallList";
|
||||
import classNames from "classnames";
|
||||
import React from "react";
|
||||
import { useClient } from "./ConferenceCallManagerHooks";
|
||||
import { ErrorView, LoadingView } from "./FullScreenView";
|
||||
import { useModalTriggerState } from "./Modal";
|
||||
import { randomString } from "matrix-js-sdk/src/randomstring";
|
||||
import { JoinExistingCallModal } from "./JoinExistingCallModal";
|
||||
import { RecaptchaInput } from "./RecaptchaInput";
|
||||
import { UserMenuContainer } from "./UserMenuContainer";
|
||||
import { UnauthenticatedView } from "./home/UnauthenticatedView";
|
||||
import { RegisteredView } from "./home/RegisteredView";
|
||||
|
||||
export function Home() {
|
||||
const {
|
||||
isAuthenticated,
|
||||
isGuest,
|
||||
isPasswordlessUser,
|
||||
loading,
|
||||
error,
|
||||
client,
|
||||
} = useClient();
|
||||
|
||||
const [{ privacyPolicyUrl, recaptchaKey }, register] =
|
||||
useInteractiveRegistration();
|
||||
const [recaptchaResponse, setRecaptchaResponse] = useState();
|
||||
|
||||
const history = useHistory();
|
||||
const [creatingRoom, setCreatingRoom] = useState(false);
|
||||
const [createRoomError, setCreateRoomError] = useState();
|
||||
const { modalState, modalProps } = useModalTriggerState();
|
||||
const [existingRoomId, setExistingRoomId] = useState();
|
||||
|
||||
const onCreateRoom = useCallback(
|
||||
(e) => {
|
||||
e.preventDefault();
|
||||
const data = new FormData(e.target);
|
||||
const roomName = data.get("roomName");
|
||||
const userName = data.get("userName");
|
||||
|
||||
async function onCreateRoom() {
|
||||
let _client = client;
|
||||
|
||||
if (!recaptchaResponse) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_client || isGuest) {
|
||||
_client = await register(
|
||||
userName,
|
||||
randomString(16),
|
||||
recaptchaResponse,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
const roomIdOrAlias = await createRoom(_client, roomName);
|
||||
|
||||
if (roomIdOrAlias) {
|
||||
history.push(`/room/${roomIdOrAlias}`);
|
||||
}
|
||||
}
|
||||
|
||||
setCreateRoomError(undefined);
|
||||
setCreatingRoom(true);
|
||||
|
||||
return onCreateRoom().catch((error) => {
|
||||
if (error.errcode === "M_ROOM_IN_USE") {
|
||||
setExistingRoomId(roomAliasFromRoomName(roomName));
|
||||
setCreateRoomError(undefined);
|
||||
modalState.open();
|
||||
} else {
|
||||
setCreateRoomError(error);
|
||||
}
|
||||
|
||||
setCreatingRoom(false);
|
||||
});
|
||||
},
|
||||
[client, history, register, isGuest, recaptchaResponse]
|
||||
);
|
||||
|
||||
const onJoinRoom = useCallback(
|
||||
(e) => {
|
||||
e.preventDefault();
|
||||
const data = new FormData(e.target);
|
||||
const roomId = data.get("roomId");
|
||||
history.push(`/${roomId}`);
|
||||
},
|
||||
[history]
|
||||
);
|
||||
|
||||
const onJoinExistingRoom = useCallback(() => {
|
||||
history.push(`/${existingRoomId}`);
|
||||
}, [history, existingRoomId]);
|
||||
const { isAuthenticated, isPasswordlessUser, loading, error, client } =
|
||||
useClient();
|
||||
|
||||
if (loading) {
|
||||
return <LoadingView />;
|
||||
} else if (error) {
|
||||
return <ErrorView error={error} />;
|
||||
} else {
|
||||
return (
|
||||
<>
|
||||
{!isAuthenticated || isGuest ? (
|
||||
<UnregisteredView
|
||||
onCreateRoom={onCreateRoom}
|
||||
createRoomError={createRoomError}
|
||||
creatingRoom={creatingRoom}
|
||||
onJoinRoom={onJoinRoom}
|
||||
privacyPolicyUrl={privacyPolicyUrl}
|
||||
recaptchaKey={recaptchaKey}
|
||||
setRecaptchaResponse={setRecaptchaResponse}
|
||||
/>
|
||||
) : (
|
||||
<RegisteredView
|
||||
client={client}
|
||||
isPasswordlessUser={isPasswordlessUser}
|
||||
isGuest={isGuest}
|
||||
onCreateRoom={onCreateRoom}
|
||||
createRoomError={createRoomError}
|
||||
creatingRoom={creatingRoom}
|
||||
onJoinRoom={onJoinRoom}
|
||||
/>
|
||||
)}
|
||||
{modalState.isOpen && (
|
||||
<JoinExistingCallModal onJoin={onJoinExistingRoom} {...modalProps} />
|
||||
)}
|
||||
</>
|
||||
return isAuthenticated ? (
|
||||
<RegisteredView isPasswordlessUser={isPasswordlessUser} client={client} />
|
||||
) : (
|
||||
<UnauthenticatedView />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function UnregisteredView({
|
||||
onCreateRoom,
|
||||
createRoomError,
|
||||
creatingRoom,
|
||||
onJoinRoom,
|
||||
privacyPolicyUrl,
|
||||
recaptchaKey,
|
||||
setRecaptchaResponse,
|
||||
}) {
|
||||
const acceptTermsRef = useRef();
|
||||
const [acceptTerms, setAcceptTerms] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!acceptTermsRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!acceptTerms) {
|
||||
acceptTermsRef.current.setCustomValidity(
|
||||
"You must accept the terms to continue."
|
||||
);
|
||||
} else {
|
||||
acceptTermsRef.current.setCustomValidity("");
|
||||
}
|
||||
}, [acceptTerms]);
|
||||
|
||||
return (
|
||||
<div className={classNames(styles.home, styles.fullWidth)}>
|
||||
<Header className={styles.header}>
|
||||
<LeftNav>
|
||||
<HeaderLogo />
|
||||
</LeftNav>
|
||||
<RightNav>
|
||||
<UserMenuContainer />
|
||||
</RightNav>
|
||||
</Header>
|
||||
<div className={styles.splitContainer}>
|
||||
<div className={styles.left}>
|
||||
<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="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>
|
||||
<FieldRow>
|
||||
<InputField
|
||||
id="acceptTerms"
|
||||
type="checkbox"
|
||||
name="acceptTerms"
|
||||
onChange={(e) => setAcceptTerms(e.target.checked)}
|
||||
checked={acceptTerms}
|
||||
label="Accept Privacy Policy"
|
||||
ref={acceptTermsRef}
|
||||
/>
|
||||
<a target="_blank" href={privacyPolicyUrl}>
|
||||
Privacy Policy
|
||||
</a>
|
||||
</FieldRow>
|
||||
{recaptchaKey && (
|
||||
<FieldRow>
|
||||
<RecaptchaInput
|
||||
publicKey={recaptchaKey}
|
||||
onResponse={setRecaptchaResponse}
|
||||
/>
|
||||
</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 className={styles.authLinks}>
|
||||
<p>
|
||||
Not registered yet?{" "}
|
||||
<Link to="/register">Create an account</Link>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function RegisteredView({
|
||||
client,
|
||||
isPasswordlessUser,
|
||||
isGuest,
|
||||
onCreateRoom,
|
||||
createRoomError,
|
||||
creatingRoom,
|
||||
onJoinRoom,
|
||||
}) {
|
||||
const publicRooms = usePublicRooms(
|
||||
client,
|
||||
import.meta.env.VITE_PUBLIC_SPACE_ROOM_ID
|
||||
);
|
||||
const recentRooms = useGroupCallRooms(client);
|
||||
|
||||
const hideCallList = publicRooms.length === 0 && recentRooms.length === 0;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(styles.home, {
|
||||
[styles.fullWidth]: hideCallList,
|
||||
})}
|
||||
>
|
||||
<Header className={styles.header}>
|
||||
<LeftNav className={styles.leftNav}>
|
||||
<HeaderLogo />
|
||||
</LeftNav>
|
||||
<RightNav>
|
||||
<UserMenuContainer />
|
||||
</RightNav>
|
||||
</Header>
|
||||
<div className={styles.splitContainer}>
|
||||
<div className={styles.left}>
|
||||
<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>
|
||||
{(isPasswordlessUser || isGuest) && (
|
||||
<div className={styles.authLinks}>
|
||||
<p>
|
||||
Not registered yet?{" "}
|
||||
<Link to="/register">Create an account</Link>
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{!hideCallList && (
|
||||
<div className={styles.right}>
|
||||
<div className={styles.content}>
|
||||
{publicRooms.length > 0 && (
|
||||
<CallList
|
||||
title="Public Calls"
|
||||
rooms={publicRooms}
|
||||
client={client}
|
||||
/>
|
||||
)}
|
||||
{recentRooms.length > 0 && (
|
||||
<CallList
|
||||
title="Recent Calls"
|
||||
rooms={recentRooms}
|
||||
client={client}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user