Skip to content

Commit

Permalink
feat(web): builtin infobox video and markdown block (#1117)
Browse files Browse the repository at this point in the history
  • Loading branch information
airslice authored Aug 28, 2024
1 parent 6af1e29 commit dd0a5fa
Show file tree
Hide file tree
Showing 20 changed files with 239 additions and 33 deletions.
42 changes: 42 additions & 0 deletions server/pkg/builtin/manifest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2709,3 +2709,45 @@ extensions:
field: displayType
type: string
value: custom
- id: videoInfoboxBetaBlock
name: Video
type: infoboxBlock
description: Infobox Video Block
schema:
groups:
- id: panel
title: Panel Setting
fields:
- id: padding
type: spacing
title: Padding
ui: padding
min: 0
max: 100
- id: default
title: Video Block
fields:
- id: src
type: string
title: Video
- id: markdownInfoboxBetaBlock
name: MD Text
type: infoboxBlock
description: Infobox MD Text Block
schema:
groups:
- id: panel
title: Panel Setting
fields:
- id: padding
type: spacing
title: Padding
ui: padding
min: 0
max: 100
- id: default
title: MD Text Block
fields:
- id: src
type: string
title: Content
28 changes: 28 additions & 0 deletions server/pkg/builtin/manifest_ja.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1347,6 +1347,34 @@ extensions:
custom: カスタム
property_list:
title: プロパティリスト
panel:
title: パネル設定
fields:
padding:
title: 余白
videoInfoboxBetaBlock:
name: ビデオ
description: インフォボックスビデオブロック
propertySchema:
default:
title: ビデオブロック
fields:
src:
title: ビデオ
panel:
title: パネル設定
fields:
padding:
title: 余白
markdownInfoboxBetaBlock:
name: MDテキスト
description: インフォボックスMDテキストブロック
propertySchema:
default:
title: MDテキストブロック
fields:
src:
title: コンテンツ
panel:
title: パネル設定
fields:
Expand Down
5 changes: 3 additions & 2 deletions server/schemas/plugin_manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,8 @@
"cluster",
"story",
"storyPage",
"storyBlock"
"storyBlock",
"infoboxBlock"
]
},
"singleOnly": {
Expand Down Expand Up @@ -454,4 +455,4 @@
}
},
"$ref": "#/definitions/root"
}
}
2 changes: 1 addition & 1 deletion web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@
"react-ga4": "2.1.0",
"react-i18next": "12.2.2",
"react-markdown": "8.0.7",
"react-player": "2.13.0",
"react-player": "2.16.0",
"react-popper": "2.3.0",
"react-router-dom": "6.21.0",
"react-sortablejs": "6.1.4",
Expand Down
2 changes: 1 addition & 1 deletion web/src/beta/components/DragAndDropList/Item.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { styled } from "@reearth/services/theme";
import type { Identifier } from "dnd-core";
import type { FC, ReactNode } from "react";
import { memo, useRef, createContext, useContext } from "react";
Expand All @@ -8,7 +9,6 @@ import {
useDrop,
} from "react-dnd";

import { styled } from "@reearth/services/theme";

