@vnejs/plugins.views.screens.history 0.1.8
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/const/events.js +14 -0
- package/const/params.js +11 -0
- package/index.js +10 -0
- package/modules/controller.js +49 -0
- package/modules/history.js +66 -0
- package/modules/view.js +14 -0
- package/package.json +17 -0
- package/view/components/HistoryClose.jsx +15 -0
- package/view/components/HistoryLines.jsx +53 -0
- package/view/components/index.js +2 -0
- package/view/index.jsx +27 -0
package/const/events.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const SUBSCRIBE_EVENTS = {
|
|
2
|
+
GET: "vne:history:get",
|
|
3
|
+
ADD: "vne:history:add",
|
|
4
|
+
LOAD: "vne:history:load",
|
|
5
|
+
BACK: "vne:history:back",
|
|
6
|
+
KEYS: "vne:history:keys",
|
|
7
|
+
CLEAR: "vne:history:clear",
|
|
8
|
+
|
|
9
|
+
HIDE: "vne:history:hide",
|
|
10
|
+
SHOW: "vne:history:show",
|
|
11
|
+
CLICK: "vne:history:click",
|
|
12
|
+
UPDATE: "vne:history:update",
|
|
13
|
+
ACCEPT: "vne:history:accept",
|
|
14
|
+
};
|
package/const/params.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const MAX_LENGTH = 50;
|
|
2
|
+
|
|
3
|
+
export const ZINDEX = 2000;
|
|
4
|
+
export const TRANSITION = 300;
|
|
5
|
+
export const LOC_LABEL = "history";
|
|
6
|
+
|
|
7
|
+
export const VIEW_PROPS = {
|
|
8
|
+
screen: { isDisableAutoread: true, withBlur: true, withDark: true, zIndex: ZINDEX, transition: TRANSITION },
|
|
9
|
+
lines: { position: { top: 120, left: 120, right: 120 }, controls: { wrapHeight: 1800, withScrollbar: true, flexGap: 36, textSize: 60, textMarginTop: 36 } },
|
|
10
|
+
close: { position: { bottom: 120, left: 120 }, text: { size: 60 } },
|
|
11
|
+
};
|
package/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { regPlugin } from "@vnejs/shared";
|
|
2
|
+
|
|
3
|
+
import { SUBSCRIBE_EVENTS } from "./const/events";
|
|
4
|
+
import * as params from "./const/params";
|
|
5
|
+
|
|
6
|
+
import { HistoryController } from "./modules/controller";
|
|
7
|
+
import { History } from "./modules/history";
|
|
8
|
+
import { HistoryView } from "./modules/view";
|
|
9
|
+
|
|
10
|
+
regPlugin("HISTORY", { events: SUBSCRIBE_EVENTS, params }, [HistoryController, History, HistoryView]);
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { ModuleController } from "@vnejs/module.components";
|
|
2
|
+
|
|
3
|
+
export class HistoryController extends ModuleController {
|
|
4
|
+
name = "history.controller";
|
|
5
|
+
|
|
6
|
+
emitHide = () => this.emit(this.EVENTS.HISTORY.HIDE);
|
|
7
|
+
|
|
8
|
+
updateEvent = this.EVENTS.HISTORY.UPDATE;
|
|
9
|
+
controls = {
|
|
10
|
+
[this.CONST.CONTROLS.BUTTONS.BACK]: this.emitHide,
|
|
11
|
+
[this.CONST.CONTROLS.BUTTONS.MENU]: this.emitHide,
|
|
12
|
+
[this.CONST.CONTROLS.BUTTONS.GAMEMENU]: this.emitHide,
|
|
13
|
+
[this.CONST.CONTROLS.BUTTONS.ARROW_UP]: this.decCurrentItem,
|
|
14
|
+
[this.CONST.CONTROLS.BUTTONS.ARROW_BOTTOM]: this.incCurrentItem,
|
|
15
|
+
[this.CONST.CONTROLS.BUTTONS.ACCEPT]: () => this.emit(this.EVENTS.HISTORY.ACCEPT),
|
|
16
|
+
};
|
|
17
|
+
controlsIndex = this.PARAMS.HISTORY.ZINDEX;
|
|
18
|
+
|
|
19
|
+
subscribe = () => {
|
|
20
|
+
this.on(this.EVENTS.HISTORY.SHOW, this.onShow);
|
|
21
|
+
this.on(this.EVENTS.HISTORY.HIDE, this.onHide);
|
|
22
|
+
this.on(this.EVENTS.HISTORY.ACCEPT, this.onAccept);
|
|
23
|
+
this.on(this.EVENTS.HISTORY.CLICK, this.onClick);
|
|
24
|
+
|
|
25
|
+
this.on(this.EVENTS.STATE.SET, this.onStateSet);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
beforeShow = async () => {
|
|
29
|
+
this.maxCurrentItem = this.globalState.history.history.length - 1;
|
|
30
|
+
|
|
31
|
+
this.updateState({
|
|
32
|
+
historyLocs: await Promise.all(this.globalState.history.history.map(this.getHistoryText)),
|
|
33
|
+
historyKeys: await this.emitOne(this.EVENTS.HISTORY.KEYS),
|
|
34
|
+
history: this.globalState.history.history,
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
afterHide = () => this.setDefaultState();
|
|
38
|
+
|
|
39
|
+
onAccept = () => this.currentItem !== null && this.emit(this.EVENTS.HISTORY.CLICK, { uid: this.globalState.history.history[this.currentItem].uid });
|
|
40
|
+
onClick = ({ uid } = {}) => this.state.historyKeys.includes(uid) && this.emit(this.EVENTS.HISTORY.LOAD, { uid });
|
|
41
|
+
|
|
42
|
+
onStateSet = () => this.emit(this.EVENTS.HISTORY.HIDE, { isForce: true });
|
|
43
|
+
|
|
44
|
+
getHistoryText = async ({ label, text, args, uid } = {}) => {
|
|
45
|
+
const state = await this.emitOne(this.EVENTS.HISTORY.GET, { uid });
|
|
46
|
+
|
|
47
|
+
return this.emitOne(this.EVENTS.TEXT.REPLACE, { label, text, args, state });
|
|
48
|
+
};
|
|
49
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { Module } from "@vnejs/module";
|
|
2
|
+
|
|
3
|
+
export class History extends Module {
|
|
4
|
+
name = "history";
|
|
5
|
+
|
|
6
|
+
isLoadInProcess = false;
|
|
7
|
+
|
|
8
|
+
subscribe = () => {
|
|
9
|
+
this.on(this.EVENTS.HISTORY.ADD, this.onHistoryAdd);
|
|
10
|
+
this.on(this.EVENTS.HISTORY.GET, this.onHistoryGet);
|
|
11
|
+
this.on(this.EVENTS.HISTORY.LOAD, this.onHistoryLoad);
|
|
12
|
+
this.on(this.EVENTS.HISTORY.BACK, this.onHistoryBack);
|
|
13
|
+
this.on(this.EVENTS.HISTORY.KEYS, this.onHistoryKeys);
|
|
14
|
+
|
|
15
|
+
this.on(this.EVENTS.STATE.CLEAR, this.setDefaultState);
|
|
16
|
+
this.on(this.EVENTS.STATE.SET, this.onStateSet);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
init = () => this.emit(this.EVENTS.MEMORY.REG, { module: this.name });
|
|
20
|
+
|
|
21
|
+
onHistoryAdd = async (historyObj = {}) => {
|
|
22
|
+
if (this.isLoadInProcess) return;
|
|
23
|
+
|
|
24
|
+
const [state, uid] = await Promise.all([this.emitOne(this.EVENTS.STATE.GET), this.emitOne(this.EVENTS.VENDORS.UID)]);
|
|
25
|
+
|
|
26
|
+
this.emit(this.EVENTS.LOGS.EMIT, { module: this.name, value: { action: "add", uid } });
|
|
27
|
+
|
|
28
|
+
await this.emit(this.EVENTS.MEMORY.SET, { module: this.name, key: uid, value: state });
|
|
29
|
+
|
|
30
|
+
this.state.history.push({ uid, ...historyObj });
|
|
31
|
+
|
|
32
|
+
if (this.state.history.length > this.PARAMS.HISTORY.MAX_LENGTH)
|
|
33
|
+
this.state.history = this.state.history.slice(this.state.history.length - this.PARAMS.HISTORY.MAX_LENGTH, this.state.history.length);
|
|
34
|
+
|
|
35
|
+
this.updateHistoryKeys();
|
|
36
|
+
};
|
|
37
|
+
onHistoryLoad = async ({ uid } = {}) => {
|
|
38
|
+
this.isLoadInProcess = true;
|
|
39
|
+
|
|
40
|
+
this.emit(this.EVENTS.LOGS.EMIT, { module: this.name, value: { action: "load start", uid } });
|
|
41
|
+
|
|
42
|
+
const state = await this.emitOne(this.EVENTS.HISTORY.GET, { uid });
|
|
43
|
+
|
|
44
|
+
if (!state) return void this.emit(this.EVENTS.LOGS.EMIT, { module: this.name, value: { action: "load deleted", uid } });
|
|
45
|
+
|
|
46
|
+
await this.emit(this.EVENTS.STATE.LOAD, await this.emitOne(this.EVENTS.VENDORS.CLONE, state));
|
|
47
|
+
|
|
48
|
+
this.emit(this.EVENTS.SCENARIO.LABEL_GET, { label: state.scenario.label });
|
|
49
|
+
|
|
50
|
+
this.isLoadInProcess = false;
|
|
51
|
+
|
|
52
|
+
this.emit(this.EVENTS.LOGS.EMIT, { module: this.name, value: { action: "load end", uid } });
|
|
53
|
+
|
|
54
|
+
this.updateHistoryKeys();
|
|
55
|
+
};
|
|
56
|
+
onHistoryBack = () =>
|
|
57
|
+
!this.isLoadInProcess && this.state.history.length && this.emit(this.EVENTS.HISTORY.LOAD, { uid: this.state.history[this.state.history.length - 1].uid });
|
|
58
|
+
onHistoryKeys = () => this.emitOne(this.EVENTS.MEMORY.KEYS, { module: this.name });
|
|
59
|
+
onHistoryGet = ({ uid = "" } = {}) => this.emitOne(this.EVENTS.MEMORY.GET, { module: this.name, key: uid });
|
|
60
|
+
|
|
61
|
+
onStateSet = async ({ [this.name]: state } = {}) => this.setState(await this.emitOne(this.EVENTS.VENDORS.CLONE, state));
|
|
62
|
+
|
|
63
|
+
updateHistoryKeys = () => Promise.all(this.state.history.map(({ uid = "" } = {}) => this.emitOne(this.EVENTS.HISTORY.GET, { uid })));
|
|
64
|
+
|
|
65
|
+
getDefaultState = () => ({ history: [] });
|
|
66
|
+
}
|
package/modules/view.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ModuleView } from "@vnejs/module.components";
|
|
2
|
+
|
|
3
|
+
import { render } from "../view";
|
|
4
|
+
|
|
5
|
+
export class HistoryView extends ModuleView {
|
|
6
|
+
name = "history.view";
|
|
7
|
+
|
|
8
|
+
locLabel = this.PARAMS.HISTORY.LOC_LABEL;
|
|
9
|
+
animationTime = this.PARAMS.HISTORY.TRANSITION;
|
|
10
|
+
updateEvent = this.EVENTS.HISTORY.UPDATE;
|
|
11
|
+
|
|
12
|
+
renderFunc = render;
|
|
13
|
+
updateHandler = this.onUpdateStoreComponent;
|
|
14
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vnejs/plugins.views.screens.history",
|
|
3
|
+
"version": "0.1.8",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
7
|
+
"publish:major:plugin": "npm run publish:major",
|
|
8
|
+
"publish:minor:plugin": "npm run publish:minor",
|
|
9
|
+
"publish:patch:plugin": "npm run publish:patch",
|
|
10
|
+
"publish:major": "npm version major && npm publish --access public",
|
|
11
|
+
"publish:minor": "npm version minor && npm publish --access public",
|
|
12
|
+
"publish:patch": "npm version patch && npm publish --access public"
|
|
13
|
+
},
|
|
14
|
+
"author": "",
|
|
15
|
+
"license": "ISC",
|
|
16
|
+
"description": ""
|
|
17
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { useCallback, useMemo } from "react";
|
|
2
|
+
|
|
3
|
+
import { PositionBox, Text } from "@vnejs/uis.react";
|
|
4
|
+
|
|
5
|
+
export const HistoryClose = ({ locs = {}, ...props } = {}) => {
|
|
6
|
+
const onClick = useCallback(() => props.emit(props.EVENTS.HISTORY.HIDE), []);
|
|
7
|
+
|
|
8
|
+
const propsText = useMemo(() => ({ ...props.PARAMS.HISTORY.VIEW_PROPS.close.text, text: locs.back, onClick }), [locs]);
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<PositionBox {...props.PARAMS.HISTORY.VIEW_PROPS.close.position}>
|
|
12
|
+
<Text {...propsText} />
|
|
13
|
+
</PositionBox>
|
|
14
|
+
);
|
|
15
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { useCallback, useEffect, useMemo, useRef } from "react";
|
|
2
|
+
|
|
3
|
+
import { PositionBox, Text, TextControls } from "@vnejs/uis.react";
|
|
4
|
+
|
|
5
|
+
const scrollToBottom = (scrollbarWrapRef) => {
|
|
6
|
+
if (!scrollbarWrapRef.current) return requestAnimationFrame(() => scrollToBottom(scrollbarWrapRef));
|
|
7
|
+
if (scrollbarWrapRef.current.clientHeight === scrollbarWrapRef.current.scrollHeight || scrollbarWrapRef.current.scrollTop !== 0) return;
|
|
8
|
+
|
|
9
|
+
scrollbarWrapRef.current.scrollTop = 9999999;
|
|
10
|
+
requestAnimationFrame(() => scrollToBottom(scrollbarWrapRef));
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const HistoryLines = ({ isShow = false, history = [], currentItem = null, historyLocs = [], historyKeys = [], locs = {}, ...props } = {}) => {
|
|
14
|
+
const scrollbarWrapRef = useRef(null);
|
|
15
|
+
|
|
16
|
+
const onClick = useCallback((uid) => historyKeys.includes(uid) && props.emit(props.EVENTS.HISTORY.CLICK, { uid }), [historyKeys]);
|
|
17
|
+
|
|
18
|
+
const mapTexts = useCallback(
|
|
19
|
+
({ text, uid, speaker, meet }, i) => {
|
|
20
|
+
const speakers = props.PARAMS.TEXT.SPEAKERS_INFO;
|
|
21
|
+
|
|
22
|
+
const { speakerColor = "white" } = speakers[speaker] || speakers.default;
|
|
23
|
+
const speakerName = locs[`speaker.${speaker}.${meet}`];
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
text: (historyLocs && historyLocs[i]) || text,
|
|
27
|
+
value: uid,
|
|
28
|
+
textPrefix: speakerName ? `${speakerName}: ` : undefined,
|
|
29
|
+
colorPrefix: speakerColor,
|
|
30
|
+
weightPrefix: Text.WEIGHT.BOLD,
|
|
31
|
+
isHoverable: Boolean(historyKeys.find((key) => key === uid)),
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
[historyLocs, historyKeys],
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (isShow) requestAnimationFrame(() => scrollToBottom(scrollbarWrapRef));
|
|
39
|
+
}, [isShow]);
|
|
40
|
+
|
|
41
|
+
const texts = useMemo(() => history.map(mapTexts), [history, mapTexts]);
|
|
42
|
+
|
|
43
|
+
const propsView = props.PARAMS.HISTORY.VIEW_PROPS.lines;
|
|
44
|
+
|
|
45
|
+
const propsControlsCommon = useMemo(() => ({ ...propsView.controls, onClick, scrollbarWrapRef }), [scrollbarWrapRef]);
|
|
46
|
+
const propsControls = useMemo(() => ({ ...propsControlsCommon, texts, selectedIndex: currentItem }), [texts, currentItem]);
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<PositionBox {...propsView.position}>
|
|
50
|
+
<TextControls {...propsControls} />
|
|
51
|
+
</PositionBox>
|
|
52
|
+
);
|
|
53
|
+
};
|
package/view/index.jsx
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { useEffect, useMemo, useState } from "react";
|
|
2
|
+
import { createRoot } from "react-dom/client";
|
|
3
|
+
|
|
4
|
+
import { Screen } from "@vnejs/uis.react";
|
|
5
|
+
|
|
6
|
+
import { HistoryClose, HistoryLines } from "./components";
|
|
7
|
+
|
|
8
|
+
const History = ({ store, onMount, ...props } = {}) => {
|
|
9
|
+
const [{ isShow = false, isForce = false, locs = {}, history = [], historyLocs = [], historyKeys = [], currentItem = null }, setState] = useState({});
|
|
10
|
+
|
|
11
|
+
useEffect(() => store.subscribe(setState), []);
|
|
12
|
+
useEffect(() => void onMount(), []);
|
|
13
|
+
|
|
14
|
+
const propsScreen = useMemo(() => ({ ...props.PARAMS.HISTORY.VIEW_PROPS.screen, isShow, isForce }), [isShow, isForce]);
|
|
15
|
+
const propsHistory = useMemo(() => ({ history, historyLocs, historyKeys }), [history, historyLocs, historyKeys]);
|
|
16
|
+
const propsLines = useMemo(() => ({ ...props, ...propsHistory, isShow, currentItem, locs }), [propsHistory, isShow, currentItem, locs]);
|
|
17
|
+
const propsClose = useMemo(() => ({ ...props, locs }), [locs]);
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<Screen {...propsScreen}>
|
|
21
|
+
<HistoryLines {...propsLines} />
|
|
22
|
+
<HistoryClose {...propsClose} />
|
|
23
|
+
</Screen>
|
|
24
|
+
);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const render = (props, root) => createRoot(root).render(<History {...props} />);
|