Refactored buttons and modals to be separate

This commit is contained in:
Mitchell McCaffrey 2020-04-13 18:15:00 +10:00
parent a1c0ce8b9d
commit bcf9f94c24
8 changed files with 248 additions and 155 deletions

View File

@ -1,27 +1,11 @@
import React, { useRef, useState, useEffect } from "react"; import React, { useRef, useState, useEffect } from "react";
import { import { IconButton } from "theme-ui";
IconButton,
Box,
Button,
Image as UIImage,
Flex,
Label,
Input,
} from "theme-ui";
import Modal from "./Modal"; import AddMapModal from "../modals/AddMapModal";
const defaultMapSize = 22; const defaultMapSize = 22;
function AddMapButton({ onMapChanged }) { function AddMapButton({ onMapChanged }) {
const fileInputRef = useRef();
function openImageDialog() {
if (fileInputRef.current) {
fileInputRef.current.click();
}
}
const [isAddModalOpen, setIsAddModalOpen] = useState(false); const [isAddModalOpen, setIsAddModalOpen] = useState(false);
function openModal() { function openModal() {
setIsAddModalOpen(true); setIsAddModalOpen(true);
@ -82,77 +66,18 @@ function AddMapButton({ onMapChanged }) {
<path d="M21.02 5H19V2.98c0-.54-.44-.98-.98-.98h-.03c-.55 0-.99.44-.99.98V5h-2.01c-.54 0-.98.44-.99.98v.03c0 .55.44.99.99.99H17v2.01c0 .54.44.99.99.98h.03c.54 0 .98-.44.98-.98V7h2.02c.54 0 .98-.44.98-.98v-.04c0-.54-.44-.98-.98-.98zM16 9.01V8h-1.01c-.53 0-1.03-.21-1.41-.58-.37-.38-.58-.88-.58-1.44 0-.36.1-.69.27-.98H5c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2v-8.28c-.3.17-.64.28-1.02.28-1.09-.01-1.98-.9-1.98-1.99zM15.96 19H6c-.41 0-.65-.47-.4-.8l1.98-2.63c.21-.28.62-.26.82.02L10 18l2.61-3.48c.2-.26.59-.27.79-.01l2.95 3.68c.26.33.03.81-.39.81z" /> <path d="M21.02 5H19V2.98c0-.54-.44-.98-.98-.98h-.03c-.55 0-.99.44-.99.98V5h-2.01c-.54 0-.98.44-.99.98v.03c0 .55.44.99.99.99H17v2.01c0 .54.44.99.99.98h.03c.54 0 .98-.44.98-.98V7h2.02c.54 0 .98-.44.98-.98v-.04c0-.54-.44-.98-.98-.98zM16 9.01V8h-1.01c-.53 0-1.03-.21-1.41-.58-.37-.38-.58-.88-.58-1.44 0-.36.1-.69.27-.98H5c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2v-8.28c-.3.17-.64.28-1.02.28-1.09-.01-1.98-.9-1.98-1.99zM15.96 19H6c-.41 0-.65-.47-.4-.8l1.98-2.63c.21-.28.62-.26.82.02L10 18l2.61-3.48c.2-.26.59-.27.79-.01l2.95 3.68c.26.33.03.81-.39.81z" />
</svg> </svg>
</IconButton> </IconButton>
<Modal isOpen={isAddModalOpen} onRequestClose={closeModal}> <AddMapModal
<Box isOpen={isAddModalOpen}
as="form" onRequestClose={closeModal}
onSubmit={(e) => { onDone={handleDone}
e.preventDefault(); onImageUpload={handleImageUpload}
handleDone(); rows={rows}
}} onRowsChange={setRows}
> columns={columns}
<Label pt={2} pb={1}> onColumnsChange={setColumns}
Add map imageLoaded={imageLoaded}
</Label> mapSource={mapSource}
<input />
onChange={handleImageUpload}
type="file"
accept="image/*"
style={{ display: "none" }}
ref={fileInputRef}
/>
<Flex sx={{ flexDirection: "column" }}>
<UIImage
my={2}
sx={{
width: "500px",
minHeight: "200px",
maxHeight: "300px",
objectFit: "contain",
borderRadius: "4px",
}}
src={mapSource}
onClick={openImageDialog}
bg="muted"
/>
<Flex>
<Box mb={2} mr={1} sx={{ flexGrow: 1 }}>
<Label htmlFor="rows">Rows</Label>
<Input
type="number"
name="rows"
value={rows}
onChange={(e) => setRows(e.target.value)}
/>
</Box>
<Box mb={2} ml={1} sx={{ flexGrow: 1 }}>
<Label htmlFor="columns">Columns</Label>
<Input
type="number"
name="columns"
value={columns}
onChange={(e) => setColumns(e.target.value)}
/>
</Box>
</Flex>
{mapSource ? (
<Button variant="primary" disabled={!imageLoaded}>
Done
</Button>
) : (
<Button
varient="primary"
onClick={(e) => {
e.preventDefault();
openImageDialog();
}}
>
Select Image
</Button>
)}
</Flex>
</Box>
</Modal>
</> </>
); );
} }

View File

@ -1,7 +1,7 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { IconButton, Box, Label, Text } from "theme-ui"; import { IconButton } from "theme-ui";
import Modal from "./Modal"; import AddPartyMemberModal from "../modals/AddPartyMemberModal";
function AddPartyMemberButton({ gameId }) { function AddPartyMemberButton({ gameId }) {
const [isAddModalOpen, setIsAddModalOpen] = useState(false); const [isAddModalOpen, setIsAddModalOpen] = useState(false);
@ -31,25 +31,11 @@ function AddPartyMemberButton({ gameId }) {
<path d="M15 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm-9-2V8c0-.55-.45-1-1-1s-1 .45-1 1v2H2c-.55 0-1 .45-1 1s.45 1 1 1h2v2c0 .55.45 1 1 1s1-.45 1-1v-2h2c.55 0 1-.45 1-1s-.45-1-1-1H6zm9 4c-2.67 0-8 1.34-8 4v1c0 .55.45 1 1 1h14c.55 0 1-.45 1-1v-1c0-2.66-5.33-4-8-4z" /> <path d="M15 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm-9-2V8c0-.55-.45-1-1-1s-1 .45-1 1v2H2c-.55 0-1 .45-1 1s.45 1 1 1h2v2c0 .55.45 1 1 1s1-.45 1-1v-2h2c.55 0 1-.45 1-1s-.45-1-1-1H6zm9 4c-2.67 0-8 1.34-8 4v1c0 .55.45 1 1 1h14c.55 0 1-.45 1-1v-1c0-2.66-5.33-4-8-4z" />
</svg> </svg>
</IconButton> </IconButton>
<Modal isOpen={isAddModalOpen} onRequestClose={closeModal}> <AddPartyMemberModal
<Box> isOpen={isAddModalOpen}
<Label pt={2} pb={1}> onRequestClose={closeModal}
Invite players gameId={gameId}
</Label> />
<Text as="p" mb={2} variant="caption">
Other people can join using the game ID
</Text>
<Box p={2} bg="hsla(230, 20%, 0%, 20%)">
<Text>{gameId}</Text>
</Box>
<Text as="p" my={2} variant="caption">
Or by using this link
</Text>
<Box p={2} bg="hsla(230, 20%, 0%, 20%)">
<Text>{window.location.href}</Text>
</Box>
</Box>
</Modal>
</> </>
); );
} }

