1
0
mirror of https://github.com/spacebarchat/client.git synced 2024-11-22 10:22:30 +01:00

Merge branch 'react' into feat/instancepicker

This commit is contained in:
Puyodead1 2023-08-08 21:25:51 -04:00
commit 8f7780992e
No known key found for this signature in database
GPG Key ID: A4FA4FEC0DD353FC
7 changed files with 389 additions and 481 deletions

View File

@ -0,0 +1,156 @@
import styled from "styled-components";
import Button from "./Button";
import Container from "./Container";
export const Wrapper = styled(Container)`
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: var(--background-tertiary);
`;
export const AuthContainer = styled(Container)`
background-color: var(--background-primary-alt);
padding: 32px;
font-size: 18px;
color: var(--text-muted);
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
@media (max-width: 480px) {
width: 100%;
height: 100%;
}
@media (min-width: 480px) {
width: 480px;
border-radius: 18px;
}
`;
export const HeaderContainer = styled.div`
width: 100%;
`;
export const Header = styled.h1`
margin-bottom: 3px;
color: var(--text);
font-weight: 600;
font-size: 24px;
`;
export const SubHeader = styled.h2<{ noBranding?: boolean }>`
margin-top: 3px;
color: var(--text-muted);
font-weight: 400;
font-size: ${(props) => (props.noBranding ? "20px" : "16px")};
`;
export const FormContainer = styled.form`
width: 100%;
`;
export const InputContainer = styled.h1<{ marginBottom: boolean }>`
margin-bottom: ${(props) => (props.marginBottom ? "20px" : "0")};
display: flex;
flex-direction: column;
align-items: flex-start;
`;
export const LabelWrapper = styled.div<{ error?: boolean }>`
display: flex;
flex-direction: row;
margin-bottom: 8px;
color: ${(props) => (props.error ? "var(--error)" : "var(--text)")};
`;
export const InputErrorText = styled.label`
font-size: 14px;
font-weight: 400;
font-style: italic;
`;
export const InputLabel = styled.label`
font-size: 14px;
font-weight: 700;
`;
export const InputWrapper = styled.div`
width: 100%;
display: flex;
`;
// TODO: Fix border hover causing small layout shift
export const Input = styled.input<{ error?: boolean }>`
outline: none;
background: var(--background-secondary);
padding: 10px;
font-size: 16px;
flex: 1;
border-radius: 12px;
color: var(--text);
margin: 0;
border: none;
aria-invalid: ${(props) => (props.error ? "true" : "false")};
border: ${(props) => (props.error ? "1px solid var(--error)" : "none")};
&:focus {
border: 1px solid var(--primary);
}
`;
export const Link = styled.button`
margin-bottom: 20px;
margin-top: 4px;
padding: 2px 0;
font-size: 14px;
display: flex;
color: var(--text-link);
background: none;
border: none;
&:hover {
text-decoration: underline;
cursor: pointer;
}
`;
export const SubmitButton = styled(Button)`
margin-bottom: 8px;
width: 100%;
min-width: 130px;
min-height: 44px;
font-size: 14px;
`;
export const AuthSwitchPageContainer = styled.div`
margin-top: 4px;
text-align: initial;
`;
export const AuthSwitchPageLabel = styled.label`
font-size: 14px;
`;
export const AuthSwitchPageLink = styled.button`
font-size: 14px;
background: none;
border: none;
color: var(--text-link);
@media (max-width: 480px) {
display: inline-block;
}
&:hover {
text-decoration: underline;
cursor: pointer;
}
`;
export const Divider = styled.span`
padding: 0 4px;
`;

View File

