@ray-js/t-agent-ui-ray 0.2.1-beta.3 → 0.2.2-beta-2

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.
Files changed (38) hide show
  1. package/dist/ChatContainer/index.d.ts +2 -1
  2. package/dist/ChatContainer/index.js +53 -48
  3. package/dist/EchartsBlockRender/index.js +6 -4
  4. package/dist/EchartsBlockRender/index.rjs +35 -9
  5. package/dist/MessageInput/MessageInputAIStream/WaveformVisualizer.d.ts +2 -2
  6. package/dist/MessageInput/MessageInputAIStream/WaveformVisualizer.js +30 -23
  7. package/dist/MessageInput/MessageInputAIStream/index.d.ts +8 -0
  8. package/dist/MessageInput/MessageInputAIStream/index.js +52 -41
  9. package/dist/MessageInput/index.d.ts +2 -1
  10. package/dist/MessageInput/index.js +2 -1
  11. package/dist/MessageList/LazyView.d.ts +9 -0
  12. package/dist/MessageList/LazyView.js +57 -0
  13. package/dist/MessageList/ScrollBottomView.d.ts +47 -0
  14. package/dist/MessageList/ScrollBottomView.js +205 -0
  15. package/dist/MessageList/index.d.ts +5 -2
  16. package/dist/MessageList/index.js +26 -88
  17. package/dist/MessageList/index.less +15 -4
  18. package/dist/MessageRender/index.less +1 -0
  19. package/dist/TileRender/index.js +5 -3
  20. package/dist/contexts.d.ts +18 -6
  21. package/dist/contexts.js +5 -17
  22. package/dist/hooks/context.d.ts +4 -4
  23. package/dist/hooks/context.js +13 -4
  24. package/dist/hooks/useStableCallback.d.ts +1 -0
  25. package/dist/hooks/useStableCallback.js +13 -0
  26. package/dist/tiles/BubbleTile/index.js +4 -4
  27. package/dist/tiles/ExecuteCardTile/index.d.ts +1 -8
  28. package/dist/tiles/ExecuteCardTile/index.js +7 -15
  29. package/dist/tiles/ExecuteCardTile/index.less +177 -151
  30. package/dist/tiles/OperateCardTile/index.d.ts +2 -6
  31. package/dist/tiles/OperateCardTile/index.js +6 -4
  32. package/dist/tiles/types.d.ts +31 -0
  33. package/dist/tiles/types.js +5 -0
  34. package/dist/types.d.ts +1 -0
  35. package/dist/utils/createSharedStore.d.ts +4 -0
  36. package/dist/utils/createSharedStore.js +64 -0
  37. package/dist/utils/index.js +1 -1
  38. package/package.json +2 -2
@@ -1,11 +1,12 @@
1
1
  import './index.less';
2
2
  import React, { PropsWithChildren } from 'react';
3
3
  import { ChatAgent } from '@ray-js/t-agent';
4
+ import { UIChatAgent } from '../contexts';
4
5
  import { RenderOptions } from '../types';
5
6
  export default function ChatContainer<T extends ChatAgent<any>>(props: PropsWithChildren<{
6
7
  createAgent: () => T;
7
8
  renderOptions?: RenderOptions;
8
9
  className?: string;
9
10
  style?: React.CSSProperties;
10
- agentRef?: React.MutableRefObject<T>;
11
+ agentRef?: React.MutableRefObject<UIChatAgent | null>;
11
12
  }>): React.JSX.Element;
@@ -4,10 +4,10 @@ import "core-js/modules/esnext.iterator.filter.js";
4
4
  import "core-js/modules/esnext.iterator.map.js";
5
5
  import "core-js/modules/web.dom-collections.iterator.js";
6
6
  import './index.less';
7
- import React, { useEffect, useMemo, useState } from 'react';
7
+ import React, { useCallback, useEffect, useMemo, useState } from 'react';
8
8
  import { View } from '@ray-js/components';