View File

@ -1,7 +1,7 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { Box, Input, Button, Label, IconButton, Flex } from "theme-ui"; import { IconButton } from "theme-ui";
import Modal from "./Modal"; import ChangeNicknameModal from "../modals/ChangeNicknameModal";
function ChangeNicknameButton({ nickname, onChange }) { function ChangeNicknameButton({ nickname, onChange }) {
const [isChangeModalOpen, setIsChangeModalOpen] = useState(false); const [isChangeModalOpen, setIsChangeModalOpen] = useState(false);
@ -41,23 +41,13 @@ function ChangeNicknameButton({ nickname, onChange }) {
<path d="M3 17.46v3.04c0 .28.22.5.5.5h3.04c.13 0 .26-.05.35-.15L17.81 9.94l-3.75-3.75L3.15 17.1c-.1.1-.15.22-.15.36zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z" /> <path d="M3 17.46v3.04c0 .28.22.5.5.5h3.04c.13 0 .26-.05.35-.15L17.81 9.94l-3.75-3.75L3.15 17.1c-.1.1-.15.22-.15.36zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z" />
</svg> </svg>
</IconButton> </IconButton>
<Modal isOpen={isChangeModalOpen} onRequestClose={closeModal}> <ChangeNicknameModal
<Box as="form" onSubmit={handleChangeSubmit}> isOpen={isChangeModalOpen}
<Label py={2} htmlFor="nicknameChange"> onRequestClose={closeModal}
Change your nickname onChangeSubmit={handleChangeSubmit}
</Label> onChange={handleChange}
<Input nickname={changedNickname}
id="nicknameChange" />
value={changedNickname}
onChange={handleChange}
/>
<Flex py={2}>
<Button sx={{ flexGrow: 1 }} disabled={!changedNickname}>
Change
</Button>
</Flex>
</Box>
</Modal>
</> </>
); );
} }

