activities: use sessionStorage for selected tab

The useLocalStorage hook synchronizes state between windows. In the
case of the activities tabs, we don't want this state synchronized,
otherwise changing a tab in one window would change the tab in all
open windows.

Instead, we can use sessionStorage so that the state persists when
refreshing or duplicating a browser tab. Local storage is still used
as the default value so that any new window that is opened will use
the last selected state.

Issue: https://github.com/pybricks/support/issues/807
This commit is contained in:
David Lechner
2022-12-06 15:38:58 -06:00
committed by David Lechner
parent bb303ae4d3
commit ee850dec71
4 changed files with 30 additions and 3 deletions
+1
View File
@@ -11,6 +11,7 @@ afterEach(() => {
cleanup();
jest.resetAllMocks();
localStorage.clear();
sessionStorage.clear();
});
describe('Activities', () => {
+26 -3
View File
@@ -1,7 +1,8 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2022 The Pybricks Authors
import { useLocalStorage } from 'usehooks-ts';
import { useEffect } from 'react';
import { useEffectOnce, useLocalStorage, useSessionStorage } from 'usehooks-ts';
/** Indicates the selected activity. */
export enum Activity {
@@ -17,6 +18,28 @@ export enum Activity {
* React hook for getting and setting the selected activity in the activity panel.
* @returns a tuple of the current state and the setter function (like useState()).
*/
export function useActivitiesSelectedActivity() {
return useLocalStorage('activities.selectedActivity', Activity.Explorer);
export function useActivitiesSelectedActivity(): ReturnType<
typeof useSessionStorage<Activity>
> {
// If multiple windows are open, this allows each window to control the
// current activity independently. The local storage uses a "last one wins"
// approach to deciding which state to restore when a window is opened.
const [lastSelectedActivity, setLastSelectedActivity] = useLocalStorage(
'activities.selectedActivity',
Activity.Explorer,
);
const [selectedActivity, setSelectedActivity] = useSessionStorage(
'activities.selectedActivity',
lastSelectedActivity,
);
// Force writing to session storage since default value is not constant.
useEffectOnce(() => setSelectedActivity(selectedActivity));
useEffect(() => {
setLastSelectedActivity(selectedActivity);
}, [selectedActivity]);
return [selectedActivity, setSelectedActivity];
}