Working on refactoring to support router use case

This commit is contained in:
Max Lynch
2020-12-30 13:19:31 -06:00
parent 3fe67d30b3
commit 29ae24c6a6
11 changed files with 172 additions and 145 deletions
+128
View File
@@ -0,0 +1,128 @@
import { useDrag } from 'react-use-gesture';
import { Route, Switch } from 'wouter';
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 { useEffect, useState } from 'react';
import Home from './pages/Home';
import { cog, cogOutline, home, homeOutline, list, listOutline } from 'ionicons/icons';
const CurrentPage = ({ page }) => {
const currentPage = Store.useState(selectors.getCurrentPage);
// const Page = currentPage.component;
const Page = page;
const [local, setLocal] = useState(false);
useEffect(() => {
setLocal(true);
}, []);
return (
<PageStack>
{local ? (
<Switch>
<Route path="/" component={Home} />
</Switch>
) : (
<Page selected={true} />
)}
{/*pages.map(p => {
const Page = p.component;
return <Page selected={page.id === p.id} key={p.id} />;
})*/}
{/*<Page selected={true} />*/}
</PageStack>
);
};
const AppShell = ({ page }) => {
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',
}
);
// This is an example app layout. We've got a hidden menu that will be toggled
//
return (
<App
{...bind()}
style={{
touchAction: 'pan-x',
}}
>
<SafeAreaProvider>
<Menu open={showMenu} onClose={closeMenu}>
<MenuContent />
</Menu>
<Nav page={currentPage} />
{/*<CurrentPage page={currentPage} />*/}
<CurrentPage page={page} />
<TabBar>
<Tab
icon={homeOutline}
selectedIcon={home}
title="Home"
onClick={() => actions.setPage(p)}
selected={'home' === currentPage?.id}
/>
<Tab
icon={listOutline}
selectedIcon={list}
title="Lists"
onClick={() => actions.setPage(p)}
selected={'lists' === currentPage?.id}
/>
<Tab
icon={cogOutline}
selectedIcon={cog}
title="settings"
onClick={() => actions.setPage(p)}
selected={'settings' === currentPage?.id}
/>
</TabBar>
<Backdrop open={showMenu || showNotifications} onClose={backdropClose} />
<Modal open={showNotifications} onClose={closeNotifications}>
<Notifications />
</Modal>
</SafeAreaProvider>
</App>
);
};
export default AppShell;
+3 -11
View File
@@ -14,8 +14,6 @@ const MenuItem = ({ children, ...props }) => (
); );
const MenuContent = () => { const MenuContent = () => {
const menuLinks = Store.useState(selectors.getMenuLinks);
const go = page => { const go = page => {
actions.setPage(page); actions.setPage(page);
actions.setMenuOpen(false); actions.setMenuOpen(false);
@@ -27,15 +25,9 @@ const MenuContent = () => {
<h2 className="text-xl select-none dark:text-gray-500">Menu</h2> <h2 className="text-xl select-none dark:text-gray-500">Menu</h2>
</div> </div>
<ul> <ul>
{menuLinks.map(p => { <MenuItem onClick={() => {}}>Home</MenuItem>
const title = typeof p.title === 'function' ? p.title() : p.title; <MenuItem onClick={() => {}}>Lists</MenuItem>
<MenuItem onClick={() => {}}>Settings</MenuItem>
return (
<MenuItem key={p.id} onClick={() => go(p)}>
{title}
</MenuItem>
);
})}
</ul> </ul>
</> </>
); );
+10 -1
View File
@@ -3,6 +3,8 @@ import Card from '../ui/Card';
import Content from '../ui/Content'; import Content from '../ui/Content';
import * as selectors from '../../store/selectors'; import * as selectors from '../../store/selectors';
import usePage from '../../hooks/usePage';
import { home, homeOutline } from 'ionicons/icons';
const HomeCard = ({ title, type, text, author, image }) => ( const HomeCard = ({ title, type, text, author, image }) => (
<Card className="my-4"> <Card className="my-4">
@@ -18,10 +20,17 @@ const HomeCard = ({ title, type, text, author, image }) => (
); );
const Home = ({ selected }) => { const Home = ({ selected }) => {
usePage({
id: 'home',
title: 'Home',
icon: homeOutline,
selectedIcon: home,
});
const homeItems = Store.useState(selectors.getHomeItems); const homeItems = Store.useState(selectors.getHomeItems);
return ( return (
<Content visible={selected} className="p-4 dark:bg-black"> <Content visible={true} className="p-4 dark:bg-black">
{homeItems.map((i, index) => ( {homeItems.map((i, index) => (
<HomeCard {...i} key={index} /> <HomeCard {...i} key={index} />
))} ))}
+1 -1
View File
@@ -6,7 +6,7 @@ import * as actions from '../../store/actions';
const Nav = ({ page }) => { const Nav = ({ page }) => {
const [showProfileMenu, setShowProfileMenu] = useState(false); const [showProfileMenu, setShowProfileMenu] = useState(false);
const title = typeof page.title === 'function' ? page.title() : page.title; const title = typeof page?.title === 'function' ? page?.title() : page?.title || '';
useEffect(() => { useEffect(() => {
Plugins.StatusBar.setStyle({ Plugins.StatusBar.setStyle({
+12
View File
@@ -0,0 +1,12 @@
import { useEffect } from 'react';
import Store from '../store';
const usePage = fields => {
useEffect(() => {
Store.update(s => {
s.currentPage = fields;
});
}, [fields]);
};
export default usePage;
+6
View File
@@ -6233,6 +6233,12 @@
"errno": "~0.1.7" "errno": "~0.1.7"
} }
}, },
"wouter": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/wouter/-/wouter-2.7.0.tgz",
"integrity": "sha512-+0KbaxtM8pcLZWH22oaatq1Rbtce+0KXnrGCjy/GSFPNs3pTyyL6nQoiPga+96LqO8SPnC8wy15jD7Ix/tZm1A==",
"dev": true
},
"wrappy": { "wrappy": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+2 -1
View File
@@ -30,6 +30,7 @@
"react-toggle": "^4.1.1", "react-toggle": "^4.1.1",
"react-transition-group": "^4.4.1", "react-transition-group": "^4.4.1",
"react-use-gesture": "^9.0.0-beta.11", "react-use-gesture": "^9.0.0-beta.11",
"reselect": "^4.0.0" "reselect": "^4.0.0",
"wouter": "^2.7.0"
} }
} }
+3 -94
View File
@@ -1,97 +1,6 @@
import { useDrag } from 'react-use-gesture'; import AppShell from '../components/AppShell';
import Home from '../components/pages/Home';
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 { useEffect, useState } from 'react';
const CurrentPage = ({ page }) => {
const pages = Store.useState(selectors.getPages);
const currentPage = Store.useState(selectors.getCurrentPage);
const Page = currentPage.component;
return (
<PageStack>
{/*pages.map(p => {
const Page = p.component;
return <Page selected={page.id === p.id} key={p.id} />;
})*/}
<Page selected={true} />
</PageStack>
);
};
export default function Index() { export default function Index() {
const showMenu = Store.useState(selectors.getMenuOpen); return <AppShell page={Home} />;
const showNotifications = Store.useState(selectors.getNotificationsOpen);
const currentPage = Store.useState(selectors.getCurrentPage);
const tabs = Store.useState(selectors.getTabs);
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',
}
);
// This is an example app layout. We've got a hidden menu that will be toggled
//
return (
<App
{...bind()}
style={{
touchAction: 'pan-x',
}}
>
<SafeAreaProvider>
<Menu open={showMenu} onClose={closeMenu}>
<MenuContent />
</Menu>
<Nav page={currentPage} />
<CurrentPage page={currentPage} />
<TabBar>
{tabs.map(p => (
<Tab
key={p.id}
{...p}
onClick={() => actions.setPage(p)}
selected={p.id === currentPage.id}
/>
))}
</TabBar>
<Backdrop open={showMenu || showNotifications} onClose={backdropClose} />
<Modal open={showNotifications} onClose={closeNotifications}>
<Notifications />
</Modal>
</SafeAreaProvider>
</App>
);
} }
+6
View File
@@ -0,0 +1,6 @@
import AppShell from '../../components/AppShell';
import Home from '../../components/pages/Home';
export default function UserId() {
return <AppShell page={Home} />;
}
+1 -34
View File
@@ -7,32 +7,6 @@ import Lists from '../components/pages/Lists';
import Settings from '../components/pages/Settings'; import Settings from '../components/pages/Settings';
import ListDetail from '../components/pages/ListDetail'; import ListDetail from '../components/pages/ListDetail';
// The available pages here
const pages = [
{ id: 'home', title: 'Home', icon: homeOutline, selectedIcon: home, component: Home },
{
id: 'lists',
title: 'Lists',
icon: listOutline,
selectedIcon: list,
component: Lists,
},
{
id: 'list-detail',
title: () => Store.getRawState().selectedList?.name,
icon: listOutline,
selectedIcon: list,
component: ListDetail,
},
{
id: 'settings',
title: 'Settings',
icon: cogOutline,
selectedIcon: cog,
component: Settings,
},
];
export const images = [ export const images = [
'https://images.unsplash.com/photo-1608091526083-86ae8489ae5c?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=2100&q=80', 'https://images.unsplash.com/photo-1608091526083-86ae8489ae5c?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=2100&q=80',
'https://images.unsplash.com/photo-1608050072262-7b26ba63fb46?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=2100&q=80', 'https://images.unsplash.com/photo-1608050072262-7b26ba63fb46?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=2100&q=80',
@@ -91,14 +65,7 @@ const Store = new PullStateStore({
safeAreaBottom: 0, safeAreaBottom: 0,
menuOpen: false, menuOpen: false,
notificationsOpen: false, notificationsOpen: false,
currentPage: pages[0], currentPage: null,
pages,
// The pages that are linked to tabs
tabs: pages.filter(p => ['home', 'lists', 'settings'].indexOf(p.id) >= 0),
// The pages that are linked to the menu
menuLinks: pages.filter(p => ['home', 'lists', 'settings'].indexOf(p.id) >= 0),
homeItems, homeItems,
lists, lists,
selectedList: null, selectedList: null,
-3
View File
@@ -5,9 +5,6 @@ const getState = state => state;
export const getMenuOpen = createSelector(getState, state => state.menuOpen); export const getMenuOpen = createSelector(getState, state => state.menuOpen);
export const getNotificationsOpen = createSelector(getState, state => state.notificationsOpen); export const getNotificationsOpen = createSelector(getState, state => state.notificationsOpen);
export const getCurrentPage = createSelector(getState, state => state.currentPage); export const getCurrentPage = createSelector(getState, state => state.currentPage);
export const getTabs = createSelector(getState, state => state.tabs);
export const getMenuLinks = createSelector(getState, state => state.menuLinks);
export const getPages = createSelector(getState, state => state.pages);
// App specific selectors // App specific selectors
export const getHomeItems = createSelector(getState, state => state.homeItems); export const getHomeItems = createSelector(getState, state => state.homeItems);