diff --git a/src/App.jsx b/src/App.jsx index 67ef05b..cff7900 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -23,7 +23,7 @@ import { useLocation, } from "react-router-dom"; import { useConferenceCallManager } from "./ConferenceCallManagerHooks"; -import { JoinOrCreateRoom } from "./JoinOrCreateRoom"; +import { Home } from "./Home"; import { LoginOrRegister } from "./LoginOrRegister"; import { Room } from "./Room"; import { GridDemo } from "./GridDemo"; @@ -37,7 +37,7 @@ export default function App() { return ( -
+ <> {error &&

{error.message}

} {loading ? (

Loading...

@@ -45,7 +45,7 @@ export default function App() { {authenticated ? ( - + ) : ( )} @@ -61,7 +61,7 @@ export default function App() { )} -
+
); } diff --git a/src/Header.jsx b/src/Header.jsx new file mode 100644 index 0000000..6573b38 --- /dev/null +++ b/src/Header.jsx @@ -0,0 +1,40 @@ +import classNames from "classnames"; +import React from "react"; +import { Link } from "react-router-dom"; +import styles from "./Header.module.css"; +import { ReactComponent as Logo } from "./Logo.svg"; + +export function Header({ children, className, ...rest }) { + return ( +
+ {children} +
+ ); +} + +export function LeftNav({ children, className, ...rest }) { + return ( +
+ + + + {children} +
+ ); +} + +export function CenterNav({ children, className, ...rest }) { + return ( +
+ {children} +
+ ); +} + +export function RightNav({ children, className, ...rest }) { + return ( +
+ {children} +
+ ); +} diff --git a/src/Header.module.css b/src/Header.module.css new file mode 100644 index 0000000..55c3eef --- /dev/null +++ b/src/Header.module.css @@ -0,0 +1,25 @@ +.header { + position: relative; + display: flex; + justify-content: center; + align-items: center; + height: 98px; + user-select: none; +} + +.leftNav { + position: absolute; + left: 20px; +} + +.logo { + display: flex; + align-items: center; + text-decoration: none; +} + +.rightNav { + position: absolute; + right: 20px; + max-width: 30%; +} \ No newline at end of file diff --git a/src/Home.jsx b/src/Home.jsx new file mode 100644 index 0000000..2251b86 --- /dev/null +++ b/src/Home.jsx @@ -0,0 +1,123 @@ +/* +Copyright 2021 New Vector Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React, { useCallback, useRef, useState } from "react"; +import { useHistory, Link } from "react-router-dom"; +import { useRooms } from "./ConferenceCallManagerHooks"; +import { Header, LeftNav, RightNav } from "./Header"; +import ColorHash from "color-hash"; +import styles from "./Home.module.css"; +import { FieldRow, InputField, Button } from "./Input"; + +const colorHash = new ColorHash({ lightness: 0.3 }); + +export function Home({ manager }) { + const history = useHistory(); + const roomNameRef = useRef(); + const [createRoomError, setCreateRoomError] = useState(); + const rooms = useRooms(manager); + + const onCreateRoom = useCallback( + (e) => { + e.preventDefault(); + setCreateRoomError(undefined); + + manager.client + .createRoom({ + visibility: "private", + preset: "public_chat", + name: roomNameRef.current.value, + }) + .then(({ room_id }) => { + history.push(`/room/${room_id}`); + }) + .catch(setCreateRoomError); + }, + [manager] + ); + + const onLogout = useCallback( + (e) => { + e.preventDefault(); + manager.logout(); + location.reload(); + }, + [manager] + ); + + return ( + <> +
+ + + + {manager.client && manager.client.getUserId()} + + + +
+
+
+
Rooms:
+
+ {rooms.map((room) => ( + +
+ {room.name.slice(0, 1)} +
+
{room.name}
+ + ))} +
+
+
+
+

Create New Room

+ + + + {createRoomError &&

{createRoomError.message}

} + + + +
+
+
+ + ); +} diff --git a/src/Home.module.css b/src/Home.module.css new file mode 100644 index 0000000..1c30d98 --- /dev/null +++ b/src/Home.module.css @@ -0,0 +1,99 @@ +.content { + display: grid; + grid-template-columns: minmax(200px, 320px) 3fr; + gap: 20px; + margin: 0 20px; + flex: 1; +} + +.roomsSidebar { + padding: 12px; + background-color: rgba(33,38,44,.9); + border-radius: 8px; +} + +.roomsSidebar h5 { + color: rgb(142, 153, 164); + font-size: 13px; + margin: 0 0 8px 0; +} + +.roomList { + +} + +.roomListItem { + margin-bottom: 4px; + padding: 4px; + display: flex; + cursor: pointer; + text-decoration: none; + color: white; + align-items: center; +} + +.roomListItem:hover { + background-color: rgba(141, 151, 165, 0.2); + border-radius: 8px; + color: white; +} + +.roomAvatar { + position: relative; + width: 32px; + height: 32px; + border-radius: 32px; +} + +.roomAvatar > * { + position: absolute; + left: 0; + color: #fff; + text-align: center; + pointer-events: none; + font-weight: 400; +} + +.roomAvatar span { + font-size: 20.8px; + width: 32px; + line-height: 32px; +} + +.roomName { + margin-left: 8px; + font-size: 14px; + line-height: 18px; +} + +.center { + flex: 1; + display: flex; + justify-content: center; + align-items: center; +} + +.createRoomContainer { + color: #232f32; + border-radius: 8px; + padding: 25px 60px; + width: 400px; + background-color: white; +} + +.createRoomContainer h2 { + margin: 0 0 20px 0; +} + +.userName { + font-weight: 600; + margin-right: 8px; +} + +.signOutButton { + background: transparent; + border: none; + color: rgb(255, 75, 85); + cursor: pointer; + font-weight: 600; +} diff --git a/src/Input.jsx b/src/Input.jsx new file mode 100644 index 0000000..1360492 --- /dev/null +++ b/src/Input.jsx @@ -0,0 +1,44 @@ +import React, { forwardRef } from "react"; +import classNames from "classnames"; +import styles from "./Input.module.css"; + +export function FieldRow({ children, rightAlign, className, ...rest }) { + return ( +
+ {children} +
+ ); +} + +export function Field({ children, className, ...rest }) { + return
{children}
; +} + +export const InputField = forwardRef( + ({ id, label, className, ...rest }, ref) => { + return ( + + + + + ); + } +); + +export const Button = forwardRef(({ className, children, ...rest }, ref) => { + return ( + + ); +}); diff --git a/src/Input.module.css b/src/Input.module.css new file mode 100644 index 0000000..c71c04e --- /dev/null +++ b/src/Input.module.css @@ -0,0 +1,106 @@ +.fieldRow { + display: flex; + margin-bottom: 10px; +} + +.field { + display: flex; + flex: 1; + min-width: 0; + position: relative; + margin: 1em 0; + border-radius: 4px; + transition: border-color .25s; + border: 1px solid #e7e7e7; +} + +.fieldRow.rightAlign { + justify-content: flex-end; +} + +.fieldRow > .field { + margin: 0 5px; +} + +.fieldRow > .field:first-child { + margin-left: 0; +} + +.fieldRow > .field:last-child { + margin-right: 0; +} + +.field input { + font-weight: 400; + font-size: 14px; + border: none; + border-radius: 4px; + padding: 8px 9px; + color: #2e2f32; + background-color: #fff; + flex: 1; + min-width: 0; +} + +.field input::placeholder { + transition: color 0.25s ease-in 0s; + color: transparent; +} + +.field input:placeholder-shown:focus::placeholder { + transition: color .25s ease-in .1s; + color: #888; +} + +.field label { + transition: font-size .25s ease-out .1s,color .25s ease-out .1s,top .25s ease-out .1s,background-color .25s ease-out .1s; + color: #2e2f32; + background-color: transparent; + font-size: 14px; + position: absolute; + left: 0; + top: 0; + margin: 7px 8px; + padding: 2px; + pointer-events: none; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + max-width: calc(100% - 20px); +} + +.field input:focus + label { + background-color: #fff; + color: #238cf5; + transition: font-size .25s ease-out 0s,color .25s ease-out 0s,top .25s ease-out 0s,background-color .25s ease-out 0s; + font-size: 10px; + top: -13px; + padding: 0 2px; + background-color: #fff; + pointer-events: auto; +} + +.button { + vertical-align: middle; + border: 0; + border-radius: 8px; + font-size: 14px; + color: #fff; + background-color: #0dbd8b; + width: auto; + padding: 7px 15px; + cursor: pointer; + display: inline-block; + outline: none; + -webkit-box-sizing: border-box; + box-sizing: border-box; + text-align: center; +} + +.button:hover { + +} + +.button:active { + +} \ No newline at end of file diff --git a/src/JoinOrCreateRoom.jsx b/src/JoinOrCreateRoom.jsx deleted file mode 100644 index 4b2888d..0000000 --- a/src/JoinOrCreateRoom.jsx +++ /dev/null @@ -1,116 +0,0 @@ -/* -Copyright 2021 New Vector Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -import React, { useCallback, useRef, useState } from "react"; -import { useHistory, Link } from "react-router-dom"; -import { useRooms } from "./ConferenceCallManagerHooks"; - -export function JoinOrCreateRoom({ manager }) { - const history = useHistory(); - const roomNameRef = useRef(); - const roomIdRef = useRef(); - const [createRoomError, setCreateRoomError] = useState(); - const [joinRoomError, setJoinRoomError] = useState(); - const rooms = useRooms(manager); - - const onCreateRoom = useCallback( - (e) => { - e.preventDefault(); - setCreateRoomError(undefined); - - manager.client - .createRoom({ - visibility: "private", - preset: "public_chat", - name: roomNameRef.current.value, - }) - .then(({ room_id }) => { - history.push(`/room/${room_id}`); - }) - .catch(setCreateRoomError); - }, - [manager] - ); - - const onJoinRoom = useCallback( - (e) => { - e.preventDefault(); - setJoinRoomError(undefined); - - manager.client - .joinRoom(roomIdRef.current.value) - .then(({ roomId }) => { - history.push(`/room/${roomId}`); - }) - .catch(setJoinRoomError); - }, - [manager] - ); - - const onLogout = useCallback( - (e) => { - e.preventDefault(); - manager.logout(); - location.reload(); - }, - [manager] - ); - - return ( -
-

Matrix Video Chat

-
-

Create New Room

- - {createRoomError &&

{createRoomError.message}

} - -
-
-

Join Existing Room

- - {joinRoomError &&

{joinRoomError.message}

} - -
-

Rooms:

- - -
- ); -} diff --git a/src/Room.jsx b/src/Room.jsx index c66d8aa..8024e7e 100644 --- a/src/Room.jsx +++ b/src/Room.jsx @@ -26,7 +26,7 @@ import { MicButton, VideoButton, } from "./RoomButton"; -import { ReactComponent as Logo } from "./Logo.svg"; +import { Header, LeftNav, RightNav } from "./Header"; function useQuery() { const location = useLocation(); @@ -69,21 +69,19 @@ export function Room({ manager }) { return (
{!loading && room && ( -
-
- - - -
-

{room.name}

-
+
+ + +

{room.name}

+
+ setDebug((debug) => !debug)} /> -
-
+ + )} {loading && (
diff --git a/src/Room.module.css b/src/Room.module.css index 24661e8..2f10ec5 100644 --- a/src/Room.module.css +++ b/src/Room.module.css @@ -23,37 +23,6 @@ limitations under the License. overflow: hidden; } -.header { - position: relative; - display: flex; - justify-content: center; - align-items: center; - height: 98px; - user-select: none; -} - -.header h5 { - text-overflow: ellipsis; - overflow: hidden; -} - -.backNav { - position: absolute; - left: 20px; -} - -.logo { - display: flex; - align-items: center; - text-decoration: none; -} - -.userNav { - position: absolute; - right: 20px; - max-width: 30%; -} - .joinRoom { display: flex; flex-direction: column; diff --git a/src/index.css b/src/index.css index 8a404d6..3d0f102 100644 --- a/src/index.css +++ b/src/index.css @@ -105,7 +105,7 @@ limitations under the License. } body { - background-color: #21262C; + background-color: rgb(21, 25, 30); color: #fff; margin: 0; font-family: "Inter", -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', @@ -115,19 +115,13 @@ body { -moz-osx-font-smoothing: grayscale; } -button { - border: none; - background-color: #ccc; - color: black; - font-size: 16px; - font-weight: bold; - padding: 8px 16px; - border-radius: 4px; - cursor: pointer; +html, body, #root { + height: 100%; } -button:hover, button:active { - background-color: #888; +#root { + display: flex; + flex-direction: column; } a { @@ -138,23 +132,3 @@ a { a:hover, a:active { color: rgb(76, 134, 173); } - -.page { - margin: 0 auto; - max-width: 960px; - display: flex; - flex-direction: column; - padding: 0 20px; -} - -.page input { - padding: 8px 4px; - font-size: 16px; - border-radius: 4px; - border: 1px solid #888; -} - -.page input, .page button { - display: block; - margin-top: 16px; -}