Add bottom navigation and locale selector.

This commit is contained in:
Paul 2021-06-21 13:44:43 +01:00
parent 0115ace3fa
commit 3c6e3b9fbf
6 changed files with 137 additions and 5 deletions

View file

@ -0,0 +1,42 @@
import ComboBox from "../ui/ComboBox";
import { connectState } from "../../redux/connector";
import { WithDispatcher } from "../../redux/reducers";
import { LanguageEntry, Languages } from "../../context/Locale";
type Props = WithDispatcher & {
locale: string;
};
export function LocaleSelector(props: Props) {
return (
<ComboBox
value={props.locale}
onChange={e =>
props.dispatcher &&
props.dispatcher({
type: "SET_LOCALE",
locale: e.currentTarget.value as any
})
}
>
{Object.keys(Languages).map(x => {
const l = (Languages as any)[x] as LanguageEntry;
return (
<option value={x}>
{l.emoji} {l.display}
</option>
);
})}
</ComboBox>
);
}
export default connectState(
LocaleSelector,
state => {
return {
locale: state.locale
};
},
true
);

View file

@ -0,0 +1,72 @@
import styled, { css } from "styled-components";
import { Link } from "react-router-dom";
import IconButton from "../ui/IconButton";
import UserIcon from "../common/user/UserIcon";
import { useSelf } from "../../context/revoltjs/hooks";
import { useHistory, useLocation } from "react-router";
import { MessageCircle, Users } from "@styled-icons/feather";
const NavigationBase = styled.div`
z-index: 10;
height: 50px;
display: flex;
background: var(--secondary-background);
`;
const Button = styled.a<{ active: boolean }>`
flex: 1;
> a, > div, > a > div {
width: 100%;
height: 100%;
}
${ props => props.active && css`
background: var(--hover);
` }
`;
export default function BottomNavigation() {
const user = useSelf();
const history = useHistory();
const path = useLocation().pathname;
const friendsActive = path.startsWith("/friends");
const settingsActive = path.startsWith("/settings");
const homeActive = !(friendsActive || settingsActive);
return (
<NavigationBase>
<Button active={homeActive}>
<IconButton
onClick={() => {
if (!homeActive) {
if (settingsActive) {
if (history.length > 0) {
history.goBack();
} else {
history.push('/');
}
}
}
}}>
<MessageCircle size={26} />
</IconButton>
</Button>
<Button active={friendsActive}>
<Link to="/friends">
<IconButton>
<Users size={26} />
</IconButton>
</Link>
</Button>
<Button active={settingsActive}>
<Link to="/settings">
<IconButton>
<UserIcon target={user} size={26} status={true} />
</IconButton>
</Link>
</Button>
</NavigationBase>
);
}

View file

