Moving to more workable v1 solution
This commit is contained in:
+12
-126
@@ -1,133 +1,19 @@
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { useDrag } from 'react-use-gesture';
|
||||
import { Router, Route, Switch, useRoute } from 'wouter';
|
||||
import { cog, cogOutline, home, homeOutline, list, listOutline } from 'ionicons/icons';
|
||||
import { IonApp, IonRouterOutlet } from '@ionic/react';
|
||||
import { IonReactRouter } from '@ionic/react-router';
|
||||
import { Redirect, Route } from 'react-router-dom';
|
||||
|
||||
import Store from '../store';
|
||||
import * as actions from '../store/actions';
|
||||
import * as selectors from '../store/selectors';
|
||||
|
||||
import App from '../components/ui/App';
|
||||
import Backdrop from '../components/ui/Backdrop';
|
||||
import Menu from '../components/ui/Menu';
|
||||
import Modal from '../components/ui/Modal';
|
||||
import Nav from '../components/ui/Nav';
|
||||
import PageStack from '../components/ui/PageStack';
|
||||
import Tab from '../components/ui/Tab';
|
||||
import TabBar from '../components/ui/TabBar';
|
||||
import { SafeAreaProvider } from '../components/ui/SafeArea';
|
||||
import Notifications from '../components/Notifications';
|
||||
import MenuContent from '../components/MenuContent';
|
||||
import Home from './pages/Home';
|
||||
import Lists from './pages/Lists';
|
||||
import Settings from './pages/Settings';
|
||||
import useLocation from '../hooks/useLocation';
|
||||
import ListDetail from './pages/ListDetail';
|
||||
|
||||
const CurrentPage = ({ page, pageProps = {} }) => {
|
||||
const currentPage = Store.useState(selectors.getCurrentPage);
|
||||
|
||||
const Page = page;
|
||||
|
||||
const [local, setLocal] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setLocal(true);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<PageStack>
|
||||
{local ? (
|
||||
<Switch>
|
||||
<Route path="/" component={Home} />
|
||||
<Route path="/lists" component={Lists} />
|
||||
<Route path="/lists/:listId" component={ListDetail} />
|
||||
<Route path="/settings" component={Settings} />
|
||||
</Switch>
|
||||
) : (
|
||||
<Page selected={true} {...pageProps} />
|
||||
)}
|
||||
</PageStack>
|
||||
);
|
||||
};
|
||||
import Tabs from './pages/Tabs';
|
||||
|
||||
const AppShell = ({ page, pageProps }) => {
|
||||
const [location] = useLocation();
|
||||
|
||||
const showMenu = Store.useState(selectors.getMenuOpen);
|
||||
const showNotifications = Store.useState(selectors.getNotificationsOpen);
|
||||
const currentPage = Store.useState(selectors.getCurrentPage);
|
||||
|
||||
const closeMenu = () => actions.setMenuOpen(false);
|
||||
|
||||
const backdropClose = () => {
|
||||
actions.setMenuOpen(false);
|
||||
actions.setNotificationsOpen(false);
|
||||
};
|
||||
|
||||
const closeNotifications = () => actions.setNotificationsOpen(false);
|
||||
|
||||
// To enable edge drag detection to open the side menu
|
||||
const bind = useDrag(
|
||||
({ down, movement: [mx], xy: [x, y], cancel }) => {
|
||||
if (mx > 5 && x < 50 && down) {
|
||||
actions.setMenuOpen(true);
|
||||
cancel();
|
||||
}
|
||||
},
|
||||
{
|
||||
axis: 'x',
|
||||
}
|
||||
);
|
||||
|
||||
console.log('Got location', location);
|
||||
|
||||
// This is an example app layout. We've got a hidden menu that will be toggled
|
||||
//
|
||||
return (
|
||||
<App
|
||||
{...bind()}
|
||||
style={{
|
||||
touchAction: 'pan-x',
|
||||
}}
|
||||
>
|
||||
<SafeAreaProvider>
|
||||
<Router hook={useLocation}>
|
||||
<Menu open={showMenu} onClose={closeMenu}>
|
||||
<MenuContent />
|
||||
</Menu>
|
||||
<Nav page={currentPage} />
|
||||
<CurrentPage page={page} pageProps={pageProps} />
|
||||
<TabBar>
|
||||
<Tab
|
||||
icon={homeOutline}
|
||||
selectedIcon={home}
|
||||
title="Home"
|
||||
href="/"
|
||||
selected={'/' === location}
|
||||
/>
|
||||
<Tab
|
||||
icon={listOutline}
|
||||
selectedIcon={list}
|
||||
title="Lists"
|
||||
href="/lists"
|
||||
selected={location.indexOf('/lists') === 0}
|
||||
/>
|
||||
<Tab
|
||||
icon={cogOutline}
|
||||
selectedIcon={cog}
|
||||
title="Settings"
|
||||
href="/settings"
|
||||
selected={'/settings' === location}
|
||||
/>
|
||||
</TabBar>
|
||||
<Backdrop open={showMenu || showNotifications} onClose={backdropClose} />
|
||||
<Modal open={showNotifications} onClose={closeNotifications}>
|
||||
<Notifications />
|
||||
</Modal>
|
||||
</Router>
|
||||
</SafeAreaProvider>
|
||||
</App>
|
||||
<IonApp>
|
||||
<IonReactRouter>
|
||||
<IonRouterOutlet>
|
||||
<Route path="/tabs" render={() => <Tabs />} />
|
||||
<Route exact path="/" render={() => <Redirect to="/tabs" />} />
|
||||
</IonRouterOutlet>
|
||||
</IonReactRouter>
|
||||
</IonApp>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Link as ReactRouterLink } from 'react-router-dom';
|
||||
|
||||
const Link = ({ children, href, router, ...props }) => {
|
||||
const [local, setLocal] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setLocal(true);
|
||||
}, []);
|
||||
|
||||
console.log('Rendering link', local, router);
|
||||
|
||||
if (!local || router === false) {
|
||||
return children;
|
||||
}
|
||||
// return <a {...props}>{children}</a>;
|
||||
return (
|
||||
<ReactRouterLink to={href} {...props}>
|
||||
{children}
|
||||
</ReactRouterLink>
|
||||
);
|
||||
};
|
||||
|
||||
export default Link;
|
||||
+13
-20
@@ -1,10 +1,7 @@
|
||||
import Store from '../../store';
|
||||
import Card from '../ui/Card';
|
||||
import Content from '../ui/Content';
|
||||
|
||||
import * as selectors from '../../store/selectors';
|
||||
import usePage from '../../hooks/usePage';
|
||||
import { home, homeOutline } from 'ionicons/icons';
|
||||
import { IonPage, IonHeader, IonToolbar, IonTitle, IonContent } from '@ionic/react';
|
||||
import { homeItems } from '../../store';
|
||||
|
||||
const HomeCard = ({ title, type, text, author, image }) => (
|
||||
<Card className="my-4">
|
||||
@@ -19,23 +16,19 @@ const HomeCard = ({ title, type, text, author, image }) => (
|
||||
</Card>
|
||||
);
|
||||
|
||||
const Home = ({ selected }) => {
|
||||
usePage({
|
||||
id: 'home',
|
||||
title: 'Home',
|
||||
icon: homeOutline,
|
||||
selectedIcon: home,
|
||||
});
|
||||
|
||||
const homeItems = Store.useState(selectors.getHomeItems);
|
||||
|
||||
return (
|
||||
<Content className="p-4 dark:bg-black">
|
||||
const Home = () => (
|
||||
<IonPage>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>Inbox</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent>
|
||||
{homeItems.map((i, index) => (
|
||||
<HomeCard {...i} key={index} />
|
||||
))}
|
||||
</Content>
|
||||
);
|
||||
};
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
|
||||
export default Home;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Link } from 'wouter';
|
||||
import Link from '../../components/Link';
|
||||
|
||||
import usePage from '../../hooks/usePage';
|
||||
import Store from '../../store';
|
||||
|
||||
+15
-15
@@ -1,13 +1,10 @@
|
||||
import { Link } from 'wouter';
|
||||
import Link from '../../components/Link';
|
||||
|
||||
import usePage from '../../hooks/usePage';
|
||||
import Store from '../../store';
|
||||
import * as actions from '../../store/actions';
|
||||
import * as selectors from '../../store/selectors';
|
||||
|
||||
import Content from '../ui/Content';
|
||||
import List from '../ui/List';
|
||||
import VirtualScroll from '../ui/VirtualScroll';
|
||||
import { IonPage, IonHeader, IonToolbar, IonTitle, IonContent } from '@ionic/react';
|
||||
|
||||
const ListEntry = ({ list, ...props }) => (
|
||||
<Link href={`/lists/${list.id}`}>
|
||||
@@ -33,17 +30,20 @@ const AllLists = ({ onSelect }) => {
|
||||
);
|
||||
};
|
||||
|
||||
const Lists = ({ selected }) => {
|
||||
usePage({
|
||||
title: 'Lists',
|
||||
});
|
||||
|
||||
const Lists = ({ selected, ...props }) => {
|
||||
return (
|
||||
<Content className="p-4 dark:bg-black">
|
||||
<List className="h-full w-full">
|
||||
<AllLists />
|
||||
</List>
|
||||
</Content>
|
||||
<IonPage>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>Lists</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent>
|
||||
<List className="h-full w-full">
|
||||
<AllLists />
|
||||
</List>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,38 +1,23 @@
|
||||
import Store from '../../store';
|
||||
import * as selectors from '../../store/selectors';
|
||||
import * as actions from '../../store/actions';
|
||||
|
||||
import Content from '../ui/Content';
|
||||
import List from '../ui/List';
|
||||
import ListItem from '../ui/ListItem';
|
||||
import Toggle from '../ui/Toggle';
|
||||
import usePage from '../../hooks/usePage';
|
||||
|
||||
const Settings = ({ selected }) => {
|
||||
usePage({
|
||||
title: 'Settings',
|
||||
});
|
||||
|
||||
const Settings = () => {
|
||||
const enableNotifications = Store.useState();
|
||||
const settings = Store.useState(selectors.getSettings);
|
||||
|
||||
return (
|
||||
<Content className="p-4 dark:bg-black">
|
||||
<List>
|
||||
<ListItem className="flex">
|
||||
<span className="text-md flex-1 dark:text-gray-200">Enable Notifications</span>
|
||||
<Toggle
|
||||
checked={settings.enableNotifications}
|
||||
onChange={e =>
|
||||
actions.setSettings({
|
||||
...settings,
|
||||
enableNotifications: e.target.checked,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
</List>
|
||||
</Content>
|
||||
<IonPage>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>Settings</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent>
|
||||
<List className="h-full w-full">
|
||||
<AllLists />
|
||||
</List>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import { Redirect, Route } from 'react-router-dom';
|
||||
import {
|
||||
IonApp,
|
||||
IonRouterOutlet,
|
||||
IonTabs,
|
||||
IonTabBar,
|
||||
IonTabButton,
|
||||
IonIcon,
|
||||
IonLabel,
|
||||
} from '@ionic/react';
|
||||
import { IonReactRouter } from '@ionic/react-router';
|
||||
import { ellipse, square, triangle } from 'ionicons/icons';
|
||||
|
||||
import Home from './Home';
|
||||
import Lists from './Lists';
|
||||
import Settings from './Settings';
|
||||
|
||||
const Tabs = () => {
|
||||
return (
|
||||
<IonReactRouter>
|
||||
<IonTabs>
|
||||
<IonRouterOutlet>
|
||||
<Route path="/tabs/home" component={Home} exact={true} />
|
||||
<Route path="/tabs/lists" component={Lists} exact={true} />
|
||||
<Route path="/tabs/settings" component={Settings} exact={true} />
|
||||
<Route path="/" render={() => <Redirect to="/tabs/home" />} exact={true} />
|
||||
</IonRouterOutlet>
|
||||
<IonTabBar slot="bottom">
|
||||
<IonTabButton tab="tab1" href="/tabs/home">
|
||||
<IonIcon icon={triangle} />
|
||||
<IonLabel>Tab 1</IonLabel>
|
||||
</IonTabButton>
|
||||
<IonTabButton tab="tab2" href="/tabs/lists">
|
||||
<IonIcon icon={ellipse} />
|
||||
<IonLabel>Tab 2</IonLabel>
|
||||
</IonTabButton>
|
||||
<IonTabButton tab="tab3" href="/tabs/settings">
|
||||
<IonIcon icon={square} />
|
||||
<IonLabel>Tab 3</IonLabel>
|
||||
</IonTabButton>
|
||||
</IonTabBar>
|
||||
</IonTabs>
|
||||
</IonReactRouter>
|
||||
);
|
||||
};
|
||||
|
||||
export default Tabs;
|
||||
@@ -1,12 +0,0 @@
|
||||
import classNames from 'classnames';
|
||||
|
||||
const Content = ({ className, children, ...props }) => (
|
||||
<div
|
||||
{...props}
|
||||
className={classNames(`h-full w-full overflow-auto py-2 absolute top-0`, className)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
||||
export default Content;
|
||||
@@ -1,37 +0,0 @@
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { Transition } from 'react-transition-group';
|
||||
|
||||
const duration = 500;
|
||||
|
||||
const defaultStyle = {
|
||||
transition: `opacity ${duration}ms ease-in-out`,
|
||||
opacity: 0,
|
||||
};
|
||||
|
||||
const transitionStyles = {
|
||||
entering: { opacity: 1 },
|
||||
entered: { opacity: 1 },
|
||||
exiting: { opacity: 0 },
|
||||
exited: { opacity: 0 },
|
||||
};
|
||||
|
||||
const PageStack = ({ children, className, ...props }) => (
|
||||
<div {...props} className={classNames('flex-1 z-0 overflow-hidden relative', className)}>
|
||||
<Transition in={true} duration={duration}>
|
||||
{state => (
|
||||
<div
|
||||
className="w-full h-full"
|
||||
style={{
|
||||
...defaultStyle,
|
||||
...transitionStyles[state],
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)}
|
||||
</Transition>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default PageStack;
|
||||
@@ -1,6 +1,6 @@
|
||||
import classNames from 'classnames';
|
||||
import Icon from './Icon';
|
||||
import { Link } from 'wouter';
|
||||
import Link from '../../components/Link';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
const Tab = ({ title, href, icon, selected, selectedIcon, onClick }) => {
|
||||
|
||||
Reference in New Issue
Block a user