@ -13,7 +13,7 @@ import GuildSidebarListItem from "./GuildSidebarListItem";
import SidebarPill, { PillType } from "./SidebarPill";
import Tooltip from "./Tooltip";
const Wrapper = styled(Container)<{ active?: boolean }>`
const Wrapper = styled(Container)<{ active?: boolean; hasImage?: boolean }>`
display: flex;
align-items: center;
justify-content: center;
@ -21,13 +21,18 @@ const Wrapper = styled(Container)<{ active?: boolean }>`
height: 48px;
border-radius: ${(props) => (props.active ? "30%" : "50%")};
background-color: ${(props) =>
props.active ? "var(--primary)" : "var(--background-secondary)"};
props.hasImage
? "transparent"
: props.active
? "var(--primary)"
: "var(--background-secondary)"};
transition: border-radius 0.2s ease, background-color 0.2s ease;
cursor: pointer;
&:hover {
border-radius: 30%;
background-color: var(--primary);
background-color: ${(props) =>
props.hasImage ? "transparent" : "var(--primary)"};
}
`;
@ -71,6 +76,7 @@ function GuildItem(props: Props) {
<Wrapper
onClick={doNavigate}
active={props.active}
hasImage={!!guild?.icon}
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
>
@ -87,7 +93,13 @@ function GuildItem(props: Props) {
height={48}
/>
) : (
<span style={{ fontSize: "18px", fontWeight: "bold", cursor: "pointer" }}>
<span
style={{
fontSize: "18px",
fontWeight: "bold",
cursor: "pointer",
}}
>
{guild?.acronym}
</span>
)}

View File

