mirror of
https://github.com/urbit/shrub.git
synced 2024-11-28 22:33:06 +03:00
profile: add identity form
This commit is contained in:
parent
e9c6322ff4
commit
6085752f21
@ -1,5 +1,7 @@
|
||||
import _ from 'lodash';
|
||||
|
||||
export const MOBILE_BROWSER_REGEX = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i;
|
||||
|
||||
export function resourceAsPath(resource) {
|
||||
const { name, ship } = resource;
|
||||
return `/ship/~${ship}/${name}`;
|
||||
@ -75,6 +77,14 @@ export function uxToHex(ux) {
|
||||
return value;
|
||||
}
|
||||
|
||||
export function hexToUx(hex) {
|
||||
const ux = _.chain(hex.split(""))
|
||||
.chunk(4)
|
||||
.map((x) => _.dropWhile(x, (y) => y === 0).join(""))
|
||||
.join(".");
|
||||
return `0x${ux}`;
|
||||
}
|
||||
|
||||
function hexToDec(hex) {
|
||||
const alphabet = '0123456789ABCDEF'.split('');
|
||||
return hex.reverse().reduce((acc, digit, idx) => {
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React, { Component } from 'react';
|
||||
import { UnControlled as CodeEditor } from 'react-codemirror2';
|
||||
import { MOBILE_BROWSER_REGEX } from "~/logic/lib/util";
|
||||
import CodeMirror from 'codemirror';
|
||||
|
||||
import 'codemirror/mode/markdown/markdown';
|
||||
@ -132,7 +133,7 @@ export default class ChatEditor extends Component {
|
||||
onChange={(e, d, v) => this.messageChange(e, d, v)}
|
||||
editorDidMount={(editor) => {
|
||||
this.editor = editor;
|
||||
if (!BROWSER_REGEX.test(navigator.userAgent)) {
|
||||
if (!MOBILE_BROWSER_REGEX.test(navigator.userAgent)) {
|
||||
editor.focus();
|
||||
}
|
||||
}}
|
||||
|
@ -333,33 +333,6 @@ export default class GroupsApp extends Component<GroupsAppProps, {}> {
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Route exact path="/~groups/me"
|
||||
render={(props) => {
|
||||
const me = defaultContacts[window.ship] || {};
|
||||
|
||||
return (
|
||||
<Skeleton
|
||||
history={props.history}
|
||||
api={api}
|
||||
contacts={contacts}
|
||||
groups={groups}
|
||||
invites={invites}
|
||||
activeDrawer="rightPanel"
|
||||
selected="me"
|
||||
associations={associations}
|
||||
>
|
||||
<ContactCard
|
||||
api={api}
|
||||
history={props.history}
|
||||
path="/~/default"
|
||||
contact={me}
|
||||
s3={s3}
|
||||
ship={window.ship}
|
||||
/>
|
||||
</Skeleton>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Switch>
|
||||
</>
|
||||
);
|
||||
|
@ -0,0 +1,124 @@
|
||||
import React, { Component } from "react";
|
||||
import { Sigil } from "~/logic/lib/sigil";
|
||||
import * as Yup from "yup";
|
||||
|
||||
import { Link } from "react-router-dom";
|
||||
import { EditElement } from "./edit-element";
|
||||
import { Spinner } from "~/views/components/Spinner";
|
||||
import { uxToHex } from "~/logic/lib/util";
|
||||
import { Col, Input, Box, Text, Row } from "@tlon/indigo-react";
|
||||
import { Formik, Form, FormikHelpers } from "formik";
|
||||
import { Contact } from "~/types/contact-update";
|
||||
import { AsyncButton } from "~/views/components/AsyncButton";
|
||||
import { ColorInput } from "~/views/components/ColorInput";
|
||||
import GlobalApi from "~/logic/api/global";
|
||||
import { ImageInput } from "~/views/components/ImageInput";
|
||||
import { S3State } from "~/types";
|
||||
|
||||
interface ContactCardProps {
|
||||
contact: Contact;
|
||||
path: string;
|
||||
api: GlobalApi;
|
||||
s3: S3State;
|
||||
}
|
||||
|
||||
const formSchema = Yup.object({
|
||||
color: Yup.string(),
|
||||
nickname: Yup.string(),
|
||||
email: Yup.string().matches(
|
||||
new RegExp(
|
||||
String(
|
||||
/[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*/.source
|
||||
) +
|
||||
/@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/
|
||||
.source
|
||||
),
|
||||
"Not a valid email"
|
||||
),
|
||||
phone: Yup.string().matches(
|
||||
new RegExp(
|
||||
String(/^\s*(?:\+?(\d{1,3}))?/.source) +
|
||||
/([-. (]*(\d{3})[-. )]*)?((\d{3})[-. ]*(\d{2,4})(?:[-.x ]*(\d+))?)\s*$/
|
||||
.source
|
||||
),
|
||||
"Not a valid phone"
|
||||
),
|
||||
|
||||
website: Yup.string().matches(
|
||||
new RegExp(
|
||||
String(/[(http(s)?):\/\/(www\.)?a-zA-Z0-9@:%._\+~#=]{2,256}/.source) +
|
||||
/\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/.source
|
||||
),
|
||||
"Not a valid website"
|
||||
),
|
||||
});
|
||||
|
||||
export function ContactCard(props: ContactCardProps) {
|
||||
const us = `~${window.ship}`;
|
||||
const { contact } = props;
|
||||
const onSubmit = async (values: Contact, actions: FormikHelpers<Contact>) => {
|
||||
try {
|
||||
await Object.keys(values).reduce((acc, key) => {
|
||||
const newValue = key !== "color" ? values[key] : uxToHex(values[key]);
|
||||
if (newValue !== contact[key]) {
|
||||
if (key === "avatar") {
|
||||
return acc.then(() =>
|
||||
props.api.contacts.edit(props.path, us, {
|
||||
avatar: { url: newValue },
|
||||
} as any)
|
||||
);
|
||||
}
|
||||
|
||||
return acc.then(() =>
|
||||
props.api.contacts.edit(props.path, us, {
|
||||
[key]: newValue,
|
||||
} as any)
|
||||
);
|
||||
}
|
||||
return acc;
|
||||
}, Promise.resolve());
|
||||
actions.setStatus({ success: null });
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
actions.setStatus({ error: e.message });
|
||||
}
|
||||
};
|
||||
|
||||
const hexColor = contact.color ? `#${uxToHex(contact.color)}` : "#000000";
|
||||
|
||||
return (
|
||||
<Box p={4} height="100%" overflowY="auto">
|
||||
<Formik
|
||||
validationSchema={formSchema}
|
||||
initialValues={contact}
|
||||
onSubmit={onSubmit}
|
||||
>
|
||||
<Form>
|
||||
<Col>
|
||||
<Row
|
||||
borderBottom={1}
|
||||
borderBottomColor="washedGray"
|
||||
pb={3}
|
||||
alignItems="center"
|
||||
>
|
||||
<Sigil size={32} classes="" color={hexColor} ship={us} />
|
||||
<Box ml={2}>
|
||||
<Text fontFamily="mono">{us}</Text>
|
||||
</Box>
|
||||
</Row>
|
||||
<ImageInput mt={3} id="avatar" label="Avatar" s3={props.s3} />
|
||||
<ColorInput id="color" label="Sigil Color" />
|
||||
<Input id="nickname" label="Nickname" />
|
||||
<Input id="email" label="Email" />
|
||||
<Input id="phone" label="Phone" />
|
||||
<Input id="website" label="Website" />
|
||||
<Input id="notes" label="Notes" />
|
||||
<AsyncButton primary loadingText="Updating..." border>
|
||||
Save
|
||||
</AsyncButton>
|
||||
</Col>
|
||||
</Form>
|
||||
</Formik>
|
||||
</Box>
|
||||
);
|
||||
}
|
@ -18,30 +18,6 @@ export class GroupSidebar extends Component {
|
||||
|
||||
const selectedClass = (props.selected === 'me') ? 'bg-gray4 bg-gray1-d' : 'bg-white bg-gray0-d';
|
||||
|
||||
const rootIdentity = <Link
|
||||
key={1}
|
||||
to={'/~groups/me'}
|
||||
>
|
||||
<div
|
||||
className={
|
||||
'w-100 pl4 pt1 pb1 f9 flex justify-start content-center ' +
|
||||
selectedClass}
|
||||
>
|
||||
<Sigil
|
||||
ship={window.ship}
|
||||
color="#000000"
|
||||
classes="mix-blend-diff"
|
||||
size={32}
|
||||
/>
|
||||
<p
|
||||
className="f9 w-70 dib v-mid ml2 nowrap mono"
|
||||
style={{ paddingTop: 6 }}
|
||||
>
|
||||
{cite(window.ship)}
|
||||
</p>
|
||||
</div>
|
||||
</Link>;
|
||||
|
||||
const inviteItems =
|
||||
Object.keys(props.invites)
|
||||
.map((uid) => {
|
||||
@ -127,8 +103,6 @@ export class GroupSidebar extends Component {
|
||||
<p className="f9 pt4 pl4 green2 bn">Join Group</p>
|
||||
</Link>
|
||||
<Welcome contacts={props.contacts} />
|
||||
<h2 className="f9 pt4 pr4 pb2 pl4 gray2 c-default">Your Identity</h2>
|
||||
{rootIdentity}
|
||||
{inviteItems}
|
||||
<h2 className="f9 pt4 pr4 pb2 pl4 gray2 c-default">Groups</h2>
|
||||
{groupItems}
|
||||
|
@ -1,9 +1,9 @@
|
||||
import React from 'react';
|
||||
import { Box, InputLabel, Radio, Input } from '@tlon/indigo-react';
|
||||
|
||||
import GlobalApi from '../../../../api/global';
|
||||
import { S3State } from '../../../../types';
|
||||
import { ImageInput } from './ImageInput';
|
||||
import GlobalApi from '~/logic/api/global';
|
||||
import { S3State } from '~/types';
|
||||
import { ImageInput } from '~/views/components/ImageInput';
|
||||
|
||||
export type BgType = "none" | "url" | "color";
|
||||
|
||||
|
@ -1,10 +1,26 @@
|
||||
import React, { useMemo } from "react";
|
||||
import { useDrag } from "react-dnd";
|
||||
import { usePreview } from "react-dnd-multi-backend";
|
||||
import { capitalize } from 'lodash';
|
||||
import { capitalize } from "lodash";
|
||||
import { TileTypeBasic, Tile } from "../../../../types/launch-update";
|
||||
|
||||
import { Box, Img, Text } from "@tlon/indigo-react";
|
||||
import { Box, Img as _Img, Text } from "@tlon/indigo-react";
|
||||
import styled from "styled-components";
|
||||
|
||||
// Need to change dojo image
|
||||
const Img = styled(_Img)<{ invert?: boolean }>`
|
||||
${(p) =>
|
||||
p.theme.colors.white !== "rgba(255,255,255,1)" ? `filter: invert(1);` : ``}
|
||||
|
||||
${(p) =>
|
||||
!p.invert
|
||||
? ``
|
||||
: p.theme.colors.white !== "rgba(255,255,255,1)"
|
||||
? `
|
||||
filter: invert(0);
|
||||
`
|
||||
: `filter: invert(1);`}
|
||||
`;
|
||||
|
||||
interface DragTileProps {
|
||||
index: number;
|
||||
@ -27,6 +43,7 @@ function DragTileBox({ title, index, tile, ...props }: any) {
|
||||
justifyContent="space-around"
|
||||
flexDirection="column"
|
||||
border={1}
|
||||
borderColor="black"
|
||||
height="100%"
|
||||
width="100%"
|
||||
style={{ cursor: "move" }}
|
||||
@ -38,7 +55,13 @@ function DragTileBox({ title, index, tile, ...props }: any) {
|
||||
function DragTileCustom({ index, title, style }: any) {
|
||||
const tile = { type: { custom: null } };
|
||||
return (
|
||||
<DragTileBox bg="white" style={style} title={title} tile={tile} index={index}>
|
||||
<DragTileBox
|
||||
bg="white"
|
||||
style={style}
|
||||
title={title}
|
||||
tile={tile}
|
||||
index={index}
|
||||
>
|
||||
<Text fontSize={1}>{capitalize(title)}</Text>
|
||||
</DragTileBox>
|
||||
);
|
||||
@ -55,11 +78,19 @@ function DragTileBasic(props: {
|
||||
<DragTileBox
|
||||
tile={{ type: props.tile }}
|
||||
index={props.index}
|
||||
bg={isDojo ? "black" : "white"}
|
||||
bg={
|
||||
"white" // isDojo ? "black" : "white"
|
||||
}
|
||||
style={props.style}
|
||||
>
|
||||
<Img width="48px" height="48px" src={tile.iconUrl} />
|
||||
<Text color={isDojo ? "white" : "black"}>{tile.title}</Text>
|
||||
<Img width="48px" height="48px" src={tile.iconUrl} invert={isDojo} />
|
||||
<Text
|
||||
color={
|
||||
"black" // isDojo ? "white" : "black"
|
||||
}
|
||||
>
|
||||
{tile.title}
|
||||
</Text>
|
||||
</DragTileBox>
|
||||
);
|
||||
}
|
||||
|
@ -1,68 +1,124 @@
|
||||
import React from "react";
|
||||
|
||||
import { Box, Col, Center, Icon } from "@tlon/indigo-react";
|
||||
import { Box, Text, Row, Col, Center, Icon } from "@tlon/indigo-react";
|
||||
|
||||
import { Sigil } from "~/logic/lib/sigil";
|
||||
import { uxToHex, MOBILE_BROWSER_REGEX } from "~/logic/lib/util";
|
||||
|
||||
import Settings from "./components/settings";
|
||||
import { Route, Link } from "react-router-dom";
|
||||
import { ContactCard } from "../groups/components/lib/ContactCard";
|
||||
|
||||
const SidebarItem = ({ children, view, current }) => {
|
||||
const selected = current === view;
|
||||
const color = selected ? "blue" : "black";
|
||||
return (
|
||||
<Link to={`/~profile/${view}`}>
|
||||
<Row
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
verticalAlign="middle"
|
||||
py={1}
|
||||
px={3}
|
||||
backgroundColor={selected ? "washedBlue" : "white"}
|
||||
>
|
||||
<Icon mr={2} display="inline-block" icon="Circle" fill={color} />
|
||||
<Text color={color} fontSize={0}>
|
||||
{children}
|
||||
</Text>
|
||||
</Row>
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
export default function ProfileScreen(props: any) {
|
||||
const { ship, dark } = props;
|
||||
return (
|
||||
<Box height="100%" px={[0,3]} pb={[0,3]} borderRadius={1}>
|
||||
<Box
|
||||
height="100%"
|
||||
width="100%"
|
||||
display="flex"
|
||||
borderRadius={1}
|
||||
bg="white"
|
||||
border={1}
|
||||
borderColor="washedGray"
|
||||
>
|
||||
<Col
|
||||
display={["none", "block"]}
|
||||
collapse
|
||||
borderRight={1}
|
||||
borderColor="washedGray"
|
||||
>
|
||||
<Box borderBottom={1} borderBottomColor="washedGray">
|
||||
<Route
|
||||
path={["/~profile/:view", "/~profile"]}
|
||||
render={({ match, history }) => {
|
||||
const { view } = match.params;
|
||||
const contact = props.contacts?.["/~/default"]?.[window.ship];
|
||||
const sigilColor = contact?.color
|
||||
? `#${uxToHex(contact.color)}`
|
||||
: dark
|
||||
? "#FFFFFF"
|
||||
: "#000000";
|
||||
if(!contact) {
|
||||
return null;
|
||||
}
|
||||
if (!view && !MOBILE_BROWSER_REGEX.test(window.navigator.userAgent)) {
|
||||
history.replace("/~profile/settings");
|
||||
}
|
||||
|
||||
return (
|
||||
<Box height="100%" px={[0, 3]} pb={[0, 3]} borderRadius={1}>
|
||||
<Box
|
||||
bg="black"
|
||||
borderRadius={8}
|
||||
margin={4}
|
||||
height={128}
|
||||
width={128}
|
||||
display="flex"
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
height="100%"
|
||||
width="100%"
|
||||
display="grid"
|
||||
gridTemplateColumns={["100%", "200px 1fr"]}
|
||||
gridTemplateRows={["48px 1fr", "1fr"]}
|
||||
borderRadius={1}
|
||||
bg="white"
|
||||
border={1}
|
||||
borderColor="washedGray"
|
||||
>
|
||||
<Sigil
|
||||
ship={`~${ship}`}
|
||||
size={80}
|
||||
color={dark ? "#FFFFFF" : "#000000"}
|
||||
/>
|
||||
<Col
|
||||
display={!view ? "flex" : ["none", "flex"]}
|
||||
alignItems="center"
|
||||
borderRight={1}
|
||||
borderColor="washedGray"
|
||||
>
|
||||
<Box width="100%" borderBottom={1} borderBottomColor="washedGray">
|
||||
<Box
|
||||
mx="auto"
|
||||
bg={sigilColor}
|
||||
borderRadius={8}
|
||||
my={4}
|
||||
height={128}
|
||||
width={128}
|
||||
display="flex"
|
||||
justifyContent="center"
|
||||
alignItems="center"
|
||||
>
|
||||
<Sigil ship={`~${ship}`} size={80} color={sigilColor} />
|
||||
</Box>
|
||||
</Box>
|
||||
<Box width="100%" py={3}>
|
||||
<SidebarItem current={view} view="settings">
|
||||
Ship Settings
|
||||
</SidebarItem>
|
||||
<SidebarItem current={view} view="identity">
|
||||
Your Identity
|
||||
</SidebarItem>
|
||||
</Box>
|
||||
</Col>
|
||||
<Box
|
||||
display={!view ? "none" : ["flex", "none"]}
|
||||
alignItems="center"
|
||||
px={3}
|
||||
borderBottom={1}
|
||||
borderBottomColor="washedGray"
|
||||
>
|
||||
<Link to="/~profile">{"<- Back"}</Link>
|
||||
</Box>
|
||||
<Box overflowY="auto" flexGrow={1}>
|
||||
{view === "settings" && <Settings {...props} />}
|
||||
|
||||
{view === "identity" && (
|
||||
<ContactCard
|
||||
contact={contact}
|
||||
path="/~/default"
|
||||
api={props.api}
|
||||
s3={props.s3}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box py={4}>
|
||||
<Box
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
verticalAlign="middle"
|
||||
fontSize={0}
|
||||
py={1}
|
||||
px={3}
|
||||
color="blue"
|
||||
backgroundColor="washedBlue"
|
||||
>
|
||||
<Icon mr={2} display="inline-block" icon="Circle" fill="blue" />
|
||||
Ship Settings
|
||||
</Box>
|
||||
</Box>
|
||||
</Col>
|
||||
<Box overflowY="auto" flexGrow={1}>
|
||||
<Settings {...props} />
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}}
|
||||
></Route>
|
||||
);
|
||||
}
|
||||
|
64
pkg/interface/src/views/components/ColorInput.tsx
Normal file
64
pkg/interface/src/views/components/ColorInput.tsx
Normal file
@ -0,0 +1,64 @@
|
||||
import React from "react";
|
||||
import { useField } from "formik";
|
||||
import styled from "styled-components";
|
||||
import { Col, InputLabel, Row, Box, ErrorMessage } from "@tlon/indigo-react";
|
||||
|
||||
import { uxToHex, hexToUx } from "~/logic/lib/util";
|
||||
|
||||
const Input = styled.input`
|
||||
background-color: ${ p => p.theme.colors.white };
|
||||
color: ${ p => p.theme.colors.black };
|
||||
box-sizing: border-box;
|
||||
border: 1px solid;
|
||||
border-right: none;
|
||||
border-color: ${(p) => p.theme.colors.lightGray};
|
||||
border-top-left-radius: ${(p) => p.theme.radii[2]}px;
|
||||
border-bottom-left-radius: ${(p) => p.theme.radii[2]}px;
|
||||
padding: ${(p) => p.theme.space[2]}px;
|
||||
font-size: 12px;
|
||||
line-height: 1.2;
|
||||
`;
|
||||
|
||||
type ColorInputProps = Parameters<typeof Col>[0] & {
|
||||
id: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
export function ColorInput(props: ColorInputProps) {
|
||||
const { id, label, ...rest } = props;
|
||||
const [{ value }, { error }, { setValue }] = useField(id);
|
||||
|
||||
const hex = value.substr(2).replace('.', '');
|
||||
const padded = hex.padStart(6, '0');
|
||||
|
||||
const onChange = (e: any) => {
|
||||
const { value: newValue } = e.target as HTMLInputElement;
|
||||
const valid = newValue.match(/^(\d|[a-f]|[A-F]){0,6}$/);
|
||||
|
||||
if(!valid) {
|
||||
return;
|
||||
}
|
||||
const result = hexToUx(newValue);
|
||||
setValue(result);
|
||||
};
|
||||
|
||||
return (
|
||||
<Col {...rest}>
|
||||
<InputLabel htmlFor={id}>{label}</InputLabel>
|
||||
<Row mt={2}>
|
||||
<Input onChange={onChange} value={hex} />
|
||||
<Box
|
||||
borderBottomRightRadius={1}
|
||||
borderTopRightRadius={1}
|
||||
border={1}
|
||||
borderLeft={0}
|
||||
borderColor="lightGray"
|
||||
width="32px"
|
||||
alignSelf="stretch"
|
||||
bg={`#${padded}`}
|
||||
/>
|
||||
</Row>
|
||||
<ErrorMessage mt="2">{error}</ErrorMessage>
|
||||
</Col>
|
||||
);
|
||||
}
|
@ -6,19 +6,16 @@ import { useField } from "formik";
|
||||
import { S3State } from "~/types/s3-update";
|
||||
import { useS3 } from "~/logic/lib/useS3";
|
||||
|
||||
interface ImageInputProps {
|
||||
type ImageInputProps = Parameters<typeof Box>[0] & {
|
||||
id: string;
|
||||
name: string;
|
||||
label: string;
|
||||
url: string;
|
||||
api: GlobalApi;
|
||||
s3: S3State;
|
||||
}
|
||||
};
|
||||
|
||||
export function ImageInput(props: ImageInputProps) {
|
||||
const { name, id, label, url, api } = props;
|
||||
const { id, label, s3, ...rest } = props;
|
||||
|
||||
const { uploadDefault, canUpload } = useS3(props.s3);
|
||||
const { uploadDefault, canUpload } = useS3(s3);
|
||||
|
||||
const [uploading, setUploading] = useState(false);
|
||||
|
||||
@ -47,8 +44,8 @@ export function ImageInput(props: ImageInputProps) {
|
||||
}, [ref]);
|
||||
|
||||
return (
|
||||
<Box display="flex">
|
||||
<Input type="text" label={label} id={id} />
|
||||
<Box {...rest} display="flex">
|
||||
<Input disabled={uploading} type="text" label={label} id={id} />
|
||||
{canUpload && (
|
||||
<>
|
||||
<Button
|
@ -1,50 +1,40 @@
|
||||
import React from 'react';
|
||||
import { Box, Text } from '@tlon/indigo-react';
|
||||
import React from "react";
|
||||
import { Box, Text } from "@tlon/indigo-react";
|
||||
|
||||
const ReconnectBox = ({ color, children, onClick }) => (
|
||||
<Box
|
||||
ml={2}
|
||||
px={2}
|
||||
py={1}
|
||||
display="flex"
|
||||
color={color}
|
||||
bg="white"
|
||||
alignItems="center"
|
||||
border={1}
|
||||
verticalAlign="middle"
|
||||
lineHeight="0"
|
||||
borderRadius={2}
|
||||
style={{ cursor: "pointer" }}
|
||||
onClick={onClick}
|
||||
>
|
||||
<Text color={color}>{children}</Text>
|
||||
</Box>
|
||||
);
|
||||
|
||||
const ReconnectButton = ({ connection, subscription }) => {
|
||||
const connectedStatus = connection || 'connected';
|
||||
const connectedStatus = connection || "connected";
|
||||
const reconnect = subscription.restart.bind(subscription);
|
||||
if (connectedStatus === 'disconnected') {
|
||||
if (connectedStatus === "disconnected") {
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
ml={2}
|
||||
px={2}
|
||||
py={1}
|
||||
display='inline-block'
|
||||
color='red'
|
||||
bg="white"
|
||||
border={1}
|
||||
verticalAlign="middle"
|
||||
lineHeight='0'
|
||||
borderRadius={2}
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={reconnect}>
|
||||
<Text color='red'>Reconnect ↻</Text>
|
||||
</Box>
|
||||
</>
|
||||
<ReconnectBox onClick={reconnect} color="red">
|
||||
Reconnect ↻
|
||||
</ReconnectBox>
|
||||
);
|
||||
} else if (connectedStatus === 'reconnecting') {
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
ml={2}
|
||||
px={2}
|
||||
py={1}
|
||||
bg='white'
|
||||
lineHeight="0"
|
||||
verticalAlign="middle"
|
||||
display='inline-block'
|
||||
color='yellow'
|
||||
border={1}
|
||||
borderRadius={2}>
|
||||
<Text color='yellow'>Reconnecting</Text>
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
} else if (connectedStatus === "reconnecting") {
|
||||
return <ReconnectBox color="yellow">Reconnecting</ReconnectBox>;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
export default ReconnectButton;
|
||||
|
Loading…
Reference in New Issue
Block a user