Merge branch 'develop' of https://github.com/RocketChat/Rocket.Chat.ReactNative into fdroid-build
This commit is contained in:
commit
a4055dab93
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { View } from 'react-native';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
import FastImage from '@rocket.chat/react-native-fast-image';
|
||||
import Touchable from 'react-native-platform-touchable';
|
||||
import { settings as RocketChatSettings } from '@rocket.chat/sdk';
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
import FastImage from '@rocket.chat/react-native-fast-image';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const CustomEmoji = React.memo(({ baseUrl, emoji, style }) => (
|
||||
|
|
|
@ -90,6 +90,8 @@ const NotifierComponent = React.memo(({
|
|||
|
||||
if (isMasterDetail) {
|
||||
Navigation.navigate('DrawerNavigator');
|
||||
} else {
|
||||
Navigation.navigate('RoomsListView');
|
||||
}
|
||||
goRoom({ item, isMasterDetail });
|
||||
hideNotification();
|
||||
|
|
|
@ -201,7 +201,13 @@ const MessageActions = React.memo(forwardRef(({
|
|||
hideActionSheet();
|
||||
};
|
||||
|
||||
const handleReadReceipt = message => Navigation.navigate('ReadReceiptsView', { messageId: message.id });
|
||||
const handleReadReceipt = (message) => {
|
||||
if (isMasterDetail) {
|
||||
Navigation.navigate('ModalStackNavigator', { screen: 'ReadReceiptsView', params: { messageId: message.id } });
|
||||
} else {
|
||||
Navigation.navigate('ReadReceiptsView', { messageId: message.id });
|
||||
}
|
||||
};
|
||||
|
||||
const handleToggleTranslation = async(message) => {
|
||||
try {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useContext, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { TouchableOpacity } from 'react-native';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
import FastImage from '@rocket.chat/react-native-fast-image';
|
||||
|
||||
import styles from '../styles';
|
||||
import { CustomIcon } from '../../../lib/Icons';
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { View, StyleSheet } from 'react-native';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
import FastImage from '@rocket.chat/react-native-fast-image';
|
||||
import PropTypes from 'prop-types';
|
||||
import { BLOCK_CONTEXT } from '@rocket.chat/ui-kit';
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
|||
import { Text, View } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
import Touchable from 'react-native-platform-touchable';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
import FastImage from '@rocket.chat/react-native-fast-image';
|
||||
|
||||
import { themes } from '../../../constants/colors';
|
||||
import { textParser } from '../utils';
|
||||
|
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
|||
import { Text, FlatList } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
import Touchable from 'react-native-platform-touchable';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
import FastImage from '@rocket.chat/react-native-fast-image';
|
||||
|
||||
import Separator from '../../Separator';
|
||||
import Check from '../../Check';
|
||||
|
|
|
@ -383,9 +383,9 @@ class Markdown extends PureComponent {
|
|||
m = m.replace(/^\[([\s]]*)\]\(([^)]*)\)\s/, '').trim();
|
||||
|
||||
if (preview) {
|
||||
m = m.replace(/\n+/g, ' ');
|
||||
m = shortnameToUnicode(m);
|
||||
m = removeMarkdown(m);
|
||||
m = m.replace(/\n+/g, ' ');
|
||||
return (
|
||||
<Text accessibilityLabel={m} style={[styles.text, { color: themes[theme].bodyText }, ...style]} numberOfLines={numberOfLines} testID={testID}>
|
||||
{m}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useContext } from 'react';
|
||||
import { View } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
import FastImage from '@rocket.chat/react-native-fast-image';
|
||||
import equal from 'deep-equal';
|
||||
import { createImageProgress } from 'react-native-image-progress';
|
||||
import * as Progress from 'react-native-progress';
|
||||
|
|
|
@ -3,7 +3,7 @@ import {
|
|||
View, Text, StyleSheet, Clipboard
|
||||
} from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
import FastImage from '@rocket.chat/react-native-fast-image';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
|
||||
import Touchable from './Touchable';
|
||||
|
|
|
@ -6,7 +6,7 @@ export const ImageComponent = (type) => {
|
|||
const { Image } = require('react-native');
|
||||
Component = Image;
|
||||
} else {
|
||||
const FastImage = require('react-native-fast-image').default;
|
||||
const FastImage = require('@rocket.chat/react-native-fast-image').default;
|
||||
Component = FastImage;
|
||||
}
|
||||
return Component;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { View, Text } from 'react-native';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
import FastImage from '@rocket.chat/react-native-fast-image';
|
||||
|
||||
import Touch from '../../utils/touch';
|
||||
import Check from '../../containers/Check';
|
||||
|
|
|
@ -189,7 +189,7 @@ const ModalStackNavigator = React.memo(({ navigation }) => {
|
|||
<ModalStack.Screen
|
||||
name='ReadReceiptsView'
|
||||
component={ReadReceiptsView}
|
||||
options={ReadReceiptsView.navigationOptions}
|
||||
options={props => ReadReceiptsView.navigationOptions({ ...props, isMasterDetail: true })}
|
||||
/>
|
||||
<ModalStack.Screen
|
||||
name='SettingsView'
|
||||
|
|
|
@ -78,9 +78,7 @@ class MessagesView extends React.Component {
|
|||
}
|
||||
|
||||
defineMessagesViewContent = (name) => {
|
||||
const { messages } = this.state;
|
||||
const { user, baseUrl, theme } = this.props;
|
||||
|
||||
const renderItemCommonProps = item => ({
|
||||
item,
|
||||
baseUrl,
|
||||
|
@ -101,6 +99,7 @@ class MessagesView extends React.Component {
|
|||
Files: {
|
||||
name: I18n.t('Files'),
|
||||
fetchFunc: async() => {
|
||||
const { messages } = this.state;
|
||||
const result = await RocketChat.getFiles(this.rid, this.t, messages.length);
|
||||
return { ...result, messages: result.files };
|
||||
},
|
||||
|
@ -125,12 +124,15 @@ class MessagesView extends React.Component {
|
|||
// Mentions Messages Screen
|
||||
Mentions: {
|
||||
name: I18n.t('Mentions'),
|
||||
fetchFunc: () => RocketChat.getMessages(
|
||||
fetchFunc: () => {
|
||||
const { messages } = this.state;
|
||||
return RocketChat.getMessages(
|
||||
this.rid,
|
||||
this.t,
|
||||
{ 'mentions._id': { $in: [user.id] } },
|
||||
messages.length
|
||||
),
|
||||
);
|
||||
},
|
||||
noDataMsg: I18n.t('No_mentioned_messages'),
|
||||
testID: 'mentioned-messages-view',
|
||||
renderItem: item => (
|
||||
|
@ -144,12 +146,15 @@ class MessagesView extends React.Component {
|
|||
// Starred Messages Screen
|
||||
Starred: {
|
||||
name: I18n.t('Starred'),
|
||||
fetchFunc: () => RocketChat.getMessages(
|
||||
fetchFunc: () => {
|
||||
const { messages } = this.state;
|
||||
return RocketChat.getMessages(
|
||||
this.rid,
|
||||
this.t,
|
||||
{ 'starred._id': { $in: [user.id] } },
|
||||
messages.length
|
||||
),
|
||||
);
|
||||
},
|
||||
noDataMsg: I18n.t('No_starred_messages'),
|
||||
testID: 'starred-messages-view',
|
||||
renderItem: item => (
|
||||
|
@ -166,7 +171,10 @@ class MessagesView extends React.Component {
|
|||
// Pinned Messages Screen
|
||||
Pinned: {
|
||||
name: I18n.t('Pinned'),
|
||||
fetchFunc: () => RocketChat.getMessages(this.rid, this.t, { pinned: true }, messages.length),
|
||||
fetchFunc: () => {
|
||||
const { messages } = this.state;
|
||||
return RocketChat.getMessages(this.rid, this.t, { pinned: true }, messages.length);
|
||||
},
|
||||
noDataMsg: I18n.t('No_pinned_messages'),
|
||||
testID: 'pinned-messages-view',
|
||||
renderItem: item => (
|
||||
|
|
|
@ -8,6 +8,7 @@ import { connect } from 'react-redux';
|
|||
import Avatar from '../../containers/Avatar';
|
||||
import styles from './styles';
|
||||
import ActivityIndicator from '../../containers/ActivityIndicator';
|
||||
import { CloseModalButton } from '../../containers/HeaderButton';
|
||||
import I18n from '../../i18n';
|
||||
import RocketChat from '../../lib/rocketchat';
|
||||
import StatusBar from '../../containers/StatusBar';
|
||||
|
@ -17,8 +18,14 @@ import { getUserSelector } from '../../selectors/login';
|
|||
import SafeAreaView from '../../containers/SafeAreaView';
|
||||
|
||||
class ReadReceiptView extends React.Component {
|
||||
static navigationOptions = {
|
||||
static navigationOptions = ({ navigation, isMasterDetail }) => {
|
||||
const options = {
|
||||
title: I18n.t('Read_Receipt')
|
||||
};
|
||||
if (isMasterDetail) {
|
||||
options.headerLeft = () => <CloseModalButton navigation={navigation} testID='read-receipt-view-close' />;
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
|
|
|
@ -22,6 +22,8 @@ import { themes } from '../../constants/colors';
|
|||
import { withTheme } from '../../theme';
|
||||
import { getUserSelector } from '../../selectors/login';
|
||||
import Markdown from '../../containers/markdown';
|
||||
import { LISTENER } from '../../containers/Toast';
|
||||
import EventEmitter from '../../utils/events';
|
||||
|
||||
import Livechat from './Livechat';
|
||||
import Channel from './Channel';
|
||||
|
@ -59,7 +61,8 @@ class RoomInfoView extends React.Component {
|
|||
baseUrl: PropTypes.string,
|
||||
rooms: PropTypes.array,
|
||||
theme: PropTypes.string,
|
||||
isMasterDetail: PropTypes.bool
|
||||
isMasterDetail: PropTypes.bool,
|
||||
jitsiEnabled: PropTypes.bool
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
|
@ -167,11 +170,11 @@ class RoomInfoView extends React.Component {
|
|||
}
|
||||
|
||||
loadUser = async() => {
|
||||
const { room: roomState, roomUser } = this.state;
|
||||
const { room, roomUser } = this.state;
|
||||
|
||||
if (_.isEmpty(roomUser)) {
|
||||
try {
|
||||
const roomUserId = RocketChat.getUidDirectMessage(roomState);
|
||||
const roomUserId = RocketChat.getUidDirectMessage(room);
|
||||
const result = await RocketChat.getUserInfo(roomUserId);
|
||||
if (result.success) {
|
||||
const { user } = result;
|
||||
|
@ -183,9 +186,7 @@ class RoomInfoView extends React.Component {
|
|||
}));
|
||||
}
|
||||
|
||||
const room = await this.getDirect(user.username);
|
||||
|
||||
this.setState({ roomUser: user, room: { ...roomState, rid: room.rid } });
|
||||
this.setState({ roomUser: user });
|
||||
}
|
||||
} catch {
|
||||
// do nothing
|
||||
|
@ -220,16 +221,28 @@ class RoomInfoView extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
getDirect = async(username) => {
|
||||
createDirect = () => new Promise(async(resolve, reject) => {
|
||||
const { route } = this.props;
|
||||
|
||||
// We don't need to create a direct
|
||||
const member = route.params?.member;
|
||||
if (!_.isEmpty(member)) {
|
||||
return resolve();
|
||||
}
|
||||
|
||||
// TODO: Check if some direct with the user already exists on database
|
||||
try {
|
||||
const { roomUser: { username } } = this.state;
|
||||
const result = await RocketChat.createDirectMessage(username);
|
||||
if (result.success) {
|
||||
return result.room;
|
||||
const { room: { rid } } = result;
|
||||
return this.setState(({ room }) => ({ room: { ...room, rid } }), resolve);
|
||||
}
|
||||
} catch {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
reject();
|
||||
})
|
||||
|
||||
goRoom = () => {
|
||||
const { roomUser, room } = this.state;
|
||||
|
@ -287,9 +300,19 @@ class RoomInfoView extends React.Component {
|
|||
|
||||
renderButton = (onPress, iconName, text) => {
|
||||
const { theme } = this.props;
|
||||
|
||||
const onActionPress = async() => {
|
||||
try {
|
||||
await this.createDirect();
|
||||
onPress();
|
||||
} catch {
|
||||
EventEmitter.emit(LISTENER, { message: I18n.t('error-action-not-allowed', { action: I18n.t('Create_Direct_Messages') }) });
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<BorderlessButton
|
||||
onPress={onPress}
|
||||
onPress={onActionPress}
|
||||
style={styles.roomButton}
|
||||
>
|
||||
<CustomIcon
|
||||
|
@ -302,12 +325,15 @@ class RoomInfoView extends React.Component {
|
|||
);
|
||||
}
|
||||
|
||||
renderButtons = () => (
|
||||
renderButtons = () => {
|
||||
const { jitsiEnabled } = this.props;
|
||||
return (
|
||||
<View style={styles.roomButtonsContainer}>
|
||||
{this.renderButton(this.goRoom, 'message', I18n.t('Message'))}
|
||||
{this.renderButton(this.videoCall, 'video-1', I18n.t('Video_call'))}
|
||||
{jitsiEnabled ? this.renderButton(this.videoCall, 'video-1', I18n.t('Video_call')) : null}
|
||||
</View>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
renderContent = () => {
|
||||
const { room, roomUser } = this.state;
|
||||
|
@ -348,7 +374,8 @@ const mapStateToProps = state => ({
|
|||
baseUrl: state.server.server,
|
||||
user: getUserSelector(state),
|
||||
rooms: state.room.rooms,
|
||||
isMasterDetail: state.app.isMasterDetail
|
||||
isMasterDetail: state.app.isMasterDetail,
|
||||
jitsiEnabled: state.settings.Jitsi_Enabled || false
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(withTheme(RoomInfoView));
|
||||
|
|
|
@ -6,6 +6,7 @@ import PropTypes from 'prop-types';
|
|||
import { connect } from 'react-redux';
|
||||
import AsyncStorage from '@react-native-community/async-storage';
|
||||
import RNConfigReader from 'react-native-config-reader';
|
||||
import FastImage from '@rocket.chat/react-native-fast-image';
|
||||
|
||||
import { logout as logoutAction } from '../../actions/login';
|
||||
import { selectServerRequest as selectServerRequestAction } from '../../actions/server';
|
||||
|
@ -106,9 +107,11 @@ class SettingsView extends React.Component {
|
|||
const {
|
||||
server: { server }, appStart, selectServerRequest
|
||||
} = this.props;
|
||||
await appStart({ root: ROOT_LOADING, text: I18n.t('Clear_cache_loading') });
|
||||
appStart({ root: ROOT_LOADING, text: I18n.t('Clear_cache_loading') });
|
||||
await RocketChat.clearCache({ server });
|
||||
await selectServerRequest(server, null, true);
|
||||
await FastImage.clearMemoryCache();
|
||||
await FastImage.clearDiskCache();
|
||||
selectServerRequest(server, null, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import { StyleSheet, View, Text } from 'react-native';
|
|||
import PropTypes from 'prop-types';
|
||||
import { createImageProgress } from 'react-native-image-progress';
|
||||
import * as Progress from 'react-native-progress';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
import FastImage from '@rocket.chat/react-native-fast-image';
|
||||
|
||||
import sharedStyles from '../Styles';
|
||||
import { themes } from '../../constants/colors';
|
||||
|
|
|
@ -440,7 +440,7 @@ PODS:
|
|||
- React
|
||||
- rn-fetch-blob (0.12.0):
|
||||
- React-Core
|
||||
- RNBootSplash (2.2.4):
|
||||
- RNBootSplash (2.2.5):
|
||||
- React
|
||||
- RNCAsyncStorage (1.10.3):
|
||||
- React
|
||||
|
@ -486,9 +486,9 @@ PODS:
|
|||
- React
|
||||
- RNVectorIcons (6.6.0):
|
||||
- React
|
||||
- SDWebImage (5.7.4):
|
||||
- SDWebImage/Core (= 5.7.4)
|
||||
- SDWebImage/Core (5.7.4)
|
||||
- SDWebImage (5.8.0):
|
||||
- SDWebImage/Core (= 5.8.0)
|
||||
- SDWebImage/Core (5.8.0)
|
||||
- SDWebImageWebPCoder (0.4.1):
|
||||
- libwebp (~> 1.0)
|
||||
- SDWebImage/Core (~> 5.5)
|
||||
|
@ -595,7 +595,7 @@ DEPENDENCIES:
|
|||
- "RNCMaskedView (from `../node_modules/@react-native-community/masked-view`)"
|
||||
- "RNDateTimePicker (from `../node_modules/@react-native-community/datetimepicker`)"
|
||||
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
|
||||
- RNFastImage (from `../node_modules/react-native-fast-image`)
|
||||
- "RNFastImage (from `../node_modules/@rocket.chat/react-native-fast-image`)"
|
||||
- RNFirebase (from `../node_modules/react-native-firebase/ios`)
|
||||
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
|
||||
- RNImageCropPicker (from `../node_modules/react-native-image-crop-picker`)
|
||||
|
@ -771,7 +771,7 @@ EXTERNAL SOURCES:
|
|||
RNDeviceInfo:
|
||||
:path: "../node_modules/react-native-device-info"
|
||||
RNFastImage:
|
||||
:path: "../node_modules/react-native-fast-image"
|
||||
:path: "../node_modules/@rocket.chat/react-native-fast-image"
|
||||
RNFirebase:
|
||||
:path: "../node_modules/react-native-firebase/ios"
|
||||
RNGestureHandler:
|
||||
|
@ -904,7 +904,7 @@ SPEC CHECKSUMS:
|
|||
ReactNativeKeyboardTrackingView: 02137fac3b2ebd330d74fa54ead48b14750a2306
|
||||
rn-extensions-share: 8db79372089567cbc5aefe8444869bbc808578d3
|
||||
rn-fetch-blob: f065bb7ab7fb48dd002629f8bdcb0336602d3cba
|
||||
RNBootSplash: 7cb9b4fe7e94177edc0d11010f7631d79db2f5e9
|
||||
RNBootSplash: b3836aa90c5bec690c6cd3c9ab355fcf98d0fe1d
|
||||
RNCAsyncStorage: cd7234ff15c010723ed7c499ae4eedc605eac1fd
|
||||
RNCMaskedView: 5a8ec07677aa885546a0d98da336457e2bea557f
|
||||
RNDateTimePicker: 4bd49e09f91ca73d69119a9e1173b0d43b82f5e5
|
||||
|
@ -919,7 +919,7 @@ SPEC CHECKSUMS:
|
|||
RNScreens: cf198f915f8a2bf163de94ca9f5bfc8d326c3706
|
||||
RNUserDefaults: c421fd97ad06b35c16608c5d0fe675db353f632d
|
||||
RNVectorIcons: 0bb4def82230be1333ddaeee9fcba45f0b288ed4
|
||||
SDWebImage: 48b88379b798fd1e4298f95bb25d2cdabbf4deb3
|
||||
SDWebImage: 84000f962cbfa70c07f19d2234cbfcf5d779b5dc
|
||||
SDWebImageWebPCoder: 36f8f47bd9879a8aea6044765c1351120fd8e3a8
|
||||
TOCropViewController: e9da34f484aedd4e5d5a8ab230ba217cfe16c729
|
||||
UMAppLoader: ee77a072f9e15128f777ccd6d2d00f52ab4387e6
|
||||
|
|
|
@ -1 +1 @@
|
|||
../../../../../node_modules/react-native-fast-image/ios/FastImage/FFFastImageSource.h
|
||||
../../../../../node_modules/@rocket.chat/react-native-fast-image/ios/FastImage/FFFastImageSource.h
|
|
@ -1 +1 @@
|
|||
../../../../../node_modules/react-native-fast-image/ios/FastImage/FFFastImageView.h
|
||||
../../../../../node_modules/@rocket.chat/react-native-fast-image/ios/FastImage/FFFastImageView.h
|
|
@ -1 +1 @@
|
|||
../../../../../node_modules/react-native-fast-image/ios/FastImage/FFFastImageViewManager.h
|
||||
../../../../../node_modules/@rocket.chat/react-native-fast-image/ios/FastImage/FFFastImageViewManager.h
|
|
@ -1 +1 @@
|
|||
../../../../../node_modules/react-native-fast-image/ios/FastImage/RCTConvert+FFFastImage.h
|
||||
../../../../../node_modules/@rocket.chat/react-native-fast-image/ios/FastImage/RCTConvert+FFFastImage.h
|
|
@ -0,0 +1 @@
|
|||
../../../SDWebImage/SDWebImage/Private/SDWebImageTransitionInternal.h
|
|
@ -1 +1 @@
|
|||
../../../../../node_modules/react-native-fast-image/ios/FastImage/FFFastImageSource.h
|
||||
../../../../../node_modules/@rocket.chat/react-native-fast-image/ios/FastImage/FFFastImageSource.h
|
|
@ -1 +1 @@
|
|||
../../../../../node_modules/react-native-fast-image/ios/FastImage/FFFastImageView.h
|
||||
../../../../../node_modules/@rocket.chat/react-native-fast-image/ios/FastImage/FFFastImageView.h
|
|
@ -1 +1 @@
|
|||
../../../../../node_modules/react-native-fast-image/ios/FastImage/FFFastImageViewManager.h
|
||||
../../../../../node_modules/@rocket.chat/react-native-fast-image/ios/FastImage/FFFastImageViewManager.h
|
|
@ -1 +1 @@
|
|||
../../../../../node_modules/react-native-fast-image/ios/FastImage/RCTConvert+FFFastImage.h
|
||||
../../../../../node_modules/@rocket.chat/react-native-fast-image/ios/FastImage/RCTConvert+FFFastImage.h
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
]
|
||||
},
|
||||
"version": "2.2.4",
|
||||
"version": "2.2.5",
|
||||
"license": "MIT",
|
||||
"summary": "Display a bootsplash on your app starts. Hide it when you want.",
|
||||
"authors": "Mathieu Acthernoene <zoontek@gmail.com>",
|
||||
|
@ -17,7 +17,7 @@
|
|||
"requires_arc": true,
|
||||
"source": {
|
||||
"git": "https://github.com/zoontek/react-native-bootsplash.git",
|
||||
"tag": "2.2.4"
|
||||
"tag": "2.2.5"
|
||||
},
|
||||
"source_files": "ios/*.{h,m}"
|
||||
}
|
||||
|
|
|
@ -440,7 +440,7 @@ PODS:
|
|||
- React
|
||||
- rn-fetch-blob (0.12.0):
|
||||
- React-Core
|
||||
- RNBootSplash (2.2.4):
|
||||
- RNBootSplash (2.2.5):
|
||||
- React
|
||||
- RNCAsyncStorage (1.10.3):
|
||||
- React
|
||||
|
@ -486,9 +486,9 @@ PODS:
|
|||
- React
|
||||
- RNVectorIcons (6.6.0):
|
||||
- React
|
||||
- SDWebImage (5.7.4):
|
||||
- SDWebImage/Core (= 5.7.4)
|
||||
- SDWebImage/Core (5.7.4)
|
||||
- SDWebImage (5.8.0):
|
||||
- SDWebImage/Core (= 5.8.0)
|
||||
- SDWebImage/Core (5.8.0)
|
||||
- SDWebImageWebPCoder (0.4.1):
|
||||
- libwebp (~> 1.0)
|
||||
- SDWebImage/Core (~> 5.5)
|
||||
|
@ -595,7 +595,7 @@ DEPENDENCIES:
|
|||
- "RNCMaskedView (from `../node_modules/@react-native-community/masked-view`)"
|
||||
- "RNDateTimePicker (from `../node_modules/@react-native-community/datetimepicker`)"
|
||||
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
|
||||
- RNFastImage (from `../node_modules/react-native-fast-image`)
|
||||
- "RNFastImage (from `../node_modules/@rocket.chat/react-native-fast-image`)"
|
||||
- RNFirebase (from `../node_modules/react-native-firebase/ios`)
|
||||
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
|
||||
- RNImageCropPicker (from `../node_modules/react-native-image-crop-picker`)
|
||||
|
@ -771,7 +771,7 @@ EXTERNAL SOURCES:
|
|||
RNDeviceInfo:
|
||||
:path: "../node_modules/react-native-device-info"
|
||||
RNFastImage:
|
||||
:path: "../node_modules/react-native-fast-image"
|
||||
:path: "../node_modules/@rocket.chat/react-native-fast-image"
|
||||
RNFirebase:
|
||||
:path: "../node_modules/react-native-firebase/ios"
|
||||
RNGestureHandler:
|
||||
|
@ -904,7 +904,7 @@ SPEC CHECKSUMS:
|
|||
ReactNativeKeyboardTrackingView: 02137fac3b2ebd330d74fa54ead48b14750a2306
|
||||
rn-extensions-share: 8db79372089567cbc5aefe8444869bbc808578d3
|
||||
rn-fetch-blob: f065bb7ab7fb48dd002629f8bdcb0336602d3cba
|
||||
RNBootSplash: 7cb9b4fe7e94177edc0d11010f7631d79db2f5e9
|
||||
RNBootSplash: b3836aa90c5bec690c6cd3c9ab355fcf98d0fe1d
|
||||
RNCAsyncStorage: cd7234ff15c010723ed7c499ae4eedc605eac1fd
|
||||
RNCMaskedView: 5a8ec07677aa885546a0d98da336457e2bea557f
|
||||
RNDateTimePicker: 4bd49e09f91ca73d69119a9e1173b0d43b82f5e5
|
||||
|
@ -919,7 +919,7 @@ SPEC CHECKSUMS:
|
|||
RNScreens: cf198f915f8a2bf163de94ca9f5bfc8d326c3706
|
||||
RNUserDefaults: c421fd97ad06b35c16608c5d0fe675db353f632d
|
||||
RNVectorIcons: 0bb4def82230be1333ddaeee9fcba45f0b288ed4
|
||||
SDWebImage: 48b88379b798fd1e4298f95bb25d2cdabbf4deb3
|
||||
SDWebImage: 84000f962cbfa70c07f19d2234cbfcf5d779b5dc
|
||||
SDWebImageWebPCoder: 36f8f47bd9879a8aea6044765c1351120fd8e3a8
|
||||
TOCropViewController: e9da34f484aedd4e5d5a8ab230ba217cfe16c729
|
||||
UMAppLoader: ee77a072f9e15128f777ccd6d2d00f52ab4387e6
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -133,6 +133,7 @@ You can use those directly, or create similar components of your own, by using t
|
|||
|
||||
- If you **want to contribute**, read the [Contributing Guide](https://github.com/SDWebImage/SDWebImage/blob/master/.github/CONTRIBUTING.md)
|
||||
- For **development contribution guide**, read the [How-To-Contribute](https://github.com/SDWebImage/SDWebImage/wiki/How-to-Contribute)
|
||||
- For **understanding code architecture**, read the [Code Architecture Analysis](https://github.com/SDWebImage/SDWebImage/wiki/5.6-Code-Architecture-Analysis)
|
||||
|
||||
## How To Use
|
||||
|
||||
|
@ -283,6 +284,12 @@ In the source files where you need to use the library, import the umbrella heade
|
|||
#import <SDWebImage/SDWebImage.h>
|
||||
```
|
||||
|
||||
It's also recommend to use the module import syntax, available for CocoaPods(enable `modular_headers`)/Carthage/SwiftPM.
|
||||
|
||||
```objecitivec
|
||||
@import SDWebImage;
|
||||
```
|
||||
|
||||
### Build Project
|
||||
|
||||
At this point your workspace should build without error. If you are having problem, post to the Issue and the
|
||||
|
@ -310,6 +317,8 @@ All source code is licensed under the [MIT License](https://github.com/SDWebImag
|
|||
|
||||
## Architecture
|
||||
|
||||
To learn about SDWebImage's architecture design for contribution, read [The Core of SDWebImage v5.6 Architecture](https://github.com/SDWebImage/SDWebImage/wiki/5.6-Code-Architecture-Analysis). Thanks @looseyi for the post and translation.
|
||||
|
||||
#### High Level Diagram
|
||||
<p align="center" >
|
||||
<img src="https://raw.githubusercontent.com/SDWebImage/SDWebImage/master/Docs/Diagrams/SDWebImageHighLevelDiagram.jpeg" title="SDWebImage high level diagram">
|
||||
|
|
|
@ -81,6 +81,13 @@
|
|||
*/
|
||||
@property (nonatomic, assign) BOOL resetFrameIndexWhenStopped;
|
||||
|
||||
/**
|
||||
If the image has more than one frame, set this value to `YES` will automatically
|
||||
play/stop the animation when the view become visible/invisible.
|
||||
Default is YES.
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL autoPlayAnimatedImage;
|
||||
|
||||
/**
|
||||
You can specify a runloop mode to let it rendering.
|
||||
Default is NSRunLoopCommonModes on multi-core device, NSDefaultRunLoopMode on single-core device
|
||||
|
|
|
@ -93,6 +93,7 @@
|
|||
{
|
||||
// Pay attention that UIKit's `initWithImage:` will trigger a `setImage:` during initialization before this `commonInit`.
|
||||
// So the properties which rely on this order, should using lazy-evaluation or do extra check in `setImage:`.
|
||||
self.autoPlayAnimatedImage = YES;
|
||||
self.shouldCustomLoopCount = NO;
|
||||
self.shouldIncrementalLoad = YES;
|
||||
self.playbackRate = 1.0;
|
||||
|
@ -183,8 +184,8 @@
|
|||
// Ensure disabled highlighting; it's not supported (see `-setHighlighted:`).
|
||||
super.highlighted = NO;
|
||||
|
||||
// Start animating
|
||||
[self startAnimating];
|
||||
[self stopAnimating];
|
||||
[self checkPlay];
|
||||
|
||||
[self.imageViewLayer setNeedsDisplay];
|
||||
}
|
||||
|
@ -258,12 +259,7 @@
|
|||
[super didMoveToSuperview];
|
||||
#endif
|
||||
|
||||
[self updateShouldAnimate];
|
||||
if (self.shouldAnimate) {
|
||||
[self startAnimating];
|
||||
} else {
|
||||
[self stopAnimating];
|
||||
}
|
||||
[self checkPlay];
|
||||
}
|
||||
|
||||
#if SD_MAC
|
||||
|
@ -278,12 +274,7 @@
|
|||
[super didMoveToWindow];
|
||||
#endif
|
||||
|
||||
[self updateShouldAnimate];
|
||||
if (self.shouldAnimate) {
|
||||
[self startAnimating];
|
||||
} else {
|
||||
[self stopAnimating];
|
||||
}
|
||||
[self checkPlay];
|
||||
}
|
||||
|
||||
#if SD_MAC
|
||||
|
@ -298,24 +289,14 @@
|
|||
[super setAlpha:alpha];
|
||||
#endif
|
||||
|
||||
[self updateShouldAnimate];
|
||||
if (self.shouldAnimate) {
|
||||
[self startAnimating];
|
||||
} else {
|
||||
[self stopAnimating];
|
||||
}
|
||||
[self checkPlay];
|
||||
}
|
||||
|
||||
- (void)setHidden:(BOOL)hidden
|
||||
{
|
||||
[super setHidden:hidden];
|
||||
|
||||
[self updateShouldAnimate];
|
||||
if (self.shouldAnimate) {
|
||||
[self startAnimating];
|
||||
} else {
|
||||
[self stopAnimating];
|
||||
}
|
||||
[self checkPlay];
|
||||
}
|
||||
|
||||
#pragma mark - UIImageView Method Overrides
|
||||
|
@ -344,6 +325,8 @@
|
|||
} else {
|
||||
#if SD_UIKIT
|
||||
[super startAnimating];
|
||||
#else
|
||||
[super setAnimates:YES];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -362,6 +345,8 @@
|
|||
} else {
|
||||
#if SD_UIKIT
|
||||
[super stopAnimating];
|
||||
#else
|
||||
[super setAnimates:NO];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -378,9 +363,17 @@
|
|||
#endif
|
||||
|
||||
#if SD_MAC
|
||||
- (BOOL)animates
|
||||
{
|
||||
if (self.player) {
|
||||
return self.player.isPlaying;
|
||||
} else {
|
||||
return [super animates];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setAnimates:(BOOL)animates
|
||||
{
|
||||
[super setAnimates:animates];
|
||||
if (animates) {
|
||||
[self startAnimating];
|
||||
} else {
|
||||
|
@ -403,6 +396,19 @@
|
|||
#pragma mark - Private Methods
|
||||
#pragma mark Animation
|
||||
|
||||
/// Check if it should be played
|
||||
- (void)checkPlay
|
||||
{
|
||||
if (self.autoPlayAnimatedImage) {
|
||||
[self updateShouldAnimate];
|
||||
if (self.shouldAnimate) {
|
||||
[self startAnimating];
|
||||
} else {
|
||||
[self stopAnimating];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Don't repeatedly check our window & superview in `-displayDidRefresh:` for performance reasons.
|
||||
// Just update our cached value whenever the animated image or visibility (window, superview, hidden, alpha) is changed.
|
||||
- (void)updateShouldAnimate
|
||||
|
|
|
@ -79,6 +79,14 @@ FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeMaxPixelSi
|
|||
*/
|
||||
FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeMaxFileSize;
|
||||
|
||||
/**
|
||||
A Boolean value indicating the encoding format should contains a thumbnail image into the output data. Only some of image format (like JPEG/HEIF/AVIF) support this behavior. The embed thumbnail will be used during next time thumbnail decoding (provided `.thumbnailPixelSize`), which is faster than full image thumbnail decoding. (NSNumber)
|
||||
Defaults to NO, which does not embed any thumbnail.
|
||||
@note The thumbnail image's pixel size is not defined, the encoder can choose the proper pixel size which is suitable for encoding quality.
|
||||
@note works for `SDImageCoder`
|
||||
*/
|
||||
FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderEncodeEmbedThumbnail;
|
||||
|
||||
/**
|
||||
A SDWebImageContext object which hold the original context options from top-level API. (SDWebImageContext)
|
||||
This option is ignored for all built-in coders and take no effect.
|
||||
|
|
|
@ -18,5 +18,6 @@ SDImageCoderOption const SDImageCoderEncodeCompressionQuality = @"encodeCompress
|
|||
SDImageCoderOption const SDImageCoderEncodeBackgroundColor = @"encodeBackgroundColor";
|
||||
SDImageCoderOption const SDImageCoderEncodeMaxPixelSize = @"encodeMaxPixelSize";
|
||||
SDImageCoderOption const SDImageCoderEncodeMaxFileSize = @"encodeMaxFileSize";
|
||||
SDImageCoderOption const SDImageCoderEncodeEmbedThumbnail = @"encodeEmbedThumbnail";
|
||||
|
||||
SDImageCoderOption const SDImageCoderWebImageContext = @"webImageContext";
|
||||
|
|
|
@ -476,6 +476,7 @@ static NSString * kSDCGImageDestinationRequestedFileSize = @"kCGImageDestination
|
|||
} else {
|
||||
finalPixelSize = maxPixelSize.height;
|
||||
}
|
||||
properties[(__bridge NSString *)kCGImageDestinationImageMaxPixelSize] = @(finalPixelSize);
|
||||
}
|
||||
NSUInteger maxFileSize = [options[SDImageCoderEncodeMaxFileSize] unsignedIntegerValue];
|
||||
if (maxFileSize > 0) {
|
||||
|
@ -483,31 +484,31 @@ static NSString * kSDCGImageDestinationRequestedFileSize = @"kCGImageDestination
|
|||
// Remove the quality if we have file size limit
|
||||
properties[(__bridge NSString *)kCGImageDestinationLossyCompressionQuality] = nil;
|
||||
}
|
||||
BOOL embedThumbnail = NO;
|
||||
if (options[SDImageCoderEncodeEmbedThumbnail]) {
|
||||
embedThumbnail = [options[SDImageCoderEncodeEmbedThumbnail] boolValue];
|
||||
}
|
||||
properties[(__bridge NSString *)kCGImageDestinationEmbedThumbnail] = @(embedThumbnail);
|
||||
|
||||
BOOL encodeFirstFrame = [options[SDImageCoderEncodeFirstFrameOnly] boolValue];
|
||||
if (encodeFirstFrame || frames.count == 0) {
|
||||
// for static single images
|
||||
if (finalPixelSize > 0) {
|
||||
properties[(__bridge NSString *)kCGImageDestinationImageMaxPixelSize] = @(finalPixelSize);
|
||||
}
|
||||
CGImageDestinationAddImage(imageDestination, imageRef, (__bridge CFDictionaryRef)properties);
|
||||
} else {
|
||||
// for animated images
|
||||
NSUInteger loopCount = image.sd_imageLoopCount;
|
||||
NSDictionary *containerProperties = @{self.class.loopCountProperty : @(loopCount)};
|
||||
properties[self.class.dictionaryProperty] = containerProperties;
|
||||
CGImageDestinationSetProperties(imageDestination, (__bridge CFDictionaryRef)properties);
|
||||
NSDictionary *containerProperties = @{
|
||||
self.class.dictionaryProperty: @{self.class.loopCountProperty : @(loopCount)}
|
||||
};
|
||||
// container level properties (applies for `CGImageDestinationSetProperties`, not individual frames)
|
||||
CGImageDestinationSetProperties(imageDestination, (__bridge CFDictionaryRef)containerProperties);
|
||||
|
||||
for (size_t i = 0; i < frames.count; i++) {
|
||||
SDImageFrame *frame = frames[i];
|
||||
NSTimeInterval frameDuration = frame.duration;
|
||||
CGImageRef frameImageRef = frame.image.CGImage;
|
||||
NSMutableDictionary *frameProperties = [NSMutableDictionary dictionary];
|
||||
frameProperties[self.class.dictionaryProperty] = @{self.class.delayTimeProperty : @(frameDuration)};
|
||||
if (finalPixelSize > 0) {
|
||||
frameProperties[(__bridge NSString *)kCGImageDestinationImageMaxPixelSize] = @(finalPixelSize);
|
||||
}
|
||||
CGImageDestinationAddImage(imageDestination, frameImageRef, (__bridge CFDictionaryRef)frameProperties);
|
||||
properties[self.class.dictionaryProperty] = @{self.class.delayTimeProperty : @(frameDuration)};
|
||||
CGImageDestinationAddImage(imageDestination, frameImageRef, (__bridge CFDictionaryRef)properties);
|
||||
}
|
||||
}
|
||||
// Finalize the destination.
|
||||
|
|
|
@ -294,6 +294,11 @@ static NSString * kSDCGImageDestinationRequestedFileSize = @"kCGImageDestination
|
|||
// Remove the quality if we have file size limit
|
||||
properties[(__bridge NSString *)kCGImageDestinationLossyCompressionQuality] = nil;
|
||||
}
|
||||
BOOL embedThumbnail = NO;
|
||||
if (options[SDImageCoderEncodeEmbedThumbnail]) {
|
||||
embedThumbnail = [options[SDImageCoderEncodeEmbedThumbnail] boolValue];
|
||||
}
|
||||
properties[(__bridge NSString *)kCGImageDestinationEmbedThumbnail] = @(embedThumbnail);
|
||||
|
||||
// Add your image to the destination.
|
||||
CGImageDestinationAddImage(imageDestination, imageRef, (__bridge CFDictionaryRef)properties);
|
||||
|
|
|
@ -272,9 +272,17 @@ FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextQueryC
|
|||
*/
|
||||
FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextStoreCacheType;
|
||||
|
||||
/**
|
||||
The same behavior like `SDWebImageContextQueryCacheType`, but control the query cache type for the original image when you use image transformer feature. This allows the detail control of cache query for these two images. For example, if you want to query the transformed image from both memory/disk cache, query the original image from disk cache only, use `[.queryCacheType : .all, .originalQueryCacheType : .disk]`
|
||||
If not provide or the value is invalid, we will use `SDImageCacheTypeNone`, which does not query the original image from cache. (NSNumber)
|
||||
@note Which means, if you set this value to not be `.none`, we will query the original image from cache, then do transform with transformer, instead of actual downloading, which can save bandwidth usage.
|
||||
*/
|
||||
FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextOriginalQueryCacheType;
|
||||
|
||||
/**
|
||||
The same behavior like `SDWebImageContextStoreCacheType`, but control the store cache type for the original image when you use image transformer feature. This allows the detail control of cache storage for these two images. For example, if you want to store the transformed image into both memory/disk cache, store the original image into disk cache only, use `[.storeCacheType : .all, .originalStoreCacheType : .disk]`
|
||||
If not provide or the value is invalid, we will use `SDImageCacheTypeNone`, which does not store the original image into cache. (NSNumber)
|
||||
@note This only store the original image, if you want to use the original image without downloading in next query, specify `SDWebImageContextOriginalQueryCacheType` as well.
|
||||
*/
|
||||
FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextOriginalStoreCacheType;
|
||||
|
||||
|
|
|
@ -129,6 +129,7 @@ SDWebImageContextOption const SDWebImageContextImagePreserveAspectRatio = @"imag
|
|||
SDWebImageContextOption const SDWebImageContextImageThumbnailPixelSize = @"imageThumbnailPixelSize";
|
||||
SDWebImageContextOption const SDWebImageContextQueryCacheType = @"queryCacheType";
|
||||
SDWebImageContextOption const SDWebImageContextStoreCacheType = @"storeCacheType";
|
||||
SDWebImageContextOption const SDWebImageContextOriginalQueryCacheType = @"originalQueryCacheType";
|
||||
SDWebImageContextOption const SDWebImageContextOriginalStoreCacheType = @"originalStoreCacheType";
|
||||
SDWebImageContextOption const SDWebImageContextAnimatedImageClass = @"animatedImageClass";
|
||||
SDWebImageContextOption const SDWebImageContextDownloadRequestModifier = @"downloadRequestModifier";
|
||||
|
|
|
@ -30,7 +30,12 @@ A downloader response modifier class with block.
|
|||
*/
|
||||
@interface SDWebImageDownloaderDecryptor : NSObject <SDWebImageDownloaderDecryptor>
|
||||
|
||||
/// Create the data decryptor with block
|
||||
/// @param block A block to control decrypt logic
|
||||
- (nonnull instancetype)initWithBlock:(nonnull SDWebImageDownloaderDecryptorBlock)block;
|
||||
|
||||
/// Create the data decryptor with block
|
||||
/// @param block A block to control decrypt logic
|
||||
+ (nonnull instancetype)decryptorWithBlock:(nonnull SDWebImageDownloaderDecryptorBlock)block;
|
||||
|
||||
@end
|
||||
|
|
|
@ -474,7 +474,8 @@ didReceiveResponse:(NSURLResponse *)response
|
|||
UIImage *image = SDImageLoaderDecodeImageData(imageData, self.request.URL, [[self class] imageOptionsFromDownloaderOptions:self.options], self.context);
|
||||
CGSize imageSize = image.size;
|
||||
if (imageSize.width == 0 || imageSize.height == 0) {
|
||||
[self callCompletionBlocksWithError:[NSError errorWithDomain:SDWebImageErrorDomain code:SDWebImageErrorBadImageData userInfo:@{NSLocalizedDescriptionKey : @"Downloaded image has 0 pixels"}]];
|
||||
NSString *description = image == nil ? @"Downloaded image decode failed" : @"Downloaded image has 0 pixels";
|
||||
[self callCompletionBlocksWithError:[NSError errorWithDomain:SDWebImageErrorDomain code:SDWebImageErrorBadImageData userInfo:@{NSLocalizedDescriptionKey : description}]];
|
||||
} else {
|
||||
[self callCompletionBlocksWithImage:image imageData:imageData error:nil finished:YES];
|
||||
}
|
||||
|
|
|
@ -29,7 +29,41 @@ typedef NSURLRequest * _Nullable (^SDWebImageDownloaderRequestModifierBlock)(NSU
|
|||
*/
|
||||
@interface SDWebImageDownloaderRequestModifier : NSObject <SDWebImageDownloaderRequestModifier>
|
||||
|
||||
/// Create the request modifier with block
|
||||
/// @param block A block to control modifier logic
|
||||
- (nonnull instancetype)initWithBlock:(nonnull SDWebImageDownloaderRequestModifierBlock)block;
|
||||
|
||||
/// Create the request modifier with block
|
||||
/// @param block A block to control modifier logic
|
||||
+ (nonnull instancetype)requestModifierWithBlock:(nonnull SDWebImageDownloaderRequestModifierBlock)block;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
A convenient request modifier to provide the HTTP request including HTTP Method, Headers and Body.
|
||||
*/
|
||||
@interface SDWebImageDownloaderRequestModifier (Conveniences)
|
||||
|
||||
/// Create the request modifier with HTTP Method.
|
||||
/// @param method HTTP Method, nil means to GET.
|
||||
/// @note This is for convenience, if you need code to control the logic, use block API instead.
|
||||
- (nonnull instancetype)initWithMethod:(nullable NSString *)method;
|
||||
|
||||
/// Create the request modifier with HTTP Headers.
|
||||
/// @param headers HTTP Headers. Case insensitive according to HTTP/1.1(HTTP/2) standard. The headers will overide the same fileds from original request.
|
||||
/// @note This is for convenience, if you need code to control the logic, use block API instead.
|
||||
- (nonnull instancetype)initWithHeaders:(nullable NSDictionary<NSString *, NSString *> *)headers;
|
||||
|
||||
/// Create the request modifier with HTTP Body.
|
||||
/// @param body HTTP Body.
|
||||
/// @note This is for convenience, if you need code to control the logic, use block API instead.
|
||||
- (nonnull instancetype)initWithBody:(nullable NSData *)body;
|
||||
|
||||
/// Create the request modifier with HTTP Method, Headers and Body.
|
||||
/// @param method HTTP Method, nil means to GET.
|
||||
/// @param headers HTTP Headers. Case insensitive according to HTTP/1.1(HTTP/2) standard. The headers will overide the same fileds from original request.
|
||||
/// @param body HTTP Body.
|
||||
/// @note This is for convenience, if you need code to control the logic, use block API instead.
|
||||
- (nonnull instancetype)initWithMethod:(nullable NSString *)method headers:(nullable NSDictionary<NSString *, NSString *> *)headers body:(nullable NSData *)body;
|
||||
|
||||
@end
|
||||
|
|
|
@ -37,3 +37,35 @@
|
|||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation SDWebImageDownloaderRequestModifier (Conveniences)
|
||||
|
||||
- (instancetype)initWithMethod:(NSString *)method {
|
||||
return [self initWithMethod:method headers:nil body:nil];
|
||||
}
|
||||
|
||||
- (instancetype)initWithHeaders:(NSDictionary<NSString *,NSString *> *)headers {
|
||||
return [self initWithMethod:nil headers:headers body:nil];
|
||||
}
|
||||
|
||||
- (instancetype)initWithBody:(NSData *)body {
|
||||
return [self initWithMethod:nil headers:nil body:body];
|
||||
}
|
||||
|
||||
- (instancetype)initWithMethod:(NSString *)method headers:(NSDictionary<NSString *,NSString *> *)headers body:(NSData *)body {
|
||||
method = [method copy];
|
||||
headers = [headers copy];
|
||||
body = [body copy];
|
||||
return [self initWithBlock:^NSURLRequest * _Nullable(NSURLRequest * _Nonnull request) {
|
||||
NSMutableURLRequest *mutableRequest = [request mutableCopy];
|
||||
mutableRequest.HTTPMethod = method;
|
||||
mutableRequest.HTTPBody = body;
|
||||
for (NSString *header in headers) {
|
||||
NSString *value = headers[header];
|
||||
[mutableRequest setValue:value forHTTPHeaderField:header];
|
||||
}
|
||||
return [mutableRequest copy];
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -29,7 +29,41 @@ typedef NSURLResponse * _Nullable (^SDWebImageDownloaderResponseModifierBlock)(N
|
|||
*/
|
||||
@interface SDWebImageDownloaderResponseModifier : NSObject <SDWebImageDownloaderResponseModifier>
|
||||
|
||||
/// Create the response modifier with block
|
||||
/// @param block A block to control modifier logic
|
||||
- (nonnull instancetype)initWithBlock:(nonnull SDWebImageDownloaderResponseModifierBlock)block;
|
||||
|
||||
/// Create the response modifier with block
|
||||
/// @param block A block to control modifier logic
|
||||
+ (nonnull instancetype)responseModifierWithBlock:(nonnull SDWebImageDownloaderResponseModifierBlock)block;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
A convenient response modifier to provide the HTTP response including HTTP Status Code, Version and Headers.
|
||||
*/
|
||||
@interface SDWebImageDownloaderResponseModifier (Conveniences)
|
||||
|
||||
/// Create the response modifier with HTTP Status code.
|
||||
/// @param statusCode HTTP Status Code.
|
||||
/// @note This is for convenience, if you need code to control the logic, use block API instead.
|
||||
- (nonnull instancetype)initWithStatusCode:(NSInteger)statusCode;
|
||||
|
||||
/// Create the response modifier with HTTP Version. Status code defaults to 200.
|
||||
/// @param version HTTP Version, nil means "HTTP/1.1".
|
||||
/// @note This is for convenience, if you need code to control the logic, use block API instead.
|
||||
- (nonnull instancetype)initWithVersion:(nullable NSString *)version;
|
||||
|
||||
/// Create the response modifier with HTTP Headers. Status code defaults to 200.
|
||||
/// @param headers HTTP Headers. Case insensitive according to HTTP/1.1(HTTP/2) standard. The headers will overide the same fileds from original response.
|
||||
/// @note This is for convenience, if you need code to control the logic, use block API instead.
|
||||
- (nonnull instancetype)initWithHeaders:(nullable NSDictionary<NSString *, NSString *> *)headers;
|
||||
|
||||
/// Create the response modifier with HTTP Status Code, Version and Headers.
|
||||
/// @param statusCode HTTP Status Code.
|
||||
/// @param version HTTP Version, nil means "HTTP/1.1".
|
||||
/// @param headers HTTP Headers. Case insensitive according to HTTP/1.1(HTTP/2) standard. The headers will overide the same fileds from original response.
|
||||
/// @note This is for convenience, if you need code to control the logic, use block API instead.
|
||||
- (nonnull instancetype)initWithStatusCode:(NSInteger)statusCode version:(nullable NSString *)version headers:(nullable NSDictionary<NSString *, NSString *> *)headers;
|
||||
|
||||
@end
|
||||
|
|
|
@ -38,3 +38,36 @@
|
|||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation SDWebImageDownloaderResponseModifier (Conveniences)
|
||||
|
||||
- (instancetype)initWithStatusCode:(NSInteger)statusCode {
|
||||
return [self initWithStatusCode:statusCode version:nil headers:nil];
|
||||
}
|
||||
|
||||
- (instancetype)initWithVersion:(NSString *)version {
|
||||
return [self initWithStatusCode:200 version:version headers:nil];
|
||||
}
|
||||
|
||||
- (instancetype)initWithHeaders:(NSDictionary<NSString *,NSString *> *)headers {
|
||||
return [self initWithStatusCode:200 version:nil headers:headers];
|
||||
}
|
||||
|
||||
- (instancetype)initWithStatusCode:(NSInteger)statusCode version:(NSString *)version headers:(NSDictionary<NSString *,NSString *> *)headers {
|
||||
version = version ? [version copy] : @"HTTP/1.1";
|
||||
headers = [headers copy];
|
||||
return [self initWithBlock:^NSURLResponse * _Nullable(NSURLResponse * _Nonnull response) {
|
||||
if (![response isKindOfClass:NSHTTPURLResponse.class]) {
|
||||
return response;
|
||||
}
|
||||
NSMutableDictionary *mutableHeaders = [((NSHTTPURLResponse *)response).allHeaderFields mutableCopy];
|
||||
for (NSString *header in headers) {
|
||||
NSString *value = headers[header];
|
||||
mutableHeaders[header] = value;
|
||||
}
|
||||
NSHTTPURLResponse *httpResponse = [[NSHTTPURLResponse alloc] initWithURL:response.URL statusCode:statusCode HTTPVersion:version headerFields:[mutableHeaders copy]];
|
||||
return httpResponse;
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -19,6 +19,7 @@ typedef NS_ERROR_ENUM(SDWebImageErrorDomain, SDWebImageError) {
|
|||
SDWebImageErrorInvalidURL = 1000, // The URL is invalid, such as nil URL or corrupted URL
|
||||
SDWebImageErrorBadImageData = 1001, // The image data can not be decoded to image, or the image data is empty
|
||||
SDWebImageErrorCacheNotModified = 1002, // The remote location specify that the cached image is not modified, such as the HTTP response 304 code. It's useful for `SDWebImageRefreshCached`
|
||||
SDWebImageErrorBlackListed = 1003, // The URL is blacklisted because of unrecoverable failsure marked by downloader (such as 404), you can use `.retryFailed` option to avoid this
|
||||
SDWebImageErrorInvalidDownloadOperation = 2000, // The image download operation is invalid, such as nil operation or unexpected error occur when operation initialized
|
||||
SDWebImageErrorInvalidDownloadStatusCode = 2001, // The image download response a invalid status code. You can check the status code in error's userInfo under `SDWebImageErrorDownloadStatusCodeKey`
|
||||
SDWebImageErrorCancelled = 2002, // The image loading operation is cancelled before finished, during either async disk cache query, or waiting before actual network request. For actual network request error, check `NSURLErrorDomain` error domain and code.
|
||||
|
|
|
@ -261,6 +261,17 @@ SDWebImageManager *manager = [SDWebImageManager sharedManager];
|
|||
*/
|
||||
- (void)cancelAll;
|
||||
|
||||
/**
|
||||
* Remove the specify URL from failed black list.
|
||||
* @param url The failed URL.
|
||||
*/
|
||||
- (void)removeFailedURL:(nonnull NSURL *)url;
|
||||
|
||||
/**
|
||||
* Remove all the URL from failed black list.
|
||||
*/
|
||||
- (void)removeAllFailedURLs;
|
||||
|
||||
/**
|
||||
* Return the cache key for a given URL, does not considerate transformer or thumbnail.
|
||||
* @note This method does not have context option, only use the url and manager level cacheKeyFilter to generate the cache key.
|
||||
|
|
|
@ -194,7 +194,9 @@ static id<SDImageLoader> _defaultImageLoader;
|
|||
}
|
||||
|
||||
if (url.absoluteString.length == 0 || (!(options & SDWebImageRetryFailed) && isFailedUrl)) {
|
||||
[self callCompletionBlockForOperation:operation completion:completedBlock error:[NSError errorWithDomain:SDWebImageErrorDomain code:SDWebImageErrorInvalidURL userInfo:@{NSLocalizedDescriptionKey : @"Image url is nil"}] url:url];
|
||||
NSString *description = isFailedUrl ? @"Image url is blacklisted" : @"Image url is nil";
|
||||
NSInteger code = isFailedUrl ? SDWebImageErrorBlackListed : SDWebImageErrorInvalidURL;
|
||||
[self callCompletionBlockForOperation:operation completion:completedBlock error:[NSError errorWithDomain:SDWebImageErrorDomain code:code userInfo:@{NSLocalizedDescriptionKey : description}] url:url];
|
||||
return operation;
|
||||
}
|
||||
|
||||
|
@ -226,9 +228,24 @@ static id<SDImageLoader> _defaultImageLoader;
|
|||
return isRunning;
|
||||
}
|
||||
|
||||
- (void)removeFailedURL:(NSURL *)url {
|
||||
if (!url) {
|
||||
return;
|
||||
}
|
||||
SD_LOCK(self.failedURLsLock);
|
||||
[self.failedURLs removeObject:url];
|
||||
SD_UNLOCK(self.failedURLsLock);
|
||||
}
|
||||
|
||||
- (void)removeAllFailedURLs {
|
||||
SD_LOCK(self.failedURLsLock);
|
||||
[self.failedURLs removeAllObjects];
|
||||
SD_UNLOCK(self.failedURLsLock);
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
// Query cache process
|
||||
// Query normal cache process
|
||||
- (void)callCacheProcessForOperation:(nonnull SDWebImageCombinedOperation *)operation
|
||||
url:(nonnull NSURL *)url
|
||||
options:(SDWebImageOptions)options
|
||||
|
@ -242,13 +259,15 @@ static id<SDImageLoader> _defaultImageLoader;
|
|||
} else {
|
||||
imageCache = self.imageCache;
|
||||
}
|
||||
// Check whether we should query cache
|
||||
BOOL shouldQueryCache = !SD_OPTIONS_CONTAINS(options, SDWebImageFromLoaderOnly);
|
||||
|
||||
// Get the query cache type
|
||||
SDImageCacheType queryCacheType = SDImageCacheTypeAll;
|
||||
if (context[SDWebImageContextQueryCacheType]) {
|
||||
queryCacheType = [context[SDWebImageContextQueryCacheType] integerValue];
|
||||
}
|
||||
|
||||
// Check whether we should query cache
|
||||
BOOL shouldQueryCache = !SD_OPTIONS_CONTAINS(options, SDWebImageFromLoaderOnly);
|
||||
if (shouldQueryCache) {
|
||||
NSString *key = [self cacheKeyForURL:url context:context];
|
||||
@weakify(operation);
|
||||
|
@ -259,7 +278,12 @@ static id<SDImageLoader> _defaultImageLoader;
|
|||
[self callCompletionBlockForOperation:operation completion:completedBlock error:[NSError errorWithDomain:SDWebImageErrorDomain code:SDWebImageErrorCancelled userInfo:@{NSLocalizedDescriptionKey : @"Operation cancelled by user during querying the cache"}] url:url];
|
||||
[self safelyRemoveOperationFromRunning:operation];
|
||||
return;
|
||||
} else if (context[SDWebImageContextImageTransformer] && !cachedImage) {
|
||||
// Have a chance to quary original cache instead of downloading
|
||||
[self callOriginalCacheProcessForOperation:operation url:url options:options context:context progress:progressBlock completed:completedBlock];
|
||||
return;
|
||||
}
|
||||
|
||||
// Continue download process
|
||||
[self callDownloadProcessForOperation:operation url:url options:options context:context cachedImage:cachedImage cachedData:cachedData cacheType:cacheType progress:progressBlock completed:completedBlock];
|
||||
}];
|
||||
|
@ -269,6 +293,69 @@ static id<SDImageLoader> _defaultImageLoader;
|
|||
}
|
||||
}
|
||||
|
||||
// Query original cache process
|
||||
- (void)callOriginalCacheProcessForOperation:(nonnull SDWebImageCombinedOperation *)operation
|
||||
url:(nonnull NSURL *)url
|
||||
options:(SDWebImageOptions)options
|
||||
context:(nullable SDWebImageContext *)context
|
||||
progress:(nullable SDImageLoaderProgressBlock)progressBlock
|
||||
completed:(nullable SDInternalCompletionBlock)completedBlock {
|
||||
// Grab the image cache to use
|
||||
id<SDImageCache> imageCache;
|
||||
if ([context[SDWebImageContextImageCache] conformsToProtocol:@protocol(SDImageCache)]) {
|
||||
imageCache = context[SDWebImageContextImageCache];
|
||||
} else {
|
||||
imageCache = self.imageCache;
|
||||
}
|
||||
|
||||
// Get the original query cache type
|
||||
SDImageCacheType originalQueryCacheType = SDImageCacheTypeNone;
|
||||
if (context[SDWebImageContextOriginalQueryCacheType]) {
|
||||
originalQueryCacheType = [context[SDWebImageContextOriginalQueryCacheType] integerValue];
|
||||
}
|
||||
|
||||
// Check whether we should query original cache
|
||||
BOOL shouldQueryOriginalCache = (originalQueryCacheType != SDImageCacheTypeNone);
|
||||
if (shouldQueryOriginalCache) {
|
||||
// Change originContext to mutable
|
||||
SDWebImageMutableContext * __block originContext;
|
||||
if (context) {
|
||||
originContext = [context mutableCopy];
|
||||
} else {
|
||||
originContext = [NSMutableDictionary dictionary];
|
||||
}
|
||||
|
||||
// Disable transformer for cache key generation
|
||||
id<SDImageTransformer> transformer = originContext[SDWebImageContextImageTransformer];
|
||||
originContext[SDWebImageContextImageTransformer] = [NSNull null];
|
||||
|
||||
NSString *key = [self cacheKeyForURL:url context:originContext];
|
||||
@weakify(operation);
|
||||
operation.cacheOperation = [imageCache queryImageForKey:key options:options context:context cacheType:originalQueryCacheType completion:^(UIImage * _Nullable cachedImage, NSData * _Nullable cachedData, SDImageCacheType cacheType) {
|
||||
@strongify(operation);
|
||||
if (!operation || operation.isCancelled) {
|
||||
// Image combined operation cancelled by user
|
||||
[self callCompletionBlockForOperation:operation completion:completedBlock error:[NSError errorWithDomain:SDWebImageErrorDomain code:SDWebImageErrorCancelled userInfo:@{NSLocalizedDescriptionKey : @"Operation cancelled by user during querying the cache"}] url:url];
|
||||
[self safelyRemoveOperationFromRunning:operation];
|
||||
return;
|
||||
}
|
||||
|
||||
// Add original transformer
|
||||
if (transformer) {
|
||||
originContext[SDWebImageContextImageTransformer] = transformer;
|
||||
}
|
||||
|
||||
// Use the store cache process instead of downloading, and ignore .refreshCached option for now
|
||||
[self callStoreCacheProcessForOperation:operation url:url options:options context:context downloadedImage:cachedImage downloadedData:cachedData finished:YES progress:progressBlock completed:completedBlock];
|
||||
|
||||
[self safelyRemoveOperationFromRunning:operation];
|
||||
}];
|
||||
} else {
|
||||
// Continue download process
|
||||
[self callDownloadProcessForOperation:operation url:url options:options context:context cachedImage:nil cachedData:nil cacheType:originalQueryCacheType progress:progressBlock completed:completedBlock];
|
||||
}
|
||||
}
|
||||
|
||||
// Download process
|
||||
- (void)callDownloadProcessForOperation:(nonnull SDWebImageCombinedOperation *)operation
|
||||
url:(nonnull NSURL *)url
|
||||
|
@ -286,6 +373,7 @@ static id<SDImageLoader> _defaultImageLoader;
|
|||
} else {
|
||||
imageLoader = self.imageLoader;
|
||||
}
|
||||
|
||||
// Check whether we should download image from network
|
||||
BOOL shouldDownload = !SD_OPTIONS_CONTAINS(options, SDWebImageFromCacheOnly);
|
||||
shouldDownload &= (!cachedImage || options & SDWebImageRefreshCached);
|
||||
|
|
|
@ -16,6 +16,20 @@ typedef UIViewAnimationOptions SDWebImageAnimationOptions;
|
|||
#else
|
||||
typedef NS_OPTIONS(NSUInteger, SDWebImageAnimationOptions) {
|
||||
SDWebImageAnimationOptionAllowsImplicitAnimation = 1 << 0, // specify `allowsImplicitAnimation` for the `NSAnimationContext`
|
||||
|
||||
SDWebImageAnimationOptionCurveEaseInOut = 0 << 16, // default
|
||||
SDWebImageAnimationOptionCurveEaseIn = 1 << 16,
|
||||
SDWebImageAnimationOptionCurveEaseOut = 2 << 16,
|
||||
SDWebImageAnimationOptionCurveLinear = 3 << 16,
|
||||
|
||||
SDWebImageAnimationOptionTransitionNone = 0 << 20, // default
|
||||
SDWebImageAnimationOptionTransitionFlipFromLeft = 1 << 20,
|
||||
SDWebImageAnimationOptionTransitionFlipFromRight = 2 << 20,
|
||||
SDWebImageAnimationOptionTransitionCurlUp = 3 << 20,
|
||||
SDWebImageAnimationOptionTransitionCurlDown = 4 << 20,
|
||||
SDWebImageAnimationOptionTransitionCrossDissolve = 5 << 20,
|
||||
SDWebImageAnimationOptionTransitionFlipFromTop = 6 << 20,
|
||||
SDWebImageAnimationOptionTransitionFlipFromBottom = 7 << 20,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -42,7 +56,7 @@ typedef void (^SDWebImageTransitionCompletionBlock)(BOOL finished);
|
|||
/**
|
||||
The timing function used for all animations within this transition animation (macOS).
|
||||
*/
|
||||
@property (nonatomic, strong, nullable) CAMediaTimingFunction *timingFunction API_UNAVAILABLE(ios, tvos, watchos);
|
||||
@property (nonatomic, strong, nullable) CAMediaTimingFunction *timingFunction API_UNAVAILABLE(ios, tvos, watchos) API_DEPRECATED("Use SDWebImageAnimationOptions instead, or grab NSAnimationContext.currentContext and modify the timingFunction", macos(10.10, 10.10));
|
||||
/**
|
||||
A mask of options indicating how you want to perform the animations.
|
||||
*/
|
||||
|
|
|
@ -11,7 +11,62 @@
|
|||
#if SD_UIKIT || SD_MAC
|
||||
|
||||
#if SD_MAC
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
#import "SDWebImageTransitionInternal.h"
|
||||
#import "SDInternalMacros.h"
|
||||
|
||||
CAMediaTimingFunction * SDTimingFunctionFromAnimationOptions(SDWebImageAnimationOptions options) {
|
||||
if (SD_OPTIONS_CONTAINS(SDWebImageAnimationOptionCurveLinear, options)) {
|
||||
return [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
|
||||
} else if (SD_OPTIONS_CONTAINS(SDWebImageAnimationOptionCurveEaseIn, options)) {
|
||||
return [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
|
||||
} else if (SD_OPTIONS_CONTAINS(SDWebImageAnimationOptionCurveEaseOut, options)) {
|
||||
return [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
|
||||
} else if (SD_OPTIONS_CONTAINS(SDWebImageAnimationOptionCurveEaseInOut, options)) {
|
||||
return [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
|
||||
} else {
|
||||
return [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault];
|
||||
}
|
||||
}
|
||||
|
||||
CATransition * SDTransitionFromAnimationOptions(SDWebImageAnimationOptions options) {
|
||||
if (SD_OPTIONS_CONTAINS(options, SDWebImageAnimationOptionTransitionCrossDissolve)) {
|
||||
CATransition *trans = [CATransition animation];
|
||||
trans.type = kCATransitionFade;
|
||||
return trans;
|
||||
} else if (SD_OPTIONS_CONTAINS(options, SDWebImageAnimationOptionTransitionFlipFromLeft)) {
|
||||
CATransition *trans = [CATransition animation];
|
||||
trans.type = kCATransitionPush;
|
||||
trans.subtype = kCATransitionFromLeft;
|
||||
return trans;
|
||||
} else if (SD_OPTIONS_CONTAINS(options, SDWebImageAnimationOptionTransitionFlipFromRight)) {
|
||||
CATransition *trans = [CATransition animation];
|
||||
trans.type = kCATransitionPush;
|
||||
trans.subtype = kCATransitionFromRight;
|
||||
return trans;
|
||||
} else if (SD_OPTIONS_CONTAINS(options, SDWebImageAnimationOptionTransitionFlipFromTop)) {
|
||||
CATransition *trans = [CATransition animation];
|
||||
trans.type = kCATransitionPush;
|
||||
trans.subtype = kCATransitionFromTop;
|
||||
return trans;
|
||||
} else if (SD_OPTIONS_CONTAINS(options, SDWebImageAnimationOptionTransitionFlipFromBottom)) {
|
||||
CATransition *trans = [CATransition animation];
|
||||
trans.type = kCATransitionPush;
|
||||
trans.subtype = kCATransitionFromBottom;
|
||||
return trans;
|
||||
} else if (SD_OPTIONS_CONTAINS(options, SDWebImageAnimationOptionTransitionCurlUp)) {
|
||||
CATransition *trans = [CATransition animation];
|
||||
trans.type = kCATransitionReveal;
|
||||
trans.subtype = kCATransitionFromTop;
|
||||
return trans;
|
||||
} else if (SD_OPTIONS_CONTAINS(options, SDWebImageAnimationOptionTransitionCurlDown)) {
|
||||
CATransition *trans = [CATransition animation];
|
||||
trans.type = kCATransitionReveal;
|
||||
trans.subtype = kCATransitionFromBottom;
|
||||
return trans;
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@implementation SDWebImageTransition
|
||||
|
@ -33,11 +88,7 @@
|
|||
#if SD_UIKIT
|
||||
transition.animationOptions = UIViewAnimationOptionTransitionCrossDissolve | UIViewAnimationOptionAllowUserInteraction;
|
||||
#else
|
||||
transition.animations = ^(__kindof NSView * _Nonnull view, NSImage * _Nullable image) {
|
||||
CATransition *trans = [CATransition animation];
|
||||
trans.type = kCATransitionFade;
|
||||
[view.layer addAnimation:trans forKey:kCATransition];
|
||||
};
|
||||
transition.animationOptions = SDWebImageAnimationOptionTransitionCrossDissolve;
|
||||
#endif
|
||||
return transition;
|
||||
}
|
||||
|
@ -47,12 +98,7 @@
|
|||
#if SD_UIKIT
|
||||
transition.animationOptions = UIViewAnimationOptionTransitionFlipFromLeft | UIViewAnimationOptionAllowUserInteraction;
|
||||
#else
|
||||
transition.animations = ^(__kindof NSView * _Nonnull view, NSImage * _Nullable image) {
|
||||
CATransition *trans = [CATransition animation];
|
||||
trans.type = kCATransitionPush;
|
||||
trans.subtype = kCATransitionFromLeft;
|
||||
[view.layer addAnimation:trans forKey:kCATransition];
|
||||
};
|
||||
transition.animationOptions = SDWebImageAnimationOptionTransitionFlipFromLeft;
|
||||
#endif
|
||||
return transition;
|
||||
}
|
||||
|
@ -62,12 +108,7 @@
|
|||
#if SD_UIKIT
|
||||
transition.animationOptions = UIViewAnimationOptionTransitionFlipFromRight | UIViewAnimationOptionAllowUserInteraction;
|
||||
#else
|
||||
transition.animations = ^(__kindof NSView * _Nonnull view, NSImage * _Nullable image) {
|
||||
CATransition *trans = [CATransition animation];
|
||||
trans.type = kCATransitionPush;
|
||||
trans.subtype = kCATransitionFromRight;
|
||||
[view.layer addAnimation:trans forKey:kCATransition];
|
||||
};
|
||||
transition.animationOptions = SDWebImageAnimationOptionTransitionFlipFromRight;
|
||||
#endif
|
||||
return transition;
|
||||
}
|
||||
|
@ -77,12 +118,7 @@
|
|||
#if SD_UIKIT
|
||||
transition.animationOptions = UIViewAnimationOptionTransitionFlipFromTop | UIViewAnimationOptionAllowUserInteraction;
|
||||
#else
|
||||
transition.animations = ^(__kindof NSView * _Nonnull view, NSImage * _Nullable image) {
|
||||
CATransition *trans = [CATransition animation];
|
||||
trans.type = kCATransitionPush;
|
||||
trans.subtype = kCATransitionFromTop;
|
||||
[view.layer addAnimation:trans forKey:kCATransition];
|
||||
};
|
||||
transition.animationOptions = SDWebImageAnimationOptionTransitionFlipFromTop;
|
||||
#endif
|
||||
return transition;
|
||||
}
|
||||
|
@ -92,12 +128,7 @@
|
|||
#if SD_UIKIT
|
||||
transition.animationOptions = UIViewAnimationOptionTransitionFlipFromBottom | UIViewAnimationOptionAllowUserInteraction;
|
||||
#else
|
||||
transition.animations = ^(__kindof NSView * _Nonnull view, NSImage * _Nullable image) {
|
||||
CATransition *trans = [CATransition animation];
|
||||
trans.type = kCATransitionPush;
|
||||
trans.subtype = kCATransitionFromBottom;
|
||||
[view.layer addAnimation:trans forKey:kCATransition];
|
||||
};
|
||||
transition.animationOptions = SDWebImageAnimationOptionTransitionFlipFromBottom;
|
||||
#endif
|
||||
return transition;
|
||||
}
|
||||
|
@ -107,12 +138,7 @@
|
|||
#if SD_UIKIT
|
||||
transition.animationOptions = UIViewAnimationOptionTransitionCurlUp | UIViewAnimationOptionAllowUserInteraction;
|
||||
#else
|
||||
transition.animations = ^(__kindof NSView * _Nonnull view, NSImage * _Nullable image) {
|
||||
CATransition *trans = [CATransition animation];
|
||||
trans.type = kCATransitionReveal;
|
||||
trans.subtype = kCATransitionFromTop;
|
||||
[view.layer addAnimation:trans forKey:kCATransition];
|
||||
};
|
||||
transition.animationOptions = SDWebImageAnimationOptionTransitionCurlUp;
|
||||
#endif
|
||||
return transition;
|
||||
}
|
||||
|
@ -122,12 +148,7 @@
|
|||
#if SD_UIKIT
|
||||
transition.animationOptions = UIViewAnimationOptionTransitionCurlDown | UIViewAnimationOptionAllowUserInteraction;
|
||||
#else
|
||||
transition.animations = ^(__kindof NSView * _Nonnull view, NSImage * _Nullable image) {
|
||||
CATransition *trans = [CATransition animation];
|
||||
trans.type = kCATransitionReveal;
|
||||
trans.subtype = kCATransitionFromBottom;
|
||||
[view.layer addAnimation:trans forKey:kCATransition];
|
||||
};
|
||||
transition.animationOptions = SDWebImageAnimationOptionTransitionCurlDown;
|
||||
#endif
|
||||
return transition;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#import "UIView+WebCacheOperation.h"
|
||||
#import "SDWebImageError.h"
|
||||
#import "SDInternalMacros.h"
|
||||
#import "SDWebImageTransitionInternal.h"
|
||||
|
||||
const int64_t SDWebImageProgressUnitCountUnknown = 1LL;
|
||||
|
||||
|
@ -52,10 +53,19 @@ const int64_t SDWebImageProgressUnitCountUnknown = 1LL;
|
|||
setImageBlock:(nullable SDSetImageBlock)setImageBlock
|
||||
progress:(nullable SDImageLoaderProgressBlock)progressBlock
|
||||
completed:(nullable SDInternalCompletionBlock)completedBlock {
|
||||
context = [context copy]; // copy to avoid mutable object
|
||||
if (context) {
|
||||
// copy to avoid mutable object
|
||||
context = [context copy];
|
||||
} else {
|
||||
context = [NSDictionary dictionary];
|
||||
}
|
||||
NSString *validOperationKey = context[SDWebImageContextSetImageOperationKey];
|
||||
if (!validOperationKey) {
|
||||
// pass through the operation key to downstream, which can used for tracing operation or image view class
|
||||
validOperationKey = NSStringFromClass([self class]);
|
||||
SDWebImageMutableContext *mutableContext = [context mutableCopy];
|
||||
mutableContext[SDWebImageContextSetImageOperationKey] = validOperationKey;
|
||||
context = [mutableContext copy];
|
||||
}
|
||||
self.sd_latestOperationKey = validOperationKey;
|
||||
[self sd_cancelImageLoadOperationWithKey:validOperationKey];
|
||||
|
@ -83,6 +93,11 @@ const int64_t SDWebImageProgressUnitCountUnknown = 1LL;
|
|||
SDWebImageManager *manager = context[SDWebImageContextCustomManager];
|
||||
if (!manager) {
|
||||
manager = [SDWebImageManager sharedManager];
|
||||
} else {
|
||||
// remove this manager to avoid retain cycle (manger -> loader -> operation -> context -> manager)
|
||||
SDWebImageMutableContext *mutableContext = [context mutableCopy];
|
||||
mutableContext[SDWebImageContextCustomManager] = nil;
|
||||
context = [mutableContext copy];
|
||||
}
|
||||
|
||||
SDImageLoaderProgressBlock combinedProgressBlock = ^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {
|
||||
|
@ -260,11 +275,22 @@ const int64_t SDWebImageProgressUnitCountUnknown = 1LL;
|
|||
} completionHandler:^{
|
||||
[NSAnimationContext runAnimationGroup:^(NSAnimationContext * _Nonnull context) {
|
||||
context.duration = transition.duration;
|
||||
context.timingFunction = transition.timingFunction;
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
CAMediaTimingFunction *timingFunction = transition.timingFunction;
|
||||
#pragma clang diagnostic pop
|
||||
if (!timingFunction) {
|
||||
timingFunction = SDTimingFunctionFromAnimationOptions(transition.animationOptions);
|
||||
}
|
||||
context.timingFunction = timingFunction;
|
||||
context.allowsImplicitAnimation = SD_OPTIONS_CONTAINS(transition.animationOptions, SDWebImageAnimationOptionAllowsImplicitAnimation);
|
||||
if (finalSetImageBlock && !transition.avoidAutoSetImage) {
|
||||
finalSetImageBlock(image, imageData, cacheType, imageURL);
|
||||
}
|
||||
CATransition *trans = SDTransitionFromAnimationOptions(transition.animationOptions);
|
||||
if (trans) {
|
||||
[view.layer addAnimation:trans forKey:kCATransition];
|
||||
}
|
||||
if (transition.animations) {
|
||||
transition.animations(view, image);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* This file is part of the SDWebImage package.
|
||||
* (c) Olivier Poitrey <rs@dailymotion.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
#import "SDWebImageCompat.h"
|
||||
|
||||
#if SD_MAC
|
||||
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
|
||||
/// Helper method for Core Animation transition
|
||||
FOUNDATION_EXPORT CAMediaTimingFunction * _Nullable SDTimingFunctionFromAnimationOptions(SDWebImageAnimationOptions options);
|
||||
FOUNDATION_EXPORT CATransition * _Nullable SDTransitionFromAnimationOptions(SDWebImageAnimationOptions options);
|
||||
|
||||
#endif
|
|
@ -15,7 +15,7 @@ FOUNDATION_EXPORT double SDWebImageVersionNumber;
|
|||
//! Project version string for SDWebImage.
|
||||
FOUNDATION_EXPORT const unsigned char SDWebImageVersionString[];
|
||||
|
||||
// In this header, you should import all the public headers of your framework using statements like #import <WebImage/PublicHeader.h>
|
||||
// In this header, you should import all the public headers of your framework using statements like #import <SDWebImage/PublicHeader.h>
|
||||
|
||||
#import <SDWebImage/SDWebImageManager.h>
|
||||
#import <SDWebImage/SDWebImageCacheKeyFilter.h>
|
||||
|
|
|
@ -6,7 +6,7 @@ OTHER_CFLAGS = $(inherited) -fmodule-map-file="${PODS_ROOT}/Headers/Public/yoga/
|
|||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_ROOT = ${SRCROOT}
|
||||
PODS_TARGET_SRCROOT = ${PODS_ROOT}/../../node_modules/react-native-fast-image
|
||||
PODS_TARGET_SRCROOT = ${PODS_ROOT}/../../node_modules/@rocket.chat/react-native-fast-image
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
|
||||
SKIP_INSTALL = YES
|
||||
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
|
||||
|
|
|
@ -841,7 +841,7 @@
|
|||
"$(inherited)",
|
||||
"$(SRCROOT)/../node_modules/rn-extensions-share/ios/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-firebase/ios/RNFirebase/**",
|
||||
$PODS_CONFIGURATION_BUILD_DIR/Firebase,
|
||||
"$PODS_CONFIGURATION_BUILD_DIR/Firebase",
|
||||
);
|
||||
INFOPLIST_FILE = ShareRocketChatRN/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
|
@ -907,7 +907,7 @@
|
|||
"$(inherited)",
|
||||
"$(SRCROOT)/../node_modules/rn-extensions-share/ios/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-firebase/ios/RNFirebase/**",
|
||||
$PODS_CONFIGURATION_BUILD_DIR/Firebase,
|
||||
"$PODS_CONFIGURATION_BUILD_DIR/Firebase",
|
||||
);
|
||||
INFOPLIST_FILE = ShareRocketChatRN/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
"@react-navigation/drawer": "5.8.1",
|
||||
"@react-navigation/native": "5.5.0",
|
||||
"@react-navigation/stack": "^5.3.9",
|
||||
"@rocket.chat/react-native-fast-image": "^8.1.5",
|
||||
"@rocket.chat/sdk": "djorkaeffalexandre/Rocket.Chat.js.SDK#test.fix-ddp",
|
||||
"@rocket.chat/ui-kit": "0.8.0",
|
||||
"base-64": "0.1.0",
|
||||
|
@ -57,7 +58,7 @@
|
|||
"i18n-js": "3.5.1",
|
||||
"js-base64": "2.5.2",
|
||||
"js-sha256": "^0.9.0",
|
||||
"lodash": "4.17.16",
|
||||
"lodash": "4.17.19",
|
||||
"moment": "2.25.3",
|
||||
"pretty-bytes": "^5.3.0",
|
||||
"prop-types": "15.7.2",
|
||||
|
@ -73,7 +74,6 @@
|
|||
"react-native-document-picker": "3.3.3",
|
||||
"react-native-easy-grid": "^0.2.2",
|
||||
"react-native-easy-toast": "^1.2.0",
|
||||
"react-native-fast-image": "8.1.5",
|
||||
"react-native-firebase": "5.6.0",
|
||||
"react-native-gesture-handler": "^1.6.1",
|
||||
"react-native-image-crop-picker": "RocketChat/react-native-image-crop-picker",
|
||||
|
|
53
yarn.lock
53
yarn.lock
|
@ -1825,6 +1825,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@redux-saga/types/-/types-1.1.0.tgz#0e81ce56b4883b4b2a3001ebe1ab298b84237204"
|
||||
integrity sha512-afmTuJrylUU/0OtqzaRkbyYFFNgCF73Bvel/sw90pvGrWIZ+vyoIJqA6eMSoA6+nb443kTmulmBtC9NerXboNg==
|
||||
|
||||
"@rocket.chat/react-native-fast-image@^8.1.5":
|
||||
version "8.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@rocket.chat/react-native-fast-image/-/react-native-fast-image-8.1.5.tgz#325d80ebb351fb024436093b3e2add280696aba3"
|
||||
integrity sha512-ZjSt7NXiCkJ9KQr4b/b+mYgiwDAIGHfHdChgEU020C9sBbhSk6VxslqnfdZoAjxRW7doWMbhWkoYMjx2TnsGRw==
|
||||
|
||||
"@rocket.chat/sdk@djorkaeffalexandre/Rocket.Chat.js.SDK#test.fix-ddp":
|
||||
version "1.0.0-dj.15"
|
||||
resolved "https://codeload.github.com/djorkaeffalexandre/Rocket.Chat.js.SDK/tar.gz/216de62f7e52dd4a9f73d7989d6943ced550a92a"
|
||||
|
@ -4668,8 +4673,8 @@ commondir@^1.0.1:
|
|||
integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=
|
||||
|
||||
"commonmark-react-renderer@git+https://github.com/RocketChat/commonmark-react-renderer.git":
|
||||
version "4.3.4"
|
||||
resolved "git+https://github.com/RocketChat/commonmark-react-renderer.git#1264ac7b1c13d9be3e2f67eec6702a3132f4fac2"
|
||||
version "4.3.5"
|
||||
resolved "git+https://github.com/RocketChat/commonmark-react-renderer.git#996553c27ab6457775ba1f4b6a5a6a20ce7ddfbc"
|
||||
dependencies:
|
||||
lodash.assign "^4.2.0"
|
||||
lodash.isplainobject "^4.0.6"
|
||||
|
@ -4677,14 +4682,14 @@ commondir@^1.0.1:
|
|||
xss-filters "^1.2.6"
|
||||
|
||||
"commonmark@git+https://github.com/RocketChat/commonmark.js.git":
|
||||
version "0.29.0"
|
||||
resolved "git+https://github.com/RocketChat/commonmark.js.git#5d293fe9ba83a3e6f842d5d3f41a9b57c35bea1f"
|
||||
version "0.29.2"
|
||||
resolved "git+https://github.com/RocketChat/commonmark.js.git#020b5af060459ac2010e382e9ae431d48ed39777"
|
||||
dependencies:
|
||||
entities "~ 1.1.1"
|
||||
entities "~2.0"
|
||||
mdurl "~1.0.1"
|
||||
minimist "~ 1.2.0"
|
||||
minimist ">=1.2.2"
|
||||
string.prototype.repeat "^0.2.0"
|
||||
xregexp "4.1.1"
|
||||
xregexp "^4.3.0"
|
||||
|
||||
compare-urls@^2.0.0:
|
||||
version "2.0.0"
|
||||
|
@ -5631,7 +5636,7 @@ enhanced-resolve@^4.1.0:
|
|||
memory-fs "^0.5.0"
|
||||
tapable "^1.0.0"
|
||||
|
||||
entities@^1.1.1, entities@^1.1.2, "entities@~ 1.1.1":
|
||||
entities@^1.1.1, entities@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
|
||||
integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==
|
||||
|
@ -5641,6 +5646,11 @@ entities@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.2.tgz#ac74db0bba8d33808bbf36809c3a5c3683531436"
|
||||
integrity sha512-dmD3AvJQBUjKpcNkoqr+x+IF0SdRtPz9Vk0uTy4yWqga9ibB6s4v++QFWNohjiUGoMlF552ZvNyXDxz5iW0qmw==
|
||||
|
||||
entities@~2.0:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.3.tgz#5c487e5742ab93c15abb5da22759b8590ec03b7f"
|
||||
integrity sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==
|
||||
|
||||
envinfo@^7.1.0:
|
||||
version "7.5.1"
|
||||
resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.5.1.tgz#93c26897225a00457c75e734d354ea9106a72236"
|
||||
|
@ -9436,15 +9446,10 @@ lodash.throttle@^4.1.1:
|
|||
resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
|
||||
integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=
|
||||
|
||||
lodash@4.17.16:
|
||||
version "4.17.16"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.16.tgz#34fa1571037ea4b35b2726932961eafedad3058e"
|
||||
integrity sha512-mzxOTaU4AsJhnIujhngm+OnA6JX4fTI8D5H26wwGd+BJ57bW70oyRwTqo6EFJm1jTZ7hCo7yVzH1vB8TMFd2ww==
|
||||
|
||||
lodash@4.x.x, lodash@^4.0.0, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0, lodash@^4.5.0:
|
||||
version "4.17.15"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
|
||||
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
|
||||
lodash@4.17.19, lodash@4.x.x, lodash@^4.0.0, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0, lodash@^4.5.0:
|
||||
version "4.17.19"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b"
|
||||
integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==
|
||||
|
||||
log-symbols@3.0.0:
|
||||
version "3.0.0"
|
||||
|
@ -9598,7 +9603,7 @@ md5.js@^1.3.4:
|
|||
inherits "^2.0.1"
|
||||
safe-buffer "^5.1.2"
|
||||
|
||||
"mdurl@~ 1.0.1":
|
||||
mdurl@~1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
|
||||
integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=
|
||||
|
@ -10041,7 +10046,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
|
|||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5, "minimist@~ 1.2.0":
|
||||
minimist@>=1.2.2, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5:
|
||||
version "1.2.5"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
|
||||
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
|
||||
|
@ -11813,11 +11818,6 @@ react-native-easy-toast@^1.2.0:
|
|||
dependencies:
|
||||
prop-types "^15.5.10"
|
||||
|
||||
react-native-fast-image@8.1.5:
|
||||
version "8.1.5"
|
||||
resolved "https://registry.yarnpkg.com/react-native-fast-image/-/react-native-fast-image-8.1.5.tgz#0a6404c988dad68c98d26f91155d0a5293ba2ea5"
|
||||
integrity sha512-DoAWGLeQ2hbllummrpXH9B38OgM0TFmNYCF34F90/hdHZirqUtYHzF4QDdb/NV7ebSijHmM3mpkzct8PXtcYyg==
|
||||
|
||||
react-native-firebase@5.6.0:
|
||||
version "5.6.0"
|
||||
resolved "https://registry.yarnpkg.com/react-native-firebase/-/react-native-firebase-5.6.0.tgz#6f6123f53cb73477915dd55c55f3e1de91db38d2"
|
||||
|
@ -14893,11 +14893,6 @@ xpipe@^1.0.5:
|
|||
resolved "https://registry.yarnpkg.com/xpipe/-/xpipe-1.0.5.tgz#8dd8bf45fc3f7f55f0e054b878f43a62614dafdf"
|
||||
integrity sha1-jdi/Rfw/f1Xw4FS4ePQ6YmFNr98=
|
||||
|
||||
xregexp@4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.1.1.tgz#eb8a032aa028d403f7b1b22c47a5f16c24b21d8d"
|
||||
integrity sha512-QJ1gfSUV7kEOLfpKFCjBJRnfPErUzkNKFMso4kDSmGpp3x6ZgkyKf74inxI7PnnQCFYq5TqYJCd7DrgDN8Q05A==
|
||||
|
||||
xregexp@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.3.0.tgz#7e92e73d9174a99a59743f67a4ce879a04b5ae50"
|
||||
|
|
Loading…
Reference in New Issue