@ray-js/t-agent-ui-ray 0.0.5-beta-1 → 0.0.6-beta-1

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.
@@ -6,7 +6,6 @@ import './index.less';
6
6
  import React, { useEffect, useMemo, useState } from 'react';
7
7
  import { View } from '@ray-js/components';
8
8
  import { getWebSocketStatusSync, SocketStatus } from '@ray-js/t-agent-plugin-assistant';
9
- import { getSystemInfoSync } from '@ray-js/ray';
10
9
  import { ChatAgentContext, MessageContext, RenderContext } from '../contexts';
11
10
  import { defaultRenderOptions } from '../renderOption';
12
11
  import logger from '../logger';
@@ -66,7 +65,7 @@ export default function ChatContainer(props) {
66
65
  break;
67
66
  case 'update':
68
67
  setMessages(prev => {
69
- if (getSystemInfoSync().platform === 'android') {
68
+ if (ty.getSystemInfoSync().platform === 'android') {
70
69
  var _prev;
71
70
  // Android 上有兼容问题,需要手动滚动到底部
72
71
  if (((_prev = prev[prev.length - 1]) === null || _prev === void 0 ? void 0 : _prev.id) === message.id) {
@@ -1,6 +1,5 @@
1
1
  import Render from './index.rjs';
2
2
  import logger from '../logger';
3
- import { getSystemInfoSync } from '@ray-js/ray';
4
3
 
5
4
  // eslint-disable-next-line no-undef
6
5
  Component({
@@ -47,7 +46,8 @@ Component({
47
46
  });
48
47
  const data = JSON.parse(content);
49
48
  if (data.option) {
50
- const pixelRatio = getSystemInfoSync().pixelRatio;
49
+ // eslint-disable-next-line no-undef
50
+ const pixelRatio = ty.getSystemInfoSync().pixelRatio;
51
51
  this.rjs.update(this.data.canvasId, pixelRatio, data.option);
52
52
  this.setData({
53
53
  loading: false,
@@ -1,3 +1,4 @@
1
+ import "core-js/modules/esnext.iterator.constructor.js";
1
2
  import "core-js/modules/esnext.iterator.map.js";
2
3
  import "core-js/modules/web.dom-collections.iterator.js";
3
4
  import './index.less';
@@ -27,10 +28,7 @@ const MarkdownRender = props => {
27
28
  }, [text, parser]);
28
29
  const sendAction = useSendAction();
29
30
  return /*#__PURE__*/React.createElement(View, {
30
- className: "t-agent-markdown-render",
31
- onClick: event => {
32
- console.log('click', event);
33
- }
31
+ className: "t-agent-markdown-render"
34
32
  }, blocks.map(block => {
35
33
  const {
36
34
  id,
@@ -1,9 +1,11 @@
1
1
  import './index.less';
2
2
  import React from 'react';
3
3
  interface Props {
4
+ text: string;
5
+ setText: (text: string) => void;
4
6
  onBack: () => void;
5
7
  sendDisabled: boolean;
6
- onSend: (text: string) => Promise<any>;
8
+ onSend: () => Promise<any>;
7
9
  onError: (error: Error) => void;
8
10
  onMoreClick: () => void;
9
11
  closeMore: () => void;
@@ -9,15 +9,15 @@ export default function AsrInput(props) {
9
9
  onMoreClick,
10
10
  moreOpen,
11
11
  closeMore,
12
- hasMore
12
+ hasMore,
13
+ text,
14
+ setText
13
15
  } = props;
14
16
  const {
15
17
  state,
16
18
  press,
17
19
  release,
18
20
  clear,
19
- text,
20
- setText,
21
21
  currentText,
22
22
  incomingText
23
23
  } = useAsrInput(props);
@@ -26,15 +26,18 @@ export default function AsrInput(props) {
26
26
  }, (state === 'recording' || state === 'pending') && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(View, {
27
27
  className: "t-agent-message-input-voice-mask"
28
28
  }), /*#__PURE__*/React.createElement(View, {
29
- className: "t-agent-message-input-voice-bubble"
29
+ className: "t-agent-message-input-voice-bubble",
30
+ "data-testid": "t-agent-message-input-asr-bubble"
30
31
  }, state === 'recording' ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Text, null, currentText), /*#__PURE__*/React.createElement(Text, {
31
32
  className: "t-agent-message-input-voice-bubble-predicted"
32
33
  }, incomingText)) : /*#__PURE__*/React.createElement(Textarea, {
34
+ "data-testid": "t-agent-message-input-asr-bubble-input",
33
35
  autoHeight: true,
34
36
  className: "t-agent-message-input-voice-bubble-input",
35
37
  value: text,
36
38
  onInput: event => setText(event.value)
37
39
  }))), /*#__PURE__*/React.createElement(Button, {
40
+ "data-testid": "t-agent-message-input-asr-button-left",
38
41
  className: cx('t-agent-message-input-button', {
39
42
  't-agent-message-input-button-text': state === 'init',
40
43
  't-agent-message-input-button-hide': state === 'recording',
@@ -49,6 +52,7 @@ export default function AsrInput(props) {
49
52
  }
50
53
  }
51
54
  }), /*#__PURE__*/React.createElement(Button, {
55
+ "data-testid": "t-agent-message-input-asr-button-middle",
52
56
  className: "t-agent-message-input-button t-agent-message-input-button-voice-active",
53
57
  disabled: sendDisabled,
54
58
  onTouchStart: () => {
@@ -60,6 +64,7 @@ export default function AsrInput(props) {
60
64
  onTouchEnd: release
61
65
  }), /*#__PURE__*/React.createElement(Button, {
62
66
  disabled: sendDisabled,
67
+ "data-testid": "t-agent-message-input-asr-button-right",
63
68
  className: cx('t-agent-message-input-button', {
64
69
  't-agent-message-input-button-voice-send': state === 'pending',
65
70
  't-agent-message-input-button-hide': state === 'recording',
@@ -70,7 +75,7 @@ export default function AsrInput(props) {
70
75
  if (state === 'init' && hasMore) {
71
76
  onMoreClick();
72
77
  } else {
73
- props.onSend(text);
78
+ props.onSend();
74
79
  clear();
75
80
  }
76
81
  }
@@ -5,7 +5,7 @@ import "core-js/modules/web.dom-collections.iterator.js";
5
5
  import './index.less';
6
6
  import { Button, View } from '@ray-js/components';
7
7
  import React, { useState } from 'react';
8
- import { Image, Input, ScrollView, showToast } from '@ray-js/ray';
8
+ import { Image, Input, ScrollView } from '@ray-js/ray';
9
9
  import { Asr, SocketStatus } from '@ray-js/t-agent-plugin-assistant';
10
10
  import cx from 'clsx';
11
11
  import PrivateImage from '../PrivateImage';
@@ -13,24 +13,24 @@ import imageSvg from './icons/image.svg';
13
13
  import videoSvg from './icons/video.svg';
14
14
  import loadingSvg from './icons/loading.svg';
15
15
  import closeCircleSvg from './icons/close-circle.svg';
16
- import { useChatAgent, useEmitEvent, useOnEvent, useRenderOptions, useBlockInput } from '../hooks';
16
+ import { useAttachmentInput, useChatAgent, useEmitEvent, useIsUnmounted, useOnEvent, useRenderOptions } from '../hooks';
17
17
  import AsrInput from './AsrInput';
18
18
  export default function MessageInput(props) {
19
19
  const [moreOpen, setMoreOpen] = useState(false);
20
+ const [text, setText] = useState('');
21
+ const [asrText, setAsrText] = useState('');
22
+ const attachmentInput = useAttachmentInput();
20
23
  const {
21
- text,
22
- setText,
23
24
  uploading,
24
25
  uploaded,
25
26
  setUploaded,
26
- blocks,
27
- loadBlocks,
28
27
  upload
29
- } = useBlockInput();
28
+ } = attachmentInput;
30
29
  const [responding, setResponding] = useState(false);
31
30
  const [mode, setMode] = useState('text');
32
31
  const agent = useChatAgent();
33
32
  const emitEvent = useEmitEvent();
33
+ const isUnmounted = useIsUnmounted();
34
34
  useOnEvent('updateSocketStatus', status => {
35
35
  if ((status === SocketStatus.FAILED || status === SocketStatus.CONNECTING) && responding) {
36
36
  setResponding(false);
@@ -38,17 +38,19 @@ export default function MessageInput(props) {
38
38
  });
39
39
  const hasMore = !!agent.plugins.assistant.options.multiModal;
40
40
  const isMore = !text.length && hasMore;
41
- const send = async input => {
42
- if (!input || uploading || responding) {
41
+ const send = async inputBlocks => {
42
+ if (!(inputBlocks !== null && inputBlocks !== void 0 && inputBlocks.length) || attachmentInput.uploading || responding) {
43
43
  return;
44
44
  }
45
45
  setUploaded([]);
46
46
  setText('');
47
47
  setResponding(true);
48
48
  try {
49
- await agent.pushInputBlocks(blocks);
49
+ await agent.pushInputBlocks(inputBlocks);
50
50
  } finally {
51
- setResponding(false);
51
+ if (!isUnmounted()) {
52
+ setResponding(false);
53
+ }
52
54
  }
53
55
  };
54
56
  useOnEvent('sendMessage', async _ref => {
@@ -65,7 +67,9 @@ export default function MessageInput(props) {
65
67
  try {
66
68
  await agent.pushInputBlocks(blocks);
67
69
  } finally {
68
- setResponding(false);
70
+ if (!isUnmounted()) {
71
+ setResponding(false);
72
+ }
69
73
  }
70
74
  });
71
75
  useOnEvent('setInputBlocks', async _ref2 => {
@@ -75,7 +79,19 @@ export default function MessageInput(props) {
75
79
  if (uploading || responding) {
76
80
  return;
77
81
  }
78
- loadBlocks(blocks);
82
+ if (mode !== 'text') {
83
+ setMode('text');
84
+ }
85
+ attachmentInput.loadBlocks(blocks);
86
+ let t = '';
87
+ for (const block of blocks) {
88
+ if (block.type === 'text') {
89
+ t = block.text;
90
+ }
91
+ }
92
+ if (t) {
93
+ setText(t);
94
+ }
79
95
  setMoreOpen(false);
80
96
  });
81
97
  const openMoreClick = () => {
@@ -100,8 +116,14 @@ export default function MessageInput(props) {
100
116
  value: text,
101
117
  onInput: event => setText(event.detail.value),
102
118
  placeholder: props.placeholder,
119
+ "data-testid": "t-agent-message-input-text-inner",
103
120
  className: "t-agent-message-input-text-inner",
104
- onConfirm: () => send(text),
121
+ onConfirm: () => {
122
+ send([...attachmentInput.blocks, {
123
+ type: 'text',
124
+ text
125
+ }]);
126
+ },
105
127
  maxLength: 200,
106
128
  placeholderStyle: "color: var(--app-B1-N4)",
107
129
  onFocus: () => {
@@ -111,15 +133,17 @@ export default function MessageInput(props) {
111
133
  });
112
134
  }
113
135
  }), /*#__PURE__*/React.createElement(Button, {
136
+ "data-testid": "t-agent-message-input-button-asr",
114
137
  onClick: async () => {
115
138
  const auth = await Asr.authorize();
116
139
  if (!auth) {
117
- showToast({
140
+ ty.showToast({
118
141
  icon: 'none',
119
142
  title: I18n.t('chat.input.voice.requirePermission')
120
143
  });
121
144
  return;
122
145
  }
146
+ setText('');
123
147
  setMode('voice');
124
148
  },
125
149
  className: "t-agent-message-input-button t-agent-message-input-button-voice"
@@ -130,25 +154,41 @@ export default function MessageInput(props) {
130
154
  't-agent-message-input-button-more-open': moreOpen && isMore,
131
155
  't-agent-message-input-button-send': !isMore
132
156
  }),
157
+ "data-testid": "t-agent-message-input-button-main",
133
158
  onClick: async () => {
134
159
  if (isMore) {
135
160
  openMoreClick();
136
- } else {
137
- await send(text);
161
+ } else if (text) {
162
+ await send([...attachmentInput.blocks, {
163
+ type: 'text',
164
+ text
165
+ }]);
138
166
  }
139
167
  }
140
168
  }));
141
169
  } else {
142
170
  container = /*#__PURE__*/React.createElement(AsrInput, {
143
- onBack: () => setMode('text'),
171
+ text: asrText,
172
+ setText: setAsrText,
173
+ onBack: () => {
174
+ setText('');
175
+ setMode('text');
176
+ },
144
177
  moreOpen: moreOpen,
145
178
  closeMore: () => setMoreOpen(false),
146
179
  onMoreClick: openMoreClick,
147
180
  sendDisabled: responding || uploading,
148
- onSend: text => send(text),
181
+ onSend: async () => {
182
+ if (asrText) {
183
+ await send([...attachmentInput.blocks, {
184
+ type: 'text',
185
+ text: asrText
186
+ }]);
187
+ }
188
+ },
149
189
  hasMore: hasMore,
150
190
  onError: error => {
151
- showToast({
191
+ ty.showToast({
152
192
  icon: 'error',
153
193
  title: error.message
154
194
  });
@@ -216,7 +256,7 @@ export default function MessageInput(props) {
216
256
  try {
217
257
  await upload('image', 1);
218
258
  } catch (e) {
219
- showToast({
259
+ ty.showToast({
220
260
  icon: 'error',
221
261
  title: I18n.t('common.upload.failed')
222
262
  });
@@ -232,7 +272,7 @@ export default function MessageInput(props) {
232
272
  try {
233
273
  await upload('video', 1);
234
274
  } catch (e) {
235
- showToast({
275
+ ty.showToast({
236
276
  icon: 'error',
237
277
  title: I18n.t('common.upload.failed')
238
278
  });
@@ -7,10 +7,12 @@
7
7
  }
8
8
  }
9
9
 
10
+ .t-agent-message-input {
11
+ padding-bottom: var(--t-agent-safe-bottom);
12
+ }
10
13
 
11
14
  .t-agent-message-input-container {
12
15
  --t-agent-input-border-color: var(--app-B1-N7);
13
- padding-bottom: var(--t-agent-safe-bottom);
14
16
  border-top: 2rpx solid var(--t-agent-input-border-color);
15
17
  background: var(--app-B1);
16
18
  }
@@ -259,6 +261,7 @@
259
261
  color: var(--app-M1-N1);
260
262
  font-size: 32rpx;
261
263
  transition: height 0.2s ease-in-out;
264
+ white-space: pre-wrap;
262
265
 
263
266
  &::after {
264
267
  content: '';
@@ -3,9 +3,9 @@ import React from 'react';
3
3
  interface Props {
4
4
  className?: string;
5
5
  roleSide?: {
6
- user?: 'start' | 'end';
7
- assistant?: 'start' | 'end';
8
- [key: string]: 'start' | 'end';
6
+ user?: 'start' | 'end' | string;
7
+ assistant?: 'start' | 'end' | string;
8
+ [key: string]: 'start' | 'end' | string;
9
9
  };
10
10
  }
11
11
  export default function MessageList(props: Props): React.JSX.Element;
@@ -1,4 +1,5 @@
1
1
  import "core-js/modules/es.array.reverse.js";
2
+ import "core-js/modules/esnext.iterator.constructor.js";
2
3
  import "core-js/modules/esnext.iterator.map.js";
3
4
  import "core-js/modules/web.dom-collections.iterator.js";
4
5
  import './index.less';
@@ -6,7 +7,7 @@ import { View } from '@ray-js/components';
6
7
  import React, { useMemo, useState } from 'react';
7
8
  import { ScrollView } from '@ray-js/ray';
8
9
  import MessageRender from '../MessageRender';
9
- import { useAgentMessage, useOnEvent } from '../hooks';
10
+ import { useAgentMessage, useOnEvent, useSleep } from '../hooks';
10
11
  export default function MessageList(props) {
11
12
  const {
12
13
  className,
@@ -18,25 +19,27 @@ export default function MessageList(props) {
18
19
  const [scrollAnimation, setScrollAnimation] = useState(false);
19
20
  // 最大整数位数,用于强制滚动到底部,收到连续 scrollToBottom 时,每 10 毫秒更新一次
20
21
  const [scrollTop, setScrollTop] = useState(() => 1000000000000000 + Math.floor(Date.now() / 10));
22
+ const sleep = useSleep();
21
23
 
22
24
  // 强制滚动到底部
23
25
  useOnEvent('scrollToBottom', _ref => {
24
26
  let {
25
27
  animation
26
28
  } = _ref;
27
- setTimeout(() => {
29
+ sleep(100).then(() => {
28
30
  setScrollAnimation(!!animation);
29
31
  const top = 1000000000000000 + Math.floor(Date.now() / 10);
30
32
  if (top !== scrollTop) {
31
33
  setScrollTop(top);
32
34
  }
33
- }, 100);
35
+ });
34
36
  });
35
37
 
36
38
  // 使用翻转列表,让滚动和新消息出现在第一条,这样可以避免滚动到底部时的闪烁
37
39
  const reversed = useMemo(() => [...messages].reverse(), [messages]);
38
40
  return /*#__PURE__*/React.createElement(View, {
39
- className: "t-agent-message-list"
41
+ className: "t-agent-message-list",
42
+ "data-testid": "t-agent-message-list"
40
43
  }, /*#__PURE__*/React.createElement(ScrollView, {
41
44
  className: "".concat(className || '', " t-agent-message-list-scroll"),
42
45
  scrollWithAnimation: scrollAnimation,
@@ -4,7 +4,7 @@ import { ChatMessageObject } from '@ray-js/t-agent';
4
4
  interface Props {
5
5
  message: ChatMessageObject;
6
6
  isLatestMessage: boolean;
7
- side: 'start' | 'end';
7
+ side: 'start' | 'end' | string;
8
8
  }
9
9
  export default function MessageRender({ message, isLatestMessage, side }: Props): React.JSX.Element;
10
10
  export {};
@@ -1,3 +1,4 @@
1
+ import "core-js/modules/esnext.iterator.constructor.js";
1
2
  import "core-js/modules/esnext.iterator.map.js";
2
3
  import './index.less';
3
4
  import { View } from '@ray-js/components';
@@ -4,7 +4,7 @@ import { ChatMessageObject, ChatTileObject } from '@ray-js/t-agent';
4
4
  interface Props {
5
5
  tile: ChatTileObject;
6
6
  message: ChatMessageObject;
7
- side: 'start' | 'end';
7
+ side: 'start' | 'end' | string;
8
8
  isLatestMessage?: boolean;
9
9
  }
10
10
  declare const _default: React.MemoExoticComponent<({ tile, message, isLatestMessage, side }: Props) => React.JSX.Element>;
@@ -1,3 +1,4 @@
1
+ import "core-js/modules/esnext.iterator.constructor.js";
1
2
  import "core-js/modules/esnext.iterator.map.js";
2
3
  import './index.less';
3
4
  import { WorkflowReplyResourceType } from '@ray-js/t-agent-plugin-assistant';
@@ -19,7 +19,7 @@ export const useOnEvent = (eventName, callback) => {
19
19
  return agent.plugins.ui.onEvent(eventName, detail => {
20
20
  callbackRef.current(detail);
21
21
  });
22
- }, [agent, eventName, callback]);
22
+ }, [agent, eventName]);
23
23
  };
24
24
  export const useEmitEvent = () => {
25
25
  const agent = useChatAgent();
@@ -1,3 +1,5 @@
1
1
  export * from './context';
2
- export * from './useBlockInput';
2
+ export * from './useAttachmentInput';
3
3
  export * from './useAsrInput';
4
+ export * from './useSleep';
5
+ export * from './useIsUnmounted';
@@ -1,3 +1,5 @@
1
1
  export * from './context';
2
- export * from './useBlockInput';
3
- export * from './useAsrInput';
2
+ export * from './useAttachmentInput';
3
+ export * from './useAsrInput';
4
+ export * from './useSleep';
5
+ export * from './useIsUnmounted';
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  export declare enum AsrErrorCode {
3
2
  SHORT_TIME = 0
4
3
  }
@@ -7,6 +6,8 @@ export declare class AsrError extends Error {
7
6
  constructor(errorCode: AsrErrorCode, message?: string);
8
7
  }
9
8
  export interface UseAsrInputOptions {
9
+ text: string;
10
+ setText: (text: string) => void;
10
11
  onError: (error: Error) => void;
11
12
  }
12
13
  /**
@@ -27,8 +28,6 @@ export interface UseAsrInputOptions {
27
28
  +-------------------------+ +--------------------------+
28
29
  */
29
30
  export declare function useAsrInput(options: UseAsrInputOptions): {
30
- text: string;
31
- setText: import("react").Dispatch<import("react").SetStateAction<string>>;
32
31
  currentText: string;
33
32
  incomingText: string;
34
33
  state: "pending" | "recording" | "init";
@@ -40,17 +40,16 @@ export class AsrError extends Error {
40
40
  */
41
41
  export function useAsrInput(options) {
42
42
  const {
43
+ text,
44
+ setText,
43
45
  onError
44
46
  } = options;
45
47
  const asrRef = useRef(null);
46
- const [text, setText] = useState('');
47
48
  const [currentText, setCurrentText] = useState('');
48
49
  const [incomingText, setIncomingText] = useState('');
49
50
  const [state, setState] = useState('init');
50
51
  const startAt = useRef(0);
51
52
  return {
52
- text,
53
- setText,
54
53
  currentText,
55
54
  incomingText,
56
55
  state,
@@ -99,7 +98,7 @@ export function useAsrInput(options) {
99
98
  onError(new AsrError(AsrErrorCode.SHORT_TIME));
100
99
  setState('init');
101
100
  }
102
- if (Date.now() - startAt.current < 1000) {
101
+ if (Date.now() - startAt.current < 500 && text.length === 0) {
103
102
  onError(new AsrError(AsrErrorCode.SHORT_TIME));
104
103
  }
105
104
  if (asrRef.current) {
@@ -6,9 +6,7 @@ export interface UploadFile {
6
6
  url?: string;
7
7
  thumbUrl?: string;
8
8
  }
9
- export declare function useBlockInput(): {
10
- text: string;
11
- setText: import("react").Dispatch<import("react").SetStateAction<string>>;
9
+ export declare function useAttachmentInput(): {
12
10
  blocks: InputBlock[];
13
11
  uploaded: UploadFile[];
14
12
  setUploaded: import("react").Dispatch<import("react").SetStateAction<UploadFile[]>>;
@@ -7,19 +7,15 @@ import { useCallback, useMemo, useState } from 'react';
7
7
  import { chooseImage, chooseVideo, uploadImage, uploadVideo } from '@ray-js/t-agent-plugin-assistant';
8
8
  import { generateId } from '@ray-js/t-agent';
9
9
  import { useRenderOptions } from './context';
10
- export function useBlockInput() {
11
- const [text, setText] = useState('');
10
+ export function useAttachmentInput() {
12
11
  const [uploaded, setUploaded] = useState([]);
13
12
  const uploading = useMemo(() => uploaded.some(file => file.type === 'loading'), [uploaded]);
14
13
  const blocks = useMemo(() => {
15
- const blocks = [{
16
- text,
17
- type: 'text'
18
- }];
14
+ const b = [];
19
15
  if (uploaded.length) {
20
16
  for (const uploadFile of uploaded) {
21
17
  if (uploadFile.type === 'image') {
22
- blocks.push({
18
+ b.push({
23
19
  type: 'image_url',
24
20
  image_url: {
25
21
  url: uploadFile.url
@@ -27,7 +23,7 @@ export function useBlockInput() {
27
23
  });
28
24
  }
29
25
  if (uploadFile.type === 'video') {
30
- blocks.push({
26
+ b.push({
31
27
  type: 'video_url',
32
28
  video_url: {
33
29
  url: uploadFile.url,
@@ -36,12 +32,10 @@ export function useBlockInput() {
36
32
  });
37
33
  }
38
34
  }
39
- setUploaded([]);
40
35
  }
41
- return blocks;
42
- }, [uploaded, text]);
36
+ return b;
37
+ }, [uploaded]);
43
38
  const loadBlocks = useCallback((blocks, append) => {
44
- let t = '';
45
39
  const uploaded = [];
46
40
  for (const block of blocks) {
47
41
  if (block.type === 'image_url') {
@@ -59,17 +53,10 @@ export function useBlockInput() {
59
53
  thumbUrl: block.video_url.thumb_url
60
54
  });
61
55
  }
62
- if (block.type === 'text') {
63
- t = block.text;
64
- }
65
56
  }
66
57
  if (append) {
67
- if (t) {
68
- setText(t);
69
- }
70
- setUploaded(prev => uploaded.length ? [...prev, ...uploaded] : prev);
58
+ setUploaded(prev => [...prev, ...uploaded]);
71
59
  } else {
72
- setText(t);
73
60
  setUploaded(uploaded);
74
61
  }
75
62
  }, []);
@@ -136,8 +123,6 @@ export function useBlockInput() {
136
123
  }
137
124
  }, [getStaticResourceBizType]);
138
125
  return {
139
- text,
140
- setText,
141
126
  blocks,
142
127
  uploaded,
143
128
  setUploaded,
@@ -0,0 +1 @@
1
+ export declare function useIsUnmounted(): () => boolean;
@@ -0,0 +1,10 @@
1
+ import { useCallback, useEffect, useRef } from 'react';
2
+ export function useIsUnmounted() {
3
+ const unmounted = useRef(false);
4
+ useEffect(() => {
5
+ return () => {
6
+ unmounted.current = true;
7
+ };
8
+ }, []);
9
+ return useCallback(() => unmounted.current, []);
10
+ }
@@ -0,0 +1 @@
1
+ export declare function useSleep(): (ms: number) => Promise<void>;
@@ -0,0 +1,25 @@
1
+ import "core-js/modules/esnext.iterator.constructor.js";
2
+ import "core-js/modules/esnext.iterator.filter.js";
3
+ import "core-js/modules/esnext.iterator.for-each.js";
4
+ import { useCallback, useEffect, useRef } from 'react';
5
+ export function useSleep() {
6
+ const ids = useRef([]);
7
+ const sleep = useCallback(ms => {
8
+ return new Promise(resolve => {
9
+ const id = setTimeout(() => {
10
+ resolve();
11
+ ids.current = ids.current.filter(i => i !== id);
12
+ }, ms);
13
+ ids.current.push(id);
14
+ });
15
+ }, []);
16
+ useEffect(() => {
17
+ return () => {
18
+ ids.current.forEach(id => {
19
+ clearTimeout(id);
20
+ });
21
+ ids.current = [];
22
+ };
23
+ }, []);
24
+ return sleep;
25
+ }
@@ -1,10 +1,11 @@
1
1
  import "core-js/modules/es.json.stringify.js";
2
+ import "core-js/modules/esnext.iterator.constructor.js";
2
3
  import "core-js/modules/esnext.iterator.map.js";
3
4
  import "core-js/modules/web.dom-collections.iterator.js";
4
5
  import './index.less';
5
6
  import { Text, View } from '@ray-js/components';
6
7
  import React, { useEffect, useState } from 'react';
7
- import { getStorage, Image, showToast, setStorage } from '@ray-js/ray';
8
+ import { Image } from '@ray-js/ray';
8
9
  import { BubbleTileStatus, ChatMessageStatus, safeParseJSON } from '@ray-js/t-agent';
9
10
  import { getCurrentHomeInfo, submitEvaluation } from '@ray-js/t-agent-plugin-assistant';
10
11
  import TileRender from '../../TileRender';
@@ -34,7 +35,7 @@ const BubbleTile = props => {
34
35
  const [feedbackLoaded, setFeedbackLoaded] = useState(false);
35
36
  const [feedbackValue, setFeedbackValue] = useState(null);
36
37
  useEffect(() => {
37
- getStorage({
38
+ ty.getStorage({
38
39
  key: 'latestMessageFeedbackValue',
39
40
  success: res => {
40
41
  if (res.data) {
@@ -65,9 +66,9 @@ const BubbleTile = props => {
65
66
  return /*#__PURE__*/React.createElement(View, {
66
67
  className: "t-agent-bubble-tile t-agent-bubble-tile-".concat(side),
67
68
  onLongPress: () => {
68
- showToast({
69
- title: 'long press'
70
- });
69
+ // ty.showToast({
70
+ // title: 'long press',
71
+ // });
71
72
  }
72
73
  }, bubbleStatus === BubbleTileStatus.ERROR && side === 'end' && /*#__PURE__*/React.createElement(Image, {
73
74
  onClick: showInfo,
@@ -102,14 +103,14 @@ const BubbleTile = props => {
102
103
  score: value,
103
104
  channel
104
105
  });
105
- setStorage({
106
+ ty.setStorage({
106
107
  key: 'latestMessageFeedbackValue',
107
108
  data: JSON.stringify({
108
109
  requestId: message.meta.requestId,
109
110
  value
110
111
  })
111
112
  });
112
- showToast({
113
+ ty.showToast({
113
114
  title: I18n.t('chat.feedback.success'),
114
115
  icon: 'none'
115
116
  });
@@ -1,3 +1,4 @@
1
+ import "core-js/modules/esnext.iterator.constructor.js";
1
2
  import "core-js/modules/esnext.iterator.map.js";
2
3
  import { Button, View } from '@ray-js/components';
3
4
  import React from 'react';
@@ -1,3 +1,4 @@
1
+ import "core-js/modules/esnext.iterator.constructor.js";
1
2
  import "core-js/modules/esnext.iterator.map.js";
2
3
  import { View } from '@ray-js/components';
3
4
  import React from 'react';
@@ -1,4 +1,5 @@
1
1
  import "core-js/modules/es.array.sort.js";
2
+ import "core-js/modules/esnext.iterator.constructor.js";
2
3
  import "core-js/modules/esnext.iterator.map.js";
3
4
  import { View } from '@ray-js/components';
4
5
  import React, { useMemo } from 'react';
@@ -1,7 +1,6 @@
1
1
  import React, { useMemo } from 'react';
2
2
  import { View } from '@ray-js/components';
3
3
  import './index.less';
4
- import { getSystemInfoSync } from '@ray-js/ray';
5
4
  import MarkdownRender from '../../MarkdownRender';
6
5
  import { useRenderOptions } from '../../hooks';
7
6
  const TextTile = props => {
@@ -13,7 +12,7 @@ const TextTile = props => {
13
12
  renderCustomBlockAs,
14
13
  customBlockTypes
15
14
  } = useRenderOptions();
16
- const theme = useMemo(() => getSystemInfoSync().theme, []);
15
+ const theme = useMemo(() => ty.getSystemInfoSync().theme, []);
17
16
  return markdown ? /*#__PURE__*/React.createElement(MarkdownRender, {
18
17
  theme: theme,
19
18
  text: text,
@@ -1,3 +1,4 @@
1
+ import "core-js/modules/esnext.iterator.constructor.js";
1
2
  import "core-js/modules/esnext.iterator.map.js";
2
3
  import { Button, View } from '@ray-js/components';
3
4
  import React from 'react';
package/dist/types.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { ChatAgent, ChatCardObject, ChatMessageObject, ChatTileObject } from '@ray-js/t-agent';
2
2
  import React from 'react';
3
3
  export interface TileProps<T = any, P = any> {
4
- side: 'start' | 'end';
4
+ side: 'start' | 'end' | string;
5
5
  message: ChatMessageObject;
6
6
  tile: ChatTileObject<T>;
7
7
  emitEvent: (payload: P) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ray-js/t-agent-ui-ray",
3
- "version": "0.0.5-beta-1",
3
+ "version": "0.0.6-beta-1",
4
4
  "author": "Tuya.inc",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -41,5 +41,5 @@
41
41
  "@types/echarts": "^4.9.22",
42
42
  "@types/markdown-it": "^14.1.1"
43
43
  },
44
- "gitHead": "c2f10c94fb4031e1c375864e70a69adb3bbadd2d"
44
+ "gitHead": "942a1aeceb65c55ba935409d386bc09f9874e283"
45
45
  }