This commit is contained in:
Djorkaeff Alexandre 2020-07-18 14:27:46 -03:00
commit a4055dab93
59 changed files with 7645 additions and 7227 deletions

View File

@ -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';

View File

@ -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 }) => (

View File

@ -90,6 +90,8 @@ const NotifierComponent = React.memo(({
if (isMasterDetail) {
Navigation.navigate('DrawerNavigator');
} else {
Navigation.navigate('RoomsListView');
}
goRoom({ item, isMasterDetail });
hideNotification();

View File

@ -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 {

View File

@ -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';

View File

@ -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';

View File

@ -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';

View File

@ -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';

View File

@ -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}

View File

@ -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';

View File

@ -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';

View File

@ -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;

View File

@ -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';

View File

@ -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'

View File

@ -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(
this.rid,
this.t,
{ 'mentions._id': { $in: [user.id] } },
messages.length
),
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(
this.rid,
this.t,
{ 'starred._id': { $in: [user.id] } },
messages.length
),
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 => (

View File

@ -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 = {
title: I18n.t('Read_Receipt')
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 = {

View File

@ -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 = () => (
<View style={styles.roomButtonsContainer}>
{this.renderButton(this.goRoom, 'message', I18n.t('Message'))}
{this.renderButton(this.videoCall, 'video-1', I18n.t('Video_call'))}
</View>
)
renderButtons = () => {
const { jitsiEnabled } = this.props;
return (
<View style={styles.roomButtonsContainer}>
{this.renderButton(this.goRoom, 'message', I18n.t('Message'))}
{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));

View File

@ -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);
}
});
}

View File

@ -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';

View File

@ -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

View File

@ -1 +1 @@
../../../../../node_modules/react-native-fast-image/ios/FastImage/FFFastImageSource.h
../../../../../node_modules/@rocket.chat/react-native-fast-image/ios/FastImage/FFFastImageSource.h

View File

@ -1 +1 @@
../../../../../node_modules/react-native-fast-image/ios/FastImage/FFFastImageView.h
../../../../../node_modules/@rocket.chat/react-native-fast-image/ios/FastImage/FFFastImageView.h

View File

@ -1 +1 @@
../../../../../node_modules/react-native-fast-image/ios/FastImage/FFFastImageViewManager.h
../../../../../node_modules/@rocket.chat/react-native-fast-image/ios/FastImage/FFFastImageViewManager.h

View File

@ -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

View File

@ -0,0 +1 @@
../../../SDWebImage/SDWebImage/Private/SDWebImageTransitionInternal.h

View File

@ -1 +1 @@
../../../../../node_modules/react-native-fast-image/ios/FastImage/FFFastImageSource.h
../../../../../node_modules/@rocket.chat/react-native-fast-image/ios/FastImage/FFFastImageSource.h

View File

@ -1 +1 @@
../../../../../node_modules/react-native-fast-image/ios/FastImage/FFFastImageView.h
../../../../../node_modules/@rocket.chat/react-native-fast-image/ios/FastImage/FFFastImageView.h

View File

@ -1 +1 @@
../../../../../node_modules/react-native-fast-image/ios/FastImage/FFFastImageViewManager.h
../../../../../node_modules/@rocket.chat/react-native-fast-image/ios/FastImage/FFFastImageViewManager.h

View File

@ -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

View File

@ -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}"
}

16
ios/Pods/Manifest.lock generated
View File

@ -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

View File

@ -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">

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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";

View File

@ -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.

View File

@ -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);

View File

@ -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;

View File

@ -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";

View File

@ -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

View File

@ -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];
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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);

View File

@ -15,7 +15,21 @@
typedef UIViewAnimationOptions SDWebImageAnimationOptions;
#else
typedef NS_OPTIONS(NSUInteger, SDWebImageAnimationOptions) {
SDWebImageAnimationOptionAllowsImplicitAnimation = 1 << 0, // specify `allowsImplicitAnimation` for the `NSAnimationContext`
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.
*/

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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

View File

@ -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>

View File

@ -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

View File

@ -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;

View File

@ -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",

View File

@ -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"
mdurl "~ 1.0.1"
minimist "~ 1.2.0"
entities "~2.0"
mdurl "~1.0.1"
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"