Merge pull request #485 from toger5/ts_Form+Home

This commit is contained in:
Timo 2022-08-01 18:20:59 +02:00 committed by GitHub
commit 44b9bd0046
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 103 additions and 39 deletions

View file

@ -62,6 +62,7 @@ interface ClientState {
changePassword: (password: string) => Promise<void>;
logout: () => void;
setClient: (client: MatrixClient, session: Session) => void;
error?: Error;
}
const ClientContext = createContext<ClientState>(null);

View file

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

View file

@ -15,13 +15,26 @@ limitations under the License.
*/
import classNames from "classnames";
import React, { forwardRef } from "react";
import React, { FormEventHandler, forwardRef } from "react";
import styles from "./Form.module.css";
export const Form = forwardRef(({ children, className, ...rest }, ref) => {
return (
<form {...rest} className={classNames(styles.form, className)} ref={ref}>
{children}
</form>
);
});
interface FormProps {
className: string;
onSubmit: FormEventHandler<HTMLFormElement>;
children: JSX.Element[];
}
export const Form = forwardRef<HTMLFormElement, FormProps>(
({ children, className, onSubmit }, ref) => {
return (
<form
onSubmit={onSubmit}
className={classNames(styles.form, className)}
ref={ref}
>
{children}
</form>
);
}
);

View file

@ -16,14 +16,22 @@ limitations under the License.
import React from "react";
import { Link } from "react-router-dom";
import { MatrixClient, RoomMember } from "matrix-js-sdk";
import { CopyButton } from "../button";
import { Facepile } from "../Facepile";
import { Avatar } from "../Avatar";
import { Avatar, Size } from "../Avatar";
import styles from "./CallList.module.css";
import { getRoomUrl } from "../matrix-utils";
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 (
<>
<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({
name,
avatarUrl,
@ -56,12 +71,12 @@ function CallTile({
participants,
client,
disableFacepile,
}) {
}: CallTileProps) {
return (
<div className={styles.callTile}>
<Link to={`/room/${roomId}`} className={styles.callTileLink}>
<Avatar
size="lg"
size={Size.LG}
bgKey={name}
src={avatarUrl}
fallback={name.slice(0, 1).toUpperCase()}

View file

@ -15,6 +15,7 @@ limitations under the License.
*/
import React from "react";
import { useClient } from "../ClientContext";
import { ErrorView, LoadingView } from "../FullScreenView";
import { UnauthenticatedView } from "./UnauthenticatedView";

View file

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

View file

@ -14,7 +14,15 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { useState, useCallback } from "react";
import React, {
useState,
useCallback,
FormEvent,
FormEventHandler,
} from "react";
import { useHistory } from "react-router-dom";
import { MatrixClient } from "matrix-js-sdk";
import { createRoom, roomAliasLocalpartFromRoomName } from "../matrix-utils";
import { useGroupCallRooms } from "./useGroupCallRooms";
import { Header, HeaderLogo, LeftNav, RightNav } from "../Header";
@ -26,28 +34,35 @@ import { CallList } from "./CallList";
import { UserMenuContainer } from "../UserMenuContainer";
import { useModalTriggerState } from "../Modal";
import { JoinExistingCallModal } from "./JoinExistingCallModal";
import { useHistory } from "react-router-dom";
import { Title } from "../typography/Typography";
import { Form } from "../form/Form";
import { CallType, CallTypeDropdown } from "./CallTypeDropdown";
export function RegisteredView({ client }) {
interface Props {
client: MatrixClient;
isPasswordlessUser: boolean;
}
export function RegisteredView({ client, isPasswordlessUser }: Props) {
const [callType, setCallType] = useState(CallType.Video);
const [loading, setLoading] = useState(false);
const [error, setError] = useState();
const [error, setError] = useState<Error>();
const history = useHistory();
const onSubmit = useCallback(
(e) => {
const { modalState, modalProps } = useModalTriggerState();
const onSubmit: FormEventHandler<HTMLFormElement> = useCallback(
(e: FormEvent) => {
e.preventDefault();
const data = new FormData(e.target);
const roomName = data.get("callName");
const ptt = callType === CallType.Radio;
const data = new FormData(e.target as HTMLFormElement);
const roomNameData = data.get("callName");
const roomName = typeof roomNameData === "string" ? roomNameData : "";
// const ptt = callType === CallType.Radio;
async function submit() {
setError(undefined);
setLoading(true);
const [roomIdOrAlias] = await createRoom(client, roomName, ptt);
const [roomIdOrAlias] = await createRoom(client, roomName);
if (roomIdOrAlias) {
history.push(`/room/${roomIdOrAlias}`);
@ -64,17 +79,15 @@ export function RegisteredView({ client }) {
console.error(error);
setLoading(false);
setError(error);
reset();
}
});
},
[client, callType]
[client, history, modalState]
);
const recentRooms = useGroupCallRooms(client);
const { modalState, modalProps } = useModalTriggerState();
const [existingRoomId, setExistingRoomId] = useState();
const [existingRoomId, setExistingRoomId] = useState<string>();
const onJoinExistingRoom = useCallback(() => {
history.push(`/${existingRoomId}`);
}, [history, existingRoomId]);

View file

@ -14,11 +14,21 @@ See the License for the specific language governing permissions and
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";
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]) {
return tsCache[r.roomId];
}
@ -59,13 +69,13 @@ function getLastTs(client, r) {
return ts;
}
function sortRooms(client, rooms) {
function sortRooms(client: MatrixClient, rooms: Room[]): Room[] {
return rooms.sort((a, b) => {
return getLastTs(client, b) - getLastTs(client, a);
});
}
export function useGroupCallRooms(client) {
export function useGroupCallRooms(client: MatrixClient): GroupCallRoom[] {
const [rooms, setRooms] = useState([]);
useEffect(() => {
@ -90,12 +100,15 @@ export function useGroupCallRooms(client) {
updateRooms();
client.on("GroupCall.incoming", updateRooms);
client.on("GroupCall.participants", updateRooms);
client.on(GroupCallEventHandlerEvent.Incoming, updateRooms);
client.on(GroupCallEventHandlerEvent.Participants, updateRooms);
return () => {
client.removeListener("GroupCall.incoming", updateRooms);
client.removeListener("GroupCall.participants", updateRooms);
client.removeListener(GroupCallEventHandlerEvent.Incoming, updateRooms);
client.removeListener(
GroupCallEventHandlerEvent.Participants,
updateRooms
);
};
}, [client]);