@vnejs/plugins.views.scenario.interface 0.1.12 → 0.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -0
- package/dist/index.js +6 -0
- package/dist/modules/controller.d.ts +23 -0
- package/dist/modules/controller.js +77 -0
- package/dist/modules/interface.d.ts +27 -0
- package/dist/modules/interface.js +71 -0
- package/dist/modules/view.d.ts +11 -0
- package/dist/modules/view.js +10 -0
- package/dist/types.d.ts +17 -0
- package/dist/types.js +1 -0
- package/dist/utils/interface.d.ts +44 -0
- package/dist/utils/interface.js +1 -0
- package/dist/view/components/InterfaceBackdrop.d.ts +2 -0
- package/dist/view/components/InterfaceBackdrop.js +9 -0
- package/dist/view/components/InterfaceViewDialog.d.ts +2 -0
- package/dist/view/components/InterfaceViewDialog.js +19 -0
- package/dist/view/components/InterfaceViewLine.d.ts +2 -0
- package/dist/view/components/InterfaceViewLine.js +12 -0
- package/dist/view/components/InterfaceViewWall.d.ts +2 -0
- package/dist/view/components/InterfaceViewWall.js +24 -0
- package/dist/view/components/index.d.ts +4 -0
- package/dist/view/components/index.js +4 -0
- package/dist/view/components/tokens.hook.d.ts +6 -0
- package/dist/view/components/tokens.hook.js +30 -0
- package/dist/view/index.d.ts +3 -0
- package/dist/view/index.js +27 -0
- package/package.json +38 -6
- package/src/index.ts +8 -0
- package/{modules/controller.js → src/modules/controller.ts} +36 -10
- package/{modules/interface.js → src/modules/interface.ts} +29 -18
- package/src/modules/view.ts +22 -0
- package/src/types.ts +35 -0
- package/src/utils/interface.ts +52 -0
- package/src/view/components/InterfaceBackdrop.tsx +24 -0
- package/{view/components/InterfaceViewDialog.jsx → src/view/components/InterfaceViewDialog.tsx} +11 -11
- package/src/view/components/InterfaceViewLine.tsx +27 -0
- package/src/view/components/InterfaceViewWall.tsx +93 -0
- package/src/view/components/index.ts +4 -0
- package/{view/components/tokens.hook.jsx → src/view/components/tokens.hook.ts} +10 -12
- package/src/view/index.tsx +69 -0
- package/tsconfig.json +10 -0
- package/const/events.js +0 -31
- package/const/params.js +0 -37
- package/index.js +0 -10
- package/modules/view.js +0 -14
- package/view/components/InterfaceBackdrop.jsx +0 -22
- package/view/components/InterfaceViewLine.jsx +0 -25
- package/view/components/InterfaceViewWall.jsx +0 -65
- package/view/components/index.js +0 -4
- package/view/index.jsx +0 -62
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
import { Module } from "@vnejs/module";
|
|
2
|
-
|
|
3
2
|
import { tokenizeExecLine } from "@vnejs/helpers";
|
|
4
3
|
|
|
5
|
-
|
|
4
|
+
import type { InterfacePluginConstants, InterfacePluginEvents, InterfacePluginParams, InterfacePluginSettings } from "../types.js";
|
|
5
|
+
import type {
|
|
6
|
+
InterfaceForcePayload,
|
|
7
|
+
InterfaceLineExecPayload,
|
|
8
|
+
InterfaceModuleState,
|
|
9
|
+
InterfaceSpeakerChangedPayload,
|
|
10
|
+
InterfaceStateSetPayload,
|
|
11
|
+
InterfaceTextChangedPayload,
|
|
12
|
+
InterfaceViewPayload,
|
|
13
|
+
} from "../utils/interface.js";
|
|
14
|
+
|
|
15
|
+
export class Interface extends Module<InterfacePluginEvents, InterfacePluginConstants, InterfacePluginSettings, InterfacePluginParams, InterfaceModuleState> {
|
|
6
16
|
name = "interface";
|
|
7
17
|
|
|
8
18
|
subscribe = () => {
|
|
@@ -20,9 +30,10 @@ export class Interface extends Module {
|
|
|
20
30
|
this.on(this.EVENTS.STATE.SET, this.onStateSet);
|
|
21
31
|
this.on(this.EVENTS.STATE.CLEAR, this.onStateClear);
|
|
22
32
|
};
|
|
33
|
+
|
|
23
34
|
init = () => this.emit(this.EVENTS.SCENARIO.LINE_EXEC_REG, { module: this.name, handler: this.onLineExec });
|
|
24
35
|
|
|
25
|
-
onLineExec = async ({ line = "" } = {}) => {
|
|
36
|
+
onLineExec = async ({ line = "" }: InterfaceLineExecPayload = {}) => {
|
|
26
37
|
const isForce = Boolean(this.shared.viewForceAnimationSources.length);
|
|
27
38
|
|
|
28
39
|
const [action = "", execArg = ""] = tokenizeExecLine(line);
|
|
@@ -35,35 +46,35 @@ export class Interface extends Module {
|
|
|
35
46
|
};
|
|
36
47
|
|
|
37
48
|
onInteract = () => this.emit(this.state.isVisible ? this.EVENTS.INTERACT.EMIT : this.EVENTS.INTERFACE.VISIBLE);
|
|
38
|
-
onShow = ({ isForce = false } = {}) => !this.state.isShow && this.setShow(true, isForce);
|
|
39
|
-
onHide = ({ isForce = false } = {}) => this.state.isShow && this.setShow(false, isForce);
|
|
40
|
-
onVisible = ({ isForce = false } = {}) => this.setVisible(!this.state.isVisible, isForce);
|
|
41
|
-
onTextChanged = ({ tokens, wall, uid, tokensVisible } = {}) => this.setText(tokens, wall, uid, tokensVisible);
|
|
42
|
-
onTextSpeakerChanged = ({ speaker, meet } = {}) => this.setSpeaker(speaker, meet);
|
|
49
|
+
onShow = ({ isForce = false }: InterfaceForcePayload = {}) => !this.state.isShow && this.setShow(true, isForce);
|
|
50
|
+
onHide = ({ isForce = false }: InterfaceForcePayload = {}) => this.state.isShow && this.setShow(false, isForce);
|
|
51
|
+
onVisible = ({ isForce = false }: InterfaceForcePayload = {}) => this.setVisible(!this.state.isVisible, isForce);
|
|
52
|
+
onTextChanged = ({ tokens, wall, uid, tokensVisible }: InterfaceTextChangedPayload = {}) => this.setText(tokens, wall, uid, tokensVisible);
|
|
53
|
+
onTextSpeakerChanged = ({ speaker, meet }: InterfaceSpeakerChangedPayload = {}) => this.setSpeaker(speaker, meet);
|
|
43
54
|
onTextEmitBefore = () => this.emit(this.EVENTS.INTERFACE.SHOW);
|
|
44
55
|
onTextHide = () => this.setText([], [], "", 0);
|
|
45
|
-
onView = ({ view, isForce = false } = {}) => this.setView(view, isForce);
|
|
46
|
-
onStateSet = ({ [this.name]: state } = {}) => this.setNewState(state
|
|
56
|
+
onView = ({ view, isForce = false }: InterfaceViewPayload = {}) => this.setView(view, isForce);
|
|
57
|
+
onStateSet = ({ [this.name]: state }: InterfaceStateSetPayload = {}) => this.setNewState(state?.view, state?.isVisible, state?.isShow);
|
|
47
58
|
onStateClear = () => this.setNewState(this.PARAMS.INTERFACE.DEFAULT_VIEW, false, false);
|
|
48
59
|
|
|
49
|
-
setView = (view, isForce = false) => {
|
|
50
|
-
this.state.view = view;
|
|
60
|
+
setView = (view?: string, isForce = false) => {
|
|
61
|
+
this.state.view = view ?? "";
|
|
51
62
|
|
|
52
63
|
return this.emit(this.EVENTS.INTERFACE.VIEW_CHANGED, { isForce });
|
|
53
64
|
};
|
|
54
|
-
setShow = async (isShow, isForce = false) => {
|
|
65
|
+
setShow = async (isShow: boolean, isForce = false) => {
|
|
55
66
|
this.state.isShow = isShow;
|
|
56
67
|
|
|
57
68
|
if (isShow && !this.state.isVisible) await this.setVisible(true, isForce);
|
|
58
69
|
|
|
59
70
|
return this.emit(this.EVENTS.INTERFACE.SHOW_CHANGED, { isForce });
|
|
60
71
|
};
|
|
61
|
-
setVisible = (isVisible, isForce = false) => {
|
|
72
|
+
setVisible = (isVisible: boolean, isForce = false) => {
|
|
62
73
|
this.state.isVisible = isVisible;
|
|
63
74
|
|
|
64
75
|
return this.emit(this.EVENTS.INTERFACE.VISIBLE_CHANGED, { isForce });
|
|
65
76
|
};
|
|
66
|
-
setText = (tokens = [], wall = [], uid = "", tokensVisible) => {
|
|
77
|
+
setText = (tokens: InterfaceModuleState["tokens"] = [], wall: InterfaceModuleState["wall"] = [], uid = "", tokensVisible?: number) => {
|
|
67
78
|
Object.assign(this.state, { tokens, wall, uid, tokensVisible });
|
|
68
79
|
|
|
69
80
|
return this.emit(this.EVENTS.INTERFACE.TEXT_CHANGED);
|
|
@@ -73,15 +84,15 @@ export class Interface extends Module {
|
|
|
73
84
|
|
|
74
85
|
return this.emit(this.EVENTS.INTERFACE.SPEAKER_CHANGED);
|
|
75
86
|
};
|
|
76
|
-
setNewState = (view, isVisible, isShow) => {
|
|
87
|
+
setNewState = (view?: string, isVisible?: boolean, isShow?: boolean) => {
|
|
77
88
|
Object.assign(this.state, { isShow, view, isVisible });
|
|
78
89
|
|
|
79
90
|
return this.emit(this.EVENTS.INTERFACE.STATE_CHANGED);
|
|
80
91
|
};
|
|
81
92
|
|
|
82
|
-
getDefaultState = () => {
|
|
93
|
+
getDefaultState = (): InterfaceModuleState => {
|
|
83
94
|
const result = { tokens: [], view: this.PARAMS.INTERFACE.DEFAULT_VIEW, uid: "", speaker: "" };
|
|
84
95
|
|
|
85
|
-
return { ...result, meet: 0, tokensVisible: 0, isShow: false, isVisible: false };
|
|
96
|
+
return { ...result, meet: 0, tokensVisible: 0, isShow: false, isVisible: false, wall: [] };
|
|
86
97
|
};
|
|
87
98
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ModuleView } from "@vnejs/module.components";
|
|
2
|
+
|
|
3
|
+
import { render } from "../view/index.js";
|
|
4
|
+
import type { InterfacePluginConstants, InterfacePluginEvents, InterfacePluginParams, InterfacePluginSettings } from "../types.js";
|
|
5
|
+
import type { InterfacePluginState } from "../utils/interface.js";
|
|
6
|
+
|
|
7
|
+
export class InterfaceView extends ModuleView<
|
|
8
|
+
InterfacePluginEvents,
|
|
9
|
+
InterfacePluginConstants,
|
|
10
|
+
InterfacePluginSettings,
|
|
11
|
+
InterfacePluginParams,
|
|
12
|
+
InterfacePluginState
|
|
13
|
+
> {
|
|
14
|
+
name = "interface.view";
|
|
15
|
+
|
|
16
|
+
locLabel = this.PARAMS.INTERFACE.LOC_LABEL;
|
|
17
|
+
animationTime = this.PARAMS.INTERFACE.TRANSITION;
|
|
18
|
+
updateEvent = this.EVENTS.INTERFACE.VIEW_UPDATE;
|
|
19
|
+
|
|
20
|
+
renderFunc = render;
|
|
21
|
+
updateHandler = this.onUpdateStoreComponent;
|
|
22
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ModuleComponentsConstants, ModuleComponentsEvents, ModuleComponentsParams, ModuleComponentsSettings } from "@vnejs/module.components";
|
|
2
|
+
import type { ReactComponentProps } from "@vnejs/uis.react";
|
|
3
|
+
import type { Constants as ControlsConstants, PluginName as ControlsPluginName } from "@vnejs/plugins.controls.contract";
|
|
4
|
+
import type { PluginName as InteractPluginName, SubscribeEvents as InteractSubscribeEvents } from "@vnejs/plugins.core.interact.contract";
|
|
5
|
+
import type { PluginName as ScenarioPluginName, SubscribeEvents as ScenarioSubscribeEvents } from "@vnejs/plugins.core.scenario.contract";
|
|
6
|
+
import type { PluginName as StatePluginName, SubscribeEvents as StateSubscribeEvents } from "@vnejs/plugins.core.state.contract";
|
|
7
|
+
import type { PluginName as TextPluginName, Params as TextParams, SubscribeEvents as TextSubscribeEvents } from "@vnejs/plugins.text.contract";
|
|
8
|
+
import type { Params, PluginName, SubscribeEvents } from "@vnejs/plugins.views.scenario.interface.contract";
|
|
9
|
+
|
|
10
|
+
import type { InterfacePluginState } from "./utils/interface.js";
|
|
11
|
+
|
|
12
|
+
export type InterfacePluginEvents = ModuleComponentsEvents &
|
|
13
|
+
Record<PluginName, SubscribeEvents> &
|
|
14
|
+
Record<ScenarioPluginName, ScenarioSubscribeEvents> &
|
|
15
|
+
Record<StatePluginName, StateSubscribeEvents> &
|
|
16
|
+
Record<TextPluginName, TextSubscribeEvents> &
|
|
17
|
+
Record<InteractPluginName, InteractSubscribeEvents>;
|
|
18
|
+
|
|
19
|
+
export type InterfacePluginConstants = ModuleComponentsConstants & Record<ControlsPluginName, ControlsConstants>;
|
|
20
|
+
|
|
21
|
+
export type InterfacePluginSettings = ModuleComponentsSettings;
|
|
22
|
+
|
|
23
|
+
export type InterfacePluginParams = ModuleComponentsParams & Record<PluginName, Params> & Record<TextPluginName, TextParams>;
|
|
24
|
+
|
|
25
|
+
export type InterfacePluginViewState = InterfacePluginState & {
|
|
26
|
+
isViewActive?: boolean;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export type InterfaceViewProps = ReactComponentProps<
|
|
30
|
+
InterfacePluginEvents,
|
|
31
|
+
InterfacePluginConstants,
|
|
32
|
+
InterfacePluginSettings,
|
|
33
|
+
InterfacePluginParams,
|
|
34
|
+
InterfacePluginViewState
|
|
35
|
+
>;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { ModuleControllerState } from "@vnejs/module.components";
|
|
2
|
+
import type { TokenizedChar, WallElement } from "@vnejs/plugins.text.contract";
|
|
3
|
+
import type { InterfaceModuleState } from "@vnejs/plugins.views.scenario.interface.contract";
|
|
4
|
+
|
|
5
|
+
export type { InterfaceModuleState };
|
|
6
|
+
|
|
7
|
+
export type InterfaceSpeakerInfo = {
|
|
8
|
+
color?: string;
|
|
9
|
+
opacity?: number;
|
|
10
|
+
speakerColor?: string;
|
|
11
|
+
names?: Record<string, string[] | undefined> & { default?: string[] };
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type InterfacePluginState = ModuleControllerState &
|
|
15
|
+
InterfaceModuleState & {
|
|
16
|
+
isFast?: boolean;
|
|
17
|
+
locs?: Record<string, string>;
|
|
18
|
+
prefix?: string;
|
|
19
|
+
postfix?: string;
|
|
20
|
+
transition?: number;
|
|
21
|
+
speakerText?: string;
|
|
22
|
+
speakerName?: string;
|
|
23
|
+
speakerColor?: string;
|
|
24
|
+
color?: string;
|
|
25
|
+
opacity?: number;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type InterfaceLineExecPayload = {
|
|
29
|
+
line?: string;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export type InterfaceForcePayload = {
|
|
33
|
+
isForce?: boolean;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export type InterfaceViewPayload = InterfaceForcePayload & {
|
|
37
|
+
view?: string;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export type InterfaceTextChangedPayload = {
|
|
41
|
+
tokens?: TokenizedChar[];
|
|
42
|
+
wall?: WallElement[];
|
|
43
|
+
uid?: string;
|
|
44
|
+
tokensVisible?: number;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export type InterfaceSpeakerChangedPayload = {
|
|
48
|
+
speaker?: string;
|
|
49
|
+
meet?: number;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export type InterfaceStateSetPayload = Record<string, Pick<InterfaceModuleState, "view" | "isVisible" | "isShow"> | undefined>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Backdrop, PositionBox, useMemo } from "@vnejs/uis.react";
|
|
2
|
+
|
|
3
|
+
import type { InterfaceViewProps } from "../../types.js";
|
|
4
|
+
|
|
5
|
+
export const InterfaceBackdrop = ({ view = "", transition = 0, PARAMS }: InterfaceViewProps) => {
|
|
6
|
+
const propsByView = useMemo(() => PARAMS.INTERFACE.VIEW_PROPS[view as keyof typeof PARAMS.INTERFACE.VIEW_PROPS]?.backdrop || {}, [view, PARAMS.INTERFACE.VIEW_PROPS]);
|
|
7
|
+
|
|
8
|
+
const propsBackdrop = useMemo(() => ({ ...propsByView.props, transition }), [propsByView, transition]);
|
|
9
|
+
const propsPosition = useMemo(() => ({ ...propsByView.flatPosition, transition }), [propsByView, transition]);
|
|
10
|
+
|
|
11
|
+
const styleFlatBackdrop = useMemo(
|
|
12
|
+
() => ({ ...propsByView.flatStyle, width: "100%", height: "100%", transition: `${transition}ms` }),
|
|
13
|
+
[propsByView, transition],
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<>
|
|
18
|
+
<Backdrop {...propsBackdrop} />
|
|
19
|
+
<PositionBox {...propsPosition}>
|
|
20
|
+
<div style={styleFlatBackdrop} />
|
|
21
|
+
</PositionBox>
|
|
22
|
+
</>
|
|
23
|
+
);
|
|
24
|
+
};
|
package/{view/components/InterfaceViewDialog.jsx → src/view/components/InterfaceViewDialog.tsx}
RENAMED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { useMemo } from "react";
|
|
2
|
-
|
|
3
|
-
import { Flex, PositionBox, SmoothText, Text } from "@vnejs/uis.react";
|
|
1
|
+
import { Flex, PositionBox, SmoothText, Text, useMemo } from "@vnejs/uis.react";
|
|
4
2
|
import { getVneLength } from "@vnejs/uis.utils";
|
|
5
|
-
import { useTokensHook } from "./tokens.hook";
|
|
6
3
|
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
import type { InterfaceViewProps } from "../../types.js";
|
|
5
|
+
import { useTokensHook } from "./tokens.hook.js";
|
|
6
|
+
|
|
7
|
+
export const InterfaceViewDialog = (props: InterfaceViewProps) => {
|
|
8
|
+
const { isViewActive = false, transition, tokensVisible = 0, tokens = [], speakerText, speakerName, speakerColor, opacity, color, uid = "", PARAMS } = props;
|
|
9
9
|
|
|
10
|
-
const propsByView =
|
|
10
|
+
const propsByView = PARAMS.INTERFACE.VIEW_PROPS.adv;
|
|
11
11
|
|
|
12
|
-
const propsPosition = useMemo(() => ({ ...propsByView.position, opacity:
|
|
12
|
+
const propsPosition = useMemo(() => ({ ...propsByView.position, opacity: isViewActive ? 1 : 0, transition }), [isViewActive, transition, propsByView.position]);
|
|
13
13
|
|
|
14
14
|
const speakerOpacity = speakerName ? 1 : 0;
|
|
15
15
|
const speakerTransition = speakerName ? transition : 0;
|
|
@@ -19,15 +19,15 @@ export const InterfaceViewDialog = (props = {}) => {
|
|
|
19
19
|
const styleSepColor = useMemo(() => ({ opacity: speakerOpacity, transition: `${speakerTransition}ms` || "none" }), [speakerOpacity, speakerTransition]);
|
|
20
20
|
const styleSep = useMemo(() => ({ ...styleSepBg, ...styleSepColor }), [styleSepBg, styleSepColor]);
|
|
21
21
|
|
|
22
|
-
const { realTokens, realTokensVisible } = useTokensHook(
|
|
22
|
+
const { realTokens, realTokensVisible } = useTokensHook(isViewActive, tokens, tokensVisible, uid);
|
|
23
23
|
|
|
24
24
|
const propsSpeaker = useMemo(
|
|
25
25
|
() => ({ ...propsByView.speaker, text: speakerText, color: speakerColor, opacity: speakerOpacity, transition: speakerTransition }),
|
|
26
|
-
[speakerText, speakerColor, speakerOpacity, speakerTransition],
|
|
26
|
+
[speakerText, speakerColor, speakerOpacity, speakerTransition, propsByView.speaker],
|
|
27
27
|
);
|
|
28
28
|
const propsText = useMemo(
|
|
29
29
|
() => ({ ...propsByView.text, opacity, color, tokens: realTokens, tokensVisibleForce: realTokensVisible, transition }),
|
|
30
|
-
[opacity, color, realTokens, realTokensVisible, transition],
|
|
30
|
+
[opacity, color, realTokens, realTokensVisible, transition, propsByView.text],
|
|
31
31
|
);
|
|
32
32
|
|
|
33
33
|
return (
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Flex, PositionBox, SmoothText, useMemo } from "@vnejs/uis.react";
|
|
2
|
+
|
|
3
|
+
import type { InterfaceViewProps } from "../../types.js";
|
|
4
|
+
import { useTokensHook } from "./tokens.hook.js";
|
|
5
|
+
|
|
6
|
+
export const InterfaceViewLine = (props: InterfaceViewProps) => {
|
|
7
|
+
const { isViewActive = false, transition = 0, tokensVisible = 0, tokens = [], opacity, color, uid = "", PARAMS } = props;
|
|
8
|
+
|
|
9
|
+
const propsByView = PARAMS.INTERFACE.VIEW_PROPS.line;
|
|
10
|
+
|
|
11
|
+
const { realTokens, realTokensVisible } = useTokensHook(isViewActive, tokens, tokensVisible, uid);
|
|
12
|
+
|
|
13
|
+
const propsTextTokens = useMemo(() => ({ tokens: realTokens, tokensVisibleForce: realTokensVisible }), [realTokens, realTokensVisible]);
|
|
14
|
+
const propsText = useMemo(
|
|
15
|
+
() => ({ ...propsByView.text, opacity, color, transition, ...propsTextTokens }),
|
|
16
|
+
[opacity, color, transition, propsTextTokens, propsByView.text],
|
|
17
|
+
);
|
|
18
|
+
const propsPosition = useMemo(() => ({ ...propsByView.position, opacity: isViewActive ? 1 : 0, transition }), [isViewActive, transition, propsByView.position]);
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<PositionBox {...propsPosition}>
|
|
22
|
+
<Flex {...propsByView.flex}>
|
|
23
|
+
<SmoothText {...propsText} />
|
|
24
|
+
</Flex>
|
|
25
|
+
</PositionBox>
|
|
26
|
+
);
|
|
27
|
+
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { TokenizedChar, WallElement } from "@vnejs/plugins.text.contract";
|
|
2
|
+
import { Flex, PositionBox, Scrollbar, SmoothText, Text, useMemo } from "@vnejs/uis.react";
|
|
3
|
+
|
|
4
|
+
import type { Params as InterfaceContractParams } from "@vnejs/plugins.views.scenario.interface.contract";
|
|
5
|
+
|
|
6
|
+
import type { InterfaceViewProps } from "../../types.js";
|
|
7
|
+
import type { InterfaceSpeakerInfo } from "../../utils/interface.js";
|
|
8
|
+
import { useTokensHook } from "./tokens.hook.js";
|
|
9
|
+
|
|
10
|
+
type WallTextElement = {
|
|
11
|
+
speakerName?: string;
|
|
12
|
+
speakerColor?: string;
|
|
13
|
+
uid: string;
|
|
14
|
+
color?: string;
|
|
15
|
+
opacity?: number;
|
|
16
|
+
tokens: TokenizedChar[];
|
|
17
|
+
tokensVisible: number;
|
|
18
|
+
transition?: number;
|
|
19
|
+
propsByView: InterfaceContractParams["VIEW_PROPS"]["wall"];
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const renderOneText = (wallElement: WallTextElement) => (
|
|
23
|
+
<div key={wallElement.uid}>
|
|
24
|
+
{wallElement.speakerName && (
|
|
25
|
+
<Text
|
|
26
|
+
{...wallElement.propsByView.text}
|
|
27
|
+
isInlineBlock={true}
|
|
28
|
+
color={wallElement.speakerColor}
|
|
29
|
+
text={`${wallElement.speakerName}:`}
|
|
30
|
+
marginRight={12}
|
|
31
|
+
/>
|
|
32
|
+
)}
|
|
33
|
+
<SmoothText
|
|
34
|
+
{...wallElement.propsByView.text}
|
|
35
|
+
isNoScrollBar={true}
|
|
36
|
+
color={wallElement.color}
|
|
37
|
+
opacity={wallElement.opacity}
|
|
38
|
+
transition={wallElement.transition}
|
|
39
|
+
tokens={wallElement.tokens}
|
|
40
|
+
tokensVisibleForce={wallElement.tokensVisible}
|
|
41
|
+
/>
|
|
42
|
+
</div>
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
const mapWall = ({ uid = "", tokens = [], speaker = "", meet = 0, transition = 0, props }: WallElement & { transition?: number; props: InterfaceViewProps }) => {
|
|
46
|
+
const propsByView = props.PARAMS.INTERFACE.VIEW_PROPS.wall;
|
|
47
|
+
const speakersInfo = props.PARAMS.TEXT.SPEAKERS_INFO as Record<string, InterfaceSpeakerInfo>;
|
|
48
|
+
const speakerInfo = speakersInfo[speaker] || speakersInfo.default || {};
|
|
49
|
+
const { color, opacity = 1, names = {}, speakerColor = "white" } = speakerInfo;
|
|
50
|
+
|
|
51
|
+
const langNames = names[(props.shared as { lang?: string }).lang ?? ""] || names.default || [];
|
|
52
|
+
const speakerName = langNames[meet] || langNames[langNames.length - 1];
|
|
53
|
+
|
|
54
|
+
return { speakerName, speakerColor, uid, color, opacity, tokens, tokensVisible: tokens.length, transition, propsByView };
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export const InterfaceViewWall = (props: InterfaceViewProps) => {
|
|
58
|
+
const {
|
|
59
|
+
isViewActive = false,
|
|
60
|
+
transition = 0,
|
|
61
|
+
tokensVisible = 0,
|
|
62
|
+
tokens = [],
|
|
63
|
+
wall = [],
|
|
64
|
+
uid = "",
|
|
65
|
+
speakerName,
|
|
66
|
+
speakerColor,
|
|
67
|
+
color,
|
|
68
|
+
opacity,
|
|
69
|
+
PARAMS,
|
|
70
|
+
} = props;
|
|
71
|
+
|
|
72
|
+
const propsByView = PARAMS.INTERFACE.VIEW_PROPS.wall;
|
|
73
|
+
|
|
74
|
+
const propsPosition = useMemo(() => ({ ...propsByView.position, opacity: isViewActive ? 1 : 0, transition }), [isViewActive, transition, propsByView.position]);
|
|
75
|
+
const wallWithProps = useMemo(() => wall.map((item) => ({ ...item, transition, props })), [wall, transition, props]);
|
|
76
|
+
|
|
77
|
+
const { realTokens, realTokensVisible } = useTokensHook(isViewActive, tokens, tokensVisible, uid);
|
|
78
|
+
|
|
79
|
+
const wallTexts = useMemo(() => wallWithProps.map(mapWall), [wallWithProps]);
|
|
80
|
+
const curText = useMemo(
|
|
81
|
+
() => ({ speakerName, speakerColor, uid, color, opacity, tokens: realTokens, tokensVisible: realTokensVisible, transition, propsByView }),
|
|
82
|
+
[speakerName, speakerColor, uid, color, opacity, realTokens, realTokensVisible, transition, propsByView],
|
|
83
|
+
);
|
|
84
|
+
const texts = useMemo(() => [...wallTexts, curText], [wallTexts, curText]);
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<PositionBox {...propsPosition}>
|
|
88
|
+
<Scrollbar {...propsByView.scrollBar}>
|
|
89
|
+
<Flex {...propsByView.flex}>{texts.map(renderOneText)}</Flex>
|
|
90
|
+
</Scrollbar>
|
|
91
|
+
</PositionBox>
|
|
92
|
+
);
|
|
93
|
+
};
|
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { flushSync } from "react
|
|
1
|
+
import type { TokenizedChar } from "@vnejs/plugins.text.contract";
|
|
2
|
+
import { flushSync, useEffect, useMemo, useState } from "@vnejs/uis.react";
|
|
3
3
|
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
export const useTokensHook = (isShow, tokens, tokensVisible, uid) => {
|
|
4
|
+
export const useTokensHook = (isShow: boolean, tokens: TokenizedChar[], tokensVisible: number, uid: string) => {
|
|
7
5
|
const [savedUid, setSavedUid] = useState("");
|
|
8
|
-
const [tokensSync, setTokensSync] = useState(
|
|
9
|
-
const [tokensWrong, setTokensWrong] = useState(
|
|
6
|
+
const [tokensSync, setTokensSync] = useState([] as TokenizedChar[]);
|
|
7
|
+
const [tokensWrong, setTokensWrong] = useState([] as TokenizedChar[]);
|
|
10
8
|
|
|
11
9
|
useEffect(() => {
|
|
12
10
|
if (isShow) setTokensWrong(tokens);
|
|
13
|
-
}, [isShow]);
|
|
11
|
+
}, [isShow, tokens]);
|
|
14
12
|
useEffect(() => {
|
|
15
|
-
|
|
13
|
+
setTimeout(() => {
|
|
16
14
|
if (savedUid === uid) {
|
|
17
15
|
if (!isShow) setTokensWrong(tokens);
|
|
18
16
|
setTokensSync(tokens);
|
|
@@ -23,12 +21,12 @@ export const useTokensHook = (isShow, tokens, tokensVisible, uid) => {
|
|
|
23
21
|
if (!isShow) setTokensWrong(tokens);
|
|
24
22
|
setTokensSync(tokens);
|
|
25
23
|
});
|
|
26
|
-
});
|
|
27
|
-
}, [tokens]);
|
|
24
|
+
}, 0);
|
|
25
|
+
}, [tokens, savedUid, uid, isShow]);
|
|
28
26
|
|
|
29
27
|
const isShowTokens = useMemo(() => tokensSync !== tokensWrong, [tokensSync, tokensWrong]);
|
|
30
28
|
const realTokensVisible = useMemo(() => (isShowTokens ? tokensVisible : 0), [isShowTokens, tokensVisible]);
|
|
31
|
-
const realTokens = useMemo(() => (isShowTokens ? tokensSync :
|
|
29
|
+
const realTokens = useMemo(() => (isShowTokens ? tokensSync : []), [isShowTokens, tokensSync]);
|
|
32
30
|
|
|
33
31
|
return { isShowTokens, realTokensVisible, realTokens };
|
|
34
32
|
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { ViewRenderFunc } from "@vnejs/module.components";
|
|
2
|
+
import type { ReactComponentProps } from "@vnejs/uis.react";
|
|
3
|
+
import { Screen, createRenderFunc, useCallback, useIsForceHook, useMemo, useStoreState } from "@vnejs/uis.react";
|
|
4
|
+
|
|
5
|
+
import type { InterfacePluginConstants, InterfacePluginEvents, InterfacePluginParams, InterfacePluginSettings } from "../types.js";
|
|
6
|
+
import type { InterfacePluginState, InterfaceSpeakerInfo } from "../utils/interface.js";
|
|
7
|
+
import { InterfaceBackdrop, InterfaceViewDialog, InterfaceViewLine, InterfaceViewWall } from "./components/index.js";
|
|
8
|
+
|
|
9
|
+
type InterfaceComponentProps = ReactComponentProps<
|
|
10
|
+
InterfacePluginEvents,
|
|
11
|
+
InterfacePluginConstants,
|
|
12
|
+
InterfacePluginSettings,
|
|
13
|
+
InterfacePluginParams,
|
|
14
|
+
InterfacePluginState
|
|
15
|
+
>;
|
|
16
|
+
|
|
17
|
+
const Interface = (props: InterfaceComponentProps) => {
|
|
18
|
+
const { store, onMount, emit, EVENTS, PARAMS } = props;
|
|
19
|
+
const state = useStoreState<InterfacePluginState>(store, onMount);
|
|
20
|
+
|
|
21
|
+
const { isShow = false, isVisible = false, isForce = false, tokensVisible = 0, view = "", locs = {} } = state;
|
|
22
|
+
const { speaker = "", meet = 0, tokens = [], wall = [], postfix = "", prefix = "", uid = "" } = state;
|
|
23
|
+
|
|
24
|
+
const onClick = useCallback(() => emit(EVENTS.INTERFACE.INTERACT), [emit, EVENTS.INTERFACE.INTERACT]);
|
|
25
|
+
|
|
26
|
+
const isRealForce = useIsForceHook(isForce);
|
|
27
|
+
|
|
28
|
+
const speakerName = locs[`speaker.${speaker}.${meet ?? 0}`];
|
|
29
|
+
const speakerText = speakerName ? `${`${locs[`prefix.${prefix}`] ?? ""} `}${speakerName}${` ${locs[`postfix.${postfix}`] ?? ""}`}` : ".";
|
|
30
|
+
const transition = isRealForce ? 0 : PARAMS.INTERFACE.TRANSITION;
|
|
31
|
+
const speakersInfo = PARAMS.TEXT.SPEAKERS_INFO as Record<string, InterfaceSpeakerInfo>;
|
|
32
|
+
const speakerInfo = speakersInfo[speaker] || speakersInfo[PARAMS.TEXT.DEFAULT_SPEAKER_NAME] || {};
|
|
33
|
+
|
|
34
|
+
const { color, opacity = 1, speakerColor = "white" } = speakerInfo;
|
|
35
|
+
|
|
36
|
+
const propsCommon = useMemo(
|
|
37
|
+
() => ({ isForce: isRealForce, transition, tokensVisible, tokens, wall, uid }),
|
|
38
|
+
[isRealForce, transition, tokensVisible, tokens, wall, uid],
|
|
39
|
+
);
|
|
40
|
+
const propsSpeaker = useMemo(() => ({ speakerText, speakerName, speakerColor }), [speakerText, speakerName, speakerColor]);
|
|
41
|
+
const propsText = useMemo(() => ({ opacity, color }), [opacity, color]);
|
|
42
|
+
const propsView = useMemo(() => ({ ...propsCommon, ...propsSpeaker, ...propsText }), [propsCommon, propsSpeaker, propsText]);
|
|
43
|
+
|
|
44
|
+
const propsBackdrop = useMemo(() => ({ view, transition, ...props }), [view, transition, props]);
|
|
45
|
+
const propsDialog = useMemo(() => ({ isViewActive: view === "adv", ...propsView, ...props }), [view, propsView, props]);
|
|
46
|
+
const propsLine = useMemo(() => ({ isViewActive: view === "line", ...propsView, ...props }), [view, propsView, props]);
|
|
47
|
+
const propsWall = useMemo(() => ({ isViewActive: view === "wall", ...propsView, ...props }), [view, propsView, props]);
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<Screen
|
|
51
|
+
isShow={isShow}
|
|
52
|
+
isForce={isRealForce}
|
|
53
|
+
isHidden={!isVisible}
|
|
54
|
+
isDisableAutoread={false}
|
|
55
|
+
isAllowAutoread={Boolean(isShow && isVisible)}
|
|
56
|
+
isIgnoreOnScreenshot={false}
|
|
57
|
+
transition={transition}
|
|
58
|
+
zIndex={PARAMS.INTERFACE.ZINDEX}
|
|
59
|
+
onClick={onClick}
|
|
60
|
+
>
|
|
61
|
+
<InterfaceBackdrop {...propsBackdrop} />
|
|
62
|
+
<InterfaceViewDialog {...propsDialog} />
|
|
63
|
+
<InterfaceViewLine {...propsLine} />
|
|
64
|
+
<InterfaceViewWall {...propsWall} />
|
|
65
|
+
</Screen>
|
|
66
|
+
);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const render: ViewRenderFunc<InterfacePluginState> = createRenderFunc(Interface);
|
package/tsconfig.json
ADDED
package/const/events.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
export const SUBSCRIBE_EVENTS = {
|
|
2
|
-
SHOW: "vne:interface:show",
|
|
3
|
-
HIDE: "vne:interface:hide",
|
|
4
|
-
|
|
5
|
-
SHOW_CHANGED: "vne:interface:show_changed",
|
|
6
|
-
|
|
7
|
-
VIEW_SHOW: "vne:interface:view_show",
|
|
8
|
-
VIEW_HIDE: "vne:interface:view_hide",
|
|
9
|
-
VIEW_UPDATE: "vne:interface:view_update",
|
|
10
|
-
|
|
11
|
-
TEXT: "vne:interface:text",
|
|
12
|
-
TEXT_HIDE: "vne:interface:text_hide",
|
|
13
|
-
TEXT_CHANGED: "vne:interface:text_changed",
|
|
14
|
-
|
|
15
|
-
SPEAKER_CHANGED: "vne:interface:speaker_changed",
|
|
16
|
-
|
|
17
|
-
VISIBLE: "vne:interface:visible",
|
|
18
|
-
VISIBLE_CHANGED: "vne:interface:visible_changed",
|
|
19
|
-
|
|
20
|
-
VIEW: "vne:interface:view",
|
|
21
|
-
VIEW_CHANGED: "vne:interface:view_changed",
|
|
22
|
-
|
|
23
|
-
HISTORY: "vne:interface:history",
|
|
24
|
-
HISTORY_BACK: "vne:interface:history_back",
|
|
25
|
-
|
|
26
|
-
GAMEMENU: "vne:interface:gamemenu",
|
|
27
|
-
|
|
28
|
-
INTERACT: "vne:interface:interact",
|
|
29
|
-
|
|
30
|
-
STATE_CHANGED: "vne:interface:state_changed",
|
|
31
|
-
};
|
package/const/params.js
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { getVneLength } from "@vnejs/uis.utils";
|
|
2
|
-
|
|
3
|
-
export const DEFAULT_VIEW = "line";
|
|
4
|
-
|
|
5
|
-
export const LOC_LABEL = "interface";
|
|
6
|
-
|
|
7
|
-
export const TRANSITION = 500;
|
|
8
|
-
export const ZINDEX = 1000;
|
|
9
|
-
|
|
10
|
-
const createBackdropProps = (opacity) => ({ type: "bottom", size: 600, transition: TRANSITION, opacity });
|
|
11
|
-
const createFlatBackdropPosition = (margin, opacity) => ({ top: margin, left: margin, right: margin, bottom: margin, transition: TRANSITION, opacity });
|
|
12
|
-
const createFlatBackdropStyle = (borderRadius) => ({ background: "rgba(0, 0, 0, 0.6)", borderRadius, transition: `${TRANSITION}ms` });
|
|
13
|
-
|
|
14
|
-
export const VIEW_PROPS = {
|
|
15
|
-
adv: {
|
|
16
|
-
backdrop: { props: createBackdropProps(1), flatPosition: createFlatBackdropPosition(0, 0), flatStyle: createFlatBackdropStyle(0) },
|
|
17
|
-
position: { bottom: 144, left: 600, right: 600 },
|
|
18
|
-
flex: { direction: "column", gap: 24 },
|
|
19
|
-
speaker: { size: 72, weight: "bold" },
|
|
20
|
-
text: { size: 60, height: 300 },
|
|
21
|
-
},
|
|
22
|
-
wall: {
|
|
23
|
-
backdrop: { props: createBackdropProps(0), flatPosition: createFlatBackdropPosition(120, 1), flatStyle: createFlatBackdropStyle(getVneLength(48)) },
|
|
24
|
-
position: { top: 180, left: 180, right: 180, bottom: 264 },
|
|
25
|
-
flex: { direction: "column", gap: 24 },
|
|
26
|
-
scrollBar: { height: 1680, scrollToEnd: true, hideScrolbars: true, disableScroll: true },
|
|
27
|
-
speaker: { size: 72, weight: "bold" },
|
|
28
|
-
text: { size: 60 },
|
|
29
|
-
},
|
|
30
|
-
line: {
|
|
31
|
-
backdrop: { props: createBackdropProps(0), flatPosition: createFlatBackdropPosition(0, 1), flatStyle: createFlatBackdropStyle(0) },
|
|
32
|
-
position: { isCentered: true },
|
|
33
|
-
flex: { direction: "column", gap: 60 },
|
|
34
|
-
speaker: { size: 72, weight: "bold" },
|
|
35
|
-
text: { isCentered: true, size: 60, width: 3120 },
|
|
36
|
-
},
|
|
37
|
-
};
|
package/index.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { regPlugin } from "@vnejs/shared";
|
|
2
|
-
|
|
3
|
-
import { SUBSCRIBE_EVENTS } from "./const/events";
|
|
4
|
-
import * as params from "./const/params";
|
|
5
|
-
|
|
6
|
-
import { InterfaceController } from "./modules/controller";
|
|
7
|
-
import { Interface } from "./modules/interface";
|
|
8
|
-
import { InterfaceView } from "./modules/view";
|
|
9
|
-
|
|
10
|
-
regPlugin("INTERFACE", { events: SUBSCRIBE_EVENTS, params }, [InterfaceController, Interface, InterfaceView]);
|
package/modules/view.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { ModuleView } from "@vnejs/module.components";
|
|
2
|
-
|
|
3
|
-
import { render } from "../view";
|
|
4
|
-
|
|
5
|
-
export class InterfaceView extends ModuleView {
|
|
6
|
-
name = "interface.view";
|
|
7
|
-
|
|
8
|
-
locLabel = this.PARAMS.INTERFACE.LOC_LABEL;
|
|
9
|
-
animationTime = this.PARAMS.INTERFACE.TRANSITION;
|
|
10
|
-
updateEvent = this.EVENTS.INTERFACE.VIEW_UPDATE;
|
|
11
|
-
|
|
12
|
-
renderFunc = render;
|
|
13
|
-
updateHandler = this.onUpdateStoreComponent;
|
|
14
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { useMemo } from "react";
|
|
2
|
-
|
|
3
|
-
import { Backdrop, PositionBox } from "@vnejs/uis.react";
|
|
4
|
-
|
|
5
|
-
export const InterfaceBackdrop = ({ view = "", transition = 0, ...props }) => {
|
|
6
|
-
const propsByView = useMemo(() => props.PARAMS.INTERFACE.VIEW_PROPS[view]?.backdrop || {}, [view]);
|
|
7
|
-
|
|
8
|
-
const propsBackdrop = useMemo(() => ({ ...propsByView.props, transition }), [propsByView, transition]);
|
|
9
|
-
const propsPosition = useMemo(() => ({ ...propsByView.flatPosition, transition }), [propsByView, transition]);
|
|
10
|
-
|
|
11
|
-
const styleFlatBackdrop = useMemo(() => ({ ...propsByView.flatStyle, width: "100%", height: "100%", transition: `${transition}ms` }), [propsByView]);
|
|
12
|
-
|
|
13
|
-
return (
|
|
14
|
-
<>
|
|
15
|
-
<Backdrop {...propsBackdrop} />
|
|
16
|
-
|
|
17
|
-
<PositionBox {...propsPosition}>
|
|
18
|
-
<div style={styleFlatBackdrop} />
|
|
19
|
-
</PositionBox>
|
|
20
|
-
</>
|
|
21
|
-
);
|
|
22
|
-
};
|