type DragItem = {
index: number;
Expand Down
2 changes: 1 addition & 1 deletion web/src/beta/components/SidePanelSectionField/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { styled, useTheme } from "@reearth/services/theme";
import { useState, ReactNode, useEffect } from "react";

import { styled, useTheme } from "@reearth/services/theme";

import Icon from "../Icon";
import Text from "../Text";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { useMemo } from "react";

import Button from "@reearth/beta/components/Button";
import NumberInput from "@reearth/beta/components/fields/common/NumberInput";
import Text from "@reearth/beta/components/Text";
import { Camera } from "@reearth/beta/utils/value";
import { useT } from "@reearth/services/i18n";
import { styled } from "@reearth/services/theme";
import { useMemo } from "react";

import PanelCommon from "../../common/PanelCommon";
import type { RowType } from "../types";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { FC } from "react";

import { ColorField, NumberField, SwitchField } from "@reearth/beta/ui/fields";
import { Panel } from "@reearth/beta/ui/layout";
import { useT } from "@reearth/services/i18n";
import { WidgetAreaPadding } from "@reearth/services/state";
import { styled } from "@reearth/services/theme";
import { FC } from "react";

import { useWidgetsPage } from "../context";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@ export default ImageBlock;
const Image = styled("img")(() => ({
width: "100%",
height: "100%",
objectFit: "cover",
objectFit: "contain",
objectPosition: "center",
}));
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { FC, useMemo } from "react";
import ReactMarkdown from "react-markdown";
import gfm from "remark-gfm";

import BlockWrapper from "@reearth/beta/features/Visualizer/shared/components/BlockWrapper";
import { CommonBlockProps } from "@reearth/beta/features/Visualizer/shared/types";
import { ValueTypes } from "@reearth/beta/utils/value";
import { styled } from "@reearth/services/theme";

import { InfoboxBlock } from "../../../types";
import useExpressionEval from "../useExpressionEval";

const plugins = [gfm];

const MarkdownBlock: FC<CommonBlockProps<InfoboxBlock>> = ({ block, isSelected, ...props }) => {
const src = useMemo(
() => block?.property?.default?.src?.value as ValueTypes["string"],
[block?.property?.default?.src],
);

const evaluatedSrc = useExpressionEval(src);

return (
<BlockWrapper
name={block?.name}
icon={block?.extensionId}
isSelected={isSelected}
propertyId={block?.propertyId}
property={block?.property}
{...props}>
{evaluatedSrc !== undefined ? (
<Wrapper>
<ReactMarkdown remarkPlugins={plugins} linkTarget="_blank">
{evaluatedSrc || ""}
</ReactMarkdown>
</Wrapper>
) : null}
</BlockWrapper>
);
};

export default MarkdownBlock;

const Wrapper = styled("div")(() => ({
width: "100%",
position: "relative",
["*"]: {
maxWidth: "100%",
height: "auto",
},
}));
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { FC, useCallback, useMemo, useState } from "react";
import Player from "react-player";
import type ReactPlayer from "react-player";

import BlockWrapper from "@reearth/beta/features/Visualizer/shared/components/BlockWrapper";
import { CommonBlockProps } from "@reearth/beta/features/Visualizer/shared/types";
import { ValueTypes } from "@reearth/beta/utils/value";
import { styled } from "@reearth/services/theme";

import { InfoboxBlock } from "../../../types";
import useExpressionEval from "../useExpressionEval";

const VideoBlock: FC<CommonBlockProps<InfoboxBlock>> = ({ block, isSelected, ...props }) => {
const [aspectRatio, setAspectRatio] = useState(56.25);

const src = useMemo(
() => block?.property?.default?.src?.value as ValueTypes["string"],
[block?.property?.default?.src],
);

const evaluatedSrc = useExpressionEval(src);

const handleVideoReady = useCallback((player: ReactPlayer) => {
const height = player.getInternalPlayer().videoHeight;
const width = player.getInternalPlayer().videoWidth;
if (!height || !width) return;
setAspectRatio((height / width) * 100);
}, []);

return (
<BlockWrapper
name={block?.name}
icon={block?.extensionId}
isSelected={isSelected}
propertyId={block?.propertyId}
property={block?.property}
{...props}>
{evaluatedSrc !== undefined ? (
<Wrapper aspectRatio={aspectRatio}>
<StyledPlayer
url={evaluatedSrc}
width="100%"
height="100%"
onReady={handleVideoReady}
playsinline
pip
controls
light
/>
</Wrapper>
) : null}
</BlockWrapper>
);
};

export default VideoBlock;

const Wrapper = styled("div")<{ aspectRatio: number }>(({ aspectRatio }) => ({
position: "relative",
paddingTop: `${aspectRatio}%`,
width: "100%",
}));

const StyledPlayer = styled(Player)({
position: "absolute",
top: 0,
left: 0,
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,22 @@ import {
IMAGE_BUILTIN_INFOBOX_BLOCK_ID,
TEXT_BUILTIN_INFOBOX_BLOCK_ID,
PROPERTY_BUILTIN_INFOBOX_BLOCK_ID,
VIDEO_BUILTIN_INFOBOX_BLOCK_ID,
MARKDOWN_BUILTIN_INFOBOX_BLOCK_ID,
} from "../../constants";

import ImageBlock from "./Image";
import MarkdownBlock from "./Markdown";
import PropertyListBlock from "./PropertyList";
import TextBlock from "./Text";
import VideoBlock from "./Video";

export type ReEarthBuiltinInfoboxBlocks<T = unknown> = Record<
| typeof TEXT_BUILTIN_INFOBOX_BLOCK_ID
| typeof PROPERTY_BUILTIN_INFOBOX_BLOCK_ID
| typeof IMAGE_BUILTIN_INFOBOX_BLOCK_ID,
| typeof IMAGE_BUILTIN_INFOBOX_BLOCK_ID
| typeof VIDEO_BUILTIN_INFOBOX_BLOCK_ID
| typeof MARKDOWN_BUILTIN_INFOBOX_BLOCK_ID,
T
>;

Expand All @@ -25,6 +31,8 @@ const reearthBuiltin: BuiltinInfoboxBlocks<Component> = {
[IMAGE_BUILTIN_INFOBOX_BLOCK_ID]: ImageBlock,
[TEXT_BUILTIN_INFOBOX_BLOCK_ID]: TextBlock,
[PROPERTY_BUILTIN_INFOBOX_BLOCK_ID]: PropertyListBlock,
[VIDEO_BUILTIN_INFOBOX_BLOCK_ID]: VideoBlock,
[MARKDOWN_BUILTIN_INFOBOX_BLOCK_ID]: MarkdownBlock,
};

const builtin = merge({}, reearthBuiltin);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ export default (value: unknown | undefined) => {
>(undefined);

const [evaluatedResult, setEvaluatedResult] = useState<string | undefined>(
undefined,
undefined
);

const visualizer = useVisualizer();

// We want the useEffect to be called on each render to make sure evaluatedResult is up to date
// eslint-disable-next-line react-hooks/exhaustive-deps
useEffect(() => {
if (!isReady) {
setIsReady(true);
Expand All @@ -26,7 +27,17 @@ export default (value: unknown | undefined) => {
setEvaluatedResult(undefined);
return;
}
const selectedFeature = visualizer.current?.layers.selectedFeature();

// NOTE: core's selectedFeature is not always up to date, but the computed.features from selectedLayer is always up to date
// TODO: fix it on core
const selectedLayer = visualizer.current?.layers.selectedLayer();
const selectedFeature =
selectedLayer?.type === "simple" && selectedLayer?.data?.isSketchLayer
? selectedLayer.computed?.features.find(
(f) => f.id === visualizer.current?.layers.selectedFeature()?.id
)
: visualizer.current?.layers.selectedFeature();

if (selectedFeature && selectedFeature.id !== lastFeatureSelected) {
setLastFeatureSelected(selectedFeature.id);
setEvaluatedResult(undefined);
Expand All @@ -45,7 +56,7 @@ export default (value: unknown | undefined) => {
expression: currentValue,
},
undefined,
simpleFeature,
simpleFeature
);
if (
(es && typeof es === "string") ||
Expand All @@ -57,14 +68,7 @@ export default (value: unknown | undefined) => {
}
}
}
}, [
isReady,
currentValue,
value,
evaluatedResult,
visualizer,
lastFeatureSelected,
]);
});

return evaluatedResult;
};
4 changes: 4 additions & 0 deletions web/src/beta/features/Visualizer/Crust/Infobox/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@ export const IMAGE_BUILTIN_INFOBOX_BLOCK_ID = "reearth/imageInfoboxBetaBlock";
export const TEXT_BUILTIN_INFOBOX_BLOCK_ID = "reearth/textInfoboxBetaBlock";
export const PROPERTY_BUILTIN_INFOBOX_BLOCK_ID =
"reearth/propertyInfoboxBetaBlock";
export const VIDEO_BUILTIN_INFOBOX_BLOCK_ID = "reearth/videoInfoboxBetaBlock";
export const MARKDOWN_BUILTIN_INFOBOX_BLOCK_ID = "reearth/markdownInfoboxBetaBlock";

export const AVAILABLE_INFOBOX_BLOCK_IDS = [
IMAGE_BUILTIN_INFOBOX_BLOCK_ID,
TEXT_BUILTIN_INFOBOX_BLOCK_ID,
PROPERTY_BUILTIN_INFOBOX_BLOCK_ID,
VIDEO_BUILTIN_INFOBOX_BLOCK_ID,
MARKDOWN_BUILTIN_INFOBOX_BLOCK_ID,
];
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { styled } from "@reearth/services/theme";
import { Meta, Story } from "@storybook/react";
import { ReactNode, useState } from "react";

import { styled } from "@reearth/services/theme";

import { Icon } from "../Icon";

Expand Down
Loading

0 comments on commit dd0a5fa

Please sign in to comment.