Update UX for post long press menu (#2325)
* Update UX for post long press menu * Post menu feedback review
35
NOTICE.txt
|
|
@ -2076,41 +2076,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
---
|
||||
|
||||
## react-native-tooltip
|
||||
|
||||
This product contains 'react-native-tooltip' by Chirag Jain.
|
||||
|
||||
A react-native wrapper for showing tooltips
|
||||
|
||||
* HOMEPAGE:
|
||||
* https://github.com/chirag04/react-native-tooltip#readme
|
||||
|
||||
* LICENSE: MIT
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015-2016 Chirag Jain
|
||||
|
||||
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.
|
||||
|
||||
---
|
||||
|
||||
## react-native-vector-icons
|
||||
|
||||
This product contains 'react-native-vector-icons' by Joel Arvidsson.
|
||||
|
|
|
|||
|
|
@ -8,10 +8,9 @@ import {intlShape} from 'react-intl';
|
|||
|
||||
import {displayUsername} from 'mattermost-redux/utils/user_utils';
|
||||
|
||||
import {emptyFunction} from 'app/utils/general';
|
||||
|
||||
import CustomPropTypes from 'app/constants/custom_prop_types';
|
||||
import mattermostManaged from 'app/mattermost_managed';
|
||||
import BottomSheet from 'app/utils/bottom_sheet';
|
||||
|
||||
export default class AtMention extends React.PureComponent {
|
||||
static propTypes = {
|
||||
|
|
@ -19,7 +18,6 @@ export default class AtMention extends React.PureComponent {
|
|||
mentionName: PropTypes.string.isRequired,
|
||||
mentionStyle: CustomPropTypes.Style,
|
||||
navigator: PropTypes.object.isRequired,
|
||||
onLongPress: PropTypes.func.isRequired,
|
||||
onPostPress: PropTypes.func,
|
||||
textStyle: CustomPropTypes.Style,
|
||||
teammateNameDisplay: PropTypes.string,
|
||||
|
|
@ -27,10 +25,6 @@ export default class AtMention extends React.PureComponent {
|
|||
usersByUsername: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
onLongPress: emptyFunction,
|
||||
};
|
||||
|
||||
static contextTypes = {
|
||||
intl: intlShape,
|
||||
};
|
||||
|
|
@ -101,26 +95,33 @@ export default class AtMention extends React.PureComponent {
|
|||
}
|
||||
|
||||
handleLongPress = async () => {
|
||||
const {intl} = this.context;
|
||||
const {formatMessage} = this.context.intl;
|
||||
|
||||
const config = await mattermostManaged.getLocalConfig();
|
||||
|
||||
let action;
|
||||
if (config.copyAndPasteProtection !== 'false') {
|
||||
action = {
|
||||
text: intl.formatMessage({
|
||||
id: 'mobile.mention.copy_mention',
|
||||
defaultMessage: 'Copy Mention',
|
||||
}),
|
||||
onPress: this.handleCopyMention,
|
||||
};
|
||||
}
|
||||
const cancelText = formatMessage({id: 'mobile.post.cancel', defaultMessage: 'Cancel'});
|
||||
const actionText = formatMessage({id: 'mobile.mention.copy_mention', defaultMessage: 'Copy Mention'});
|
||||
|
||||
this.props.onLongPress(action);
|
||||
BottomSheet.showBottomSheetWithOptions({
|
||||
options: [actionText, cancelText],
|
||||
cancelButtonIndex: 1,
|
||||
}, (value) => {
|
||||
if (value !== 1) {
|
||||
this.handleCopyMention();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
handleCopyMention = () => {
|
||||
const {username} = this.state;
|
||||
const {user} = this.state;
|
||||
const {mentionName} = this.props;
|
||||
let username = mentionName;
|
||||
if (user.username) {
|
||||
username = user.username;
|
||||
}
|
||||
|
||||
Clipboard.setString(`@${username}`);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ export default class FileAttachment extends PureComponent {
|
|||
file: PropTypes.object.isRequired,
|
||||
index: PropTypes.number.isRequired,
|
||||
onCaptureRef: PropTypes.func,
|
||||
onLongPress: PropTypes.func,
|
||||
onPreviewPress: PropTypes.func,
|
||||
theme: PropTypes.object.isRequired,
|
||||
navigator: PropTypes.object,
|
||||
|
|
@ -92,6 +93,7 @@ export default class FileAttachment extends PureComponent {
|
|||
file,
|
||||
theme,
|
||||
navigator,
|
||||
onLongPress,
|
||||
} = this.props;
|
||||
const {data} = file;
|
||||
const style = getStyleSheet(theme);
|
||||
|
|
@ -99,7 +101,10 @@ export default class FileAttachment extends PureComponent {
|
|||
let fileAttachmentComponent;
|
||||
if ((data && data.has_preview_image) || file.loading || isGif(data)) {
|
||||
fileAttachmentComponent = (
|
||||
<TouchableOpacity onPress={this.handlePreviewPress}>
|
||||
<TouchableOpacity
|
||||
onPress={this.handlePreviewPress}
|
||||
onLongPress={onLongPress}
|
||||
>
|
||||
<FileAttachmentImage
|
||||
file={data || {}}
|
||||
onCaptureRef={this.handleCaptureRef}
|
||||
|
|
@ -114,12 +119,16 @@ export default class FileAttachment extends PureComponent {
|
|||
canDownloadFiles={canDownloadFiles}
|
||||
file={file}
|
||||
navigator={navigator}
|
||||
onLongPress={onLongPress}
|
||||
theme={theme}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
fileAttachmentComponent = (
|
||||
<TouchableOpacity onPress={this.handlePreviewPress}>
|
||||
<TouchableOpacity
|
||||
onPress={this.handlePreviewPress}
|
||||
onLongPress={onLongPress}
|
||||
>
|
||||
<FileAttachmentIcon
|
||||
file={data}
|
||||
onCaptureRef={this.handleCaptureRef}
|
||||
|
|
@ -135,6 +144,7 @@ export default class FileAttachment extends PureComponent {
|
|||
<View style={[style.fileWrapper, {width}]}>
|
||||
{fileAttachmentComponent}
|
||||
<TouchableOpacity
|
||||
onLongPress={onLongPress}
|
||||
onPress={this.handlePreviewPress}
|
||||
style={style.fileInfoContainer}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ export default class FileAttachmentDocument extends PureComponent {
|
|||
file: PropTypes.object.isRequired,
|
||||
theme: PropTypes.object.isRequired,
|
||||
navigator: PropTypes.object,
|
||||
onLongPress: PropTypes.func,
|
||||
wrapperHeight: PropTypes.number,
|
||||
wrapperWidth: PropTypes.number,
|
||||
};
|
||||
|
|
@ -349,7 +350,7 @@ export default class FileAttachmentDocument extends PureComponent {
|
|||
}
|
||||
|
||||
render() {
|
||||
const {theme, wrapperHeight} = this.props;
|
||||
const {onLongPress, theme, wrapperHeight} = this.props;
|
||||
const {downloading, progress} = this.state;
|
||||
|
||||
let fileAttachmentComponent;
|
||||
|
|
@ -371,8 +372,11 @@ export default class FileAttachmentDocument extends PureComponent {
|
|||
}
|
||||
|
||||
return (
|
||||
<TouchableOpacity onPress={this.handlePreviewPress}>
|
||||
<View style={style.whiteBackgroud}>
|
||||
<TouchableOpacity
|
||||
onPress={this.handlePreviewPress}
|
||||
onLongPress={onLongPress}
|
||||
>
|
||||
<View style={style.whiteBackground}>
|
||||
{fileAttachmentComponent}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
|
|
@ -389,7 +393,7 @@ const style = StyleSheet.create({
|
|||
position: 'absolute',
|
||||
top: 0,
|
||||
},
|
||||
whiteBackgroud: {
|
||||
whiteBackground: {
|
||||
backgroundColor: '#fff',
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import {
|
|||
Platform,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
} from 'react-native';
|
||||
|
||||
|
|
@ -30,7 +29,6 @@ export default class FileAttachmentList extends Component {
|
|||
deviceWidth: PropTypes.number.isRequired,
|
||||
fileIds: PropTypes.array.isRequired,
|
||||
files: PropTypes.array.isRequired,
|
||||
hideOptionsContext: PropTypes.func.isRequired,
|
||||
isFailed: PropTypes.bool,
|
||||
navigator: PropTypes.object,
|
||||
onLongPress: PropTypes.func,
|
||||
|
|
@ -121,7 +119,6 @@ export default class FileAttachmentList extends Component {
|
|||
};
|
||||
|
||||
handlePreviewPress = preventDoubleTap((idx) => {
|
||||
this.props.hideOptionsContext();
|
||||
Keyboard.dismiss();
|
||||
previewImageAtIndex(this.props.navigator, this.items, idx, this.galleryFiles);
|
||||
});
|
||||
|
|
@ -157,23 +154,18 @@ export default class FileAttachmentList extends Component {
|
|||
};
|
||||
|
||||
return (
|
||||
<TouchableOpacity
|
||||
<FileAttachment
|
||||
key={file.id}
|
||||
canDownloadFiles={canDownloadFiles}
|
||||
deviceWidth={deviceWidth}
|
||||
file={f}
|
||||
index={idx}
|
||||
navigator={navigator}
|
||||
onCaptureRef={this.handleCaptureRef}
|
||||
onPreviewPress={this.handlePreviewPress}
|
||||
onLongPress={this.props.onLongPress}
|
||||
onPressIn={this.handlePressIn}
|
||||
onPressOut={this.handlePressOut}
|
||||
>
|
||||
<FileAttachment
|
||||
canDownloadFiles={canDownloadFiles}
|
||||
deviceWidth={deviceWidth}
|
||||
file={f}
|
||||
index={idx}
|
||||
navigator={navigator}
|
||||
onCaptureRef={this.handleCaptureRef}
|
||||
onPreviewPress={this.handlePreviewPress}
|
||||
theme={this.props.theme}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
theme={this.props.theme}
|
||||
/>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -116,7 +116,6 @@ class FormattedMarkdownText extends React.PureComponent {
|
|||
mentionStyle={this.props.textStyles.mention}
|
||||
mentionName={mentionName}
|
||||
navigator={this.props.navigator}
|
||||
onLongPress={this.props.onPostPress}
|
||||
onPostPress={this.props.onPostPress}
|
||||
textStyle={this.computeTextStyle(this.props.baseTextStyle, context)}
|
||||
/>
|
||||
|
|
@ -145,4 +144,4 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
|||
};
|
||||
});
|
||||
|
||||
export default injectIntl(FormattedMarkdownText);
|
||||
export default injectIntl(FormattedMarkdownText);
|
||||
|
|
|
|||
|
|
@ -49,7 +49,6 @@ export default class Markdown extends PureComponent {
|
|||
navigator: PropTypes.object.isRequired,
|
||||
onChannelLinkPress: PropTypes.func,
|
||||
onHashtagPress: PropTypes.func,
|
||||
onLongPress: PropTypes.func,
|
||||
onPermalinkPress: PropTypes.func,
|
||||
onPostPress: PropTypes.func,
|
||||
textStyles: PropTypes.object,
|
||||
|
|
@ -80,13 +79,13 @@ export default class Markdown extends PureComponent {
|
|||
return new Parser({
|
||||
urlFilter: this.urlFilter,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
urlFilter = (url) => {
|
||||
const scheme = getScheme(url);
|
||||
|
||||
return !scheme || this.props.autolinkedUrlSchemes.indexOf(scheme) !== -1;
|
||||
}
|
||||
};
|
||||
|
||||
createRenderer = () => {
|
||||
return new Renderer({
|
||||
|
|
@ -130,7 +129,7 @@ export default class Markdown extends PureComponent {
|
|||
renderParagraphsInLists: true,
|
||||
getExtraPropsForNode: this.getExtraPropsForNode,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
getExtraPropsForNode = (node) => {
|
||||
const extraProps = {
|
||||
|
|
@ -144,11 +143,11 @@ export default class Markdown extends PureComponent {
|
|||
}
|
||||
|
||||
return extraProps;
|
||||
}
|
||||
};
|
||||
|
||||
computeTextStyle = (baseStyle, context) => {
|
||||
return concatStyles(baseStyle, context.map((type) => this.props.textStyles[type]));
|
||||
}
|
||||
};
|
||||
|
||||
renderText = ({context, literal}) => {
|
||||
if (context.indexOf('image') !== -1) {
|
||||
|
|
@ -160,19 +159,17 @@ export default class Markdown extends PureComponent {
|
|||
const style = this.computeTextStyle(this.props.baseTextStyle, context);
|
||||
|
||||
return <Text style={style}>{literal}</Text>;
|
||||
}
|
||||
};
|
||||
|
||||
renderCodeSpan = ({context, literal}) => {
|
||||
return <Text style={this.computeTextStyle([this.props.baseTextStyle, this.props.textStyles.code], context)}>{literal}</Text>;
|
||||
}
|
||||
};
|
||||
|
||||
renderImage = ({linkDestination, reactChildren, context, src}) => {
|
||||
if (context.indexOf('table') !== -1) {
|
||||
// We have enough problems rendering images as is, so just render a link inside of a table
|
||||
return (
|
||||
<MarkdownTableImage
|
||||
linkDestination={linkDestination}
|
||||
onLongPress={this.props.onLongPress}
|
||||
source={src}
|
||||
textStyle={[this.computeTextStyle(this.props.baseTextStyle, context), this.props.textStyles.link]}
|
||||
navigator={this.props.navigator}
|
||||
|
|
@ -187,14 +184,13 @@ export default class Markdown extends PureComponent {
|
|||
linkDestination={linkDestination}
|
||||
isReplyPost={this.props.isReplyPost}
|
||||
navigator={this.props.navigator}
|
||||
onLongPress={this.props.onLongPress}
|
||||
source={src}
|
||||
errorTextStyle={[this.computeTextStyle(this.props.baseTextStyle, context), this.props.textStyles.error]}
|
||||
>
|
||||
{reactChildren}
|
||||
</MarkdownImage>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
renderAtMention = ({context, mentionName}) => {
|
||||
if (this.props.disableAtMentions) {
|
||||
|
|
@ -207,12 +203,11 @@ export default class Markdown extends PureComponent {
|
|||
textStyle={this.computeTextStyle(this.props.baseTextStyle, context)}
|
||||
isSearchResult={this.props.isSearchResult}
|
||||
mentionName={mentionName}
|
||||
onLongPress={this.props.onLongPress}
|
||||
onPostPress={this.props.onPostPress}
|
||||
navigator={this.props.navigator}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
renderChannelLink = ({context, channelName}) => {
|
||||
if (this.props.disableChannelLink) {
|
||||
|
|
@ -227,7 +222,7 @@ export default class Markdown extends PureComponent {
|
|||
channelName={channelName}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
renderEmoji = ({context, emojiName, literal}) => {
|
||||
return (
|
||||
|
|
@ -237,7 +232,7 @@ export default class Markdown extends PureComponent {
|
|||
textStyle={this.computeTextStyle(this.props.baseTextStyle, context)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
renderHashtag = ({context, hashtag}) => {
|
||||
if (this.props.disableHashtags) {
|
||||
|
|
@ -252,7 +247,7 @@ export default class Markdown extends PureComponent {
|
|||
navigator={this.props.navigator}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
renderParagraph = ({children, first}) => {
|
||||
if (!children || children.length === 0) {
|
||||
|
|
@ -271,7 +266,7 @@ export default class Markdown extends PureComponent {
|
|||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
renderHeading = ({children, level}) => {
|
||||
const containerStyle = [
|
||||
|
|
@ -286,7 +281,7 @@ export default class Markdown extends PureComponent {
|
|||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
renderCodeBlock = (props) => {
|
||||
// These sometimes include a trailing newline
|
||||
|
|
@ -298,10 +293,9 @@ export default class Markdown extends PureComponent {
|
|||
content={content}
|
||||
language={props.language}
|
||||
textStyle={this.props.textStyles.codeBlock}
|
||||
onLongPress={this.props.onLongPress}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
renderBlockQuote = ({children, ...otherProps}) => {
|
||||
return (
|
||||
|
|
@ -312,7 +306,7 @@ export default class Markdown extends PureComponent {
|
|||
{children}
|
||||
</MarkdownBlockQuote>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
renderList = ({children, start, tight, type}) => {
|
||||
return (
|
||||
|
|
@ -324,7 +318,7 @@ export default class Markdown extends PureComponent {
|
|||
{children}
|
||||
</MarkdownList>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
renderListItem = ({children, context, ...otherProps}) => {
|
||||
const level = context.filter((type) => type === 'list').length;
|
||||
|
|
@ -338,19 +332,19 @@ export default class Markdown extends PureComponent {
|
|||
{children}
|
||||
</MarkdownListItem>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
renderHardBreak = () => {
|
||||
return <Text>{'\n'}</Text>;
|
||||
}
|
||||
};
|
||||
|
||||
renderThematicBreak = () => {
|
||||
return <View style={this.props.blockStyles.horizontalRule}/>;
|
||||
}
|
||||
};
|
||||
|
||||
renderSoftBreak = () => {
|
||||
return <Text>{'\n'}</Text>;
|
||||
}
|
||||
};
|
||||
|
||||
renderHtml = (props) => {
|
||||
let rendered = this.renderText(props);
|
||||
|
|
@ -366,7 +360,7 @@ export default class Markdown extends PureComponent {
|
|||
}
|
||||
|
||||
return rendered;
|
||||
}
|
||||
};
|
||||
|
||||
renderTable = ({children}) => {
|
||||
return (
|
||||
|
|
@ -374,19 +368,18 @@ export default class Markdown extends PureComponent {
|
|||
{children}
|
||||
</MarkdownTable>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
renderLink = ({children, href}) => {
|
||||
return (
|
||||
<MarkdownLink
|
||||
href={href}
|
||||
onLongPress={this.props.onLongPress}
|
||||
onPermalinkPress={this.props.onPermalinkPress}
|
||||
>
|
||||
{children}
|
||||
</MarkdownLink>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
renderEditedIndicator = ({context}) => {
|
||||
let spacer = '';
|
||||
|
|
@ -411,7 +404,7 @@ export default class Markdown extends PureComponent {
|
|||
/>
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
let ast = this.parser.parse(this.props.value);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import {
|
|||
|
||||
import CustomPropTypes from 'app/constants/custom_prop_types';
|
||||
import FormattedText from 'app/components/formatted_text';
|
||||
import BottomSheet from 'app/utils/bottom_sheet';
|
||||
import {getDisplayNameForLanguage} from 'app/utils/markdown';
|
||||
import {preventDoubleTap} from 'app/utils/tap';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
|
||||
|
|
@ -28,7 +29,6 @@ export default class MarkdownCodeBlock extends React.PureComponent {
|
|||
language: PropTypes.string,
|
||||
content: PropTypes.string.isRequired,
|
||||
textStyle: CustomPropTypes.Style,
|
||||
onLongPress: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
|
|
@ -84,20 +84,23 @@ export default class MarkdownCodeBlock extends React.PureComponent {
|
|||
|
||||
const config = await mattermostManaged.getLocalConfig();
|
||||
|
||||
let action;
|
||||
if (config.copyAndPasteProtection !== 'true') {
|
||||
action = {
|
||||
text: formatMessage({id: 'mobile.markdown.code.copy_code', defaultMessage: 'Copy Code'}),
|
||||
onPress: this.handleCopyCode,
|
||||
};
|
||||
const cancelText = formatMessage({id: 'mobile.post.cancel', defaultMessage: 'Cancel'});
|
||||
const actionText = formatMessage({id: 'mobile.markdown.code.copy_code', defaultMessage: 'Copy Code'});
|
||||
BottomSheet.showBottomSheetWithOptions({
|
||||
options: [actionText, cancelText],
|
||||
cancelButtonIndex: 1,
|
||||
}, (value) => {
|
||||
if (value !== 1) {
|
||||
this.handleCopyCode();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.props.onLongPress(action);
|
||||
}
|
||||
};
|
||||
|
||||
handleCopyCode = () => {
|
||||
Clipboard.setString(this.props.content);
|
||||
}
|
||||
};
|
||||
|
||||
trimContent = (content) => {
|
||||
const lines = content.split('\n');
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import FormattedText from 'app/components/formatted_text';
|
|||
import ProgressiveImage from 'app/components/progressive_image';
|
||||
import CustomPropTypes from 'app/constants/custom_prop_types';
|
||||
import mattermostManaged from 'app/mattermost_managed';
|
||||
import BottomSheet from 'app/utils/bottom_sheet';
|
||||
import ImageCacheManager from 'app/utils/image_cache_manager';
|
||||
import {previewImageAtIndex, calculateDimensions} from 'app/utils/images';
|
||||
import {normalizeProtocol} from 'app/utils/url';
|
||||
|
|
@ -38,7 +39,6 @@ export default class MarkdownImage extends React.Component {
|
|||
linkDestination: PropTypes.string,
|
||||
isReplyPost: PropTypes.bool,
|
||||
navigator: PropTypes.object.isRequired,
|
||||
onLongPress: PropTypes.func,
|
||||
serverURL: PropTypes.string.isRequired,
|
||||
source: PropTypes.string.isRequired,
|
||||
errorTextStyle: CustomPropTypes.Style,
|
||||
|
|
@ -138,15 +138,18 @@ export default class MarkdownImage extends React.Component {
|
|||
|
||||
const config = await mattermostManaged.getLocalConfig();
|
||||
|
||||
let action;
|
||||
if (config.copyAndPasteProtection !== 'true') {
|
||||
action = {
|
||||
text: formatMessage({id: 'mobile.markdown.link.copy_url', defaultMessage: 'Copy URL'}),
|
||||
onPress: this.handleLinkCopy,
|
||||
};
|
||||
const cancelText = formatMessage({id: 'mobile.post.cancel', defaultMessage: 'Cancel'});
|
||||
const actionText = formatMessage({id: 'mobile.markdown.link.copy_url', defaultMessage: 'Copy URL'});
|
||||
BottomSheet.showBottomSheetWithOptions({
|
||||
options: [actionText, cancelText],
|
||||
cancelButtonIndex: 1,
|
||||
}, (value) => {
|
||||
if (value !== 1) {
|
||||
this.handleLinkCopy();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.props.onLongPress(action);
|
||||
};
|
||||
|
||||
handleLinkCopy = () => {
|
||||
|
|
|
|||
|
|
@ -9,24 +9,22 @@ import {intlShape} from 'react-intl';
|
|||
|
||||
import CustomPropTypes from 'app/constants/custom_prop_types';
|
||||
import mattermostManaged from 'app/mattermost_managed';
|
||||
|
||||
import Config from 'assets/config';
|
||||
|
||||
import BottomSheet from 'app/utils/bottom_sheet';
|
||||
import {preventDoubleTap} from 'app/utils/tap';
|
||||
import {matchPermalink, normalizeProtocol} from 'app/utils/url';
|
||||
|
||||
import Config from 'assets/config';
|
||||
|
||||
export default class MarkdownLink extends PureComponent {
|
||||
static propTypes = {
|
||||
children: CustomPropTypes.Children.isRequired,
|
||||
href: PropTypes.string.isRequired,
|
||||
onLongPress: PropTypes.func,
|
||||
onPermalinkPress: PropTypes.func,
|
||||
serverURL: PropTypes.string.isRequired,
|
||||
siteURL: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
onLongPress: () => true,
|
||||
onPermalinkPress: () => true,
|
||||
};
|
||||
|
||||
|
|
@ -89,27 +87,30 @@ export default class MarkdownLink extends PureComponent {
|
|||
...otherChildProps,
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
handleLongPress = async () => {
|
||||
const {formatMessage} = this.context.intl;
|
||||
|
||||
const config = await mattermostManaged.getLocalConfig();
|
||||
|
||||
let action;
|
||||
if (config.copyAndPasteProtection !== 'true') {
|
||||
action = {
|
||||
text: formatMessage({id: 'mobile.markdown.link.copy_url', defaultMessage: 'Copy URL'}),
|
||||
onPress: this.handleCopyURL,
|
||||
};
|
||||
const cancelText = formatMessage({id: 'mobile.post.cancel', defaultMessage: 'Cancel'});
|
||||
const actionText = formatMessage({id: 'mobile.markdown.link.copy_url', defaultMessage: 'Copy URL'});
|
||||
BottomSheet.showBottomSheetWithOptions({
|
||||
options: [actionText, cancelText],
|
||||
cancelButtonIndex: 1,
|
||||
}, (value) => {
|
||||
if (value !== 1) {
|
||||
this.handleLinkCopy();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.props.onLongPress(action);
|
||||
}
|
||||
};
|
||||
|
||||
handleCopyURL = () => {
|
||||
Clipboard.setString(this.props.href);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const children = Config.ExperimentalNormalizeMarkdownLinks ? this.parseChildren() : this.props.children;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ export default class MessageAttachments extends PureComponent {
|
|||
postId: PropTypes.string.isRequired,
|
||||
navigator: PropTypes.object.isRequired,
|
||||
onHashtagPress: PropTypes.func,
|
||||
onLongPress: PropTypes.func.isRequired,
|
||||
onPermalinkPress: PropTypes.func,
|
||||
theme: PropTypes.object,
|
||||
textStyles: PropTypes.object,
|
||||
|
|
@ -30,7 +29,6 @@ export default class MessageAttachments extends PureComponent {
|
|||
blockStyles,
|
||||
navigator,
|
||||
onHashtagPress,
|
||||
onLongPress,
|
||||
onPermalinkPress,
|
||||
postId,
|
||||
theme,
|
||||
|
|
@ -47,7 +45,6 @@ export default class MessageAttachments extends PureComponent {
|
|||
key={'att_' + i}
|
||||
navigator={navigator}
|
||||
onHashtagPress={onHashtagPress}
|
||||
onLongPress={onLongPress}
|
||||
onPermalinkPress={onPermalinkPress}
|
||||
postId={postId}
|
||||
theme={theme}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@ export default class MessageAttachment extends PureComponent {
|
|||
blockStyles: PropTypes.object,
|
||||
navigator: PropTypes.object.isRequired,
|
||||
postId: PropTypes.string.isRequired,
|
||||
onLongPress: PropTypes.func.isRequired,
|
||||
onPermalinkPress: PropTypes.func,
|
||||
theme: PropTypes.object,
|
||||
textStyles: PropTypes.object,
|
||||
|
|
@ -194,7 +193,6 @@ export default class MessageAttachment extends PureComponent {
|
|||
blockStyles={blockStyles}
|
||||
value={(field.value || '')}
|
||||
navigator={navigator}
|
||||
onLongPress={this.props.onLongPress}
|
||||
onPermalinkPress={onPermalinkPress}
|
||||
/>
|
||||
</View>
|
||||
|
|
@ -317,7 +315,6 @@ export default class MessageAttachment extends PureComponent {
|
|||
blockStyles={blockStyles}
|
||||
value={attachment.pretext}
|
||||
navigator={navigator}
|
||||
onLongPress={this.props.onLongPress}
|
||||
onPermalinkPress={onPermalinkPress}
|
||||
/>
|
||||
</View>
|
||||
|
|
@ -415,7 +412,6 @@ export default class MessageAttachment extends PureComponent {
|
|||
blockStyles={blockStyles}
|
||||
value={attachment.text}
|
||||
navigator={navigator}
|
||||
onLongPress={this.props.onLongPress}
|
||||
onPermalinkPress={onPermalinkPress}
|
||||
/>
|
||||
</View>
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// Used to leverage the platform specific components
|
||||
import OptionsContext from './options_context';
|
||||
export default OptionsContext;
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React, {PureComponent} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {TouchableHighlight, View} from 'react-native';
|
||||
import RNBottomSheet from 'react-native-bottom-sheet';
|
||||
|
||||
export default class OptionsContext extends PureComponent {
|
||||
static propTypes = {
|
||||
getPostActions: PropTypes.func,
|
||||
cancelText: PropTypes.string,
|
||||
children: PropTypes.node.isRequired,
|
||||
onPress: PropTypes.func.isRequired,
|
||||
toggleSelected: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
getPostActions: () => [],
|
||||
cancelText: 'Cancel',
|
||||
};
|
||||
|
||||
show = (additionalAction) => {
|
||||
const {getPostActions, cancelText} = this.props;
|
||||
const nextActions = getPostActions();
|
||||
if (additionalAction && !additionalAction.nativeEvent && additionalAction.text) {
|
||||
const copyPostIndex = nextActions.findIndex((action) => action.copyPost);
|
||||
nextActions.splice(copyPostIndex + 1, 0, additionalAction);
|
||||
}
|
||||
|
||||
if (nextActions.length) {
|
||||
const actionsText = nextActions.map((a) => a.text);
|
||||
RNBottomSheet.showBottomSheetWithOptions({
|
||||
options: [...actionsText, cancelText],
|
||||
cancelButtonIndex: nextActions.length,
|
||||
}, (value) => {
|
||||
if (value !== nextActions.length) {
|
||||
const selectedOption = nextActions[value];
|
||||
if (selectedOption && selectedOption.onPress) {
|
||||
selectedOption.onPress();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
handleHideUnderlay = () => {
|
||||
this.props.toggleSelected(false, this.props.getPostActions().length > 0);
|
||||
};
|
||||
|
||||
handleShowUnderlay = () => {
|
||||
this.props.toggleSelected(true, this.props.getPostActions().length > 0);
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<TouchableHighlight
|
||||
onHideUnderlay={this.handleHideUnderlay}
|
||||
onLongPress={this.show}
|
||||
onPress={this.props.onPress}
|
||||
onShowUnderlay={this.handleShowUnderlay}
|
||||
underlayColor='transparent'
|
||||
style={{flex: 1, flexDirection: 'row'}}
|
||||
>
|
||||
<View style={{flex: 1}}>
|
||||
{this.props.children}
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,108 +0,0 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React, {PureComponent} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import ToolTip from 'app/components/tooltip';
|
||||
|
||||
export default class OptionsContext extends PureComponent {
|
||||
static propTypes = {
|
||||
getPostActions: PropTypes.func,
|
||||
children: PropTypes.node.isRequired,
|
||||
onPress: PropTypes.func.isRequired,
|
||||
toggleSelected: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
getPostActions: () => [],
|
||||
additionalActions: [],
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
actions: props.getPostActions(),
|
||||
};
|
||||
}
|
||||
|
||||
beforeShow = (additionalAction) => {
|
||||
const nextActions = this.props.getPostActions();
|
||||
if (additionalAction && additionalAction.text && !additionalAction.nativeEvent) {
|
||||
const copyPostIndex = nextActions.findIndex((action) => action.copyPost);
|
||||
nextActions.splice(copyPostIndex + 1, 0, additionalAction);
|
||||
}
|
||||
|
||||
this.setState({
|
||||
actions: nextActions,
|
||||
});
|
||||
};
|
||||
|
||||
handleHide = () => {
|
||||
this.isShowing = false;
|
||||
this.props.toggleSelected(false);
|
||||
};
|
||||
|
||||
handleHideUnderlay = () => {
|
||||
if (!this.isShowing) {
|
||||
this.props.toggleSelected(false);
|
||||
}
|
||||
};
|
||||
|
||||
handleShow = () => {
|
||||
this.isShowing = true;
|
||||
this.props.toggleSelected(true);
|
||||
}
|
||||
|
||||
handleShowUnderlay = () => {
|
||||
this.beforeShow();
|
||||
this.props.toggleSelected(true);
|
||||
};
|
||||
|
||||
hide = () => {
|
||||
this.setState({
|
||||
actions: this.props.getPostActions(),
|
||||
});
|
||||
|
||||
if (this.refs.toolTip) {
|
||||
this.refs.toolTip.hideMenu();
|
||||
}
|
||||
|
||||
this.isShowing = false;
|
||||
this.props.toggleSelected(false);
|
||||
};
|
||||
|
||||
handlePress = () => {
|
||||
this.props.toggleSelected(false);
|
||||
this.props.onPress();
|
||||
};
|
||||
|
||||
show = (additionalAction) => {
|
||||
this.props.toggleSelected(true);
|
||||
this.beforeShow(additionalAction);
|
||||
|
||||
if (this.refs.toolTip) {
|
||||
this.refs.toolTip.showMenu();
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<ToolTip
|
||||
onHideUnderlay={this.handleHideUnderlay}
|
||||
onShowUnderlay={this.handleShowUnderlay}
|
||||
ref='toolTip'
|
||||
actions={this.state.actions}
|
||||
arrowDirection='down'
|
||||
longPress={true}
|
||||
onHide={this.handleHide}
|
||||
onShow={this.handleShow}
|
||||
onPress={this.handlePress}
|
||||
underlayColor='transparent'
|
||||
>
|
||||
{this.props.children}
|
||||
</ToolTip>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -4,19 +4,15 @@
|
|||
import {connect} from 'react-redux';
|
||||
import {bindActionCreators} from 'redux';
|
||||
|
||||
import {createPost, deletePost, removePost} from 'mattermost-redux/actions/posts';
|
||||
import {General, Posts} from 'mattermost-redux/constants';
|
||||
import {getCurrentChannelId, isCurrentChannelReadOnly} from 'mattermost-redux/selectors/entities/channels';
|
||||
import {createPost, removePost} from 'mattermost-redux/actions/posts';
|
||||
import {Posts} from 'mattermost-redux/constants';
|
||||
import {isCurrentChannelReadOnly} from 'mattermost-redux/selectors/entities/channels';
|
||||
import {getPost, makeGetCommentCountForPost} from 'mattermost-redux/selectors/entities/posts';
|
||||
import {getCurrentUserId, getCurrentUserRoles} from 'mattermost-redux/selectors/entities/users';
|
||||
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
|
||||
import {getMyPreferences, getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {getCurrentTeamUrl, getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
|
||||
import {canDeletePost, canEditPost, isPostFlagged, isSystemMessage} from 'mattermost-redux/utils/post_utils';
|
||||
import {isAdmin as checkIsAdmin, isSystemAdmin as checkIsSystemAdmin} from 'mattermost-redux/utils/user_utils';
|
||||
import {getConfig, getLicense} from 'mattermost-redux/selectors/entities/general';
|
||||
import {isPostFlagged, isSystemMessage} from 'mattermost-redux/utils/post_utils';
|
||||
|
||||
import {insertToDraft, setPostTooltipVisible} from 'app/actions/views/channel';
|
||||
import {addReaction} from 'app/actions/views/emoji';
|
||||
|
||||
import Post from './post';
|
||||
|
||||
|
|
@ -45,13 +41,8 @@ function makeMapStateToProps() {
|
|||
const getCommentCountForPost = makeGetCommentCountForPost();
|
||||
return function mapStateToProps(state, ownProps) {
|
||||
const post = getPost(state, ownProps.postId);
|
||||
const config = getConfig(state);
|
||||
const license = getLicense(state);
|
||||
const roles = getCurrentUserId(state) ? getCurrentUserRoles(state) : '';
|
||||
const myPreferences = getMyPreferences(state);
|
||||
const currentUserId = getCurrentUserId(state);
|
||||
const currentTeamId = getCurrentTeamId(state);
|
||||
const currentChannelId = getCurrentChannelId(state);
|
||||
|
||||
let isFirstReply = true;
|
||||
let isLastReply = true;
|
||||
|
|
@ -78,28 +69,8 @@ function makeMapStateToProps() {
|
|||
}
|
||||
}
|
||||
|
||||
const isAdmin = checkIsAdmin(roles);
|
||||
const isSystemAdmin = checkIsSystemAdmin(roles);
|
||||
|
||||
let canDelete = false;
|
||||
let canEdit = false;
|
||||
let canEditUntil = -1;
|
||||
if (post) {
|
||||
canDelete = canDeletePost(state, config, license, currentTeamId, currentChannelId, currentUserId, post, isAdmin, isSystemAdmin);
|
||||
canEdit = canEditPost(state, config, license, currentTeamId, currentChannelId, currentUserId, post);
|
||||
if (canEdit && license.IsLicensed === 'true' &&
|
||||
(config.AllowEditPost === General.ALLOW_EDIT_POST_TIME_LIMIT || (config.PostEditTimeLimit !== -1 && config.PostEditTimeLimit !== '-1'))
|
||||
) {
|
||||
canEditUntil = post.create_at + (config.PostEditTimeLimit * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
channelIsReadOnly: isCurrentChannelReadOnly(state),
|
||||
canDelete,
|
||||
canEdit,
|
||||
canEditUntil,
|
||||
currentTeamUrl: getCurrentTeamUrl(state),
|
||||
currentUserId,
|
||||
post,
|
||||
isFirstReply,
|
||||
|
|
@ -116,9 +87,7 @@ function makeMapStateToProps() {
|
|||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators({
|
||||
addReaction,
|
||||
createPost,
|
||||
deletePost,
|
||||
removePost,
|
||||
setPostTooltipVisible,
|
||||
insertToDraft,
|
||||
|
|
|
|||
|
|
@ -4,15 +4,12 @@
|
|||
import React, {PureComponent} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
Alert,
|
||||
Clipboard,
|
||||
Platform,
|
||||
TouchableHighlight,
|
||||
View,
|
||||
ViewPropTypes,
|
||||
} from 'react-native';
|
||||
import {intlShape} from 'react-intl';
|
||||
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
|
||||
|
||||
import FlagIcon from 'app/components/flag_icon';
|
||||
import PostBody from 'app/components/post_body';
|
||||
|
|
@ -22,7 +19,6 @@ import {NavigationTypes} from 'app/constants';
|
|||
import {fromAutoResponder} from 'app/utils/general';
|
||||
import {preventDoubleTap} from 'app/utils/tap';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
|
||||
import {getToolTipVisible} from 'app/utils/tooltip';
|
||||
import {t} from 'app/utils/i18n';
|
||||
|
||||
import {Posts} from 'mattermost-redux/constants';
|
||||
|
|
@ -34,14 +30,11 @@ import Config from 'assets/config';
|
|||
export default class Post extends PureComponent {
|
||||
static propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
addReaction: PropTypes.func.isRequired,
|
||||
createPost: PropTypes.func.isRequired,
|
||||
deletePost: PropTypes.func.isRequired,
|
||||
insertToDraft: PropTypes.func.isRequired,
|
||||
removePost: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
channelIsReadOnly: PropTypes.bool,
|
||||
currentTeamUrl: PropTypes.string.isRequired,
|
||||
currentUserId: PropTypes.string.isRequired,
|
||||
highlight: PropTypes.bool,
|
||||
style: ViewPropTypes.style,
|
||||
|
|
@ -56,9 +49,6 @@ export default class Post extends PureComponent {
|
|||
commentedOnPost: PropTypes.object,
|
||||
managedConfig: PropTypes.object.isRequired,
|
||||
navigator: PropTypes.object,
|
||||
canEdit: PropTypes.bool.isRequired,
|
||||
canEditUntil: PropTypes.number.isRequired,
|
||||
canDelete: PropTypes.bool.isRequired,
|
||||
onHashtagPress: PropTypes.func,
|
||||
onPermalinkPress: PropTypes.func,
|
||||
shouldRenderReplyButton: PropTypes.bool,
|
||||
|
|
@ -112,83 +102,6 @@ export default class Post extends PureComponent {
|
|||
this.props.actions.insertToDraft(`@${username} `);
|
||||
};
|
||||
|
||||
handlePostDelete = () => {
|
||||
const {formatMessage} = this.context.intl;
|
||||
const {actions, currentUserId, post} = this.props;
|
||||
|
||||
Alert.alert(
|
||||
formatMessage({id: 'mobile.post.delete_title', defaultMessage: 'Delete Post'}),
|
||||
formatMessage({
|
||||
id: 'mobile.post.delete_question',
|
||||
defaultMessage: 'Are you sure you want to delete this post?',
|
||||
}),
|
||||
[{
|
||||
text: formatMessage({id: 'mobile.post.cancel', defaultMessage: 'Cancel'}),
|
||||
style: 'cancel',
|
||||
}, {
|
||||
text: formatMessage({id: 'post_info.del', defaultMessage: 'Delete'}),
|
||||
style: 'destructive',
|
||||
onPress: () => {
|
||||
actions.deletePost(post);
|
||||
if (post.user_id === currentUserId) {
|
||||
actions.removePost(post);
|
||||
}
|
||||
},
|
||||
}]
|
||||
);
|
||||
};
|
||||
|
||||
handlePostEdit = () => {
|
||||
const {intl} = this.context;
|
||||
const {navigator, post, theme} = this.props;
|
||||
MaterialIcon.getImageSource('close', 20, theme.sidebarHeaderTextColor).then((source) => {
|
||||
navigator.showModal({
|
||||
screen: 'EditPost',
|
||||
title: intl.formatMessage({id: 'mobile.edit_post.title', defaultMessage: 'Editing Message'}),
|
||||
animated: true,
|
||||
navigatorStyle: {
|
||||
navBarTextColor: theme.sidebarHeaderTextColor,
|
||||
navBarBackgroundColor: theme.sidebarHeaderBg,
|
||||
navBarButtonColor: theme.sidebarHeaderTextColor,
|
||||
screenBackgroundColor: theme.centerChannelBg,
|
||||
},
|
||||
passProps: {
|
||||
post,
|
||||
closeButton: source,
|
||||
},
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
handleAddReactionToPost = (emoji) => {
|
||||
const {post} = this.props;
|
||||
this.props.actions.addReaction(post.id, emoji);
|
||||
};
|
||||
|
||||
handleAddReaction = preventDoubleTap(() => {
|
||||
const {intl} = this.context;
|
||||
const {navigator, post, theme} = this.props;
|
||||
|
||||
MaterialIcon.getImageSource('close', 20, theme.sidebarHeaderTextColor).then((source) => {
|
||||
navigator.showModal({
|
||||
screen: 'AddReaction',
|
||||
title: intl.formatMessage({id: 'mobile.post_info.add_reaction', defaultMessage: 'Add Reaction'}),
|
||||
animated: true,
|
||||
navigatorStyle: {
|
||||
navBarTextColor: theme.sidebarHeaderTextColor,
|
||||
navBarBackgroundColor: theme.sidebarHeaderBg,
|
||||
navBarButtonColor: theme.sidebarHeaderTextColor,
|
||||
screenBackgroundColor: theme.centerChannelBg,
|
||||
},
|
||||
passProps: {
|
||||
post,
|
||||
closeButton: source,
|
||||
onEmojiPress: this.handleAddReactionToPost,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
handleFailedPostPress = () => {
|
||||
const options = {
|
||||
title: {
|
||||
|
|
@ -246,22 +159,17 @@ export default class Post extends PureComponent {
|
|||
showLongPost,
|
||||
} = this.props;
|
||||
|
||||
if (!getToolTipVisible()) {
|
||||
const isValidSystemMessage = fromAutoResponder(post) || !isSystemMessage(post);
|
||||
if (onPress && post.state !== Posts.POST_DELETED && isValidSystemMessage && !isPostPendingOrFailed(post)) {
|
||||
onPress(post);
|
||||
} else if ((isPostEphemeral(post) || post.state === Posts.POST_DELETED) && !showLongPost) {
|
||||
this.onRemovePost(post);
|
||||
}
|
||||
} else if (this.refs.postBody) {
|
||||
this.refs.postBody.getWrappedInstance().hideOptionsContext();
|
||||
this.handleHideUnderlay();
|
||||
const isValidSystemMessage = fromAutoResponder(post) || !isSystemMessage(post);
|
||||
if (onPress && post.state !== Posts.POST_DELETED && isValidSystemMessage && !isPostPendingOrFailed(post)) {
|
||||
onPress(post);
|
||||
} else if ((isPostEphemeral(post) || post.state === Posts.POST_DELETED) && !showLongPost) {
|
||||
this.onRemovePost(post);
|
||||
}
|
||||
});
|
||||
|
||||
handleReply = preventDoubleTap(() => {
|
||||
const {post, onReply} = this.props;
|
||||
if (!getToolTipVisible() && onReply) {
|
||||
if (onReply) {
|
||||
return onReply(post);
|
||||
}
|
||||
|
||||
|
|
@ -305,31 +213,13 @@ export default class Post extends PureComponent {
|
|||
};
|
||||
|
||||
viewUserProfile = preventDoubleTap(() => {
|
||||
if (!getToolTipVisible()) {
|
||||
this.goToUserProfile();
|
||||
}
|
||||
this.goToUserProfile();
|
||||
});
|
||||
|
||||
toggleSelected = (selected) => {
|
||||
this.setState({selected});
|
||||
};
|
||||
|
||||
handleCopyText = (text) => {
|
||||
let textToCopy = this.props.post.message;
|
||||
if (typeof text === 'string') {
|
||||
textToCopy = text;
|
||||
}
|
||||
|
||||
Clipboard.setString(textToCopy);
|
||||
};
|
||||
|
||||
handleCopyPermalink = () => {
|
||||
const {currentTeamUrl, postId} = this.props;
|
||||
const permalink = `${currentTeamUrl}/pl/${postId}`;
|
||||
|
||||
Clipboard.setString(permalink);
|
||||
};
|
||||
|
||||
handleHideUnderlay = () => {
|
||||
this.toggleSelected(false);
|
||||
};
|
||||
|
|
@ -338,9 +228,9 @@ export default class Post extends PureComponent {
|
|||
this.toggleSelected(true);
|
||||
};
|
||||
|
||||
showOptionsContext = () => {
|
||||
showPostOptions = () => {
|
||||
if (this.refs.postBody) {
|
||||
this.refs.postBody.getWrappedInstance().showOptionsContext();
|
||||
this.refs.postBody.getWrappedInstance().showPostOptions();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -405,7 +295,7 @@ export default class Post extends PureComponent {
|
|||
onPress={this.handlePress}
|
||||
onHideUnderlay={this.handleHideUnderlay}
|
||||
onShowUnderlay={this.handleShowUnderlay}
|
||||
onLongPress={this.showOptionsContext}
|
||||
onLongPress={this.showPostOptions}
|
||||
underlayColor='transparent'
|
||||
>
|
||||
<PostProfilePicture
|
||||
|
|
@ -440,21 +330,13 @@ export default class Post extends PureComponent {
|
|||
{postHeader}
|
||||
<PostBody
|
||||
ref={'postBody'}
|
||||
canDelete={this.props.canDelete}
|
||||
canEdit={this.props.canEdit}
|
||||
canEditUntil={this.props.canEditUntil}
|
||||
highlight={highlight}
|
||||
channelIsReadOnly={channelIsReadOnly}
|
||||
isSearchResult={isSearchResult}
|
||||
navigator={this.props.navigator}
|
||||
onAddReaction={this.handleAddReaction}
|
||||
onCopyPermalink={this.handleCopyPermalink}
|
||||
onCopyText={this.handleCopyText}
|
||||
onFailedPostPress={this.handleFailedPostPress}
|
||||
onHashtagPress={onHashtagPress}
|
||||
onPermalinkPress={onPermalinkPress}
|
||||
onPostDelete={this.handlePostDelete}
|
||||
onPostEdit={this.handlePostEdit}
|
||||
onPress={this.handlePress}
|
||||
postId={post.id}
|
||||
replyBarStyle={replyBarStyle}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ export default class PostAddChannelMember extends React.PureComponent {
|
|||
userIds: PropTypes.array.isRequired,
|
||||
usernames: PropTypes.array.isRequired,
|
||||
navigator: PropTypes.object.isRequired,
|
||||
onLongPress: PropTypes.func,
|
||||
onPostPress: PropTypes.func,
|
||||
textStyles: PropTypes.object,
|
||||
};
|
||||
|
|
@ -85,7 +84,6 @@ export default class PostAddChannelMember extends React.PureComponent {
|
|||
<AtMention
|
||||
mentionStyle={this.props.textStyles.mention}
|
||||
mentionName={usernames[0]}
|
||||
onLongPress={this.props.onLongPress}
|
||||
onPostPress={this.props.onPostPress}
|
||||
navigator={this.props.navigator}
|
||||
/>
|
||||
|
|
@ -114,7 +112,6 @@ export default class PostAddChannelMember extends React.PureComponent {
|
|||
key={username}
|
||||
mentionStyle={this.props.textStyles.mention}
|
||||
mentionName={username}
|
||||
onLongPress={this.props.onLongPress}
|
||||
onPostPress={this.props.onPostPress}
|
||||
navigator={this.props.navigator}
|
||||
/>
|
||||
|
|
@ -192,4 +189,4 @@ export default class PostAddChannelMember extends React.PureComponent {
|
|||
</Text>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,27 +2,19 @@
|
|||
// See LICENSE.txt for license information.
|
||||
|
||||
import {connect} from 'react-redux';
|
||||
import {bindActionCreators} from 'redux';
|
||||
|
||||
import {flagPost, unflagPost} from 'mattermost-redux/actions/posts';
|
||||
import {
|
||||
General,
|
||||
Posts,
|
||||
} from 'mattermost-redux/constants';
|
||||
import {General, Posts} from 'mattermost-redux/constants';
|
||||
import {getChannel, canManageChannelMembers, getCurrentChannelId} from 'mattermost-redux/selectors/entities/channels';
|
||||
import {getPost} from 'mattermost-redux/selectors/entities/posts';
|
||||
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {hasNewPermissions, getConfig, getLicense} from 'mattermost-redux/selectors/entities/general';
|
||||
import {haveIChannelPermission} from 'mattermost-redux/selectors/entities/roles';
|
||||
import {getConfig, getLicense} from 'mattermost-redux/selectors/entities/general';
|
||||
import {getCurrentUserId, getCurrentUserRoles} from 'mattermost-redux/selectors/entities/users';
|
||||
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
|
||||
import Permissions from 'mattermost-redux/constants/permissions';
|
||||
|
||||
import {
|
||||
isEdited,
|
||||
isPostEphemeral,
|
||||
isSystemMessage,
|
||||
canEditPost,
|
||||
canDeletePost,
|
||||
} from 'mattermost-redux/utils/post_utils';
|
||||
import {isAdmin as checkIsAdmin, isSystemAdmin as checkIsSystemAdmin} from 'mattermost-redux/utils/user_utils';
|
||||
|
|
@ -34,19 +26,6 @@ const POST_TIMEOUT = 20000;
|
|||
function mapStateToProps(state, ownProps) {
|
||||
const post = getPost(state, ownProps.postId) || {};
|
||||
const channel = getChannel(state, post.channel_id) || {};
|
||||
const channelIsArchived = channel ? channel.delete_at !== 0 : false;
|
||||
const teamId = channel.team_id;
|
||||
|
||||
let canAddReaction = true;
|
||||
if (channelIsArchived) {
|
||||
canAddReaction = false;
|
||||
} else if (hasNewPermissions(state)) {
|
||||
canAddReaction = haveIChannelPermission(state, {
|
||||
team: teamId,
|
||||
channel: post.channel_id,
|
||||
permission: Permissions.ADD_REACTION,
|
||||
});
|
||||
}
|
||||
|
||||
let isFailed = post.failed;
|
||||
let isPending = post.id === post.pending_post_id;
|
||||
|
|
@ -69,12 +48,9 @@ function mapStateToProps(state, ownProps) {
|
|||
const isAdmin = checkIsAdmin(roles);
|
||||
const isSystemAdmin = checkIsSystemAdmin(roles);
|
||||
let canDelete = false;
|
||||
let canEdit = false;
|
||||
if (post) {
|
||||
if (!channelIsArchived) {
|
||||
canDelete = canDeletePost(state, config, license, currentTeamId, currentChannelId, currentUserId, post, isAdmin, isSystemAdmin);
|
||||
canEdit = canEditPost(state, config, license, currentTeamId, currentChannelId, currentUserId, post);
|
||||
}
|
||||
|
||||
if (post && !ownProps.channelIsArchived) {
|
||||
canDelete = canDeletePost(state, config, license, currentTeamId, currentChannelId, currentUserId, post, isAdmin, isSystemAdmin);
|
||||
}
|
||||
|
||||
let isPostAddChannelMember = false;
|
||||
|
|
@ -103,19 +79,8 @@ function mapStateToProps(state, ownProps) {
|
|||
isSystemMessage: isSystemMessage(post),
|
||||
message: post.message,
|
||||
theme: getTheme(state),
|
||||
canAddReaction,
|
||||
canDelete,
|
||||
canEdit,
|
||||
};
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators({
|
||||
flagPost,
|
||||
unflagPost,
|
||||
}, dispatch),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps, null, {withRef: true})(PostBody);
|
||||
export default connect(mapStateToProps, null, null, {withRef: true})(PostBody);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import React, {PureComponent} from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
Dimensions,
|
||||
Platform,
|
||||
TouchableHighlight,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
|
|
@ -18,7 +17,6 @@ import {Posts} from 'mattermost-redux/constants';
|
|||
import CombinedSystemMessage from 'app/components/combined_system_message';
|
||||
import FormattedText from 'app/components/formatted_text';
|
||||
import Markdown from 'app/components/markdown';
|
||||
import OptionsContext from 'app/components/options_context';
|
||||
import ShowMoreButton from 'app/components/show_more_button';
|
||||
|
||||
import {emptyFunction} from 'app/utils/general';
|
||||
|
|
@ -33,14 +31,7 @@ let Reactions;
|
|||
|
||||
export default class PostBody extends PureComponent {
|
||||
static propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
flagPost: PropTypes.func.isRequired,
|
||||
unflagPost: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
canAddReaction: PropTypes.bool,
|
||||
canDelete: PropTypes.bool,
|
||||
canEdit: PropTypes.bool,
|
||||
canEditUntil: PropTypes.number.isRequired,
|
||||
channelIsReadOnly: PropTypes.bool.isRequired,
|
||||
fileIds: PropTypes.array,
|
||||
hasBeenDeleted: PropTypes.bool,
|
||||
|
|
@ -58,14 +49,9 @@ export default class PostBody extends PureComponent {
|
|||
managedConfig: PropTypes.object,
|
||||
message: PropTypes.string,
|
||||
navigator: PropTypes.object.isRequired,
|
||||
onAddReaction: PropTypes.func,
|
||||
onCopyPermalink: PropTypes.func,
|
||||
onCopyText: PropTypes.func,
|
||||
onFailedPostPress: PropTypes.func,
|
||||
onHashtagPress: PropTypes.func,
|
||||
onPermalinkPress: PropTypes.func,
|
||||
onPostDelete: PropTypes.func,
|
||||
onPostEdit: PropTypes.func,
|
||||
onPress: PropTypes.func,
|
||||
postId: PropTypes.string.isRequired,
|
||||
postProps: PropTypes.object,
|
||||
|
|
@ -79,12 +65,7 @@ export default class PostBody extends PureComponent {
|
|||
|
||||
static defaultProps = {
|
||||
fileIds: [],
|
||||
onAddReaction: emptyFunction,
|
||||
onCopyPermalink: emptyFunction,
|
||||
onCopyText: emptyFunction,
|
||||
onFailedPostPress: emptyFunction,
|
||||
onPostDelete: emptyFunction,
|
||||
onPostEdit: emptyFunction,
|
||||
onPress: emptyFunction,
|
||||
replyBarStyle: [],
|
||||
toggleSelected: emptyFunction,
|
||||
|
|
@ -98,11 +79,6 @@ export default class PostBody extends PureComponent {
|
|||
isLongPost: false,
|
||||
};
|
||||
|
||||
flagPost = () => {
|
||||
const {actions, postId} = this.props;
|
||||
actions.flagPost(postId);
|
||||
};
|
||||
|
||||
handleHideUnderlay = () => {
|
||||
this.props.toggleSelected(false);
|
||||
};
|
||||
|
|
@ -111,84 +87,6 @@ export default class PostBody extends PureComponent {
|
|||
this.props.toggleSelected(true);
|
||||
};
|
||||
|
||||
hideOptionsContext = () => {
|
||||
if (Platform.OS === 'ios' && this.refs.options) {
|
||||
this.refs.options.hide();
|
||||
}
|
||||
};
|
||||
|
||||
getPostActions = () => {
|
||||
const {formatMessage} = this.context.intl;
|
||||
const {
|
||||
canEdit,
|
||||
canEditUntil,
|
||||
canDelete,
|
||||
canAddReaction,
|
||||
channelIsReadOnly,
|
||||
hasBeenDeleted,
|
||||
isPending,
|
||||
isFailed,
|
||||
isFlagged,
|
||||
isPostEphemeral,
|
||||
isSystemMessage,
|
||||
managedConfig,
|
||||
message,
|
||||
onCopyText,
|
||||
onPostDelete,
|
||||
onPostEdit,
|
||||
showAddReaction,
|
||||
} = this.props;
|
||||
const actions = [];
|
||||
const isPendingOrFailedPost = isPending || isFailed;
|
||||
|
||||
// we should check for the user roles and permissions
|
||||
if (!isPendingOrFailedPost && !isSystemMessage && !isPostEphemeral) {
|
||||
if (showAddReaction && canAddReaction && !channelIsReadOnly) {
|
||||
actions.push({
|
||||
text: formatMessage({id: 'mobile.post_info.add_reaction', defaultMessage: 'Add Reaction'}),
|
||||
onPress: this.props.onAddReaction,
|
||||
});
|
||||
}
|
||||
|
||||
if (managedConfig.copyAndPasteProtection !== 'true' && message) {
|
||||
actions.push({
|
||||
text: formatMessage({id: 'mobile.post_info.copy_post', defaultMessage: 'Copy Post'}),
|
||||
onPress: onCopyText,
|
||||
copyPost: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (!channelIsReadOnly) {
|
||||
if (isFlagged) {
|
||||
actions.push({
|
||||
text: formatMessage({id: 'post_info.mobile.unflag', defaultMessage: 'Unflag'}),
|
||||
onPress: this.unflagPost,
|
||||
});
|
||||
} else {
|
||||
actions.push({
|
||||
text: formatMessage({id: 'post_info.mobile.flag', defaultMessage: 'Flag'}),
|
||||
onPress: this.flagPost,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (canEdit && (canEditUntil === -1 || canEditUntil > Date.now())) {
|
||||
actions.push({text: formatMessage({id: 'post_info.edit', defaultMessage: 'Edit'}), onPress: onPostEdit});
|
||||
}
|
||||
|
||||
actions.push({
|
||||
text: formatMessage({id: 'get_post_link_modal.title', defaultMessage: 'Copy Permalink'}),
|
||||
onPress: this.props.onCopyPermalink,
|
||||
});
|
||||
}
|
||||
|
||||
if (!isPendingOrFailedPost && !isPostEphemeral && canDelete && !hasBeenDeleted) {
|
||||
actions.push({text: formatMessage({id: 'post_info.del', defaultMessage: 'Delete'}), onPress: onPostDelete});
|
||||
}
|
||||
|
||||
return actions;
|
||||
};
|
||||
|
||||
measurePost = (event) => {
|
||||
const {height} = event.nativeEvent.layout;
|
||||
const {height: deviceHeight} = Dimensions.get('window');
|
||||
|
|
@ -206,7 +104,6 @@ export default class PostBody extends PureComponent {
|
|||
const {
|
||||
managedConfig,
|
||||
navigator,
|
||||
onAddReaction,
|
||||
onHashtagPress,
|
||||
onPermalinkPress,
|
||||
postId,
|
||||
|
|
@ -225,7 +122,6 @@ export default class PostBody extends PureComponent {
|
|||
passProps: {
|
||||
postId,
|
||||
managedConfig,
|
||||
onAddReaction,
|
||||
onHashtagPress,
|
||||
onPermalinkPress,
|
||||
},
|
||||
|
|
@ -234,15 +130,51 @@ export default class PostBody extends PureComponent {
|
|||
navigator.showModal(options);
|
||||
});
|
||||
|
||||
unflagPost = () => {
|
||||
const {actions, postId} = this.props;
|
||||
actions.unflagPost(postId);
|
||||
};
|
||||
showPostOptions = () => {
|
||||
const {
|
||||
canDelete,
|
||||
channelIsReadOnly,
|
||||
hasBeenDeleted,
|
||||
isFailed,
|
||||
isFlagged,
|
||||
isPending,
|
||||
isPostEphemeral,
|
||||
isSystemMessage,
|
||||
managedConfig,
|
||||
navigator,
|
||||
postId,
|
||||
showAddReaction,
|
||||
} = this.props;
|
||||
|
||||
showOptionsContext = (additionalAction) => {
|
||||
if (this.refs.options) {
|
||||
this.refs.options.show(additionalAction);
|
||||
if (isSystemMessage && (!canDelete || hasBeenDeleted)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isPending || isFailed || isPostEphemeral) {
|
||||
return;
|
||||
}
|
||||
|
||||
const options = {
|
||||
screen: 'PostOptions',
|
||||
animationType: 'none',
|
||||
backButtonTitle: '',
|
||||
navigatorStyle: {
|
||||
navBarHidden: true,
|
||||
screenBackgroundColor: 'transparent',
|
||||
modalPresentationStyle: 'overCurrentContext',
|
||||
},
|
||||
passProps: {
|
||||
canDelete,
|
||||
channelIsReadOnly,
|
||||
hasBeenDeleted,
|
||||
isFlagged,
|
||||
postId,
|
||||
managedConfig,
|
||||
showAddReaction,
|
||||
},
|
||||
};
|
||||
|
||||
navigator.showModal(options);
|
||||
};
|
||||
|
||||
renderAddChannelMember = (style, messageStyle, textStyles) => {
|
||||
|
|
@ -258,7 +190,6 @@ export default class PostBody extends PureComponent {
|
|||
<PostAddChannelMember
|
||||
baseTextStyle={messageStyle}
|
||||
navigator={navigator}
|
||||
onLongPress={this.showOptionsContext}
|
||||
onPostPress={onPress}
|
||||
textStyles={textStyles}
|
||||
postId={postProps.add_channel_member.post_id}
|
||||
|
|
@ -293,9 +224,8 @@ export default class PostBody extends PureComponent {
|
|||
attachments = (
|
||||
<FileAttachmentList
|
||||
fileIds={fileIds}
|
||||
hideOptionsContext={this.hideOptionsContext}
|
||||
isFailed={isFailed}
|
||||
onLongPress={this.showOptionsContext}
|
||||
onLongPress={this.showPostOptions}
|
||||
postId={postId}
|
||||
toggleSelected={toggleSelected}
|
||||
navigator={navigator}
|
||||
|
|
@ -323,7 +253,6 @@ export default class PostBody extends PureComponent {
|
|||
textStyles={textStyles}
|
||||
isReplyPost={isReplyPost}
|
||||
onHashtagPress={onHashtagPress}
|
||||
onLongPress={this.showOptionsContext}
|
||||
onPermalinkPress={onPermalinkPress}
|
||||
/>
|
||||
);
|
||||
|
|
@ -334,7 +263,6 @@ export default class PostBody extends PureComponent {
|
|||
hasReactions,
|
||||
isSearchResult,
|
||||
navigator,
|
||||
onAddReaction,
|
||||
postId,
|
||||
showLongPost,
|
||||
} = this.props;
|
||||
|
|
@ -350,14 +278,12 @@ export default class PostBody extends PureComponent {
|
|||
return (
|
||||
<Reactions
|
||||
postId={postId}
|
||||
onAddReaction={onAddReaction}
|
||||
navigator={navigator}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const {formatMessage} = this.context.intl;
|
||||
const {
|
||||
hasBeenDeleted,
|
||||
hasBeenEdited,
|
||||
|
|
@ -378,7 +304,6 @@ export default class PostBody extends PureComponent {
|
|||
postType,
|
||||
replyBarStyle,
|
||||
theme,
|
||||
toggleSelected,
|
||||
} = this.props;
|
||||
const {isLongPost, maxHeight} = this.state;
|
||||
const style = getStyleSheet(theme);
|
||||
|
|
@ -412,7 +337,7 @@ export default class PostBody extends PureComponent {
|
|||
} else if (postType === Posts.POST_TYPES.COMBINED_USER_ACTIVITY) {
|
||||
const {allUserIds, allUsernames, messageData} = postProps.user_activity;
|
||||
messageComponent = (
|
||||
<TouchableOpacity onLongPress={this.showOptionsContext}>
|
||||
<TouchableOpacity onLongPress={this.showPostOptions}>
|
||||
<View style={style.row}>
|
||||
<View style={style.flex}>
|
||||
<CombinedSystemMessage
|
||||
|
|
@ -443,7 +368,6 @@ export default class PostBody extends PureComponent {
|
|||
isSearchResult={isSearchResult}
|
||||
navigator={navigator}
|
||||
onHashtagPress={onHashtagPress}
|
||||
onLongPress={this.showOptionsContext}
|
||||
onPermalinkPress={onPermalinkPress}
|
||||
onPostPress={onPress}
|
||||
textStyles={textStyles}
|
||||
|
|
@ -456,14 +380,14 @@ export default class PostBody extends PureComponent {
|
|||
|
||||
if (!hasBeenDeleted) {
|
||||
body = (
|
||||
<View style={style.messageBody}>
|
||||
<OptionsContext
|
||||
getPostActions={this.getPostActions}
|
||||
ref='options'
|
||||
onPress={onPress}
|
||||
toggleSelected={toggleSelected}
|
||||
cancelText={formatMessage({id: 'channel_modal.cancel', defaultMessage: 'Cancel'})}
|
||||
>
|
||||
<TouchableHighlight
|
||||
onHideUnderlay={this.handleHideUnderlay}
|
||||
onPress={onPress}
|
||||
onLongPress={this.showPostOptions}
|
||||
onShowUnderlay={this.handleShowUnderlay}
|
||||
underlayColor='transparent'
|
||||
>
|
||||
<View style={style.messageBody}>
|
||||
<View onLayout={this.measurePost}>
|
||||
{messageComponent}
|
||||
{isLongPost &&
|
||||
|
|
@ -476,8 +400,8 @@ export default class PostBody extends PureComponent {
|
|||
{this.renderPostAdditionalContent(blockStyles, messageStyle, textStyles)}
|
||||
{this.renderFileAttachments()}
|
||||
{this.renderReactions()}
|
||||
</OptionsContext>
|
||||
</View>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ import {intlShape} from 'react-intl';
|
|||
import ProgressiveImage from 'app/components/progressive_image';
|
||||
|
||||
import CustomPropTypes from 'app/constants/custom_prop_types';
|
||||
import {emptyFunction} from 'app/utils/general';
|
||||
import ImageCacheManager from 'app/utils/image_cache_manager';
|
||||
import {previewImageAtIndex, calculateDimensions} from 'app/utils/images';
|
||||
import {getYouTubeVideoId, isImageLink, isYoutubeLink} from 'app/utils/url';
|
||||
|
|
@ -45,7 +44,6 @@ export default class PostBodyAdditionalContent extends PureComponent {
|
|||
message: PropTypes.string.isRequired,
|
||||
navigator: PropTypes.object.isRequired,
|
||||
onHashtagPress: PropTypes.func,
|
||||
onLongPress: PropTypes.func,
|
||||
onPermalinkPress: PropTypes.func,
|
||||
openGraphData: PropTypes.object,
|
||||
postId: PropTypes.string.isRequired,
|
||||
|
|
@ -55,10 +53,6 @@ export default class PostBodyAdditionalContent extends PureComponent {
|
|||
theme: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
onLongPress: emptyFunction,
|
||||
};
|
||||
|
||||
static contextTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
|
@ -311,7 +305,6 @@ export default class PostBodyAdditionalContent extends PureComponent {
|
|||
textStyles={textStyles}
|
||||
theme={theme}
|
||||
onHashtagPress={onHashtagPress}
|
||||
onLongPress={this.props.onLongPress}
|
||||
onPermalinkPress={onPermalinkPress}
|
||||
/>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,10 @@ import {
|
|||
TouchableOpacity,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import {intlShape} from 'react-intl';
|
||||
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
|
||||
|
||||
import {preventDoubleTap} from 'app/utils/tap';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
|
||||
import addReactionIcon from 'assets/images/icons/reaction.png';
|
||||
|
||||
|
|
@ -24,7 +27,6 @@ export default class Reactions extends PureComponent {
|
|||
}).isRequired,
|
||||
highlightedReactions: PropTypes.array.isRequired,
|
||||
navigator: PropTypes.object.isRequired,
|
||||
onAddReaction: PropTypes.func.isRequired,
|
||||
position: PropTypes.oneOf(['right', 'left']),
|
||||
postId: PropTypes.string.isRequired,
|
||||
reactions: PropTypes.object.isRequired,
|
||||
|
|
@ -37,11 +39,43 @@ export default class Reactions extends PureComponent {
|
|||
position: 'right',
|
||||
};
|
||||
|
||||
static contextTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
const {actions, postId} = this.props;
|
||||
actions.getReactionsForPost(postId);
|
||||
}
|
||||
|
||||
handleAddReaction = preventDoubleTap(() => {
|
||||
const {formatMessage} = this.context.intl;
|
||||
const {navigator, theme} = this.props;
|
||||
|
||||
MaterialIcon.getImageSource('close', 20, theme.sidebarHeaderTextColor).then((source) => {
|
||||
navigator.showModal({
|
||||
screen: 'AddReaction',
|
||||
title: formatMessage({id: 'mobile.post_info.add_reaction', defaultMessage: 'Add Reaction'}),
|
||||
animated: true,
|
||||
navigatorStyle: {
|
||||
navBarTextColor: theme.sidebarHeaderTextColor,
|
||||
navBarBackgroundColor: theme.sidebarHeaderBg,
|
||||
navBarButtonColor: theme.sidebarHeaderTextColor,
|
||||
screenBackgroundColor: theme.centerChannelBg,
|
||||
},
|
||||
passProps: {
|
||||
closeButton: source,
|
||||
onEmojiPress: this.handleAddReactionToPost,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
handleAddReactionToPost = (emoji) => {
|
||||
const {postId} = this.props;
|
||||
this.props.actions.addReaction(postId, emoji);
|
||||
};
|
||||
|
||||
handleReactionPress = (emoji, remove) => {
|
||||
const {actions, postId} = this.props;
|
||||
if (remove && this.props.canRemoveReaction) {
|
||||
|
|
@ -104,7 +138,7 @@ export default class Reactions extends PureComponent {
|
|||
addMoreReactions = (
|
||||
<TouchableOpacity
|
||||
key='addReaction'
|
||||
onPress={this.props.onAddReaction}
|
||||
onPress={this.handleAddReaction}
|
||||
style={[styles.reaction]}
|
||||
>
|
||||
<Image
|
||||
|
|
|
|||
|
|
@ -15,14 +15,15 @@ import {DeviceTypes} from 'app/constants';
|
|||
|
||||
import SlideUpPanelIndicator from './slide_up_panel_indicator';
|
||||
|
||||
export const BOTTOM_MARGIN = DeviceTypes.IS_IPHONE_X ? 24 : 0;
|
||||
const TOP_IOS_MARGIN = DeviceTypes.IS_IPHONE_X ? 84 : 64;
|
||||
const TOP_ANDROID_MARGIN = 44;
|
||||
const TOP_MARGIN = Platform.OS === 'ios' ? TOP_IOS_MARGIN : TOP_ANDROID_MARGIN;
|
||||
const BOTTOM_MARGIN = DeviceTypes.IS_IPHONE_X ? 24 : 0;
|
||||
const CONTAINER_MARGIN = TOP_MARGIN - 10;
|
||||
|
||||
export default class SlideUpPanel extends PureComponent {
|
||||
static propTypes = {
|
||||
alwaysCaptureContainerMove: PropTypes.bool,
|
||||
containerHeight: PropTypes.number,
|
||||
children: PropTypes.oneOfType([
|
||||
PropTypes.arrayOf(PropTypes.node),
|
||||
|
|
@ -45,14 +46,28 @@ export default class SlideUpPanel extends PureComponent {
|
|||
super(props);
|
||||
|
||||
const initialUsedSpace = Math.abs(props.initialPosition);
|
||||
const initialPosition = ((props.containerHeight - (props.headerHeight + BOTTOM_MARGIN)) * (1 - initialUsedSpace));
|
||||
let initialPosition;
|
||||
if (initialUsedSpace <= 1) {
|
||||
initialPosition = ((props.containerHeight - (props.headerHeight + BOTTOM_MARGIN)) * (1 - initialUsedSpace));
|
||||
} else {
|
||||
initialPosition = ((props.containerHeight - (props.headerHeight + BOTTOM_MARGIN)) - initialUsedSpace);
|
||||
}
|
||||
|
||||
this.mainPanGesture = PanResponder.create({
|
||||
onMoveShouldSetPanResponder: (evt, gestureState) => {
|
||||
onMoveShouldSetPanResponderCapture: (evt, gestureState) => {
|
||||
if (this.props.alwaysCaptureContainerMove) {
|
||||
return gestureState.dy !== 0;
|
||||
}
|
||||
const isGoingDown = gestureState.y0 < gestureState.dy;
|
||||
return this.isAValidMovement(gestureState.dx, gestureState.dy, isGoingDown);
|
||||
},
|
||||
onPanResponderMove: (evt, gestureState) => {
|
||||
const isGoingDown = gestureState.dy > 0;
|
||||
if (this.props.alwaysCaptureContainerMove &&
|
||||
!this.isAValidMovement(gestureState.dx, gestureState.dy, isGoingDown)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.moveStart(gestureState);
|
||||
},
|
||||
onPanResponderRelease: (evt, gestureState) => {
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ export function registerScreens(store, Provider) {
|
|||
Navigation.registerComponent('NotificationSettingsMobile', () => wrapWithContextProvider(require('app/screens/settings/notification_settings_mobile').default), store, Provider);
|
||||
Navigation.registerComponent('OptionsModal', () => wrapWithContextProvider(require('app/screens/options_modal').default), store, Provider);
|
||||
Navigation.registerComponent('Permalink', () => wrapWithContextProvider(require('app/screens/permalink').default), store, Provider);
|
||||
Navigation.registerComponent('PostOptions', () => wrapWithContextProvider(require('app/screens/post_options').default), store, Provider);
|
||||
Navigation.registerComponent('ReactionList', () => wrapWithContextProvider(require('app/screens/reaction_list').default), store, Provider);
|
||||
Navigation.registerComponent('RecentMentions', () => wrapWithContextProvider(require('app/screens/recent_mentions').default), store, Provider);
|
||||
Navigation.registerComponent('Root', () => require('app/screens/root').default, store, Provider);
|
||||
|
|
|
|||
|
|
@ -51,7 +51,6 @@ export default class LongPost extends PureComponent {
|
|||
inThreadView: PropTypes.bool,
|
||||
managedConfig: PropTypes.object,
|
||||
navigator: PropTypes.object,
|
||||
onAddReaction: PropTypes.func,
|
||||
onHashtagPress: PropTypes.func,
|
||||
onPermalinkPress: PropTypes.func,
|
||||
postId: PropTypes.string.isRequired,
|
||||
|
|
@ -141,7 +140,6 @@ export default class LongPost extends PureComponent {
|
|||
<View style={style.attachments}>
|
||||
<FileAttachmentList
|
||||
fileIds={fileIds}
|
||||
hideOptionsContext={emptyFunction}
|
||||
isFailed={false}
|
||||
onLongPress={emptyFunction}
|
||||
postId={postId}
|
||||
|
|
@ -155,7 +153,7 @@ export default class LongPost extends PureComponent {
|
|||
}
|
||||
|
||||
renderReactions = (style) => {
|
||||
const {hasReactions, postId, onAddReaction} = this.props;
|
||||
const {hasReactions, navigator, postId} = this.props;
|
||||
|
||||
if (!hasReactions) {
|
||||
return null;
|
||||
|
|
@ -164,9 +162,9 @@ export default class LongPost extends PureComponent {
|
|||
return (
|
||||
<View style={style.reactions}>
|
||||
<Reactions
|
||||
navigator={navigator}
|
||||
position='left'
|
||||
postId={postId}
|
||||
onAddReaction={onAddReaction}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
|
|
|
|||
81
app/screens/post_options/index.js
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {bindActionCreators} from 'redux';
|
||||
import {connect} from 'react-redux';
|
||||
|
||||
import {deletePost, flagPost, unflagPost, removePost} from 'mattermost-redux/actions/posts';
|
||||
import {General, Permissions} from 'mattermost-redux/constants';
|
||||
import {getChannel, getCurrentChannelId} from 'mattermost-redux/selectors/entities/channels';
|
||||
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
|
||||
import {getConfig, getLicense, hasNewPermissions} from 'mattermost-redux/selectors/entities/general';
|
||||
import {getPost} from 'mattermost-redux/selectors/entities/posts';
|
||||
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
import {haveIChannelPermission} from 'mattermost-redux/selectors/entities/roles';
|
||||
import {getCurrentTeamId, getCurrentTeamUrl} from 'mattermost-redux/selectors/entities/teams';
|
||||
import {canEditPost} from 'mattermost-redux/utils/post_utils';
|
||||
|
||||
import {addReaction} from 'app/actions/views/emoji';
|
||||
import {getDimensions} from 'app/selectors/device';
|
||||
|
||||
import PostOptions from './post_options';
|
||||
|
||||
function mapStateToProps(state, ownProps) {
|
||||
const post = getPost(state, ownProps.postId);
|
||||
const channel = getChannel(state, post.channel_id);
|
||||
const config = getConfig(state);
|
||||
const license = getLicense(state);
|
||||
const currentUserId = getCurrentUserId(state);
|
||||
const currentTeamId = getCurrentTeamId(state);
|
||||
const currentChannelId = getCurrentChannelId(state);
|
||||
|
||||
const channelIsArchived = channel.delete_at !== 0;
|
||||
|
||||
let canAddReaction = true;
|
||||
let canEdit = false;
|
||||
let canEditUntil = -1;
|
||||
|
||||
if (hasNewPermissions(state)) {
|
||||
canAddReaction = haveIChannelPermission(state, {
|
||||
team: currentTeamId,
|
||||
channel: post.channel_id,
|
||||
permission: Permissions.ADD_REACTION,
|
||||
});
|
||||
}
|
||||
|
||||
if (channelIsArchived) {
|
||||
canAddReaction = false;
|
||||
} else {
|
||||
canEdit = canEditPost(state, config, license, currentTeamId, currentChannelId, currentUserId, post);
|
||||
if (canEdit && license.IsLicensed === 'true' &&
|
||||
(config.AllowEditPost === General.ALLOW_EDIT_POST_TIME_LIMIT || (config.PostEditTimeLimit !== -1 && config.PostEditTimeLimit !== '-1'))
|
||||
) {
|
||||
canEditUntil = post.create_at + (config.PostEditTimeLimit * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...getDimensions(state),
|
||||
canAddReaction,
|
||||
canEdit,
|
||||
canEditUntil,
|
||||
currentTeamUrl: getCurrentTeamUrl(state),
|
||||
isMyPost: currentUserId === post.user_id,
|
||||
post,
|
||||
theme: getTheme(state),
|
||||
};
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators({
|
||||
addReaction,
|
||||
deletePost,
|
||||
flagPost,
|
||||
removePost,
|
||||
unflagPost,
|
||||
}, dispatch),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(PostOptions);
|
||||
106
app/screens/post_options/post_option.js
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React, {PureComponent} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
Image,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TouchableHighlight,
|
||||
View,
|
||||
} from 'react-native';
|
||||
|
||||
import copy from 'assets/images/post_menu/copy.png';
|
||||
import edit from 'assets/images/post_menu/edit.png';
|
||||
import emoji from 'assets/images/post_menu/emoji.png';
|
||||
import flag from 'assets/images/post_menu/flag.png';
|
||||
import link from 'assets/images/post_menu/link.png';
|
||||
import trash from 'assets/images/post_menu/trash.png';
|
||||
|
||||
const icons = {
|
||||
copy,
|
||||
edit,
|
||||
emoji,
|
||||
flag,
|
||||
link,
|
||||
trash,
|
||||
};
|
||||
|
||||
export default class PostOption extends PureComponent {
|
||||
static propTypes = {
|
||||
destructive: PropTypes.bool,
|
||||
icon: PropTypes.string.isRequired,
|
||||
onPress: PropTypes.func.isRequired,
|
||||
text: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
render() {
|
||||
const {destructive, icon, onPress, text} = this.props;
|
||||
const image = icons[icon];
|
||||
|
||||
return (
|
||||
<View style={style.container} >
|
||||
<TouchableHighlight
|
||||
onPress={onPress}
|
||||
underlayColor='rgba(0, 0, 0, 0.05)'
|
||||
style={style.flex}
|
||||
>
|
||||
<View style={style.row}>
|
||||
<View style={style.icon}>
|
||||
<Image source={image}/>
|
||||
</View>
|
||||
<View style={style.textContainer}>
|
||||
<Text style={[style.text, destructive ? style.destructive : null]}>
|
||||
{text}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
<View style={style.footer}/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const style = StyleSheet.create({
|
||||
container: {
|
||||
height: 51,
|
||||
width: '100%',
|
||||
},
|
||||
flex: {
|
||||
flex: 1,
|
||||
},
|
||||
destructive: {
|
||||
color: '#D0021B',
|
||||
},
|
||||
row: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
},
|
||||
icon: {
|
||||
alignItems: 'center',
|
||||
height: 50,
|
||||
justifyContent: 'center',
|
||||
width: 60,
|
||||
},
|
||||
textContainer: {
|
||||
justifyContent: 'center',
|
||||
flex: 1,
|
||||
height: 50,
|
||||
marginRight: 5,
|
||||
},
|
||||
text: {
|
||||
color: '#000000',
|
||||
fontSize: 16,
|
||||
lineHeight: 19,
|
||||
opacity: 0.9,
|
||||
letterSpacing: -0.45,
|
||||
},
|
||||
footer: {
|
||||
height: 1,
|
||||
marginLeft: 60,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: 'rgba(0, 0, 0 ,0.2)',
|
||||
},
|
||||
});
|
||||
358
app/screens/post_options/post_options.js
Normal file
|
|
@ -0,0 +1,358 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React, {PureComponent} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {Alert, Clipboard, StyleSheet, View} from 'react-native';
|
||||
import {intlShape} from 'react-intl';
|
||||
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
|
||||
|
||||
import SlideUpPanel from 'app/components/slide_up_panel';
|
||||
import {BOTTOM_MARGIN} from 'app/components/slide_up_panel/slide_up_panel';
|
||||
|
||||
import PostOption from './post_option';
|
||||
|
||||
const OPTION_HEIGHT = 50;
|
||||
const INITIAL_OPTION_COUNT = 6;
|
||||
|
||||
export default class PostOptions extends PureComponent {
|
||||
static propTypes = {
|
||||
actions: PropTypes.shape({
|
||||
addReaction: PropTypes.func.isRequired,
|
||||
deletePost: PropTypes.func.isRequired,
|
||||
flagPost: PropTypes.func.isRequired,
|
||||
removePost: PropTypes.func.isRequired,
|
||||
unflagPost: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
additionalOption: PropTypes.object,
|
||||
canAddReaction: PropTypes.bool,
|
||||
canDelete: PropTypes.bool,
|
||||
canEdit: PropTypes.bool,
|
||||
canEditUntil: PropTypes.number.isRequired,
|
||||
channelIsReadOnly: PropTypes.bool,
|
||||
currentTeamUrl: PropTypes.string.isRequired,
|
||||
deviceHeight: PropTypes.number.isRequired,
|
||||
hasBeenDeleted: PropTypes.bool,
|
||||
isFlagged: PropTypes.bool,
|
||||
isMyPost: PropTypes.bool,
|
||||
managedConfig: PropTypes.object.isRequired,
|
||||
navigator: PropTypes.object.isRequired,
|
||||
post: PropTypes.object.isRequired,
|
||||
showAddReaction: PropTypes.bool,
|
||||
theme: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
static contextTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
};
|
||||
|
||||
close = () => {
|
||||
this.props.navigator.dismissModal({
|
||||
animationType: 'none',
|
||||
});
|
||||
};
|
||||
|
||||
closeWithAnimation = () => {
|
||||
if (this.slideUpPanel) {
|
||||
this.slideUpPanel.getWrappedInstance().handleTouchEnd();
|
||||
} else {
|
||||
this.close();
|
||||
}
|
||||
};
|
||||
|
||||
getAddReactionOption = () => {
|
||||
const {formatMessage} = this.context.intl;
|
||||
const {canAddReaction, channelIsReadOnly, showAddReaction} = this.props;
|
||||
|
||||
if (showAddReaction && canAddReaction && !channelIsReadOnly) {
|
||||
return (
|
||||
<PostOption
|
||||
key='reaction'
|
||||
icon='emoji'
|
||||
text={formatMessage({id: 'mobile.post_info.add_reaction', defaultMessage: 'Add Reaction'})}
|
||||
onPress={this.handleAddReaction}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
getCopyPermalink = () => {
|
||||
const {formatMessage} = this.context.intl;
|
||||
|
||||
return (
|
||||
<PostOption
|
||||
key='permalink'
|
||||
icon='link'
|
||||
text={formatMessage({id: 'get_post_link_modal.title', defaultMessage: 'Copy Permalink'})}
|
||||
onPress={this.handleCopyPermalink}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
getCopyText = () => {
|
||||
const {formatMessage} = this.context.intl;
|
||||
const {managedConfig, post} = this.props;
|
||||
|
||||
if (managedConfig.copyAndPasteProtection !== 'true' && post.message) {
|
||||
return (
|
||||
<PostOption
|
||||
key='copy'
|
||||
icon='copy'
|
||||
text={formatMessage({id: 'mobile.post_info.copy_text', defaultMessage: 'Copy Text'})}
|
||||
onPress={this.handleCopyText}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
getDeleteOption = () => {
|
||||
const {formatMessage} = this.context.intl;
|
||||
const {canDelete, hasBeenDeleted} = this.props;
|
||||
|
||||
if (canDelete && !hasBeenDeleted) {
|
||||
return (
|
||||
<PostOption
|
||||
destructive={true}
|
||||
key='delete'
|
||||
icon='trash'
|
||||
text={formatMessage({id: 'post_info.del', defaultMessage: 'Delete'})}
|
||||
onPress={this.handlePostDelete}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
getEditOption = () => {
|
||||
const {formatMessage} = this.context.intl;
|
||||
const {canEdit, canEditUntil} = this.props;
|
||||
|
||||
if (canEdit && (canEditUntil === -1 || canEditUntil > Date.now())) {
|
||||
return (
|
||||
<PostOption
|
||||
key='edit'
|
||||
icon='edit'
|
||||
text={formatMessage({id: 'post_info.edit', defaultMessage: 'Edit'})}
|
||||
onPress={this.handlePostEdit}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
getFlagOption = () => {
|
||||
const {formatMessage} = this.context.intl;
|
||||
const {channelIsReadOnly, isFlagged} = this.props;
|
||||
|
||||
if (channelIsReadOnly) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isFlagged) {
|
||||
return (
|
||||
<PostOption
|
||||
key='unflag'
|
||||
icon='flag'
|
||||
text={formatMessage({id: 'post_info.mobile.unflag', defaultMessage: 'Unflag'})}
|
||||
onPress={this.handleUnflagPost}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<PostOption
|
||||
key='flagged'
|
||||
icon='flag'
|
||||
text={formatMessage({id: 'post_info.mobile.flag', defaultMessage: 'Flag'})}
|
||||
onPress={this.handleFlagPost}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
getMyPostOptions = () => {
|
||||
const actions = [
|
||||
this.getEditOption(),
|
||||
this.getFlagOption(),
|
||||
this.getAddReactionOption(),
|
||||
this.getCopyPermalink(),
|
||||
this.getCopyText(),
|
||||
this.getDeleteOption(),
|
||||
];
|
||||
|
||||
return actions.filter((a) => a !== null);
|
||||
};
|
||||
|
||||
getOthersPostOptions = () => {
|
||||
const actions = [
|
||||
this.getFlagOption(),
|
||||
this.getAddReactionOption(),
|
||||
this.getCopyPermalink(),
|
||||
this.getCopyText(),
|
||||
this.getEditOption(),
|
||||
this.getDeleteOption(),
|
||||
];
|
||||
|
||||
return actions.filter((a) => a !== null);
|
||||
};
|
||||
|
||||
getPostOptions = () => {
|
||||
const {isMyPost} = this.props;
|
||||
|
||||
if (isMyPost) {
|
||||
return this.getMyPostOptions();
|
||||
}
|
||||
|
||||
return this.getOthersPostOptions();
|
||||
};
|
||||
|
||||
handleAddReaction = () => {
|
||||
const {formatMessage} = this.context.intl;
|
||||
const {navigator, theme} = this.props;
|
||||
|
||||
this.close();
|
||||
requestAnimationFrame(() => {
|
||||
MaterialIcon.getImageSource('close', 20, theme.sidebarHeaderTextColor).then((source) => {
|
||||
navigator.showModal({
|
||||
screen: 'AddReaction',
|
||||
title: formatMessage({id: 'mobile.post_info.add_reaction', defaultMessage: 'Add Reaction'}),
|
||||
animated: true,
|
||||
navigatorStyle: {
|
||||
navBarTextColor: theme.sidebarHeaderTextColor,
|
||||
navBarBackgroundColor: theme.sidebarHeaderBg,
|
||||
navBarButtonColor: theme.sidebarHeaderTextColor,
|
||||
screenBackgroundColor: theme.centerChannelBg,
|
||||
},
|
||||
passProps: {
|
||||
closeButton: source,
|
||||
onEmojiPress: this.handleAddReactionToPost,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
handleAddReactionToPost = (emoji) => {
|
||||
const {actions, post} = this.props;
|
||||
|
||||
actions.addReaction(post.id, emoji);
|
||||
};
|
||||
|
||||
handleCopyPermalink = () => {
|
||||
const {currentTeamUrl, post} = this.props;
|
||||
const permalink = `${currentTeamUrl}/pl/${post.id}`;
|
||||
|
||||
Clipboard.setString(permalink);
|
||||
this.closeWithAnimation();
|
||||
};
|
||||
|
||||
handleCopyText = () => {
|
||||
const {message} = this.props.post;
|
||||
|
||||
Clipboard.setString(message);
|
||||
this.closeWithAnimation();
|
||||
};
|
||||
|
||||
handleFlagPost = () => {
|
||||
const {actions, post} = this.props;
|
||||
|
||||
actions.flagPost(post.id);
|
||||
this.closeWithAnimation();
|
||||
};
|
||||
|
||||
handlePostDelete = () => {
|
||||
const {formatMessage} = this.context.intl;
|
||||
const {actions, isMyPost, post} = this.props;
|
||||
|
||||
Alert.alert(
|
||||
formatMessage({id: 'mobile.post.delete_title', defaultMessage: 'Delete Post'}),
|
||||
formatMessage({
|
||||
id: 'mobile.post.delete_question',
|
||||
defaultMessage: 'Are you sure you want to delete this post?',
|
||||
}),
|
||||
[{
|
||||
text: formatMessage({id: 'mobile.post.cancel', defaultMessage: 'Cancel'}),
|
||||
style: 'cancel',
|
||||
}, {
|
||||
text: formatMessage({id: 'post_info.del', defaultMessage: 'Delete'}),
|
||||
style: 'destructive',
|
||||
onPress: () => {
|
||||
actions.deletePost(post);
|
||||
if (isMyPost) {
|
||||
actions.removePost(post);
|
||||
}
|
||||
this.closeWithAnimation();
|
||||
},
|
||||
}]
|
||||
);
|
||||
};
|
||||
|
||||
handlePostEdit = () => {
|
||||
const {intl} = this.context;
|
||||
const {navigator, post, theme} = this.props;
|
||||
|
||||
this.close();
|
||||
requestAnimationFrame(() => {
|
||||
MaterialIcon.getImageSource('close', 20, theme.sidebarHeaderTextColor).then((source) => {
|
||||
navigator.showModal({
|
||||
screen: 'EditPost',
|
||||
title: intl.formatMessage({id: 'mobile.edit_post.title', defaultMessage: 'Editing Message'}),
|
||||
animated: true,
|
||||
navigatorStyle: {
|
||||
navBarTextColor: theme.sidebarHeaderTextColor,
|
||||
navBarBackgroundColor: theme.sidebarHeaderBg,
|
||||
navBarButtonColor: theme.sidebarHeaderTextColor,
|
||||
screenBackgroundColor: theme.centerChannelBg,
|
||||
},
|
||||
passProps: {
|
||||
post,
|
||||
closeButton: source,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
handleUnflagPost = () => {
|
||||
const {actions, post} = this.props;
|
||||
|
||||
actions.unflagPost(post.id);
|
||||
this.closeWithAnimation();
|
||||
};
|
||||
|
||||
refSlideUpPanel = (r) => {
|
||||
this.slideUpPanel = r;
|
||||
};
|
||||
|
||||
render() {
|
||||
const {deviceHeight} = this.props;
|
||||
const options = this.getPostOptions();
|
||||
const initialPosition = (INITIAL_OPTION_COUNT + 1) * OPTION_HEIGHT;
|
||||
const marginFromTop = deviceHeight - BOTTOM_MARGIN - ((options.length + 1) * OPTION_HEIGHT);
|
||||
|
||||
return (
|
||||
<View style={style.flex}>
|
||||
<SlideUpPanel
|
||||
alwaysCaptureContainerMove={true}
|
||||
ref={this.refSlideUpPanel}
|
||||
marginFromTop={marginFromTop}
|
||||
onRequestClose={this.close}
|
||||
initialPosition={initialPosition}
|
||||
>
|
||||
{options}
|
||||
</SlideUpPanel>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const style = StyleSheet.create({
|
||||
flex: {
|
||||
flex: 1,
|
||||
},
|
||||
});
|
||||
|
|
@ -46,7 +46,6 @@ export default class ReactionList extends PureComponent {
|
|||
|
||||
this.contentOffsetY = -1;
|
||||
this.state = {
|
||||
canDrag: true,
|
||||
allUserIds: getUniqueUserIds(reactions),
|
||||
reactions,
|
||||
reactionsByName,
|
||||
|
|
|
|||
5
app/utils/bottom_sheet/bottom_sheet.android.js
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import RNBottomSheet from 'react-native-bottom-sheet';
|
||||
export default RNBottomSheet;
|
||||
14
app/utils/bottom_sheet/bottom_sheet.ios.js
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {ActionSheetIOS} from 'react-native';
|
||||
|
||||
export default {
|
||||
showBottomSheetWithOptions: (options, callback) => {
|
||||
return ActionSheetIOS.showActionSheetWithOptions(options, callback);
|
||||
},
|
||||
|
||||
showShareBottomSheetWithOptions: (options, failureCallback, successCallback) => {
|
||||
return ActionSheetIOS.showShareActionSheetWithOptions(options, failureCallback, successCallback);
|
||||
},
|
||||
};
|
||||
5
app/utils/bottom_sheet/index.js
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import BottomSheet from './bottom_sheet';
|
||||
export default BottomSheet;
|
||||
|
|
@ -330,7 +330,7 @@
|
|||
"mobile.open_gm.error": "We couldn't open a group message with those users. Please check your connection and try again.",
|
||||
"mobile.open_unknown_channel.error": "Unable to join the channel. Please reset the cache and try again.",
|
||||
"mobile.post_info.add_reaction": "Add Reaction",
|
||||
"mobile.post_info.copy_post": "Copy Post",
|
||||
"mobile.post_info.copy_text": "Copy Text",
|
||||
"mobile.post_textbox.empty.message": "You are trying to send an empty message.\nPlease make sure you have a message or at least one attached file.",
|
||||
"mobile.post_textbox.empty.ok": "OK",
|
||||
"mobile.post_textbox.empty.title": "Empty Message",
|
||||
|
|
|
|||
BIN
assets/base/images/post_menu/copy.png
Executable file
|
After Width: | Height: | Size: 293 B |
BIN
assets/base/images/post_menu/copy@2x.png
Executable file
|
After Width: | Height: | Size: 493 B |
BIN
assets/base/images/post_menu/copy@3x.png
Executable file
|
After Width: | Height: | Size: 719 B |
BIN
assets/base/images/post_menu/edit.png
Executable file
|
After Width: | Height: | Size: 399 B |
BIN
assets/base/images/post_menu/edit@2x.png
Executable file
|
After Width: | Height: | Size: 851 B |
BIN
assets/base/images/post_menu/edit@3x.png
Executable file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
assets/base/images/post_menu/emoji.png
Executable file
|
After Width: | Height: | Size: 400 B |
BIN
assets/base/images/post_menu/emoji@2x.png
Executable file
|
After Width: | Height: | Size: 883 B |
BIN
assets/base/images/post_menu/emoji@3x.png
Executable file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/base/images/post_menu/flag.png
Executable file
|
After Width: | Height: | Size: 365 B |
BIN
assets/base/images/post_menu/flag@2x.png
Executable file
|
After Width: | Height: | Size: 612 B |
BIN
assets/base/images/post_menu/flag@3x.png
Executable file
|
After Width: | Height: | Size: 878 B |
BIN
assets/base/images/post_menu/link.png
Executable file
|
After Width: | Height: | Size: 441 B |
BIN
assets/base/images/post_menu/link@2x.png
Executable file
|
After Width: | Height: | Size: 945 B |
BIN
assets/base/images/post_menu/link@3x.png
Executable file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
assets/base/images/post_menu/pin.png
Executable file
|
After Width: | Height: | Size: 448 B |
BIN
assets/base/images/post_menu/pin@2x.png
Executable file
|
After Width: | Height: | Size: 920 B |
BIN
assets/base/images/post_menu/pin@3x.png
Executable file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
assets/base/images/post_menu/trash.png
Executable file
|
After Width: | Height: | Size: 511 B |
BIN
assets/base/images/post_menu/trash@2x.png
Executable file
|
After Width: | Height: | Size: 952 B |
BIN
assets/base/images/post_menu/trash@3x.png
Executable file
|
After Width: | Height: | Size: 1.4 KiB |
|
|
@ -5,6 +5,7 @@
|
|||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; };
|
||||
00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; };
|
||||
|
|
@ -28,9 +29,13 @@
|
|||
375218501F4B9EE70035444B /* libRCTCameraRoll.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3752184F1F4B9E980035444B /* libRCTCameraRoll.a */; };
|
||||
37ABD3C81F4CE142001FDE6B /* libART.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 37ABD39C1F4CE13B001FDE6B /* libART.a */; };
|
||||
382D94CF15EE4FC292C3F341 /* Foundation.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 51F5A483EA9F4A9A87ACFB59 /* Foundation.ttf */; };
|
||||
3C0B333879CE4730843D8584 /* Roboto-MediumItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = D08F54E10DF14AE4BBF4E2B4 /* Roboto-MediumItalic.ttf */; };
|
||||
3D38ABA732A34A9BB3294F90 /* EvilIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 349FBA7338E74D9BBD709528 /* EvilIcons.ttf */; };
|
||||
3D7B4E6EE6B948AAA6A1E4E6 /* Roboto-BoldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = C46342B0E5FD4D878AF3A129 /* Roboto-BoldItalic.ttf */; };
|
||||
3F876A0DC6314E27B16C8A96 /* libRNReactNativeDocViewer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6BAF8296411D4657B5A0E8F8 /* libRNReactNativeDocViewer.a */; };
|
||||
420A7328E12C4B72AEF420CE /* Octicons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = EDC04CBCF81642219D199CBB /* Octicons.ttf */; };
|
||||
460A48EA5C6C4D8B8D9A2C75 /* Roboto-Italic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 031EF04FB2D14EEFAACBAA1A /* Roboto-Italic.ttf */; };
|
||||
552835DCC0C24FC691EE6CAB /* Roboto-LightItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 8F0B22D2C9924FAFA7FB681C /* Roboto-LightItalic.ttf */; };
|
||||
55C6561DDBBA45929D88B6D1 /* OpenSans-BoldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 32AC3D4EA79E44738A6E9766 /* OpenSans-BoldItalic.ttf */; };
|
||||
5A0920184BD344979BCFCD5C /* libRCTVideo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B89192186C764B9FA473403A /* libRCTVideo.a */; };
|
||||
5CB86E9DFB94485CAA748DF3 /* YTPlayerView-iframe-player.html in Resources */ = {isa = PBXBuildFile; fileRef = 79CB6EBA24FE4ABFB0C155F0 /* YTPlayerView-iframe-player.html */; };
|
||||
|
|
@ -38,6 +43,7 @@
|
|||
5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */; };
|
||||
62A8448264674B4D95A5A7C2 /* OpenSans-Semibold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = C78A387124874496AD2C1466 /* OpenSans-Semibold.ttf */; };
|
||||
69AC753E496743BABB7A7124 /* OpenSans-SemiboldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 0E617BF0F36D4E738F51D169 /* OpenSans-SemiboldItalic.ttf */; };
|
||||
71F30A436B5847DF9D319D15 /* Roboto-BlackItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7F54ABFAE6CE4A6DB11D1ED7 /* Roboto-BlackItalic.ttf */; };
|
||||
74D116AD208A8D5600CF8A79 /* libRNKeychain.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 74D116AA208A8D3100CF8A79 /* libRNKeychain.a */; };
|
||||
7F2691A11EE1DC6A007574FE /* libRNNotifications.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F2691A01EE1DC51007574FE /* libRNNotifications.a */; };
|
||||
7F292A711E8AB73400A450A3 /* SplashScreenResource in Resources */ = {isa = PBXBuildFile; fileRef = 7F292A701E8AB73400A450A3 /* SplashScreenResource */; };
|
||||
|
|
@ -62,7 +68,6 @@
|
|||
7F5CA9A0208FE3B9004F91CE /* libRNDocumentPicker.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F5CA991208FE38F004F91CE /* libRNDocumentPicker.a */; };
|
||||
7F642DF02093533300F3165E /* libRNDeviceInfo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F642DED2093530B00F3165E /* libRNDeviceInfo.a */; };
|
||||
7F642DF1209353A400F3165E /* libRNDeviceInfo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F642DED2093530B00F3165E /* libRNDeviceInfo.a */; };
|
||||
7F6877B31E7836070094B63F /* libToolTipMenu.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F6877B01E7835E50094B63F /* libToolTipMenu.a */; };
|
||||
7F6C47A51FE87E8C00F5A912 /* PerformRequests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F6C47A41FE87E8C00F5A912 /* PerformRequests.m */; };
|
||||
7F7D7F98201645E100D31155 /* libReactNativePermissions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F7D7F87201645D300D31155 /* libReactNativePermissions.a */; };
|
||||
7F95132F208646CE00616E3E /* 0155-keys.png in Resources */ = {isa = PBXBuildFile; fileRef = 7F9512EA208646CD00616E3E /* 0155-keys.png */; };
|
||||
|
|
@ -103,25 +108,20 @@
|
|||
9358B95F95184EE0A4DCE629 /* OpenSans-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = D4B1B363C2414DA19C1AC521 /* OpenSans-Bold.ttf */; };
|
||||
A08D512E7ADC40CCAD055A9E /* OpenSans-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = BC977883E2624E05975CA65B /* OpenSans-Regular.ttf */; };
|
||||
A9B746D2CFA9CEBFB8AE2B5B /* libPods-Mattermost.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 65FD5EA57EBAE06106094B2F /* libPods-Mattermost.a */; };
|
||||
AA9605CFDA8E4E7CB8A041BF /* Roboto-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = C5BD64DE829E455A997DCAD5 /* Roboto-Regular.ttf */; };
|
||||
ABF5F93B1D0A47BAACEAC376 /* Roboto-Light.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 34B20A903038487E8D7DEA1E /* Roboto-Light.ttf */; };
|
||||
C035DB50ED2045F09923FFAE /* MaterialCommunityIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 04AA5E8EF3B54735A11E3B95 /* MaterialCommunityIcons.ttf */; };
|
||||
C337E8708D2845C6A8DBB47E /* Ionicons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 2DCFD31D3F4A4154822AB532 /* Ionicons.ttf */; };
|
||||
C99BB3F4E4564F01A531FBEA /* Roboto-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 09FA716C56874BDDA30FE8C4 /* Roboto-Medium.ttf */; };
|
||||
D719A67137964F08BE47A5FC /* OpenSans-ExtraBold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 3647DF63D6764CF093375861 /* OpenSans-ExtraBold.ttf */; };
|
||||
DDE492F7425D451884DAA088 /* Roboto-Black.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 6EFF13DD24CE4E26953E598A /* Roboto-Black.ttf */; };
|
||||
DE863F2E1E194A45A5B58FFA /* Roboto-Thin.ttf in Resources */ = {isa = PBXBuildFile; fileRef = A734E00E7E184582A877F2B3 /* Roboto-Thin.ttf */; };
|
||||
DEBCF44F1F46413BB407D316 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 8606EB1EB7E349EF8248933E /* libz.tbd */; };
|
||||
E052494CD6104A65840485E7 /* Roboto-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 71E626D4980A4560B26F0E1C /* Roboto-Bold.ttf */; };
|
||||
EC6AF34E03F647389D377064 /* Roboto-ThinItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 12D0B0E475FD46E29907305E /* Roboto-ThinItalic.ttf */; };
|
||||
F006936FC2884C24A1321FC0 /* MaterialIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 356C9186FA374641A00EB2EA /* MaterialIcons.ttf */; };
|
||||
F083DB472349411A8E6E7AAD /* OpenSans-LightItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = BE17F630DB5D41FD93F32D22 /* OpenSans-LightItalic.ttf */; };
|
||||
F23C99AA5FA10E457A76803A /* libPods-MattermostTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 4246DC09024BB33A3E491E25 /* libPods-MattermostTests.a */; };
|
||||
DDE492F7425D451884DAA088 /* Roboto-Black.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 6EFF13DD24CE4E26953E598A /* Roboto-Black.ttf */; };
|
||||
71F30A436B5847DF9D319D15 /* Roboto-BlackItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7F54ABFAE6CE4A6DB11D1ED7 /* Roboto-BlackItalic.ttf */; };
|
||||
E052494CD6104A65840485E7 /* Roboto-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 71E626D4980A4560B26F0E1C /* Roboto-Bold.ttf */; };
|
||||
3D7B4E6EE6B948AAA6A1E4E6 /* Roboto-BoldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = C46342B0E5FD4D878AF3A129 /* Roboto-BoldItalic.ttf */; };
|
||||
460A48EA5C6C4D8B8D9A2C75 /* Roboto-Italic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 031EF04FB2D14EEFAACBAA1A /* Roboto-Italic.ttf */; };
|
||||
ABF5F93B1D0A47BAACEAC376 /* Roboto-Light.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 34B20A903038487E8D7DEA1E /* Roboto-Light.ttf */; };
|
||||
552835DCC0C24FC691EE6CAB /* Roboto-LightItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 8F0B22D2C9924FAFA7FB681C /* Roboto-LightItalic.ttf */; };
|
||||
C99BB3F4E4564F01A531FBEA /* Roboto-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 09FA716C56874BDDA30FE8C4 /* Roboto-Medium.ttf */; };
|
||||
3C0B333879CE4730843D8584 /* Roboto-MediumItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = D08F54E10DF14AE4BBF4E2B4 /* Roboto-MediumItalic.ttf */; };
|
||||
AA9605CFDA8E4E7CB8A041BF /* Roboto-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = C5BD64DE829E455A997DCAD5 /* Roboto-Regular.ttf */; };
|
||||
DE863F2E1E194A45A5B58FFA /* Roboto-Thin.ttf in Resources */ = {isa = PBXBuildFile; fileRef = A734E00E7E184582A877F2B3 /* Roboto-Thin.ttf */; };
|
||||
EC6AF34E03F647389D377064 /* Roboto-ThinItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 12D0B0E475FD46E29907305E /* Roboto-ThinItalic.ttf */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
|
|
@ -468,20 +468,6 @@
|
|||
remoteGlobalIDString = E72EC1401F7ABB5A0001BC90;
|
||||
remoteInfo = "RNDeviceInfo-tvOS";
|
||||
};
|
||||
7F6877AF1E7835E50094B63F /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 7F6877AA1E7835E50094B63F /* ToolTipMenu.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 4681C0211B05271A004D67D4;
|
||||
remoteInfo = ToolTipMenu;
|
||||
};
|
||||
7F6877B11E7835E50094B63F /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 7F6877AA1E7835E50094B63F /* ToolTipMenu.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 4681C02C1B05271A004D67D4;
|
||||
remoteInfo = ToolTipMenuTests;
|
||||
};
|
||||
7F6FF6B4203499F400150948 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
|
||||
|
|
@ -658,9 +644,12 @@
|
|||
00E356EE1AD99517003FC87E /* MattermostTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MattermostTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
00E356F21AD99517003FC87E /* MattermostTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MattermostTests.m; sourceTree = "<group>"; };
|
||||
031EF04FB2D14EEFAACBAA1A /* Roboto-Italic.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Roboto-Italic.ttf"; path = "../assets/fonts/Roboto-Italic.ttf"; sourceTree = "<group>"; };
|
||||
04AA5E8EF3B54735A11E3B95 /* MaterialCommunityIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = MaterialCommunityIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf"; sourceTree = "<group>"; };
|
||||
09FA716C56874BDDA30FE8C4 /* Roboto-Medium.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Roboto-Medium.ttf"; path = "../assets/fonts/Roboto-Medium.ttf"; sourceTree = "<group>"; };
|
||||
0A091BF1A3D04650AD306A0D /* Zocial.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Zocial.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Zocial.ttf"; sourceTree = "<group>"; };
|
||||
0E617BF0F36D4E738F51D169 /* OpenSans-SemiboldItalic.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "OpenSans-SemiboldItalic.ttf"; path = "../assets/fonts/OpenSans-SemiboldItalic.ttf"; sourceTree = "<group>"; };
|
||||
12D0B0E475FD46E29907305E /* Roboto-ThinItalic.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Roboto-ThinItalic.ttf"; path = "../assets/fonts/Roboto-ThinItalic.ttf"; sourceTree = "<group>"; };
|
||||
139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = "<group>"; };
|
||||
139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = "../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj"; sourceTree = "<group>"; };
|
||||
13B07F961A680F5B00A75B9A /* Mattermost.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Mattermost.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
|
|
@ -678,6 +667,7 @@
|
|||
2DCFD31D3F4A4154822AB532 /* Ionicons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Ionicons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Ionicons.ttf"; sourceTree = "<group>"; };
|
||||
32AC3D4EA79E44738A6E9766 /* OpenSans-BoldItalic.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "OpenSans-BoldItalic.ttf"; path = "../assets/fonts/OpenSans-BoldItalic.ttf"; sourceTree = "<group>"; };
|
||||
349FBA7338E74D9BBD709528 /* 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>"; };
|
||||
34B20A903038487E8D7DEA1E /* Roboto-Light.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Roboto-Light.ttf"; path = "../assets/fonts/Roboto-Light.ttf"; sourceTree = "<group>"; };
|
||||
356C9186FA374641A00EB2EA /* MaterialIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = MaterialIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/MaterialIcons.ttf"; sourceTree = "<group>"; };
|
||||
3647DF63D6764CF093375861 /* OpenSans-ExtraBold.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "OpenSans-ExtraBold.ttf"; path = "../assets/fonts/OpenSans-ExtraBold.ttf"; sourceTree = "<group>"; };
|
||||
3752184A1F4B9E980035444B /* RCTCameraRoll.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTCameraRoll.xcodeproj; path = "../node_modules/react-native/Libraries/CameraRoll/RCTCameraRoll.xcodeproj"; sourceTree = "<group>"; };
|
||||
|
|
@ -697,6 +687,8 @@
|
|||
6561AEAC21CC40B8A72ABB93 /* OpenSans-Light.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "OpenSans-Light.ttf"; path = "../assets/fonts/OpenSans-Light.ttf"; sourceTree = "<group>"; };
|
||||
65FD5EA57EBAE06106094B2F /* libPods-Mattermost.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Mattermost.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
6BAF8296411D4657B5A0E8F8 /* libRNReactNativeDocViewer.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNReactNativeDocViewer.a; sourceTree = "<group>"; };
|
||||
6EFF13DD24CE4E26953E598A /* Roboto-Black.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Roboto-Black.ttf"; path = "../assets/fonts/Roboto-Black.ttf"; sourceTree = "<group>"; };
|
||||
71E626D4980A4560B26F0E1C /* Roboto-Bold.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Roboto-Bold.ttf"; path = "../assets/fonts/Roboto-Bold.ttf"; sourceTree = "<group>"; };
|
||||
74D116A3208A8C8400CF8A79 /* libRNKeychain.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libRNKeychain.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
74D116A4208A8D3000CF8A79 /* RNKeychain.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RNKeychain.xcodeproj; path = "../node_modules/react-native-keychain/RNKeychain.xcodeproj"; sourceTree = "<group>"; };
|
||||
7535D128F00C4A47A182627E /* libRNCookieManagerIOS.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNCookieManagerIOS.a; sourceTree = "<group>"; };
|
||||
|
|
@ -713,11 +705,11 @@
|
|||
7F43D6051F6BF9EB001FC614 /* libPods-Mattermost.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libPods-Mattermost.a"; path = "../../../../../../../Library/Developer/Xcode/DerivedData/Mattermost-czlinsdviifujheezzjvmisotjrm/Build/Products/Debug-iphonesimulator/libPods-Mattermost.a"; sourceTree = "<group>"; };
|
||||
7F50C968203C6E80007CA374 /* SessionManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SessionManager.h; sourceTree = "<group>"; };
|
||||
7F50C969203C6E80007CA374 /* SessionManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SessionManager.m; sourceTree = "<group>"; };
|
||||
7F54ABFAE6CE4A6DB11D1ED7 /* Roboto-BlackItalic.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Roboto-BlackItalic.ttf"; path = "../assets/fonts/Roboto-BlackItalic.ttf"; sourceTree = "<group>"; };
|
||||
7F5CA956208FE38F004F91CE /* RNDocumentPicker.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RNDocumentPicker.xcodeproj; path = "../node_modules/react-native-document-picker/ios/RNDocumentPicker.xcodeproj"; sourceTree = "<group>"; };
|
||||
7F63D27B1E6C957C001FAE12 /* RCTPushNotification.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTPushNotification.xcodeproj; path = "../node_modules/react-native/Libraries/PushNotificationIOS/RCTPushNotification.xcodeproj"; sourceTree = "<group>"; };
|
||||
7F63D2C21E6DD98A001FAE12 /* Mattermost.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = Mattermost.entitlements; path = Mattermost/Mattermost.entitlements; sourceTree = "<group>"; };
|
||||
7F642DE72093530B00F3165E /* RNDeviceInfo.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RNDeviceInfo.xcodeproj; path = "../node_modules/react-native-device-info/ios/RNDeviceInfo.xcodeproj"; sourceTree = "<group>"; };
|
||||
7F6877AA1E7835E50094B63F /* ToolTipMenu.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ToolTipMenu.xcodeproj; path = "../node_modules/react-native-tooltip/ToolTipMenu.xcodeproj"; sourceTree = "<group>"; };
|
||||
7F6C47A31FE87E8C00F5A912 /* PerformRequests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PerformRequests.h; sourceTree = "<group>"; };
|
||||
7F6C47A41FE87E8C00F5A912 /* PerformRequests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PerformRequests.m; sourceTree = "<group>"; };
|
||||
7F7D7F52201645D300D31155 /* ReactNativePermissions.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ReactNativePermissions.xcodeproj; path = "../node_modules/react-native-permissions/ios/ReactNativePermissions.xcodeproj"; sourceTree = "<group>"; };
|
||||
|
|
@ -754,17 +746,22 @@
|
|||
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = "<group>"; };
|
||||
849D881A0372465294DE7315 /* RNSafeArea.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNSafeArea.xcodeproj; path = "../node_modules/react-native-safe-area/ios/RNSafeArea.xcodeproj"; sourceTree = "<group>"; };
|
||||
8606EB1EB7E349EF8248933E /* libz.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
|
||||
8F0B22D2C9924FAFA7FB681C /* Roboto-LightItalic.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Roboto-LightItalic.ttf"; path = "../assets/fonts/Roboto-LightItalic.ttf"; sourceTree = "<group>"; };
|
||||
9263CF9B16054263B13EA23B /* libRNSafeArea.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNSafeArea.a; sourceTree = "<group>"; };
|
||||
9552041247E749308CE7B412 /* RNSentry.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNSentry.xcodeproj; path = "../node_modules/react-native-sentry/ios/RNSentry.xcodeproj"; sourceTree = "<group>"; };
|
||||
A2968536BEC74A4ABBB73BD9 /* RCTYouTube.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RCTYouTube.xcodeproj; path = "../node_modules/react-native-youtube/RCTYouTube.xcodeproj"; sourceTree = "<group>"; };
|
||||
A734E00E7E184582A877F2B3 /* Roboto-Thin.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Roboto-Thin.ttf"; path = "../assets/fonts/Roboto-Thin.ttf"; sourceTree = "<group>"; };
|
||||
AC6EB561E1F64C17A69D2FAD /* Entypo.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Entypo.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Entypo.ttf"; sourceTree = "<group>"; };
|
||||
ACC6B9FDC0AD45A6BFA4FBCD /* libBVLinearGradient.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libBVLinearGradient.a; sourceTree = "<group>"; };
|
||||
B89192186C764B9FA473403A /* libRCTVideo.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRCTVideo.a; sourceTree = "<group>"; };
|
||||
BC977883E2624E05975CA65B /* OpenSans-Regular.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "OpenSans-Regular.ttf"; path = "../assets/fonts/OpenSans-Regular.ttf"; sourceTree = "<group>"; };
|
||||
BE17F630DB5D41FD93F32D22 /* OpenSans-LightItalic.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "OpenSans-LightItalic.ttf"; path = "../assets/fonts/OpenSans-LightItalic.ttf"; sourceTree = "<group>"; };
|
||||
BFB7025EA936C1B5DC9725C2 /* Pods-Mattermost.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mattermost.release.xcconfig"; path = "Pods/Target Support Files/Pods-Mattermost/Pods-Mattermost.release.xcconfig"; sourceTree = "<group>"; };
|
||||
C46342B0E5FD4D878AF3A129 /* Roboto-BoldItalic.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Roboto-BoldItalic.ttf"; path = "../assets/fonts/Roboto-BoldItalic.ttf"; sourceTree = "<group>"; };
|
||||
C5BD64DE829E455A997DCAD5 /* Roboto-Regular.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Roboto-Regular.ttf"; path = "../assets/fonts/Roboto-Regular.ttf"; sourceTree = "<group>"; };
|
||||
C78A387124874496AD2C1466 /* OpenSans-Semibold.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "OpenSans-Semibold.ttf"; path = "../assets/fonts/OpenSans-Semibold.ttf"; sourceTree = "<group>"; };
|
||||
D0281D64B98143668D6AD42B /* RNLocalAuth.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNLocalAuth.xcodeproj; path = "../node_modules/react-native-local-auth/RNLocalAuth.xcodeproj"; sourceTree = "<group>"; };
|
||||
D08F54E10DF14AE4BBF4E2B4 /* Roboto-MediumItalic.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Roboto-MediumItalic.ttf"; path = "../assets/fonts/Roboto-MediumItalic.ttf"; sourceTree = "<group>"; };
|
||||
D4B1B363C2414DA19C1AC521 /* OpenSans-Bold.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "OpenSans-Bold.ttf"; path = "../assets/fonts/OpenSans-Bold.ttf"; sourceTree = "<group>"; };
|
||||
DF9DAAAA482343F3910A1A4C /* 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>"; };
|
||||
EBA6063A99C141098D40C67A /* RNPasscodeStatus.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNPasscodeStatus.xcodeproj; path = "../node_modules/react-native-passcode-status/ios/RNPasscodeStatus.xcodeproj"; sourceTree = "<group>"; };
|
||||
|
|
@ -773,18 +770,6 @@
|
|||
EE671DF7637347CD8C069819 /* libRNDeviceInfo.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNDeviceInfo.a; sourceTree = "<group>"; };
|
||||
F1F071EE85494E269A50AE88 /* SimpleLineIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = SimpleLineIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/SimpleLineIcons.ttf"; sourceTree = "<group>"; };
|
||||
FBBEC29EE2D3418D9AC33BD5 /* OpenSans-ExtraBoldItalic.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "OpenSans-ExtraBoldItalic.ttf"; path = "../assets/fonts/OpenSans-ExtraBoldItalic.ttf"; sourceTree = "<group>"; };
|
||||
6EFF13DD24CE4E26953E598A /* Roboto-Black.ttf */ = {isa = PBXFileReference; name = "Roboto-Black.ttf"; path = "../assets/fonts/Roboto-Black.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||
7F54ABFAE6CE4A6DB11D1ED7 /* Roboto-BlackItalic.ttf */ = {isa = PBXFileReference; name = "Roboto-BlackItalic.ttf"; path = "../assets/fonts/Roboto-BlackItalic.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||
71E626D4980A4560B26F0E1C /* Roboto-Bold.ttf */ = {isa = PBXFileReference; name = "Roboto-Bold.ttf"; path = "../assets/fonts/Roboto-Bold.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||
C46342B0E5FD4D878AF3A129 /* Roboto-BoldItalic.ttf */ = {isa = PBXFileReference; name = "Roboto-BoldItalic.ttf"; path = "../assets/fonts/Roboto-BoldItalic.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||
031EF04FB2D14EEFAACBAA1A /* Roboto-Italic.ttf */ = {isa = PBXFileReference; name = "Roboto-Italic.ttf"; path = "../assets/fonts/Roboto-Italic.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||
34B20A903038487E8D7DEA1E /* Roboto-Light.ttf */ = {isa = PBXFileReference; name = "Roboto-Light.ttf"; path = "../assets/fonts/Roboto-Light.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||
8F0B22D2C9924FAFA7FB681C /* Roboto-LightItalic.ttf */ = {isa = PBXFileReference; name = "Roboto-LightItalic.ttf"; path = "../assets/fonts/Roboto-LightItalic.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||
09FA716C56874BDDA30FE8C4 /* Roboto-Medium.ttf */ = {isa = PBXFileReference; name = "Roboto-Medium.ttf"; path = "../assets/fonts/Roboto-Medium.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||
D08F54E10DF14AE4BBF4E2B4 /* Roboto-MediumItalic.ttf */ = {isa = PBXFileReference; name = "Roboto-MediumItalic.ttf"; path = "../assets/fonts/Roboto-MediumItalic.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||
C5BD64DE829E455A997DCAD5 /* Roboto-Regular.ttf */ = {isa = PBXFileReference; name = "Roboto-Regular.ttf"; path = "../assets/fonts/Roboto-Regular.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||
A734E00E7E184582A877F2B3 /* Roboto-Thin.ttf */ = {isa = PBXFileReference; name = "Roboto-Thin.ttf"; path = "../assets/fonts/Roboto-Thin.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||
12D0B0E475FD46E29907305E /* Roboto-ThinItalic.ttf */ = {isa = PBXFileReference; name = "Roboto-ThinItalic.ttf"; path = "../assets/fonts/Roboto-ThinItalic.ttf"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
|
@ -820,7 +805,6 @@
|
|||
00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */,
|
||||
139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */,
|
||||
7F43D63F1F6BFA19001FC614 /* libBVLinearGradient.a in Frameworks */,
|
||||
7F6877B31E7836070094B63F /* libToolTipMenu.a in Frameworks */,
|
||||
7FC200E81EBB65370099331B /* libReactNativeNavigation.a in Frameworks */,
|
||||
7F2691A11EE1DC6A007574FE /* libRNNotifications.a in Frameworks */,
|
||||
7F43D5D61F6BF8C2001FC614 /* libRNLocalAuth.a in Frameworks */,
|
||||
|
|
@ -1194,15 +1178,6 @@
|
|||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7F6877AB1E7835E50094B63F /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7F6877B01E7835E50094B63F /* libToolTipMenu.a */,
|
||||
7F6877B21E7835E50094B63F /* ToolTipMenuTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7F7D7F53201645D300D31155 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
|
@ -1355,7 +1330,6 @@
|
|||
3752184A1F4B9E980035444B /* RCTCameraRoll.xcodeproj */,
|
||||
7F26919B1EE1DC51007574FE /* RNNotifications.xcodeproj */,
|
||||
7FC200BC1EBB65100099331B /* ReactNativeNavigation.xcodeproj */,
|
||||
7F6877AA1E7835E50094B63F /* ToolTipMenu.xcodeproj */,
|
||||
7F63D27B1E6C957C001FAE12 /* RCTPushNotification.xcodeproj */,
|
||||
5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */,
|
||||
146833FF1AC3E56700842450 /* React.xcodeproj */,
|
||||
|
|
@ -1694,10 +1668,6 @@
|
|||
ProductGroup = 7FDF28EE1E1F4B4E00DBBE56 /* Products */;
|
||||
ProjectRef = 2B25899FDAC149EB96ED3305 /* RNVectorIcons.xcodeproj */;
|
||||
},
|
||||
{
|
||||
ProductGroup = 7F6877AB1E7835E50094B63F /* Products */;
|
||||
ProjectRef = 7F6877AA1E7835E50094B63F /* ToolTipMenu.xcodeproj */;
|
||||
},
|
||||
);
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
|
|
@ -2045,20 +2015,6 @@
|
|||
remoteRef = 7F642DEE2093530B00F3165E /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
7F6877B01E7835E50094B63F /* libToolTipMenu.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = libToolTipMenu.a;
|
||||
remoteRef = 7F6877AF1E7835E50094B63F /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
7F6877B21E7835E50094B63F /* ToolTipMenuTests.xctest */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = wrapper.cfbundle;
|
||||
path = ToolTipMenuTests.xctest;
|
||||
remoteRef = 7F6877B11E7835E50094B63F /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
7F6FF6B5203499F400150948 /* libjsinspector.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
|
|
|
|||
5
package-lock.json
generated
|
|
@ -12891,11 +12891,6 @@
|
|||
"prop-types": "15.6.2"
|
||||
}
|
||||
},
|
||||
"react-native-tooltip": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-tooltip/-/react-native-tooltip-5.2.0.tgz",
|
||||
"integrity": "sha512-3mbPGd/VDfb3dUZmdmgg4eE8idJU4OyYM9ItGifnofz+Cz50Aua+sVGo2Ecc7zHV0S+kM0mOyLL758hhTz2gDw=="
|
||||
},
|
||||
"react-native-vector-icons": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-vector-icons/-/react-native-vector-icons-5.0.0.tgz",
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@
|
|||
"react-native-status-bar-size": "0.3.3",
|
||||
"react-native-svg": "7.0.2",
|
||||
"react-native-tableview": "2.3.1",
|
||||
"react-native-tooltip": "5.2.0",
|
||||
"react-native-vector-icons": "5.0.0",
|
||||
"react-native-video": "3.2.1",
|
||||
"react-native-youtube": "github:enahum/react-native-youtube#3f395b620ae4e05a3f1c6bdeef3a1158e78daadc",
|
||||
|
|
|
|||