Skip to content

Commit

Permalink
Merge pull request #928 from thundersdata-frontend/rn-issue
Browse files Browse the repository at this point in the history
feat: 优化弹窗类组件的显示方式
  • Loading branch information
chj-damon authored Jan 20, 2025
2 parents acf3f5a + d035cb8 commit 5195d22
Show file tree
Hide file tree
Showing 19 changed files with 231 additions and 283 deletions.
8 changes: 8 additions & 0 deletions .changeset/kind-guests-clap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@td-design/react-native-image-picker': patch
'@td-design/react-native-picker': patch
'@td-design/react-native-share': patch
'@td-design/react-native': patch
---

feat: 优化弹窗类组件的显示方式
59 changes: 6 additions & 53 deletions packages/react-native-image-picker/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React, { forwardRef, useImperativeHandle } from 'react';
import { Image, TouchableWithoutFeedback } from 'react-native';
import { Image } from 'react-native';
import { CameraOptions } from 'react-native-image-picker';

import { ActionSheet, Box, helpers, Indicator, Modal, Pressable, Theme, useTheme } from '@td-design/react-native';
import { Box, helpers, Indicator, Pressable, Theme, useTheme } from '@td-design/react-native';

import { ImagePickerProps, ImagePickerRef } from './type';
import useImagePicker from './useImagePicker';

const { px, ONE_PIXEL, deviceWidth, deviceHeight } = helpers;
const { px, ONE_PIXEL } = helpers;
const { UIActivityIndicator } = Indicator;

