Skip to content

Commit

Permalink
refactor(extension): storytelling layer updates (#294)
Browse files Browse the repository at this point in the history
Co-authored-by: keiya sasaki <[email protected]>
  • Loading branch information
airslice and keiya01 authored Mar 28, 2024
1 parent 2dc20e9 commit 125ed0d
Show file tree
Hide file tree
Showing 31 changed files with 500 additions and 860 deletions.
40 changes: 29 additions & 11 deletions extension/src/prototypes/ui-components/LayerListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import {
} from "react";

import { XYZ } from "../../shared/reearth/types";
import { LayerModelOverrides } from "../layers";
import { useForkEventHandler } from "../react-helpers";
import { STORY_LAYER } from "../view-layers";

import { EntityTitleButton, type EntityTitleButtonProps } from "./EntityTitleButton";
import { TrashSmallIcon } from "./icons/TrashSmallIcon";
Expand All @@ -17,7 +19,9 @@ import { VisibilityOnSmallIcon } from "./icons/VisibilityOnSmallIcon";

import { AddressIcon } from "./index";

const StyledEntityTitleButton = styled(EntityTitleButton)(({ theme }) => ({
const StyledEntityTitleButton = styled(EntityTitleButton, {
shouldForwardProp: props => props !== "layerType" && props !== "hasStoryCamera",
})(({ theme }) => ({
paddingRight: theme.spacing(1),
}));

Expand All @@ -33,6 +37,8 @@ interface HoverMenuProps {
onMove?: () => void;
boundingSphere?: XYZ | null;
layerId?: string | null;
layerType?: keyof LayerModelOverrides;
hasStoryCamera?: boolean;
}

const HoverMenu: FC<HoverMenuProps> = ({
Expand All @@ -42,9 +48,12 @@ const HoverMenu: FC<HoverMenuProps> = ({
onToggleHidden,
onMove,
layerId,
layerType,
boundingSphere,
hasStoryCamera,
}) => {
const isButtonDisabled = layerId == null && boundingSphere == null;
const isButtonDisabled =
layerId == null && boundingSphere == null && !(layerType === STORY_LAYER && hasStoryCamera);
if (!hovered && !hidden) {
return null;
}
Expand All @@ -71,15 +80,20 @@ const HoverMenu: FC<HoverMenuProps> = ({
</IconButton>
</Tooltip>
)}
<Tooltip title={hidden ? "表示" : "隠す"}>
<IconButton color="inherit" aria-label={hidden ? "表示" : "隠す"} onClick={onToggleHidden}>
{hidden ? (
<VisibilityOffSmallIcon fontSize="small" />
) : (
<VisibilityOnSmallIcon fontSize="small" />
)}
</IconButton>
</Tooltip>
{layerType !== STORY_LAYER && (
<Tooltip title={hidden ? "表示" : "隠す"}>
<IconButton
color="inherit"
aria-label={hidden ? "表示" : "隠す"}
onClick={onToggleHidden}>
{hidden ? (
<VisibilityOffSmallIcon fontSize="small" />
) : (
<VisibilityOnSmallIcon fontSize="small" />
)}
</IconButton>
</Tooltip>
)}
</Stack>
);
};
Expand All @@ -97,7 +111,9 @@ export const LayerListItem: FC<LayerListItemProps> = ({
onMouseLeave,
onMove,
layerId,
layerType,
boundingSphere,
hasStoryCamera,
...props
}) => {
const [hovered, setHovered] = useState(false);
Expand All @@ -121,7 +137,9 @@ export const LayerListItem: FC<LayerListItemProps> = ({
onToggleHidden={onToggleHidden}
onMove={onMove}
layerId={layerId}
layerType={layerType}
boundingSphere={boundingSphere}
hasStoryCamera={hasStoryCamera}
/>
{accessory}
</Stack>
Expand Down
21 changes: 21 additions & 0 deletions extension/src/prototypes/ui-components/icons/PencilIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { createSvgIcon } from "@mui/material";

export const PencilIcon = createSvgIcon(
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M7.5 16.875H3.75C3.58424 16.875 3.42527 16.8092 3.30806 16.692C3.19085 16.5748 3.125 16.4158 3.125 16.25V12.7589C3.125 12.6768 3.14117 12.5956 3.17258 12.5197C3.20398 12.4439 3.25002 12.375 3.30806 12.317L12.6831 2.94197C12.8003 2.82476 12.9592 2.75891 13.125 2.75891C13.2908 2.75891 13.4497 2.82476 13.5669 2.94197L17.0581 6.43309C17.1753 6.5503 17.2411 6.70927 17.2411 6.87503C17.2411 7.04079 17.1753 7.19976 17.0581 7.31697L7.5 16.875Z"
stroke="currentColor"
strokeWidth="1"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M10.625 5L15 9.375"
stroke="currentColor"
strokeWidth="1"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>,
"PencilIcon",
);
1 change: 1 addition & 0 deletions extension/src/prototypes/ui-components/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,4 @@ export * from "./ShareLoading";
export * from "./CameraIcon";
export * from "./Compass";
export * from "./ARIcon";
export * from "./PencilIcon";
11 changes: 10 additions & 1 deletion extension/src/prototypes/view-layers/ViewLayerListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ColorMapIcon, ColorSetIcon, ImageIconSetIcon, LayerListItem } from "../
import { CustomLegendSetIcon } from "../ui-components/CustomLegendSetIcon";

import { layerTypeIcons } from "./layerTypeIcons";
import { STORY_LAYER } from "./layerTypes";
import {
colorSchemeSelectionAtom,
customLegendSchemeSelectionAtom,
Expand Down Expand Up @@ -53,8 +54,14 @@ export const ViewLayerListItem: FC<ViewLayerListItemProps> = memo(
const layerCamera = useOptionalAtomValue(
useMemo(() => ("cameraAtom" in props ? props.cameraAtom : undefined), [props]),
);
const storyCamera = useOptionalAtomValue(
useMemo(() => ("capturesAtom" in props ? props.capturesAtom : undefined), [props]),
)?.[0]?.camera;
const boundingSphere = useAtomValue(boundingSphereAtom);
const handleMove = useCallback(() => {
if (type === STORY_LAYER) {
return storyCamera && flyToCamera(storyCamera);
}
const camera = rootLayer?.general?.camera;
if (camera) {
return flyToCamera(camera);
Expand All @@ -68,7 +75,7 @@ export const ViewLayerListItem: FC<ViewLayerListItemProps> = memo(
if (layerId) {
return flyToLayerId(layerId);
}
}, [layerId, rootLayer?.general?.camera, layerCamera, boundingSphere]);
}, [layerId, rootLayer?.general?.camera, layerCamera, boundingSphere, storyCamera, type]);

const [hidden, setHidden] = useAtom(hiddenAtom);
const handleToggleHidden = useCallback(() => {
Expand Down Expand Up @@ -157,7 +164,9 @@ export const ViewLayerListItem: FC<ViewLayerListItemProps> = memo(
loading={loading}
hidden={hidden}
layerId={layerId}
layerType={type}
boundingSphere={boundingSphere}
hasStoryCamera={!!storyCamera}
accessory={
colorMap != null ? (
<Tooltip title={colorScheme?.name}>
Expand Down
20 changes: 0 additions & 20 deletions extension/src/prototypes/view-layers/states.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { atom } from "jotai";
import { fromPairs, uniq, without } from "lodash-es";
import invariant from "tiny-invariant";

import { STORY_OBJECT, storySelectionAtom } from "../../shared/layerContainers/story";
import { rootLayersAtom, rootLayersLayersAtom } from "../../shared/states/rootLayer";
import { RootLayerAtom, StoryLayerModel } from "../../shared/view-layers";
import { matchIdentifier, parseIdentifier } from "../cesium-helpers";
Expand Down Expand Up @@ -39,22 +38,6 @@ export const storyLayersAtom = atom(get =>
get(rootLayersLayersAtom).filter((layer): layer is StoryLayerModel => layer.type === STORY_LAYER),
);

export const highlightedStoryLayersAtom = atom(get => {
const entityIds = get(storySelectionAtom).map(({ value }) => value);
const storyLayers = get(storyLayersAtom);
return storyLayers.filter(layer => {
const captures = get(layer.capturesAtom);
return entityIds.some(entityId =>
captures.some(capture =>
matchIdentifier(entityId, {
type: "Story",
key: capture.id,
}),
),
);
});
});

export const sketchLayersAtom = atom(get =>
get(rootLayersLayersAtom).filter(
(layer): layer is SketchLayerModel => layer.type === SKETCH_LAYER,
Expand Down Expand Up @@ -106,7 +89,6 @@ export const highlightedLayersAtom = atom(get => {
const layers = get(rootLayersLayersAtom);
const result: LayerModel[] = [];
const highlightedSketchLayers = get(highlightedSketchLayersAtom);
const hightlightedStoryLayers = get(highlightedStoryLayersAtom);
for (const layer of layers) {
const layerId = get(layer.layerIdAtom);
const selection = screenSpaceSelection.some(v => {
Expand All @@ -115,8 +97,6 @@ export const highlightedLayersAtom = atom(get => {
return layer.type === PEDESTRIAN_LAYER && layer.id === parseIdentifier(v.value).key;
case SKETCH_OBJECT:
return highlightedSketchLayers.some(v => v.id === layer.id);
case STORY_OBJECT:
return hightlightedStoryLayers.some(v => v.id === layer.id);
default:
return layerId === v.value.layerId;
}
Expand Down
4 changes: 0 additions & 4 deletions extension/src/prototypes/view/containers/KeyBindings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,6 @@ export const KeyBindings: FC = () => {
event.preventDefault();
send({ type: "SKETCH" });
return;
case "t":
event.preventDefault();
send({ type: "STORY" });
return;
case "p":
event.preventDefault();
send({ type: "PEDESTRIAN" });
Expand Down
19 changes: 3 additions & 16 deletions extension/src/prototypes/view/containers/ScreenSpaceSelection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import { useMediaQuery, useTheme } from "@mui/material";
import { useAtomValue } from "jotai";
import { type FC } from "react";

import { STORY_MARKER_ID_PROPERTY } from "../../../shared/reearth/layers";
import { PickedFeature } from "../../../shared/reearth/types";
import {
ScreenSpaceSelection as PlateauScreenSpaceSelection,
type ScreenSpaceSelectionProps as PlateauScreenSpaceSelectionProps,
Expand All @@ -16,30 +14,19 @@ const EVENTS_ON_SELECT_TOOL = {
select: true,
};

const EVENTS_ON_STORY_TOOL = {
point: true,
rectangle: false,
select: false,
};

export type ScreenSpaceSelectionProps = Omit<PlateauScreenSpaceSelectionProps, "disabled">;

const isFeatureStoryCapture = (f: PickedFeature | undefined) =>
f?.properties && !!f.properties[STORY_MARKER_ID_PROPERTY];

export const ScreenSpaceSelection: FC<ScreenSpaceSelectionProps> = props => {
const tool = useAtomValue(toolAtom);
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down("mobile"));
return (
<PlateauScreenSpaceSelection
{...props}
disabled={tool?.type !== "select" && tool?.type !== "story"}
disabled={tool?.type !== "select"}
allowClickWhenDisabled={isMobile}
filterSelectedFeature={tool?.type === "story" ? isFeatureStoryCapture : undefined}
allowedEvents={
isMobile || tool?.type === "select" ? EVENTS_ON_SELECT_TOOL : EVENTS_ON_STORY_TOOL
}
filterSelectedFeature={undefined}
allowedEvents={isMobile || tool?.type === "select" ? EVENTS_ON_SELECT_TOOL : undefined}
/>
);
};
Loading

0 comments on commit 125ed0d

Please sign in to comment.