Right Click to Navigate History #3547
5 changed files with 104 additions and 10 deletions
3
ui/component/buttonNavigation/index.js
Normal file
3
ui/component/buttonNavigation/index.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import ButtonNavigation from './view';
|
||||||
|
|
||||||
|
export default ButtonNavigation;
|
67
ui/component/buttonNavigation/view.jsx
Normal file
67
ui/component/buttonNavigation/view.jsx
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
// @flow
|
||||||
|
import React, { useState, useCallback } from 'react';
|
||||||
|
import * as ICONS from 'constants/icons';
|
||||||
|
import Button from 'component/button';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
isBackward: boolean,
|
||||||
|
history: {
|
||||||
|
entries: { key: string, title: string }[],
|
||||||
|
go: number => void,
|
||||||
|
goBack: () => void,
|
||||||
|
goForward: () => void,
|
||||||
|
index: number,
|
||||||
|
length: number,
|
||||||
|
location: { pathname: string },
|
||||||
|
push: string => void,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const ButtonNavigation = (props: Props) => {
|
||||||
|
const { isBackward, history } = props;
|
||||||
|
const [showHistory, setShowHistory] = useState(false);
|
||||||
|
|
||||||
|
const makeItem = useCallback(
|
||||||
|
(entry, index) => {
|
||||||
|
const goArg = index - history.index;
|
||||||
|
console.log(`index: ${index}, currentIndex: ${history.index}, goArg: ${goArg}, title: ${entry.title}`);
|
||||||
|
return (
|
||||||
|
<li
|
||||||
|
key={entry.key}
|
||||||
|
onClick={() => {
|
||||||
|
setShowHistory(!showHistory);
|
||||||
|
history.go(goArg);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{entry.title}
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[history, showHistory]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Button
|
||||||
|
className="header__navigation-item header__navigation-item--back"
|
||||||
|
description={__('Navigate back')}
|
||||||
|
onClick={() => history.goBack()}
|
||||||
|
onContextMenu={e => {
|
||||||
|
setShowHistory(!showHistory);
|
||||||
|
// the following three lines prevent the regular context menu (right click menu) from appearing
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
return false; // returning false disables the regular context menu
|
||||||
|
}}
|
||||||
|
icon={isBackward ? ICONS.ARROW_LEFT : ICONS.ARROW_RIGHT}
|
||||||
|
iconSize={18}
|
||||||
|
/>
|
||||||
|
{showHistory && (
|
||||||
|
<ul className={'header__navigaiton-dropdown'} style={{ position: 'absolute' }}>
|
||||||
|
{history.entries.slice(1, history.length).map(makeItem)}
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default ButtonNavigation;
|
|
@ -11,6 +11,7 @@ import WunderBar from 'component/wunderbar';
|
||||||
import Icon from 'component/common/icon';
|
import Icon from 'component/common/icon';
|
||||||
import { Menu, MenuList, MenuButton, MenuItem } from '@reach/menu-button';
|
import { Menu, MenuList, MenuButton, MenuItem } from '@reach/menu-button';
|
||||||
import Tooltip from 'component/common/tooltip';
|
import Tooltip from 'component/common/tooltip';
|
||||||
|
import ButtonNavigation from 'component/buttonNavigation';
|
||||||
// @if TARGET='app'
|
// @if TARGET='app'
|
||||||
import { IS_MAC } from 'component/app/view';
|
import { IS_MAC } from 'component/app/view';
|
||||||
// @endif
|
// @endif
|
||||||
|
@ -18,7 +19,15 @@ import { IS_MAC } from 'component/app/view';
|
||||||
type Props = {
|
type Props = {
|
||||||
balance: string,
|
balance: string,
|
||||||
roundedBalance: number,
|
roundedBalance: number,
|
||||||
history: { push: string => void, goBack: () => void, goForward: () => void, location: { pathname: string } },
|
history: {
|
||||||
|
entities: {}[],
|
||||||
|
goBack: () => void,
|
||||||
|
goForward: () => void,
|
||||||
|
index: number,
|
||||||
|
length: number,
|
||||||
|
location: { pathname: string },
|
||||||
|
push: string => void,
|
||||||
|
},
|
||||||
currentTheme: string,
|
currentTheme: string,
|
||||||
automaticDarkModeEnabled: boolean,
|
automaticDarkModeEnabled: boolean,
|
||||||
setClientSetting: (string, boolean | string) => void,
|
setClientSetting: (string, boolean | string) => void,
|
||||||
|
@ -105,13 +114,7 @@ const Header = (props: Props) => {
|
||||||
{/* @if TARGET='app' */}
|
{/* @if TARGET='app' */}
|
||||||
{!authHeader && (
|
{!authHeader && (
|
||||||
<div className="header__navigation-arrows">
|
<div className="header__navigation-arrows">
|
||||||
<Button
|
<ButtonNavigation isBackward history={history} />
|
||||||
className="header__navigation-item header__navigation-item--back"
|
|
||||||
description={__('Navigate back')}
|
|
||||||
onClick={() => history.goBack()}
|
|
||||||
icon={ICONS.ARROW_LEFT}
|
|
||||||
iconSize={18}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
className="header__navigation-item header__navigation-item--forward"
|
className="header__navigation-item header__navigation-item--forward"
|
||||||
|
|
|
@ -147,3 +147,17 @@
|
||||||
.header__navigation-item--balance {
|
.header__navigation-item--balance {
|
||||||
margin: 0 var(--spacing-medium);
|
margin: 0 var(--spacing-medium);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.header__navigaiton-dropdown {
|
||||||
|
list-style-type: none;
|
||||||
|
background-color: var(--color-header-background);
|
||||||
|
|
||||||
|
li {
|
||||||
|
padding: 2px 5px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: var(--color-menu-background--active);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
11
ui/store.js
11
ui/store.js
|
@ -7,7 +7,7 @@ import { createFilter, createBlacklistFilter } from 'redux-persist-transform-fil
|
||||||
import localForage from 'localforage';
|
import localForage from 'localforage';
|
||||||
import { createStore, applyMiddleware, compose } from 'redux';
|
import { createStore, applyMiddleware, compose } from 'redux';
|
||||||
import thunk from 'redux-thunk';
|
import thunk from 'redux-thunk';
|
||||||
import { createHashHistory, createBrowserHistory } from 'history';
|
import { createMemoryHistory, createBrowserHistory } from 'history';
|
||||||
import { routerMiddleware } from 'connected-react-router';
|
import { routerMiddleware } from 'connected-react-router';
|
||||||
import createRootReducer from './reducers';
|
import createRootReducer from './reducers';
|
||||||
import { buildSharedStateMiddleware, ACTIONS as LBRY_REDUX_ACTIONS } from 'lbry-redux';
|
import { buildSharedStateMiddleware, ACTIONS as LBRY_REDUX_ACTIONS } from 'lbry-redux';
|
||||||
|
@ -96,12 +96,19 @@ const persistOptions = {
|
||||||
|
|
||||||
let history;
|
let history;
|
||||||
// @if TARGET='app'
|
// @if TARGET='app'
|
||||||
history = createHashHistory();
|
history = createMemoryHistory();
|
||||||
// @endif
|
// @endif
|
||||||
// @if TARGET='web'
|
// @if TARGET='web'
|
||||||
history = createBrowserHistory();
|
history = createBrowserHistory();
|
||||||
// @endif
|
// @endif
|
||||||
|
|
||||||
|
history.listen((l, a) => {
|
||||||
|
console.log('document.title: ', document.title);
|
||||||
|
console.log('history: ', history);
|
||||||
|
document.oncontextmenu = () => false;
|
||||||
|
l.title = document.title;
|
||||||
createMemoryHistory gives us an array of entries so that we can reference the history stack. Excerpt from history/docs/GettingStarted
createMemoryHistory gives us an array of entries so that we can reference the history stack.
*Excerpt from [history/docs/GettingStarted](https://github.com/ReactTraining/history/blob/master/docs/GettingStarted.md)*
> Additionally, createMemoryHistory provides history.index and history.entries properties that let you inspect the history stack.
|
|||||||
|
});
|
||||||
|
|
||||||
const triggerSharedStateActions = [
|
const triggerSharedStateActions = [
|
||||||
ACTIONS.CHANNEL_SUBSCRIBE,
|
ACTIONS.CHANNEL_SUBSCRIBE,
|
||||||
ACTIONS.CHANNEL_UNSUBSCRIBE,
|
ACTIONS.CHANNEL_UNSUBSCRIBE,
|
||||||
|
|
Loading…
Reference in a new issue
What is the difference between these two?