refactor: use tab instead of modal. fixed layout as well.
This commit is contained in:
parent
4620a17e0d
commit
b64c2a5fba
@ -1,5 +1,5 @@
|
|||||||
import { renderWithProviders, screen, waitFor } from '~/test-utils/test-helper';
|
import { renderWithProviders, screen, waitFor } from '~/test-utils/test-helper';
|
||||||
import App from '~/components/App';
|
import { AppRoot } from '~/components/AppRoot';
|
||||||
|
|
||||||
vi.mock('../decrypt-worker/client', () => {
|
vi.mock('../decrypt-worker/client', () => {
|
||||||
return {
|
return {
|
||||||
@ -10,7 +10,7 @@ vi.mock('../decrypt-worker/client', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should be able to render App', async () => {
|
test('should be able to render App', async () => {
|
||||||
renderWithProviders(<App />);
|
renderWithProviders(<AppRoot />);
|
||||||
|
|
||||||
// Should eventually load sdk version
|
// Should eventually load sdk version
|
||||||
await waitFor(() => screen.getByTestId('sdk-version'));
|
await waitFor(() => screen.getByTestId('sdk-version'));
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
import { Box, Center, Container } from '@chakra-ui/react';
|
|
||||||
import { SelectFile } from './SelectFile';
|
|
||||||
|
|
||||||
import { FileListing } from '~/features/file-listing/FileListing';
|
|
||||||
import { Footer } from './Footer';
|
|
||||||
import { Toolbar } from './Toolbar';
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Box height="full" width="full" pt="4">
|
|
||||||
<Container maxW="container.large">
|
|
||||||
<Center>
|
|
||||||
<SelectFile />
|
|
||||||
</Center>
|
|
||||||
<Toolbar />
|
|
||||||
<FileListing />
|
|
||||||
<Footer />
|
|
||||||
</Container>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default App;
|
|
@ -1,11 +1,15 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import App from './App';
|
import { MdSettings, MdHome } from 'react-icons/md';
|
||||||
|
import { ChakraProvider, Tabs, TabList, TabPanels, Tab, TabPanel, Icon, chakra } from '@chakra-ui/react';
|
||||||
|
|
||||||
|
import { MainTab } from '~/tabs/MainTab';
|
||||||
|
import { SettingsTab } from '~/tabs/SettingsTab';
|
||||||
|
|
||||||
import { ChakraProvider } from '@chakra-ui/react';
|
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import { theme } from '~/theme';
|
import { theme } from '~/theme';
|
||||||
import { persistSettings } from '~/features/settings/persistSettings';
|
import { persistSettings } from '~/features/settings/persistSettings';
|
||||||
import { setupStore } from '~/store';
|
import { setupStore } from '~/store';
|
||||||
|
import { Footer } from '~/components/Footer';
|
||||||
|
|
||||||
// Private to this file only.
|
// Private to this file only.
|
||||||
const store = setupStore();
|
const store = setupStore();
|
||||||
@ -16,7 +20,29 @@ export function AppRoot() {
|
|||||||
return (
|
return (
|
||||||
<ChakraProvider theme={theme}>
|
<ChakraProvider theme={theme}>
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<App />
|
<Tabs flex={1} minH={0} display="flex" flexDir="column">
|
||||||
|
<TabList justifyContent="center">
|
||||||
|
<Tab>
|
||||||
|
<Icon as={MdHome} mr="1" />
|
||||||
|
<chakra.span>应用</chakra.span>
|
||||||
|
</Tab>
|
||||||
|
<Tab>
|
||||||
|
<Icon as={MdSettings} mr="1" />
|
||||||
|
<chakra.span>设置</chakra.span>
|
||||||
|
</Tab>
|
||||||
|
</TabList>
|
||||||
|
|
||||||
|
<TabPanels overflow="auto" minW={0}>
|
||||||
|
<TabPanel>
|
||||||
|
<MainTab />
|
||||||
|
</TabPanel>
|
||||||
|
<TabPanel>
|
||||||
|
<SettingsTab />
|
||||||
|
</TabPanel>
|
||||||
|
</TabPanels>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
<Footer />
|
||||||
</Provider>
|
</Provider>
|
||||||
</ChakraProvider>
|
</ChakraProvider>
|
||||||
);
|
);
|
||||||
|
@ -5,18 +5,19 @@ import { CurrentYear } from './CurrentYear';
|
|||||||
|
|
||||||
export function Footer() {
|
export function Footer() {
|
||||||
return (
|
return (
|
||||||
<Center height="footer.container">
|
|
||||||
<Center
|
<Center
|
||||||
height="footer.content"
|
|
||||||
fontSize="sm"
|
fontSize="sm"
|
||||||
textAlign="center"
|
textAlign="center"
|
||||||
position="fixed"
|
|
||||||
bottom="0"
|
bottom="0"
|
||||||
w="full"
|
w="full"
|
||||||
|
pt="3"
|
||||||
|
pb="3"
|
||||||
|
borderTop="1px solid"
|
||||||
|
borderColor="gray.300"
|
||||||
bg="gray.100"
|
bg="gray.100"
|
||||||
color="gray.800"
|
color="gray.800"
|
||||||
left="0"
|
|
||||||
flexDir="column"
|
flexDir="column"
|
||||||
|
flexShrink={0}
|
||||||
>
|
>
|
||||||
<Flex as={Text}>
|
<Flex as={Text}>
|
||||||
{'音乐解锁 (__APP_VERSION_SHORT__'}
|
{'音乐解锁 (__APP_VERSION_SHORT__'}
|
||||||
@ -38,6 +39,5 @@ export function Footer() {
|
|||||||
。
|
。
|
||||||
</Text>
|
</Text>
|
||||||
</Center>
|
</Center>
|
||||||
</Center>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
import { Button, HStack, Icon, useDisclosure } from '@chakra-ui/react';
|
|
||||||
import { MdSettings } from 'react-icons/md';
|
|
||||||
import { SettingsModal } from '~/modals/SettingsModal';
|
|
||||||
|
|
||||||
export function Toolbar() {
|
|
||||||
const {
|
|
||||||
isOpen: isSettingsModalOpen,
|
|
||||||
onClose: onSettingsModalClose,
|
|
||||||
getButtonProps: getSettingsButtonProps,
|
|
||||||
} = useDisclosure();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<HStack alignItems="center" justifyContent="center" p="4">
|
|
||||||
<Button {...getSettingsButtonProps()}>
|
|
||||||
<Icon as={MdSettings} mr="1" />
|
|
||||||
设置
|
|
||||||
</Button>
|
|
||||||
</HStack>
|
|
||||||
<SettingsModal isOpen={isSettingsModalOpen} onClose={onSettingsModalClose} />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
import {
|
|
||||||
Button,
|
|
||||||
HStack,
|
|
||||||
Modal,
|
|
||||||
ModalBody,
|
|
||||||
ModalCloseButton,
|
|
||||||
ModalContent,
|
|
||||||
ModalFooter,
|
|
||||||
ModalHeader,
|
|
||||||
ModalOverlay,
|
|
||||||
} from '@chakra-ui/react';
|
|
||||||
|
|
||||||
export interface SettingsModalProps {
|
|
||||||
onClose: () => void;
|
|
||||||
isOpen: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function SettingsModal({ isOpen, onClose }: SettingsModalProps) {
|
|
||||||
return (
|
|
||||||
<Modal onClose={onClose} isOpen={isOpen} closeOnOverlayClick={false} scrollBehavior="inside" size="full" isCentered>
|
|
||||||
<ModalOverlay />
|
|
||||||
<ModalContent>
|
|
||||||
<ModalHeader>应用设置</ModalHeader>
|
|
||||||
<ModalCloseButton />
|
|
||||||
<ModalBody>
|
|
||||||
<p>Hallo</p>
|
|
||||||
<p>Thank you, thank you very much.</p>
|
|
||||||
<p>Ha-Halo, thank you</p>
|
|
||||||
<p>Thank you very much!</p>
|
|
||||||
</ModalBody>
|
|
||||||
<ModalFooter>
|
|
||||||
<HStack>
|
|
||||||
<Button onClick={onClose} variant="ghost" colorScheme="red">
|
|
||||||
放弃
|
|
||||||
</Button>
|
|
||||||
<Button onClick={onClose}>应用</Button>
|
|
||||||
</HStack>
|
|
||||||
</ModalFooter>
|
|
||||||
</ModalContent>
|
|
||||||
</Modal>
|
|
||||||
);
|
|
||||||
}
|
|
18
src/tabs/MainTab.tsx
Normal file
18
src/tabs/MainTab.tsx
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { Box, VStack } from '@chakra-ui/react';
|
||||||
|
import { SelectFile } from '../components/SelectFile';
|
||||||
|
|
||||||
|
import { FileListing } from '~/features/file-listing/FileListing';
|
||||||
|
|
||||||
|
export function MainTab() {
|
||||||
|
return (
|
||||||
|
<Box h="full" w="full" pt="4">
|
||||||
|
<VStack gap="3">
|
||||||
|
<SelectFile />
|
||||||
|
|
||||||
|
<Box w="full">
|
||||||
|
<FileListing />
|
||||||
|
</Box>
|
||||||
|
</VStack>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
10
src/tabs/SettingsTab.tsx
Normal file
10
src/tabs/SettingsTab.tsx
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
export function SettingsTab() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<p>Hallo</p>
|
||||||
|
<p>Thank you, thank you very much.</p>
|
||||||
|
<p>Ha-Halo, thank you</p>
|
||||||
|
<p>Thank you very much!</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -21,15 +21,18 @@ export const theme = extendTheme({
|
|||||||
},
|
},
|
||||||
styles: {
|
styles: {
|
||||||
global: {
|
global: {
|
||||||
body: {
|
'#root': {
|
||||||
minHeight: '100vh',
|
minHeight: '100vh',
|
||||||
|
maxHeight: '100vh',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
sizes: {
|
sizes: {
|
||||||
footer: {
|
footer: {
|
||||||
container: '7rem',
|
container: '5rem',
|
||||||
content: '5rem',
|
content: '4rem',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user