@unif/react-native-chat 3.6.1 → 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 +24 -16
- 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/Attachments/styles.js +4 -2
- package/lib/module/components/Attachments/styles.js.map +1 -1
- package/lib/module/components/Composer/Composer.js +10 -7
- 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/Composer/styles.js +5 -2
- package/lib/module/components/Composer/styles.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/MarkdownContent.js +3 -1
- package/lib/module/components/Message/MarkdownContent/MarkdownContent.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/MarkdownContent/types.js +2 -0
- package/lib/module/components/Message/Message.js +7 -5
- package/lib/module/components/Message/Message.js.map +1 -1
- package/lib/module/components/MessageList/MessageListEndButton.js +25 -26
- package/lib/module/components/MessageList/MessageListEndButton.js.map +1 -1
- package/lib/module/components/MessageList/styles.js +1 -2
- package/lib/module/components/MessageList/styles.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/Attachments/styles.d.ts +4 -2
- package/lib/typescript/src/components/Attachments/styles.d.ts.map +1 -1
- package/lib/typescript/src/components/Composer/Composer.d.ts.map +1 -1
- package/lib/typescript/src/components/Composer/styles.d.ts +3 -1
- package/lib/typescript/src/components/Composer/styles.d.ts.map +1 -1
- package/lib/typescript/src/components/Composer/types.d.ts +5 -3
- 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/MarkdownContent.d.ts +1 -1
- package/lib/typescript/src/components/Message/MarkdownContent/MarkdownContent.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/MarkdownContent/types.d.ts +2 -0
- package/lib/typescript/src/components/Message/MarkdownContent/types.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/MessageList/styles.d.ts +1 -2
- package/lib/typescript/src/components/MessageList/styles.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 +20 -20
- package/src/components/Attachments/constants.ts +14 -6
- package/src/components/Attachments/styles.ts +2 -2
- package/src/components/Composer/Composer.tsx +16 -5
- package/src/components/Composer/ComposerIconAction.tsx +3 -3
- package/src/components/Composer/styles.ts +3 -2
- package/src/components/Composer/types.ts +5 -3
- 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/MarkdownContent.tsx +2 -1
- package/src/components/Message/MarkdownContent/MarkdownImage/MarkdownImage.tsx +4 -2
- package/src/components/Message/MarkdownContent/types.ts +3 -0
- package/src/components/Message/Message.tsx +10 -3
- package/src/components/MessageList/MessageListEndButton.tsx +18 -24
- package/src/components/MessageList/styles.ts +1 -2
- 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
|
@@ -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,
|
|
@@ -14,6 +21,7 @@ import {
|
|
|
14
21
|
} from 'react-native';
|
|
15
22
|
import {
|
|
16
23
|
ActionMenuContent,
|
|
24
|
+
GlassLayer,
|
|
17
25
|
fixed,
|
|
18
26
|
Textarea,
|
|
19
27
|
useTheme,
|
|
@@ -118,7 +126,7 @@ export const Composer = forwardRef<ComposerHandle, ComposerProps>(
|
|
|
118
126
|
const moreAction =
|
|
119
127
|
actions.length > 0 ? (
|
|
120
128
|
<ComposerIconAction
|
|
121
|
-
icon=
|
|
129
|
+
icon={PlusOutlined}
|
|
122
130
|
label="更多操作"
|
|
123
131
|
expanded={menuOpen}
|
|
124
132
|
disabled={moreDisabled}
|
|
@@ -137,6 +145,7 @@ export const Composer = forwardRef<ComposerHandle, ComposerProps>(
|
|
|
137
145
|
}
|
|
138
146
|
}}
|
|
139
147
|
>
|
|
148
|
+
{surface === 'card' ? <GlassLayer style={styles.glass} /> : null}
|
|
140
149
|
{header != null ? (
|
|
141
150
|
<View
|
|
142
151
|
style={[
|
|
@@ -241,7 +250,7 @@ export const Composer = forwardRef<ComposerHandle, ComposerProps>(
|
|
|
241
250
|
<View style={styles.trailingActions}>
|
|
242
251
|
{voice ? (
|
|
243
252
|
<ComposerIconAction
|
|
244
|
-
icon=
|
|
253
|
+
icon={MicOutlined}
|
|
245
254
|
label="开始语音输入"
|
|
246
255
|
disabled={disabled || voice.disabled}
|
|
247
256
|
onPress={() => {
|
|
@@ -252,7 +261,9 @@ export const Composer = forwardRef<ComposerHandle, ComposerProps>(
|
|
|
252
261
|
) : null}
|
|
253
262
|
{showPrimary ? (
|
|
254
263
|
<ComposerIconAction
|
|
255
|
-
icon={
|
|
264
|
+
icon={
|
|
265
|
+
primaryAction.kind === 'send' ? SendOutlined : StopFilled
|
|
266
|
+
}
|
|
256
267
|
label={primaryLabel}
|
|
257
268
|
visual="primary"
|
|
258
269
|
disabled={primaryDisabled}
|
|
@@ -274,7 +285,7 @@ export const Composer = forwardRef<ComposerHandle, ComposerProps>(
|
|
|
274
285
|
{voice && voice.status !== 'idle' ? (
|
|
275
286
|
<View style={styles.voice}>
|
|
276
287
|
<ComposerIconAction
|
|
277
|
-
icon=
|
|
288
|
+
icon={CloseOutlined}
|
|
278
289
|
visual="cancel"
|
|
279
290
|
label="取消语音输入"
|
|
280
291
|
disabled={disabled || voice.disabled}
|
|
@@ -298,7 +309,7 @@ export const Composer = forwardRef<ComposerHandle, ComposerProps>(
|
|
|
298
309
|
</View>
|
|
299
310
|
{voice.status === 'listening' || voice.status === 'finishing' ? (
|
|
300
311
|
<ComposerIconAction
|
|
301
|
-
icon=
|
|
312
|
+
icon={StopFilled}
|
|
302
313
|
visual="primary"
|
|
303
314
|
label="停止语音输入"
|
|
304
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
|
|
@@ -9,10 +9,11 @@ export const createStyles = (colors: ColorTokens, shadows: ShadowTokens) =>
|
|
|
9
9
|
card: {
|
|
10
10
|
borderRadius: r(20),
|
|
11
11
|
borderWidth: 0.5,
|
|
12
|
-
borderColor: colors.
|
|
13
|
-
backgroundColor: colors.surface,
|
|
12
|
+
borderColor: colors.glassBorder,
|
|
14
13
|
...shadows.card,
|
|
15
14
|
},
|
|
15
|
+
// 仅材质层定义圆角,根容器保留浮菜单的溢出空间。
|
|
16
|
+
glass: { borderRadius: r(20) },
|
|
16
17
|
accessory: { padding: space[3] },
|
|
17
18
|
header: {
|
|
18
19
|
padding: space[2],
|
|
@@ -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 {
|
|
@@ -50,7 +52,7 @@ export interface ComposerProps {
|
|
|
50
52
|
voice?: ComposerVoiceControl;
|
|
51
53
|
header?: ReactNode;
|
|
52
54
|
footer?: ReactNode;
|
|
53
|
-
/** card
|
|
55
|
+
/** card 提供统一玻璃表面;plain 由外层提供表面,内部 Textarea 均不单独绘制表面。 */
|
|
54
56
|
surface?: 'card' | 'plain';
|
|
55
57
|
/** Textarea 整体最小高度(含内间距),默认 44,不低于最小触达高度。 */
|
|
56
58
|
minInputHeight?: number;
|
|
@@ -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
|
};
|
|
@@ -16,6 +16,7 @@ export function MarkdownContent({
|
|
|
16
16
|
text,
|
|
17
17
|
onLinkPress,
|
|
18
18
|
outgoing = false,
|
|
19
|
+
style,
|
|
19
20
|
}: MarkdownContentProps) {
|
|
20
21
|
const { scheme } = useTheme();
|
|
21
22
|
const styles = useThemedStyles(
|
|
@@ -96,5 +97,5 @@ export function MarkdownContent({
|
|
|
96
97
|
styles: markdown.styles,
|
|
97
98
|
});
|
|
98
99
|
const content = Children.toArray(nodes);
|
|
99
|
-
return content.length ? <View>{content}</View> : null;
|
|
100
|
+
return content.length ? <View style={style}>{content}</View> : null;
|
|
100
101
|
}
|
|
@@ -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,
|
|
@@ -49,7 +50,6 @@ export function Message(props: MessageProps) {
|
|
|
49
50
|
placement === 'end' && styles.outgoing,
|
|
50
51
|
],
|
|
51
52
|
surface === 'outlined' && styles.outlined,
|
|
52
|
-
status === 'failed' && styles.failed,
|
|
53
53
|
waiting &&
|
|
54
54
|
surface === 'bubble' &&
|
|
55
55
|
placement === 'start' &&
|
|
@@ -66,6 +66,7 @@ export function Message(props: MessageProps) {
|
|
|
66
66
|
text={props.text}
|
|
67
67
|
onLinkPress={props.onLinkPress}
|
|
68
68
|
outgoing={surface === 'bubble' && placement === 'end'}
|
|
69
|
+
style={status === 'failed' ? styles.failed : undefined}
|
|
69
70
|
/>
|
|
70
71
|
) : (
|
|
71
72
|
<Text
|
|
@@ -75,6 +76,7 @@ export function Message(props: MessageProps) {
|
|
|
75
76
|
surface === 'bubble' &&
|
|
76
77
|
placement === 'end' &&
|
|
77
78
|
styles.outgoingText,
|
|
79
|
+
status === 'failed' && styles.failed,
|
|
78
80
|
]}
|
|
79
81
|
numberOfLines={props.numberOfLines}
|
|
80
82
|
>
|
|
@@ -86,7 +88,12 @@ export function Message(props: MessageProps) {
|
|
|
86
88
|
)}
|
|
87
89
|
{waiting ? <MessageWaiting label={statusText} /> : null}
|
|
88
90
|
{statusText && !waiting ? (
|
|
89
|
-
<Text
|
|
91
|
+
<Text
|
|
92
|
+
style={[
|
|
93
|
+
styles.status,
|
|
94
|
+
status === 'failed' && [styles.errorText, styles.failed],
|
|
95
|
+
]}
|
|
96
|
+
>
|
|
90
97
|
{statusText}
|
|
91
98
|
</Text>
|
|
92
99
|
) : null}
|
|
@@ -136,7 +143,7 @@ export function Message(props: MessageProps) {
|
|
|
136
143
|
<View style={[styles.failureRow, placement === 'end' && styles.end]}>
|
|
137
144
|
{bubble}
|
|
138
145
|
<IconButton
|
|
139
|
-
icon=
|
|
146
|
+
icon={AlertOutlined}
|
|
140
147
|
size="sm"
|
|
141
148
|
variant="ghost"
|
|
142
149
|
color={colors.error}
|
|
@@ -1,8 +1,8 @@
|
|
|
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 {
|
|
4
5
|
IconButton,
|
|
5
|
-
Reveal,
|
|
6
6
|
Spinner,
|
|
7
7
|
usePrefersReducedMotion,
|
|
8
8
|
useThemedStyles,
|
|
@@ -33,29 +33,23 @@ export function MessageListEndButton({
|
|
|
33
33
|
}, [reducedMotion, scale]);
|
|
34
34
|
return (
|
|
35
35
|
<View style={styles.returnToEnd} pointerEvents="box-none">
|
|
36
|
-
<
|
|
37
|
-
|
|
38
|
-
style={
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
iconSize={18}
|
|
54
|
-
style={styles.returnButton}
|
|
55
|
-
onPress={onPress}
|
|
56
|
-
/>
|
|
57
|
-
</Animated.View>
|
|
58
|
-
</Reveal>
|
|
36
|
+
<Animated.View style={[styles.returnVisual, { transform: [{ scale }] }]}>
|
|
37
|
+
{busy ? (
|
|
38
|
+
<View style={styles.returnProgress} pointerEvents="none">
|
|
39
|
+
<Spinner size={44} thickness={2} />
|
|
40
|
+
</View>
|
|
41
|
+
) : null}
|
|
42
|
+
<IconButton
|
|
43
|
+
icon={ArrowDownOutlined}
|
|
44
|
+
accessibilityLabel={busy ? '回到最新消息,正在处理' : '回到最新消息'}
|
|
45
|
+
variant="glass"
|
|
46
|
+
size="md"
|
|
47
|
+
surfaceSize={36}
|
|
48
|
+
iconSize={18}
|
|
49
|
+
style={styles.returnButton}
|
|
50
|
+
onPress={onPress}
|
|
51
|
+
/>
|
|
52
|
+
</Animated.View>
|
|
59
53
|
</View>
|
|
60
54
|
);
|
|
61
55
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { StyleSheet } from 'react-native';
|
|
2
2
|
import type { ColorTokens, ShadowTokens } from '@unif/react-native-design';
|
|
3
|
-
export const createStyles = (
|
|
3
|
+
export const createStyles = (_colors: ColorTokens, shadows: ShadowTokens) =>
|
|
4
4
|
StyleSheet.create({
|
|
5
5
|
root: { flex: 1, minHeight: 0, minWidth: 0 },
|
|
6
6
|
list: { flex: 1 },
|
|
@@ -23,7 +23,6 @@ export const createStyles = (colors: ColorTokens, shadows: ShadowTokens) =>
|
|
|
23
23
|
returnButton: {
|
|
24
24
|
alignSelf: 'center',
|
|
25
25
|
borderRadius: 18,
|
|
26
|
-
backgroundColor: colors.surface,
|
|
27
26
|
...shadows.card,
|
|
28
27
|
},
|
|
29
28
|
});
|
|
@@ -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;
|