@unif/react-native-chat 3.7.0 → 4.0.0
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/lib/module/components/Attachments/AttachmentItem.js +13 -12
- package/lib/module/components/Attachments/AttachmentItem.js.map +1 -1
- package/lib/module/components/Attachments/constants.js +5 -4
- package/lib/module/components/Attachments/constants.js.map +1 -1
- package/lib/module/components/Composer/Composer.js +6 -5
- package/lib/module/components/Composer/Composer.js.map +1 -1
- package/lib/module/components/Composer/ComposerIconAction.js +3 -3
- package/lib/module/components/Composer/ComposerIconAction.js.map +1 -1
- package/lib/module/components/Confirmation/Confirmation.js +4 -3
- package/lib/module/components/Confirmation/Confirmation.js.map +1 -1
- package/lib/module/components/Feedback/Feedback.js +4 -3
- package/lib/module/components/Feedback/Feedback.js.map +1 -1
- package/lib/module/components/Feedback/constants.js +5 -4
- package/lib/module/components/Feedback/constants.js.map +1 -1
- package/lib/module/components/Message/MarkdownContent/MarkdownImage/MarkdownImage.js +6 -3
- package/lib/module/components/Message/MarkdownContent/MarkdownImage/MarkdownImage.js.map +1 -1
- package/lib/module/components/Message/Message.js +2 -1
- package/lib/module/components/Message/Message.js.map +1 -1
- package/lib/module/components/MessageList/MessageListEndButton.js +2 -1
- package/lib/module/components/MessageList/MessageListEndButton.js.map +1 -1
- package/lib/module/components/Process/Process.js +4 -3
- package/lib/module/components/Process/Process.js.map +1 -1
- package/lib/module/components/Process/ProcessCompactStep.js +11 -10
- package/lib/module/components/Process/ProcessCompactStep.js.map +1 -1
- package/lib/module/components/Process/ProcessTimelineStep.js +3 -3
- package/lib/module/components/Process/ProcessTimelineStep.js.map +1 -1
- package/lib/module/components/Process/constants.js +6 -5
- package/lib/module/components/Process/constants.js.map +1 -1
- package/lib/module/components/Sources/Sources.js +6 -3
- package/lib/module/components/Sources/Sources.js.map +1 -1
- package/lib/module/components/Suggestions/Suggestions.js +2 -3
- package/lib/module/components/Suggestions/Suggestions.js.map +1 -1
- package/lib/typescript/src/actions/types.d.ts +3 -2
- package/lib/typescript/src/actions/types.d.ts.map +1 -1
- package/lib/typescript/src/components/Attachments/AttachmentItem.d.ts.map +1 -1
- package/lib/typescript/src/components/Attachments/constants.d.ts +3 -2
- package/lib/typescript/src/components/Attachments/constants.d.ts.map +1 -1
- package/lib/typescript/src/components/Composer/Composer.d.ts.map +1 -1
- package/lib/typescript/src/components/Composer/types.d.ts +4 -2
- package/lib/typescript/src/components/Composer/types.d.ts.map +1 -1
- package/lib/typescript/src/components/Confirmation/Confirmation.d.ts.map +1 -1
- package/lib/typescript/src/components/Feedback/Feedback.d.ts.map +1 -1
- package/lib/typescript/src/components/Feedback/constants.d.ts +3 -2
- package/lib/typescript/src/components/Feedback/constants.d.ts.map +1 -1
- package/lib/typescript/src/components/Message/MarkdownContent/MarkdownImage/MarkdownImage.d.ts.map +1 -1
- package/lib/typescript/src/components/Message/Message.d.ts.map +1 -1
- package/lib/typescript/src/components/MessageList/MessageListEndButton.d.ts.map +1 -1
- package/lib/typescript/src/components/Process/Process.d.ts.map +1 -1
- package/lib/typescript/src/components/Process/ProcessCompactStep.d.ts.map +1 -1
- package/lib/typescript/src/components/Process/constants.d.ts +3 -2
- package/lib/typescript/src/components/Process/constants.d.ts.map +1 -1
- package/lib/typescript/src/components/Process/types.d.ts +4 -0
- package/lib/typescript/src/components/Process/types.d.ts.map +1 -1
- package/lib/typescript/src/components/Sources/Sources.d.ts.map +1 -1
- package/lib/typescript/src/components/Suggestions/Suggestions.d.ts.map +1 -1
- package/lib/typescript/src/components/Suggestions/types.d.ts +3 -2
- package/lib/typescript/src/components/Suggestions/types.d.ts.map +1 -1
- package/package.json +5 -3
- package/src/actions/types.ts +3 -2
- package/src/components/Attachments/AttachmentItem.tsx +14 -20
- package/src/components/Attachments/constants.ts +14 -6
- package/src/components/Composer/Composer.tsx +14 -5
- package/src/components/Composer/ComposerIconAction.tsx +3 -3
- package/src/components/Composer/types.ts +4 -2
- package/src/components/Confirmation/Confirmation.tsx +12 -12
- package/src/components/Feedback/Feedback.tsx +3 -2
- package/src/components/Feedback/constants.ts +16 -6
- package/src/components/Message/MarkdownContent/MarkdownImage/MarkdownImage.tsx +4 -2
- package/src/components/Message/Message.tsx +2 -1
- package/src/components/MessageList/MessageListEndButton.tsx +2 -1
- package/src/components/Process/Process.tsx +4 -3
- package/src/components/Process/ProcessCompactStep.tsx +26 -20
- package/src/components/Process/ProcessTimelineStep.tsx +2 -2
- package/src/components/Process/constants.ts +16 -7
- package/src/components/Process/types.ts +5 -0
- package/src/components/Sources/Sources.tsx +6 -2
- package/src/components/Suggestions/Suggestions.tsx +2 -6
- package/src/components/Suggestions/types.ts +4 -2
package/src/actions/types.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ComponentType } from 'react';
|
|
2
|
+
import type { IconProps } from '@unif/react-native-icons';
|
|
2
3
|
|
|
3
4
|
export interface ChatAction {
|
|
4
5
|
id: string;
|
|
5
6
|
label: string;
|
|
6
|
-
icon?:
|
|
7
|
+
icon?: ComponentType<IconProps>;
|
|
7
8
|
disabled?: boolean;
|
|
8
9
|
loading?: boolean;
|
|
9
10
|
accessibilityHint?: string;
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CloseOutlined,
|
|
3
|
+
EyeOutlined,
|
|
4
|
+
RefreshOutlined,
|
|
5
|
+
} from '@unif/react-native-icons';
|
|
1
6
|
import { Pressable, Text, View } from 'react-native';
|
|
2
7
|
import {
|
|
3
8
|
Button,
|
|
4
9
|
CircularProgress,
|
|
5
10
|
GlassLayer,
|
|
6
|
-
Icon,
|
|
7
11
|
IconButton,
|
|
8
12
|
radius,
|
|
9
13
|
Spinner,
|
|
@@ -55,12 +59,7 @@ export function AttachmentItem({
|
|
|
55
59
|
const removable = item.removable && onRemove;
|
|
56
60
|
const singleAction = item.actions?.length === 1 ? item.actions[0] : undefined;
|
|
57
61
|
const retry =
|
|
58
|
-
failed &&
|
|
59
|
-
!caption &&
|
|
60
|
-
singleAction &&
|
|
61
|
-
(singleAction.id === 'retry' ||
|
|
62
|
-
singleAction.icon === 'retry' ||
|
|
63
|
-
singleAction.icon === 'refresh')
|
|
62
|
+
failed && !caption && singleAction?.id === 'retry'
|
|
64
63
|
? singleAction
|
|
65
64
|
: undefined;
|
|
66
65
|
const statusLeft = (imageSize - ATTACHMENT_STATUS_OWNER_SIZE) / 2;
|
|
@@ -73,9 +72,8 @@ export function AttachmentItem({
|
|
|
73
72
|
ATTACHMENT_STATUS_OWNER_SIZE
|
|
74
73
|
)
|
|
75
74
|
: statusLeft;
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
);
|
|
75
|
+
const Glyph = ATTACHMENT_ICONS[item.kind ?? 'file'];
|
|
76
|
+
const icon = <Glyph size={ROW_IMAGE_SIZE} color={colors.foregroundMuted} />;
|
|
79
77
|
const thumbnail = item.thumbnail ? (
|
|
80
78
|
<Thumbnail
|
|
81
79
|
source={item.thumbnail}
|
|
@@ -91,16 +89,13 @@ export function AttachmentItem({
|
|
|
91
89
|
{icon}
|
|
92
90
|
</View>
|
|
93
91
|
);
|
|
92
|
+
const Glyph2 = retry?.icon ?? RefreshOutlined;
|
|
94
93
|
const statusVisual =
|
|
95
94
|
busy || failed ? (
|
|
96
95
|
<View style={styles.statusVisual}>
|
|
97
96
|
<GlassLayer colorScheme="dark" style={styles.circleGlass} />
|
|
98
97
|
{failed ? (
|
|
99
|
-
<
|
|
100
|
-
name={retry?.icon ?? 'refresh'}
|
|
101
|
-
size={16}
|
|
102
|
-
color={colors.onPrimary}
|
|
103
|
-
/>
|
|
98
|
+
<Glyph2 size={16} color={colors.onPrimary} />
|
|
104
99
|
) : progress !== undefined ? (
|
|
105
100
|
<CircularProgress
|
|
106
101
|
value={progress}
|
|
@@ -225,7 +220,7 @@ export function AttachmentItem({
|
|
|
225
220
|
<View style={styles.actions}>
|
|
226
221
|
{previewable && retry ? (
|
|
227
222
|
<IconButton
|
|
228
|
-
icon=
|
|
223
|
+
icon={EyeOutlined}
|
|
229
224
|
size="sm"
|
|
230
225
|
accessibilityLabel={`预览${name}`}
|
|
231
226
|
onPress={() => onPreview?.(item)}
|
|
@@ -233,7 +228,7 @@ export function AttachmentItem({
|
|
|
233
228
|
) : null}
|
|
234
229
|
{removable ? (
|
|
235
230
|
<IconButton
|
|
236
|
-
icon=
|
|
231
|
+
icon={CloseOutlined}
|
|
237
232
|
size="sm"
|
|
238
233
|
accessibilityLabel={`移除${name}`}
|
|
239
234
|
disabled={item.removeDisabled}
|
|
@@ -332,8 +327,7 @@ export function AttachmentItem({
|
|
|
332
327
|
{!failed ? (
|
|
333
328
|
<GlassLayer colorScheme="dark" style={styles.circleGlass} />
|
|
334
329
|
) : null}
|
|
335
|
-
<
|
|
336
|
-
name="close"
|
|
330
|
+
<CloseOutlined
|
|
337
331
|
size={preview ? 12 : 10}
|
|
338
332
|
color={colors.onPrimary}
|
|
339
333
|
strokeWidth={2.5}
|
|
@@ -363,7 +357,7 @@ export function AttachmentItem({
|
|
|
363
357
|
{separatePreview ? (
|
|
364
358
|
<View style={[styles.previewAction, { width: imageSize }]}>
|
|
365
359
|
<IconButton
|
|
366
|
-
icon=
|
|
360
|
+
icon={EyeOutlined}
|
|
367
361
|
size="sm"
|
|
368
362
|
accessibilityLabel={`预览${name}`}
|
|
369
363
|
onPress={() => onPreview?.(item)}
|
|
@@ -1,5 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FileOutlined,
|
|
3
|
+
ImageOutlined,
|
|
4
|
+
PlayOutlined,
|
|
5
|
+
SoundOutlined,
|
|
6
|
+
} from '@unif/react-native-icons';
|
|
7
|
+
import type { ComponentType } from 'react';
|
|
8
|
+
import type { IconProps } from '@unif/react-native-icons';
|
|
1
9
|
import { icon, r } from '@unif/react-native-design';
|
|
2
|
-
|
|
10
|
+
|
|
3
11
|
import type { ChatAttachmentItem } from './types';
|
|
4
12
|
|
|
5
13
|
export const CARD_WIDTH = r(76);
|
|
@@ -15,12 +23,12 @@ export const ATTACHMENT_STATUS_OWNER_SIZE = Math.max(
|
|
|
15
23
|
export const ATTACHMENT_REMOVE_OWNER_SIZE = 44;
|
|
16
24
|
export const ATTACHMENT_ICONS: Record<
|
|
17
25
|
NonNullable<ChatAttachmentItem['kind']>,
|
|
18
|
-
|
|
26
|
+
ComponentType<IconProps>
|
|
19
27
|
> = {
|
|
20
|
-
image:
|
|
21
|
-
file:
|
|
22
|
-
audio:
|
|
23
|
-
video:
|
|
28
|
+
image: ImageOutlined,
|
|
29
|
+
file: FileOutlined,
|
|
30
|
+
audio: SoundOutlined,
|
|
31
|
+
video: PlayOutlined,
|
|
24
32
|
};
|
|
25
33
|
export const STATUS_LABELS = {
|
|
26
34
|
idle: '',
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CloseOutlined,
|
|
3
|
+
MicOutlined,
|
|
4
|
+
PlusOutlined,
|
|
5
|
+
SendOutlined,
|
|
6
|
+
StopFilled,
|
|
7
|
+
} from '@unif/react-native-icons';
|
|
1
8
|
import {
|
|
2
9
|
forwardRef,
|
|
3
10
|
useEffect,
|
|
@@ -119,7 +126,7 @@ export const Composer = forwardRef<ComposerHandle, ComposerProps>(
|
|
|
119
126
|
const moreAction =
|
|
120
127
|
actions.length > 0 ? (
|
|
121
128
|
<ComposerIconAction
|
|
122
|
-
icon=
|
|
129
|
+
icon={PlusOutlined}
|
|
123
130
|
label="更多操作"
|
|
124
131
|
expanded={menuOpen}
|
|
125
132
|
disabled={moreDisabled}
|
|
@@ -243,7 +250,7 @@ export const Composer = forwardRef<ComposerHandle, ComposerProps>(
|
|
|
243
250
|
<View style={styles.trailingActions}>
|
|
244
251
|
{voice ? (
|
|
245
252
|
<ComposerIconAction
|
|
246
|
-
icon=
|
|
253
|
+
icon={MicOutlined}
|
|
247
254
|
label="开始语音输入"
|
|
248
255
|
disabled={disabled || voice.disabled}
|
|
249
256
|
onPress={() => {
|
|
@@ -254,7 +261,9 @@ export const Composer = forwardRef<ComposerHandle, ComposerProps>(
|
|
|
254
261
|
) : null}
|
|
255
262
|
{showPrimary ? (
|
|
256
263
|
<ComposerIconAction
|
|
257
|
-
icon={
|
|
264
|
+
icon={
|
|
265
|
+
primaryAction.kind === 'send' ? SendOutlined : StopFilled
|
|
266
|
+
}
|
|
258
267
|
label={primaryLabel}
|
|
259
268
|
visual="primary"
|
|
260
269
|
disabled={primaryDisabled}
|
|
@@ -276,7 +285,7 @@ export const Composer = forwardRef<ComposerHandle, ComposerProps>(
|
|
|
276
285
|
{voice && voice.status !== 'idle' ? (
|
|
277
286
|
<View style={styles.voice}>
|
|
278
287
|
<ComposerIconAction
|
|
279
|
-
icon=
|
|
288
|
+
icon={CloseOutlined}
|
|
280
289
|
visual="cancel"
|
|
281
290
|
label="取消语音输入"
|
|
282
291
|
disabled={disabled || voice.disabled}
|
|
@@ -300,7 +309,7 @@ export const Composer = forwardRef<ComposerHandle, ComposerProps>(
|
|
|
300
309
|
</View>
|
|
301
310
|
{voice.status === 'listening' || voice.status === 'finishing' ? (
|
|
302
311
|
<ComposerIconAction
|
|
303
|
-
icon=
|
|
312
|
+
icon={StopFilled}
|
|
304
313
|
visual="primary"
|
|
305
314
|
label="停止语音输入"
|
|
306
315
|
disabled={
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ActivityIndicator, Pressable, View } from 'react-native';
|
|
2
|
-
import {
|
|
2
|
+
import { useColors, useThemedStyles } from '@unif/react-native-design';
|
|
3
3
|
import {
|
|
4
4
|
COMPOSER_ACTION_ICON_SIZE,
|
|
5
5
|
COMPOSER_PRIMARY_ICON_SIZE,
|
|
@@ -28,6 +28,7 @@ export function ComposerIconAction({
|
|
|
28
28
|
? colors.foregroundSubtle
|
|
29
29
|
: colors.onPrimary
|
|
30
30
|
: colors.foregroundMuted;
|
|
31
|
+
const Glyph = icon;
|
|
31
32
|
return (
|
|
32
33
|
<Pressable
|
|
33
34
|
accessibilityRole="button"
|
|
@@ -54,8 +55,7 @@ export function ComposerIconAction({
|
|
|
54
55
|
{busy ? (
|
|
55
56
|
<ActivityIndicator size="small" color={color} />
|
|
56
57
|
) : (
|
|
57
|
-
<
|
|
58
|
-
name={icon}
|
|
58
|
+
<Glyph
|
|
59
59
|
size={
|
|
60
60
|
primary
|
|
61
61
|
? COMPOSER_PRIMARY_ICON_SIZE
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import type { ComponentType } from 'react';
|
|
2
|
+
import type { IconProps } from '@unif/react-native-icons';
|
|
1
3
|
import type { ReactNode } from 'react';
|
|
2
4
|
import type { StyleProp, ViewStyle } from 'react-native';
|
|
3
|
-
import type {
|
|
5
|
+
import type { TextFieldHandle } from '@unif/react-native-design';
|
|
4
6
|
import type { ChatAction } from '../../actions';
|
|
5
7
|
|
|
6
8
|
export interface ComposerSendAction {
|
|
@@ -65,7 +67,7 @@ export interface ComposerProps {
|
|
|
65
67
|
export type ComposerHandle = TextFieldHandle;
|
|
66
68
|
|
|
67
69
|
export interface ComposerIconActionProps {
|
|
68
|
-
icon:
|
|
70
|
+
icon: ComponentType<IconProps>;
|
|
69
71
|
label: string;
|
|
70
72
|
onPress?(): void;
|
|
71
73
|
disabled?: boolean;
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CheckOutlined,
|
|
3
|
+
CloseOutlined,
|
|
4
|
+
WarningOutlined,
|
|
5
|
+
} from '@unif/react-native-icons';
|
|
1
6
|
import { Text, View } from 'react-native';
|
|
2
7
|
import {
|
|
3
8
|
Button,
|
|
4
|
-
Icon,
|
|
5
9
|
Spinner,
|
|
6
10
|
useColors,
|
|
7
11
|
useThemedStyles,
|
|
@@ -44,23 +48,19 @@ export function Confirmation({
|
|
|
44
48
|
? statusText
|
|
45
49
|
: (statusText ?? CONFIRMATION_STATUS_TEXT[status]);
|
|
46
50
|
|
|
51
|
+
const Glyph =
|
|
52
|
+
status === 'confirmed'
|
|
53
|
+
? CheckOutlined
|
|
54
|
+
: status === 'cancelled'
|
|
55
|
+
? CloseOutlined
|
|
56
|
+
: WarningOutlined;
|
|
47
57
|
return (
|
|
48
58
|
<View style={[styles.root, { borderColor }, style]} testID={testID}>
|
|
49
59
|
<View style={styles.heading}>
|
|
50
60
|
{status === 'processing' ? (
|
|
51
61
|
<Spinner size={14} color={tint} />
|
|
52
62
|
) : (
|
|
53
|
-
<
|
|
54
|
-
name={
|
|
55
|
-
status === 'confirmed'
|
|
56
|
-
? 'check'
|
|
57
|
-
: status === 'cancelled'
|
|
58
|
-
? 'close'
|
|
59
|
-
: 'warning'
|
|
60
|
-
}
|
|
61
|
-
size={14}
|
|
62
|
-
color={tint}
|
|
63
|
-
/>
|
|
63
|
+
<Glyph size={14} color={tint} />
|
|
64
64
|
)}
|
|
65
65
|
<Text
|
|
66
66
|
style={[styles.title, status === 'cancelled' && styles.cancelled]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Text, View } from 'react-native';
|
|
2
2
|
import {
|
|
3
3
|
Button,
|
|
4
|
-
|
|
4
|
+
r,
|
|
5
5
|
useColors,
|
|
6
6
|
useThemedStyles,
|
|
7
7
|
} from '@unif/react-native-design';
|
|
@@ -48,6 +48,7 @@ export function Feedback({
|
|
|
48
48
|
const toneLabel = FEEDBACK_TONE_LABELS[tone];
|
|
49
49
|
const accessibilityLabel = `${toneLabel}:${title ? `${title}。` : ''}${message}`;
|
|
50
50
|
|
|
51
|
+
const Glyph = FEEDBACK_TONE_ICONS[tone];
|
|
51
52
|
return (
|
|
52
53
|
<View
|
|
53
54
|
style={[
|
|
@@ -57,7 +58,7 @@ export function Feedback({
|
|
|
57
58
|
]}
|
|
58
59
|
testID={testID}
|
|
59
60
|
>
|
|
60
|
-
<
|
|
61
|
+
<Glyph size={r(18)} color={toneColors.iconColor} />
|
|
61
62
|
<View style={styles.content}>
|
|
62
63
|
<View accessible accessibilityLabel={accessibilityLabel}>
|
|
63
64
|
{title ? (
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
ErrorOutlined,
|
|
3
|
+
InfoOutlined,
|
|
4
|
+
SuccessOutlined,
|
|
5
|
+
WarningOutlined,
|
|
6
|
+
} from '@unif/react-native-icons';
|
|
7
|
+
import type { ComponentType } from 'react';
|
|
8
|
+
import type { IconProps } from '@unif/react-native-icons';
|
|
9
|
+
|
|
2
10
|
import type { FeedbackTone } from './types';
|
|
3
11
|
|
|
4
12
|
export const FEEDBACK_TONE_LABELS: Readonly<Record<FeedbackTone, string>> = {
|
|
@@ -8,9 +16,11 @@ export const FEEDBACK_TONE_LABELS: Readonly<Record<FeedbackTone, string>> = {
|
|
|
8
16
|
error: '错误',
|
|
9
17
|
};
|
|
10
18
|
|
|
11
|
-
export const FEEDBACK_TONE_ICONS: Readonly<
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
19
|
+
export const FEEDBACK_TONE_ICONS: Readonly<
|
|
20
|
+
Record<FeedbackTone, ComponentType<IconProps>>
|
|
21
|
+
> = {
|
|
22
|
+
info: InfoOutlined,
|
|
23
|
+
success: SuccessOutlined,
|
|
24
|
+
warning: WarningOutlined,
|
|
25
|
+
error: ErrorOutlined,
|
|
16
26
|
};
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import { ImageOutlined } from '@unif/react-native-icons';
|
|
1
2
|
import { useEffect, useState } from 'react';
|
|
2
3
|
import { Image, View } from 'react-native';
|
|
3
|
-
import {
|
|
4
|
+
import { Thumbnail, r, useColors } from '@unif/react-native-design';
|
|
4
5
|
import { styles } from './styles';
|
|
5
6
|
import type { ImageRatio, MarkdownImageProps } from './types';
|
|
6
7
|
|
|
7
8
|
export function MarkdownImage({ uri, label }: MarkdownImageProps) {
|
|
9
|
+
const colors = useColors();
|
|
8
10
|
const [width, setWidth] = useState(1);
|
|
9
11
|
const [ratio, setRatio] = useState<ImageRatio | undefined>(undefined);
|
|
10
12
|
useEffect(() => {
|
|
@@ -44,7 +46,7 @@ export function MarkdownImage({ uri, label }: MarkdownImageProps) {
|
|
|
44
46
|
borderRadius: 0,
|
|
45
47
|
}}
|
|
46
48
|
resizeMode="contain"
|
|
47
|
-
fallback={<
|
|
49
|
+
fallback={<ImageOutlined size={r(18)} color={colors.foregroundMuted} />}
|
|
48
50
|
accessibilityLabel={label || '图片'}
|
|
49
51
|
/>
|
|
50
52
|
</View>
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AlertOutlined } from '@unif/react-native-icons';
|
|
1
2
|
import { Pressable, Text, View } from 'react-native';
|
|
2
3
|
import {
|
|
3
4
|
Button,
|
|
@@ -142,7 +143,7 @@ export function Message(props: MessageProps) {
|
|
|
142
143
|
<View style={[styles.failureRow, placement === 'end' && styles.end]}>
|
|
143
144
|
{bubble}
|
|
144
145
|
<IconButton
|
|
145
|
-
icon=
|
|
146
|
+
icon={AlertOutlined}
|
|
146
147
|
size="sm"
|
|
147
148
|
variant="ghost"
|
|
148
149
|
color={colors.error}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ArrowDownOutlined } from '@unif/react-native-icons';
|
|
1
2
|
import { useEffect, useRef } from 'react';
|
|
2
3
|
import { Animated, View } from 'react-native';
|
|
3
4
|
import {
|
|
@@ -39,7 +40,7 @@ export function MessageListEndButton({
|
|
|
39
40
|
</View>
|
|
40
41
|
) : null}
|
|
41
42
|
<IconButton
|
|
42
|
-
icon=
|
|
43
|
+
icon={ArrowDownOutlined}
|
|
43
44
|
accessibilityLabel={busy ? '回到最新消息,正在处理' : '回到最新消息'}
|
|
44
45
|
variant="glass"
|
|
45
46
|
size="md"
|
|
@@ -2,7 +2,7 @@ import { useEffect, useState } from 'react';
|
|
|
2
2
|
import { Text, View } from 'react-native';
|
|
3
3
|
import {
|
|
4
4
|
Button,
|
|
5
|
-
|
|
5
|
+
r,
|
|
6
6
|
useColors,
|
|
7
7
|
useThemedStyles,
|
|
8
8
|
} from '@unif/react-native-design';
|
|
@@ -130,6 +130,7 @@ export function Process(props: ProcessProps): React.JSX.Element {
|
|
|
130
130
|
onToggle={() => toggleDetails(step.id)}
|
|
131
131
|
/>
|
|
132
132
|
);
|
|
133
|
+
const Glyph = PROCESS_STATUS_ICONS[step.status];
|
|
133
134
|
return (
|
|
134
135
|
<View
|
|
135
136
|
key={step.id}
|
|
@@ -150,8 +151,8 @@ export function Process(props: ProcessProps): React.JSX.Element {
|
|
|
150
151
|
accessible
|
|
151
152
|
accessibilityLabel={`${step.title},${statusLabel}`}
|
|
152
153
|
>
|
|
153
|
-
<
|
|
154
|
-
|
|
154
|
+
<Glyph
|
|
155
|
+
size={r(18)}
|
|
155
156
|
color={
|
|
156
157
|
step.status === 'failed'
|
|
157
158
|
? colors.error
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ChevronDownOutlined,
|
|
3
|
+
ChevronUpOutlined,
|
|
4
|
+
SparkOutlined,
|
|
5
|
+
} from '@unif/react-native-icons';
|
|
1
6
|
import { Pressable, ScrollView, Text, View } from 'react-native';
|
|
2
7
|
import {
|
|
3
8
|
Button,
|
|
4
|
-
Icon,
|
|
5
9
|
Pulse,
|
|
6
10
|
Reveal,
|
|
7
11
|
motion,
|
|
@@ -32,24 +36,28 @@ export function ProcessCompactStep({
|
|
|
32
36
|
: step.status === 'failed'
|
|
33
37
|
? colors.error
|
|
34
38
|
: colors.foregroundMuted;
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
const Glyph =
|
|
40
|
+
step.icon ??
|
|
41
|
+
(running || step.status === 'completed'
|
|
42
|
+
? SparkOutlined
|
|
43
|
+
: PROCESS_STATUS_ICONS[step.status]);
|
|
44
|
+
const icon =
|
|
45
|
+
step.icon === null ? null : (
|
|
46
|
+
<Glyph
|
|
47
|
+
size={14}
|
|
48
|
+
color={step.icon === undefined ? color : colors.foregroundMuted}
|
|
49
|
+
/>
|
|
50
|
+
);
|
|
51
|
+
const Glyph2 = expanded ? ChevronUpOutlined : ChevronDownOutlined;
|
|
46
52
|
return (
|
|
47
53
|
<View>
|
|
48
54
|
<Pressable
|
|
49
55
|
testID={`process-step-${step.id}-toggle`}
|
|
50
56
|
accessible
|
|
51
57
|
accessibilityRole={hasDetails ? 'button' : undefined}
|
|
52
|
-
accessibilityLabel={
|
|
58
|
+
accessibilityLabel={[step.title, statusText, elapsed]
|
|
59
|
+
.filter(Boolean)
|
|
60
|
+
.join(',')}
|
|
53
61
|
accessibilityState={hasDetails ? { expanded } : undefined}
|
|
54
62
|
disabled={!hasDetails}
|
|
55
63
|
hitSlop={10}
|
|
@@ -65,7 +73,7 @@ export function ProcessCompactStep({
|
|
|
65
73
|
<View style={styles.spacer} />
|
|
66
74
|
</>
|
|
67
75
|
) : null}
|
|
68
|
-
{running ? (
|
|
76
|
+
{running && icon ? (
|
|
69
77
|
<Pulse from={0.4} duration={motion.pulse / 2}>
|
|
70
78
|
{icon}
|
|
71
79
|
</Pulse>
|
|
@@ -81,14 +89,12 @@ export function ProcessCompactStep({
|
|
|
81
89
|
{step.title}
|
|
82
90
|
</Text>
|
|
83
91
|
) : null}
|
|
84
|
-
|
|
92
|
+
{statusText ? (
|
|
93
|
+
<Text style={styles.compactStatus}>{statusText}</Text>
|
|
94
|
+
) : null}
|
|
85
95
|
{elapsed ? <Text style={styles.elapsed}>{elapsed}</Text> : null}
|
|
86
96
|
{hasDetails ? (
|
|
87
|
-
<
|
|
88
|
-
name={expanded ? 'chevron-up' : 'chevron-down'}
|
|
89
|
-
size={14}
|
|
90
|
-
color={colors.foregroundSubtle}
|
|
91
|
-
/>
|
|
97
|
+
<Glyph2 size={14} color={colors.foregroundSubtle} />
|
|
92
98
|
) : null}
|
|
93
99
|
</Pressable>
|
|
94
100
|
{step.description ? (
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { CloseOutlined } from '@unif/react-native-icons';
|
|
1
2
|
import { Text, View } from 'react-native';
|
|
2
3
|
import {
|
|
3
4
|
Button,
|
|
4
|
-
Icon,
|
|
5
5
|
StatusDot,
|
|
6
6
|
icon,
|
|
7
7
|
useColors,
|
|
@@ -35,7 +35,7 @@ export function ProcessTimelineStep({
|
|
|
35
35
|
>
|
|
36
36
|
<View style={styles.timelineGutter}>
|
|
37
37
|
{step.status === 'cancelled' ? (
|
|
38
|
-
<
|
|
38
|
+
<CloseOutlined size={icon.xs} color={colors.foregroundSubtle} />
|
|
39
39
|
) : (
|
|
40
40
|
<StatusDot
|
|
41
41
|
status={status}
|
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
CircleMinusOutlined,
|
|
3
|
+
CloseOutlined,
|
|
4
|
+
ErrorOutlined,
|
|
5
|
+
SuccessOutlined,
|
|
6
|
+
ThinkingOutlined,
|
|
7
|
+
} from '@unif/react-native-icons';
|
|
8
|
+
import type { ComponentType } from 'react';
|
|
9
|
+
import type { IconProps } from '@unif/react-native-icons';
|
|
10
|
+
|
|
2
11
|
import type { ProcessStepStatus } from './types';
|
|
3
12
|
|
|
4
13
|
export const PROCESS_STATUS_LABELS: Readonly<
|
|
@@ -12,11 +21,11 @@ export const PROCESS_STATUS_LABELS: Readonly<
|
|
|
12
21
|
};
|
|
13
22
|
|
|
14
23
|
export const PROCESS_STATUS_ICONS: Readonly<
|
|
15
|
-
Record<ProcessStepStatus,
|
|
24
|
+
Record<ProcessStepStatus, ComponentType<IconProps>>
|
|
16
25
|
> = {
|
|
17
|
-
pending:
|
|
18
|
-
running:
|
|
19
|
-
completed:
|
|
20
|
-
failed:
|
|
21
|
-
cancelled:
|
|
26
|
+
pending: CircleMinusOutlined,
|
|
27
|
+
running: ThinkingOutlined,
|
|
28
|
+
completed: SuccessOutlined,
|
|
29
|
+
failed: ErrorOutlined,
|
|
30
|
+
cancelled: CloseOutlined,
|
|
22
31
|
};
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import type { ComponentType } from 'react';
|
|
2
|
+
import type { IconProps } from '@unif/react-native-icons';
|
|
1
3
|
import type { ReactNode } from 'react';
|
|
4
|
+
|
|
2
5
|
import type { StyleProp, ViewStyle } from 'react-native';
|
|
3
6
|
import type { ChatAction } from '../../actions';
|
|
4
7
|
|
|
@@ -9,6 +12,8 @@ export interface ProcessStep {
|
|
|
9
12
|
id: string;
|
|
10
13
|
title: string;
|
|
11
14
|
status: ProcessStepStatus;
|
|
15
|
+
/** compact 的活动图标;null 不显示,省略时沿状态呈现。 */
|
|
16
|
+
icon?: ComponentType<IconProps> | null;
|
|
12
17
|
/** 调用者提供的状态显示文案;不改变 status 的语义。 */
|
|
13
18
|
statusText?: string;
|
|
14
19
|
description?: string;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { ChevronRightOutlined } from '@unif/react-native-icons';
|
|
1
2
|
import { Pressable, Text, View } from 'react-native';
|
|
2
|
-
import {
|
|
3
|
+
import { r, useColors, useThemedStyles } from '@unif/react-native-design';
|
|
3
4
|
import { DEFAULT_SOURCES_TITLE } from './constants';
|
|
4
5
|
import { createStyles } from './styles';
|
|
5
6
|
import type { SourceItem, SourcesProps } from './types';
|
|
@@ -12,6 +13,7 @@ export function Sources({
|
|
|
12
13
|
testID,
|
|
13
14
|
}: SourcesProps): React.JSX.Element | null {
|
|
14
15
|
const styles = useThemedStyles(createStyles);
|
|
16
|
+
const colors = useColors();
|
|
15
17
|
|
|
16
18
|
if (items.length === 0) return null;
|
|
17
19
|
|
|
@@ -26,7 +28,9 @@ export function Sources({
|
|
|
26
28
|
<Text style={styles.description}>{item.description}</Text>
|
|
27
29
|
) : null}
|
|
28
30
|
</View>
|
|
29
|
-
{showChevron ?
|
|
31
|
+
{showChevron ? (
|
|
32
|
+
<ChevronRightOutlined size={r(18)} color={colors.foregroundMuted} />
|
|
33
|
+
) : null}
|
|
30
34
|
</>
|
|
31
35
|
);
|
|
32
36
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { View } from 'react-native';
|
|
2
|
-
import { Chip,
|
|
2
|
+
import { Chip, useColors } from '@unif/react-native-design';
|
|
3
3
|
import { SUGGESTION_ICON_SIZE } from './constants';
|
|
4
4
|
import { styles } from './styles';
|
|
5
5
|
import type { SuggestionsProps } from './types';
|
|
@@ -29,11 +29,7 @@ export function Suggestions({
|
|
|
29
29
|
disabled={item.disabled}
|
|
30
30
|
leading={
|
|
31
31
|
item.icon ? (
|
|
32
|
-
<
|
|
33
|
-
name={item.icon}
|
|
34
|
-
size={SUGGESTION_ICON_SIZE}
|
|
35
|
-
color={colors.primary}
|
|
36
|
-
/>
|
|
32
|
+
<item.icon size={SUGGESTION_ICON_SIZE} color={colors.primary} />
|
|
37
33
|
) : undefined
|
|
38
34
|
}
|
|
39
35
|
onPress={onSelect ? () => onSelect(item) : undefined}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ComponentType } from 'react';
|
|
2
|
+
import type { IconProps } from '@unif/react-native-icons';
|
|
3
|
+
|
|
2
4
|
import type { StyleProp, ViewStyle } from 'react-native';
|
|
3
5
|
|
|
4
6
|
export interface SuggestionItem {
|
|
5
7
|
id: string;
|
|
6
8
|
label: string;
|
|
7
9
|
/** 14 布局单位的主题主色图标,普通与选中状态保持相同图标样式。 */
|
|
8
|
-
icon?:
|
|
10
|
+
icon?: ComponentType<IconProps>;
|
|
9
11
|
selected?: boolean;
|
|
10
12
|
loading?: boolean;
|
|
11
13
|
disabled?: boolean;
|