diff options
| author | Oskar Nyberg <oskar@mullvad.net> | 2022-11-04 10:54:07 +0100 |
|---|---|---|
| committer | Oskar Nyberg <oskar@mullvad.net> | 2022-11-07 10:46:07 +0100 |
| commit | 40bc4e6bbd51fd78ff67e376a5fbe921cd4c4964 (patch) | |
| tree | cc3833ddeefa03f5979883bb77464098fa9b32aa /gui/src | |
| parent | f5037f6fbc93148569210f18dfa24be4be1e0a6a (diff) | |
| download | mullvadvpn-40bc4e6bbd51fd78ff67e376a5fbe921cd4c4964.tar.xz mullvadvpn-40bc4e6bbd51fd78ff67e376a5fbe921cd4c4964.zip | |
Add view state to history location state
Diffstat (limited to 'gui/src')
| -rw-r--r-- | gui/src/main/index.ts | 7 | ||||
| -rw-r--r-- | gui/src/renderer/app.tsx | 13 | ||||
| -rw-r--r-- | gui/src/renderer/components/ExpiredAccountAddTime.tsx | 2 | ||||
| -rw-r--r-- | gui/src/renderer/components/NavigationBar.tsx | 27 | ||||
| -rw-r--r-- | gui/src/renderer/lib/history.tsx | 45 | ||||
| -rw-r--r-- | gui/src/renderer/redux/userinterface/actions.ts | 46 | ||||
| -rw-r--r-- | gui/src/renderer/redux/userinterface/reducers.ts | 17 | ||||
| -rw-r--r-- | gui/src/shared/ipc-schema.ts | 3 | ||||
| -rw-r--r-- | gui/src/shared/ipc-types.ts | 7 |
9 files changed, 41 insertions, 126 deletions
diff --git a/gui/src/main/index.ts b/gui/src/main/index.ts index e6336b1d18..4649cac8a7 100644 --- a/gui/src/main/index.ts +++ b/gui/src/main/index.ts @@ -11,7 +11,7 @@ import { DaemonEvent, DeviceEvent, ISettings, TunnelState } from '../shared/daem import { messages, relayLocations } from '../shared/gettext'; import { SYSTEM_PREFERRED_LOCALE_KEY } from '../shared/gui-settings-state'; import { ITranslations, MacOsScrollbarVisibility } from '../shared/ipc-schema'; -import { IChangelog, IHistoryObject, ScrollPositions } from '../shared/ipc-types'; +import { IChangelog, IHistoryObject } from '../shared/ipc-types'; import log, { ConsoleOutput, Logger } from '../shared/logging'; import { LogLevel } from '../shared/logging-types'; import { SystemNotification } from '../shared/notifications/notification'; @@ -105,7 +105,6 @@ class ApplicationMain private changelog?: IChangelog; private navigationHistory?: IHistoryObject; - private scrollPositions: ScrollPositions = {}; public run() { // Remove window animations to combat window flickering when opening window. Can be removed when @@ -699,7 +698,6 @@ class ApplicationMain changelog: this.changelog ?? [], forceShowChanges: SHOULD_SHOW_CHANGES, navigationHistory: this.navigationHistory, - scrollPositions: this.scrollPositions, })); IpcMainEventChannel.location.handleGet(() => this.daemonRpc.getLocation()); @@ -760,9 +758,6 @@ class ApplicationMain IpcMainEventChannel.navigation.handleSetHistory((history) => { this.navigationHistory = history; }); - IpcMainEventChannel.navigation.handleSetScrollPositions((scrollPositions) => { - this.scrollPositions = scrollPositions; - }); problemReport.registerIpcListeners(); this.userInterface!.registerIpcListeners(); diff --git a/gui/src/renderer/app.tsx b/gui/src/renderer/app.tsx index ca349b073b..80e969a920 100644 --- a/gui/src/renderer/app.tsx +++ b/gui/src/renderer/app.tsx @@ -25,12 +25,7 @@ import { import { messages, relayLocations } from '../shared/gettext'; import { IGuiSettingsState, SYSTEM_PREFERRED_LOCALE_KEY } from '../shared/gui-settings-state'; import { IRelayListPair } from '../shared/ipc-schema'; -import { - IChangelog, - ICurrentAppVersionInfo, - IHistoryObject, - ScrollPositions, -} from '../shared/ipc-types'; +import { IChangelog, ICurrentAppVersionInfo, IHistoryObject } from '../shared/ipc-types'; import log, { ConsoleOutput } from '../shared/logging'; import { LogLevel } from '../shared/logging-types'; import { Scheduler } from '../shared/scheduler'; @@ -252,8 +247,6 @@ export default class AppRenderer { void this.updateLocation(); - this.reduxActions.userInterface.setScrollPositions(initialState.scrollPositions); - if (initialState.navigationHistory) { // Set last action to POP to trigger automatic scrolling to saved coordinates. initialState.navigationHistory.lastAction = 'POP'; @@ -518,10 +511,6 @@ export default class AppRenderer { IpcRendererEventChannel.navigation.setHistory(history); } - public setScrollPositions(scrollPositions: ScrollPositions) { - IpcRendererEventChannel.navigation.setScrollPositions(scrollPositions); - } - private isLoggedIn(): boolean { return this.deviceState?.type === 'logged in'; } diff --git a/gui/src/renderer/components/ExpiredAccountAddTime.tsx b/gui/src/renderer/components/ExpiredAccountAddTime.tsx index 14a2de74c4..54d27f75d8 100644 --- a/gui/src/renderer/components/ExpiredAccountAddTime.tsx +++ b/gui/src/renderer/components/ExpiredAccountAddTime.tsx @@ -280,7 +280,7 @@ function useFinishedCallback() { accountSetupFinished(); } - history.reset(RoutePath.main, undefined, transitions.push); + history.reset(RoutePath.main, transitions.push); }, [isNewAccount, accountSetupFinished, history]); return callback; diff --git a/gui/src/renderer/components/NavigationBar.tsx b/gui/src/renderer/components/NavigationBar.tsx index 4c27665b65..317a9bd26e 100644 --- a/gui/src/renderer/components/NavigationBar.tsx +++ b/gui/src/renderer/components/NavigationBar.tsx @@ -3,11 +3,8 @@ import React, { useCallback, useContext, useEffect, useLayoutEffect, useRef } fr import { colors } from '../../config.json'; import { messages } from '../../shared/gettext'; import { useAppContext } from '../context'; -import useActions from '../lib/actionsHook'; import { useHistory } from '../lib/history'; import { useCombinedRefs } from '../lib/utilityHooks'; -import { useSelector } from '../redux/store'; -import userInterface from '../redux/userinterface/actions'; import CustomScrollbars, { CustomScrollbarsRef, IScrollEvent } from './CustomScrollbars'; import { BackActionContext } from './KeyboardNavigation'; import { @@ -92,41 +89,35 @@ export const NavigationScrollbars = React.forwardRef(function NavigationScrollba forwardedRef?: React.Ref<CustomScrollbarsRef>, ) { const history = useHistory(); + const { setNavigationHistory } = useAppContext(); const { onScroll } = useContext(NavigationScrollContext); - const { setScrollPositions } = useAppContext(); const ref = useRef<CustomScrollbarsRef>(); const combinedRefs = useCombinedRefs(forwardedRef, ref); - const { addScrollPosition, removeScrollPosition } = useActions(userInterface); - const scrollPositions = useSelector((state) => state.userInterface.scrollPosition); - useEffect(() => { - const path = history.location.pathname; const beforeunload = () => { if (ref.current) { - const scrollPosition = ref.current.getScrollPosition(); - setScrollPositions({ ...scrollPositions, [path]: scrollPosition }); + history.location.state.scrollPosition = ref.current.getScrollPosition(); + setNavigationHistory(history.asObject); } }; window.addEventListener('beforeunload', beforeunload); return () => window.removeEventListener('beforeunload', beforeunload); - }, [scrollPositions]); + }, []); useLayoutEffect(() => { - const path = history.location.pathname; - - const scrollPosition = scrollPositions[history.location.pathname]; - if (history.action === 'POP' && scrollPosition) { - ref.current?.scrollTo(...scrollPosition); - removeScrollPosition(path); + const location = history.location; + if (history.action === 'POP') { + ref.current?.scrollTo(...location.state.scrollPosition); } return () => { if (history.action === 'PUSH' && ref.current) { - addScrollPosition(path, ref.current.getScrollPosition()); + location.state.scrollPosition = ref.current.getScrollPosition(); + setNavigationHistory(history.asObject); } }; }, []); diff --git a/gui/src/renderer/lib/history.tsx b/gui/src/renderer/lib/history.tsx index 486093cca0..e74552f786 100644 --- a/gui/src/renderer/lib/history.tsx +++ b/gui/src/renderer/lib/history.tsx @@ -1,7 +1,7 @@ import { Action, History as OriginalHistory, Location, LocationDescriptorObject } from 'history'; import { useHistory as useReactRouterHistory } from 'react-router'; -import { IHistoryObject } from '../../shared/ipc-types'; +import { IHistoryObject, LocationState } from '../../shared/ipc-types'; import { GeneratedRoutePath, RoutePath } from './routes'; export interface ITransitionSpecification { @@ -39,25 +39,21 @@ export const transitions: ITransitionMap = { }, }; -type LocationDescriptor<S> = RoutePath | GeneratedRoutePath | LocationDescriptorObject<S>; +type LocationDescriptor = RoutePath | GeneratedRoutePath | LocationDescriptorObject<LocationState>; -type LocationListener<S = unknown> = ( - location: Location<S>, +type LocationListener = ( + location: Location<LocationState>, action: Action, transition: ITransitionSpecification, ) => void; -// It currently isn't possible to implement this correctly with support for a generic state. State -// can be added as a generic type (<S = unknown>) after this issue has been resolved: -// https://github.com/DefinitelyTyped/DefinitelyTyped/issues/49060 -type S = unknown; export default class History { - private listeners: LocationListener<S>[] = []; - private entries: Location<S>[]; + private listeners: LocationListener[] = []; + private entries: Location<LocationState>[]; private index = 0; private lastAction: Action = 'POP'; - public constructor(location: LocationDescriptor<S>, state?: S) { + public constructor(location: LocationDescriptor, state?: LocationState) { this.entries = [this.createLocation(location, state)]; } @@ -70,7 +66,7 @@ export default class History { return history; } - public get location(): Location<S> { + public get location(): Location<LocationState> { return this.entries[this.index]; } @@ -82,7 +78,7 @@ export default class History { return this.lastAction; } - public push = (nextLocation: LocationDescriptor<S>, nextState?: S) => { + public push = (nextLocation: LocationDescriptor, nextState?: LocationState) => { this.pushImpl(nextLocation, nextState); this.notify(transitions.push); }; @@ -93,7 +89,7 @@ export default class History { } }; - public show = (nextLocation: LocationDescriptor<S>, nextState?: S) => { + public show = (nextLocation: LocationDescriptor, nextState?: LocationState) => { this.pushImpl(nextLocation, nextState); this.notify(transitions.show); }; @@ -105,9 +101,9 @@ export default class History { }; public reset = ( - nextLocation: LocationDescriptor<S>, + nextLocation: LocationDescriptor, transition?: ITransitionSpecification, - nextState?: S, + nextState?: LocationState, ) => { const location = this.createLocation(nextLocation, nextState); this.lastAction = 'REPLACE'; @@ -117,7 +113,7 @@ export default class History { this.notify(transition ?? transitions.none); }; - public listen(callback: LocationListener<S>) { + public listen(callback: LocationListener) { this.listeners.push(callback); return () => (this.listeners = this.listeners.filter((listener) => listener !== callback)); } @@ -162,7 +158,7 @@ export default class History { throw Error('Not implemented'); } - private pushImpl(nextLocation: LocationDescriptor<S>, nextState?: S) { + private pushImpl(nextLocation: LocationDescriptor, nextState?: LocationState) { const location = this.createLocation(nextLocation, nextState); this.lastAction = 'PUSH'; this.index += 1; @@ -185,7 +181,10 @@ export default class History { this.listeners.forEach((listener) => listener(this.location, this.action, transition)); } - private createLocation(location: LocationDescriptor<S>, state?: S): Location<S> { + private createLocation( + location: LocationDescriptor, + state?: LocationState, + ): Location<LocationState> { if (typeof location === 'string') { return this.createLocationFromString(location, state); } else if ('routePath' in location) { @@ -195,18 +194,18 @@ export default class History { pathname: location.pathname ?? this.location.pathname, search: location.search ?? '', hash: location.hash ?? '', - state: location.state, + state: location.state ?? { scrollPosition: [0, 0], expandedSections: [] }, key: location.key ?? this.getRandomKey(), }; } } - private createLocationFromString(path: string, state?: S): Location<S> { + private createLocationFromString(path: string, state?: LocationState): Location<LocationState> { return { pathname: path, search: '', hash: '', - state, + state: state ?? { scrollPosition: [0, 0], expandedSections: [] }, key: this.getRandomKey(), }; } @@ -217,5 +216,5 @@ export default class History { } export function useHistory(): History { - return useReactRouterHistory() as History; + return useReactRouterHistory<LocationState>() as History; } diff --git a/gui/src/renderer/redux/userinterface/actions.ts b/gui/src/renderer/redux/userinterface/actions.ts index 19ae7380bc..46da6bdc3d 100644 --- a/gui/src/renderer/redux/userinterface/actions.ts +++ b/gui/src/renderer/redux/userinterface/actions.ts @@ -1,5 +1,5 @@ import { MacOsScrollbarVisibility } from '../../../shared/ipc-schema'; -import { IChangelog, ScrollPositions } from '../../../shared/ipc-types'; +import { IChangelog } from '../../../shared/ipc-types'; export interface IUpdateLocaleAction { type: 'UPDATE_LOCALE'; @@ -20,22 +20,6 @@ export interface ISetWindowFocusedAction { focused: boolean; } -export interface ISetScrollPositions { - type: 'SET_SCROLL_POSITIONS'; - scrollPositions: ScrollPositions; -} - -export interface IAddScrollPosition { - type: 'ADD_SCROLL_POSITION'; - path: string; - scrollPosition: [number, number]; -} - -export interface IRemoveScrollPosition { - type: 'REMOVE_SCROLL_POSITION'; - path: string; -} - export interface ISetMacOsScrollbarVisibility { type: 'SET_MACOS_SCROLLBAR_VISIBILITY'; visibility: MacOsScrollbarVisibility; @@ -66,9 +50,6 @@ export type UserInterfaceAction = | IUpdateWindowArrowPositionAction | IUpdateConnectionInfoOpenAction | ISetWindowFocusedAction - | ISetScrollPositions - | IAddScrollPosition - | IRemoveScrollPosition | ISetMacOsScrollbarVisibility | ISetConnectedToDaemon | ISetChangelog @@ -102,28 +83,6 @@ function setWindowFocused(focused: boolean): ISetWindowFocusedAction { }; } -function setScrollPositions(scrollPositions: ScrollPositions): ISetScrollPositions { - return { - type: 'SET_SCROLL_POSITIONS', - scrollPositions, - }; -} - -function addScrollPosition(path: string, scrollPosition: [number, number]): IAddScrollPosition { - return { - type: 'ADD_SCROLL_POSITION', - path, - scrollPosition, - }; -} - -function removeScrollPosition(path: string): IRemoveScrollPosition { - return { - type: 'REMOVE_SCROLL_POSITION', - path, - }; -} - function setMacOsScrollbarVisibility( visibility: MacOsScrollbarVisibility, ): ISetMacOsScrollbarVisibility { @@ -166,9 +125,6 @@ export default { updateWindowArrowPosition, toggleConnectionPanel, setWindowFocused, - setScrollPositions, - addScrollPosition, - removeScrollPosition, setMacOsScrollbarVisibility, setConnectedToDaemon, setChangelog, diff --git a/gui/src/renderer/redux/userinterface/reducers.ts b/gui/src/renderer/redux/userinterface/reducers.ts index 2ab684b377..96d8bc03e6 100644 --- a/gui/src/renderer/redux/userinterface/reducers.ts +++ b/gui/src/renderer/redux/userinterface/reducers.ts @@ -7,7 +7,6 @@ export interface IUserInterfaceReduxState { arrowPosition?: number; connectionPanelVisible: boolean; windowFocused: boolean; - scrollPosition: Record<string, [number, number]>; macOsScrollbarVisibility?: MacOsScrollbarVisibility; connectedToDaemon: boolean; changelog: IChangelog; @@ -19,7 +18,6 @@ const initialState: IUserInterfaceReduxState = { locale: 'en', connectionPanelVisible: false, windowFocused: false, - scrollPosition: {}, macOsScrollbarVisibility: undefined, connectedToDaemon: false, changelog: [], @@ -44,21 +42,6 @@ export default function ( case 'SET_WINDOW_FOCUSED': return { ...state, windowFocused: action.focused }; - case 'SET_SCROLL_POSITIONS': - return { ...state, scrollPosition: action.scrollPositions }; - - case 'ADD_SCROLL_POSITION': - return { - ...state, - scrollPosition: { ...state.scrollPosition, [action.path]: action.scrollPosition }, - }; - - case 'REMOVE_SCROLL_POSITION': { - const scrollPosition = { ...state.scrollPosition }; - delete scrollPosition[action.path]; - return { ...state, scrollPosition }; - } - case 'SET_MACOS_SCROLLBAR_VISIBILITY': return { ...state, macOsScrollbarVisibility: action.visibility }; diff --git a/gui/src/shared/ipc-schema.ts b/gui/src/shared/ipc-schema.ts index 85c7f2cabc..210e85e007 100644 --- a/gui/src/shared/ipc-schema.ts +++ b/gui/src/shared/ipc-schema.ts @@ -34,7 +34,6 @@ import { ICurrentAppVersionInfo, IHistoryObject, IWindowShapeParameters, - ScrollPositions, } from './ipc-types'; export interface ITranslations { @@ -76,7 +75,6 @@ export interface IAppStateSnapshot { changelog: IChangelog; forceShowChanges: boolean; navigationHistory?: IHistoryObject; - scrollPositions: ScrollPositions; } // The different types of requests are: @@ -130,7 +128,6 @@ export const ipcSchema = { navigation: { reset: notifyRenderer<void>(), setHistory: send<IHistoryObject>(), - setScrollPositions: send<ScrollPositions>(), }, daemon: { isPerformingPostUpgrade: notifyRenderer<boolean>(), diff --git a/gui/src/shared/ipc-types.ts b/gui/src/shared/ipc-types.ts index 2b42f42b0e..4d2a35357f 100644 --- a/gui/src/shared/ipc-types.ts +++ b/gui/src/shared/ipc-types.ts @@ -13,8 +13,13 @@ export interface IWindowShapeParameters { export type IChangelog = Array<string>; +export interface LocationState { + scrollPosition: [number, number]; + expandedSections: number[]; +} + export interface IHistoryObject { - entries: Location<unknown>[]; + entries: Location<LocationState>[]; index: number; lastAction: Action; } |