const cameraOptions: CameraOptions = {
Expand All @@ -28,8 +28,6 @@ const ImagePicker = forwardRef<ImagePickerRef, ImagePickerProps>(
showUploadImg = true,
launchLibraryText = '打开相册',
launchCameraText = '打开摄像头',
previewImgText = '预览图片',
deleteImgText = '删除图片',
children,
onBeforeUpload,
onUpload,
Expand All @@ -43,22 +41,7 @@ const ImagePicker = forwardRef<ImagePickerRef, ImagePickerProps>(
) => {
const theme = useTheme<Theme>();

const {
currentImgSource,
loading,
launchLibrary,
launchCamera,
launchVisible,
previewImage,
deleteImage,
handlePress,
handleLongPress,
previewVisible,
visible,
setVisibleFalse,
setLaunchVisibleFalse,
setPreviewVisibleFalse,
} = useImagePicker({
const { currentImgSource, loading, handlePress } = useImagePicker({
value,
showUploadImg,
options,
Expand All @@ -68,6 +51,8 @@ const ImagePicker = forwardRef<ImagePickerRef, ImagePickerProps>(
onCancel,
onFail,
onGrantFail,
launchLibraryText,
launchCameraText,
});

useImperativeHandle(ref, () => ({}));
Expand All @@ -77,7 +62,6 @@ const ImagePicker = forwardRef<ImagePickerRef, ImagePickerProps>(
<Pressable
activeOpacity={activeOpacity}
onPress={handlePress}
onLongPress={handleLongPress}
disabled={loading}
style={{ justifyContent: 'center', alignItems: 'flex-start', width, height }}
>
Expand Down Expand Up @@ -110,37 +94,6 @@ const ImagePicker = forwardRef<ImagePickerRef, ImagePickerProps>(
<UIActivityIndicator size={px(24)} color={theme.colors.primary200} />
</Box>
)}
{/* 打开相册或者打开相机 */}
<ActionSheet
items={[
{ text: launchLibraryText, onPress: launchLibrary },
{ text: launchCameraText, onPress: launchCamera },
]}
onCancel={setLaunchVisibleFalse}
visible={launchVisible}
/>
{/* 预览图片或者删除图片 */}
<ActionSheet
items={[
{ text: previewImgText, onPress: previewImage },
{ text: deleteImgText, onPress: deleteImage, type: 'danger' },
]}
onCancel={setVisibleFalse}
visible={visible}
/>
{/* 弹窗预览图片 */}
<Modal visible={previewVisible} onClose={setPreviewVisibleFalse} position="fullscreen">
<TouchableWithoutFeedback onPress={setPreviewVisibleFalse}>
<Image
source={{ uri: currentImgSource }}
style={{
width: deviceWidth,
height: deviceHeight,
}}
resizeMode="contain"
/>
</TouchableWithoutFeedback>
</Modal>
</Box>
);
}
Expand Down
14 changes: 9 additions & 5 deletions packages/react-native-image-picker/src/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,20 @@ export type ImagePickerProps = PropsWithChildren<{
launchLibraryText?: string;
/** 打开摄像头文本 */
launchCameraText?: string;
/** 预览图片文本 */
previewImgText?: string;
/** 删除图片文本 */
deleteImgText?: string;
/** 按下时的不透明度 */
activeOpacity?: number;
}>;

export type HookProps = Pick<
ImagePickerProps,
'value' | 'onBeforeUpload' | 'onUpload' | 'onAfterUpload' | 'onCancel' | 'onFail' | 'onGrantFail'
| 'value'
| 'onBeforeUpload'
| 'onUpload'
| 'onAfterUpload'
| 'onCancel'
| 'onFail'
| 'onGrantFail'
| 'launchLibraryText'
| 'launchCameraText'
> &
Required<Pick<ImagePickerProps, 'options' | 'showUploadImg'>>;
48 changes: 10 additions & 38 deletions packages/react-native-image-picker/src/useImagePicker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import { useEffect } from 'react';
import { Keyboard, PermissionsAndroid, Platform } from 'react-native';
import { ImagePickerResponse, launchImageLibrary, launchCamera as launchRNCamera } from 'react-native-image-picker';

import { ActionSheet } from '@td-design/react-native';
import type { File } from '@td-design/react-native';
import { useBoolean, useSafeState } from '@td-design/rn-hooks';
import { useSafeState } from '@td-design/rn-hooks';

import { HookProps } from './type';

Expand All @@ -24,14 +25,9 @@ export default function useImagePicker({
onCancel,
onFail,
onGrantFail,
launchLibraryText,
launchCameraText,
}: HookProps) {
/** 打开相册或者摄像头的ActionSheet */
const [launchVisible, { setTrue: setLaunchVisibleTrue, setFalse: setLaunchVisibleFalse }] = useBoolean(false);
/** 打开预览或者删除的ActionSheet */
const [visible, { setTrue: setVisibleTrue, setFalse: setVisibleFalse }] = useBoolean(false);
/** 打开预览图片的弹窗 */
const [previewVisible, { setTrue: setPreviewVisibleTrue, setFalse: setPreviewVisibleFalse }] = useBoolean(false);

const [currentImgSource, setCurrentImgSource] = useSafeState<string | undefined>(getSource(value));
const [loading, setLoading] = useSafeState(false);

Expand Down Expand Up @@ -95,43 +91,19 @@ export default function useImagePicker({
}
};

const previewImage = () => {
setVisibleFalse();
setPreviewVisibleTrue();
};

const deleteImage = () => {
onAfterUpload?.(undefined);
setCurrentImgSource(undefined);
setVisibleFalse();
};

const handlePress = () => {
Keyboard.dismiss();
setLaunchVisibleTrue();
};

const handleLongPress = () => {
Keyboard.dismiss();
if (showUploadImg && currentImgSource) {
setVisibleTrue();
}
ActionSheet.show({
items: [
{ text: launchLibraryText!, onPress: launchLibrary },
{ text: launchCameraText!, onPress: launchCamera },
],
});
};

return {
currentImgSource,
loading,
launchLibrary,
launchCamera,
launchVisible,
previewImage,
deleteImage,
handlePress,
handleLongPress,
previewVisible,
visible,
setVisibleFalse,
setLaunchVisibleFalse,
setPreviewVisibleFalse,
};
}
52 changes: 40 additions & 12 deletions packages/react-native-share/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { FC, ReactNode } from 'react';
import React, { FC, ReactNode, useState } from 'react';
import { Linking, ScrollView, StyleSheet } from 'react-native';

import { Box, helpers, Modal, Pressable, Text, Theme, useTheme } from '@td-design/react-native';
import { Box, helpers, Modal, Portal, Pressable, Text, Theme, useTheme } from '@td-design/react-native';

import Alipay from './svg/alipay';
import Dingding from './svg/dingding';
Expand Down Expand Up @@ -29,12 +29,8 @@ export interface ShareAction {
onPress: () => void;
}
interface ShareProps {
/** 是否显示操作面板 */
visible: boolean;
/** 按下时的不透明度 */
activeOpacity?: number;
/** 关闭操作面板 */
onCancel: () => void;
/** 关闭文字 */
cancelText?: string;
/** 刷新文字 */
Expand All @@ -56,12 +52,11 @@ interface ShareProps {
onShareQQMail?: () => void;
}

const Share: FC<ShareProps> = ({
visible,
const ShareContent: FC<ShareProps & { onAnimationEnd: (visible: boolean) => void }> = ({
activeOpacity = 0.6,
onCancel,
cancelText = '取消',
refreshText = '刷新',
onAnimationEnd,
onRefresh,
extraShares = [],
extraActions = [],
Expand All @@ -75,6 +70,8 @@ const Share: FC<ShareProps> = ({
onShareZhihu,
onShareQQMail,
}) => {
const [visible, setVisible] = useState(true);

const theme = useTheme<Theme>();
const styles = StyleSheet.create({
action: {
Expand Down Expand Up @@ -202,19 +199,50 @@ const Share: FC<ShareProps> = ({
};

return (
<Modal visible={visible} onClose={onCancel}>
<Modal.Content
position="bottom"
maskVisible
maskClosable
animationType="slide"
onAnimationEnd={onAnimationEnd}
visible={visible}
onClose={() => setVisible(false)}
>
<ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles.content1}>
{_actions.map(renderShareItem)}
</ScrollView>
<ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles.content2}>
{secondaryActions.map(renderActionItem)}
</ScrollView>
<Pressable activeOpacity={activeOpacity} onPress={onCancel} style={styles.action}>
<Pressable
activeOpacity={activeOpacity}
onPress={() => {
setVisible(false);
}}
style={styles.action}
>
<Text variant="p0" color="text">
{cancelText}
</Text>
</Pressable>
</Modal>
</Modal.Content>
);
};

const Share = () => null;

Share.displayName = 'Share';

Share.show = (props: ShareProps) => {
const key = Portal.add(
<ShareContent
{...props}
onAnimationEnd={visible => {
if (!visible) {
Portal.remove(key);
}
}}
/>
);
};

Expand Down
Loading

0 comments on commit 5195d22

Please sign in to comment.