Skip to content

Commit 5b68170

Browse files
committed
fix: upload progress styles
1 parent 4d1cd3c commit 5b68170

6 files changed

Lines changed: 136 additions & 26 deletions

File tree

package/src/components/Attachment/AttachmentUploadIndicator.tsx

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { ActivityIndicator, StyleSheet, View } from 'react-native';
33
import type { StyleProp, ViewStyle } from 'react-native';
44

55
import { CircularProgressIndicator } from './CircularProgressIndicator';
6+
import { MediaUploadProgressOverlay } from './MediaUploadProgressOverlay';
67

78
import { useTheme } from '../../contexts/themeContext/ThemeContext';
89
import { usePendingAttachmentUpload } from '../../hooks/usePendingAttachmentUpload';
@@ -16,6 +17,7 @@ export type AttachmentUploadIndicatorProps = {
1617
strokeWidth?: number;
1718
style?: StyleProp<ViewStyle>;
1819
testID?: string;
20+
variant?: 'compact' | 'overlay';
1921
};
2022

2123
/**
@@ -28,18 +30,32 @@ export const AttachmentUploadIndicatorUI = ({
2830
strokeWidth = 2,
2931
style,
3032
testID,
33+
variant = 'compact',
3134
}: AttachmentUploadIndicatorProps) => {
3235
const {
3336
theme: { semantics },
3437
} = useTheme();
3538
const pendingUpload = usePendingAttachmentUpload(localId);
3639
const uploadProgress = pendingUpload.uploadProgress;
3740
const shouldRender = pendingUpload.isUploading;
41+
const resolvedSize = variant === 'overlay' && size === 16 ? 28 : size;
42+
const resolvedStrokeWidth = variant === 'overlay' && strokeWidth === 2 ? 3 : strokeWidth;
3843

3944
if (!shouldRender) {
4045
return null;
4146
}
4247

48+
if (variant === 'overlay') {
49+
return (
50+
<MediaUploadProgressOverlay
51+
progress={uploadProgress}
52+
size={resolvedSize}
53+
strokeWidth={resolvedStrokeWidth}
54+
testID={testID}
55+
/>
56+
);
57+
}
58+
4359
return (
4460
<View pointerEvents='none' style={containerStyle}>
4561
{uploadProgress === undefined ? (
@@ -52,12 +68,14 @@ export const AttachmentUploadIndicatorUI = ({
5268
</View>
5369
) : (
5470
<CircularProgressIndicator
55-
color={semantics.accentPrimary}
71+
backgroundColor={semantics.backgroundCoreElevation0}
72+
filledColor={semantics.accentPrimary}
5673
progress={uploadProgress}
57-
size={size}
58-
strokeWidth={strokeWidth}
74+
size={resolvedSize}
75+
strokeWidth={resolvedStrokeWidth}
5976
style={style}
6077
testID={testID}
78+
unfilledColor={semantics.borderCoreDefault}
6179
/>
6280
)}
6381
</View>
@@ -68,6 +86,7 @@ export const AttachmentUploadIndicator = ({
6886
containerStyle,
6987
localId,
7088
sourceUrl,
89+
variant,
7190
...props
7291
}: AttachmentUploadIndicatorProps) => {
7392
const shouldTrackPendingUpload = !!localId && !!sourceUrl && isLocalUrl(sourceUrl);
@@ -81,6 +100,7 @@ export const AttachmentUploadIndicator = ({
81100
{...props}
82101
containerStyle={containerStyle}
83102
localId={localId}
103+
variant={variant}
84104
/>
85105
);
86106
};

package/src/components/Attachment/CircularProgressIndicator.tsx

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ const PROGRESS_ANIMATION_DURATION_MS = 1200;
1717

1818
export type CircularProgressIndicatorProps = {
1919
/** Upload percent **0–100**. */
20+
backgroundColor: ColorValue;
21+
filledColor: ColorValue;
2022
progress: number;
21-
color: ColorValue;
23+
unfilledColor: ColorValue;
2224
size?: number;
2325
strokeWidth?: number;
2426
style?: StyleProp<ViewStyle>;
@@ -29,12 +31,14 @@ export type CircularProgressIndicatorProps = {
2931
* Circular upload progress ring (determinate) or rotating arc (indeterminate).
3032
*/
3133
export const CircularProgressIndicator = ({
32-
color,
34+
backgroundColor,
35+
filledColor,
3336
progress,
3437
size = 16,
3538
strokeWidth = 2,
3639
style,
3740
testID,
41+
unfilledColor,
3842
}: CircularProgressIndicatorProps) => {
3943
const animatedProgress = useSharedValue(0);
4044
const rotation = useSharedValue(0);
@@ -99,13 +103,21 @@ export const CircularProgressIndicator = ({
99103
if (fraction !== undefined) {
100104
return (
101105
<Svg height={size} style={style} testID={testID} viewBox={`0 0 ${size} ${size}`} width={size}>
106+
<Circle
107+
cx={cx}
108+
cy={cy}
109+
fill={backgroundColor}
110+
r={r}
111+
stroke={unfilledColor}
112+
strokeWidth={strokeWidth}
113+
/>
102114
<AnimatedCircle
103115
animatedProps={animatedCircleProps}
104116
cx={cx}
105117
cy={cy}
106118
fill='none'
107119
r={r}
108-
stroke={color as string}
120+
stroke={filledColor}
109121
strokeDasharray={`${circumference}`}
110122
strokeLinecap='round'
111123
strokeWidth={strokeWidth}
@@ -124,12 +136,20 @@ export const CircularProgressIndicator = ({
124136
testID={testID}
125137
>
126138
<Svg height={size} viewBox={`0 0 ${size} ${size}`} width={size}>
139+
<Circle
140+
cx={cx}
141+
cy={cy}
142+
fill={backgroundColor}
143+
r={r}
144+
stroke={unfilledColor}
145+
strokeWidth={strokeWidth}
146+
/>
127147
<Circle
128148
cx={cx}
129149
cy={cy}
130150
fill='none'
131151
r={r}
132-
stroke={color as string}
152+
stroke={filledColor}
133153
strokeDasharray={`${arc} ${gap}`}
134154
strokeLinecap='round'
135155
strokeWidth={strokeWidth}

package/src/components/Attachment/Gallery.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -378,9 +378,9 @@ const GalleryImageThumbnail = ({
378378
/>
379379
{isLoadingImage ? <ImageLoadingIndicator /> : null}
380380
<AttachmentUploadIndicator
381-
containerStyle={styles.uploadProgressOnImage}
382381
localId={thumbnail.localId}
383382
sourceUrl={thumbnail.url}
383+
variant='overlay'
384384
/>
385385
</>
386386
)}
@@ -604,11 +604,6 @@ const useStyles = () => {
604604
top: 0,
605605
overflow: 'hidden',
606606
},
607-
uploadProgressOnImage: {
608-
bottom: primitives.spacingXxs,
609-
left: primitives.spacingXxs,
610-
position: 'absolute',
611-
},
612607
});
613608
}, [semantics, isMyMessage]);
614609
};
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import React, { useMemo } from 'react';
2+
import { ActivityIndicator, StyleSheet, View } from 'react-native';
3+
4+
import { CircularProgressIndicator } from './CircularProgressIndicator';
5+
6+
import { useTheme } from '../../contexts/themeContext/ThemeContext';
7+
8+
export type MediaUploadProgressOverlayProps = {
9+
progress?: number;
10+
size?: number;
11+
strokeWidth?: number;
12+
testID?: string;
13+
};
14+
15+
/**
16+
* Full-cover upload overlay for image and video thumbnails.
17+
*/
18+
export const MediaUploadProgressOverlay = ({
19+
progress,
20+
size = 18,
21+
strokeWidth = 3,
22+
testID,
23+
}: MediaUploadProgressOverlayProps) => {
24+
const styles = useStyles();
25+
const {
26+
theme: {
27+
messageItemView: { attachmentUploadIndicator },
28+
semantics,
29+
},
30+
} = useTheme();
31+
32+
return (
33+
<View
34+
pointerEvents='none'
35+
style={[
36+
StyleSheet.absoluteFill,
37+
styles.indicatorContainer,
38+
attachmentUploadIndicator.overlayContent,
39+
]}
40+
testID={testID ? `${testID}-content` : undefined}
41+
>
42+
{typeof progress === 'number' ? (
43+
<CircularProgressIndicator
44+
backgroundColor={semantics.backgroundCoreElevation0}
45+
filledColor={semantics.accentPrimary}
46+
progress={progress}
47+
size={size}
48+
strokeWidth={strokeWidth}
49+
style={attachmentUploadIndicator.indicator}
50+
unfilledColor={semantics.borderCoreDefault}
51+
/>
52+
) : (
53+
<ActivityIndicator
54+
color={semantics.accentPrimary}
55+
style={attachmentUploadIndicator.indicator}
56+
/>
57+
)}
58+
</View>
59+
);
60+
};
61+
62+
const useStyles = () => {
63+
const {
64+
theme: { semantics },
65+
} = useTheme();
66+
return useMemo(
67+
() =>
68+
StyleSheet.create({
69+
indicatorContainer: {
70+
alignItems: 'center',
71+
justifyContent: 'center',
72+
backgroundColor: semantics.backgroundCoreOverlayLight,
73+
},
74+
}),
75+
[semantics],
76+
);
77+
};

package/src/components/Attachment/VideoThumbnail.tsx

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,9 @@ import { AttachmentUploadIndicator } from './AttachmentUploadIndicator';
55

66
import { useComponentsContext } from '../../contexts/componentsContext/ComponentsContext';
77
import { useTheme } from '../../contexts/themeContext/ThemeContext';
8-
import { primitives } from '../../theme';
98
import { VideoPlayIndicator } from '../ui/VideoPlayIndicator';
109

1110
const styles = StyleSheet.create({
12-
uploadProgressContainer: {
13-
alignItems: 'flex-start',
14-
bottom: primitives.spacingXxs,
15-
justifyContent: 'flex-start',
16-
left: primitives.spacingXxs,
17-
position: 'absolute',
18-
},
1911
container: {
2012
alignItems: 'center',
2113
justifyContent: 'center',
@@ -53,11 +45,7 @@ export const VideoThumbnail = (props: VideoThumbnailProps) => {
5345
style={[StyleSheet.absoluteFill, imageStyle]}
5446
/>
5547
<VideoPlayIndicator size='md' />
56-
<AttachmentUploadIndicator
57-
containerStyle={styles.uploadProgressContainer}
58-
localId={localId}
59-
sourceUrl={thumb_url}
60-
/>
48+
<AttachmentUploadIndicator localId={localId} sourceUrl={thumb_url} variant='overlay' />
6149
</View>
6250
);
6351
};

package/src/contexts/themeContext/utils/theme.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,11 @@ export type Theme = {
677677
attachmentContainer: ViewStyle;
678678
container: ViewStyle;
679679
};
680+
attachmentUploadIndicator: {
681+
indicator: ViewStyle;
682+
overlay: ViewStyle;
683+
overlayContent: ViewStyle;
684+
};
680685
gallery: {
681686
galleryContainer: ViewStyle;
682687
galleryItemColumn: ViewStyle;
@@ -1602,6 +1607,11 @@ export const defaultTheme: Theme = {
16021607
attachmentContainer: {},
16031608
container: {},
16041609
},
1610+
attachmentUploadIndicator: {
1611+
indicator: {},
1612+
overlay: {},
1613+
overlayContent: {},
1614+
},
16051615
gallery: {
16061616
galleryContainer: {},
16071617
galleryItemColumn: {},

0 commit comments

Comments
 (0)