Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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