From e5d7d7b5ad07677a7f971fcc6955a5bddec5de4d Mon Sep 17 00:00:00 2001 From: 0xzion <0xzion.penx@gmail.com> Date: Thu, 25 Apr 2024 18:46:20 +0800 Subject: [PATCH] feat: improve settings ui in mobile --- extensions/database/src/ui/TagDrawer.tsx | 1 + packages/app/src/Workbench/BottomBar.tsx | 2 - .../BottomBarDrawer/BottomBarDrawer.tsx | 46 ---- .../BottomBarDrawer/QuickAddEditor.tsx | 209 ------------------ .../Workbench/BottomBarDrawer/QuickAddTag.tsx | 43 ---- .../Workbench/BulletDrawer/BulletDrawer.tsx | 1 + .../app/src/Workbench/NodeNav/MobileNav.tsx | 8 + .../Workbench/PageSettings/PageSettings.tsx | 19 ++ .../Workbench/PageSettings/SettingsDrawer.tsx | 57 +++++ .../SettingsModal/SettingsSidebar.tsx | 84 +++++-- .../SpacePopover/SpacePopoverTrigger.tsx | 15 +- .../Workbench/SidebarDrawer/SidebarDrawer.tsx | 1 + packages/app/src/Workbench/Workbench.tsx | 2 + packages/hooks/src/index.ts | 2 +- packages/hooks/src/useBottomBarDrawer.ts | 12 - packages/hooks/src/useSettingDrawer.ts | 27 +++ packages/store/src/stores/RouterStore.ts | 6 + packages/store/src/types.ts | 1 + 18 files changed, 201 insertions(+), 335 deletions(-) delete mode 100644 packages/app/src/Workbench/BottomBarDrawer/BottomBarDrawer.tsx delete mode 100644 packages/app/src/Workbench/BottomBarDrawer/QuickAddEditor.tsx delete mode 100644 packages/app/src/Workbench/BottomBarDrawer/QuickAddTag.tsx create mode 100644 packages/app/src/Workbench/PageSettings/PageSettings.tsx create mode 100644 packages/app/src/Workbench/PageSettings/SettingsDrawer.tsx delete mode 100644 packages/hooks/src/useBottomBarDrawer.ts create mode 100644 packages/hooks/src/useSettingDrawer.ts diff --git a/extensions/database/src/ui/TagDrawer.tsx b/extensions/database/src/ui/TagDrawer.tsx index 948717d8b..6a836b65b 100644 --- a/extensions/database/src/ui/TagDrawer.tsx +++ b/extensions/database/src/ui/TagDrawer.tsx @@ -36,6 +36,7 @@ export const TagDrawer = () => { right-0 zIndex-101 autoFocus + outlineNone // overflowHidden > diff --git a/packages/app/src/Workbench/BottomBar.tsx b/packages/app/src/Workbench/BottomBar.tsx index 83bd7154f..3aca7fb00 100644 --- a/packages/app/src/Workbench/BottomBar.tsx +++ b/packages/app/src/Workbench/BottomBar.tsx @@ -10,7 +10,6 @@ import { useNodeContext } from '@penx/node-hooks' import { store } from '@penx/store' import { DailyShortcut, MotionButton } from '@penx/widget' import { setStatusBarColor } from '../common/setStatusBarColor' -import { BottomBarDrawer } from './BottomBarDrawer/BottomBarDrawer' import { QuickAdd } from './QuickAdd/QuickAdd' interface ActionButtonProps extends ButtonProps, FowerHTMLProps<'button'> { @@ -46,7 +45,6 @@ export function BottomBar() { return ( <> - diff --git a/packages/app/src/Workbench/BottomBarDrawer/BottomBarDrawer.tsx b/packages/app/src/Workbench/BottomBarDrawer/BottomBarDrawer.tsx deleted file mode 100644 index cded51c85..000000000 --- a/packages/app/src/Workbench/BottomBarDrawer/BottomBarDrawer.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { styled } from '@fower/react' -import { Drawer } from 'vaul' -import { useBottomBarDrawer } from '@penx/hooks' -import { QuickAddEditor } from './QuickAddEditor' - -const DrawerOverlay = styled(Drawer.Overlay) -const DrawerContent = styled(Drawer.Content) - -export const BottomBarDrawer = () => { - const { isOpen, close, open } = useBottomBarDrawer() - - return ( - { - if (o) { - open() - } else { - close() - } - }} - > - - - - - - - - ) -} diff --git a/packages/app/src/Workbench/BottomBarDrawer/QuickAddEditor.tsx b/packages/app/src/Workbench/BottomBarDrawer/QuickAddEditor.tsx deleted file mode 100644 index 543d3bc1f..000000000 --- a/packages/app/src/Workbench/BottomBarDrawer/QuickAddEditor.tsx +++ /dev/null @@ -1,209 +0,0 @@ -import { useRef, useState } from 'react' -import TextareaAutosize from 'react-textarea-autosize' -import { Box, css } from '@fower/react' -import { Clock, Hash, X } from 'lucide-react' -import { Button, Checkbox, toast } from 'uikit' -import { ELEMENT_P, ELEMENT_TAG, ELEMENT_TODO } from '@penx/constants' -import { useBottomBarDrawer, useRouterStore } from '@penx/hooks' -import { db, getCommonNode, getNewNode } from '@penx/local-db' -import { Node } from '@penx/model' -import { store } from '@penx/store' -import { QuickAddTag } from './QuickAddTag' - -export const QuickAddEditor = () => { - const { close } = useBottomBarDrawer() - const ref = useRef(null) - - const [value, setValue] = useState('') - const [isTodo, setIsTodo] = useState(false) - const [databases, setDatabases] = useState([]) - - const { isTodos } = useRouterStore() - - function selectTag(node: Node) { - if (databases.map((d) => d.id).includes(node.id)) { - setDatabases(databases.filter((d) => d.id !== node.id)) - } else { - setDatabases([...databases, node]) - } - - ref.current?.focus() - } - - async function addWithTags() { - const spaceId = store.space.getActiveSpace().id - const children: any[] = [{ text: value }, { text: ' ' }] - const element: any = { - type: isTodo ? ELEMENT_TODO : ELEMENT_P, - children, - } - const divider = { text: ' ' } - - const tags = databases.map((d) => ({ - type: ELEMENT_TAG, - databaseId: d.id, - trigger: '#', - name: d.tagName, - isOpen: false, - children: [{ text: '#' + d.tagName }], - })) - - tags.forEach((tag, index) => { - if (index === tags.length - 1) { - children.push(...[tag, divider]) - // children.push(tag) - } else { - children.push(tag) - } - }) - - const newNode = getCommonNode({ - spaceId, - element, - }) - - const newTodayNode = await db.addNodesToToday(spaceId, [newNode]) - - for (const tag of tags) { - await db.createTagRow(spaceId, tag.name, newNode.id) - } - - if (isTodo) { - await db.createTodoRow(spaceId, newNode.id, newTodayNode.id) - } - - const nodes = await db.listNodesBySpaceId(spaceId) - - store.node.setNodes(nodes) - store.node.selectNode(newTodayNode) - } - - async function send() { - if (!value) return - - if (databases.length > 0) { - addWithTags() - } else { - if (isTodo) { - store.node.addTodo(value, isTodos()) - } else { - store.node.addTextToToday(value) - } - } - close() - } - - return ( - - - - {isTodo && ( - - - - - - )} - - setValue(e.target.value)} - /> - - - {databases.length > 0 && ( - - {databases.map((node) => { - return ( - selectTag(node)} - > - #{node.tagName} - - - - - ) - })} - - )} - - - - - - { - setIsTodo(e.target.checked) - ref.current?.focus() - }} - /> - - - - - { - toast.info('Coming soon!') - }} - > - - - {/* - - */} - - - - - { - selectTag(node) - }} - /> - - - ) -} diff --git a/packages/app/src/Workbench/BottomBarDrawer/QuickAddTag.tsx b/packages/app/src/Workbench/BottomBarDrawer/QuickAddTag.tsx deleted file mode 100644 index 906c6f011..000000000 --- a/packages/app/src/Workbench/BottomBarDrawer/QuickAddTag.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { Box } from '@fower/react' -import { Node } from '@penx/model' -import { useDatabaseNodes } from '@penx/node-hooks' - -interface Props { - onSelect: (node: Node) => void -} - -export const QuickAddTag = ({ onSelect }: Props) => { - const nodes = useDatabaseNodes() - return ( - - - Quick add a tag: - - - {nodes.map((item) => { - const node = new Node(item) - if (node.isTodoDatabase) return null - return ( - onSelect(node)} - > - #{node.tagName} - - ) - })} - - - ) -} diff --git a/packages/app/src/Workbench/BulletDrawer/BulletDrawer.tsx b/packages/app/src/Workbench/BulletDrawer/BulletDrawer.tsx index 3df4e4dc6..bf1276d99 100644 --- a/packages/app/src/Workbench/BulletDrawer/BulletDrawer.tsx +++ b/packages/app/src/Workbench/BulletDrawer/BulletDrawer.tsx @@ -35,6 +35,7 @@ export const BulletDrawer = () => { left-0 right-0 zIndex-101 + outlineNone autoFocus > diff --git a/packages/app/src/Workbench/NodeNav/MobileNav.tsx b/packages/app/src/Workbench/NodeNav/MobileNav.tsx index ae54159f4..3dbc22dc6 100644 --- a/packages/app/src/Workbench/NodeNav/MobileNav.tsx +++ b/packages/app/src/Workbench/NodeNav/MobileNav.tsx @@ -11,6 +11,14 @@ function Title() { const { activeNodes } = useActiveNodes() const router = useRouterStore() + if (router.isSettings()) { + return ( + + Settings + + ) + } + if (router.isTodos()) { return ( diff --git a/packages/app/src/Workbench/PageSettings/PageSettings.tsx b/packages/app/src/Workbench/PageSettings/PageSettings.tsx new file mode 100644 index 000000000..5fa54b660 --- /dev/null +++ b/packages/app/src/Workbench/PageSettings/PageSettings.tsx @@ -0,0 +1,19 @@ +import { Box } from '@fower/react' +import { WORKBENCH_NAV_HEIGHT } from '@penx/constants' +import { SettingsSidebar } from '../SettingsModal/SettingsSidebar' +import { SettingsDrawer } from './SettingsDrawer' + +export const PageSettings = () => { + return ( + + + + + ) +} diff --git a/packages/app/src/Workbench/PageSettings/SettingsDrawer.tsx b/packages/app/src/Workbench/PageSettings/SettingsDrawer.tsx new file mode 100644 index 000000000..aab8f2897 --- /dev/null +++ b/packages/app/src/Workbench/PageSettings/SettingsDrawer.tsx @@ -0,0 +1,57 @@ +import { Box, styled } from '@fower/react' +import { Drawer } from 'vaul' +import { SettingsType } from '@penx/constants' +import { useSettingDrawer } from '@penx/hooks' +import { SyncServer } from '../../SyncServer/SyncServer' +import { AccountSettings } from '../AccountSettings/AccountSettings' +import { Backup } from '../Backup/Backup' +import { RecoveryPhrase } from '../RecoveryPhrase/RecoveryPhrase' +import { SpaceSettings } from '../SpaceSettings/SpaceSettings' + +const DrawerOverlay = styled(Drawer.Overlay) +const DrawerContent = styled(Drawer.Content) + +export const SettingsDrawer = () => { + const { isOpen, type, spaceId, close, open } = useSettingDrawer() + + return ( + { + if (o) { + open(type, spaceId) + } else { + close() + } + }} + > + + + + {type === SettingsType.ACCOUNT_SETTINGS && } + {type === SettingsType.RECOVERY_PHRASE && } + {type === SettingsType.SYNC_BACKUP && } + {type === SettingsType.SYNC_SERVER && } + {type === SettingsType.SPACE && } + + + + ) +} diff --git a/packages/app/src/Workbench/SettingsModal/SettingsSidebar.tsx b/packages/app/src/Workbench/SettingsModal/SettingsSidebar.tsx index 8b0e195f7..ebbe4ab8b 100644 --- a/packages/app/src/Workbench/SettingsModal/SettingsSidebar.tsx +++ b/packages/app/src/Workbench/SettingsModal/SettingsSidebar.tsx @@ -1,6 +1,14 @@ import { useMemo } from 'react' +import { isMobile } from 'react-device-detect' import { Box, FowerHTMLProps, styled } from '@fower/react' -import { Cloud, GitCompare, Key, LogOut, User } from 'lucide-react' +import { + ChevronRightIcon, + Cloud, + GitCompare, + Key, + LogOut, + User, +} from 'lucide-react' import { Avatar, AvatarFallback, @@ -10,11 +18,25 @@ import { } from 'uikit' import { isSyncEnabled, SettingsType } from '@penx/constants' import { appEmitter } from '@penx/event' -import { useSpaces, useUser } from '@penx/hooks' +import { useSettingDrawer, useSpaces, useUser } from '@penx/hooks' import { IconPassword } from '@penx/icons' import { useSession } from '@penx/session' -const Title = styled('div', ['gray400', 'mb4', 'textXS', 'uppercase']) +const Title = styled('div', ['gray400', 'mb3', 'textXS', 'uppercase']) + +interface SectionProps extends FowerHTMLProps<'div'> {} +function Section({ children, ...rest }: SectionProps) { + return ( + + {children} + + ) +} interface SidebarItemProps extends FowerHTMLProps<'div'> { type: any @@ -24,30 +46,48 @@ interface SidebarItemProps extends FowerHTMLProps<'div'> { function SidebarItem({ type = SettingsType.PREFERENCES, spaceId, + children, ...rest }: SidebarItemProps) { const { data = SettingsType.PREFERENCES, setData } = useModalContext<{ type: SettingsType spaceId?: string }>() + + const settingDrawer = useSettingDrawer() + return ( { + if (isMobile) { + settingDrawer.open(type, spaceId!) + return + } setData({ type, spaceId }) }} - /> + > + + {children} + + + + + + ) } @@ -70,7 +110,14 @@ export const SettingsSidebar = () => { const image = session?.user?.image || '' return ( - + @@ -81,7 +128,7 @@ export const SettingsSidebar = () => { General - +
Account settings @@ -99,27 +146,28 @@ export const SettingsSidebar = () => { {isSyncEnabled && ( - + Sync servers )} - +
Space - - {spaces.map((space) => ( +
+ {spaces.map((space, index) => ( {space.name} ))} - +
@@ -128,7 +176,7 @@ export const SettingsSidebar = () => { w-100p colorScheme="red500" gap2 - display={['none', 'none', 'flex']} + // display={['none', 'none', 'flex']} onClick={async () => { // await disconnectAsync() // disconnect() diff --git a/packages/app/src/Workbench/Sidebar/SpacePopover/SpacePopoverTrigger.tsx b/packages/app/src/Workbench/Sidebar/SpacePopover/SpacePopoverTrigger.tsx index 38465010d..c6f7f574d 100644 --- a/packages/app/src/Workbench/Sidebar/SpacePopover/SpacePopoverTrigger.tsx +++ b/packages/app/src/Workbench/Sidebar/SpacePopover/SpacePopoverTrigger.tsx @@ -1,4 +1,5 @@ import { forwardRef } from 'react' +import { isMobile } from 'react-device-detect' import { Box } from '@fower/react' import { ChevronsUpDown, Settings } from 'lucide-react' import { @@ -76,9 +77,15 @@ export const SpacePopoverTrigger = forwardRef( opacity-100--$currentSpace--hover onClick={(e) => { close() - modalController.open(ModalNames.SETTINGS, { - type: SettingsType.ACCOUNT_SETTINGS, - }) + + if (isMobile) { + store.router.routeTo('SETTINGS') + } else { + modalController.open(ModalNames.SETTINGS, { + type: SettingsType.ACCOUNT_SETTINGS, + }) + } + drawer?.close?.() e.stopPropagation() }} @@ -90,7 +97,7 @@ export const SpacePopoverTrigger = forwardRef( isSquare roundedFull > - + )} diff --git a/packages/app/src/Workbench/SidebarDrawer/SidebarDrawer.tsx b/packages/app/src/Workbench/SidebarDrawer/SidebarDrawer.tsx index d3551d606..3ed863c4f 100644 --- a/packages/app/src/Workbench/SidebarDrawer/SidebarDrawer.tsx +++ b/packages/app/src/Workbench/SidebarDrawer/SidebarDrawer.tsx @@ -104,6 +104,7 @@ export const SidebarDrawer = () => { zIndex-101 // overflowHidden // bgNeutral100 + outlineNone px4 py4 > diff --git a/packages/app/src/Workbench/Workbench.tsx b/packages/app/src/Workbench/Workbench.tsx index e4965ae32..708aa0935 100644 --- a/packages/app/src/Workbench/Workbench.tsx +++ b/packages/app/src/Workbench/Workbench.tsx @@ -17,6 +17,7 @@ import { BottomBar } from './BottomBar' import { MobileNav } from './NodeNav/MobileNav' import { PCNav } from './NodeNav/PCNav' import { NodePanels } from './NodePanels' +import { PageSettings } from './PageSettings/PageSettings' import { PageTodo } from './PageTodo/PageTodo' import { SettingsModal } from './SettingsModal/SettingsModal' import { Sidebar } from './Sidebar/Sidebar' @@ -95,6 +96,7 @@ export const Workbench = () => { + {name === 'SETTINGS' && } {name === 'TODOS' && } {name === 'WEB3_PROFILE' && } {name === 'TASK_BOARD' && } diff --git a/packages/hooks/src/index.ts b/packages/hooks/src/index.ts index 05f7022e2..377eea111 100644 --- a/packages/hooks/src/index.ts +++ b/packages/hooks/src/index.ts @@ -8,7 +8,7 @@ export * from './useCommands' export * from './useSidebarDrawer' export * from './usePaletteDrawer' -export * from './useBottomBarDrawer' +export * from './useSettingDrawer' export * from './useBulletDrawer' export * from './useQuickAdd' diff --git a/packages/hooks/src/useBottomBarDrawer.ts b/packages/hooks/src/useBottomBarDrawer.ts deleted file mode 100644 index 2b5d8308d..000000000 --- a/packages/hooks/src/useBottomBarDrawer.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { atom, useAtom } from 'jotai' - -const bottomBarDrawerAtom = atom(false) - -export function useBottomBarDrawer() { - const [isOpen, setIsOpen] = useAtom(bottomBarDrawerAtom) - return { - isOpen, - open: () => setIsOpen(true), - close: () => setIsOpen(false), - } -} diff --git a/packages/hooks/src/useSettingDrawer.ts b/packages/hooks/src/useSettingDrawer.ts new file mode 100644 index 000000000..11986e0a1 --- /dev/null +++ b/packages/hooks/src/useSettingDrawer.ts @@ -0,0 +1,27 @@ +import { atom, useAtom } from 'jotai' +import { SettingsType } from '@penx/constants' + +const settingDrawerAtom = atom({ + isOpen: false, + type: SettingsType.ACCOUNT_SETTINGS, + spaceId: '', +}) + +export function useSettingDrawer() { + const [state, setState] = useAtom(settingDrawerAtom) + return { + ...state, + open: (type: SettingsType, spaceId: string) => { + setState({ + isOpen: true, + type, + spaceId, + }) + }, + close: () => + setState({ + ...state, + isOpen: false, + }), + } +} diff --git a/packages/store/src/stores/RouterStore.ts b/packages/store/src/stores/RouterStore.ts index ec6345821..d71db7838 100644 --- a/packages/store/src/stores/RouterStore.ts +++ b/packages/store/src/stores/RouterStore.ts @@ -44,11 +44,17 @@ export class RouterStore { return routerName === 'TODOS' } + isSettings = () => { + const routerName = this.getName() + return routerName === 'SETTINGS' + } + isShowMobileMenu = () => { const routerName = this.getName() return [ 'TRASH', 'NODE', + 'SETTINGS', 'TODOS', 'CREATE_SPACE', 'WEB3_PROFILE', diff --git a/packages/store/src/types.ts b/packages/store/src/types.ts index f1df6cc33..f4a4bb505 100644 --- a/packages/store/src/types.ts +++ b/packages/store/src/types.ts @@ -6,6 +6,7 @@ export type RouteName = | 'WEB3_PROFILE' | 'TASK_BOARD' | 'RESTORE_BACKUP' + | 'SETTINGS' export type IRouterStore = { name: RouteName