form_home

This commit is contained in:
Timo K 2022-07-14 19:20:52 +02:00
commit e17a7cedb6
7 changed files with 64 additions and 25 deletions

View file

@ -59,6 +59,7 @@ interface ClientState {
isPasswordlessUser: boolean; isPasswordlessUser: boolean;
client: MatrixClient; client: MatrixClient;
userName: string; userName: string;
error: Error;
changePassword: (password: string) => Promise<void>; changePassword: (password: string) => Promise<void>;
logout: () => void; logout: () => void;
setClient: (client: MatrixClient, session: Session) => void; setClient: (client: MatrixClient, session: Session) => void;

View file

@ -23,10 +23,10 @@ import { Button, ButtonVariant } from "./Button";
interface Props { interface Props {
value: string; value: string;
children: JSX.Element; children?: JSX.Element;
className: string; className: string;
variant: ButtonVariant; variant: ButtonVariant;
copiedMessage: string; copiedMessage?: string;
} }
export function CopyButton({ export function CopyButton({
value, value,

View file

@ -16,14 +16,22 @@ limitations under the License.
import React from "react"; import React from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { MatrixClient, Room, RoomMember } from "matrix-js-sdk";
import { CopyButton } from "../button"; import { CopyButton } from "../button";
import { Facepile } from "../Facepile"; import { Facepile } from "../Facepile";
import { Avatar } from "../Avatar"; import { Avatar, Size } from "../Avatar";
import styles from "./CallList.module.css"; import styles from "./CallList.module.css";
import { getRoomUrl } from "../matrix-utils"; import { getRoomUrl } from "../matrix-utils";
import { Body, Caption } from "../typography/Typography"; import { Body, Caption } from "../typography/Typography";
import { GroupCallRoom } from "./useGroupCallRooms";
export function CallList({ rooms, client, disableFacepile }) { interface CallListProps {
rooms: GroupCallRoom[];
client: MatrixClient;
disableFacepile: boolean;
}
export function CallList({ rooms, client, disableFacepile }: CallListProps) {
return ( return (
<> <>
<div className={styles.callList}> <div className={styles.callList}>
@ -48,7 +56,14 @@ export function CallList({ rooms, client, disableFacepile }) {
</> </>
); );
} }
interface CallTileProps {
name: string;
avatarUrl: string;
roomId: string;
participants: RoomMember[];
client: MatrixClient;
disableFacepile: boolean;
}
function CallTile({ function CallTile({
name, name,
avatarUrl, avatarUrl,
@ -56,12 +71,12 @@ function CallTile({
participants, participants,
client, client,
disableFacepile, disableFacepile,
}) { }: CallTileProps) {
return ( return (
<div className={styles.callTile}> <div className={styles.callTile}>
<Link to={`/room/${roomId}`} className={styles.callTileLink}> <Link to={`/room/${roomId}`} className={styles.callTileLink}>
<Avatar <Avatar
size="lg" size={Size.LG}
bgKey={name} bgKey={name}
src={avatarUrl} src={avatarUrl}
fallback={name.slice(0, 1).toUpperCase()} fallback={name.slice(0, 1).toUpperCase()}

View file

@ -15,18 +15,24 @@ limitations under the License.
*/ */
import React from "react"; import React from "react";
import { PressEvent } from "@react-types/shared";
import { Modal, ModalContent } from "../Modal"; import { Modal, ModalContent } from "../Modal";
import { Button } from "../button"; import { Button } from "../button";
import { FieldRow } from "../input/Input"; import { FieldRow } from "../input/Input";
import styles from "./JoinExistingCallModal.module.css"; import styles from "./JoinExistingCallModal.module.css";
interface Props {
export function JoinExistingCallModal({ onJoin, ...rest }) { onJoin: (e: PressEvent) => void;
onClose: (e: PressEvent) => void;
[index: string]: unknown;
}
export function JoinExistingCallModal({ onJoin, onClose, ...rest }: Props) {
return ( return (
<Modal title="Join existing call?" isDismissable {...rest}> <Modal title="Join existing call?" isDismissable {...rest}>
<ModalContent> <ModalContent>
<p>This call already exists, would you like to join?</p> <p>This call already exists, would you like to join?</p>
<FieldRow rightAlign className={styles.buttons}> <FieldRow rightAlign className={styles.buttons}>
<Button onPress={rest.onClose}>No</Button> <Button onPress={onClose}>No</Button>
<Button onPress={onJoin}>Yes, join call</Button> <Button onPress={onJoin}>Yes, join call</Button>
</FieldRow> </FieldRow>
</ModalContent> </ModalContent>

View file

@ -15,6 +15,9 @@ limitations under the License.
*/ */
import React, { useState, useCallback } from "react"; import React, { useState, useCallback } from "react";
import { useHistory } from "react-router-dom";
import { MatrixClient } from "matrix-js-sdk";
import { createRoom, roomAliasLocalpartFromRoomName } from "../matrix-utils"; import { createRoom, roomAliasLocalpartFromRoomName } from "../matrix-utils";
import { useGroupCallRooms } from "./useGroupCallRooms"; import { useGroupCallRooms } from "./useGroupCallRooms";
import { Header, HeaderLogo, LeftNav, RightNav } from "../Header"; import { Header, HeaderLogo, LeftNav, RightNav } from "../Header";
@ -26,21 +29,23 @@ import { CallList } from "./CallList";
import { UserMenuContainer } from "../UserMenuContainer"; import { UserMenuContainer } from "../UserMenuContainer";
import { useModalTriggerState } from "../Modal"; import { useModalTriggerState } from "../Modal";
import { JoinExistingCallModal } from "./JoinExistingCallModal"; import { JoinExistingCallModal } from "./JoinExistingCallModal";
import { useHistory } from "react-router-dom";
import { Title } from "../typography/Typography"; import { Title } from "../typography/Typography";
import { Form } from "../form/Form"; import { Form } from "../form/Form";
import { CallType, CallTypeDropdown } from "./CallTypeDropdown"; import { CallType, CallTypeDropdown } from "./CallTypeDropdown";
export function RegisteredView({ client }) { export function RegisteredView({ client }: { client: MatrixClient }) {
const [callType, setCallType] = useState(CallType.Video); const [callType, setCallType] = useState(CallType.Video);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [error, setError] = useState(); const [error, setError] = useState<Error>();
const history = useHistory(); const history = useHistory();
const { modalState, modalProps } = useModalTriggerState();
const onSubmit = useCallback( const onSubmit = useCallback(
(e) => { (e) => {
e.preventDefault(); e.preventDefault();
const data = new FormData(e.target); const data = new FormData(e.target);
const roomName = data.get("callName"); const roomNameData = data.get("callName");
const roomName = typeof roomNameData === "string" ? roomNameData : "";
const ptt = callType === CallType.Radio; const ptt = callType === CallType.Radio;
async function submit() { async function submit() {
@ -68,13 +73,12 @@ export function RegisteredView({ client }) {
} }
}); });
}, },
[client, callType] [callType, client, history, modalState]
); );
const recentRooms = useGroupCallRooms(client); const recentRooms = useGroupCallRooms(client);
const { modalState, modalProps } = useModalTriggerState(); const [existingRoomId, setExistingRoomId] = useState<string>();
const [existingRoomId, setExistingRoomId] = useState();
const onJoinExistingRoom = useCallback(() => { const onJoinExistingRoom = useCallback(() => {
history.push(`/${existingRoomId}`); history.push(`/${existingRoomId}`);
}, [history, existingRoomId]); }, [history, existingRoomId]);

View file

@ -14,11 +14,21 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import { GroupCall, MatrixClient, Room, RoomMember } from "matrix-js-sdk";
import { GroupCallEventHandlerEvent } from "matrix-js-sdk/src/webrtc/groupCallEventHandler";
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
const tsCache = {}; export interface GroupCallRoom {
roomId: string;
roomName: string;
avatarUrl: string;
room: Room;
groupCall: GroupCall;
participants: RoomMember[];
}
const tsCache: { [index: string]: number } = {};
function getLastTs(client, r) { function getLastTs(client: MatrixClient, r: Room) {
if (tsCache[r.roomId]) { if (tsCache[r.roomId]) {
return tsCache[r.roomId]; return tsCache[r.roomId];
} }
@ -59,13 +69,13 @@ function getLastTs(client, r) {
return ts; return ts;
} }
function sortRooms(client, rooms) { function sortRooms(client: MatrixClient, rooms: Room[]): Room[] {
return rooms.sort((a, b) => { return rooms.sort((a, b) => {
return getLastTs(client, b) - getLastTs(client, a); return getLastTs(client, b) - getLastTs(client, a);
}); });
} }
export function useGroupCallRooms(client) { export function useGroupCallRooms(client: MatrixClient): GroupCallRoom[] {
const [rooms, setRooms] = useState([]); const [rooms, setRooms] = useState([]);
useEffect(() => { useEffect(() => {
@ -90,12 +100,15 @@ export function useGroupCallRooms(client) {
updateRooms(); updateRooms();
client.on("GroupCall.incoming", updateRooms); client.on(GroupCallEventHandlerEvent.Incoming, updateRooms);
client.on("GroupCall.participants", updateRooms); client.on(GroupCallEventHandlerEvent.Participants, updateRooms);
return () => { return () => {
client.removeListener("GroupCall.incoming", updateRooms); client.removeListener(GroupCallEventHandlerEvent.Incoming, updateRooms);
client.removeListener("GroupCall.participants", updateRooms); client.removeListener(
GroupCallEventHandlerEvent.Participants,
updateRooms
);
}; };
}, [client]); }, [client]);