View File

@ -1,8 +1,8 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { IconButton, Box, Text, Button, Label, Flex, Link } from "theme-ui"; import { IconButton, Box, Text, Link } from "theme-ui";
import adapter from "webrtc-adapter"; import adapter from "webrtc-adapter";
import Modal from "./Modal"; import StartStreamModal from "../modals/StartStreamModal";
function StartStreamButton({ onStreamStart, onStreamEnd, stream }) { function StartStreamButton({ onStreamStart, onStreamEnd, stream }) {
const [isStreamModalOpoen, setIsStreamModalOpen] = useState(false); const [isStreamModalOpoen, setIsStreamModalOpen] = useState(false);
@ -89,30 +89,17 @@ function StartStreamButton({ onStreamStart, onStreamEnd, stream }) {
<path d="M3.24 6.15C2.51 6.43 2 7.17 2 8v12c0 1.1.9 2 2 2h16c1.11 0 2-.9 2-2V8c0-1.1-.9-2-2-2H8.3l7.43-3c.46-.19.68-.71.49-1.17-.19-.46-.71-.68-1.17-.49L3.24 6.15zM7 20c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm13-8h-2v-1c0-.55-.45-1-1-1s-1 .45-1 1v1H4V9c0-.55.45-1 1-1h14c.55 0 1 .45 1 1v3z" /> <path d="M3.24 6.15C2.51 6.43 2 7.17 2 8v12c0 1.1.9 2 2 2h16c1.11 0 2-.9 2-2V8c0-1.1-.9-2-2-2H8.3l7.43-3c.46-.19.68-.71.49-1.17-.19-.46-.71-.68-1.17-.49L3.24 6.15zM7 20c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm13-8h-2v-1c0-.55-.45-1-1-1s-1 .45-1 1v1H4V9c0-.55.45-1 1-1h14c.55 0 1 .45 1 1v3z" />
</svg> </svg>
</IconButton> </IconButton>
<Modal isOpen={isStreamModalOpoen} onRequestClose={closeModal}> <StartStreamModal
<Box> isOpen={isStreamModalOpoen}
<Label pt={2} pb={1}> onRequestClose={closeModal}
Radio (experimental) isSupported={isSupported}
</Label> unavailableMessage={unavailableMessage}
<Text as="p" mb={2} variant="caption"> stream={stream}
Share your computers audio with the party noAudioTrack={noAudioTrack}
</Text> noAudioMessage={noAudioMessage}
{!isSupported && unavailableMessage} onStreamStart={handleStreamStart}
{isSupported && !stream && noAudioTrack && noAudioMessage} onStreamEnd={onStreamEnd}
<Flex py={2}> />
{isSupported && !stream && (
<Button sx={{ flexGrow: 1 }} onClick={handleStreamStart}>
Start Radio
</Button>
)}
{isSupported && stream && (
<Button sx={{ flexGrow: 1 }} onClick={() => onStreamEnd(stream)}>
Stop Radio
</Button>
)}
</Flex>
</Box>
</Modal>
</> </>
); );
} }

100
src/modals/AddMapModal.js Normal file
View File

