From 7c5022810dd7a50a8626bee04d0aea2d7be184c2 Mon Sep 17 00:00:00 2001 From: KaWaite <34051327+KaWaite@users.noreply.github.com> Date: Tue, 7 Nov 2023 09:14:21 +0900 Subject: [PATCH 1/4] deselect scene setting --- web/src/beta/features/Editor/useScene.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web/src/beta/features/Editor/useScene.ts b/web/src/beta/features/Editor/useScene.ts index bb5985ec38..eb421509c1 100644 --- a/web/src/beta/features/Editor/useScene.ts +++ b/web/src/beta/features/Editor/useScene.ts @@ -17,7 +17,8 @@ export default function ({ sceneId }: SceneProps) { [scene?.property, selectedSceneSetting], ); const handleSceneSettingSelect = useCallback( - (collection: string) => setSceneSetting(collection), + (collection: string) => + setSceneSetting(selected => (selected === collection ? undefined : collection)), [], ); From bdfba8f8779c4290fc0d5d9975a1fc97ee8d687c Mon Sep 17 00:00:00 2001 From: KaWaite <34051327+KaWaite@users.noreply.github.com> Date: Tue, 7 Nov 2023 10:18:10 +0900 Subject: [PATCH 2/4] auto collapse scene settings --- .../beta/components/SidePanelSectionField/index.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/web/src/beta/components/SidePanelSectionField/index.tsx b/web/src/beta/components/SidePanelSectionField/index.tsx index 8c5ee2821f..d0e99e56d0 100644 --- a/web/src/beta/components/SidePanelSectionField/index.tsx +++ b/web/src/beta/components/SidePanelSectionField/index.tsx @@ -1,4 +1,4 @@ -import { useState, ReactNode } from "react"; +import { useState, ReactNode, useEffect } from "react"; import { styled, useTheme } from "@reearth/services/theme"; @@ -8,10 +8,15 @@ import Text from "../Text"; const SidePanelSectionField: React.FC<{ className?: string; title?: string; + startCollapsed?: boolean; children?: ReactNode; -}> = ({ className, title, children }) => { +}> = ({ className, title, startCollapsed, children }) => { const theme = useTheme(); - const [opened, setOpened] = useState(true); + const [opened, setOpened] = useState(); + + useEffect(() => { + setOpened(!startCollapsed ?? true); + }, []); // eslint-disable-line react-hooks/exhaustive-deps return ( @@ -42,7 +47,7 @@ const Header = styled.div` height: 38px; `; -const ArrowIcon = styled(Icon)<{ opened: boolean }>` +const ArrowIcon = styled(Icon)<{ opened?: boolean }>` transform: rotate(${props => (props.opened ? 90 : 180)}deg); transition: all 0.2s; `; From c13a167eb97b2b0ee8d71c781414f3055b30b628 Mon Sep 17 00:00:00 2001 From: KaWaite <34051327+KaWaite@users.noreply.github.com> Date: Tue, 7 Nov 2023 13:03:23 +0900 Subject: [PATCH 3/4] map tab single select --- .../beta/features/Editor/Visualizer/hooks.ts | 13 +++++++++--- web/src/beta/features/Editor/index.tsx | 21 +++++++++++-------- .../beta/features/Editor/useLayerStyles.ts | 9 ++++---- web/src/beta/features/Editor/useScene.ts | 15 +++++++------ web/src/services/state/index.ts | 18 +++++++++++----- 5 files changed, 49 insertions(+), 27 deletions(-) diff --git a/web/src/beta/features/Editor/Visualizer/hooks.ts b/web/src/beta/features/Editor/Visualizer/hooks.ts index 07f9c32b71..ddabda7429 100644 --- a/web/src/beta/features/Editor/Visualizer/hooks.ts +++ b/web/src/beta/features/Editor/Visualizer/hooks.ts @@ -29,6 +29,8 @@ import { useZoomedLayerId, useSelectedLayer, useSelectedStoryPageId, + useSelectedLayerStyle, + useSelectedSceneSetting, } from "@reearth/services/state"; import { convertWidgets, processLayers, processProperty } from "./convert"; @@ -68,6 +70,8 @@ export default ({ const [zoomedLayerId, zoomToLayer] = useZoomedLayerId(); const [selectedLayer, setSelectedLayer] = useSelectedLayer(); + const [, setSelectedLayerStyle] = useSelectedLayerStyle(); + const [, setSelectedSceneSetting] = useSelectedSceneSetting(); const [selectedWidgetArea, setSelectedWidgetArea] = useSelectedWidgetArea(); const [isVisualizerReady, setIsVisualizerReady] = useIsVisualizerReady(); @@ -101,13 +105,16 @@ export default ({ feature?: ComputedFeature, layerSelectionReason?: LayerSelectionReason, ) => { - if (id === selectedLayer?.layerId && feature?.id === selectedLayer?.feature?.id) return; - + if (id === selectedLayer?.layerId || !feature) return; + if (id) { + setSelectedLayerStyle(undefined); + setSelectedSceneSetting(undefined); + } setSelectedLayer( id ? { layerId: id, layer: await layer?.(), feature, layerSelectionReason } : undefined, ); }, - [selectedLayer, setSelectedLayer], + [selectedLayer, setSelectedLayer, setSelectedLayerStyle, setSelectedSceneSetting], ); const handleDropLayer = useCallback( diff --git a/web/src/beta/features/Editor/index.tsx b/web/src/beta/features/Editor/index.tsx index 50cabecc39..12f5f3339c 100644 --- a/web/src/beta/features/Editor/index.tsx +++ b/web/src/beta/features/Editor/index.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect } from "react"; +import { useCallback } from "react"; import Resizable from "@reearth/beta/components/Resizable"; import useBottomPanel from "@reearth/beta/features/Editor/useBottomPanel"; @@ -92,26 +92,29 @@ const Editor: React.FC = ({ sceneId, projectId, workspaceId, tab }) => { const handleLayerStyleSelected = useCallback( (layerStyleId: string) => { handleLayerSelect(undefined); + handleSceneSettingSelect(undefined); handleLayerStyleSelect(layerStyleId); }, - [handleLayerStyleSelect, handleLayerSelect], + [handleLayerStyleSelect, handleSceneSettingSelect, handleLayerSelect], ); const handleLayerSelected = useCallback( (layerId: string) => { setSelectedLayerStyleId(undefined); + handleSceneSettingSelect(undefined); handleLayerSelect(layerId); }, - [handleLayerSelect, setSelectedLayerStyleId], + [handleLayerSelect, handleSceneSettingSelect, setSelectedLayerStyleId], ); - useEffect(() => { - if (selectedLayer) { + const handleSceneSettingSelected = useCallback( + (collection?: string) => { setSelectedLayerStyleId(undefined); - } else if (selectedLayerStyle) { handleLayerSelect(undefined); - } - }, [selectedLayer, selectedLayerStyle, setSelectedLayerStyleId, handleLayerSelect]); + handleSceneSettingSelect(collection); + }, + [handleLayerSelect, handleSceneSettingSelect, setSelectedLayerStyleId], + ); const { leftPanel } = useLeftPanel({ tab, @@ -130,7 +133,7 @@ const Editor: React.FC = ({ sceneId, projectId, workspaceId, tab }) => { onLayerSelect: handleLayerSelected, onLayerNameUpdate: handleLayerNameUpdate, onLayerVisibilityUpate: handleLayerVisibilityUpdate, - onSceneSettingSelect: handleSceneSettingSelect, + onSceneSettingSelect: handleSceneSettingSelected, onDataSourceManagerOpen: handleDataSourceManagerOpener, onFlyTo: handleFlyTo, }); diff --git a/web/src/beta/features/Editor/useLayerStyles.ts b/web/src/beta/features/Editor/useLayerStyles.ts index 4fae02485e..8e2ecda157 100644 --- a/web/src/beta/features/Editor/useLayerStyles.ts +++ b/web/src/beta/features/Editor/useLayerStyles.ts @@ -1,8 +1,9 @@ -import { useCallback, useMemo, useState } from "react"; +import { useCallback, useMemo } from "react"; import { LayerAppearanceTypes } from "@reearth/beta/lib/core/mantle"; import { useLayerStylesFetcher } from "@reearth/services/api"; import { useT } from "@reearth/services/i18n"; +import { useSelectedLayerStyle } from "@reearth/services/state"; type LayerStyleProps = { sceneId: string; @@ -27,7 +28,7 @@ export default function ({ sceneId }: LayerStyleProps) { const t = useT(); const { useAddLayerStyle, useGetLayerStylesQuery, useRemoveLayerStyle, useUpdateLayerStyle } = useLayerStylesFetcher(); - const [selectedLayerStyleId, setSelectedLayerStyleId] = useState(undefined); + const [selectedLayerStyleId, setSelectedLayerStyleId] = useSelectedLayerStyle(); const { layerStyles = [] } = useGetLayerStylesQuery({ sceneId }); const selectedLayerStyle = useMemo( @@ -38,7 +39,7 @@ export default function ({ sceneId }: LayerStyleProps) { const handleLayerStyleSelect = useCallback( (layerId: string) => setSelectedLayerStyleId(prevId => (prevId === layerId ? undefined : layerId)), - [], + [setSelectedLayerStyleId], ); const handleLayerStyleDelete = useCallback( @@ -55,7 +56,7 @@ export default function ({ sceneId }: LayerStyleProps) { ); } }, - [layerStyles, selectedLayerStyleId, useRemoveLayerStyle], + [layerStyles, selectedLayerStyleId, setSelectedLayerStyleId, useRemoveLayerStyle], ); const handleLayerStyleAdd = useCallback( diff --git a/web/src/beta/features/Editor/useScene.ts b/web/src/beta/features/Editor/useScene.ts index eb421509c1..d6e257f3c7 100644 --- a/web/src/beta/features/Editor/useScene.ts +++ b/web/src/beta/features/Editor/useScene.ts @@ -1,7 +1,8 @@ -import { useCallback, useMemo, useState } from "react"; +import { useCallback, useMemo } from "react"; import { useSceneFetcher } from "@reearth/services/api"; import { convert } from "@reearth/services/api/propertyApi/utils"; +import { useSelectedSceneSetting } from "@reearth/services/state"; type SceneProps = { sceneId?: string; @@ -9,7 +10,7 @@ type SceneProps = { export default function ({ sceneId }: SceneProps) { const { useSceneQuery } = useSceneFetcher(); - const [selectedSceneSetting, setSceneSetting] = useState(); + const [selectedSceneSetting, setSelectedSceneSetting] = useSelectedSceneSetting(); const { scene } = useSceneQuery({ sceneId }); const sceneSettings = useMemo( @@ -17,15 +18,17 @@ export default function ({ sceneId }: SceneProps) { [scene?.property, selectedSceneSetting], ); const handleSceneSettingSelect = useCallback( - (collection: string) => - setSceneSetting(selected => (selected === collection ? undefined : collection)), - [], + (collection?: string) => + setSelectedSceneSetting( + !collection || selectedSceneSetting === collection ? undefined : collection, + ), + [selectedSceneSetting, setSelectedSceneSetting], ); return { scene, selectedSceneSetting, - handleSceneSettingSelect, sceneSettings, + handleSceneSettingSelect, }; } diff --git a/web/src/services/state/index.ts b/web/src/services/state/index.ts index 359ed65df0..fc9af9f11e 100644 --- a/web/src/services/state/index.ts +++ b/web/src/services/state/index.ts @@ -81,16 +81,24 @@ export const useCurrentCamera = () => useAtom(currentCamera); const widgetAlignEditor = atom(undefined); export const useWidgetAlignEditorActivated = () => useAtom(widgetAlignEditor); -// Selected -const selectedWidget = atom(undefined); -export const useSelectedWidget = () => useAtom(selectedWidget); -const selectedWidgetArea = atom(undefined); -export const useSelectedWidgetArea = () => useAtom(selectedWidgetArea); +// Selected - map tab const selectedLayer = atom(undefined); export const useSelectedLayer = () => useAtom(selectedLayer); +const selectedLayerStyle = atom(undefined); +export const useSelectedLayerStyle = () => useAtom(selectedLayerStyle); +const selectedSceneSetting = atom(undefined); +export const useSelectedSceneSetting = () => useAtom(selectedSceneSetting); + +// Selected - story tab const selectedStoryPageId = atom(undefined); export const useSelectedStoryPageId = () => useAtom(selectedStoryPageId); +// Selected - widget tab +const selectedWidget = atom(undefined); +export const useSelectedWidget = () => useAtom(selectedWidget); +const selectedWidgetArea = atom(undefined); +export const useSelectedWidgetArea = () => useAtom(selectedWidgetArea); + // Misc const notification = atom(undefined); export const useNotification = () => useAtom(notification); From eea39cb52472320af334a205d84ee10cc26c9382 Mon Sep 17 00:00:00 2001 From: KaWaite <34051327+KaWaite@users.noreply.github.com> Date: Tue, 7 Nov 2023 13:15:54 +0900 Subject: [PATCH 4/4] default padding --- web/src/beta/lib/core/StoryPanel/Page/hooks.ts | 13 +++++++++++-- web/src/beta/lib/core/StoryPanel/Page/index.tsx | 8 ++++---- web/src/beta/lib/core/StoryPanel/constants.ts | 6 ++++-- web/src/beta/lib/core/StoryPanel/utils.ts | 9 +++++++-- 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/web/src/beta/lib/core/StoryPanel/Page/hooks.ts b/web/src/beta/lib/core/StoryPanel/Page/hooks.ts index 4e7f9be55c..d1690c3468 100644 --- a/web/src/beta/lib/core/StoryPanel/Page/hooks.ts +++ b/web/src/beta/lib/core/StoryPanel/Page/hooks.ts @@ -1,6 +1,10 @@ import { useCallback, useEffect, useMemo, useState } from "react"; -import { DEFAULT_STORY_PAGE_GAP, DEFAULT_STORY_PAGE_PADDING } from "../constants"; +import { + DEFAULT_STORY_PAGE_GAP, + DEFAULT_STORY_PAGE_PADDING, + MIN_STORY_PAGE_GAP_IN_EDITOR, +} from "../constants"; import { StoryPage } from "../types"; import { calculatePaddingValue } from "../utils"; @@ -50,7 +54,12 @@ export default ({ isEditable, ), }, - gap: property?.panel?.gap ?? DEFAULT_STORY_PAGE_GAP, + gap: { + value: + property?.panel?.gap?.value ?? isEditable + ? MIN_STORY_PAGE_GAP_IN_EDITOR + : DEFAULT_STORY_PAGE_GAP, + }, }), [property?.panel, isEditable], ); diff --git a/web/src/beta/lib/core/StoryPanel/Page/index.tsx b/web/src/beta/lib/core/StoryPanel/Page/index.tsx index ad6643d3fa..0143bddc26 100644 --- a/web/src/beta/lib/core/StoryPanel/Page/index.tsx +++ b/web/src/beta/lib/core/StoryPanel/Page/index.tsx @@ -170,9 +170,9 @@ const Wrapper = styled.div<{ padding: Spacing; gap?: number }>` color: ${({ theme }) => theme.content.weaker}; ${({ gap }) => gap && `gap: ${gap}px;`} - padding-top: ${({ padding }) => padding.top + "px"}; - padding-bottom: ${({ padding }) => padding.bottom + "px"}; - padding-left: ${({ padding }) => padding.left + "px"}; - padding-right: ${({ padding }) => padding.right + "px"}; + ${({ padding }) => `padding-top: ${padding.top}px;`} + ${({ padding }) => `padding-bottom: ${padding.bottom}px;`} + ${({ padding }) => `padding-left: ${padding.left}px;`} + ${({ padding }) => `padding-right: ${padding.right}px;`} box-sizing: border-box; `; diff --git a/web/src/beta/lib/core/StoryPanel/constants.ts b/web/src/beta/lib/core/StoryPanel/constants.ts index 6046c5f036..49438b71a2 100644 --- a/web/src/beta/lib/core/StoryPanel/constants.ts +++ b/web/src/beta/lib/core/StoryPanel/constants.ts @@ -6,8 +6,10 @@ export const STORY_PANEL_CONTENT_ELEMENT_ID = "story-page-content"; // Story Page export const DEFAULT_STORY_PAGE_DURATION = 2; -export const DEFAULT_STORY_PAGE_GAP = 2; -export const DEFAULT_STORY_PAGE_PADDING: Spacing = { top: 4, bottom: 4, left: 4, right: 4 }; +export const DEFAULT_STORY_PAGE_GAP = 20; +export const DEFAULT_STORY_PAGE_PADDING: Spacing = { top: 20, bottom: 20, left: 20, right: 20 }; +export const MIN_STORY_PAGE_GAP_IN_EDITOR = 4; +export const MIN_STORY_PAGE_PADDING_IN_EDITOR: Spacing = { top: 4, bottom: 4, left: 4, right: 4 }; // Story Block export const TITLE_BUILTIN_STORY_BLOCK_ID = "reearth/titleStoryBlock"; // pseudo storyblock. Uninstallable. Top of each page. diff --git a/web/src/beta/lib/core/StoryPanel/utils.ts b/web/src/beta/lib/core/StoryPanel/utils.ts index 3353ee7d40..05ff99f340 100644 --- a/web/src/beta/lib/core/StoryPanel/utils.ts +++ b/web/src/beta/lib/core/StoryPanel/utils.ts @@ -3,6 +3,8 @@ import type { Item } from "@reearth/services/api/propertyApi/utils"; import type { Spacing } from "../mantle"; +import { MIN_STORY_PAGE_PADDING_IN_EDITOR } from "./constants"; + export const getFieldValue = (items: Item[], fieldId: string, fieldGroup?: string) => { const d = items.find(i => i.schemaGroup === (fieldGroup ?? "default")) ?? items[0]; const isList = d && "items" in d; @@ -24,13 +26,16 @@ export const calculatePaddingValue = ( editorMode?: boolean, ) => { const calculateValue = (position: keyof Spacing, v?: number): { [key: string]: number } => { - if (!v) { + if (v === undefined) { return { [position]: editorMode ? defaultValue[position] : 0, }; } return { - [position]: editorMode && v < defaultValue[position] ? defaultValue[position] : v, + [position]: + editorMode && v < MIN_STORY_PAGE_PADDING_IN_EDITOR[position] + ? MIN_STORY_PAGE_PADDING_IN_EDITOR[position] + : v, }; };