9
9
  import cx from 'clsx';
10
- import { ChatAgentContext, MessageContext, RenderContext } from '../contexts';
10
+ import { SharedProvider } from '../contexts';
11
11
  import { defaultRenderOptions } from '../renderOption';
12
12
  import logger from '../logger';
13
13
  import { systemInfo } from '../utils';
@@ -27,6 +27,8 @@ export default function ChatContainer(props) {
27
27
  style
28
28
  } = props;
29
29
  const [messages, setMessages] = useState([]);
30
+ const [tickValue, setRenderTick] = useState(0);
31
+ const notifyHeightChanged = useCallback(() => setRenderTick(t => t + 1), []);
30
32
  const [agent] = useState(() => {
31
33
  const agent = createAgent();
32
34
  if (!agent.plugins.ui) {
@@ -41,9 +43,6 @@ export default function ChatContainer(props) {
41
43
  });
42
44
  return agent;
43
45
  });
44
- if (props.agentRef) {
45
- props.agentRef.current = agent;
46
- }
47
46
  const uiAgent = useMemo(() => {
48
47
  const session = {
49
48
  get: agent.session.get,
@@ -58,63 +57,72 @@ export default function ChatContainer(props) {
58
57
  });
59
58
  return {
60
59
  session,
61
- plugins: agent.plugins,
60
+ plugins: {
61
+ ui: agent.plugins.ui
62
+ },
62
63
  pushInputBlocks: agent.pushInputBlocks,
63
64
  emitTileEvent: agent.emitTileEvent,
64
65
  removeMessage: agent.removeMessage
65
66
  };
66
67
  }, [agent]);