@ -1,4 +1,5 @@
import styled from "styled-components"; import styled, { css } from "styled-components";
import { isTouchscreenDevice } from "../../lib/isTouchscreenDevice";
export default styled.div` export default styled.div`
height: 100%; height: 100%;
@ -6,4 +7,8 @@ export default styled.div`
user-select: none; user-select: none;
flex-direction: row; flex-direction: row;
align-items: stretch; align-items: stretch;
${ isTouchscreenDevice && css`
padding-bottom: 50px;
` }
`; `;

View file

@ -1,6 +1,6 @@
import { Docked, OverlappingPanels } from "react-overlapping-panels"; import { Docked, OverlappingPanels, ShowIf } from "react-overlapping-panels";
import { isTouchscreenDevice } from "../lib/isTouchscreenDevice"; import { isTouchscreenDevice } from "../lib/isTouchscreenDevice";
import { Switch, Route } from "react-router-dom"; import { Switch, Route, useLocation } from "react-router-dom";
import styled from "styled-components"; import styled from "styled-components";
import ContextMenus from "../lib/ContextMenus"; import ContextMenus from "../lib/ContextMenus";
@ -11,6 +11,7 @@ import Notifications from "../context/revoltjs/Notifications";
import LeftSidebar from "../components/navigation/LeftSidebar"; import LeftSidebar from "../components/navigation/LeftSidebar";
import RightSidebar from "../components/navigation/RightSidebar"; import RightSidebar from "../components/navigation/RightSidebar";
import BottomNavigation from "../components/navigation/BottomNavigation";
import Home from './home/Home'; import Home from './home/Home';
import Friends from "./friends/Friends"; import Friends from "./friends/Friends";
@ -29,12 +30,20 @@ const Routes = styled.div`
`; `;
export default function App() { export default function App() {
const path = useLocation().pathname;
const fixedBottomNav = (path === '/' || path === '/settings' || path.startsWith("/friends"));
return ( return (
<OverlappingPanels <OverlappingPanels
width="100vw" width="100vw"
height="100vh" height="100vh"
leftPanel={{ width: 292, component: <LeftSidebar /> }} leftPanel={{ width: 292, component: <LeftSidebar /> }}
rightPanel={{ width: 240, component: <RightSidebar /> }} rightPanel={{ width: 240, component: <RightSidebar /> }}
bottomNav={{
component: <BottomNavigation />,
showIf: fixedBottomNav ? ShowIf.Always : ShowIf.Left,
height: 50
}}
docked={isTouchscreenDevice ? Docked.None : Docked.Left}> docked={isTouchscreenDevice ? Docked.None : Docked.Left}>
<Routes> <Routes>
<Switch> <Switch>

View file

@ -7,6 +7,7 @@ import { LIBRARY_VERSION } from "revolt.js";
import { Route, Switch } from "react-router-dom"; import { Route, Switch } from "react-router-dom";
import { ThemeContext } from "../../context/Theme"; import { ThemeContext } from "../../context/Theme";
import { AppContext } from "../../context/revoltjs/RevoltClient"; import { AppContext } from "../../context/revoltjs/RevoltClient";
import LocaleSelector from "../../components/common/LocaleSelector";
import background from "./background.jpg"; import background from "./background.jpg";
@ -33,7 +34,7 @@ export default function Login() {
&middot; App: <code>{APP_VERSION}</code> &middot; App: <code>{APP_VERSION}</code>
</span> </span>
<span> <span>
{/*<LocaleSelector />*/} <LocaleSelector />
</span> </span>
</div> </div>
<div className={styles.modal}> <div className={styles.modal}>

View file

@ -6,8 +6,8 @@ import { useForm } from "react-hook-form";
import { MailProvider } from "./MailProvider"; import { MailProvider } from "./MailProvider";
import { useContext, useState } from "preact/hooks"; import { useContext, useState } from "preact/hooks";
import { CheckCircle, Mail } from "@styled-icons/feather"; import { CheckCircle, Mail } from "@styled-icons/feather";
import { CaptchaBlock, CaptchaProps } from "./CaptchaBlock";
import { takeError } from "../../../context/revoltjs/util"; import { takeError } from "../../../context/revoltjs/util";
import { CaptchaBlock, CaptchaProps } from "./CaptchaBlock";
import { AppContext } from "../../../context/revoltjs/RevoltClient"; import { AppContext } from "../../../context/revoltjs/RevoltClient";
import FormField from "../FormField"; import FormField from "../FormField";
@ -15,6 +15,8 @@ import Button from "../../../components/ui/Button";
import Overline from "../../../components/ui/Overline"; import Overline from "../../../components/ui/Overline";
import Preloader from "../../../components/ui/Preloader"; import Preloader from "../../../components/ui/Preloader";
import wideSVG from '../../../assets/wide.svg';
interface Props { interface Props {
page: "create" | "login" | "send_reset" | "reset" | "resend"; page: "create" | "login" | "send_reset" | "reset" | "resend";
callback: (fields: { callback: (fields: {
@ -140,6 +142,7 @@ export function Form({ page, callback }: Props) {
return ( return (
<div className={styles.form}> <div className={styles.form}>
<img src={wideSVG} />
<form onSubmit={handleSubmit(onSubmit) as any}> <form onSubmit={handleSubmit(onSubmit) as any}>
{page !== "reset" && ( {page !== "reset" && (
<FormField <FormField