@ -2,7 +2,7 @@ import { Routes } from "@spacebarchat/spacebar-api-types/v9";
import React from "react";
import { useForm } from "react-hook-form";
import { useNavigate } from "react-router-dom";
import styled from "styled-components";
import { ReactComponent as SpacebarLogoBlue } from "../assets/images/logo/Logo-Blue.svg";
import { useAppStore } from "../stores/AppStore";
import {
IAPIError,
@ -11,154 +11,23 @@ import {
IAPITOTPRequest,
} from "../utils/interfaces/api";
import { messageFromFieldError } from "../utils/messageFromFieldError";
import Button from "./Button";
import Container from "./Container";
export const Wrapper = styled(Container)`
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: var(--background-secondary);
`;
export const AuthBox = styled(Container)`
background-color: var(--background-primary-alt);
padding: 32px;
font-size: 18px;
color: var(--text-muted);
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
@media (max-width: 480px) {
width: 100%;
height: 100%;
}
@media (min-width: 480px) {
width: 480px;
border-radius: 18px;
}
`;
export const HeaderContainer = styled.div`
width: 100%;
`;
export const Header = styled.h1`
font-weight: 600;
margin-bottom: 8px;
font-size: 24px;
color: var(--text);
`;
export const SubHeader = styled.h2`
color: var(--text-muted);
font-weight: 400;
font-size: 16px;
margin-bottom: 40px;
`;
export const FormContainer = styled.form`
width: 100%;
`;
export const InputContainer = styled.h1<{ marginBottom: boolean }>`
margin-bottom: ${(props) => (props.marginBottom ? "20px" : "0")};
display: flex;
flex-direction: column;
align-items: flex-start;
`;
export const LabelWrapper = styled.div<{ error?: boolean }>`
display: flex;
flex-direction: row;
margin-bottom: 8px;
color: ${(props) => (props.error ? "var(--error)" : "#b1b5bc")};
`;
export const InputErrorText = styled.label`
font-size: 14px;
font-weight: 400;
font-style: italic;
`;
export const InputLabel = styled.label`
font-size: 14px;
font-weight: 700;
`;
export const InputWrapper = styled.div`
width: 100%;
display: flex;
`;
export const Input = styled.input<{ error?: boolean }>`
outline: none;
background: var(--background-secondary);
padding: 10px;
font-size: 16px;
flex: 1;
border-radius: 12px;
color: var(--text);
margin: 0;
border: none;
aria-invalid: ${(props) => (props.error ? "true" : "false")};
`;
export const Link = styled.button`
margin-bottom: 20px;
margin-top: 4px;
padding: 2px 0;
font-size: 14px;
display: flex;
color: var(--text-link);
background: none;
border: none;
&:hover {
text-decoration: underline;
cursor: pointer;
}
`;
export const LoginButton = styled(Button)`
margin-bottom: 8px;
width: 100%;
min-width: 130px;
min-height: 44px;
`;
export const RegisterContainer = styled.div`
margin-top: 4px;
text-align: initial;
`;
export const RegisterLabel = styled.label`
font-size: 14px;
`;
export const RegisterLink = styled.button`
font-size: 14px;
background: none;
border: none;
color: var(--text-link);
@media (max-width: 480px) {
display: inline-block;
}
&:hover {
text-decoration: underline;
cursor: pointer;
}
`;
export const Divider = styled.span`
padding: 0 4px;
`;
import {
AuthContainer,
Divider,
FormContainer,
Header,
HeaderContainer,
Input,
InputContainer,
InputErrorText,
InputLabel,
InputWrapper,
LabelWrapper,
Link,
SubHeader,
SubmitButton,
Wrapper,
} from "./AuthComponents";
type FormValues = {
code: string;
@ -224,8 +93,9 @@ function MFA(props: IAPILoginResponseMFARequired) {
return (
<Wrapper>
<AuthBox>
<AuthContainer>
<HeaderContainer>
<SpacebarLogoBlue height={48} width="auto" />
<Header>Two-factor authentication</Header>
<SubHeader>
You can use a backup code or your two-factor
@ -238,9 +108,7 @@ function MFA(props: IAPILoginResponseMFARequired) {
style={{ marginTop: 0 }}
>
<LabelWrapper error={!!errors.code}>
<InputLabel>
Enter Spacebar Auth/Backup Code
</InputLabel>
<InputLabel>Enter 2FA/Backup Code</InputLabel>
{errors.code && (
<InputErrorText>
<>
@ -262,13 +130,13 @@ function MFA(props: IAPILoginResponseMFARequired) {
</InputWrapper>
</InputContainer>
<LoginButton
<SubmitButton
variant="primary"
type="submit"
disabled={loading}
>
Log In
</LoginButton>
</SubmitButton>
{/* <Link
onClick={() => {
@ -295,7 +163,7 @@ function MFA(props: IAPILoginResponseMFARequired) {
</Link>
</FormContainer>
</HeaderContainer>
</AuthBox>
</AuthContainer>
</Wrapper>
);
}

View File

@ -0,0 +1,81 @@
import { useModals } from "@mattjennings/react-modal-stack";
import styled from "styled-components";
import Icon from "../Icon";
import {
ModalActionItem,
ModalCloseWrapper,
ModalContainer,
ModalFooter,
ModalHeaderText,
ModalWrapper,
ModelContentContainer,
} from "./ModalComponents";
export const ModalHeader = styled.div`
padding: 16px;
`;
const SubmitButton = styled(ModalActionItem)`
transition: background-color 0.2s ease-in-out;
font-size: 16px;
&:hover {
background-color: var(--background-secondary-highlight);
}
`;
function ForgotPasswordModal() {
const { openModal, closeModal } = useModals();
if (!open) {
return null;
}
return (
<ModalContainer>
<ModalWrapper>
<ModalCloseWrapper>
<button
onClick={closeModal}
style={{
background: "none",
border: "none",
outline: "none",
}}
>
<Icon
icon="mdiClose"
size={1}
style={{
cursor: "pointer",
color: "var(--text)",
}}
/>
</button>
</ModalCloseWrapper>
<ModalHeader>
<ModalHeaderText>Instructions Sent</ModalHeaderText>
</ModalHeader>
<ModelContentContainer>
We sent instructions to change your password to
user@example.com, please check both your inbox and spam
folder.
</ModelContentContainer>
<ModalFooter>
<SubmitButton
variant="filled"
size="med"
onClick={closeModal}
>
Okay
</SubmitButton>
</ModalFooter>
</ModalWrapper>
</ModalContainer>
);
}
export default ForgotPasswordModal;

View File

@ -1,14 +1,34 @@
import HCaptchaLib from "@hcaptcha/react-hcaptcha";
import { useModals } from "@mattjennings/react-modal-stack";
import { Routes } from "@spacebarchat/spacebar-api-types/v9";
import React from "react";
import { useForm } from "react-hook-form";
import { useNavigate } from "react-router-dom";
import styled from "styled-components";
import Button from "../components/Button";
import Container from "../components/Container";
import HCaptcha from "../components/HCaptcha";
import { ReactComponent as SpacebarLogoBlue } from "../assets/images/logo/Logo-Blue.svg";
import {
AuthContainer,
AuthSwitchPageContainer,
AuthSwitchPageLabel,
AuthSwitchPageLink,
Divider,
FormContainer,
Header,
Input,
InputContainer,
InputErrorText,
InputLabel,
InputWrapper,
LabelWrapper,
SubHeader,
SubmitButton,
Wrapper,
} from "../components/AuthComponents";
import HCaptcha, { HeaderContainer } from "../components/HCaptcha";
import MFA from "../components/MFA";
import { useAppStore } from "../stores/AppStore";
import ForgotPasswordModal from "../components/modals/ForgotPasswordModal";
import { AUTH_NO_BRANDING, useAppStore } from "../stores/AppStore";
import { Globals } from "../utils/Globals";
import REST from "../utils/REST";
import {
IAPILoginRequest,
IAPILoginResponse,
@ -16,153 +36,6 @@ import {
IAPILoginResponseMFARequired,
} from "../utils/interfaces/api";
import { messageFromFieldError } from "../utils/messageFromFieldError";
import REST from "../utils/REST";
import { Globals } from "../utils/Globals";
export const Wrapper = styled(Container)`
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: var(--background-tertiary);
`;
export const AuthBox = styled(Container)`
background-color: var(--background-primary-alt);
padding: 32px;
font-size: 18px;
color: var(--text-muted);
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
@media (max-width: 480px) {
width: 100%;
height: 100%;
}
@media (min-width: 480px) {
width: 480px;
border-radius: 18px;
}
`;
export const HeaderContainer = styled.div`
width: 100%;
`;
export const Header = styled.h1`
font-weight: 600;
margin-bottom: 8px;
font-size: 24px;
color: var(--text);
`;
export const SubHeader = styled.h2`
color: var(--text-muted);
font-weight: 400;
font-size: 16px;
`;
export const FormContainer = styled.form`
width: 100%;
`;
export const InputContainer = styled.h1<{ marginBottom: boolean }>`
margin-bottom: ${(props) => (props.marginBottom ? "20px" : "0")};
display: flex;
flex-direction: column;
align-items: flex-start;
`;
export const LabelWrapper = styled.div<{ error?: boolean }>`
display: flex;
flex-direction: row;
margin-bottom: 8px;
color: ${(props) => (props.error ? "var(--error)" : "#b1b5bc")};
`;
export const InputErrorText = styled.label`
font-size: 14px;
font-weight: 400;
font-style: italic;
`;
export const InputLabel = styled.label`
font-size: 14px;
font-weight: 700;
`;
export const InputWrapper = styled.div`
width: 100%;
display: flex;
`;
export const Input = styled.input<{ error?: boolean }>`
outline: none;
background: var(--background-secondary);
padding: 10px;
font-size: 16px;
flex: 1;
border-radius: 12px;
color: var(--text);
margin: 0;
border: none;
aria-invalid: ${(props) => (props.error ? "true" : "false")};
`;
export const PasswordResetLink = styled.button`
margin-bottom: 20px;
margin-top: 4px;
padding: 2px 0;
font-size: 14px;
display: flex;
color: var(--text-link);
background: none;
border: none;
&:hover {
text-decoration: underline;
cursor: pointer;
}
`;
export const LoginButton = styled(Button)`
margin-bottom: 8px;
width: 100%;
min-width: 130px;
min-height: 44px;
`;
export const RegisterContainer = styled.div`
margin-top: 4px;
text-align: initial;
`;
export const RegisterLabel = styled.label`
font-size: 14px;
`;
export const RegisterLink = styled.button`
font-size: 14px;
background: none;
border: none;
color: var(--text-link);
@media (max-width: 480px) {
display: inline-block;
}
&:hover {
text-decoration: underline;
cursor: pointer;
}
`;
export const Divider = styled.span`
padding: 0 4px;
`;
type FormValues = {
login: string;
@ -180,6 +53,7 @@ function LoginPage() {
React.useState<IAPILoginResponseMFARequired>();
const captchaRef = React.useRef<HCaptchaLib>(null);
const [debounce, setDebounce] = React.useState<NodeJS.Timeout | null>(null);
const { openModal } = useModals();
const {
register,
@ -297,6 +171,10 @@ function LoginPage() {
onSubmit();
};
const forgotPassword = () => {
openModal(ForgotPasswordModal);
};
if (captchaSiteKey) {
return (
<HCaptcha
@ -313,10 +191,18 @@ function LoginPage() {
return (
<Wrapper>
<AuthBox>
<AuthContainer>
<HeaderContainer>
<Header>Welcome Back!</Header>
<SubHeader>We're so excited to see you again!</SubHeader>
{AUTH_NO_BRANDING ? (
<>
<Header>Login to Spacebar</Header>
</>
) : (
<>
<SpacebarLogoBlue height={48} width="auto" />
<SubHeader noBranding>Log into Spacebar</SubHeader>
</>
)}
</HeaderContainer>
<FormContainer onSubmit={onSubmit}>
@ -394,6 +280,7 @@ function LoginPage() {
<InputWrapper>
<Input
type="email"
placeholder="Email"
autoFocus
{...register("login", { required: true })}
error={!!errors.login}
@ -402,7 +289,7 @@ function LoginPage() {
</InputWrapper>
</InputContainer>
<InputContainer marginBottom={false}>
<InputContainer marginBottom>
<LabelWrapper error={!!errors.password}>
<InputLabel>Password</InputLabel>
{errors.password && (
@ -417,6 +304,7 @@ function LoginPage() {
<InputWrapper>
<Input
type="password"
placeholder="Password"
{...register("password", { required: true })}
error={!!errors.password}
disabled={loading}
@ -424,41 +312,34 @@ function LoginPage() {
</InputWrapper>
</InputContainer>
<PasswordResetLink
onClick={() => {
window.open(
"https://youtu.be/dQw4w9WgXcQ",
"_blank",
);
}}
type="button"
>
{/* TODO: I need to figure this out, clicking this should submit the form or even a different function with only email being required */}
{/* <PasswordResetLink onClick={forgotPassword} type="button">
Forgot your password?
</PasswordResetLink>
</PasswordResetLink> */}
<LoginButton
<SubmitButton
variant="primary"
type="submit"
disabled={loading}
>
Log In
</LoginButton>
Login
</SubmitButton>
<RegisterContainer>
<RegisterLabel>
Don't have an account?&nbsp;
</RegisterLabel>
<RegisterLink
<AuthSwitchPageContainer>
<AuthSwitchPageLabel>
New to Spacebar?&nbsp;
</AuthSwitchPageLabel>
<AuthSwitchPageLink
onClick={() => {
navigate("/register");
}}
type="button"
>
Sign Up
</RegisterLink>
</RegisterContainer>
Register
</AuthSwitchPageLink>
</AuthSwitchPageContainer>
</FormContainer>
</AuthBox>
</AuthContainer>
</Wrapper>
);
}

View File

@ -3,12 +3,28 @@ import { Routes } from "@spacebarchat/spacebar-api-types/v9";
import React from "react";
import { useForm } from "react-hook-form";
import { useNavigate } from "react-router-dom";
import styled from "styled-components";
import Button from "../components/Button";
import Container from "../components/Container";
import { ReactComponent as SpacebarLogoBlue } from "../assets/images/logo/Logo-Blue.svg";
import {
AuthContainer,
AuthSwitchPageContainer,
AuthSwitchPageLabel,
AuthSwitchPageLink,
Divider,
FormContainer,
Header,
Input,
InputContainer,
InputErrorText,
InputLabel,
InputWrapper,
LabelWrapper,
SubHeader,
SubmitButton,
Wrapper,
} from "../components/AuthComponents";
import DOBInput from "../components/DOBInput";
import HCaptcha from "../components/HCaptcha";
import { useAppStore } from "../stores/AppStore";
import { AUTH_NO_BRANDING, useAppStore } from "../stores/AppStore";
import {
IAPILoginResponseSuccess,
IAPIRegisterRequest,
@ -16,129 +32,6 @@ import {
} from "../utils/interfaces/api";
import { messageFromFieldError } from "../utils/messageFromFieldError";
const Wrapper = styled(Container)`
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: var(--background-tertiary);
`;
const AuthBox = styled(Container)`
background-color: var(--background-primary-alt);
padding: 32px;
font-size: 18px;
color: var(--text-muted);
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
@media (max-width: 480px) {
width: 100%;
height: 100%;
}
@media (min-width: 480px) {
width: 480px;
border-radius: 18px;
}
`;
const HeaderContainer = styled.div`
width: 100%;
`;
const Header = styled.h1`
font-weight: 600;
margin-bottom: 8px;
font-size: 24px;
color: var(--text);
`;
// const SubHeader = styled.h2`
// color: var(--text-muted);
// font-weight: 400;
// font-size: 16px;
// `;
const FormContainer = styled.form`
width: 100%;
`;
const InputContainer = styled.h1<{ marginBottom: boolean }>`
margin-bottom: ${(props) => (props.marginBottom ? "20px" : "0")};
display: flex;
flex-direction: column;
align-items: flex-start;
`;
const LabelWrapper = styled.div<{ error?: boolean }>`
display: flex;
flex-direction: row;
margin-bottom: 8px;
color: ${(props) => (props.error ? "var(--error)" : "#b1b5bc")};
`;
const InputErrorText = styled.label`
font-size: 14px;
font-weight: 400;
font-style: italic;
`;
const InputLabel = styled.label`
font-size: 14px;
font-weight: 700;
`;
const InputWrapper = styled.div`
width: 100%;
display: flex;
`;
const Input = styled.input<{ error?: boolean }>`
outline: none;
background: var(--background-secondary);
padding: 10px;
font-size: 16px;
border-radius: 12px;
color: var(--text);
margin: 0;
border: none;
aria-invalid: ${(props) => (props.error ? "true" : "false")};
box-sizing: border-box;
width: 100%;
`;
const LoginButton = styled(Button)`
margin-bottom: 8px;
width: 100%;
min-width: 130px;
min-height: 44px;
`;
const LoginLink = styled.button`
margin-top: 4px;
float: left;
font-size: 14px;
background: none;
border: none;
color: var(--text-link);
@media (max-width: 480px) {
display: inline-block;
}
&:hover {
text-decoration: underline;
cursor: pointer;
}
`;
const Divider = styled.span`
padding: 0 4px;
`;
type FormValues = {
email: string;
username: string;
@ -279,11 +172,17 @@ function RegistrationPage() {
return (
<Wrapper>
<AuthBox>
<HeaderContainer>
<Header>Create an account</Header>
{/* <SubHeader>We're so excited to see you again!</SubHeader> */}
</HeaderContainer>
<AuthContainer>
{AUTH_NO_BRANDING ? (
<>
<Header>Create an account</Header>
</>
) : (
<>
<SpacebarLogoBlue height={48} width="auto" />
<SubHeader noBranding>Create an account</SubHeader>
</>
)}
<FormContainer onSubmit={onSubmit}>
<InputContainer
@ -304,6 +203,7 @@ function RegistrationPage() {
<InputWrapper>
<Input
type="email"
placeholder="Email"
autoFocus
{...register("email", { required: true })}
error={!!errors.email}
@ -330,6 +230,7 @@ function RegistrationPage() {
<InputWrapper>
<Input
{...register("username", { required: true })}
placeholder="Username"
error={!!errors.username}
disabled={loading}
/>
@ -351,6 +252,7 @@ function RegistrationPage() {
<InputWrapper>
<Input
type="password"
placeholder="Password"
{...register("password", { required: true })}
error={!!errors.password}
disabled={loading}
@ -396,24 +298,29 @@ function RegistrationPage() {
</InputWrapper>
</InputContainer>
<LoginButton
<SubmitButton
variant="primary"
type="submit"
disabled={loading}
>
Create Account
</LoginButton>
</SubmitButton>
<LoginLink
onClick={() => {
navigate("/login", { replace: true });
}}
type="button"
>
Already have an account?
</LoginLink>
<AuthSwitchPageContainer>
<AuthSwitchPageLabel>
Already have an account?&nbsp;
</AuthSwitchPageLabel>
<AuthSwitchPageLink
onClick={() => {
navigate("/login");
}}
type="button"
>
Login
</AuthSwitchPageLink>
</AuthSwitchPageContainer>
</FormContainer>
</AuthBox>
</AuthContainer>
</Wrapper>
);
}

View File

@ -12,6 +12,9 @@ import PrivateChannelStore from "./PrivateChannelStore";
import ThemeStore from "./ThemeStore";
import UserStore from "./UserStore";
// dev thing to force toggle branding on auth pages for testing.
export const AUTH_NO_BRANDING = false;
export default class AppStore {
// whether the gateway is ready
@observable isGatewayReady = false;