Skip to content
This repository has been archived by the owner on Apr 25, 2023. It is now read-only.

Commit

Permalink
feat: extend plugin API supports get query (#374)
Browse files Browse the repository at this point in the history
* feat: add API viewport query

* refactor: types

* refactor: remove value check
  • Loading branch information
airslice committed Dec 16, 2022
1 parent 172988e commit ccae02a
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 57 deletions.
3 changes: 1 addition & 2 deletions src/components/molecules/Visualizer/Plugin/api.ts
@@ -1,7 +1,6 @@
import type { Events } from "@reearth/util/event";
import { merge } from "@reearth/util/object";

import { Viewport as VisualizerViewport } from "../hooks";
import type { LayerStore } from "../Layers";
import type { PluginInstances } from "../usePluginInstances";

Expand Down Expand Up @@ -267,7 +266,7 @@ export function commonReearth({
layers: () => LayerStore;
sceneProperty: () => any;
tags: () => Tag[];
viewport: () => VisualizerViewport;
viewport: () => GlobalThis["reearth"]["viewport"];
camera: () => GlobalThis["reearth"]["camera"]["position"];
clock: () => GlobalThis["reearth"]["clock"];
pluginInstances: () => PluginInstances;
Expand Down
15 changes: 11 additions & 4 deletions src/components/molecules/Visualizer/Plugin/context.tsx
Expand Up @@ -31,6 +31,7 @@ import type {
MouseEvent,
Clock,
Viewport,
ViewportSize,
LatLngHeight,
WidgetLocationOptions,
} from "./types";
Expand All @@ -55,7 +56,7 @@ export type Props = {
layerSelectionReason?: string;
layerOverridenInfobox?: OverriddenInfobox;
layerOverriddenProperties?: { [key: string]: any };
viewport?: VisualizerViewport;
viewport: VisualizerViewport;
showLayer: (...id: string[]) => void;
hideLayer: (...id: string[]) => void;
addLayer: (layer: Layer, parentId?: string, creator?: string) => string | undefined;
Expand Down Expand Up @@ -299,9 +300,15 @@ export function Provider({
tick: useMemo<[date: Date] | undefined>(() => {
return clock ? [clock.currentTime] : undefined;
}, [clock]),
resize: useMemo<[viewport: Viewport] | undefined>(
() => (viewport ? [viewport] : undefined),
[viewport],
resize: useMemo<[viewport: ViewportSize] | undefined>(
() => [
{
width: viewport.width,
height: viewport.height,
isMobile: viewport.isMobile,
} as ViewportSize,
],
[viewport.width, viewport.height, viewport.isMobile],
),
},
emit,
Expand Down
8 changes: 6 additions & 2 deletions src/components/molecules/Visualizer/Plugin/types.ts
Expand Up @@ -84,7 +84,7 @@ export type ReearthEventType = {
mouseleave: [props: MouseEvent];
wheel: [props: MouseEvent];
tick: [props: Date];
resize: [props: Viewport];
resize: [props: ViewportSize];
modalclose: [];
popupclose: [];
pluginmessage: [props: PluginMessage];
Expand Down Expand Up @@ -375,12 +375,16 @@ export type Visualizer = {
readonly overrideProperty: (property: any) => void;
};

export type Viewport = {
export type ViewportSize = {
readonly width: number;
readonly height: number;
readonly isMobile: boolean;
};

export type Viewport = ViewportSize & {
readonly query: Record<string, string>;
};

type Rect = {
north: number;
south: number;
Expand Down
54 changes: 5 additions & 49 deletions src/components/molecules/Visualizer/hooks.ts
Expand Up @@ -26,17 +26,12 @@ import type {
Tag,
} from "./Plugin/types";
import usePluginInstances from "./usePluginInstances";
import useViewport from "./useViewport";
import useWidgetAlignSystem from "./useWidgetAlignSystem";
import { useOverriddenProperty } from "./utils";
import type { WidgetAlignSystem, Widget } from "./WidgetAlignSystem";

export type Viewport = {
width: number;
height: number;
isMobile: boolean;
};

const viewportMobileMaxWidth = 768;
export type { Viewport } from "./useViewport";

export default ({
engineType,
Expand Down Expand Up @@ -120,48 +115,9 @@ export default ({
);
dropRef(wrapperRef);

const [viewport, setViewport] = useState<Viewport>();

useEffect(() => {
const viewportResizeObserver = new ResizeObserver(entries => {
const [entry] = entries;
let width: number | undefined;
let height: number | undefined;

if (entry.contentBoxSize) {
// Firefox(v69-91) implements `contentBoxSize` as a single content rect, rather than an array
const contentBoxSize = Array.isArray(entry.contentBoxSize)
? entry.contentBoxSize[0]
: entry.contentBoxSize;
width = contentBoxSize.inlineSize;
height = contentBoxSize.blockSize;
} else if (entry.contentRect) {
width = entry.contentRect.width;
height = entry.contentRect.height;
} else {
width = wrapperRef.current?.clientWidth;
height = wrapperRef.current?.clientHeight;
}

setViewport(
width && height
? {
width,
height,
isMobile: width <= viewportMobileMaxWidth,
}
: undefined,
);
});

if (wrapperRef.current) {
viewportResizeObserver.observe(wrapperRef.current);
}

return () => {
viewportResizeObserver.disconnect();
};
}, []);
const viewport = useViewport({
wrapperRef,
});

const {
selectedLayer,
Expand Down
1 change: 1 addition & 0 deletions src/components/molecules/Visualizer/storybook.tsx
Expand Up @@ -87,6 +87,7 @@ export const context: ProviderProps = {
width: 1280,
height: 720,
isMobile: false,
query: {},
},
layers: new LayerStore({ id: "", children: layers }),
pluginInstances: {
Expand Down
86 changes: 86 additions & 0 deletions src/components/molecules/Visualizer/useViewport.ts
@@ -0,0 +1,86 @@
import { useState, useEffect, RefObject } from "react";
import { useSearchParams } from "react-router-dom";

const viewportMobileMaxWidth = 768;

export type Viewport = {
width: number | undefined;
height: number | undefined;
isMobile: boolean | undefined;
query: Record<string, string>;
};

type Props = {
wrapperRef: RefObject<HTMLDivElement>;
};

export default ({ wrapperRef }: Props) => {
const [viewport, setViewport] = useState<Viewport>({
width: undefined,
height: undefined,
isMobile: undefined,
query: {},
});

useEffect(() => {
const viewportResizeObserver = new ResizeObserver(entries => {
const [entry] = entries;
let width: number | undefined;
let height: number | undefined;

if (entry.contentBoxSize) {
// Firefox(v69-91) implements `contentBoxSize` as a single content rect, rather than an array
const contentBoxSize = Array.isArray(entry.contentBoxSize)
? entry.contentBoxSize[0]
: entry.contentBoxSize;
width = contentBoxSize.inlineSize;
height = contentBoxSize.blockSize;
} else if (entry.contentRect) {
width = entry.contentRect.width;
height = entry.contentRect.height;
} else {
width = wrapperRef.current?.clientWidth;
height = wrapperRef.current?.clientHeight;
}

setViewport(viewport => {
return {
width,
height,
isMobile: width ? width <= viewportMobileMaxWidth : undefined,
query: viewport.query,
};
});
});

if (wrapperRef.current) {
viewportResizeObserver.observe(wrapperRef.current);
}

return () => {
viewportResizeObserver.disconnect();
};
}, [wrapperRef]);

const [searchParams] = useSearchParams();

useEffect(() => {
setViewport(viewport => {
const query = paramsToObject(searchParams.entries());
return {
...viewport,
query,
};
});
}, [searchParams]);

return viewport;
};

function paramsToObject(entries: IterableIterator<[string, string]>) {
const result: Record<string, string> = {};
for (const [key, value] of entries) {
result[key] = value;
}
return result;
}

0 comments on commit ccae02a

Please sign in to comment.