Skip to content

Commit 89abbf9

Browse files
committed
Implement context menu for navigation
1 parent e5f2d8a commit 89abbf9

2 files changed

Lines changed: 176 additions & 63 deletions

File tree

src/AppHistory.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ import {
88

99
function useAppHistory(): object {
1010
const location: Location = useLocation();
11+
location["title"] = document.title;
12+
1113
const navigationType: NavigationType = useNavigationType();
1214

1315
const idx: RefObject<number> = useRef<number>(-1);
1416

15-
const [index, setIndex] = useState<number>(-1);
17+
const [index, setIndex] = useState<number>(0);
1618
const stack: RefObject<object[]> = useRef<object[]>([location]);
1719

1820
useEffect((): void => {
@@ -23,11 +25,9 @@ function useAppHistory(): object {
2325
setIndex(index + 1); // eslint-disable-line
2426
}
2527
if (navigationType === NavigationType.Pop) {
26-
if (idx.current > history.state?.idx) {
27-
setIndex(index - 1);
28-
}
29-
if (idx.current < history.state?.idx) {
30-
setIndex(index + 1);
28+
if(idx.current!==-1){
29+
const indexDelta: number = history.state?.idx - idx.current;
30+
setIndex(index + indexDelta);
3131
}
3232
idx.current = history.state?.idx;
3333
}

src/components/Header.tsx

Lines changed: 170 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
import { ChangeEvent, JSX, useEffect, useState } from "react";
1+
import {
2+
ChangeEvent,
3+
JSX,
4+
RefObject,
5+
useEffect,
6+
useRef,
7+
useState,
8+
} from "react";
29
import {
310
Link,
411
Location,
@@ -20,6 +27,36 @@ function Header({ menuOpen, menuOpenSetter }): JSX.Element {
2027
const urlQuery: string = new URLSearchParams(location.search).get("q") || "";
2128
const [query, setQuery] = useState<string>("");
2229

30+
const [historyMenu, setHistoryMenu] = useState<"back" | "next" | null>(null);
31+
const backMenu: RefObject<HTMLUListElement> = useRef<HTMLUListElement>(null);
32+
const nextMenu: RefObject<HTMLUListElement> = useRef<HTMLUListElement>(null);
33+
34+
useEffect(() => {
35+
if (!historyMenu) {
36+
return;
37+
}
38+
39+
function handleClick(ev: MouseEvent): void {
40+
if (
41+
historyMenu === "back" &&
42+
backMenu.current &&
43+
!backMenu.current.contains(ev.target as Node)
44+
) {
45+
setHistoryMenu(null);
46+
}
47+
if (
48+
historyMenu === "next" &&
49+
nextMenu.current &&
50+
!nextMenu.current.contains(ev.target as Node)
51+
) {
52+
setHistoryMenu(null);
53+
}
54+
}
55+
56+
document.addEventListener("mousedown", handleClick);
57+
return () => document.removeEventListener("mousedown", handleClick);
58+
}, [historyMenu]);
59+
2360
useEffect((): void => {
2461
setQuery(urlQuery);
2562
}, [urlQuery]);
@@ -101,62 +138,138 @@ function Header({ menuOpen, menuOpenSetter }): JSX.Element {
101138
</Link>
102139
</div>
103140
<div style={{ justifyContent: "center" }}>
104-
<NavLink
105-
className="hoverHeaderButtonFill"
106-
disabled={appHistory.getPrevious().length === 0}
107-
onClick={
108-
appHistory.getPrevious().length > 0
109-
? (): void => {
110-
navigate(-1);
111-
}
112-
: null
113-
}
114-
to={null}
115-
style={{
116-
backgroundColor: "rgba(45, 45, 45, 0.7)",
117-
borderRadius: "1.5rem",
118-
display: "inline-block",
119-
height: "40px",
120-
marginRight: "10px",
121-
textAlign: "center",
122-
verticalAlign: "middle",
123-
width: "40px",
124-
}}
125-
>
126-
<CustomSVG
127-
icon="arrow-left"
128-
viewBox="0 0 24 24"
129-
style={{ height: "18px", padding: "11px 0" }}
130-
/>
131-
</NavLink>
132-
<NavLink
133-
className="hoverHeaderButtonFill"
134-
disabled={appHistory.getNext().length === 0}
135-
onClick={
136-
appHistory.getNext().length > 0
137-
? (): void => {
138-
navigate(1);
139-
}
140-
: null
141-
}
142-
to={null}
143-
style={{
144-
backgroundColor: "rgba(45, 45, 45, 0.7)",
145-
borderRadius: "1.5rem",
146-
display: "inline-block",
147-
height: "40px",
148-
marginRight: "10px",
149-
textAlign: "center",
150-
verticalAlign: "middle",
151-
width: "40px",
152-
}}
153-
>
154-
<CustomSVG
155-
icon="arrow-right"
156-
viewBox="0 0 24 24"
157-
style={{ height: "18px", padding: "11px 0" }}
158-
/>
159-
</NavLink>
141+
<div style={{ display: "inline-block" }}>
142+
<div style={{ display: "inline-block" }}>
143+
<NavLink
144+
className="hoverHeaderButtonFill"
145+
disabled={appHistory.getPrevious().length === 0}
146+
onClick={
147+
appHistory.getPrevious().length > 0
148+
? (): void => {
149+
navigate(-1);
150+
}
151+
: null
152+
}
153+
onContextMenu={(ev: unknown): void => {
154+
ev.preventDefault();
155+
setHistoryMenu("back");
156+
}}
157+
to={null}
158+
style={{
159+
backgroundColor: "rgba(45, 45, 45, 0.7)",
160+
borderRadius: "1.5rem",
161+
display: "inline-block",
162+
height: "40px",
163+
marginRight: "10px",
164+
textAlign: "center",
165+
verticalAlign: "middle",
166+
width: "40px",
167+
}}
168+
>
169+
<CustomSVG
170+
icon="arrow-left"
171+
viewBox="0 0 24 24"
172+
style={{ height: "18px", padding: "11px 0" }}
173+
/>
174+
</NavLink>
175+
{historyMenu === "back" && appHistory.getPrevious().length ? (
176+
<ul
177+
ref={backMenu}
178+
style={{
179+
backgroundColor: "rgba(45, 45, 45, 0.9)",
180+
borderRadius: 6,
181+
listStyle: "none",
182+
margin: "0",
183+
maxHeight: "200px",
184+
overflowY: "auto",
185+
padding: 8,
186+
position: "absolute",
187+
top: "60px",
188+
}}
189+
>
190+
{appHistory.getPrevious().map((item: object, i: number) => (
191+
<li
192+
key={i}
193+
onClick={() => navigate(-(i + 1))}
194+
style={{
195+
backgroundColor: "rgb(63,63,70)",
196+
borderRadius: "6px",
197+
cursor: "pointer",
198+
padding: "6px",
199+
}}
200+
>
201+
{item["title"]}
202+
</li>
203+
))}
204+
</ul>
205+
) : null}
206+
</div>
207+
<div style={{ display: "inline-block" }}>
208+
<NavLink
209+
className="hoverHeaderButtonFill"
210+
disabled={appHistory.getNext().length === 0}
211+
onClick={
212+
appHistory.getNext().length > 0
213+
? (): void => {
214+
navigate(1);
215+
}
216+
: null
217+
}
218+
onContextMenu={(ev: unknown): void => {
219+
ev.preventDefault();
220+
setHistoryMenu("next");
221+
}}
222+
to={null}
223+
style={{
224+
backgroundColor: "rgba(45, 45, 45, 0.7)",
225+
borderRadius: "1.5rem",
226+
display: "inline-block",
227+
height: "40px",
228+
marginRight: "10px",
229+
textAlign: "center",
230+
verticalAlign: "middle",
231+
width: "40px",
232+
}}
233+
>
234+
<CustomSVG
235+
icon="arrow-right"
236+
viewBox="0 0 24 24"
237+
style={{ height: "18px", padding: "11px 0" }}
238+
/>
239+
</NavLink>
240+
{historyMenu === "next" && appHistory.getNext().length > 0 ? (
241+
<ul
242+
ref={nextMenu}
243+
style={{
244+
backgroundColor: "rgba(45, 45, 45, 0.9)",
245+
borderRadius: 6,
246+
listStyle: "none",
247+
margin: "0",
248+
maxHeight: "200px",
249+
overflowY: "auto",
250+
padding: 8,
251+
position: "absolute",
252+
top: "60px",
253+
}}
254+
>
255+
{appHistory.getNext().map((item: object, i: number) => (
256+
<li
257+
key={i}
258+
onClick={() => navigate(i + 1)}
259+
style={{
260+
backgroundColor: "rgb(63,63,70)",
261+
borderRadius: "6px",
262+
cursor: "pointer",
263+
padding: "6px",
264+
}}
265+
>
266+
{item["title"]}
267+
</li>
268+
))}
269+
</ul>
270+
) : null}
271+
</div>
272+
</div>
160273
<div style={{ display: "inline-block", height: "40px" }}>
161274
<form
162275
action="/search"

0 commit comments

Comments
 (0)