Skip to content

Commit dee4dc1

Browse files
committed
upgrade to react-router v6
1 parent 070fc82 commit dee4dc1

24 files changed

+240
-190
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@ packages
44
.webpack
55
out
66
.idea
7+
!/yarn.lock
8+
!/yarn-error.log

electron/bridge.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
import { clipboard, contextBridge, ipcRenderer } from 'electron';
1+
import { contextBridge, ipcRenderer } from 'electron';
2+
import { InvokeEnum } from '../src/interfaces/InvokeEnum';
23

34
export const api = {
4-
auth: () => {
5-
ipcRenderer.send('message', 'auth');
6-
},
75
copyToClipboard: (text: string) => {
8-
clipboard.writeText(text);
6+
ipcRenderer.invoke(InvokeEnum.COPY_TO_CLIPBOARD, text);
97
},
108
send: (channel: string, data?: any) => {
119
ipcRenderer.send(channel, data);

electron/main.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import { app, BrowserWindow, ipcMain, shell } from 'electron';
1+
import { app, BrowserWindow, clipboard, ipcMain, shell } from 'electron';
22
import { auth } from '../src/unitls/stackexchange-auth';
3+
import { InvokeEnum } from '../src/interfaces/InvokeEnum';
34

45
let mainWindow: BrowserWindow | null;
56

@@ -20,6 +21,7 @@ function createWindow() {
2021
title: 'StackOverflow',
2122
titleBarStyle: 'hiddenInset',
2223
webPreferences: {
24+
sandbox: true,
2325
nodeIntegration: false,
2426
contextIsolation: true,
2527
preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY
@@ -79,6 +81,10 @@ async function registerListeners() {
7981
ipcMain.on('offline', (event) => {
8082
console.log('offline');
8183
});
84+
85+
ipcMain.handle(InvokeEnum.COPY_TO_CLIPBOARD, (event, text) => {
86+
clipboard.writeText(text);
87+
});
8288
}
8389

8490
app

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,19 @@
1818
"@chakra-ui/react": "^1.6.10",
1919
"@emotion/react": "^11",
2020
"@emotion/styled": "^11",
21+
"@marshallofsound/webpack-asset-relocator-loader": "^0.5.0",
2122
"@types/react-router-dom": "^5.3.1",
2223
"axios": "^0.23.0",
2324
"dayjs": "^1.10.7",
25+
"file-loader": "^6.2.0",
2426
"framer-motion": "^4",
2527
"html-react-parser": "^1.4.0",
2628
"html-to-react": "^1.4.7",
2729
"react": "17.0.2",
2830
"react-dom": "17.0.2",
2931
"react-hot-loader": "4.13.0",
3032
"react-icons": "^4.3.1",
31-
"react-router-dom": "^5.3.0",
33+
"react-router-dom": "^6.0.0",
3234
"styled-components": "5.3.0"
3335
},
3436
"devDependencies": {

public/index.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
<meta charset="UTF-8">
66
<meta name="viewport" content="width=device-width, initial-scale=1.0">
77
<meta http-equiv="X-UA-Compatible" content="ie=edge">
8+
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline' 'unsafe-eval' https://jmblog.github.io/ https://cdn.jsdelivr.net/ https://api.stackexchange.com/; img-src *">
89

910
<title>StackOverflow</title>
1011

11-
<script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>
12+
<script src="https://cdn.jsdelivr.net/gh/google/code-prettify@master/loader/run_prettify.js"></script>
1213
<!-- <link rel="stylesheet" href="https://jmblog.github.io/color-themes-for-google-code-prettify/themes/tomorrow-night.min.css">-->
1314
<link rel="stylesheet" href="https://jmblog.github.io/color-themes-for-google-code-prettify/themes/github-v2.min.css">
1415

src/@types/bridge.d.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { api } from '../../electron/bridge';
22

33
declare global {
4-
// eslint-disable-next-line
54
interface Window {
65
Main: typeof api;
76
PR: { prettyPrint: () => void };

src/App.tsx

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { Center, ChakraProvider, Spinner } from '@chakra-ui/react';
2-
import { HashRouter as Router } from 'react-router-dom';
1+
import { Center, Spinner } from '@chakra-ui/react';
32
import { useEffect, useState } from 'react';
4-
import { theme } from './styles/theme';
53
import { Layout } from './components/layout/Layout';
64
import stackoverflow from './unitls/stackexchange-api';
5+
import { useNavigate } from 'react-router-dom';
76

87
export function App() {
8+
const navigate = useNavigate();
99
const [isAuthorized, setIsAuthorized] = useState(false);
1010

1111
useEffect(() => {
@@ -17,19 +17,29 @@ export function App() {
1717
// console.log(user, 2);
1818
});
1919
});
20+
21+
document.addEventListener('paste', (e) => {
22+
const clipboardData = e.clipboardData;
23+
const pastedText = clipboardData?.getData('text');
24+
25+
// FIXME on Question page when pastin new url hash is changing, but rerender missing
26+
if (pastedText && pastedText.startsWith('https://stackoverflow.com/questions/')) {
27+
const questionId = pastedText.replace('https://stackoverflow.com/questions/', '').split('/')[0];
28+
29+
navigate(`/questions/${questionId}`, { replace: true });
30+
}
31+
});
2032
}, []);
2133

2234
return (
23-
<Router>
24-
<ChakraProvider theme={theme}>
25-
{isAuthorized ? (
26-
<Layout />
27-
) : (
28-
<Center h="100vh">
29-
<Spinner />
30-
</Center>
31-
)}
32-
</ChakraProvider>
33-
</Router>
35+
<>
36+
{isAuthorized ? (
37+
<Layout />
38+
) : (
39+
<Center h="100vh">
40+
<Spinner />
41+
</Center>
42+
)}
43+
</>
3444
);
3545
}

src/components/comments/CommentForm.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export function CommentForm({ olderCommentsCount }: Props) {
2121
<Box flexBasis="40px" flexShrink={0}>
2222
<Image src={UserPlaceholder} boxSize="24px" objectFit="cover" borderRadius="3px" />
2323
</Box>
24-
<Box flexGrow={1}>
24+
<Box w="100%">
2525
<Input size="xs" placeholder="Your comment..." />
2626
</Box>
2727
</HStack>

src/components/layout/BackButton.tsx

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,12 @@
11
import { Button, ButtonProps } from '@chakra-ui/react';
22
import { IoIosArrowBack } from 'react-icons/io';
3+
import { useNavigate } from 'react-router-dom';
34

45
export function BackButton(props: ButtonProps) {
6+
const navigate = useNavigate();
7+
58
return (
6-
<Button
7-
size="xs"
8-
variant="outline"
9-
pl="5px"
10-
leftIcon={<IoIosArrowBack />}
11-
iconSpacing="3px"
12-
onClick={() => window.history.back()}
13-
{...props}
14-
>
9+
<Button size="xs" variant="outline" pl="5px" leftIcon={<IoIosArrowBack/>} iconSpacing="3px" onClick={() => navigate(-1)} {...props}>
1510
Back
1611
</Button>
1712
);

src/components/layout/Layout.tsx

Lines changed: 48 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { Box, Center, Divider, Flex, Image, Stack, Text } from '@chakra-ui/react';
1+
import { Box, Center, DarkMode, Divider, Flex, Image, Stack, Text } from '@chakra-ui/react';
22
import Logo from '../../../assets/stackoverflow-logo.png';
33
import { NavItem } from './NavItem';
4-
import { Route, Switch } from 'react-router-dom';
4+
import { Route, Routes } from 'react-router-dom';
55
import { QuestionsPage } from '../../pages/QuestionsPage';
66
import { QuestionDetailsPage } from '../../pages/QuestionDetailsPage';
77
import { SearchBar } from './SearchBar';
@@ -10,13 +10,13 @@ import { SettingsPage } from '../../pages/SettingsPage';
1010
import { AiFillTags } from 'react-icons/ai';
1111
import { MyQuestionsPage } from '../../pages/MyQuestionsPage';
1212
import { UserMenuDropdown } from './UserMenuDropdown';
13-
import ScrollToTop from './ScrollToTop';
13+
import { ScrollToTop } from './ScrollToTop';
1414
import { SponsorWidget } from './SponsorWidget';
1515

1616
export function Layout() {
1717
return (
1818
<>
19-
<Center bgColor="gray.800" h="40px" css={{ '-webkit-app-region': 'drag' }}>
19+
<Center bgColor="gray.800" h="40px" css={{ WebkitAppRegion: 'drag' }}>
2020
<Box justifySelf="flex-start" flex={1} />
2121
<Box flex={1}>
2222
<SearchBar />
@@ -27,54 +27,56 @@ export function Layout() {
2727
</Center>
2828
<Flex h="calc(100vh - 40px)" alignItems={'stretch'}>
2929
<Stack bgColor="gray.700" color="white" flex={'0 0 200px'} overflow={'auto'} p="8px" justifyContent="space-between">
30-
<Box>
31-
<Image mt="8px" mb="16px" ml="10px" src={Logo} h="20px" />
32-
<Stack spacing={0}>
33-
<NavItem to="/">
34-
<RiEarthFill />
35-
<Text>Questions</Text>
36-
</NavItem>
37-
<NavItem to="/tags">
38-
<AiFillTags />
39-
<Text>Tags</Text>
40-
</NavItem>
41-
</Stack>
42-
<Box p="16px 8px">
43-
<Divider borderColor="gray.600" />
30+
<DarkMode>
31+
<Box>
32+
<Image mt="8px" mb="16px" ml="10px" src={Logo} h="20px" />
33+
<Stack spacing={0}>
34+
<NavItem to="/">
35+
<RiEarthFill />
36+
<Text>Questions</Text>
37+
</NavItem>
38+
<NavItem to="/tags">
39+
<AiFillTags />
40+
<Text>Tags</Text>
41+
</NavItem>
42+
</Stack>
43+
<Box p="16px 8px">
44+
<Divider borderColor="gray.600" />
45+
</Box>
46+
<Stack spacing={0}>
47+
<NavItem to="/my-bookmarks" count={4}>
48+
<Text>My bookmarks</Text>
49+
</NavItem>
50+
<NavItem to="/my-questions" count={1}>
51+
<Text>My questions</Text>
52+
</NavItem>
53+
<NavItem to="/my-answers" count={35}>
54+
<Text>My answers</Text>
55+
</NavItem>
56+
<NavItem to="/my-tags" count={18}>
57+
<Text>My tags</Text>
58+
</NavItem>
59+
</Stack>
4460
</Box>
45-
<Stack spacing={0}>
46-
<NavItem to="/my-questions">
47-
<Text>My questions</Text>
48-
</NavItem>
49-
<NavItem to="/my-answers">
50-
<Text>My answers</Text>
51-
</NavItem>
52-
<NavItem to="/my-inbox">
53-
<Text>My inbox</Text>
54-
</NavItem>
55-
<NavItem to="/my-tags">
56-
<Text>My tags</Text>
57-
</NavItem>
58-
</Stack>
59-
</Box>
6061

61-
<Box>
62-
<SponsorWidget mb="32px" />
62+
<Box>
63+
<SponsorWidget mb="32px" />
6364

64-
<NavItem to="/settings">
65-
<RiSettings3Fill />
66-
<Text>Settings</Text>
67-
</NavItem>
68-
</Box>
65+
<NavItem to="/settings">
66+
<RiSettings3Fill />
67+
<Text>Settings</Text>
68+
</NavItem>
69+
</Box>
70+
</DarkMode>
6971
</Stack>
7072
<Box overflow={'auto'} p="16px" w="100%" id="scrolling-container">
7173
<ScrollToTop />
72-
<Switch>
73-
<Route path="/" exact component={QuestionsPage} />
74-
<Route path="/questions/:id" component={QuestionDetailsPage} />
75-
<Route path="/settings" component={SettingsPage} />
76-
<Route path="/my-questions" component={MyQuestionsPage} />
77-
</Switch>
74+
<Routes>
75+
<Route path="/" element={<QuestionsPage />} />
76+
<Route path="/questions/:id" element={<QuestionDetailsPage />} />
77+
<Route path="/settings" element={<SettingsPage />} />
78+
<Route path="/my-questions" element={<MyQuestionsPage />} />
79+
</Routes>
7880
</Box>
7981
</Flex>
8082
</>

src/components/layout/NavItem.tsx

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,26 @@
1-
import { HStack } from '@chakra-ui/react';
2-
import { Link as RouterLink, useRouteMatch } from 'react-router-dom';
1+
import { Badge, HStack } from '@chakra-ui/react';
2+
import { NavLink as RouterLink } from 'react-router-dom';
33

44
type Props = {
55
to: string;
6+
count?: number;
67
children: any;
78
};
89

9-
export function NavItem({ children, to }: Props) {
10-
const routeMatch = useRouteMatch(to);
10+
export function NavItem({ children, count, to }: Props) {
11+
// const routeMatch = useRouteMatch(to);
1112
const hoverStyles = {
12-
color: routeMatch && routeMatch.isExact ? 'whiteAlpha.900' : 'whiteAlpha.800',
13+
color: 'whiteAlpha.800',
1314
bgColor: 'whiteAlpha.50'
1415
};
1516

17+
// style={({ isActive }) => ({ color: isActive ? 'green' : 'blue' })}
18+
1619
return (
1720
<RouterLink to={to}>
1821
<HStack
1922
userSelect={'none'}
20-
color={routeMatch && routeMatch.isExact ? 'whiteAlpha.900' : 'whiteAlpha.600'}
23+
color="whiteAlpha.600"
2124
borderRadius="5px"
2225
cursor="pointer"
2326
alignItems="center"
@@ -27,6 +30,7 @@ export function NavItem({ children, to }: Props) {
2730
spacing="6px"
2831
>
2932
{children}
33+
{count && <Badge display="block" style={{ marginLeft: 'auto' }}>{count}</Badge>}
3034
</HStack>
3135
</RouterLink>
3236
);

src/components/layout/ScrollToTop.tsx

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,20 @@
11
import { useEffect } from 'react';
2-
import { withRouter } from 'react-router-dom';
3-
import type { RouteComponentProps } from 'react-router';
42

5-
function ScrollToTop({ history }: RouteComponentProps) {
3+
export function ScrollToTop() {
4+
// const history = useTransition();
5+
66
useEffect(() => {
77
const scrollableEl = document.getElementById('scrolling-container');
88

9-
const unlisten = history.listen(() => {
10-
requestAnimationFrame(() => {
11-
scrollableEl!.scrollTo(0, 0);
12-
});
13-
});
9+
// const unlisten = history.listen(() => {
10+
// requestAnimationFrame(() => {
11+
// scrollableEl!.scrollTo(0, 0);
12+
// });
13+
// });
1414
return () => {
15-
unlisten();
15+
// unlisten();
1616
};
1717
}, []);
1818

1919
return null;
2020
}
21-
22-
export default withRouter(ScrollToTop);

0 commit comments

Comments
 (0)