@ -0,0 +1,100 @@
import React, { useRef } from "react";
import { Box, Button, Image as UIImage, Flex, Label, Input } from "theme-ui";
import Modal from "../components/Modal";
function AddMapModal({
isOpen,
onRequestClose,
onDone,
onImageUpload,
rows,
onRowsChange,
columns,
onColumnsChange,
imageLoaded,
mapSource,
}) {
const fileInputRef = useRef();
function openImageDialog() {
if (fileInputRef.current) {
fileInputRef.current.click();
}
}
return (
<Modal isOpen={isOpen} onRequestClose={onRequestClose}>
<Box
as="form"
onSubmit={(e) => {
e.preventDefault();
onDone();
}}
>
<Label pt={2} pb={1}>
Add map
</Label>
<input
onChange={onImageUpload}
type="file"
accept="image/*"
style={{ display: "none" }}
ref={fileInputRef}
/>
<Flex sx={{ flexDirection: "column" }}>
<UIImage
my={2}
sx={{
width: "500px",
minHeight: "200px",
maxHeight: "300px",
objectFit: "contain",
borderRadius: "4px",
}}
src={mapSource}
onClick={openImageDialog}
bg="muted"
/>
<Flex>
<Box mb={2} mr={1} sx={{ flexGrow: 1 }}>
<Label htmlFor="rows">Rows</Label>
<Input
type="number"
name="rows"
value={rows}
onChange={(e) => onRowsChange(e.target.value)}
/>
</Box>
<Box mb={2} ml={1} sx={{ flexGrow: 1 }}>
<Label htmlFor="columns">Columns</Label>
<Input
type="number"
name="columns"
value={columns}
onChange={(e) => onColumnsChange(e.target.value)}
/>
</Box>
</Flex>
{mapSource ? (
<Button variant="primary" disabled={!imageLoaded}>
Done
</Button>
) : (
<Button
varient="primary"
onClick={(e) => {
e.preventDefault();
openImageDialog();
}}
>
Select Image
</Button>
)}
</Flex>
</Box>
</Modal>
);
}
export default AddMapModal;

View File

@ -0,0 +1,30 @@
import React from "react";
import { Box, Label, Text } from "theme-ui";
import Modal from "../components/Modal";
function AddPartyMemberModal({ isOpen, onRequestClose, gameId }) {
return (
<Modal isOpen={isOpen} onRequestClose={onRequestClose}>
<Box>
<Label pt={2} pb={1}>
Invite players
</Label>
<Text as="p" mb={2} variant="caption">
Other people can join using the game ID
</Text>
<Box p={2} bg="hsla(230, 20%, 0%, 20%)">
<Text>{gameId}</Text>
</Box>
<Text as="p" my={2} variant="caption">
Or by using this link
</Text>
<Box p={2} bg="hsla(230, 20%, 0%, 20%)">
<Text>{window.location.href}</Text>
</Box>
</Box>
</Modal>
);
}
export default AddPartyMemberModal;

View File

@ -0,0 +1,30 @@
import React from "react";
import { Box, Input, Button, Label, Flex } from "theme-ui";
import Modal from "../components/Modal";
function ChangeNicknameModal({
isOpen,
onRequestClose,
onChangeSubmit,
nickname,
onChange,
}) {
return (
<Modal isOpen={isOpen} onRequestClose={onRequestClose}>
<Box as="form" onSubmit={onChangeSubmit}>
<Label py={2} htmlFor="nicknameChange">
Change your nickname
</Label>
<Input id="nicknameChange" value={nickname} onChange={onChange} />
<Flex py={2}>
<Button sx={{ flexGrow: 1 }} disabled={!nickname}>
Change
</Button>
</Flex>
</Box>
</Modal>
);
}
export default ChangeNicknameModal;

View File

@ -0,0 +1,45 @@
import React from "react";
import { Box, Text, Button, Label, Flex } from "theme-ui";
import Modal from "../components/Modal";
function StartStreamModal({
isOpen,
onRequestClose,
isSupported,
unavailableMessage,
stream,
noAudioTrack,
noAudioMessage,
onStreamStart,
onStreamEnd,
}) {
return (
<Modal isOpen={isOpen} onRequestClose={onRequestClose}>
<Box>
<Label pt={2} pb={1}>
Radio (experimental)
</Label>
<Text as="p" mb={2} variant="caption">
Share your computers audio with the party
</Text>
{!isSupported && unavailableMessage}
{isSupported && !stream && noAudioTrack && noAudioMessage}
<Flex py={2}>
{isSupported && !stream && (
<Button sx={{ flexGrow: 1 }} onClick={onStreamStart}>
Start Radio
</Button>
)}
{isSupported && stream && (
<Button sx={{ flexGrow: 1 }} onClick={() => onStreamEnd(stream)}>
Stop Radio
</Button>
)}
</Flex>
</Box>
</Modal>
);
}
export default StartStreamModal;