Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(web): remember the editor settings #825

Merged
merged 18 commits into from
Dec 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
57 changes: 47 additions & 10 deletions web/src/beta/components/Resizable/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import React, { useCallback, useState, useEffect, useMemo } from "react";

import { setLocalStorageData } from "@reearth/beta/utils/localstorage";

export type Direction = "vertical" | "horizontal";
export type Gutter = "start" | "end";

const getPositionFromEvent = (e: React.MouseEvent | React.TouchEvent) => {
const { nativeEvent } = e;
if (nativeEvent instanceof MouseEvent) {
const { clientX: x, clientY: y, which } = nativeEvent;

// When user click with right button the resize is stuck in resizing mode until users clicks again, dont continue if right click is used.
// https://github.com/bokuweb/re-resizable/blob/06dd269f835a201b03b4f62f37533784d855fdd2/src/index.tsx#L611
if (which === 3) return;

return { x, y };
Expand All @@ -30,7 +29,7 @@ const getDelta = (direction: Direction, deltaX: number, deltaY: number) =>
const getSize = (size: number, delta: number, minSize?: number, maxSize?: number) => {
let newSize = size + delta;
if (minSize !== undefined && newSize < minSize) newSize = minSize;
if (maxSize !== undefined && newSize > maxSize) newSize = maxSize; // New check for maxSize
if (maxSize !== undefined && newSize > maxSize) newSize = maxSize;
return newSize;
};

Expand All @@ -40,16 +39,38 @@ export default (
initialSize: number,
minSize: number,
maxSize?: number,
localStorageKey?: string,
) => {
const [startingSize, setStartingSize] = useState(initialSize);
const getLocalStorageParsedState = useCallback((localStorageKey?: string) => {
const savedState = localStorageKey && localStorage.getItem(localStorageKey);
return savedState ? JSON.parse(savedState) : null;
}, []);

const [startingSize, setStartingSize] = useState(initialSize);
const [isResizing, setIsResizing] = useState(false);
const [size, setSize] = useState(initialSize);
const [position, setPosition] = useState({ x: 0, y: 0 });
const [minimized, setMinimized] = useState(false);

const [difference, setDifference] = useState(0);

useEffect(() => {
const setSizeBasedOnTab = () => {
if (localStorageKey) {
const parsedState = getLocalStorageParsedState(localStorageKey);
const storedSize = parsedState?.size;

if (storedSize !== undefined) {
setSize(storedSize);
setMinimized(parsedState.minimized);
} else {
setSize(initialSize);
setMinimized(false);
}
}
};
setSizeBasedOnTab();
}, [localStorageKey, getLocalStorageParsedState, initialSize]);

const onResizeStart = useCallback(
(e: React.MouseEvent<HTMLDivElement> | React.TouchEvent<HTMLDivElement>) => {
const position = getPositionFromEvent(e);
Expand Down Expand Up @@ -80,6 +101,7 @@ export default (
if (!minimized && startingSize + newDiff <= minSize / 2) {
setMinimized(true);
}

setPosition({ x, y });
},
[
Expand All @@ -104,7 +126,12 @@ export default (
setPosition({ x: 0, y: 0 });
setStartingSize(size);
setDifference(0);
}, [isResizing, size]);
const storedData = {
size,
minimized,
};
localStorageKey && setLocalStorageData(localStorageKey, storedData);
}, [isResizing, localStorageKey, minimized, size]);

const bindEventListeners = useCallback(() => {
if (typeof window === "undefined") return;
Expand Down Expand Up @@ -144,7 +171,17 @@ export default (
const handleResetSize = useCallback(() => {
setMinimized(false);
setSize(initialSize);
}, [initialSize]);

return { size, gutterProps, minimized, handleResetSize };
localStorageKey &&
setLocalStorageData(localStorageKey, {
size: initialSize,
minimized: false,
});
}, [initialSize, localStorageKey]);

return {
size: size || initialSize,
gutterProps,
minimized,
handleResetSize,
};
};
6 changes: 5 additions & 1 deletion web/src/beta/components/Resizable/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type Props = {
initialSize: number;
minSize: number;
maxSize?: number;
localStorageKey?: string;
};

const Resizable: React.FC<Props> = ({
Expand All @@ -21,13 +22,15 @@ const Resizable: React.FC<Props> = ({
maxSize,
initialSize,
children,
localStorageKey,
}) => {
const { size, gutterProps, minimized, handleResetSize } = useHooks(
direction,
gutter,
initialSize,
minSize,
maxSize,
localStorageKey,
);

const showTopGutter = direction === "horizontal" && gutter === "start";
Expand Down Expand Up @@ -115,5 +118,6 @@ const MinimizedWrapper = styled.div<Pick<Props, "direction">>`
:hover {
background: ${({ theme }) => theme.bg[1]};
}
`;
}`;

export default Resizable;
12 changes: 8 additions & 4 deletions web/src/beta/components/SidePanelSectionField/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@ const SidePanelSectionField: React.FC<{
startCollapsed?: boolean;
gap?: number;
children?: ReactNode;
}> = ({ className, title, startCollapsed, gap, children }) => {
storageKey?: string;
}> = ({ className, title, startCollapsed, gap, children, storageKey }) => {
const theme = useTheme();
const [opened, setOpened] = useState<boolean>();
const [opened, setOpened] = useState<boolean>(() => {
const storedValue = localStorage.getItem(storageKey || "");
return storedValue ? JSON.parse(storedValue) : !startCollapsed ?? true;
});

useEffect(() => {
setOpened(!startCollapsed ?? true);
}, []); // eslint-disable-line react-hooks/exhaustive-deps
localStorage.setItem(storageKey || "", JSON.stringify(opened));
}, [opened, storageKey]);

return (
<Field className={className}>
Expand Down
2 changes: 1 addition & 1 deletion web/src/beta/features/Editor/Settings/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const Settings: React.FC<Props> = ({
return (
<Wrapper>
{tab == "story" && (
<SidePanelSectionField title={t("Layers")}>
<SidePanelSectionField title={t("Layers")} storageKey="storyLayer">
{layers && layers?.length > 0 && (
<LayerWrapper>
<AllLayers>
Expand Down
9 changes: 6 additions & 3 deletions web/src/beta/features/Editor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,8 @@ const Editor: React.FC<Props> = ({ sceneId, projectId, workspaceId, tab }) => {
direction="vertical"
gutter="end"
initialSize={metrics.propertyMenuWidth}
minSize={metrics.propertyMenuMinWidth}>
minSize={metrics.propertyMenuMinWidth}
localStorageKey={`${tab}LeftPanel`}>
{leftPanel}
</Resizable>
)}
Expand Down Expand Up @@ -224,7 +225,8 @@ const Editor: React.FC<Props> = ({ sceneId, projectId, workspaceId, tab }) => {
gutter="start"
initialSize={metrics.bottomPanelMinHeight}
minSize={metrics.bottomPanelMinHeight}
maxSize={metrics.bottomPanelMaxHeight}>
maxSize={metrics.bottomPanelMaxHeight}
localStorageKey="bottomPanel">
{bottomPanel}
</Resizable>
)}
Expand All @@ -235,7 +237,8 @@ const Editor: React.FC<Props> = ({ sceneId, projectId, workspaceId, tab }) => {
direction="vertical"
gutter="start"
initialSize={metrics.propertyMenuWidth}
minSize={metrics.propertyMenuMinWidth}>
minSize={metrics.propertyMenuMinWidth}
localStorageKey={`${tab}RightPanel`}>
{rightPanel}
</Resizable>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ const GroupSectionField: React.FC<GroupSectionFieldProps> = ({

return (
<>
<StyledSidePanelSectionField title={t("Scene")} startCollapsed gap={0}>
<StyledSidePanelSectionField title={t("Scene")} startCollapsed gap={0} storageKey="scene">
{[...new Set(scene?.property?.schema?.groups.map(({ collection }) => collection))].map(
(collection, index) =>
collection && (
Expand All @@ -77,7 +77,7 @@ const GroupSectionField: React.FC<GroupSectionFieldProps> = ({
),
)}
</StyledSidePanelSectionField>
<StyledSidePanelSectionField title={t("Layers")}>
<StyledSidePanelSectionField title={t("Layers")} storageKey="layer">
<Layers
layers={layers}
selectedLayerId={selectedLayerId}
Expand Down
5 changes: 5 additions & 0 deletions web/src/beta/utils/localstorage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const setLocalStorageData = (localStorageKey: string, storedData: any) => {
if (!localStorageKey) return;

localStorage.setItem(localStorageKey, JSON.stringify(storedData));
};