Several fixes for 1.2.1 (#448)
* Fix user.roles * Better onLongPress handle on messages * Indicator position * Fix role undefined in system messages * Add baseUrl in case of file attachments * Join room fixed * RoomView params * Broadcast fixes * Add server layout changes * Use native images * Subscribe to not joined channels * Fix alerts without i18n * Tests updated
|
@ -0,0 +1,3 @@
|
|||
export const RectButton = () => 'View';
|
||||
export const State = () => 'View';
|
||||
export const LongPressGestureHandler = () => 'View';
|
|
@ -184,6 +184,8 @@ repositories {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(':react-native-device-info')
|
||||
implementation project(':react-native-gesture-handler')
|
||||
implementation project(':react-native-image-crop-picker')
|
||||
implementation project(':react-native-i18n')
|
||||
implementation project(':react-native-fabric')
|
||||
|
|
|
@ -25,6 +25,8 @@ import com.wix.reactnativenotifications.core.AppLifecycleFacade;
|
|||
import com.wix.reactnativenotifications.core.JsIOHelper;
|
||||
import com.wix.reactnativenotifications.core.notification.INotificationsApplication;
|
||||
import com.wix.reactnativenotifications.core.notification.IPushNotification;
|
||||
import com.swmansion.gesturehandler.react.RNGestureHandlerPackage;
|
||||
import com.learnium.RNDeviceInfo.RNDeviceInfo;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
@ -57,6 +59,8 @@ public class MainApplication extends NavigationApplication implements INotificat
|
|||
public List<ReactPackage> createAdditionalReactPackages() {
|
||||
return Arrays.<ReactPackage>asList(
|
||||
new MainReactPackage(),
|
||||
new RNDeviceInfo(),
|
||||
new RNGestureHandlerPackage(),
|
||||
new PickerPackage(),
|
||||
new SvgPackage(),
|
||||
new VectorIconsPackage(),
|
||||
|
|
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 78 KiB |
After Width: | Height: | Size: 299 B |
After Width: | Height: | Size: 979 B |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
After Width: | Height: | Size: 214 B |
After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 111 KiB |
After Width: | Height: | Size: 333 B |
After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 73 KiB |
After Width: | Height: | Size: 177 KiB |
After Width: | Height: | Size: 487 B |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
After Width: | Height: | Size: 102 KiB |
After Width: | Height: | Size: 246 KiB |
After Width: | Height: | Size: 635 B |
|
@ -1,4 +1,8 @@
|
|||
rootProject.name = 'RocketChatRN'
|
||||
include ':react-native-device-info'
|
||||
project(':react-native-device-info').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-device-info/android')
|
||||
include ':react-native-gesture-handler'
|
||||
project(':react-native-gesture-handler').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-gesture-handler/android')
|
||||
include ':@remobile/react-native-toast'
|
||||
project(':@remobile/react-native-toast').projectDir = new File(rootProject.projectDir, '../node_modules/@remobile/react-native-toast/android')
|
||||
include ':rn-fetch-blob'
|
||||
|
|
|
@ -266,7 +266,7 @@ export default class MessageBox extends React.PureComponent {
|
|||
await RocketChat.sendFileMessage(this.props.rid, fileInfo);
|
||||
} catch (e) {
|
||||
if (e && e.error === 'error-file-too-large') {
|
||||
return Alert.alert('File is too large!');
|
||||
return Alert.alert(I18n.t(e.error));
|
||||
}
|
||||
log('finishAudioMessage', e);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { View, StyleSheet, TouchableOpacity, Text, Easing, Image } from 'react-native';
|
||||
import { View, StyleSheet, Text, Easing, Image } from 'react-native';
|
||||
import Video from 'react-native-video';
|
||||
import Slider from 'react-native-slider';
|
||||
import moment from 'moment';
|
||||
import { BorderlessButton } from 'react-native-gesture-handler';
|
||||
|
||||
import Markdown from './Markdown';
|
||||
|
||||
|
@ -116,7 +117,7 @@ export default class Audio extends React.PureComponent {
|
|||
paused={paused}
|
||||
repeat={false}
|
||||
/>
|
||||
<TouchableOpacity
|
||||
<BorderlessButton
|
||||
style={styles.playPauseButton}
|
||||
onPress={() => this.togglePlayPause()}
|
||||
>
|
||||
|
@ -125,7 +126,7 @@ export default class Audio extends React.PureComponent {
|
|||
<Image source={{ uri: 'play' }} style={styles.playPauseImage} /> :
|
||||
<Image source={{ uri: 'pause' }} style={styles.playPauseImage} />
|
||||
}
|
||||
</TouchableOpacity>
|
||||
</BorderlessButton>
|
||||
<Slider
|
||||
style={styles.slider}
|
||||
value={this.state.currentTime}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
import { TouchableOpacity } from 'react-native';
|
||||
import { RectButton } from 'react-native-gesture-handler';
|
||||
|
||||
import PhotoModal from './PhotoModal';
|
||||
import Markdown from './Markdown';
|
||||
|
@ -20,6 +20,12 @@ export default class extends React.PureComponent {
|
|||
|
||||
state = { modalVisible: false };
|
||||
|
||||
onPressButton() {
|
||||
this.setState({
|
||||
modalVisible: true
|
||||
});
|
||||
}
|
||||
|
||||
getDescription() {
|
||||
const {
|
||||
file, customEmojis, baseUrl, user
|
||||
|
@ -29,13 +35,12 @@ export default class extends React.PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
_onPressButton() {
|
||||
this.setState({
|
||||
modalVisible: true
|
||||
});
|
||||
isPressed = (state) => {
|
||||
this.setState({ isPressed: state });
|
||||
}
|
||||
|
||||
render() {
|
||||
const { isPressed } = this.state;
|
||||
const { baseUrl, file, user } = this.props;
|
||||
const img = `${ baseUrl }${ file.image_url }?rc_uid=${ user.id }&rc_token=${ user.token }`;
|
||||
|
||||
|
@ -45,18 +50,20 @@ export default class extends React.PureComponent {
|
|||
|
||||
return (
|
||||
[
|
||||
<TouchableOpacity
|
||||
<RectButton
|
||||
key='image'
|
||||
onPress={() => this._onPressButton()}
|
||||
onPress={() => this.onPressButton()}
|
||||
onActiveStateChange={this.isPressed}
|
||||
style={styles.imageContainer}
|
||||
underlayColor='#fff'
|
||||
>
|
||||
<FastImage
|
||||
style={styles.image}
|
||||
style={[styles.image, isPressed && { opacity: 0.5 }]}
|
||||
source={{ uri: encodeURI(img) }}
|
||||
resizeMode={FastImage.resizeMode.cover}
|
||||
/>
|
||||
{this.getDescription()}
|
||||
</TouchableOpacity>,
|
||||
</RectButton>,
|
||||
<PhotoModal
|
||||
key='modal'
|
||||
title={file.title}
|
||||
|
|
|
@ -52,17 +52,13 @@ export default class Markdown extends React.Component {
|
|||
};
|
||||
}
|
||||
return (
|
||||
<Text
|
||||
key={key}
|
||||
onPress={() => alert(`Username ${ content }`)}
|
||||
style={mentionStyle}
|
||||
>
|
||||
<Text style={mentionStyle} key={key}>
|
||||
{content}
|
||||
</Text>
|
||||
);
|
||||
},
|
||||
hashtag: node => (
|
||||
<Text key={node.key} onPress={() => alert(`Room #${ node.content }`)} style={styles.mention}>
|
||||
<Text key={node.key} style={styles.mention}>
|
||||
#{node.content}
|
||||
</Text>
|
||||
),
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import React, { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { View, Text, TouchableOpacity, ViewPropTypes, Image as ImageRN } from 'react-native';
|
||||
import { View, Text, ViewPropTypes, Image as ImageRN } from 'react-native';
|
||||
import Icon from 'react-native-vector-icons/MaterialIcons';
|
||||
import moment from 'moment';
|
||||
import { KeyboardUtils } from 'react-native-keyboard-input';
|
||||
import { State, RectButton, LongPressGestureHandler } from 'react-native-gesture-handler';
|
||||
|
||||
import Image from './Image';
|
||||
import User from './User';
|
||||
|
@ -16,7 +17,6 @@ import Reply from './Reply';
|
|||
import ReactionsModal from './ReactionsModal';
|
||||
import Emoji from './Emoji';
|
||||
import styles from './styles';
|
||||
import Touch from '../../utils/touch';
|
||||
import I18n from '../../i18n';
|
||||
import messagesStatus from '../../constants/messagesStatus';
|
||||
|
||||
|
@ -247,25 +247,31 @@ export default class Message extends PureComponent {
|
|||
|
||||
renderReaction = (reaction) => {
|
||||
const reacted = reaction.usernames.findIndex(item => item.value === this.props.user.username) !== -1;
|
||||
const reactedContainerStyle = reacted && styles.reactedContainer;
|
||||
const underlayColor = reacted ? '#fff' : '#e1e5e8';
|
||||
return (
|
||||
<TouchableOpacity
|
||||
onPress={() => this.props.onReactionPress(reaction.emoji)}
|
||||
onLongPress={this.props.onReactionLongPress}
|
||||
<LongPressGestureHandler
|
||||
key={reaction.emoji}
|
||||
testID={`message-reaction-${ reaction.emoji }`}
|
||||
onHandlerStateChange={({ nativeEvent }) => nativeEvent.state === State.ACTIVE && this.props.onReactionLongPress()}
|
||||
>
|
||||
<View style={[styles.reactionContainer, reactedContainerStyle]}>
|
||||
<Emoji
|
||||
content={reaction.emoji}
|
||||
customEmojis={this.props.customEmojis}
|
||||
standardEmojiStyle={styles.reactionEmoji}
|
||||
customEmojiStyle={styles.reactionCustomEmoji}
|
||||
baseUrl={this.props.baseUrl}
|
||||
/>
|
||||
<Text style={styles.reactionCount}>{ reaction.usernames.length }</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
<RectButton
|
||||
onPress={() => this.props.onReactionPress(reaction.emoji)}
|
||||
testID={`message-reaction-${ reaction.emoji }`}
|
||||
style={[styles.reactionButton, reacted && { backgroundColor: '#e8f2ff' }]}
|
||||
activeOpacity={0.8}
|
||||
underlayColor={underlayColor}
|
||||
>
|
||||
<View style={[styles.reactionContainer, reacted && styles.reactedContainer]}>
|
||||
<Emoji
|
||||
content={reaction.emoji}
|
||||
customEmojis={this.props.customEmojis}
|
||||
standardEmojiStyle={styles.reactionEmoji}
|
||||
customEmojiStyle={styles.reactionCustomEmoji}
|
||||
baseUrl={this.props.baseUrl}
|
||||
/>
|
||||
<Text style={styles.reactionCount}>{ reaction.usernames.length }</Text>
|
||||
</View>
|
||||
</RectButton>
|
||||
</LongPressGestureHandler>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -277,14 +283,18 @@ export default class Message extends PureComponent {
|
|||
return (
|
||||
<View style={styles.reactionsContainer}>
|
||||
{reactions.map(this.renderReaction)}
|
||||
<TouchableOpacity
|
||||
<RectButton
|
||||
onPress={this.props.toggleReactionPicker}
|
||||
key='message-add-reaction'
|
||||
testID='message-add-reaction'
|
||||
style={styles.reactionContainer}
|
||||
style={styles.reactionButton}
|
||||
activeOpacity={0.8}
|
||||
underlayColor='#e1e5e8'
|
||||
>
|
||||
<ImageRN source={{ uri: 'add_reaction' }} style={styles.addReaction} />
|
||||
</TouchableOpacity>
|
||||
<View style={styles.reactionContainer}>
|
||||
<ImageRN source={{ uri: 'add_reaction' }} style={styles.addReaction} />
|
||||
</View>
|
||||
</RectButton>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
@ -292,15 +302,15 @@ export default class Message extends PureComponent {
|
|||
renderBroadcastReply() {
|
||||
if (this.props.broadcast && !this.isOwn()) {
|
||||
return (
|
||||
<Touch
|
||||
<RectButton
|
||||
onPress={this.props.replyBroadcast}
|
||||
style={styles.broadcastButton}
|
||||
activeOpacity={0.5}
|
||||
underlayColor='#fff'
|
||||
>
|
||||
<View style={styles.broadcastButtonContainer}>
|
||||
<ImageRN source={{ uri: 'reply' }} style={styles.broadcastButtonIcon} />
|
||||
<Text style={styles.broadcastButtonText}>Reply</Text>
|
||||
</View>
|
||||
</Touch>
|
||||
<ImageRN source={{ uri: 'reply' }} style={styles.broadcastButtonIcon} />
|
||||
<Text style={styles.broadcastButtonText}>{I18n.t('Reply')}</Text>
|
||||
</RectButton>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
|
@ -313,39 +323,46 @@ export default class Message extends PureComponent {
|
|||
const accessibilityLabel = I18n.t('Message_accessibility', { user: author.username, time: moment(ts).format(timeFormat), message: msg });
|
||||
|
||||
return (
|
||||
<Touch
|
||||
onPress={this.onPress}
|
||||
onLongPress={onLongPress}
|
||||
disabled={this.isInfoMessage() || this.hasError() || archived}
|
||||
accessibilityLabel={accessibilityLabel}
|
||||
style={[styles.container, header && { marginBottom: 10 }]}
|
||||
<LongPressGestureHandler
|
||||
onHandlerStateChange={({ nativeEvent }) => nativeEvent.state === State.ACTIVE && onLongPress()}
|
||||
>
|
||||
<View style={[styles.message, editing && styles.editing, style]}>
|
||||
<View style={styles.flex}>
|
||||
{this.renderError()}
|
||||
{this.renderAvatar()}
|
||||
<View style={[styles.messageContent, header && styles.hasHeader, this.isTemp() && styles.temp]}>
|
||||
{this.renderUsername()}
|
||||
{this.renderContent()}
|
||||
{this.renderAttachment()}
|
||||
{this.renderUrl()}
|
||||
{this.renderReactions()}
|
||||
{this.renderBroadcastReply()}
|
||||
<RectButton
|
||||
enabled={!(this.isInfoMessage() || this.hasError() || archived)}
|
||||
style={[styles.container, header && { marginBottom: 10 }]}
|
||||
onPress={this.onPress}
|
||||
activeOpacity={0.8}
|
||||
underlayColor='#e1e5e8'
|
||||
>
|
||||
<View
|
||||
style={[styles.message, editing && styles.editing, style]}
|
||||
accessibilityLabel={accessibilityLabel}
|
||||
>
|
||||
<View style={styles.flex}>
|
||||
{this.renderError()}
|
||||
{this.renderAvatar()}
|
||||
<View style={[styles.messageContent, header && styles.hasHeader, this.isTemp() && styles.temp]}>
|
||||
{this.renderUsername()}
|
||||
{this.renderContent()}
|
||||
{this.renderAttachment()}
|
||||
{this.renderUrl()}
|
||||
{this.renderReactions()}
|
||||
{this.renderBroadcastReply()}
|
||||
</View>
|
||||
</View>
|
||||
{reactionsModal ?
|
||||
<ReactionsModal
|
||||
isVisible={reactionsModal}
|
||||
reactions={reactions}
|
||||
user={user}
|
||||
customEmojis={customEmojis}
|
||||
baseUrl={baseUrl}
|
||||
close={closeReactions}
|
||||
/>
|
||||
: null
|
||||
}
|
||||
</View>
|
||||
{reactionsModal ?
|
||||
<ReactionsModal
|
||||
isVisible={reactionsModal}
|
||||
reactions={reactions}
|
||||
user={user}
|
||||
customEmojis={customEmojis}
|
||||
baseUrl={baseUrl}
|
||||
close={closeReactions}
|
||||
/>
|
||||
: null
|
||||
}
|
||||
</View>
|
||||
</Touch>
|
||||
</RectButton>
|
||||
</LongPressGestureHandler>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
import React from 'react';
|
||||
import { View, StyleSheet } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
quoteSign: {
|
||||
borderWidth: 2,
|
||||
borderRadius: 4,
|
||||
height: '100%',
|
||||
marginRight: 5
|
||||
}
|
||||
});
|
||||
|
||||
const QuoteMark = ({ color }) => <View style={[styles.quoteSign, { borderColor: color || '#a0a0a0' }]} />;
|
||||
|
||||
QuoteMark.propTypes = {
|
||||
color: PropTypes.string
|
||||
};
|
||||
|
||||
export default QuoteMark;
|
|
@ -2,10 +2,10 @@ import React from 'react';
|
|||
import { View, Text, StyleSheet } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
import moment from 'moment';
|
||||
import { RectButton } from 'react-native-gesture-handler';
|
||||
|
||||
import Markdown from './Markdown';
|
||||
import openLink from '../../utils/openLink';
|
||||
import Touch from '../../utils/touch';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
button: {
|
||||
|
@ -13,13 +13,13 @@ const styles = StyleSheet.create({
|
|||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginTop: 15,
|
||||
alignSelf: 'flex-end'
|
||||
alignSelf: 'flex-end',
|
||||
backgroundColor: '#f3f4f5'
|
||||
},
|
||||
attachmentContainer: {
|
||||
flex: 1,
|
||||
borderRadius: 4,
|
||||
flexDirection: 'column',
|
||||
backgroundColor: '#f3f4f5',
|
||||
padding: 15
|
||||
},
|
||||
authorContainer: {
|
||||
|
@ -55,12 +55,15 @@ const styles = StyleSheet.create({
|
|||
}
|
||||
});
|
||||
|
||||
const onPress = (attachment) => {
|
||||
const url = attachment.title_link || attachment.author_link;
|
||||
const onPress = (attachment, baseUrl, user) => {
|
||||
let url = attachment.title_link || attachment.author_link;
|
||||
if (!url) {
|
||||
return;
|
||||
}
|
||||
openLink(attachment.title_link || attachment.author_link);
|
||||
if (attachment.type === 'file') {
|
||||
url = `${ baseUrl }${ url }?rc_uid=${ user.id }&rc_token=${ user.token }`;
|
||||
}
|
||||
openLink(url);
|
||||
};
|
||||
|
||||
const Reply = ({
|
||||
|
@ -91,9 +94,19 @@ const Reply = ({
|
|||
);
|
||||
};
|
||||
|
||||
const renderText = () => (
|
||||
attachment.text ? <Markdown msg={attachment.text} customEmojis={customEmojis} baseUrl={baseUrl} username={user.username} /> : null
|
||||
);
|
||||
const renderText = () => {
|
||||
const text = attachment.text || attachment.title;
|
||||
if (text) {
|
||||
return (
|
||||
<Markdown
|
||||
msg={text}
|
||||
customEmojis={customEmojis}
|
||||
baseUrl={baseUrl}
|
||||
username={user.username}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const renderFields = () => {
|
||||
if (!attachment.fields) {
|
||||
|
@ -113,16 +126,18 @@ const Reply = ({
|
|||
};
|
||||
|
||||
return (
|
||||
<Touch
|
||||
onPress={() => onPress(attachment)}
|
||||
<RectButton
|
||||
onPress={() => onPress(attachment, baseUrl, user)}
|
||||
style={[styles.button, index > 0 && styles.marginTop]}
|
||||
activeOpacity={0.5}
|
||||
underlayColor='#fff'
|
||||
>
|
||||
<View style={styles.attachmentContainer}>
|
||||
{renderTitle()}
|
||||
{renderText()}
|
||||
{renderFields()}
|
||||
</View>
|
||||
</Touch>
|
||||
</RectButton>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -2,9 +2,9 @@ import React from 'react';
|
|||
import { View, Text, StyleSheet } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
import { RectButton } from 'react-native-gesture-handler';
|
||||
|
||||
import openLink from '../../utils/openLink';
|
||||
import Touch from '../../utils/touch';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
button: {
|
||||
|
@ -58,16 +58,19 @@ const Url = ({ url, index }) => {
|
|||
return null;
|
||||
}
|
||||
return (
|
||||
<Touch onPress={() => onPress(url.url)} style={[styles.button, index > 0 && styles.marginTop]}>
|
||||
<View style={styles.container}>
|
||||
{url.image ? <FastImage source={{ uri: url.image }} style={styles.image} resizeMode={FastImage.resizeMode.cover} /> : null}
|
||||
<View style={styles.textContainer}>
|
||||
<Text style={styles.url} numberOfLines={1}>{url.url}</Text>
|
||||
<Text style={styles.title} numberOfLines={2}>{url.title}</Text>
|
||||
<Text style={styles.description} numberOfLines={2}>{url.description}</Text>
|
||||
</View>
|
||||
<RectButton
|
||||
onPress={() => onPress(url.url)}
|
||||
style={[styles.button, index > 0 && styles.marginTop, styles.container]}
|
||||
activeOpacity={0.5}
|
||||
underlayColor='#fff'
|
||||
>
|
||||
{url.image ? <FastImage source={{ uri: url.image }} style={styles.image} resizeMode={FastImage.resizeMode.cover} /> : null}
|
||||
<View style={styles.textContainer}>
|
||||
<Text style={styles.url} numberOfLines={1}>{url.url}</Text>
|
||||
<Text style={styles.title} numberOfLines={2}>{url.title}</Text>
|
||||
<Text style={styles.description} numberOfLines={2}>{url.description}</Text>
|
||||
</View>
|
||||
</Touch>
|
||||
</RectButton>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -36,8 +36,7 @@ export default class User extends React.PureComponent {
|
|||
username: PropTypes.string,
|
||||
alias: PropTypes.string,
|
||||
ts: PropTypes.instanceOf(Date),
|
||||
temp: PropTypes.bool,
|
||||
onPress: PropTypes.func
|
||||
temp: PropTypes.bool
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -55,7 +54,7 @@ export default class User extends React.PureComponent {
|
|||
|
||||
return (
|
||||
<View style={styles.usernameView}>
|
||||
<Text onPress={this.props.onPress} style={styles.username}>
|
||||
<Text style={styles.username}>
|
||||
{alias || username}
|
||||
</Text>
|
||||
{aliasUsername}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { StyleSheet, TouchableOpacity, Image, Platform, View } from 'react-native';
|
||||
import { StyleSheet, Image, Platform, View } from 'react-native';
|
||||
import Modal from 'react-native-modal';
|
||||
import VideoPlayer from 'react-native-video-controls';
|
||||
import { RectButton } from 'react-native-gesture-handler';
|
||||
|
||||
import Markdown from './Markdown';
|
||||
import openLink from '../../utils/openLink';
|
||||
|
||||
|
@ -70,15 +72,17 @@ export default class Video extends React.PureComponent {
|
|||
return (
|
||||
[
|
||||
<View key='button'>
|
||||
<TouchableOpacity
|
||||
<RectButton
|
||||
style={styles.button}
|
||||
onPress={() => this.open()}
|
||||
activeOpacity={0.5}
|
||||
underlayColor='#fff'
|
||||
>
|
||||
<Image
|
||||
source={{ uri: 'play_video' }}
|
||||
style={styles.image}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
</RectButton>
|
||||
<Markdown msg={description} customEmojis={customEmojis} baseUrl={baseUrl} username={user.username} />
|
||||
</View>,
|
||||
<Modal
|
||||
|
|
|
@ -146,7 +146,7 @@ export default class MessageContainer extends React.Component {
|
|||
item, message, editing, user, style, archived, baseUrl, customEmojis, useRealName, broadcast
|
||||
} = this.props;
|
||||
const {
|
||||
msg, ts, attachments, urls, reactions, t, status, avatar, u, alias, editedBy
|
||||
msg, ts, attachments, urls, reactions, t, status, avatar, u, alias, editedBy, role
|
||||
} = item;
|
||||
const isEditing = message._id === item._id && editing;
|
||||
return (
|
||||
|
@ -173,6 +173,7 @@ export default class MessageContainer extends React.Component {
|
|||
customEmojis={customEmojis}
|
||||
reactionsModal={this.state.reactionsModal}
|
||||
useRealName={useRealName}
|
||||
role={role}
|
||||
closeReactions={this.closeReactions}
|
||||
onErrorPress={this.onErrorPress}
|
||||
onLongPress={this.onLongPress}
|
||||
|
|
|
@ -51,6 +51,11 @@ export default StyleSheet.create({
|
|||
flexWrap: 'wrap',
|
||||
marginTop: 10
|
||||
},
|
||||
reactionButton: {
|
||||
marginRight: 10,
|
||||
marginBottom: 10,
|
||||
borderRadius: 4
|
||||
},
|
||||
reactionContainer: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
|
@ -58,11 +63,11 @@ export default StyleSheet.create({
|
|||
borderRadius: 4,
|
||||
borderWidth: 1.5,
|
||||
borderColor: '#e1e5e8',
|
||||
marginRight: 10,
|
||||
marginBottom: 10,
|
||||
height: 28,
|
||||
minWidth: 46,
|
||||
backgroundColor: '#FFF'
|
||||
minWidth: 46
|
||||
},
|
||||
reactedContainer: {
|
||||
borderColor: '#1d74f580'
|
||||
},
|
||||
reactionCount: {
|
||||
fontSize: 14,
|
||||
|
@ -83,10 +88,6 @@ export default StyleSheet.create({
|
|||
avatar: {
|
||||
marginTop: 5
|
||||
},
|
||||
reactedContainer: {
|
||||
borderColor: '#1d74f580',
|
||||
backgroundColor: '#e8f2ff'
|
||||
},
|
||||
addReaction: {
|
||||
width: 17,
|
||||
height: 17
|
||||
|
@ -99,9 +100,7 @@ export default StyleSheet.create({
|
|||
broadcastButton: {
|
||||
width: 107,
|
||||
height: 44,
|
||||
marginTop: 15
|
||||
},
|
||||
broadcastButtonContainer: {
|
||||
marginTop: 15,
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
|
|
|
@ -142,6 +142,7 @@ export default {
|
|||
Direct_Messages: 'Direct Messages',
|
||||
Do_you_really_want_to_key_this_room_question_mark: 'Do you really want to {{key}} this room?',
|
||||
edit: 'edit',
|
||||
erasing_room: 'erasing room',
|
||||
Edit: 'Edit',
|
||||
Email_or_password_field_is_empty: 'Email or password field is empty',
|
||||
Email: 'Email',
|
||||
|
@ -167,10 +168,12 @@ export default {
|
|||
is_not_a_valid_RocketChat_instance: 'is not a valid Rocket.Chat instance',
|
||||
is_typing: 'is typing',
|
||||
Join_the_community: 'Join the community',
|
||||
Join: 'Join',
|
||||
Just_invited_people_can_access_this_channel: 'Just invited people can access this channel',
|
||||
Language: 'Language',
|
||||
last_message: 'last message',
|
||||
Leave_channel: 'Leave channel',
|
||||
leaving_room: 'leaving room',
|
||||
leave: 'leave',
|
||||
Livechat: 'Livechat',
|
||||
Login: 'Login',
|
||||
|
|
|
@ -6,7 +6,7 @@ import messagesStatus from '../../../constants/messagesStatus';
|
|||
import log from '../../../utils/log';
|
||||
|
||||
export default async function subscribeRooms(id) {
|
||||
const subscriptions = Promise.all([
|
||||
const promises = Promise.all([
|
||||
this.ddp.subscribe('stream-notify-user', `${ id }/subscriptions-changed`, false),
|
||||
this.ddp.subscribe('stream-notify-user', `${ id }/rooms-changed`, false),
|
||||
this.ddp.subscribe('stream-notify-user', `${ id }/message`, false)
|
||||
|
@ -51,12 +51,25 @@ export default async function subscribeRooms(id) {
|
|||
const [type, data] = ddpMessage.fields.args;
|
||||
const [, ev] = ddpMessage.fields.eventName.split('/');
|
||||
if (/subscriptions/.test(ev)) {
|
||||
const rooms = database.objects('rooms').filtered('_id == $0', data.rid);
|
||||
const tpm = merge(data, rooms[0]);
|
||||
database.write(() => {
|
||||
database.create('subscriptions', tpm, true);
|
||||
database.delete(rooms);
|
||||
});
|
||||
if (type === 'removed') {
|
||||
let messages = [];
|
||||
const [subscription] = database.objects('subscriptions').filtered('_id == $0', data._id);
|
||||
|
||||
if (subscription) {
|
||||
messages = database.objects('messages').filtered('rid == $0', subscription.rid);
|
||||
}
|
||||
database.write(() => {
|
||||
database.delete(messages);
|
||||
database.delete(subscription);
|
||||
});
|
||||
} else {
|
||||
const rooms = database.objects('rooms').filtered('_id == $0', data.rid);
|
||||
const tpm = merge(data, rooms[0]);
|
||||
database.write(() => {
|
||||
database.create('subscriptions', tpm, true);
|
||||
database.delete(rooms);
|
||||
});
|
||||
}
|
||||
}
|
||||
if (/rooms/.test(ev)) {
|
||||
if (type === 'updated') {
|
||||
|
@ -93,9 +106,8 @@ export default async function subscribeRooms(id) {
|
|||
}
|
||||
|
||||
try {
|
||||
await subscriptions;
|
||||
await promises;
|
||||
} catch (e) {
|
||||
log('subscribeRooms', e);
|
||||
}
|
||||
// console.log(this.ddp.subscriptions);
|
||||
}
|
||||
|
|
|
@ -470,9 +470,11 @@ const RocketChat = {
|
|||
log('rocketchat.logout', e);
|
||||
}
|
||||
}
|
||||
// database.deleteAll();
|
||||
AsyncStorage.removeItem(TOKEN_KEY);
|
||||
AsyncStorage.removeItem(`${ TOKEN_KEY }-${ server }`);
|
||||
setTimeout(() => {
|
||||
database.deleteAll();
|
||||
}, 1000);
|
||||
},
|
||||
|
||||
registerPushToken(userId) {
|
||||
|
@ -750,7 +752,7 @@ const RocketChat = {
|
|||
// transform room roles to array
|
||||
const roomRoles = Array.from(Object.keys(roles), i => roles[i].value);
|
||||
// get user roles on the server from redux
|
||||
const userRoles = reduxStore.getState().login.user.roles || [];
|
||||
const userRoles = (reduxStore.getState().login.user && reduxStore.getState().login.user.roles) || [];
|
||||
// merge both roles
|
||||
const mergedRoles = [...new Set([...roomRoles, ...userRoles])];
|
||||
|
||||
|
|
|
@ -26,11 +26,7 @@ const handleRequest = function* handleRequest({ data }) {
|
|||
screen: 'RoomView',
|
||||
title: name,
|
||||
backButtonTitle: '',
|
||||
passProps: {
|
||||
room: { rid, name },
|
||||
rid,
|
||||
name
|
||||
}
|
||||
passProps: { rid }
|
||||
});
|
||||
} catch (err) {
|
||||
yield put(createChannelFailure(err));
|
||||
|
|
|
@ -80,12 +80,9 @@ const goRoom = function* goRoom({ rid, name }) {
|
|||
yield delay(1000);
|
||||
NavigationActions.push({
|
||||
screen: 'RoomView',
|
||||
title: name,
|
||||
backButtonTitle: '',
|
||||
passProps: {
|
||||
room: { rid, name },
|
||||
rid,
|
||||
name
|
||||
}
|
||||
passProps: { rid }
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import { messagesRequest, editCancel, replyCancel } from '../actions/messages';
|
|||
import RocketChat from '../lib/rocketchat';
|
||||
import database from '../lib/realm';
|
||||
import log from '../utils/log';
|
||||
import I18n from '../i18n';
|
||||
import { NavigationActions } from '../Navigation';
|
||||
|
||||
const leaveRoom = rid => RocketChat.leaveRoom(rid);
|
||||
|
@ -63,41 +64,40 @@ const handleMessageReceived = function* handleMessageReceived({ message }) {
|
|||
database.create('messages', message, true);
|
||||
});
|
||||
|
||||
RocketChat.readMessages(room.rid);
|
||||
if (room._id) {
|
||||
RocketChat.readMessages(room.rid);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('handleMessageReceived', e);
|
||||
}
|
||||
};
|
||||
|
||||
let opened = false;
|
||||
|
||||
const watchRoomOpen = function* watchRoomOpen({ room }) {
|
||||
try {
|
||||
yield put(messagesRequest({ ...room }));
|
||||
// const { open } = yield race({
|
||||
// messages: take(types.MESSAGES.SUCCESS),
|
||||
// open: take(types.ROOM.OPEN)
|
||||
// });
|
||||
//
|
||||
// if (open) {
|
||||
// return;
|
||||
// }
|
||||
if (opened) {
|
||||
return;
|
||||
}
|
||||
opened = true;
|
||||
|
||||
RocketChat.readMessages(room.rid);
|
||||
yield put(messagesRequest({ ...room }));
|
||||
|
||||
if (room._id) {
|
||||
RocketChat.readMessages(room.rid);
|
||||
}
|
||||
sub = yield RocketChat.subscribeRoom(room);
|
||||
// const subscriptions = yield Promise.all([RocketChat.subscribe('stream-room-messages', room.rid, false), RocketChat.subscribe('stream-notify-room', `${ room.rid }/typing`, false)]);
|
||||
thread = yield fork(usersTyping, { rid: room.rid });
|
||||
yield race({
|
||||
open: take(types.ROOM.OPEN),
|
||||
close: take(types.ROOM.CLOSE)
|
||||
});
|
||||
opened = false;
|
||||
cancel(thread);
|
||||
sub.stop();
|
||||
yield put(editCancel());
|
||||
yield put(replyCancel());
|
||||
|
||||
// subscriptions.forEach((sub) => {
|
||||
// sub.unsubscribe().catch(e => alert(e));
|
||||
// });
|
||||
} catch (e) {
|
||||
log('watchRoomOpen', e);
|
||||
}
|
||||
|
@ -161,9 +161,9 @@ const handleLeaveRoom = function* handleLeaveRoom({ rid }) {
|
|||
yield goRoomsListAndDelete(rid);
|
||||
} catch (e) {
|
||||
if (e.error === 'error-you-are-last-owner') {
|
||||
Alert.alert('You are the last owner. Please set new owner before leaving the room.');
|
||||
Alert.alert(e.error);
|
||||
} else {
|
||||
Alert.alert('Something happened when leaving room!');
|
||||
Alert.alert(I18n.t('There_was_an_error_while_action', { action: I18n.t('leaving_room') }));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -174,7 +174,7 @@ const handleEraseRoom = function* handleEraseRoom({ rid }) {
|
|||
yield call(eraseRoom, rid);
|
||||
yield goRoomsListAndDelete(rid);
|
||||
} catch (e) {
|
||||
Alert.alert('Something happened when erasing room!');
|
||||
Alert.alert(I18n.t('There_was_an_error_while_action', { action: I18n.t('erasing_room') }));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Before Width: | Height: | Size: 1021 B |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 223 B |
Before Width: | Height: | Size: 371 B |
Before Width: | Height: | Size: 527 B |
|
@ -0,0 +1,7 @@
|
|||
import DeviceInfo from 'react-native-device-info';
|
||||
|
||||
export default {
|
||||
isNotch: () => DeviceInfo.getModel() === 'iPhone X',
|
||||
getBrand: () => DeviceInfo.getBrand(),
|
||||
getReadableVersion: () => DeviceInfo.getReadableVersion()
|
||||
};
|
|
@ -37,8 +37,8 @@ const styles = StyleSheet.create({
|
|||
fontWeight: '700'
|
||||
},
|
||||
planetImage: {
|
||||
width: 200,
|
||||
height: 162,
|
||||
width: 210,
|
||||
height: 171,
|
||||
marginVertical: 20
|
||||
}
|
||||
});
|
||||
|
@ -283,10 +283,7 @@ export default class LoginSignupView extends LoggedView {
|
|||
<View style={styles.container}>
|
||||
<Text style={[sharedStyles.loginText, styles.header, { color: '#81848A' }]}>{I18n.t('Welcome_title_pt_1')}</Text>
|
||||
<Text style={[sharedStyles.loginText, styles.header]}>{I18n.t('Welcome_title_pt_2')}</Text>
|
||||
<Image
|
||||
style={styles.planetImage}
|
||||
source={require('../static/images/server.png')}
|
||||
/>
|
||||
<Image style={styles.planetImage} source={{ uri: 'new_server' }} />
|
||||
<Button
|
||||
title={I18n.t('I_have_an_account')}
|
||||
type='primary'
|
||||
|
|
|
@ -58,7 +58,7 @@ export default class LoginView extends LoggedView {
|
|||
|
||||
try {
|
||||
await this.props.loginSubmit({ username, password, code });
|
||||
Answers.logLogin('Email', true, { server: this.props.server });
|
||||
Answers.logLogin('Email', true);
|
||||
} catch (error) {
|
||||
console.warn('LoginView submit', error);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Text, ScrollView, Keyboard, SafeAreaView, Image, Alert, StyleSheet } from 'react-native';
|
||||
import { Text, ScrollView, Keyboard, SafeAreaView, Image, Alert, StyleSheet, TouchableOpacity } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import Icon from 'react-native-vector-icons/Ionicons';
|
||||
|
||||
import { serverRequest, selectServerRequest, serverInitAdd, serverFinishAdd } from '../actions/server';
|
||||
import { serverRequest } from '../actions/server';
|
||||
import sharedStyles from './Styles';
|
||||
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
||||
import Button from '../containers/Button';
|
||||
|
@ -12,11 +13,14 @@ import LoggedView from './View';
|
|||
import I18n from '../i18n';
|
||||
import { scale, verticalScale, moderateScale } from '../utils/scaling';
|
||||
import KeyboardView from '../presentation/KeyboardView';
|
||||
import DeviceInfo from '../utils/deviceInfo';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
image: {
|
||||
alignSelf: 'center',
|
||||
marginVertical: verticalScale(20)
|
||||
marginVertical: verticalScale(20),
|
||||
width: 210,
|
||||
height: 171
|
||||
},
|
||||
title: {
|
||||
alignSelf: 'center',
|
||||
|
@ -36,6 +40,11 @@ const styles = StyleSheet.create({
|
|||
paddingTop: 14,
|
||||
paddingBottom: 14,
|
||||
paddingHorizontal: 16
|
||||
},
|
||||
backButton: {
|
||||
position: 'absolute',
|
||||
paddingHorizontal: 9,
|
||||
left: 15
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -43,14 +52,9 @@ const defaultServer = 'https://open.rocket.chat';
|
|||
|
||||
@connect(state => ({
|
||||
connecting: state.server.connecting,
|
||||
failure: state.server.failure,
|
||||
currentServer: state.server.server,
|
||||
adding: state.server.adding
|
||||
failure: state.server.failure
|
||||
}), dispatch => ({
|
||||
initAdd: () => dispatch(serverInitAdd()),
|
||||
finishAdd: () => dispatch(serverFinishAdd()),
|
||||
connectServer: server => dispatch(serverRequest(server)),
|
||||
selectServer: server => dispatch(selectServerRequest(server))
|
||||
connectServer: server => dispatch(serverRequest(server))
|
||||
}))
|
||||
/** @extends React.Component */
|
||||
export default class NewServerView extends LoggedView {
|
||||
|
@ -58,14 +62,8 @@ export default class NewServerView extends LoggedView {
|
|||
navigator: PropTypes.object,
|
||||
server: PropTypes.string,
|
||||
connecting: PropTypes.bool.isRequired,
|
||||
adding: PropTypes.bool,
|
||||
failure: PropTypes.bool.isRequired,
|
||||
connectServer: PropTypes.func.isRequired,
|
||||
selectServer: PropTypes.func.isRequired,
|
||||
previousServer: PropTypes.string,
|
||||
currentServer: PropTypes.string,
|
||||
initAdd: PropTypes.func,
|
||||
finishAdd: PropTypes.func
|
||||
connectServer: PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
|
@ -73,11 +71,10 @@ export default class NewServerView extends LoggedView {
|
|||
this.state = {
|
||||
text: ''
|
||||
};
|
||||
props.navigator.setOnNavigatorEvent(this.onNavigatorEvent.bind(this));
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { server, previousServer } = this.props;
|
||||
const { server } = this.props;
|
||||
if (server) {
|
||||
this.props.connectServer(server);
|
||||
this.setState({ text: server });
|
||||
|
@ -86,9 +83,6 @@ export default class NewServerView extends LoggedView {
|
|||
this.input.focus();
|
||||
}, 600);
|
||||
}
|
||||
if (previousServer) {
|
||||
this.props.initAdd();
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
|
@ -97,26 +91,6 @@ export default class NewServerView extends LoggedView {
|
|||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
const {
|
||||
selectServer, previousServer, currentServer, adding, finishAdd
|
||||
} = this.props;
|
||||
if (adding) {
|
||||
if (previousServer !== currentServer) {
|
||||
selectServer(previousServer);
|
||||
}
|
||||
finishAdd();
|
||||
}
|
||||
}
|
||||
|
||||
onNavigatorEvent(event) {
|
||||
if (event.type === 'NavBarButtonPress') {
|
||||
if (event.id === 'cancel') {
|
||||
this.props.navigator.dismissModal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onChangeText = (text) => {
|
||||
this.setState({ text });
|
||||
}
|
||||
|
@ -147,6 +121,26 @@ export default class NewServerView extends LoggedView {
|
|||
return url.replace(/\/+$/, '');
|
||||
}
|
||||
|
||||
renderBack = () => {
|
||||
let top = 15;
|
||||
if (DeviceInfo.getBrand() === 'Apple') {
|
||||
top = DeviceInfo.isNotch() ? 45 : 30;
|
||||
}
|
||||
|
||||
return (
|
||||
<TouchableOpacity
|
||||
style={[styles.backButton, { top }]}
|
||||
onPress={() => this.props.navigator.pop()}
|
||||
>
|
||||
<Icon
|
||||
name='ios-arrow-back'
|
||||
size={30}
|
||||
color='#1D74F5'
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { connecting } = this.props;
|
||||
const { text } = this.state;
|
||||
|
@ -158,7 +152,7 @@ export default class NewServerView extends LoggedView {
|
|||
>
|
||||
<ScrollView {...scrollPersistTaps} contentContainerStyle={sharedStyles.containerScrollView}>
|
||||
<SafeAreaView style={sharedStyles.container} testID='new-server-view'>
|
||||
<Image style={styles.image} source={require('../static/images/server.png')} />
|
||||
<Image style={styles.image} source={{ uri: 'new_server' }} />
|
||||
<Text style={styles.title}>{I18n.t('Sign_in_your_server')}</Text>
|
||||
<TextInput
|
||||
inputRef={e => this.input = e}
|
||||
|
@ -182,6 +176,7 @@ export default class NewServerView extends LoggedView {
|
|||
/>
|
||||
</SafeAreaView>
|
||||
</ScrollView>
|
||||
{this.renderBack()}
|
||||
</KeyboardView>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,23 +1,64 @@
|
|||
import React from 'react';
|
||||
import { View, Text, Image, SafeAreaView } from 'react-native';
|
||||
import { View, Text, Image, SafeAreaView, TouchableOpacity } from 'react-native';
|
||||
import PropTypes from 'prop-types';
|
||||
import Icon from 'react-native-vector-icons/MaterialIcons';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { selectServerRequest, serverInitAdd, serverFinishAdd } from '../../actions/server';
|
||||
import I18n from '../../i18n';
|
||||
import openLink from '../../utils/openLink';
|
||||
import Button from './Button';
|
||||
import styles from './styles';
|
||||
import LoggedView from '../View';
|
||||
import DeviceInfo from '../../utils/deviceInfo';
|
||||
|
||||
@connect(state => ({
|
||||
currentServer: state.server.server,
|
||||
adding: state.server.adding
|
||||
}), dispatch => ({
|
||||
initAdd: () => dispatch(serverInitAdd()),
|
||||
finishAdd: () => dispatch(serverFinishAdd()),
|
||||
selectServer: server => dispatch(selectServerRequest(server))
|
||||
}))
|
||||
/** @extends React.Component */
|
||||
export default class OnboardingView extends LoggedView {
|
||||
static propTypes = {
|
||||
navigator: PropTypes.object
|
||||
navigator: PropTypes.object,
|
||||
previousServer: PropTypes.string,
|
||||
adding: PropTypes.bool,
|
||||
selectServer: PropTypes.func.isRequired,
|
||||
currentServer: PropTypes.string,
|
||||
initAdd: PropTypes.func,
|
||||
finishAdd: PropTypes.func
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super('CreateChannelView', props);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { previousServer, initAdd } = this.props;
|
||||
if (previousServer) {
|
||||
initAdd();
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
const {
|
||||
selectServer, previousServer, currentServer, adding, finishAdd
|
||||
} = this.props;
|
||||
if (adding) {
|
||||
if (previousServer !== currentServer) {
|
||||
selectServer(previousServer);
|
||||
}
|
||||
finishAdd();
|
||||
}
|
||||
}
|
||||
|
||||
close = () => {
|
||||
this.props.navigator.dismissModal();
|
||||
}
|
||||
|
||||
connectServer = () => {
|
||||
this.props.navigator.push({
|
||||
screen: 'NewServerView',
|
||||
|
@ -45,17 +86,39 @@ export default class OnboardingView extends LoggedView {
|
|||
openLink('https://cloud.rocket.chat/trial');
|
||||
}
|
||||
|
||||
renderClose = () => {
|
||||
if (this.props.previousServer) {
|
||||
let top = 15;
|
||||
if (DeviceInfo.getBrand() === 'Apple') {
|
||||
top = DeviceInfo.isNotch() ? 45 : 30;
|
||||
}
|
||||
return (
|
||||
<TouchableOpacity
|
||||
style={[styles.closeModal, { top }]}
|
||||
onPress={this.close}
|
||||
>
|
||||
<Icon
|
||||
name='close'
|
||||
size={30}
|
||||
color='#1D74F5'
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<SafeAreaView style={styles.container} testID='onboarding-view'>
|
||||
<Image style={styles.onboarding} source={require('../../static/images/onboarding.png')} />
|
||||
<Image style={styles.onboarding} source={{ uri: 'onboarding' }} />
|
||||
<Text style={styles.title}>{I18n.t('Welcome_to_RocketChat')}</Text>
|
||||
<Text style={styles.subtitle}>{I18n.t('Open_Source_Communication')}</Text>
|
||||
<View style={styles.buttonsContainer}>
|
||||
<Button
|
||||
type='secondary'
|
||||
title={I18n.t('Connect_to_a_server')}
|
||||
icon={<Image source={require('../../static/images/connectServer.png')} />}
|
||||
icon={<Image source={{ uri: 'connect_server' }} style={{ width: 30, height: 30 }} />}
|
||||
onPress={this.connectServer}
|
||||
testID='connect-server-button'
|
||||
/>
|
||||
|
@ -63,18 +126,19 @@ export default class OnboardingView extends LoggedView {
|
|||
type='secondary'
|
||||
title={I18n.t('Join_the_community')}
|
||||
subtitle='open.rocket.chat'
|
||||
icon={<Image source={require('../../static/images/logoSmall.png')} />}
|
||||
icon={<Image source={{ uri: 'logo_onboarding' }} style={{ width: 32, height: 27 }} />}
|
||||
onPress={this.joinCommunity}
|
||||
testID='join-community-button'
|
||||
/>
|
||||
<Button
|
||||
type='primary'
|
||||
title={I18n.t('Create_a_new_workspace')}
|
||||
icon={<Image source={require('../../static/images/plusWhite.png')} />}
|
||||
icon={<Image source={{ uri: 'plus_onboarding' }} style={{ width: 24, height: 24 }} />}
|
||||
onPress={this.createWorkspace}
|
||||
testID='create-workspace-button'
|
||||
/>
|
||||
</View>
|
||||
{this.renderClose()}
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -25,7 +25,9 @@ export default StyleSheet.create({
|
|||
marginTop: verticalScale(30),
|
||||
marginBottom: verticalScale(35),
|
||||
maxHeight: verticalScale(250),
|
||||
resizeMode: 'contain'
|
||||
resizeMode: 'contain',
|
||||
width: 309,
|
||||
height: 250
|
||||
},
|
||||
title: {
|
||||
alignSelf: 'center',
|
||||
|
@ -96,5 +98,9 @@ export default StyleSheet.create({
|
|||
},
|
||||
button_text_secondary: {
|
||||
color: colors.textColorSecondary
|
||||
},
|
||||
closeModal: {
|
||||
position: 'absolute',
|
||||
left: 15
|
||||
}
|
||||
});
|
||||
|
|
|
@ -2,6 +2,7 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import { FlatList, View, Vibration, SafeAreaView } from 'react-native';
|
||||
import ActionSheet from 'react-native-actionsheet';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import LoggedView from '../View';
|
||||
import styles from './styles';
|
||||
|
@ -14,6 +15,9 @@ import log from '../../utils/log';
|
|||
import I18n from '../../i18n';
|
||||
import SearchBox from '../../containers/SearchBox';
|
||||
|
||||
@connect(state => ({
|
||||
baseUrl: state.settings.Site_Url || state.server ? state.server.server : ''
|
||||
}))
|
||||
/** @extends React.Component */
|
||||
export default class RoomMembersView extends LoggedView {
|
||||
static navigatorButtons = {
|
||||
|
@ -27,7 +31,8 @@ export default class RoomMembersView extends LoggedView {
|
|||
static propTypes = {
|
||||
navigator: PropTypes.object,
|
||||
rid: PropTypes.string,
|
||||
members: PropTypes.array
|
||||
members: PropTypes.array,
|
||||
baseUrl: PropTypes.string
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
|
@ -134,11 +139,7 @@ export default class RoomMembersView extends LoggedView {
|
|||
screen: 'RoomView',
|
||||
title: name,
|
||||
backButtonTitle: '',
|
||||
passProps: {
|
||||
room: { rid, name },
|
||||
rid,
|
||||
name
|
||||
}
|
||||
passProps: { rid }
|
||||
});
|
||||
}, 1000);
|
||||
}
|
||||
|
@ -175,6 +176,7 @@ export default class RoomMembersView extends LoggedView {
|
|||
username={item.username}
|
||||
onPress={() => this.onPressUser(item)}
|
||||
onLongPress={() => this.onLongPressUser(item)}
|
||||
baseUrl={this.props.baseUrl}
|
||||
testID={`room-members-view-item-${ item.username }`}
|
||||
/>
|
||||
)
|
||||
|
|
|
@ -171,7 +171,7 @@ export class ListView extends OldList2 {
|
|||
onKeyboardDidHide: undefined
|
||||
});
|
||||
|
||||
const image = data.length === 0 ? require('../../static/images/message_empty.png') : null;
|
||||
const image = data.length === 0 ? { uri: 'message_empty' } : null;
|
||||
return (
|
||||
[
|
||||
<ImageBackground key='listview-background' source={image} style={styles.imageBackground} />,
|
||||
|
|
|
@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
|
|||
import { Text, View, LayoutAnimation, ActivityIndicator, SafeAreaView } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
import equal from 'deep-equal';
|
||||
import { RectButton } from 'react-native-gesture-handler';
|
||||
|
||||
import LoggedView from '../View';
|
||||
import { List } from './ListView';
|
||||
|
@ -60,11 +61,11 @@ export default class RoomView extends LoggedView {
|
|||
|
||||
constructor(props) {
|
||||
super('RoomView', props);
|
||||
this.rid = props.rid;
|
||||
this.rid = this.props.rid;
|
||||
this.rooms = database.objects('subscriptions').filtered('rid = $0', this.rid);
|
||||
this.state = {
|
||||
loaded: false,
|
||||
joined: typeof props.rid === 'undefined',
|
||||
joined: this.rooms.length > 0,
|
||||
room: {},
|
||||
end: false
|
||||
};
|
||||
|
@ -95,6 +96,7 @@ export default class RoomView extends LoggedView {
|
|||
});
|
||||
this.setState({ loaded: true });
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return !(equal(this.props, nextProps) && equal(this.state, nextState) && this.state.room.ro === nextState.room.ro);
|
||||
}
|
||||
|
@ -191,6 +193,9 @@ export default class RoomView extends LoggedView {
|
|||
this.props.setLastOpen(null);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.props.openRoom({ rid: this.rid });
|
||||
this.setState({ joined: false });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,9 +209,7 @@ export default class RoomView extends LoggedView {
|
|||
joinRoom = async() => {
|
||||
try {
|
||||
await RocketChat.joinRoom(this.props.rid);
|
||||
this.setState({
|
||||
joined: true
|
||||
});
|
||||
this.setState({ joined: true });
|
||||
} catch (e) {
|
||||
log('joinRoom', e);
|
||||
}
|
||||
|
@ -245,15 +248,21 @@ export default class RoomView extends LoggedView {
|
|||
);
|
||||
|
||||
renderFooter = () => {
|
||||
// TODO: fix it
|
||||
// if (!this.state.joined) {
|
||||
// return (
|
||||
// <View>
|
||||
// <Text>{I18n.t('You_are_in_preview_mode')}</Text>
|
||||
// <Button title='Join' onPress={this.joinRoom} />
|
||||
// </View>
|
||||
// );
|
||||
// }
|
||||
if (!this.state.joined) {
|
||||
return (
|
||||
<View style={styles.joinRoomContainer} key='room-view-join'>
|
||||
<Text style={styles.previewMode}>{I18n.t('You_are_in_preview_mode')}</Text>
|
||||
<RectButton
|
||||
onPress={this.joinRoom}
|
||||
style={styles.joinRoomButton}
|
||||
activeOpacity={0.5}
|
||||
underlayColor='#fff'
|
||||
>
|
||||
<Text style={styles.joinRoomText}>{I18n.t('Join')}</Text>
|
||||
</RectButton>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
if (this.state.room.archived || this.isReadOnly()) {
|
||||
return (
|
||||
<View style={styles.readOnly}>
|
||||
|
|
|
@ -53,5 +53,30 @@ export default StyleSheet.create({
|
|||
width: '100%',
|
||||
height: '100%',
|
||||
position: 'absolute'
|
||||
},
|
||||
joinRoomContainer: {
|
||||
justifyContent: 'flex-end',
|
||||
alignItems: 'center',
|
||||
marginVertical: 15
|
||||
},
|
||||
joinRoomButton: {
|
||||
width: 107,
|
||||
height: 44,
|
||||
marginTop: 15,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
backgroundColor: '#1d74f5',
|
||||
borderRadius: 4
|
||||
},
|
||||
joinRoomText: {
|
||||
color: '#fff',
|
||||
fontSize: 14,
|
||||
fontWeight: '500'
|
||||
},
|
||||
previewMode: {
|
||||
fontSize: 16,
|
||||
fontWeight: '500',
|
||||
color: '#0C0D0F'
|
||||
}
|
||||
});
|
||||
|
|
|
@ -23,12 +23,13 @@ const styles = StyleSheet.create({
|
|||
},
|
||||
disclosure: {
|
||||
marginLeft: 3,
|
||||
marginTop: 2,
|
||||
marginTop: 1,
|
||||
width: 12,
|
||||
height: 9
|
||||
},
|
||||
upsideDown: {
|
||||
transform: [{ scaleY: -1 }]
|
||||
transform: [{ scaleY: -1 }],
|
||||
marginTop: 4
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -82,17 +82,13 @@ export default class ServerDropdown extends Component {
|
|||
this.close();
|
||||
setTimeout(() => {
|
||||
this.props.navigator.showModal({
|
||||
screen: 'NewServerView',
|
||||
title: I18n.t('Add_Server'),
|
||||
screen: 'OnboardingView',
|
||||
passProps: {
|
||||
previousServer: this.props.server
|
||||
},
|
||||
navigatorButtons: {
|
||||
leftButtons: [{
|
||||
id: 'cancel',
|
||||
testID: 'new-server-close',
|
||||
title: I18n.t('Close')
|
||||
}]
|
||||
navigatorStyle: {
|
||||
navBarHidden: true,
|
||||
orientation: 'portrait'
|
||||
}
|
||||
});
|
||||
}, ANIMATION_DURATION);
|
||||
|
|
|
@ -327,11 +327,7 @@ export default class RoomsListView extends LoggedView {
|
|||
screen: 'RoomView',
|
||||
title: name,
|
||||
backButtonTitle: '',
|
||||
passProps: {
|
||||
room: { rid, name },
|
||||
rid,
|
||||
name
|
||||
}
|
||||
passProps: { rid }
|
||||
});
|
||||
this.cancelSearchingAndroid();
|
||||
}
|
||||
|
|
|
@ -118,7 +118,8 @@ export default StyleSheet.create({
|
|||
color: isIOS() ? '#1D74F5' : '#FFF',
|
||||
fontSize: 15,
|
||||
fontWeight: 'normal',
|
||||
marginRight: 15
|
||||
marginRight: 15,
|
||||
paddingVertical: 10
|
||||
},
|
||||
serverItem: {
|
||||
height: 68
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { Navigation } from 'react-native-navigation';
|
||||
import { Provider } from 'react-redux';
|
||||
import { gestureHandlerRootHOC } from 'react-native-gesture-handler';
|
||||
|
||||
import CreateChannelView from './CreateChannelView';
|
||||
import ForgotPasswordView from './ForgotPasswordView';
|
||||
|
@ -36,29 +37,29 @@ export const registerScreens = (store) => {
|
|||
Navigation.registerComponent('ForgotPasswordView', () => ForgotPasswordView, store, Provider);
|
||||
Navigation.registerComponent('LoginSignupView', () => LoginSignupView, store, Provider);
|
||||
Navigation.registerComponent('LoginView', () => LoginView, store, Provider);
|
||||
Navigation.registerComponent('MentionedMessagesView', () => MentionedMessagesView, store, Provider);
|
||||
Navigation.registerComponent('MentionedMessagesView', () => gestureHandlerRootHOC(MentionedMessagesView), store, Provider);
|
||||
Navigation.registerComponent('NewMessageView', () => NewMessageView, store, Provider);
|
||||
Navigation.registerComponent('NewServerView', () => NewServerView, store, Provider);
|
||||
Navigation.registerComponent('OAuthView', () => OAuthView, store, Provider);
|
||||
Navigation.registerComponent('OnboardingView', () => OnboardingView, store, Provider);
|
||||
Navigation.registerComponent('PinnedMessagesView', () => PinnedMessagesView, store, Provider);
|
||||
Navigation.registerComponent('PinnedMessagesView', () => gestureHandlerRootHOC(PinnedMessagesView), store, Provider);
|
||||
Navigation.registerComponent('PrivacyPolicyView', () => PrivacyPolicyView, store, Provider);
|
||||
Navigation.registerComponent('ProfileView', () => ProfileView, store, Provider);
|
||||
Navigation.registerComponent('RegisterView', () => RegisterView, store, Provider);
|
||||
Navigation.registerComponent('RoomActionsView', () => RoomActionsView, store, Provider);
|
||||
Navigation.registerComponent('RoomFilesView', () => RoomFilesView, store, Provider);
|
||||
Navigation.registerComponent('RoomFilesView', () => gestureHandlerRootHOC(RoomFilesView), store, Provider);
|
||||
Navigation.registerComponent('RoomInfoEditView', () => RoomInfoEditView, store, Provider);
|
||||
Navigation.registerComponent('RoomInfoView', () => RoomInfoView, store, Provider);
|
||||
Navigation.registerComponent('RoomMembersView', () => RoomMembersView, store, Provider);
|
||||
Navigation.registerComponent('RoomsListHeaderView', () => RoomsListHeaderView, store, Provider);
|
||||
Navigation.registerComponent('RoomsListSearchView', () => RoomsListSearchView, store, Provider);
|
||||
Navigation.registerComponent('RoomsListView', () => RoomsListView, store, Provider);
|
||||
Navigation.registerComponent('RoomView', () => RoomView, store, Provider);
|
||||
Navigation.registerComponent('SearchMessagesView', () => SearchMessagesView, store, Provider);
|
||||
Navigation.registerComponent('RoomsListView', () => gestureHandlerRootHOC(RoomsListView), store, Provider);
|
||||
Navigation.registerComponent('RoomView', () => gestureHandlerRootHOC(RoomView), store, Provider);
|
||||
Navigation.registerComponent('SearchMessagesView', () => gestureHandlerRootHOC(SearchMessagesView), store, Provider);
|
||||
Navigation.registerComponent('SelectedUsersView', () => SelectedUsersView, store, Provider);
|
||||
Navigation.registerComponent('SettingsView', () => SettingsView, store, Provider);
|
||||
Navigation.registerComponent('Sidebar', () => Sidebar, store, Provider);
|
||||
Navigation.registerComponent('SnippetedMessagesView', () => SnippetedMessagesView, store, Provider);
|
||||
Navigation.registerComponent('StarredMessagesView', () => StarredMessagesView, store, Provider);
|
||||
Navigation.registerComponent('SnippetedMessagesView', () => gestureHandlerRootHOC(SnippetedMessagesView), store, Provider);
|
||||
Navigation.registerComponent('StarredMessagesView', () => gestureHandlerRootHOC(StarredMessagesView), store, Provider);
|
||||
Navigation.registerComponent('TermsServiceView', () => TermsServiceView, store, Provider);
|
||||
};
|
||||
|
|
|
@ -24,6 +24,8 @@ target 'RocketChatRN' do
|
|||
]
|
||||
|
||||
pod 'RNImageCropPicker', :path => '../node_modules/react-native-image-crop-picker'
|
||||
pod 'RNDeviceInfo', :path => '../node_modules/react-native-device-info'
|
||||
|
||||
end
|
||||
|
||||
post_install do |installer|
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
PODS:
|
||||
- QBImagePickerController (3.4.0)
|
||||
- React (0.56.0):
|
||||
- React/Core (= 0.56.0)
|
||||
- React/Core (0.56.0):
|
||||
- yoga (= 0.56.0.React)
|
||||
- React/fishhook (0.56.0)
|
||||
|
@ -28,11 +30,13 @@ PODS:
|
|||
- React/Core
|
||||
- React/fishhook
|
||||
- React/RCTBlob
|
||||
- RNImageCropPicker (0.20.3):
|
||||
- RNDeviceInfo (0.21.5):
|
||||
- React
|
||||
- RNImageCropPicker (0.21.1):
|
||||
- QBImagePickerController
|
||||
- React/Core
|
||||
- RSKImageCropper
|
||||
- RSKImageCropper (2.0.0)
|
||||
- RSKImageCropper (2.1.0)
|
||||
- yoga (0.56.0.React)
|
||||
|
||||
DEPENDENCIES:
|
||||
|
@ -47,12 +51,15 @@ DEPENDENCIES:
|
|||
- React/RCTText (from `../node_modules/react-native`)
|
||||
- React/RCTVibration (from `../node_modules/react-native`)
|
||||
- React/RCTWebSocket (from `../node_modules/react-native`)
|
||||
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
|
||||
- RNImageCropPicker (from `../node_modules/react-native-image-crop-picker`)
|
||||
- yoga (from `../node_modules/react-native/ReactCommon/yoga/yoga.podspec`)
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
React:
|
||||
:path: ../node_modules/react-native
|
||||
RNDeviceInfo:
|
||||
:path: ../node_modules/react-native-device-info
|
||||
RNImageCropPicker:
|
||||
:path: ../node_modules/react-native-image-crop-picker
|
||||
yoga:
|
||||
|
@ -61,10 +68,11 @@ EXTERNAL SOURCES:
|
|||
SPEC CHECKSUMS:
|
||||
QBImagePickerController: d54cf93db6decf26baf6ed3472f336ef35cae022
|
||||
React: 1fe0eb13d90b625d94c3b117c274dcfd2e760e11
|
||||
RNDeviceInfo: 568c5641057313b4912d08a7742ff0b2f753ed5c
|
||||
RNImageCropPicker: 32ca4b9fef4e1b7b85ba69494242122948117e06
|
||||
RSKImageCropper: d9a1acbc0600bf8decc8f0d21895872c99a9e4cf
|
||||
RSKImageCropper: 0d0c6d8525a2381f03fde32a47c6703817a2feed
|
||||
yoga: b1ce48b6cf950b98deae82838f5173ea7cf89e85
|
||||
|
||||
PODFILE CHECKSUM: 61f93deba99bd7e36384c5bceba5b92c6b96009e
|
||||
PODFILE CHECKSUM: da5e520837501713de2c32adbff219ab7fc5c0fa
|
||||
|
||||
COCOAPODS: 1.4.0
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
../../../../../node_modules/react-native-device-info/ios/RNDeviceInfo/DeviceUID.h
|
|
@ -0,0 +1 @@
|
|||
../../../../../node_modules/react-native-device-info/ios/RNDeviceInfo/RNDeviceInfo.h
|
|
@ -0,0 +1 @@
|
|||
../../../../../node_modules/react-native-device-info/ios/RNDeviceInfo/DeviceUID.h
|
|
@ -0,0 +1 @@
|
|||
../../../../../node_modules/react-native-device-info/ios/RNDeviceInfo/RNDeviceInfo.h
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"name": "RNDeviceInfo",
|
||||
"version": "0.21.5",
|
||||
"summary": "Device Information for react-native",
|
||||
"homepage": "https://github.com/rebeccahughes/react-native-device-info",
|
||||
"license": "MIT",
|
||||
"authors": {
|
||||
"Rebecca Hughes": "rebecca@learnium.net"
|
||||
},
|
||||
"platforms": {
|
||||
"ios": "8.0",
|
||||
"tvos": "10.0"
|
||||
},
|
||||
"source": {
|
||||
"git": "https://github.com/rebeccahughes/react-native-device-info.git"
|
||||
},
|
||||
"source_files": "ios/RNDeviceInfo/*.{h,m}",
|
||||
"dependencies": {
|
||||
"React": [
|
||||
|
||||
]
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "RNImageCropPicker",
|
||||
"version": "0.20.3",
|
||||
"version": "0.21.1",
|
||||
"summary": "Select single or multiple images, with cropping option",
|
||||
"requires_arc": true,
|
||||
"license": "MIT",
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
PODS:
|
||||
- QBImagePickerController (3.4.0)
|
||||
- React (0.56.0):
|
||||
- React/Core (= 0.56.0)
|
||||
- React/Core (0.56.0):
|
||||
- yoga (= 0.56.0.React)
|
||||
- React/fishhook (0.56.0)
|
||||
|
@ -28,11 +30,13 @@ PODS:
|
|||
- React/Core
|
||||
- React/fishhook
|
||||
- React/RCTBlob
|
||||
- RNImageCropPicker (0.20.3):
|
||||
- RNDeviceInfo (0.21.5):
|
||||
- React
|
||||
- RNImageCropPicker (0.21.1):
|
||||
- QBImagePickerController
|
||||
- React/Core
|
||||
- RSKImageCropper
|
||||
- RSKImageCropper (2.0.0)
|
||||
- RSKImageCropper (2.1.0)
|
||||
- yoga (0.56.0.React)
|
||||
|
||||
DEPENDENCIES:
|
||||
|
@ -47,12 +51,15 @@ DEPENDENCIES:
|
|||
- React/RCTText (from `../node_modules/react-native`)
|
||||
- React/RCTVibration (from `../node_modules/react-native`)
|
||||
- React/RCTWebSocket (from `../node_modules/react-native`)
|
||||
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
|
||||
- RNImageCropPicker (from `../node_modules/react-native-image-crop-picker`)
|
||||
- yoga (from `../node_modules/react-native/ReactCommon/yoga/yoga.podspec`)
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
React:
|
||||
:path: ../node_modules/react-native
|
||||
RNDeviceInfo:
|
||||
:path: ../node_modules/react-native-device-info
|
||||
RNImageCropPicker:
|
||||
:path: ../node_modules/react-native-image-crop-picker
|
||||
yoga:
|
||||
|
@ -61,10 +68,11 @@ EXTERNAL SOURCES:
|
|||
SPEC CHECKSUMS:
|
||||
QBImagePickerController: d54cf93db6decf26baf6ed3472f336ef35cae022
|
||||
React: 1fe0eb13d90b625d94c3b117c274dcfd2e760e11
|
||||
RNDeviceInfo: 568c5641057313b4912d08a7742ff0b2f753ed5c
|
||||
RNImageCropPicker: 32ca4b9fef4e1b7b85ba69494242122948117e06
|
||||
RSKImageCropper: d9a1acbc0600bf8decc8f0d21895872c99a9e4cf
|
||||
RSKImageCropper: 0d0c6d8525a2381f03fde32a47c6703817a2feed
|
||||
yoga: b1ce48b6cf950b98deae82838f5173ea7cf89e85
|
||||
|
||||
PODFILE CHECKSUM: 61f93deba99bd7e36384c5bceba5b92c6b96009e
|
||||
PODFILE CHECKSUM: da5e520837501713de2c32adbff219ab7fc5c0fa
|
||||
|
||||
COCOAPODS: 1.4.0
|
||||
|
|
|
@ -99,16 +99,27 @@ Then implement the data source functions.
|
|||
// Returns a custom rect for the mask.
|
||||
- (CGRect)imageCropViewControllerCustomMaskRect:(RSKImageCropViewController *)controller
|
||||
{
|
||||
CGSize maskSize;
|
||||
if ([controller isPortraitInterfaceOrientation]) {
|
||||
maskSize = CGSizeMake(250, 250);
|
||||
} else {
|
||||
maskSize = CGSizeMake(220, 220);
|
||||
}
|
||||
CGSize aspectRatio = CGSizeMake(16.0f, 9.0f);
|
||||
|
||||
CGFloat viewWidth = CGRectGetWidth(controller.view.frame);
|
||||
CGFloat viewHeight = CGRectGetHeight(controller.view.frame);
|
||||
|
||||
CGFloat maskWidth;
|
||||
if ([controller isPortraitInterfaceOrientation]) {
|
||||
maskWidth = viewWidth;
|
||||
} else {
|
||||
maskWidth = viewHeight;
|
||||
}
|
||||
|
||||
CGFloat maskHeight;
|
||||
do {
|
||||
maskHeight = maskWidth * aspectRatio.height / aspectRatio.width;
|
||||
maskWidth -= 1.0f;
|
||||
} while (maskHeight != floor(maskHeight));
|
||||
maskWidth += 1.0f;
|
||||
|
||||
CGSize maskSize = CGSizeMake(maskWidth, maskHeight);
|
||||
|
||||
CGRect maskRect = CGRectMake((viewWidth - maskSize.width) * 0.5f,
|
||||
(viewHeight - maskSize.height) * 0.5f,
|
||||
maskSize.width,
|
||||
|
@ -123,23 +134,42 @@ Then implement the data source functions.
|
|||
CGRect rect = controller.maskRect;
|
||||
CGPoint point1 = CGPointMake(CGRectGetMinX(rect), CGRectGetMaxY(rect));
|
||||
CGPoint point2 = CGPointMake(CGRectGetMaxX(rect), CGRectGetMaxY(rect));
|
||||
CGPoint point3 = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
|
||||
CGPoint point3 = CGPointMake(CGRectGetMaxX(rect), CGRectGetMinY(rect));
|
||||
CGPoint point4 = CGPointMake(CGRectGetMinX(rect), CGRectGetMinY(rect));
|
||||
|
||||
UIBezierPath *triangle = [UIBezierPath bezierPath];
|
||||
[triangle moveToPoint:point1];
|
||||
[triangle addLineToPoint:point2];
|
||||
[triangle addLineToPoint:point3];
|
||||
[triangle closePath];
|
||||
UIBezierPath *rectangle = [UIBezierPath bezierPath];
|
||||
[rectangle moveToPoint:point1];
|
||||
[rectangle addLineToPoint:point2];
|
||||
[rectangle addLineToPoint:point3];
|
||||
[rectangle addLineToPoint:point4];
|
||||
[rectangle closePath];
|
||||
|
||||
return triangle;
|
||||
return rectangle;
|
||||
}
|
||||
|
||||
// Returns a custom rect in which the image can be moved.
|
||||
- (CGRect)imageCropViewControllerCustomMovementRect:(RSKImageCropViewController *)controller
|
||||
{
|
||||
// If the image is not rotated, then the movement rect coincides with the mask rect,
|
||||
// otherwise it is calculated individually for each custom mask.
|
||||
return controller.maskRect;
|
||||
if (controller.rotationAngle == 0) {
|
||||
return controller.maskRect;
|
||||
} else {
|
||||
CGRect maskRect = controller.maskRect;
|
||||
CGFloat rotationAngle = controller.rotationAngle;
|
||||
|
||||
CGRect movementRect = CGRectZero;
|
||||
|
||||
movementRect.size.width = CGRectGetWidth(maskRect) * fabs(cos(rotationAngle)) + CGRectGetHeight(maskRect) * fabs(sin(rotationAngle));
|
||||
movementRect.size.height = CGRectGetHeight(maskRect) * fabs(cos(rotationAngle)) + CGRectGetWidth(maskRect) * fabs(sin(rotationAngle));
|
||||
|
||||
movementRect.origin.x = CGRectGetMinX(maskRect) + (CGRectGetWidth(maskRect) - CGRectGetWidth(movementRect)) * 0.5f;
|
||||
movementRect.origin.y = CGRectGetMinY(maskRect) + (CGRectGetHeight(maskRect) - CGRectGetHeight(movementRect)) * 0.5f;
|
||||
|
||||
movementRect.origin.x = floor(CGRectGetMinX(movementRect));
|
||||
movementRect.origin.y = floor(CGRectGetMinY(movementRect));
|
||||
movementRect = CGRectIntegral(movementRect);
|
||||
|
||||
return movementRect;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -81,6 +81,9 @@ CG_EXTERN const CGPoint RSKPointNull;
|
|||
// Returns the exact center point of the given rectangle.
|
||||
CGPoint RSKRectCenterPoint(CGRect rect);
|
||||
|
||||
// Returns the `rect` with normalized values.
|
||||
CGRect RSKRectNormalize(CGRect rect);
|
||||
|
||||
// Returns the `rect` scaled around the `point` by `sx` and `sy`.
|
||||
CGRect RSKRectScaleAroundPoint(CGRect rect, CGPoint point, CGFloat sx, CGFloat sy);
|
||||
|
||||
|
|
|
@ -24,6 +24,13 @@
|
|||
|
||||
#import "CGGeometry+RSKImageCropper.h"
|
||||
|
||||
// K is a constant such that the accumulated error of our floating-point computations is definitely bounded by K units in the last place.
|
||||
#ifdef CGFLOAT_IS_DOUBLE
|
||||
static const CGFloat kK = 9;
|
||||
#else
|
||||
static const CGFloat kK = 0;
|
||||
#endif
|
||||
|
||||
const CGPoint RSKPointNull = { INFINITY, INFINITY };
|
||||
|
||||
CGPoint RSKRectCenterPoint(CGRect rect)
|
||||
|
@ -32,6 +39,45 @@ CGPoint RSKRectCenterPoint(CGRect rect)
|
|||
CGRectGetMinY(rect) + CGRectGetHeight(rect) / 2);
|
||||
}
|
||||
|
||||
CGRect RSKRectNormalize(CGRect rect)
|
||||
{
|
||||
CGPoint origin = rect.origin;
|
||||
|
||||
CGFloat x = origin.x;
|
||||
CGFloat y = origin.y;
|
||||
CGFloat ceilX = ceil(x);
|
||||
CGFloat ceilY = ceil(y);
|
||||
|
||||
if (fabs(ceilX - x) < pow(10, kK) * RSK_EPSILON * fabs(ceilX + x) || fabs(ceilX - x) < RSK_MIN ||
|
||||
fabs(ceilY - y) < pow(10, kK) * RSK_EPSILON * fabs(ceilY + y) || fabs(ceilY - y) < RSK_MIN) {
|
||||
|
||||
origin.x = ceilX;
|
||||
origin.y = ceilY;
|
||||
} else {
|
||||
origin.x = floor(x);
|
||||
origin.y = floor(y);
|
||||
}
|
||||
|
||||
CGSize size = rect.size;
|
||||
|
||||
CGFloat width = size.width;
|
||||
CGFloat height = size.height;
|
||||
CGFloat ceilWidth = ceil(width);
|
||||
CGFloat ceilHeight = ceil(height);
|
||||
|
||||
if (fabs(ceilWidth - width) < pow(10, kK) * RSK_EPSILON * fabs(ceilWidth + width) || fabs(ceilWidth - width) < RSK_MIN ||
|
||||
fabs(ceilHeight - height) < pow(10, kK) * RSK_EPSILON * fabs(ceilHeight + height) || fabs(ceilHeight - height) < RSK_MIN) {
|
||||
|
||||
size.width = ceilWidth;
|
||||
size.height = ceilHeight;
|
||||
} else {
|
||||
size.width = floor(width);
|
||||
size.height = floor(height);
|
||||
}
|
||||
|
||||
return CGRectMake(origin.x, origin.y, size.width, size.height);
|
||||
}
|
||||
|
||||
CGRect RSKRectScaleAroundPoint(CGRect rect, CGPoint point, CGFloat sx, CGFloat sy)
|
||||
{
|
||||
CGAffineTransform translationTransform, scaleTransform;
|
||||
|
|
|
@ -55,6 +55,14 @@ typedef NS_ENUM(NSUInteger, RSKImageCropMode) {
|
|||
*/
|
||||
- (instancetype)initWithImage:(UIImage *)originalImage cropMode:(RSKImageCropMode)cropMode;
|
||||
|
||||
/**
|
||||
Zooms to a specific area of the image so that it is visible.
|
||||
|
||||
@param rect A rectangle defining an area of the image.
|
||||
@param animated YES if the scrolling should be animated, NO if it should be immediate.
|
||||
*/
|
||||
- (void)zoomToRect:(CGRect)rect animated:(BOOL)animated;
|
||||
|
||||
///-----------------------------
|
||||
/// @name Accessing the Delegate
|
||||
///-----------------------------
|
||||
|
@ -329,6 +337,11 @@ typedef NS_ENUM(NSUInteger, RSKImageCropMode) {
|
|||
|
||||
@optional
|
||||
|
||||
/**
|
||||
Tells the delegate that the image has been displayed.
|
||||
*/
|
||||
- (void)imageCropViewControllerDidDisplayImage:(RSKImageCropViewController *)controller;
|
||||
|
||||
/**
|
||||
Tells the delegate that the original image will be cropped.
|
||||
*/
|
||||
|
|
|
@ -33,13 +33,6 @@
|
|||
static const CGFloat kResetAnimationDuration = 0.4;
|
||||
static const CGFloat kLayoutImageScrollViewAnimationDuration = 0.25;
|
||||
|
||||
// K is a constant such that the accumulated error of our floating-point computations is definitely bounded by K units in the last place.
|
||||
#ifdef CGFLOAT_IS_DOUBLE
|
||||
static const CGFloat kK = 9;
|
||||
#else
|
||||
static const CGFloat kK = 0;
|
||||
#endif
|
||||
|
||||
@interface RSKImageCropViewController () <UIGestureRecognizerDelegate>
|
||||
|
||||
@property (assign, nonatomic) BOOL originalNavigationControllerNavigationBarHidden;
|
||||
|
@ -57,6 +50,8 @@ static const CGFloat kLayoutImageScrollViewAnimationDuration = 0.25;
|
|||
@property (readonly, nonatomic) CGRect rectForMaskPath;
|
||||
@property (readonly, nonatomic) CGRect rectForClipPath;
|
||||
|
||||
@property (readonly, nonatomic) CGRect imageRect;
|
||||
|
||||
@property (strong, nonatomic) UILabel *moveAndScaleLabel;
|
||||
@property (strong, nonatomic) UIButton *cancelButton;
|
||||
@property (strong, nonatomic) UIButton *chooseButton;
|
||||
|
@ -136,7 +131,16 @@ static const CGFloat kLayoutImageScrollViewAnimationDuration = 0.25;
|
|||
[super viewDidLoad];
|
||||
|
||||
if ([self respondsToSelector:@selector(edgesForExtendedLayout)]) {
|
||||
|
||||
self.edgesForExtendedLayout = UIRectEdgeNone;
|
||||
}
|
||||
|
||||
if (@available(iOS 11.0, *)) {
|
||||
|
||||
self.imageScrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
|
||||
}
|
||||
else if ([self respondsToSelector:@selector(automaticallyAdjustsScrollViewInsets)] == YES) {
|
||||
|
||||
self.automaticallyAdjustsScrollViewInsets = NO;
|
||||
}
|
||||
|
||||
|
@ -157,10 +161,14 @@ static const CGFloat kLayoutImageScrollViewAnimationDuration = 0.25;
|
|||
{
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
UIApplication *application = [UIApplication rsk_sharedApplication];
|
||||
if (application) {
|
||||
self.originalStatusBarHidden = application.statusBarHidden;
|
||||
[application setStatusBarHidden:YES];
|
||||
if ([self respondsToSelector:@selector(prefersStatusBarHidden)] == NO) {
|
||||
|
||||
UIApplication *application = [UIApplication rsk_sharedApplication];
|
||||
if (application) {
|
||||
|
||||
self.originalStatusBarHidden = application.statusBarHidden;
|
||||
[application setStatusBarHidden:YES];
|
||||
}
|
||||
}
|
||||
|
||||
self.originalNavigationControllerNavigationBarHidden = self.navigationController.navigationBarHidden;
|
||||
|
@ -182,9 +190,13 @@ static const CGFloat kLayoutImageScrollViewAnimationDuration = 0.25;
|
|||
{
|
||||
[super viewWillDisappear:animated];
|
||||
|
||||
UIApplication *application = [UIApplication rsk_sharedApplication];
|
||||
if (application) {
|
||||
[application setStatusBarHidden:self.originalStatusBarHidden];
|
||||
if ([self respondsToSelector:@selector(prefersStatusBarHidden)] == NO) {
|
||||
|
||||
UIApplication *application = [UIApplication rsk_sharedApplication];
|
||||
if (application) {
|
||||
|
||||
[application setStatusBarHidden:self.originalStatusBarHidden];
|
||||
}
|
||||
}
|
||||
|
||||
[self.navigationController setNavigationBarHidden:self.originalNavigationControllerNavigationBarHidden animated:animated];
|
||||
|
@ -385,31 +397,96 @@ static const CGFloat kLayoutImageScrollViewAnimationDuration = 0.25;
|
|||
return _rotationGestureRecognizer;
|
||||
}
|
||||
|
||||
- (CGRect)cropRect
|
||||
- (CGRect)imageRect
|
||||
{
|
||||
CGRect cropRect = CGRectZero;
|
||||
float zoomScale = 1.0 / self.imageScrollView.zoomScale;
|
||||
|
||||
cropRect.origin.x = floor(self.imageScrollView.contentOffset.x * zoomScale);
|
||||
cropRect.origin.y = floor(self.imageScrollView.contentOffset.y * zoomScale);
|
||||
cropRect.size.width = CGRectGetWidth(self.imageScrollView.bounds) * zoomScale;
|
||||
cropRect.size.height = CGRectGetHeight(self.imageScrollView.bounds) * zoomScale;
|
||||
CGRect imageRect = CGRectZero;
|
||||
|
||||
CGFloat width = CGRectGetWidth(cropRect);
|
||||
CGFloat height = CGRectGetHeight(cropRect);
|
||||
CGFloat ceilWidth = ceil(width);
|
||||
CGFloat ceilHeight = ceil(height);
|
||||
imageRect.origin.x = self.imageScrollView.contentOffset.x * zoomScale;
|
||||
imageRect.origin.y = self.imageScrollView.contentOffset.y * zoomScale;
|
||||
imageRect.size.width = CGRectGetWidth(self.imageScrollView.bounds) * zoomScale;
|
||||
imageRect.size.height = CGRectGetHeight(self.imageScrollView.bounds) * zoomScale;
|
||||
|
||||
if (fabs(ceilWidth - width) < pow(10, kK) * RSK_EPSILON * fabs(ceilWidth + width) || fabs(ceilWidth - width) < RSK_MIN ||
|
||||
fabs(ceilHeight - height) < pow(10, kK) * RSK_EPSILON * fabs(ceilHeight + height) || fabs(ceilHeight - height) < RSK_MIN) {
|
||||
|
||||
cropRect.size.width = ceilWidth;
|
||||
cropRect.size.height = ceilHeight;
|
||||
} else {
|
||||
cropRect.size.width = floor(width);
|
||||
cropRect.size.height = floor(height);
|
||||
imageRect = RSKRectNormalize(imageRect);
|
||||
|
||||
CGSize imageSize = self.originalImage.size;
|
||||
CGFloat x = CGRectGetMinX(imageRect);
|
||||
CGFloat y = CGRectGetMinY(imageRect);
|
||||
CGFloat width = CGRectGetWidth(imageRect);
|
||||
CGFloat height = CGRectGetHeight(imageRect);
|
||||
|
||||
UIImageOrientation imageOrientation = self.originalImage.imageOrientation;
|
||||
if (imageOrientation == UIImageOrientationRight || imageOrientation == UIImageOrientationRightMirrored) {
|
||||
imageRect.origin.x = y;
|
||||
imageRect.origin.y = floor(imageSize.width - CGRectGetWidth(imageRect) - x);
|
||||
imageRect.size.width = height;
|
||||
imageRect.size.height = width;
|
||||
} else if (imageOrientation == UIImageOrientationLeft || imageOrientation == UIImageOrientationLeftMirrored) {
|
||||
imageRect.origin.x = floor(imageSize.height - CGRectGetHeight(imageRect) - y);
|
||||
imageRect.origin.y = x;
|
||||
imageRect.size.width = height;
|
||||
imageRect.size.height = width;
|
||||
} else if (imageOrientation == UIImageOrientationDown || imageOrientation == UIImageOrientationDownMirrored) {
|
||||
imageRect.origin.x = floor(imageSize.width - CGRectGetWidth(imageRect) - x);
|
||||
imageRect.origin.y = floor(imageSize.height - CGRectGetHeight(imageRect) - y);
|
||||
}
|
||||
|
||||
CGFloat imageScale = self.originalImage.scale;
|
||||
imageRect = CGRectApplyAffineTransform(imageRect, CGAffineTransformMakeScale(imageScale, imageScale));
|
||||
|
||||
return imageRect;
|
||||
}
|
||||
|
||||
- (CGRect)cropRect
|
||||
{
|
||||
CGRect maskRect = self.maskRect;
|
||||
CGFloat rotationAngle = self.rotationAngle;
|
||||
CGRect rotatedImageScrollViewFrame = self.imageScrollView.frame;
|
||||
float zoomScale = 1.0 / self.imageScrollView.zoomScale;
|
||||
|
||||
CGAffineTransform imageScrollViewTransform = self.imageScrollView.transform;
|
||||
self.imageScrollView.transform = CGAffineTransformIdentity;
|
||||
|
||||
CGRect imageScrollViewFrame = self.imageScrollView.frame;
|
||||
self.imageScrollView.frame = self.maskRect;
|
||||
|
||||
CGRect imageFrame = CGRectZero;
|
||||
imageFrame.origin.x = CGRectGetMinX(maskRect) - self.imageScrollView.contentOffset.x;
|
||||
imageFrame.origin.y = CGRectGetMinY(maskRect) - self.imageScrollView.contentOffset.y;
|
||||
imageFrame.size = self.imageScrollView.contentSize;
|
||||
|
||||
CGFloat tx = CGRectGetMinX(imageFrame) + self.imageScrollView.contentOffset.x + CGRectGetWidth(maskRect) * 0.5f;
|
||||
CGFloat ty = CGRectGetMinY(imageFrame) + self.imageScrollView.contentOffset.y + CGRectGetHeight(maskRect) * 0.5f;
|
||||
|
||||
CGFloat sx = CGRectGetWidth(rotatedImageScrollViewFrame) / CGRectGetWidth(imageScrollViewFrame);
|
||||
CGFloat sy = CGRectGetHeight(rotatedImageScrollViewFrame) / CGRectGetHeight(imageScrollViewFrame);
|
||||
|
||||
CGAffineTransform t1 = CGAffineTransformMakeTranslation(-tx, -ty);
|
||||
CGAffineTransform t2 = CGAffineTransformMakeRotation(rotationAngle);
|
||||
CGAffineTransform t3 = CGAffineTransformMakeScale(sx, sy);
|
||||
CGAffineTransform t4 = CGAffineTransformMakeTranslation(tx, ty);
|
||||
CGAffineTransform t1t2 = CGAffineTransformConcat(t1, t2);
|
||||
CGAffineTransform t1t2t3 = CGAffineTransformConcat(t1t2, t3);
|
||||
CGAffineTransform t1t2t3t4 = CGAffineTransformConcat(t1t2t3, t4);
|
||||
|
||||
imageFrame = CGRectApplyAffineTransform(imageFrame, t1t2t3t4);
|
||||
|
||||
CGRect cropRect = CGRectMake(0.0, 0.0, CGRectGetWidth(maskRect), CGRectGetHeight(maskRect));
|
||||
|
||||
cropRect.origin.x = -CGRectGetMinX(imageFrame) + CGRectGetMinX(maskRect);
|
||||
cropRect.origin.y = -CGRectGetMinY(imageFrame) + CGRectGetMinY(maskRect);
|
||||
|
||||
cropRect = CGRectApplyAffineTransform(cropRect, CGAffineTransformMakeScale(zoomScale, zoomScale));
|
||||
|
||||
cropRect = RSKRectNormalize(cropRect);
|
||||
|
||||
CGFloat imageScale = self.originalImage.scale;
|
||||
cropRect = CGRectApplyAffineTransform(cropRect, CGAffineTransformMakeScale(imageScale, imageScale));
|
||||
|
||||
self.imageScrollView.frame = imageScrollViewFrame;
|
||||
self.imageScrollView.transform = imageScrollViewTransform;
|
||||
|
||||
return cropRect;
|
||||
}
|
||||
|
||||
|
@ -567,6 +644,11 @@ static const CGFloat kLayoutImageScrollViewAnimationDuration = 0.25;
|
|||
}
|
||||
}
|
||||
|
||||
- (void)zoomToRect:(CGRect)rect animated:(BOOL)animated
|
||||
{
|
||||
[self.imageScrollView zoomToRect:rect animated:animated];
|
||||
}
|
||||
|
||||
#pragma mark - Public
|
||||
|
||||
- (BOOL)isPortraitInterfaceOrientation
|
||||
|
@ -677,6 +759,10 @@ static const CGFloat kLayoutImageScrollViewAnimationDuration = 0.25;
|
|||
if (self.originalImage) {
|
||||
[self.imageScrollView displayImage:self.originalImage];
|
||||
[self reset:NO];
|
||||
|
||||
if ([self.delegate respondsToSelector:@selector(imageCropViewControllerDidDisplayImage:)]) {
|
||||
[self.delegate imageCropViewControllerDidDisplayImage:self];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -832,106 +918,79 @@ static const CGFloat kLayoutImageScrollViewAnimationDuration = 0.25;
|
|||
}
|
||||
}
|
||||
|
||||
- (UIImage *)croppedImage:(UIImage *)image cropRect:(CGRect)cropRect scale:(CGFloat)imageScale orientation:(UIImageOrientation)imageOrientation
|
||||
- (UIImage *)imageWithImage:(UIImage *)image inRect:(CGRect)rect scale:(CGFloat)scale imageOrientation:(UIImageOrientation)imageOrientation
|
||||
{
|
||||
if (!image.images) {
|
||||
CGImageRef croppedCGImage = CGImageCreateWithImageInRect(image.CGImage, cropRect);
|
||||
UIImage *croppedImage = [UIImage imageWithCGImage:croppedCGImage scale:imageScale orientation:imageOrientation];
|
||||
CGImageRelease(croppedCGImage);
|
||||
return croppedImage;
|
||||
CGImageRef cgImage = CGImageCreateWithImageInRect(image.CGImage, rect);
|
||||
UIImage *image = [UIImage imageWithCGImage:cgImage scale:scale orientation:imageOrientation];
|
||||
CGImageRelease(cgImage);
|
||||
return image;
|
||||
} else {
|
||||
UIImage *animatedImage = image;
|
||||
NSMutableArray *croppedImages = [NSMutableArray array];
|
||||
for (UIImage *image in animatedImage.images) {
|
||||
UIImage *croppedImage = [self croppedImage:image cropRect:cropRect scale:imageScale orientation:imageOrientation];
|
||||
[croppedImages addObject:croppedImage];
|
||||
NSMutableArray *images = [NSMutableArray array];
|
||||
for (UIImage *animatedImageImage in animatedImage.images) {
|
||||
UIImage *image = [self imageWithImage:animatedImageImage inRect:rect scale:scale imageOrientation:imageOrientation];
|
||||
[images addObject:image];
|
||||
}
|
||||
return [UIImage animatedImageWithImages:croppedImages duration:image.duration];
|
||||
return [UIImage animatedImageWithImages:images duration:image.duration];
|
||||
}
|
||||
}
|
||||
|
||||
- (UIImage *)croppedImage:(UIImage *)image cropMode:(RSKImageCropMode)cropMode cropRect:(CGRect)cropRect rotationAngle:(CGFloat)rotationAngle zoomScale:(CGFloat)zoomScale maskPath:(UIBezierPath *)maskPath applyMaskToCroppedImage:(BOOL)applyMaskToCroppedImage
|
||||
- (UIImage *)croppedImage:(UIImage *)originalImage cropMode:(RSKImageCropMode)cropMode cropRect:(CGRect)cropRect imageRect:(CGRect)imageRect rotationAngle:(CGFloat)rotationAngle zoomScale:(CGFloat)zoomScale maskPath:(UIBezierPath *)maskPath applyMaskToCroppedImage:(BOOL)applyMaskToCroppedImage
|
||||
{
|
||||
// Step 1: check and correct the crop rect.
|
||||
CGSize imageSize = image.size;
|
||||
CGFloat x = CGRectGetMinX(cropRect);
|
||||
CGFloat y = CGRectGetMinY(cropRect);
|
||||
CGFloat width = CGRectGetWidth(cropRect);
|
||||
CGFloat height = CGRectGetHeight(cropRect);
|
||||
// Step 1: create an image using the data contained within the specified rect.
|
||||
UIImage *image = [self imageWithImage:originalImage inRect:imageRect scale:originalImage.scale imageOrientation:originalImage.imageOrientation];
|
||||
|
||||
UIImageOrientation imageOrientation = image.imageOrientation;
|
||||
if (imageOrientation == UIImageOrientationRight || imageOrientation == UIImageOrientationRightMirrored) {
|
||||
cropRect.origin.x = y;
|
||||
cropRect.origin.y = floor(imageSize.width - CGRectGetWidth(cropRect) - x);
|
||||
cropRect.size.width = height;
|
||||
cropRect.size.height = width;
|
||||
} else if (imageOrientation == UIImageOrientationLeft || imageOrientation == UIImageOrientationLeftMirrored) {
|
||||
cropRect.origin.x = floor(imageSize.height - CGRectGetHeight(cropRect) - y);
|
||||
cropRect.origin.y = x;
|
||||
cropRect.size.width = height;
|
||||
cropRect.size.height = width;
|
||||
} else if (imageOrientation == UIImageOrientationDown || imageOrientation == UIImageOrientationDownMirrored) {
|
||||
cropRect.origin.x = floor(imageSize.width - CGRectGetWidth(cropRect) - x);
|
||||
cropRect.origin.y = floor(imageSize.height - CGRectGetHeight(cropRect) - y);
|
||||
}
|
||||
// Step 2: fix orientation of the image.
|
||||
image = [image fixOrientation];
|
||||
|
||||
CGFloat imageScale = image.scale;
|
||||
cropRect = CGRectApplyAffineTransform(cropRect, CGAffineTransformMakeScale(imageScale, imageScale));
|
||||
|
||||
// Step 2: create an image using the data contained within the specified rect.
|
||||
UIImage *croppedImage = [self croppedImage:image cropRect:cropRect scale:imageScale orientation:imageOrientation];
|
||||
|
||||
// Step 3: fix orientation of the cropped image.
|
||||
croppedImage = [croppedImage fixOrientation];
|
||||
imageOrientation = croppedImage.imageOrientation;
|
||||
|
||||
// Step 4: If current mode is `RSKImageCropModeSquare` and the image is not rotated
|
||||
// or mask should not be applied to the image after cropping and the image is not rotated,
|
||||
// we can return the cropped image immediately.
|
||||
// Step 3: If current mode is `RSKImageCropModeSquare` and the original image is not rotated
|
||||
// or mask should not be applied to the image after cropping and the original image is not rotated,
|
||||
// we can return the image immediately.
|
||||
// Otherwise, we must further process the image.
|
||||
if ((cropMode == RSKImageCropModeSquare || !applyMaskToCroppedImage) && rotationAngle == 0.0) {
|
||||
// Step 5: return the cropped image immediately.
|
||||
return croppedImage;
|
||||
// Step 4: return the image immediately.
|
||||
return image;
|
||||
} else {
|
||||
// Step 5: create a new context.
|
||||
// Step 4: create a new context.
|
||||
CGSize contextSize = cropRect.size;
|
||||
UIGraphicsBeginImageContextWithOptions(contextSize, NO, imageScale);
|
||||
UIGraphicsBeginImageContextWithOptions(contextSize, NO, originalImage.scale);
|
||||
|
||||
// Step 6: apply the mask if needed.
|
||||
// Step 5: apply the mask if needed.
|
||||
if (applyMaskToCroppedImage) {
|
||||
// 6a: scale the mask to the size of the crop rect.
|
||||
// 5a: scale the mask to the size of the crop rect.
|
||||
UIBezierPath *maskPathCopy = [maskPath copy];
|
||||
CGFloat scale = 1.0 / zoomScale;
|
||||
[maskPathCopy applyTransform:CGAffineTransformMakeScale(scale, scale)];
|
||||
|
||||
// 6b: move the mask to the top-left.
|
||||
// 5b: move the mask to the top-left.
|
||||
CGPoint translation = CGPointMake(-CGRectGetMinX(maskPathCopy.bounds),
|
||||
-CGRectGetMinY(maskPathCopy.bounds));
|
||||
[maskPathCopy applyTransform:CGAffineTransformMakeTranslation(translation.x, translation.y)];
|
||||
|
||||
// 6c: apply the mask.
|
||||
// 5c: apply the mask.
|
||||
[maskPathCopy addClip];
|
||||
}
|
||||
|
||||
// Step 7: rotate the cropped image if needed.
|
||||
// Step 6: rotate the image if needed.
|
||||
if (rotationAngle != 0) {
|
||||
croppedImage = [croppedImage rotateByAngle:rotationAngle];
|
||||
image = [image rotateByAngle:rotationAngle];
|
||||
}
|
||||
|
||||
// Step 8: draw the cropped image.
|
||||
CGPoint point = CGPointMake(floor((contextSize.width - croppedImage.size.width) * 0.5f),
|
||||
floor((contextSize.height - croppedImage.size.height) * 0.5f));
|
||||
[croppedImage drawAtPoint:point];
|
||||
// Step 7: draw the image.
|
||||
CGPoint point = CGPointMake(floor((contextSize.width - image.size.width) * 0.5f),
|
||||
floor((contextSize.height - image.size.height) * 0.5f));
|
||||
[image drawAtPoint:point];
|
||||
|
||||
// Step 9: get the cropped image affter processing from the context.
|
||||
croppedImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
// Step 8: get the cropped image affter processing from the context.
|
||||
UIImage *croppedImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
|
||||
// Step 10: remove the context.
|
||||
// Step 9: remove the context.
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
croppedImage = [UIImage imageWithCGImage:croppedImage.CGImage scale:imageScale orientation:imageOrientation];
|
||||
croppedImage = [UIImage imageWithCGImage:croppedImage.CGImage scale:originalImage.scale orientation:image.imageOrientation];
|
||||
|
||||
// Step 11: return the cropped image affter processing.
|
||||
// Step 10: return the cropped image affter processing.
|
||||
return croppedImage;
|
||||
}
|
||||
}
|
||||
|
@ -945,6 +1004,7 @@ static const CGFloat kLayoutImageScrollViewAnimationDuration = 0.25;
|
|||
UIImage *originalImage = self.originalImage;
|
||||
RSKImageCropMode cropMode = self.cropMode;
|
||||
CGRect cropRect = self.cropRect;
|
||||
CGRect imageRect = self.imageRect;
|
||||
CGFloat rotationAngle = self.rotationAngle;
|
||||
CGFloat zoomScale = self.imageScrollView.zoomScale;
|
||||
UIBezierPath *maskPath = self.maskPath;
|
||||
|
@ -952,7 +1012,7 @@ static const CGFloat kLayoutImageScrollViewAnimationDuration = 0.25;
|
|||
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
|
||||
UIImage *croppedImage = [self croppedImage:originalImage cropMode:cropMode cropRect:cropRect rotationAngle:rotationAngle zoomScale:zoomScale maskPath:maskPath applyMaskToCroppedImage:applyMaskToCroppedImage];
|
||||
UIImage *croppedImage = [self croppedImage:originalImage cropMode:cropMode cropRect:cropRect imageRect:imageRect rotationAngle:rotationAngle zoomScale:zoomScale maskPath:maskPath applyMaskToCroppedImage:applyMaskToCroppedImage];
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self.delegate imageCropViewController:self didCropImage:croppedImage usingCropRect:cropRect rotationAngle:rotationAngle];
|
||||
|
|
|
@ -1,9 +1,25 @@
|
|||
//
|
||||
// RSKInternalUtility.h
|
||||
// RSKImageCropperExample
|
||||
// RSKInternalUtility.h
|
||||
//
|
||||
// Created by Ruslan Skorb on 9/5/15.
|
||||
// Copyright (c) 2015 Ruslan Skorb. All rights reserved.
|
||||
// Copyright (c) 2015-present Ruslan Skorb, http://ruslanskorb.com/
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
|
|
@ -1,9 +1,25 @@
|
|||
//
|
||||
// RSKInternalUtility.m
|
||||
// RSKImageCropperExample
|
||||
// RSKInternalUtility.m
|
||||
//
|
||||
// Created by Ruslan Skorb on 9/5/15.
|
||||
// Copyright (c) 2015 Ruslan Skorb. All rights reserved.
|
||||
// Copyright (c) 2015-present Ruslan Skorb, http://ruslanskorb.com/
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
#import "RSKInternalUtility.h"
|
||||
|
|
|
@ -12,6 +12,31 @@ The above copyright notice and this permission notice shall be included in all c
|
|||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
## RNDeviceInfo
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Rebecca Hughes
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
## RNImageCropPicker
|
||||
|
||||
MIT License
|
||||
|
|
|
@ -29,6 +29,37 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
|||
<key>Type</key>
|
||||
<string>PSGroupSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>FooterText</key>
|
||||
<string>The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Rebecca Hughes
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
</string>
|
||||
<key>License</key>
|
||||
<string>MIT</string>
|
||||
<key>Title</key>
|
||||
<string>RNDeviceInfo</string>
|
||||
<key>Type</key>
|
||||
<string>PSGroupSpecifier</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>FooterText</key>
|
||||
<string>MIT License
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/QBImagePickerController" "${PODS_ROOT}/Headers/Public/RNImageCropPicker" "${PODS_ROOT}/Headers/Public/RSKImageCropper" "${PODS_ROOT}/Headers/Public/React" "${PODS_ROOT}/Headers/Public/yoga"
|
||||
LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/QBImagePickerController" "${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker" "${PODS_CONFIGURATION_BUILD_DIR}/RSKImageCropper" "${PODS_CONFIGURATION_BUILD_DIR}/React" "${PODS_CONFIGURATION_BUILD_DIR}/yoga"
|
||||
OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/QBImagePickerController" -isystem "${PODS_ROOT}/Headers/Public/RNImageCropPicker" -isystem "${PODS_ROOT}/Headers/Public/RSKImageCropper" -isystem "${PODS_ROOT}/Headers/Public/React" -isystem "${PODS_ROOT}/Headers/Public/yoga"
|
||||
OTHER_LDFLAGS = $(inherited) -ObjC -l"QBImagePickerController" -l"RNImageCropPicker" -l"RSKImageCropper" -l"React" -l"stdc++" -l"yoga" -framework "JavaScriptCore" -framework "Photos" -framework "QuartzCore" -framework "UIKit"
|
||||
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/QBImagePickerController" "${PODS_ROOT}/Headers/Public/RNDeviceInfo" "${PODS_ROOT}/Headers/Public/RNImageCropPicker" "${PODS_ROOT}/Headers/Public/RSKImageCropper" "${PODS_ROOT}/Headers/Public/React" "${PODS_ROOT}/Headers/Public/yoga"
|
||||
LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/QBImagePickerController" "${PODS_CONFIGURATION_BUILD_DIR}/RNDeviceInfo" "${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker" "${PODS_CONFIGURATION_BUILD_DIR}/RSKImageCropper" "${PODS_CONFIGURATION_BUILD_DIR}/React" "${PODS_CONFIGURATION_BUILD_DIR}/yoga"
|
||||
OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/QBImagePickerController" -isystem "${PODS_ROOT}/Headers/Public/RNDeviceInfo" -isystem "${PODS_ROOT}/Headers/Public/RNImageCropPicker" -isystem "${PODS_ROOT}/Headers/Public/RSKImageCropper" -isystem "${PODS_ROOT}/Headers/Public/React" -isystem "${PODS_ROOT}/Headers/Public/yoga"
|
||||
OTHER_LDFLAGS = $(inherited) -ObjC -l"QBImagePickerController" -l"RNDeviceInfo" -l"RNImageCropPicker" -l"RSKImageCropper" -l"React" -l"stdc++" -l"yoga" -framework "JavaScriptCore" -framework "Photos" -framework "QuartzCore" -framework "UIKit"
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/QBImagePickerController" "${PODS_ROOT}/Headers/Public/RNImageCropPicker" "${PODS_ROOT}/Headers/Public/RSKImageCropper" "${PODS_ROOT}/Headers/Public/React" "${PODS_ROOT}/Headers/Public/yoga"
|
||||
LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/QBImagePickerController" "${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker" "${PODS_CONFIGURATION_BUILD_DIR}/RSKImageCropper" "${PODS_CONFIGURATION_BUILD_DIR}/React" "${PODS_CONFIGURATION_BUILD_DIR}/yoga"
|
||||
OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/QBImagePickerController" -isystem "${PODS_ROOT}/Headers/Public/RNImageCropPicker" -isystem "${PODS_ROOT}/Headers/Public/RSKImageCropper" -isystem "${PODS_ROOT}/Headers/Public/React" -isystem "${PODS_ROOT}/Headers/Public/yoga"
|
||||
OTHER_LDFLAGS = $(inherited) -ObjC -l"QBImagePickerController" -l"RNImageCropPicker" -l"RSKImageCropper" -l"React" -l"stdc++" -l"yoga" -framework "JavaScriptCore" -framework "Photos" -framework "QuartzCore" -framework "UIKit"
|
||||
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/QBImagePickerController" "${PODS_ROOT}/Headers/Public/RNDeviceInfo" "${PODS_ROOT}/Headers/Public/RNImageCropPicker" "${PODS_ROOT}/Headers/Public/RSKImageCropper" "${PODS_ROOT}/Headers/Public/React" "${PODS_ROOT}/Headers/Public/yoga"
|
||||
LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/QBImagePickerController" "${PODS_CONFIGURATION_BUILD_DIR}/RNDeviceInfo" "${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker" "${PODS_CONFIGURATION_BUILD_DIR}/RSKImageCropper" "${PODS_CONFIGURATION_BUILD_DIR}/React" "${PODS_CONFIGURATION_BUILD_DIR}/yoga"
|
||||
OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/QBImagePickerController" -isystem "${PODS_ROOT}/Headers/Public/RNDeviceInfo" -isystem "${PODS_ROOT}/Headers/Public/RNImageCropPicker" -isystem "${PODS_ROOT}/Headers/Public/RSKImageCropper" -isystem "${PODS_ROOT}/Headers/Public/React" -isystem "${PODS_ROOT}/Headers/Public/yoga"
|
||||
OTHER_LDFLAGS = $(inherited) -ObjC -l"QBImagePickerController" -l"RNDeviceInfo" -l"RNImageCropPicker" -l"RSKImageCropper" -l"React" -l"stdc++" -l"yoga" -framework "JavaScriptCore" -framework "Photos" -framework "QuartzCore" -framework "UIKit"
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/QBImagePickerController
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/QBImagePickerController" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/QBImagePickerController" "${PODS_ROOT}/Headers/Public/RNImageCropPicker" "${PODS_ROOT}/Headers/Public/RSKImageCropper" "${PODS_ROOT}/Headers/Public/React" "${PODS_ROOT}/Headers/Public/yoga"
|
||||
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/QBImagePickerController" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/QBImagePickerController" "${PODS_ROOT}/Headers/Public/RNDeviceInfo" "${PODS_ROOT}/Headers/Public/RNImageCropPicker" "${PODS_ROOT}/Headers/Public/RSKImageCropper" "${PODS_ROOT}/Headers/Public/React" "${PODS_ROOT}/Headers/Public/yoga"
|
||||
OTHER_LDFLAGS = -framework "Photos"
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
@interface PodsDummy_RNDeviceInfo : NSObject
|
||||
@end
|
||||
@implementation PodsDummy_RNDeviceInfo
|
||||
@end
|
|
@ -0,0 +1,12 @@
|
|||
#ifdef __OBJC__
|
||||
#import <UIKit/UIKit.h>
|
||||
#else
|
||||
#ifndef FOUNDATION_EXPORT
|
||||
#if defined(__cplusplus)
|
||||
#define FOUNDATION_EXPORT extern "C"
|
||||
#else
|
||||
#define FOUNDATION_EXPORT extern
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/RNDeviceInfo
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/RNDeviceInfo" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/QBImagePickerController" "${PODS_ROOT}/Headers/Public/RNDeviceInfo" "${PODS_ROOT}/Headers/Public/RNImageCropPicker" "${PODS_ROOT}/Headers/Public/RSKImageCropper" "${PODS_ROOT}/Headers/Public/React" "${PODS_ROOT}/Headers/Public/yoga"
|
||||
LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/React" "${PODS_CONFIGURATION_BUILD_DIR}/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-device-info
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
|
||||
SKIP_INSTALL = YES
|
|
@ -1,6 +1,6 @@
|
|||
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/RNImageCropPicker
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/RNImageCropPicker" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/QBImagePickerController" "${PODS_ROOT}/Headers/Public/RNImageCropPicker" "${PODS_ROOT}/Headers/Public/RSKImageCropper" "${PODS_ROOT}/Headers/Public/React" "${PODS_ROOT}/Headers/Public/yoga"
|
||||
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/RNImageCropPicker" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/QBImagePickerController" "${PODS_ROOT}/Headers/Public/RNDeviceInfo" "${PODS_ROOT}/Headers/Public/RNImageCropPicker" "${PODS_ROOT}/Headers/Public/RSKImageCropper" "${PODS_ROOT}/Headers/Public/React" "${PODS_ROOT}/Headers/Public/yoga"
|
||||
LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/QBImagePickerController" "${PODS_CONFIGURATION_BUILD_DIR}/RSKImageCropper" "${PODS_CONFIGURATION_BUILD_DIR}/React" "${PODS_CONFIGURATION_BUILD_DIR}/yoga"
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/RSKImageCropper
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/RSKImageCropper" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/QBImagePickerController" "${PODS_ROOT}/Headers/Public/RNImageCropPicker" "${PODS_ROOT}/Headers/Public/RSKImageCropper" "${PODS_ROOT}/Headers/Public/React" "${PODS_ROOT}/Headers/Public/yoga"
|
||||
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/RSKImageCropper" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/QBImagePickerController" "${PODS_ROOT}/Headers/Public/RNDeviceInfo" "${PODS_ROOT}/Headers/Public/RNImageCropPicker" "${PODS_ROOT}/Headers/Public/RSKImageCropper" "${PODS_ROOT}/Headers/Public/React" "${PODS_ROOT}/Headers/Public/yoga"
|
||||
OTHER_LDFLAGS = -framework "QuartzCore" -framework "UIKit"
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
CLANG_CXX_LANGUAGE_STANDARD = c++14
|
||||
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/React
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/React" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/QBImagePickerController" "${PODS_ROOT}/Headers/Public/RNImageCropPicker" "${PODS_ROOT}/Headers/Public/RSKImageCropper" "${PODS_ROOT}/Headers/Public/React" "${PODS_ROOT}/Headers/Public/yoga" "$(PODS_TARGET_SRCROOT)/ReactCommon"
|
||||
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/React" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/QBImagePickerController" "${PODS_ROOT}/Headers/Public/RNDeviceInfo" "${PODS_ROOT}/Headers/Public/RNImageCropPicker" "${PODS_ROOT}/Headers/Public/RSKImageCropper" "${PODS_ROOT}/Headers/Public/React" "${PODS_ROOT}/Headers/Public/yoga" "$(PODS_TARGET_SRCROOT)/ReactCommon"
|
||||
LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/yoga"
|
||||
OTHER_LDFLAGS = -l"stdc++" -framework "JavaScriptCore"
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/yoga
|
||||
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
|
||||
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/yoga" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/QBImagePickerController" "${PODS_ROOT}/Headers/Public/RNImageCropPicker" "${PODS_ROOT}/Headers/Public/RSKImageCropper" "${PODS_ROOT}/Headers/Public/React" "${PODS_ROOT}/Headers/Public/yoga"
|
||||
HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/yoga" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/QBImagePickerController" "${PODS_ROOT}/Headers/Public/RNDeviceInfo" "${PODS_ROOT}/Headers/Public/RNImageCropPicker" "${PODS_ROOT}/Headers/Public/RSKImageCropper" "${PODS_ROOT}/Headers/Public/React" "${PODS_ROOT}/Headers/Public/yoga"
|
||||
PODS_BUILD_DIR = ${BUILD_DIR}
|
||||
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|
||||
PODS_ROOT = ${SRCROOT}
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; };
|
||||
8A159EDB97C44E52AF62D69C /* libRNSVG.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DA50CE47374C4C35BE6D9D58 /* libRNSVG.a */; };
|
||||
8ECBD927DDAC4987B98E102E /* libRCTVideo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 20CE3E407E0D4D9E8C9885F2 /* libRCTVideo.a */; };
|
||||
95E57ADEB9A0487791D2C50E /* libRNGestureHandler.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58E5009FCA8D40E59303C3DD /* libRNGestureHandler.a */; };
|
||||
AE5D35882AE04CC29630FB3D /* Entypo.ttf in Resources */ = {isa = PBXBuildFile; fileRef = DC6EE17B5550465E98C70FF0 /* Entypo.ttf */; };
|
||||
B88F586F1FBF57F600B352B8 /* libRCTPushNotification.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B88F58461FBF55E200B352B8 /* libRCTPushNotification.a */; };
|
||||
B8971BB2202A093B0000D245 /* libKeyboardTrackingView.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B8971BB1202A091D0000D245 /* libKeyboardTrackingView.a */; };
|
||||
|
@ -380,6 +381,13 @@
|
|||
remoteGlobalIDString = 134814201AA4EA6300B7C361;
|
||||
remoteInfo = RNNotifications;
|
||||
};
|
||||
7AD44CF421518C610099D147 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = B1A58A7ACB0E4453A44AEC38 /* RNGestureHandler.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 134814201AA4EA6300B7C361;
|
||||
remoteInfo = RNGestureHandler;
|
||||
};
|
||||
7AFB804B205AE63100D004E7 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 7AFB8035205AE63000D004E7 /* RCTToast.xcodeproj */;
|
||||
|
@ -544,6 +552,7 @@
|
|||
3B696712EE2345A59F007A88 /* libRNImagePicker.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNImagePicker.a; sourceTree = "<group>"; };
|
||||
4019A5E1911B4C61944FBCEC /* SafariViewManager.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = SafariViewManager.xcodeproj; path = "../node_modules/react-native-safari-view/SafariViewManager.xcodeproj"; sourceTree = "<group>"; };
|
||||
41FE03CD3B554249859F01BA /* RNZeroconf.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNZeroconf.xcodeproj; path = "../node_modules/react-native-zeroconf/ios/RNZeroconf.xcodeproj"; sourceTree = "<group>"; };
|
||||
58E5009FCA8D40E59303C3DD /* libRNGestureHandler.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNGestureHandler.a; sourceTree = "<group>"; };
|
||||
5A0EEFAF8AB14F5B9E796CDD /* libRNVectorIcons.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNVectorIcons.a; sourceTree = "<group>"; };
|
||||
5A8684E7C27E426C9206E980 /* RealmReact.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RealmReact.xcodeproj; path = "../node_modules/realm/react-native/ios/RealmReact.xcodeproj"; sourceTree = "<group>"; };
|
||||
5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = "../node_modules/react-native/Libraries/NativeAnimation/RCTAnimation.xcodeproj"; sourceTree = "<group>"; };
|
||||
|
@ -568,6 +577,7 @@
|
|||
A18EFC3B0CFE40E0918A8F0C /* EvilIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = EvilIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf"; sourceTree = "<group>"; };
|
||||
ACD75701AFD1CB848CAB0CB3 /* Pods-RocketChatRN.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RocketChatRN.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RocketChatRN/Pods-RocketChatRN.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
AD0379F2BCE84C968538CDAF /* RCTVideo.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RCTVideo.xcodeproj; path = "../node_modules/react-native-video/ios/RCTVideo.xcodeproj"; sourceTree = "<group>"; };
|
||||
B1A58A7ACB0E4453A44AEC38 /* RNGestureHandler.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNGestureHandler.xcodeproj; path = "../node_modules/react-native-gesture-handler/ios/RNGestureHandler.xcodeproj"; sourceTree = "<group>"; };
|
||||
B2607FA180F14E6584301101 /* libSplashScreen.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libSplashScreen.a; sourceTree = "<group>"; };
|
||||
B37C79D9BD0742CE936B6982 /* libc++.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; };
|
||||
B88F58361FBF55E200B352B8 /* RCTPushNotification.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTPushNotification.xcodeproj; path = "../node_modules/react-native/Libraries/PushNotificationIOS/RCTPushNotification.xcodeproj"; sourceTree = "<group>"; };
|
||||
|
@ -632,6 +642,7 @@
|
|||
BAB7DC22804246F3923A1833 /* libFastImage.a in Frameworks */,
|
||||
F5BF54DC78E1411B8343933B /* libRNI18n.a in Frameworks */,
|
||||
50046CB6BDA69B9232CF66D9 /* libPods-RocketChatRN.a in Frameworks */,
|
||||
95E57ADEB9A0487791D2C50E /* libRNGestureHandler.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -889,6 +900,14 @@
|
|||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7AD44CF121518C610099D147 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7AD44CF521518C610099D147 /* libRNGestureHandler.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7AFB8036205AE63000D004E7 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -928,6 +947,7 @@
|
|||
1845C223DA364898A8400573 /* FastImage.xcodeproj */,
|
||||
22D3971EAF2E4660B4FAB3DD /* RNI18n.xcodeproj */,
|
||||
0B82BCC462E84F308C5B5CD1 /* RNFetchBlob.xcodeproj */,
|
||||
B1A58A7ACB0E4453A44AEC38 /* RNGestureHandler.xcodeproj */,
|
||||
);
|
||||
name = Libraries;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1039,6 +1059,7 @@
|
|||
921481B47B50490CA761932E /* libRNI18n.a */,
|
||||
C01CD6D4653143EEB5100C3A /* libRNI18n-tvOS.a */,
|
||||
1A34D902CC074FF1BCC7DB48 /* libimageCropPicker.a */,
|
||||
58E5009FCA8D40E59303C3DD /* libRNGestureHandler.a */,
|
||||
);
|
||||
name = "Recovered References";
|
||||
sourceTree = "<group>";
|
||||
|
@ -1281,6 +1302,10 @@
|
|||
ProductGroup = 7A8C912120F39A8000C8F5EE /* Products */;
|
||||
ProjectRef = 0B82BCC462E84F308C5B5CD1 /* RNFetchBlob.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 7AD44CF121518C610099D147 /* Products */;
|
||||
ProjectRef = B1A58A7ACB0E4453A44AEC38 /* RNGestureHandler.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 7A770EBC20BECDC7001AD51A /* Products */;
|
||||
ProjectRef = 22D3971EAF2E4660B4FAB3DD /* RNI18n.xcodeproj */;
|
||||
|
@ -1608,6 +1633,13 @@
|
|||
remoteRef = 7A8DEB5120ED0BDE00C5DCE4 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
7AD44CF521518C610099D147 /* libRNGestureHandler.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libRNGestureHandler.a;
|
||||
remoteRef = 7AD44CF421518C610099D147 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
7AFB804C205AE63100D004E7 /* libRCTToast.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
|
@ -1944,6 +1976,7 @@
|
|||
"$(SRCROOT)/../node_modules/react-native-fast-image/ios/FastImage/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-i18n/ios",
|
||||
"$(SRCROOT)/../node_modules/rn-fetch-blob/ios/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-gesture-handler/ios/**",
|
||||
);
|
||||
INFOPLIST_FILE = RocketChatRNTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
|
@ -1961,6 +1994,7 @@
|
|||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
);
|
||||
OTHER_LDFLAGS = (
|
||||
"-ObjC",
|
||||
|
@ -1992,6 +2026,7 @@
|
|||
"$(SRCROOT)/../node_modules/react-native-fast-image/ios/FastImage/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-i18n/ios",
|
||||
"$(SRCROOT)/../node_modules/rn-fetch-blob/ios/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-gesture-handler/ios/**",
|
||||
);
|
||||
INFOPLIST_FILE = RocketChatRNTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
|
@ -2009,6 +2044,7 @@
|
|||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
);
|
||||
OTHER_LDFLAGS = (
|
||||
"-ObjC",
|
||||
|
@ -2024,7 +2060,7 @@
|
|||
baseConfigurationReference = ACD75701AFD1CB848CAB0CB3 /* Pods-RocketChatRN.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
|
||||
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
|
||||
CODE_SIGN_ENTITLEMENTS = RocketChatRN/RocketChatRN.entitlements;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
|
@ -2053,6 +2089,7 @@
|
|||
"$(SRCROOT)/../node_modules/react-native-i18n/ios",
|
||||
"$(SRCROOT)/../node_modules/react-native-notifications/RNNotifications",
|
||||
"$(SRCROOT)/../node_modules/rn-fetch-blob/ios/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-gesture-handler/ios/**",
|
||||
);
|
||||
INFOPLIST_FILE = RocketChatRN/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
|
@ -2074,7 +2111,7 @@
|
|||
baseConfigurationReference = 66D6B1D0567051BE541450C9 /* Pods-RocketChatRN.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
|
||||
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
|
||||
CODE_SIGN_ENTITLEMENTS = RocketChatRN/RocketChatRN.entitlements;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
|
@ -2102,6 +2139,7 @@
|
|||
"$(SRCROOT)/../node_modules/react-native-i18n/ios",
|
||||
"$(SRCROOT)/../node_modules/react-native-notifications/RNNotifications",
|
||||
"$(SRCROOT)/../node_modules/rn-fetch-blob/ios/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-gesture-handler/ios/**",
|
||||
);
|
||||
INFOPLIST_FILE = RocketChatRN/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
|
@ -2146,6 +2184,7 @@
|
|||
"$(SRCROOT)/../node_modules/react-native-fast-image/ios/FastImage/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-i18n/ios",
|
||||
"$(SRCROOT)/../node_modules/rn-fetch-blob/ios/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-gesture-handler/ios/**",
|
||||
);
|
||||
INFOPLIST_FILE = "RocketChatRN-tvOS/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
|
@ -2162,6 +2201,7 @@
|
|||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
);
|
||||
OTHER_LDFLAGS = (
|
||||
"-ObjC",
|
||||
|
@ -2203,6 +2243,7 @@
|
|||
"$(SRCROOT)/../node_modules/react-native-fast-image/ios/FastImage/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-i18n/ios",
|
||||
"$(SRCROOT)/../node_modules/rn-fetch-blob/ios/**",
|
||||
"$(SRCROOT)/../node_modules/react-native-gesture-handler/ios/**",
|
||||
);
|
||||
INFOPLIST_FILE = "RocketChatRN-tvOS/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
|
@ -2219,6 +2260,7 @@
|
|||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
);
|
||||
OTHER_LDFLAGS = (
|
||||
"-ObjC",
|
||||
|
@ -2259,6 +2301,7 @@
|
|||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.RocketChatRN-tvOSTests";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
@ -2295,6 +2338,7 @@
|
|||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
"\"$(SRCROOT)/$(TARGET_NAME)\"",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.RocketChatRN-tvOSTests";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
|