68
+ if (props.agentRef) {
69
+ props.agentRef.current = uiAgent;
70
+ }
67
71
  useEffect(() => {
68
72
  const {
69
73
  onEvent,
70
74
  emitEvent
71
75
  } = agent.plugins.ui;
72
- const offMessageListInit = onEvent('messageListInit', _ref => {
76
+ const offMessageListInit = onEvent('messageListInit', async _ref => {
73
77
  let {
74
78
  messages
75
79
  } = _ref;
76
80
  setMessages(messages);
81
+ notifyHeightChanged();
77
82
  emitEvent('scrollToBottom', {
78
83
  animation: false
79
84
  });
80
85
  });
81
- const offMessageChange = onEvent('messageChange', _ref2 => {
86
+ const offMessageChange = onEvent('messageChange', async _ref2 => {
82
87
  let {
83
88
  type,
84
89
  message
85
90
  } = _ref2;
86
91
  switch (type) {
87
92
  case 'show':
88
- setMessages(prev => [...prev, message]);
89
- emitEvent('scrollToBottom', {
90
- animation: false
91
- });
92
- break;
93
+ {
94
+ setMessages(prev => [...prev, message]);
95
+ notifyHeightChanged();
96
+ emitEvent('scrollToBottom', {
97
+ animation: false
98
+ });
99
+ break;
100
+ }
93
101
  case 'update':
94
- setMessages(prev => {
95
- if (systemInfo.platform === 'android') {
96
- var _prev;
97
- // Android 上有兼容问题,需要手动滚动到底部
98
- if (((_prev = prev[prev.length - 1]) === null || _prev === void 0 ? void 0 : _prev.id) === message.id) {
99
- // 是最后一条消息,滚动到最底部
100
- emitEvent('scrollToBottom', {
101
- animation: false,
102
- follow: true
103
- });
104
- }
105
- }
106
- return prev.map(item => {
107
- if (item.id === message.id) {
108
- return message;
109
- }
110
- return item;
102
+ {
103
+ setMessages(prev => {
104
+ return prev.map(item => {
105
+ if (item.id === message.id) {
106
+ notifyHeightChanged();
107
+ return message;
108
+ }
109
+ return item;
110
+ });
111
111
  });
112
- });
113
- break;
112
+ break;
113
+ }
114
114
  case 'remove':
115
- setMessages(prev => {
116
- return prev.filter(item => item.id !== message.id);
117
- });
115
+ {
116
+ setMessages(prev => {
117
+ return prev.filter(item => item.id !== message.id);
118
+ });
119
+ notifyHeightChanged();
120
+ emitEvent('scrollToBottom', {
121
+ animation: false,
122
+ follow: true
123
+ });
124
+ break;
125
+ }
118
126
  }
119
127
  });
120
128
  return () => {
@@ -122,12 +130,6 @@ export default function ChatContainer(props) {
122
130
  offMessageChange();
123
131
  };
124
132
  }, [agent]);
125
- const messageValue = useMemo(() => {
126
- return {
127
- messages,
128
- keyboardHeight
129
- };
130
- }, [messages, keyboardHeight]);
131
133
  useEffect(() => {
132
134
  logger.debug('ChatProvider agent.start');
133
135
  agent.start().then(() => {
@@ -181,11 +183,14 @@ export default function ChatContainer(props) {
181
183
  className: cx('t-agent-chat-container', className, {
182
184
  't-agent-chat-container-keyboard-show': keyboardHeight > 0
183
185
  })
184
- }, /*#__PURE__*/React.createElement(ChatAgentContext.Provider, {
185
- value: uiAgent
186
- }, /*#__PURE__*/React.createElement(RenderContext.Provider, {
187
- value: renderOptions
188
- }, /*#__PURE__*/React.createElement(MessageContext.Provider, {
189
- value: messageValue
190
- }, children))));
186
+ }, /*#__PURE__*/React.createElement(SharedProvider, {
187
+ value: {
188
+ agent: uiAgent,
189
+ messages,
190
+ notifyHeightChanged,
191
+ keyboardHeight,
192
+ tickValue,
193
+ renderOptions
194
+ }
195
+ }, children));
191
196
  }
@@ -1,6 +1,5 @@
1
1
  import Render from './index.rjs';
2
2
  import logger from '../logger';
3
- import { systemInfo } from '../utils';
4
3
 
5
4
  // eslint-disable-next-line no-undef
6
5
  Component({
@@ -47,9 +46,12 @@ Component({
47
46
  });
48
47
  const data = JSON.parse(content);
49
48
  if (data.option) {
50
- // eslint-disable-next-line no-undef
51
- const pixelRatio = systemInfo.pixelRatio;
52
- this.rjs.update(this.data.canvasId, pixelRatio, data.option);
49
+ if (!this.isInit) {
50
+ this.rjs.init(this.data.canvasId, data.option);
51
+ this.isInit = true;
52
+ } else {
53
+ this.rjs.update(data.option);
54
+ }
53
55
  this.setData({
54
56
  loading: false,
55
57
  error: false
@@ -1,15 +1,41 @@
1
1
  export default Render({
2
2
  myChart: null,
3
- async update(canvasId, devicePixelRatio, option) {
4
- if (!this.myChart) {
3
+ option: null,
4
+ async init(canvasId, option) {
5
+ const { pixelRatio } = this.instance.getSystemInfo()
6
+ this.option = option
7
+ try {
5
8
  const canvas = await this.instance.getCanvasById(canvasId)
6
- const echarts = await requirePlugin('rjs://echarts')
7
-
8
- this.myChart = echarts.init(canvas, undefined, {
9
- devicePixelRatio,
10
- })
9
+ if (canvas) {
10
+ const echarts = await requirePlugin('rjs://echarts')
11
+ const myChart = echarts.init(canvas, undefined, {
12
+ devicePixelRatio: pixelRatio,
13
+ })
14
+ myChart.setOption(this.option, true)
15
+ this.myChart = myChart;
16
+ }
17
+ } catch (err) {
18
+ // ignore
11
19
  }
12
- // 使用刚指定的配置项和数据显示图表。
13
- this.myChart.setOption(option, true)
20
+ },
21
+ async update(option) {
22
+ this.option = option
23
+ if (this.myChart) {
24
+ this.myChart.setOption(this.option, true)
25
+ }
26
+ // const { pixelRatio } = this.instance.getSystemInfo()
27
+ // if (!this.myChart) {
28
+ // const canvas = await this.instance.getCanvasById(canvasId)
29
+ // console.log(`EchartsBlockRender init render, ${canvasId}`, Object.keys(canvas))
30
+ // if (canvas) {
31
+ // const echarts = await requirePlugin('rjs://echarts')
32
+ // this.myChart = echarts.init(canvas, undefined, {
33
+ // devicePixelRatio: pixelRatio,
34
+ // })
35
+ // }
36
+ // }
37
+ // console.log(`EchartsBlockRender set option, ${canvasId}`)
38
+ // // 使用刚指定的配置项和数据显示图表。
39
+ // this.myChart.setOption(option, true)
14
40
  },
15
41
  })
@@ -1,4 +1,4 @@
1
1
  import React from 'react';
2
- export declare const WaveformVisualizer: ({ amplitudeCount }: {
2
+ export declare const WaveformVisualizer: React.MemoExoticComponent<({ amplitudeCount }: {
3
3
  amplitudeCount: number;
4
- }) => React.JSX.Element;
4
+ }) => React.JSX.Element>;
@@ -1,10 +1,9 @@
1
1
  import "core-js/modules/esnext.iterator.constructor.js";
2
2
  import "core-js/modules/esnext.iterator.map.js";
3
3
  import "core-js/modules/web.dom-collections.iterator.js";
4
- import React, { useState } from 'react';
4
+ import React, { useEffect, useState } from 'react';
5
5
  import { View } from '@ray-js/ray';
6
- import { useOnEvent } from '../../hooks';
7
- export const WaveformVisualizer = _ref => {
6
+ export const WaveformVisualizer = /*#__PURE__*/React.memo(_ref => {
8
7
  let {
9
8
  amplitudeCount
10
9
  } = _ref;
@@ -21,27 +20,35 @@ export const WaveformVisualizer = _ref => {
21
20
  animationDelay: "".concat(index * 10, "ms")
22
21
  }
23
22
  })));
24
- useOnEvent('amplitudes', val => {
25
- const waveBase = val.body.amplitudes || [];
26
- const bars = waveBase.map((item, index) => {
27
- const value = item > 1 ? 1 : item * 100;
28
- // 将数值映射到高度范围(0-100 → 2px-20px)
29
- // const height = 2 + (value / 100) * 18;
30
- return /*#__PURE__*/React.createElement(View
31
- // eslint-disable-next-line react/no-array-index-key
32
- , {
33
- key: "asr_wave_".concat(index),
34
- className: "t-agent-message-input-waveform-bar",
35
- style: {
36
- height: "".concat(value, "%"),
37
- // 添加渐变色偏移效果
38
- animationDelay: "".concat(index * 10, "ms")
39
- }
23
+ useEffect(() => {
24
+ const handle = _ref2 => {
25
+ let {
26
+ amplitudes
27
+ } = _ref2;
28
+ const bars = (amplitudes || []).map((item, index) => {
29
+ const value = item > 1 ? 1 : item * 100;
30
+ // 将数值映射到高度范围(0-100 → 2px-20px)
31
+ // const height = 2 + (value / 100) * 18;
32
+ return /*#__PURE__*/React.createElement(View
33
+ // eslint-disable-next-line react/no-array-index-key
34
+ , {
35
+ key: "asr_wave_".concat(index),
36
+ className: "t-agent-message-input-waveform-bar",
37
+ style: {
38
+ height: "".concat(value, "%"),
39
+ // 添加渐变色偏移效果
40
+ animationDelay: "".concat(index * 10, "ms")
41
+ }
42
+ });
40
43
  });
41
- });
42
- setBars(bars);
43
- });
44
+ setBars(bars);
45
+ };
46
+ ty.aistream.onRecordAmplitudes(handle);
47
+ return () => {
48
+ ty.aistream.offRecordAmplitudes(handle);
49
+ };
50
+ }, []);
44
51
  return /*#__PURE__*/React.createElement(View, {
45
52
  className: "t-agent-message-input-waveform-container"
46
53
  }, bars);
47
- };
54
+ });
@@ -14,6 +14,14 @@ interface Props {
14
14
  attachment?: boolean | AttachmentOptions;
15
15
  maxTextLength?: number;
16
16
  maxAudioMs?: number;
17
+ onStateChange?: (state: MessageInputState) => void;
18
+ }
19
+ export declare const enum MessageInputState {
20
+ PENDING = "pending",
21
+ RECORDING = "recording",
22
+ ASR = "asr",
23
+ RESPONDING = "responding",
24
+ ABORTING = "aborting"
17
25
  }
18
26
  export default function MessageInputAIStream(props: Props): React.JSX.Element;
19
27
  export {};
@@ -17,15 +17,17 @@ import { useAttachmentInput, useChatAgent, useEmitEvent, useIsUnmounted, useOnEv
17
17
  import AsrInput from './AsrInput';
18
18
  import logger from '../../logger';
19
19
  import { systemInfo } from '../../utils';
20
+ import { useSleep } from '../../hooks/useSleep';
21
+ import { useStableCallback } from '../../hooks/useStableCallback';
20
22
  const AMPLITUDE_COUNT = 60;
21
- var InputState = /*#__PURE__*/function (InputState) {
22
- InputState["PENDING"] = "pending";
23
- InputState["RECORDING"] = "recording";
24
- InputState["ASR"] = "asr";
25
- InputState["RESPONDING"] = "responding";
26
- InputState["ABORTING"] = "aborting";
27
- return InputState;
28
- }(InputState || {});
23
+ export let MessageInputState = /*#__PURE__*/function (MessageInputState) {
24
+ MessageInputState["PENDING"] = "pending";
25
+ MessageInputState["RECORDING"] = "recording";
26
+ MessageInputState["ASR"] = "asr";
27
+ MessageInputState["RESPONDING"] = "responding";
28
+ MessageInputState["ABORTING"] = "aborting";
29
+ return MessageInputState;
30
+ }({});
29
31
  var InputAction = /*#__PURE__*/function (InputAction) {
30
32
  InputAction["SEND"] = "send";
31
33
  InputAction["RECORD"] = "record";
@@ -40,30 +42,30 @@ var InputAction = /*#__PURE__*/function (InputAction) {
40
42
  return InputAction;
41
43
  }(InputAction || {});
42
44
  const transitions = {
43
- [InputState.PENDING]: {
44
- [InputAction.SEND]: InputState.RESPONDING,
45
- [InputAction.RECORD]: InputState.RECORDING,
45
+ [MessageInputState.PENDING]: {
46
+ [InputAction.SEND]: MessageInputState.RESPONDING,
47
+ [InputAction.RECORD]: MessageInputState.RECORDING,
46
48
  // 这个变更是为了兼容 pushInputBlocks 结束的场景,没有实际意义
47
- [InputAction.TEXT_END]: InputState.PENDING
49
+ [InputAction.TEXT_END]: MessageInputState.PENDING
48
50
  },
49
- [InputState.RECORDING]: {
50
- [InputAction.RECORD_TIMEOUT]: InputState.ASR,
51
- [InputAction.RECORD_CANCEL]: InputState.PENDING,
52
- [InputAction.RECORD_CONFIRM]: InputState.ASR,
53
- [InputAction.ABORT]: InputState.ABORTING,
54
- [InputAction.ASR_ERROR]: InputState.PENDING
51
+ [MessageInputState.RECORDING]: {
52
+ [InputAction.RECORD_TIMEOUT]: MessageInputState.ASR,
53
+ [InputAction.RECORD_CANCEL]: MessageInputState.PENDING,
54
+ [InputAction.RECORD_CONFIRM]: MessageInputState.ASR,
55
+ [InputAction.ABORT]: MessageInputState.ABORTING,
56
+ [InputAction.ASR_ERROR]: MessageInputState.PENDING
55
57
  },
56
- [InputState.ASR]: {
57
- [InputAction.ASR_END]: InputState.RESPONDING,
58
- [InputAction.ASR_ERROR]: InputState.PENDING,
59
- [InputAction.ABORT]: InputState.ABORTING
58
+ [MessageInputState.ASR]: {
59
+ [InputAction.ASR_END]: MessageInputState.RESPONDING,
60
+ [InputAction.ASR_ERROR]: MessageInputState.PENDING,
61
+ [InputAction.ABORT]: MessageInputState.ABORTING
60
62
  },
61
- [InputState.RESPONDING]: {
62
- [InputAction.ABORT]: InputState.ABORTING,
63
- [InputAction.TEXT_END]: InputState.PENDING
63
+ [MessageInputState.RESPONDING]: {
64
+ [InputAction.ABORT]: MessageInputState.ABORTING,
65
+ [InputAction.TEXT_END]: MessageInputState.PENDING
64
66
  },
65
- [InputState.ABORTING]: {
66
- [InputAction.ABORT_DONE]: InputState.PENDING
67
+ [MessageInputState.ABORTING]: {
68
+ [InputAction.ABORT_DONE]: MessageInputState.PENDING
67
69
  }
68
70
  };
69
71
  export default function MessageInputAIStream(props) {
@@ -71,12 +73,11 @@ export default function MessageInputAIStream(props) {
71
73
  const t = useTranslate();
72
74
  const [text, setText] = useState('');
73
75
  const [state, setState] = useState({
74
- current: InputState.PENDING,
76
+ current: MessageInputState.PENDING,
75
77
  payload: {}
76
78
  });
77
- const dispatchRef = useRef(null);
78
79
  const initAudioRef = useRef(false);
79
- dispatchRef.current = (event, payload) => {
80
+ const dispatch = useStableCallback((event, payload) => {
80
81
  var _transitions$state$cu;
81
82
  const next = (_transitions$state$cu = transitions[state.current]) === null || _transitions$state$cu === void 0 ? void 0 : _transitions$state$cu[event];
82
83
  if (next) {
@@ -85,12 +86,14 @@ export default function MessageInputAIStream(props) {
85
86
  current: next,
86
87
  payload
87
88
  });
89
+ if (props.onStateChange) {
90
+ props.onStateChange(next);
91
+ }
88
92
  return true;
89
93
  }
90
94
  logger.error('MessageInputAIStream', "".concat(state.current, " ==").concat(event, "==> X not allowed"));
91
95
  return false;
92
- };
93
- const dispatch = (event, payload) => dispatchRef.current(event, payload);
96
+ });
94
97
  const attachmentOptions = useMemo(() => {
95
98
  const options = {
96
99
  image: true,
@@ -166,7 +169,7 @@ export default function MessageInputAIStream(props) {
166
169
  let {
167
170
  blocks
168
171
  } = _ref2;
169
- if (uploading || state.current !== InputState.PENDING) {
172
+ if (uploading || state.current !== MessageInputState.PENDING) {
170
173
  return;
171
174
  }
172
175
  if (mode !== 'text') {
@@ -193,9 +196,10 @@ export default function MessageInputAIStream(props) {
193
196
  }
194
197
  };
195
198
  let container;
196
- const canSend = text.trim().length && state.current === InputState.PENDING && !attachmentInput.uploading;
197
- const canAbort = state.current === InputState.RESPONDING || state.current === InputState.ASR;
199
+ const canSend = text.trim().length && state.current === MessageInputState.PENDING && !attachmentInput.uploading;
200
+ const canAbort = state.current === MessageInputState.RESPONDING || state.current === MessageInputState.ASR;
198
201
  const recordingFlagRef = useRef(false);
202
+ const sleep = useSleep();
199
203
  if (mode === 'text') {
200
204
  container = /*#__PURE__*/React.createElement(View, {
201
205
  className: "t-agent-message-input-text-bar"
@@ -223,6 +227,13 @@ export default function MessageInputAIStream(props) {
223
227
  emitEvent('scrollToBottom', {
224
228
  animation: true
225
229
  });
230
+ },
231
+ onBlur: () => {
232
+ sleep(200).then(() => {
233
+ emitEvent('scrollToBottom', {
234
+ follow: true
235
+ });
236
+ });
226
237
  }
227
238
  }), /*#__PURE__*/React.createElement(Button, {
228
239
  "data-testid": "t-agent-message-input-button-asr",
@@ -308,9 +319,9 @@ export default function MessageInputAIStream(props) {
308
319
  } else {
309
320
  container = /*#__PURE__*/React.createElement(AsrInput, {
310
321
  responding: canAbort,
311
- disabled: state.current === InputState.ABORTING,
322
+ disabled: state.current === MessageInputState.ABORTING,
312
323
  amplitudeCount: AMPLITUDE_COUNT,
313
- recording: state.current === InputState.RECORDING,
324
+ recording: state.current === MessageInputState.RECORDING,
314
325
  onRecord: async () => {
315
326
  logger.debug('MessageInputAIStream', 'AsrInput onRecord');
316
327
  if (attachmentInput.uploading) {
@@ -332,10 +343,10 @@ export default function MessageInputAIStream(props) {
332
343
  const emitter = new Emitter();
333
344
  emitter.addEventListener('error', async error => {
334
345
  logger.error('MessageInputAIStream', 'AsrInput error', error);
335
- if (state.current === InputState.RECORDING) {
346
+ if (state.current === MessageInputState.RECORDING) {
336
347
  clearTimeout(state.payload.recordTimeOutId);
337
348
  }
338
- if (state.current === InputState.RESPONDING) {
349
+ if (state.current === MessageInputState.RESPONDING) {
339
350
  return;
340
351
  }
341
352
  if (dispatch(InputAction.ASR_ERROR, {})) {
@@ -416,7 +427,7 @@ export default function MessageInputAIStream(props) {
416
427
  onConfirm: async () => {
417
428
  logger.debug('MessageInputAIStream', 'AsrInput onConfirm');
418
429
  recordingFlagRef.current = false;
419
- if (state.current === InputState.ABORTING || state.current === InputState.PENDING) {
430
+ if (state.current === MessageInputState.ABORTING || state.current === MessageInputState.PENDING) {
420
431
  return;
421
432
  }
422
433
  const payload = state.payload;
@@ -430,7 +441,7 @@ export default function MessageInputAIStream(props) {
430
441
  onCancel: async () => {
431
442
  logger.debug('MessageInputAIStream', 'AsrInput onCancel');
432
443
  recordingFlagRef.current = false;
433
- if (state.current === InputState.ABORTING) {
444
+ if (state.current === MessageInputState.ABORTING) {
434
445
  return false;
435
446
  }
436
447
  const payload = state.payload;
@@ -1,2 +1,3 @@
1
- import MessageInputAIStream from './MessageInputAIStream';
1
+ import MessageInputAIStream, { MessageInputState } from './MessageInputAIStream';
2
+ export { MessageInputState };
2
3
  export default MessageInputAIStream;
@@ -1,2 +1,3 @@
1
- import MessageInputAIStream from './MessageInputAIStream';
1
+ import MessageInputAIStream, { MessageInputState } from './MessageInputAIStream';
2
+ export { MessageInputState };
2
3
  export default MessageInputAIStream;
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ interface Props {
3
+ id: string;
4
+ className?: string;
5
+ children?: React.ReactNode;
6
+ containerId: string;
7
+ }
8
+ export default function LazyView(props: Props): React.JSX.Element;
9
+ export {};
@@ -0,0 +1,57 @@
1
+ import "core-js/modules/es.regexp.exec.js";
2
+ import "core-js/modules/web.dom-collections.iterator.js";
3
+ import { View } from '@ray-js/components';
4
+ import React, { useEffect, useRef, useState } from 'react';
5
+ import { usePageInstance } from '@ray-js/ray';
6
+ const queryHeight = id => {
7
+ return new Promise(resolve => {
8
+ // @ts-ignore
9
+ const query = ty.createSelectorQuery();
10
+ query.select("#".concat(id)).boundingClientRect(res => {
11
+ resolve(res.height);
12
+ }).exec();
13
+ });
14
+ };
15
+ export default function LazyView(props) {
16
+ const {
17
+ id,
18
+ className,
19
+ children,
20
+ containerId
21
+ } = props;
22
+ const [visible, setVisible] = useState(true);
23
+ const heightRef = useRef(0);
24
+ const valid = heightRef.current > 0;
25
+ console.log();
26
+ const page = usePageInstance();
27
+ useEffect(() => {
28
+ // @ts-ignore
29
+ const observer = ty.createIntersectionObserver(page, {
30
+ thresholds: [0, 1],
31
+ initialRatio: 0
32
+ });
33
+ observer.relativeTo("#".concat(containerId), {
34
+ top: 50,
35
+ bottom: 50
36
+ }).observe("#".concat(id), res => {
37
+ setVisible(res.intersectionRatio > 0);
38
+ console.log(id, res);
39
+ });
40
+ return () => {
41
+ observer.disconnect();
42
+ };
43
+ }, [id, containerId]);
44
+ useEffect(() => {
45
+ queryHeight(id).then(height => {
46
+ console.log('queryHeight', id, height);
47
+ heightRef.current = height;
48
+ });
49
+ }, [id]);
50
+ console.log('rerender', id);
51
+ return /*#__PURE__*/React.createElement(View, {
52
+ className: className,
53
+ "data-hide": !visible && valid,
54
+ id: id
55
+ // style={hide ? { visibility: 'hidden' } : null}
56
+ }, children);
57
+ }
@@ -0,0 +1,47 @@
1
+ import React from 'react';
2
+ interface ScrollBottomViewParams {
3
+ onScroll?: (event: any) => void;
4
+ }
5
+ export declare function useScrollBottomView(params: ScrollBottomViewParams): {
6
+ scrollToBottom: ({ animation, follow }: {
7
+ animation?: boolean | undefined;
8
+ follow?: boolean | undefined;
9
+ }) => void;
10
+ scrollViewLoading: boolean;
11
+ scrollIntoViewId: string;
12
+ contentViewProps: {
13
+ contentViewId: string;
14
+ };
15
+ scrollViewProps: {
16
+ 'data-render-tick': number;
17
+ id: string;
18
+ scrollY: boolean;
19
+ onScroll: (event: {
20
+ detail: {
21
+ scrollTop: number;
22
+ scrollHeight: number;
23
+ deltaY: number;
24
+ };
25
+ currentTarget: any;
26
+ timeStamp: number;
27
+ }) => void;
28
+ scrollWithAnimation: boolean;
29
+ scrollIntoView: string;
30
+ };
31
+ };
32
+ interface Props {
33
+ className?: string;
34
+ contentClassName?: string;
35
+ children: React.ReactNode;
36
+ style?: React.CSSProperties;
37
+ onScroll?: (event: any) => void;
38
+ hideScrollbar?: boolean;
39
+ }
40
+ interface Ref {
41
+ scrollToBottom: (options?: {
42
+ animation?: boolean;
43
+ follow?: boolean;
44
+ }) => void;
45
+ }
46
+ declare const _default: React.MemoExoticComponent<React.ForwardRefExoticComponent<Props & React.RefAttributes<Ref>>>;
47
+ export default _default;