[MM-18361] Style text inputs and post options with theme (#3213)

* Style text inputs with theme

* Add snapshot test

* Use theme for post options background and text colors

* Use theme for post options icon color

* Use theme for reaction list

* Use theme for slide up indicator

* Fix post options localization

* PM Feedback review

* Slideup PM changes and channel edit

* fix tests

* Fix i18n
This commit is contained in:
Miguel Alatzar 2019-09-13 06:24:36 -07:00 committed by Elias Nahum
parent 9f9a5f743c
commit b795a0bba4
21 changed files with 1175 additions and 305 deletions

View file

@ -0,0 +1,313 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`EditChannelInfo should match snapshot 1`] = `
<React.Fragment>
<Connect(StatusBar) />
<KeyboardAwareScrollViewMock
enableAutomaticScroll={true}
enableOnAndroid={false}
enableResetScrollToCoords={true}
extraHeight={75}
extraScrollHeight={0}
keyboardOpeningTime={250}
keyboardShouldPersistTaps="always"
style={
Object {
"backgroundColor": "#ffffff",
"flex": 1,
}
}
viewIsInsideTabBar={false}
>
<TouchableWithoutFeedback
onPress={[Function]}
>
<View
style={
Array [
Object {
"backgroundColor": "rgba(61,60,64,0.06)",
"flex": 1,
"paddingTop": 30,
},
Object {
"height": 600,
},
]
}
>
<View>
<View>
<FormattedText
defaultMessage="Name"
id="channel_modal.name"
style={
Array [
Object {
"color": "#3d3c40",
"fontSize": 14,
"marginLeft": 15,
},
Object {
"paddingHorizontal": 44,
},
]
}
/>
</View>
<View
style={
Array [
Object {
"backgroundColor": "#ffffff",
"marginTop": 10,
},
Object {
"paddingHorizontal": 44,
},
]
}
>
<TextInputWithLocalizedPlaceholder
autoCapitalize="none"
autoCorrect={false}
disableFullscreenUI={true}
keyboardAppearance="light"
onChangeText={[Function]}
placeholder={
Object {
"defaultMessage": "E.g.: \\"Bugs\\", \\"Marketing\\", \\"客户支持\\"",
"id": "channel_modal.nameEx",
}
}
placeholderTextColor="rgba(61,60,64,0.5)"
style={
Object {
"color": "#3d3c40",
"fontSize": 14,
"height": 40,
"paddingHorizontal": 15,
}
}
underlineColorAndroid="transparent"
value="display_name"
/>
</View>
</View>
<View>
<View
style={
Array [
Object {
"flexDirection": "row",
"marginTop": 30,
},
Object {
"paddingHorizontal": 44,
},
]
}
>
<FormattedText
defaultMessage="Purpose"
id="channel_modal.purpose"
style={
Object {
"color": "#3d3c40",
"fontSize": 14,
"marginLeft": 15,
}
}
/>
<FormattedText
defaultMessage="(optional)"
id="channel_modal.optional"
style={
Object {
"color": "rgba(61,60,64,0.5)",
"fontSize": 14,
"marginLeft": 5,
}
}
/>
</View>
<View
style={
Array [
Object {
"backgroundColor": "#ffffff",
"marginTop": 10,
},
Object {
"paddingHorizontal": 44,
},
]
}
>
<TextInputWithLocalizedPlaceholder
autoCapitalize="none"
autoCorrect={false}
blurOnSubmit={false}
disableFullscreenUI={true}
keyboardAppearance="light"
multiline={true}
onChangeText={[Function]}
placeholder={
Object {
"defaultMessage": "E.g.: \\"A channel to file bugs and improvements\\"",
"id": "channel_modal.purposeEx",
}
}
placeholderTextColor="rgba(61,60,64,0.5)"
style={
Array [
Object {
"color": "#3d3c40",
"fontSize": 14,
"height": 40,
"paddingHorizontal": 15,
},
Object {
"height": 110,
},
]
}
textAlignVertical="top"
underlineColorAndroid="transparent"
value="purpose"
/>
</View>
<View>
<FormattedText
defaultMessage="Describe how this channel should be used."
id="channel_modal.descriptionHelp"
style={
Array [
Object {
"color": "rgba(61,60,64,0.5)",
"fontSize": 14,
"marginHorizontal": 15,
"marginTop": 10,
},
Object {
"paddingHorizontal": 44,
},
]
}
/>
</View>
</View>
<View
style={
Array [
Object {
"flexDirection": "row",
"marginTop": 15,
},
Object {
"paddingHorizontal": 44,
},
]
}
>
<FormattedText
defaultMessage="Header"
id="channel_modal.header"
style={
Object {
"color": "#3d3c40",
"fontSize": 14,
"marginLeft": 15,
}
}
/>
<FormattedText
defaultMessage="(optional)"
id="channel_modal.optional"
style={
Object {
"color": "rgba(61,60,64,0.5)",
"fontSize": 14,
"marginLeft": 5,
}
}
/>
</View>
<ForwardRef(forwardConnectRef)
cursorPosition={6}
maxHeight={200}
nestedScrollEnabled={true}
onChangeText={[Function]}
value="header"
/>
<View
style={
Array [
Object {
"backgroundColor": "#ffffff",
"marginTop": 10,
},
Object {
"paddingHorizontal": 44,
},
]
}
>
<TextInputWithLocalizedPlaceholder
autoCapitalize="none"
autoCorrect={false}
blurOnSubmit={false}
disableFullscreenUI={true}
keyboardAppearance="light"
multiline={true}
onChangeText={[Function]}
onFocus={[Function]}
placeholder={
Object {
"defaultMessage": "E.g.: \\"[Link Title](http://example.com)\\"",
"id": "channel_modal.headerEx",
}
}
placeholderTextColor="rgba(61,60,64,0.5)"
style={
Array [
Object {
"color": "#3d3c40",
"fontSize": 14,
"height": 40,
"paddingHorizontal": 15,
},
Object {
"height": 110,
},
]
}
textAlignVertical="top"
underlineColorAndroid="transparent"
value="header"
/>
</View>
<View>
<FormattedText
defaultMessage="Set text that will appear in the header of the channel beside the channel name. For example, include frequently used links by typing [Link Title](http://example.com)."
id="channel_modal.headerHelp"
style={
Array [
Object {
"color": "rgba(61,60,64,0.5)",
"fontSize": 14,
"marginHorizontal": 15,
"marginTop": 10,
},
Object {
"paddingHorizontal": 44,
},
]
}
/>
</View>
</View>
</TouchableWithoutFeedback>
</KeyboardAwareScrollViewMock>
</React.Fragment>
`;

View file

@ -7,7 +7,6 @@ import {
Platform,
TouchableWithoutFeedback,
View,
Text,
findNodeHandle,
} from 'react-native';
import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view';
@ -27,7 +26,6 @@ import {
getKeyboardAppearanceFromTheme,
} from 'app/utils/theme';
import {getShortenedURL} from 'app/utils/url';
import {t} from 'app/utils/i18n';
import {paddingHorizontal as padding} from 'app/components/safe_area_view/iphone_x_spacing';
@ -138,17 +136,6 @@ export default class EditChannelInfo extends PureComponent {
this.props.enableRightButton(displayNameExists);
};
onDisplayURLChangeText = (channelURL) => {
const {editing, onChannelURLChange} = this.props;
onChannelURLChange(channelURL);
if (editing) {
const {displayName, purpose, header} = this.props;
const canUpdate = this.canUpdate(displayName, channelURL, purpose, header);
this.enableRightButton(canUpdate);
}
};
onPurposeChangeText = (purpose) => {
const {editing, onPurposeChange} = this.props;
onPurposeChange(purpose);
@ -180,20 +167,15 @@ export default class EditChannelInfo extends PureComponent {
render() {
const {
theme,
editing,
channelType,
currentTeamUrl,
deviceWidth,
deviceHeight,
displayName,
channelURL,
header,
purpose,
isLandscape,
} = this.props;
const {error, saving} = this.props;
const fullUrl = currentTeamUrl + '/channels';
const shortUrl = getShortenedURL(fullUrl, 35);
const style = getStyleSheet(theme);
@ -221,7 +203,7 @@ export default class EditChannelInfo extends PureComponent {
}
return (
<View style={style.container}>
<React.Fragment>
<StatusBar/>
<KeyboardAwareScrollView
ref={this.scroll}
@ -249,37 +231,7 @@ export default class EditChannelInfo extends PureComponent {
autoCapitalize='none'
autoCorrect={false}
placeholder={{id: t('channel_modal.nameEx'), defaultMessage: 'E.g.: "Bugs", "Marketing", "客户支持"'}}
placeholderTextColor={changeOpacity('#000', 0.5)}
underlineColorAndroid='transparent'
disableFullscreenUI={true}
keyboardAppearance={getKeyboardAppearanceFromTheme(theme)}
/>
</View>
</View>
)}
{/*TODO: Hide channel url field until it's added to CreateChannel */}
{false && editing && !displayHeaderOnly && (
<View>
<View style={[style.titleContainer30, padding(isLandscape)]}>
<FormattedText
style={style.title}
id='rename_channel.url'
defaultMessage='URL'
/>
<Text style={style.optional}>
{shortUrl}
</Text>
</View>
<View style={[style.inputContainer, padding(isLandscape)]}>
<TextInputWithLocalizedPlaceholder
ref={this.urlInput}
value={channelURL}
onChangeText={this.onDisplayURLChangeText}
style={style.input}
autoCapitalize='none'
autoCorrect={false}
placeholder={{id: t('rename_channel.handleHolder'), defaultMessage: 'lowercase alphanumeric characters'}}
placeholderTextColor={changeOpacity('#000', 0.5)}
placeholderTextColor={changeOpacity(theme.centerChannelColor, 0.5)}
underlineColorAndroid='transparent'
disableFullscreenUI={true}
keyboardAppearance={getKeyboardAppearanceFromTheme(theme)}
@ -310,7 +262,7 @@ export default class EditChannelInfo extends PureComponent {
autoCapitalize='none'
autoCorrect={false}
placeholder={{id: t('channel_modal.purposeEx'), defaultMessage: 'E.g.: "A channel to file bugs and improvements"'}}
placeholderTextColor={changeOpacity('#000', 0.5)}
placeholderTextColor={changeOpacity(theme.centerChannelColor, 0.5)}
multiline={true}
blurOnSubmit={false}
textAlignVertical='top'
@ -356,7 +308,7 @@ export default class EditChannelInfo extends PureComponent {
autoCapitalize='none'
autoCorrect={false}
placeholder={{id: t('channel_modal.headerEx'), defaultMessage: 'E.g.: "[Link Title](http://example.com)"'}}
placeholderTextColor={changeOpacity('#000', 0.5)}
placeholderTextColor={changeOpacity(theme.centerChannelColor, 0.5)}
multiline={true}
blurOnSubmit={false}
onFocus={this.scrollToEnd}
@ -376,7 +328,7 @@ export default class EditChannelInfo extends PureComponent {
</View>
</TouchableWithoutFeedback>
</KeyboardAwareScrollView>
</View>
</React.Fragment>
);
}
}
@ -389,11 +341,11 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
},
scrollView: {
flex: 1,
backgroundColor: changeOpacity(theme.centerChannelColor, 0.03),
paddingTop: 10,
backgroundColor: changeOpacity(theme.centerChannelColor, 0.06),
paddingTop: 30,
},
errorContainer: {
backgroundColor: changeOpacity(theme.centerChannelColor, 0.03),
backgroundColor: changeOpacity(theme.centerChannelColor, 0.06),
},
errorWrapper: {
justifyContent: 'center',
@ -401,10 +353,10 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
},
inputContainer: {
marginTop: 10,
backgroundColor: '#fff',
backgroundColor: theme.centerChannelBg,
},
input: {
color: '#333',
color: theme.centerChannelColor,
fontSize: 14,
height: 40,
paddingHorizontal: 15,

View file

@ -39,6 +39,14 @@ describe('EditChannelInfo', () => {
isLandscape: true,
};
test('should match snapshot', () => {
const wrapper = shallow(
<EditChannelInfo {...baseProps}/>
);
expect(wrapper.getElement()).toMatchSnapshot();
});
test('should have called onHeaderChangeText on text change from Autocomplete', () => {
const wrapper = shallow(
<EditChannelInfo {...baseProps}/>

View file

@ -61,7 +61,7 @@ exports[`PostTextBox should match, full snapshot 1`] = `
Array [
Object {
"alignItems": "stretch",
"backgroundColor": "#fff",
"backgroundColor": "#ffffff",
"flex": 1,
"flexDirection": "row",
"marginRight": 10,
@ -81,11 +81,11 @@ exports[`PostTextBox should match, full snapshot 1`] = `
onEndEditing={[Function]}
onSelectionChange={[Function]}
placeholder="Write to Test Channel"
placeholderTextColor="rgba(0,0,0,0.5)"
placeholderTextColor="rgba(61,60,64,0.5)"
rejectResponderTermination={true}
style={
Object {
"color": "#000",
"color": "#3d3c40",
"flex": 1,
"fontSize": 14,
"maxHeight": 100,

View file

@ -724,7 +724,7 @@ export default class PostTextBoxBase extends PureComponent {
onChangeText={this.handleTextChange}
onSelectionChange={this.handlePostDraftSelectionChanged}
placeholder={intl.formatMessage(placeholder, {channelDisplayName})}
placeholderTextColor={changeOpacity('#000', 0.5)}
placeholderTextColor={changeOpacity(theme.centerChannelColor, 0.5)}
multiline={true}
blurOnSubmit={false}
underlineColorAndroid='transparent'
@ -751,7 +751,7 @@ export default class PostTextBoxBase extends PureComponent {
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
return {
input: {
color: '#000',
color: theme.centerChannelColor,
flex: 1,
fontSize: 14,
maxHeight: MAX_CONTENT_HEIGHT,
@ -771,7 +771,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
inputContainer: {
flex: 1,
flexDirection: 'row',
backgroundColor: '#fff',
backgroundColor: theme.centerChannelBg,
alignItems: 'stretch',
marginRight: 10,
},

View file

@ -18,6 +18,7 @@ export default class SafeAreaIos extends PureComponent {
backgroundColor: PropTypes.string,
children: PropTypes.node.isRequired,
excludeHeader: PropTypes.bool,
excludeFooter: PropTypes.bool,
footerColor: PropTypes.string,
footerComponent: PropTypes.node,
forceTop: PropTypes.number,
@ -36,12 +37,17 @@ export default class SafeAreaIos extends PureComponent {
constructor(props) {
super(props);
let insetBottom = 0;
if ((DeviceTypes.IS_IPHONE_X || mattermostManaged.hasSafeAreaInsets) && props.excludeFooter) {
insetBottom = 20;
}
this.state = {
keyboard: false,
safeAreaInsets: {
top: DeviceTypes.IS_IPHONE_X ? 44 : 20,
left: 0,
bottom: DeviceTypes.IS_IPHONE_X || mattermostManaged.hasSafeAreaInsets ? 20 : 0,
bottom: insetBottom,
right: 0,
},
statusBarHeight: 20,
@ -152,7 +158,7 @@ export default class SafeAreaIos extends PureComponent {
};
render() {
const {backgroundColor, children, footerColor, footerComponent, keyboardOffset, theme, useLandscapeMargin} = this.props;
const {backgroundColor, children, excludeFooter, footerColor, footerComponent, keyboardOffset, theme, useLandscapeMargin} = this.props;
const {keyboard, safeAreaInsets} = this.state;
let bgColor = theme.centerChannelBg;
@ -170,6 +176,11 @@ export default class SafeAreaIos extends PureComponent {
offset = keyboardOffset;
}
let bottomInset = safeAreaInsets.bottom;
if (excludeFooter) {
bottomInset = 0;
}
return (
<View
style={{
@ -181,7 +192,7 @@ export default class SafeAreaIos extends PureComponent {
>
{this.renderTopBar()}
{children}
<View style={{height: keyboard ? offset : safeAreaInsets.bottom, backgroundColor: bottomColor}}>
<View style={{height: keyboard ? offset : bottomInset, backgroundColor: bottomColor}}>
{footerComponent}
</View>
</View>

View file

@ -0,0 +1,25 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`SlideUpPanelIndicator should match snapshot 1`] = `
<AnimatedComponent
style={
Object {
"alignItems": "center",
"justifyContent": "center",
"marginVertical": 10,
}
}
>
<View
style={
Object {
"backgroundColor": "white",
"borderRadius": 25,
"height": 5,
"opacity": 0.9,
"width": 62.5,
}
}
/>
</AnimatedComponent>
`;

View file

@ -14,6 +14,7 @@ import {
import {DeviceTypes} from 'app/constants';
import mattermostManaged from 'app/mattermost_managed';
import {hapticFeedback} from 'app/utils/general';
import {makeStyleSheetFromTheme} from 'app/utils/theme';
import SlideUpPanelIndicator from './slide_up_panel_indicator';
@ -43,6 +44,7 @@ export default class SlideUpPanel extends PureComponent {
// The space between the top of the panel and the top of the container when the SlideUpPanel is fully open.
marginFromTop: PropTypes.number,
onRequestClose: PropTypes.func,
theme: PropTypes.object.isRequired,
};
static defaultProps = {
@ -232,8 +234,11 @@ export default class SlideUpPanel extends PureComponent {
};
render() {
const {children, header} = this.props;
const {children, header, theme} = this.props;
const {lastSnap} = this.state;
const styles = getStyleSheet(theme);
const translateStyle = {
transform: [{translateY: this.translateY}],
};
@ -320,32 +325,34 @@ export default class SlideUpPanel extends PureComponent {
}
}
const styles = StyleSheet.create({
viewport: {
flex: 1,
},
container: {
flex: 1,
backgroundColor: 'white',
},
border: {
...Platform.select({
android: {
borderTopRightRadius: 2,
borderTopLeftRadius: 2,
},
ios: {
borderTopRightRadius: 10,
borderTopLeftRadius: 10,
},
}),
},
backdrop: {
backgroundColor: '#000',
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
},
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
return {
viewport: {
flex: 1,
},
container: {
flex: 1,
backgroundColor: theme.centerChannelBg,
},
border: {
...Platform.select({
android: {
borderTopRightRadius: 2,
borderTopLeftRadius: 2,
},
ios: {
borderTopRightRadius: 10,
borderTopLeftRadius: 10,
},
}),
},
backdrop: {
backgroundColor: '#000',
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
},
};
});

View file

@ -0,0 +1,21 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react';
import {shallow} from 'enzyme';
import SlideUpPanelIndicator from './slide_up_panel_indicator';
describe('SlideUpPanelIndicator', () => {
const baseProps = {
dragIndicatorColor: '#fff',
};
test('should match snapshot', () => {
const wrapper = shallow(
<SlideUpPanelIndicator {...baseProps}/>
);
expect(wrapper.getElement()).toMatchSnapshot();
});
});

View file

@ -296,7 +296,10 @@ export default class EditChannel extends PureComponent {
} = this.state;
return (
<SafeAreaView>
<SafeAreaView
excludeHeader={true}
excludeFooter={true}
>
<EditChannelInfo
theme={theme}
enableRightButton={this.emitCanUpdateChannel}

View file

@ -13,30 +13,174 @@ exports[`PostOptions should match snapshot, no option for system message to user
initialPosition={250}
marginFromTop={350}
onRequestClose={[Function]}
theme={
Object {
"awayIndicator": "#ffbc42",
"buttonBg": "#166de0",
"buttonColor": "#ffffff",
"centerChannelBg": "#ffffff",
"centerChannelColor": "#3d3c40",
"codeTheme": "github",
"dndIndicator": "#f74343",
"errorTextColor": "#fd5960",
"linkColor": "#2389d7",
"mentionBj": "#ffffff",
"mentionColor": "#145dbf",
"mentionHighlightBg": "#ffe577",
"mentionHighlightLink": "#166de0",
"newMessageSeparator": "#ff8800",
"onlineIndicator": "#06d6a0",
"sidebarBg": "#145dbf",
"sidebarHeaderBg": "#1153ab",
"sidebarHeaderTextColor": "#ffffff",
"sidebarText": "#ffffff",
"sidebarTextActiveBorder": "#579eff",
"sidebarTextActiveColor": "#ffffff",
"sidebarTextHoverBg": "#4578bf",
"sidebarUnreadText": "#ffffff",
"type": "Mattermost",
}
}
>
<PostOption
destructive={false}
icon="edit"
isLandscape={false}
onPress={[Function]}
text="Edit"
theme={
Object {
"awayIndicator": "#ffbc42",
"buttonBg": "#166de0",
"buttonColor": "#ffffff",
"centerChannelBg": "#ffffff",
"centerChannelColor": "#3d3c40",
"codeTheme": "github",
"dndIndicator": "#f74343",
"errorTextColor": "#fd5960",
"linkColor": "#2389d7",
"mentionBj": "#ffffff",
"mentionColor": "#145dbf",
"mentionHighlightBg": "#ffe577",
"mentionHighlightLink": "#166de0",
"newMessageSeparator": "#ff8800",
"onlineIndicator": "#06d6a0",
"sidebarBg": "#145dbf",
"sidebarHeaderBg": "#1153ab",
"sidebarHeaderTextColor": "#ffffff",
"sidebarText": "#ffffff",
"sidebarTextActiveBorder": "#579eff",
"sidebarTextActiveColor": "#ffffff",
"sidebarTextHoverBg": "#4578bf",
"sidebarUnreadText": "#ffffff",
"type": "Mattermost",
}
}
/>
<PostOption
destructive={false}
icon="reply"
isLandscape={false}
onPress={[Function]}
text="Reply"
theme={
Object {
"awayIndicator": "#ffbc42",
"buttonBg": "#166de0",
"buttonColor": "#ffffff",
"centerChannelBg": "#ffffff",
"centerChannelColor": "#3d3c40",
"codeTheme": "github",
"dndIndicator": "#f74343",
"errorTextColor": "#fd5960",
"linkColor": "#2389d7",
"mentionBj": "#ffffff",
"mentionColor": "#145dbf",
"mentionHighlightBg": "#ffe577",
"mentionHighlightLink": "#166de0",
"newMessageSeparator": "#ff8800",
"onlineIndicator": "#06d6a0",
"sidebarBg": "#145dbf",
"sidebarHeaderBg": "#1153ab",
"sidebarHeaderTextColor": "#ffffff",
"sidebarText": "#ffffff",
"sidebarTextActiveBorder": "#579eff",
"sidebarTextActiveColor": "#ffffff",
"sidebarTextHoverBg": "#4578bf",
"sidebarUnreadText": "#ffffff",
"type": "Mattermost",
}
}
/>
<PostOption
destructive={false}
icon="pin"
isLandscape={false}
onPress={[Function]}
text="Pin to Channel"
theme={
Object {
"awayIndicator": "#ffbc42",
"buttonBg": "#166de0",
"buttonColor": "#ffffff",
"centerChannelBg": "#ffffff",
"centerChannelColor": "#3d3c40",
"codeTheme": "github",
"dndIndicator": "#f74343",
"errorTextColor": "#fd5960",
"linkColor": "#2389d7",
"mentionBj": "#ffffff",
"mentionColor": "#145dbf",
"mentionHighlightBg": "#ffe577",
"mentionHighlightLink": "#166de0",
"newMessageSeparator": "#ff8800",
"onlineIndicator": "#06d6a0",
"sidebarBg": "#145dbf",
"sidebarHeaderBg": "#1153ab",
"sidebarHeaderTextColor": "#ffffff",
"sidebarText": "#ffffff",
"sidebarTextActiveBorder": "#579eff",
"sidebarTextActiveColor": "#ffffff",
"sidebarTextHoverBg": "#4578bf",
"sidebarUnreadText": "#ffffff",
"type": "Mattermost",
}
}
/>
<PostOption
destructive={false}
icon="emoji"
isLandscape={false}
onPress={[Function]}
text="Add Reaction"
theme={
Object {
"awayIndicator": "#ffbc42",
"buttonBg": "#166de0",
"buttonColor": "#ffffff",
"centerChannelBg": "#ffffff",
"centerChannelColor": "#3d3c40",
"codeTheme": "github",
"dndIndicator": "#f74343",
"errorTextColor": "#fd5960",
"linkColor": "#2389d7",
"mentionBj": "#ffffff",
"mentionColor": "#145dbf",
"mentionHighlightBg": "#ffe577",
"mentionHighlightLink": "#166de0",
"newMessageSeparator": "#ff8800",
"onlineIndicator": "#06d6a0",
"sidebarBg": "#145dbf",
"sidebarHeaderBg": "#1153ab",
"sidebarHeaderTextColor": "#ffffff",
"sidebarText": "#ffffff",
"sidebarTextActiveBorder": "#579eff",
"sidebarTextActiveColor": "#ffffff",
"sidebarTextHoverBg": "#4578bf",
"sidebarUnreadText": "#ffffff",
"type": "Mattermost",
}
}
/>
</ForwardRef(forwardConnectRef)>
</View>
@ -55,30 +199,174 @@ exports[`PostOptions should match snapshot, showing Delete option only for syste
initialPosition={300}
marginFromTop={300}
onRequestClose={[Function]}
theme={
Object {
"awayIndicator": "#ffbc42",
"buttonBg": "#166de0",
"buttonColor": "#ffffff",
"centerChannelBg": "#ffffff",
"centerChannelColor": "#3d3c40",
"codeTheme": "github",
"dndIndicator": "#f74343",
"errorTextColor": "#fd5960",
"linkColor": "#2389d7",
"mentionBj": "#ffffff",
"mentionColor": "#145dbf",
"mentionHighlightBg": "#ffe577",
"mentionHighlightLink": "#166de0",
"newMessageSeparator": "#ff8800",
"onlineIndicator": "#06d6a0",
"sidebarBg": "#145dbf",
"sidebarHeaderBg": "#1153ab",
"sidebarHeaderTextColor": "#ffffff",
"sidebarText": "#ffffff",
"sidebarTextActiveBorder": "#579eff",
"sidebarTextActiveColor": "#ffffff",
"sidebarTextHoverBg": "#4578bf",
"sidebarUnreadText": "#ffffff",
"type": "Mattermost",
}
}
>
<PostOption
destructive={false}
icon="edit"
isLandscape={false}
onPress={[Function]}
text="Edit"
theme={
Object {
"awayIndicator": "#ffbc42",
"buttonBg": "#166de0",
"buttonColor": "#ffffff",
"centerChannelBg": "#ffffff",
"centerChannelColor": "#3d3c40",
"codeTheme": "github",
"dndIndicator": "#f74343",
"errorTextColor": "#fd5960",
"linkColor": "#2389d7",
"mentionBj": "#ffffff",
"mentionColor": "#145dbf",
"mentionHighlightBg": "#ffe577",
"mentionHighlightLink": "#166de0",
"newMessageSeparator": "#ff8800",
"onlineIndicator": "#06d6a0",
"sidebarBg": "#145dbf",
"sidebarHeaderBg": "#1153ab",
"sidebarHeaderTextColor": "#ffffff",
"sidebarText": "#ffffff",
"sidebarTextActiveBorder": "#579eff",
"sidebarTextActiveColor": "#ffffff",
"sidebarTextHoverBg": "#4578bf",
"sidebarUnreadText": "#ffffff",
"type": "Mattermost",
}
}
/>
<PostOption
destructive={false}
icon="reply"
isLandscape={false}
onPress={[Function]}
text="Reply"
theme={
Object {
"awayIndicator": "#ffbc42",
"buttonBg": "#166de0",
"buttonColor": "#ffffff",
"centerChannelBg": "#ffffff",
"centerChannelColor": "#3d3c40",
"codeTheme": "github",
"dndIndicator": "#f74343",
"errorTextColor": "#fd5960",
"linkColor": "#2389d7",
"mentionBj": "#ffffff",
"mentionColor": "#145dbf",
"mentionHighlightBg": "#ffe577",
"mentionHighlightLink": "#166de0",
"newMessageSeparator": "#ff8800",
"onlineIndicator": "#06d6a0",
"sidebarBg": "#145dbf",
"sidebarHeaderBg": "#1153ab",
"sidebarHeaderTextColor": "#ffffff",
"sidebarText": "#ffffff",
"sidebarTextActiveBorder": "#579eff",
"sidebarTextActiveColor": "#ffffff",
"sidebarTextHoverBg": "#4578bf",
"sidebarUnreadText": "#ffffff",
"type": "Mattermost",
}
}
/>
<PostOption
destructive={false}
icon="pin"
isLandscape={false}
onPress={[Function]}
text="Pin to Channel"
theme={
Object {
"awayIndicator": "#ffbc42",
"buttonBg": "#166de0",
"buttonColor": "#ffffff",
"centerChannelBg": "#ffffff",
"centerChannelColor": "#3d3c40",
"codeTheme": "github",
"dndIndicator": "#f74343",
"errorTextColor": "#fd5960",
"linkColor": "#2389d7",
"mentionBj": "#ffffff",
"mentionColor": "#145dbf",
"mentionHighlightBg": "#ffe577",
"mentionHighlightLink": "#166de0",
"newMessageSeparator": "#ff8800",
"onlineIndicator": "#06d6a0",
"sidebarBg": "#145dbf",
"sidebarHeaderBg": "#1153ab",
"sidebarHeaderTextColor": "#ffffff",
"sidebarText": "#ffffff",
"sidebarTextActiveBorder": "#579eff",
"sidebarTextActiveColor": "#ffffff",
"sidebarTextHoverBg": "#4578bf",
"sidebarUnreadText": "#ffffff",
"type": "Mattermost",
}
}
/>
<PostOption
destructive={false}
icon="emoji"
isLandscape={false}
onPress={[Function]}
text="Add Reaction"
theme={
Object {
"awayIndicator": "#ffbc42",
"buttonBg": "#166de0",
"buttonColor": "#ffffff",
"centerChannelBg": "#ffffff",
"centerChannelColor": "#3d3c40",
"codeTheme": "github",
"dndIndicator": "#f74343",
"errorTextColor": "#fd5960",
"linkColor": "#2389d7",
"mentionBj": "#ffffff",
"mentionColor": "#145dbf",
"mentionHighlightBg": "#ffe577",
"mentionHighlightLink": "#166de0",
"newMessageSeparator": "#ff8800",
"onlineIndicator": "#06d6a0",
"sidebarBg": "#145dbf",
"sidebarHeaderBg": "#1153ab",
"sidebarHeaderTextColor": "#ffffff",
"sidebarText": "#ffffff",
"sidebarTextActiveBorder": "#579eff",
"sidebarTextActiveColor": "#ffffff",
"sidebarTextHoverBg": "#4578bf",
"sidebarUnreadText": "#ffffff",
"type": "Mattermost",
}
}
/>
<PostOption
destructive={true}
@ -86,6 +374,34 @@ exports[`PostOptions should match snapshot, showing Delete option only for syste
isLandscape={false}
onPress={[Function]}
text="Delete"
theme={
Object {
"awayIndicator": "#ffbc42",
"buttonBg": "#166de0",
"buttonColor": "#ffffff",
"centerChannelBg": "#ffffff",
"centerChannelColor": "#3d3c40",
"codeTheme": "github",
"dndIndicator": "#f74343",
"errorTextColor": "#fd5960",
"linkColor": "#2389d7",
"mentionBj": "#ffffff",
"mentionColor": "#145dbf",
"mentionHighlightBg": "#ffe577",
"mentionHighlightLink": "#166de0",
"newMessageSeparator": "#ff8800",
"onlineIndicator": "#06d6a0",
"sidebarBg": "#145dbf",
"sidebarHeaderBg": "#1153ab",
"sidebarHeaderTextColor": "#ffffff",
"sidebarText": "#ffffff",
"sidebarTextActiveBorder": "#579eff",
"sidebarTextActiveColor": "#ffffff",
"sidebarTextHoverBg": "#4578bf",
"sidebarUnreadText": "#ffffff",
"type": "Mattermost",
}
}
/>
</ForwardRef(forwardConnectRef)>
</View>
@ -104,30 +420,174 @@ exports[`PostOptions should match snapshot, showing all possible options 1`] = `
initialPosition={300}
marginFromTop={300}
onRequestClose={[Function]}
theme={
Object {
"awayIndicator": "#ffbc42",
"buttonBg": "#166de0",
"buttonColor": "#ffffff",
"centerChannelBg": "#ffffff",
"centerChannelColor": "#3d3c40",
"codeTheme": "github",
"dndIndicator": "#f74343",
"errorTextColor": "#fd5960",
"linkColor": "#2389d7",
"mentionBj": "#ffffff",
"mentionColor": "#145dbf",
"mentionHighlightBg": "#ffe577",
"mentionHighlightLink": "#166de0",
"newMessageSeparator": "#ff8800",
"onlineIndicator": "#06d6a0",
"sidebarBg": "#145dbf",
"sidebarHeaderBg": "#1153ab",
"sidebarHeaderTextColor": "#ffffff",
"sidebarText": "#ffffff",
"sidebarTextActiveBorder": "#579eff",
"sidebarTextActiveColor": "#ffffff",
"sidebarTextHoverBg": "#4578bf",
"sidebarUnreadText": "#ffffff",
"type": "Mattermost",
}
}
>
<PostOption
destructive={false}
icon="edit"
isLandscape={false}
onPress={[Function]}
text="Edit"
theme={
Object {
"awayIndicator": "#ffbc42",
"buttonBg": "#166de0",
"buttonColor": "#ffffff",
"centerChannelBg": "#ffffff",
"centerChannelColor": "#3d3c40",
"codeTheme": "github",
"dndIndicator": "#f74343",
"errorTextColor": "#fd5960",
"linkColor": "#2389d7",
"mentionBj": "#ffffff",
"mentionColor": "#145dbf",
"mentionHighlightBg": "#ffe577",
"mentionHighlightLink": "#166de0",
"newMessageSeparator": "#ff8800",
"onlineIndicator": "#06d6a0",
"sidebarBg": "#145dbf",
"sidebarHeaderBg": "#1153ab",
"sidebarHeaderTextColor": "#ffffff",
"sidebarText": "#ffffff",
"sidebarTextActiveBorder": "#579eff",
"sidebarTextActiveColor": "#ffffff",
"sidebarTextHoverBg": "#4578bf",
"sidebarUnreadText": "#ffffff",
"type": "Mattermost",
}
}
/>
<PostOption
destructive={false}
icon="reply"
isLandscape={false}
onPress={[Function]}
text="Reply"
theme={
Object {
"awayIndicator": "#ffbc42",
"buttonBg": "#166de0",
"buttonColor": "#ffffff",
"centerChannelBg": "#ffffff",
"centerChannelColor": "#3d3c40",
"codeTheme": "github",
"dndIndicator": "#f74343",
"errorTextColor": "#fd5960",
"linkColor": "#2389d7",
"mentionBj": "#ffffff",
"mentionColor": "#145dbf",
"mentionHighlightBg": "#ffe577",
"mentionHighlightLink": "#166de0",
"newMessageSeparator": "#ff8800",
"onlineIndicator": "#06d6a0",
"sidebarBg": "#145dbf",
"sidebarHeaderBg": "#1153ab",
"sidebarHeaderTextColor": "#ffffff",
"sidebarText": "#ffffff",
"sidebarTextActiveBorder": "#579eff",
"sidebarTextActiveColor": "#ffffff",
"sidebarTextHoverBg": "#4578bf",
"sidebarUnreadText": "#ffffff",
"type": "Mattermost",
}
}
/>
<PostOption
destructive={false}
icon="pin"
isLandscape={false}
onPress={[Function]}
text="Pin to Channel"
theme={
Object {
"awayIndicator": "#ffbc42",
"buttonBg": "#166de0",
"buttonColor": "#ffffff",
"centerChannelBg": "#ffffff",
"centerChannelColor": "#3d3c40",
"codeTheme": "github",
"dndIndicator": "#f74343",
"errorTextColor": "#fd5960",
"linkColor": "#2389d7",
"mentionBj": "#ffffff",
"mentionColor": "#145dbf",
"mentionHighlightBg": "#ffe577",
"mentionHighlightLink": "#166de0",
"newMessageSeparator": "#ff8800",
"onlineIndicator": "#06d6a0",
"sidebarBg": "#145dbf",
"sidebarHeaderBg": "#1153ab",
"sidebarHeaderTextColor": "#ffffff",
"sidebarText": "#ffffff",
"sidebarTextActiveBorder": "#579eff",
"sidebarTextActiveColor": "#ffffff",
"sidebarTextHoverBg": "#4578bf",
"sidebarUnreadText": "#ffffff",
"type": "Mattermost",
}
}
/>
<PostOption
destructive={false}
icon="emoji"
isLandscape={false}
onPress={[Function]}
text="Add Reaction"
theme={
Object {
"awayIndicator": "#ffbc42",
"buttonBg": "#166de0",
"buttonColor": "#ffffff",
"centerChannelBg": "#ffffff",
"centerChannelColor": "#3d3c40",
"codeTheme": "github",
"dndIndicator": "#f74343",
"errorTextColor": "#fd5960",
"linkColor": "#2389d7",
"mentionBj": "#ffffff",
"mentionColor": "#145dbf",
"mentionHighlightBg": "#ffe577",
"mentionHighlightLink": "#166de0",
"newMessageSeparator": "#ff8800",
"onlineIndicator": "#06d6a0",
"sidebarBg": "#145dbf",
"sidebarHeaderBg": "#1153ab",
"sidebarHeaderTextColor": "#ffffff",
"sidebarText": "#ffffff",
"sidebarTextActiveBorder": "#579eff",
"sidebarTextActiveColor": "#ffffff",
"sidebarTextHoverBg": "#4578bf",
"sidebarUnreadText": "#ffffff",
"type": "Mattermost",
}
}
/>
<PostOption
destructive={true}
@ -135,6 +595,34 @@ exports[`PostOptions should match snapshot, showing all possible options 1`] = `
isLandscape={false}
onPress={[Function]}
text="Delete"
theme={
Object {
"awayIndicator": "#ffbc42",
"buttonBg": "#166de0",
"buttonColor": "#ffffff",
"centerChannelBg": "#ffffff",
"centerChannelColor": "#3d3c40",
"codeTheme": "github",
"dndIndicator": "#f74343",
"errorTextColor": "#fd5960",
"linkColor": "#2389d7",
"mentionBj": "#ffffff",
"mentionColor": "#145dbf",
"mentionHighlightBg": "#ffe577",
"mentionHighlightLink": "#166de0",
"newMessageSeparator": "#ff8800",
"onlineIndicator": "#06d6a0",
"sidebarBg": "#145dbf",
"sidebarHeaderBg": "#1153ab",
"sidebarHeaderTextColor": "#ffffff",
"sidebarText": "#ffffff",
"sidebarTextActiveBorder": "#579eff",
"sidebarTextActiveColor": "#ffffff",
"sidebarTextHoverBg": "#4578bf",
"sidebarUnreadText": "#ffffff",
"type": "Mattermost",
}
}
/>
</ForwardRef(forwardConnectRef)>
</View>

View file

@ -5,14 +5,16 @@ import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import {
Image,
StyleSheet,
Text,
Platform,
TouchableHighlight,
TouchableNativeFeedback,
View,
} from 'react-native';
import {paddingLeft as padding} from 'app/components/safe_area_view/iphone_x_spacing';
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
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';
@ -40,6 +42,7 @@ export default class PostOption extends PureComponent {
onPress: PropTypes.func.isRequired,
text: PropTypes.string.isRequired,
isLandscape: PropTypes.bool.isRequired,
theme: PropTypes.object.isRequired,
};
handleOnPress = () => {
@ -50,7 +53,8 @@ export default class PostOption extends PureComponent {
};
render() {
const {destructive, icon, text, isLandscape} = this.props;
const {destructive, icon, text, isLandscape, theme} = this.props;
const style = getStyleSheet(theme);
const image = icons[icon];
const Touchable = Platform.select({
@ -78,8 +82,11 @@ export default class PostOption extends PureComponent {
style={[style.row, padding(isLandscape)]}
>
<View style={style.row}>
<View style={style.icon}>
<Image source={image}/>
<View style={[style.icon]}>
<Image
source={image}
style={[style.iconImage, destructive ? style.destructiveIconImage : null]}
/>
</View>
<View style={style.textContainer}>
<Text style={[style.text, destructive ? style.destructive : null]}>
@ -94,41 +101,49 @@ export default class PostOption extends PureComponent {
}
}
const style = StyleSheet.create({
container: {
height: 51,
width: '100%',
},
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)',
},
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
return {
container: {
height: 51,
width: '100%',
},
destructive: {
color: '#D0021B',
},
destructiveIconImage: {
tintColor: '#D0021B',
},
row: {
flex: 1,
flexDirection: 'row',
},
icon: {
alignItems: 'center',
height: 50,
justifyContent: 'center',
width: 60,
},
iconImage: {
tintColor: theme.centerChannelColor,
},
textContainer: {
justifyContent: 'center',
flex: 1,
height: 50,
marginRight: 5,
},
text: {
color: theme.centerChannelColor,
fontSize: 16,
lineHeight: 19,
opacity: 0.9,
letterSpacing: -0.45,
},
footer: {
height: 1,
marginLeft: 60,
borderBottomWidth: 1,
borderBottomColor: changeOpacity(theme.centerChannelColor, 0.2),
},
};
});

View file

@ -11,6 +11,7 @@ import EventEmitter from 'mattermost-redux/utils/event_emitter';
import SlideUpPanel from 'app/components/slide_up_panel';
import {BOTTOM_MARGIN} from 'app/components/slide_up_panel/slide_up_panel';
import {t} from 'app/utils/i18n';
import {OPTION_HEIGHT, getInitialPosition} from './post_options_utils';
import PostOption from './post_option';
@ -66,181 +67,162 @@ export default class PostOptions extends PureComponent {
}
};
getAddReactionOption = () => {
getOption = (key, icon, message, onPress, destructive = false) => {
const {formatMessage} = this.context.intl;
const {canAddReaction, isLandscape} = this.props;
const {isLandscape, theme} = this.props;
return (
<PostOption
key={key}
icon={icon}
text={formatMessage(message)}
onPress={onPress}
isLandscape={isLandscape}
destructive={destructive}
theme={theme}
/>
);
}
getAddReactionOption = () => {
const {canAddReaction} = this.props;
if (canAddReaction) {
return (
<PostOption
key='reaction'
icon='emoji'
text={formatMessage({id: 'mobile.post_info.add_reaction', defaultMessage: 'Add Reaction'})}
onPress={this.handleAddReaction}
isLandscape={isLandscape}
/>
);
const key = 'reaction';
const icon = 'emoji';
const message = {id: t('mobile.post_info.add_reaction'), defaultMessage: 'Add Reaction'};
const onPress = this.handleAddReaction;
return this.getOption(key, icon, message, onPress);
}
return null;
};
getReplyOption = () => {
const {formatMessage} = this.context.intl;
const {canReply, isLandscape} = this.props;
const {canReply} = this.props;
if (canReply) {
return (
<PostOption
key='reply'
icon='reply'
text={formatMessage({id: 'mobile.post_info.reply', defaultMessage: 'Reply'})}
onPress={this.handleReply}
isLandscape={isLandscape}
/>
);
const key = 'reply';
const icon = 'reply';
const message = {id: t('mobile.post_info.reply'), defaultMessage: 'Reply'};
const onPress = this.handleReply;
return this.getOption(key, icon, message, onPress);
}
return null;
}
getCopyPermalink = () => {
const {formatMessage} = this.context.intl;
const {canCopyPermalink, isLandscape} = this.props;
const {canCopyPermalink} = this.props;
if (canCopyPermalink) {
return (
<PostOption
key='permalink'
icon='link'
text={formatMessage({id: 'get_post_link_modal.title', defaultMessage: 'Copy Permalink'})}
onPress={this.handleCopyPermalink}
isLandscape={isLandscape}
/>
);
const key = 'permalink';
const icon = 'link';
const message = {id: t('get_post_link_modal.title'), defaultMessage: 'Copy Permalink'};
const onPress = this.handleCopyPermalink;
return this.getOption(key, icon, message, onPress);
}
return null;
};
getCopyText = () => {
const {formatMessage} = this.context.intl;
const {canCopyText, isLandscape} = this.props;
const {canCopyText} = this.props;
if (canCopyText) {
return (
<PostOption
key='copy'
icon='copy'
text={formatMessage({id: 'mobile.post_info.copy_text', defaultMessage: 'Copy Text'})}
onPress={this.handleCopyText}
isLandscape={isLandscape}
/>
);
const key = 'copy';
const icon = 'copy';
const message = {id: t('mobile.post_info.copy_text'), defaultMessage: 'Copy Text'};
const onPress = this.handleCopyText;
return this.getOption(key, icon, message, onPress);
}
return null;
};
getDeleteOption = () => {
const {formatMessage} = this.context.intl;
const {canDelete, isLandscape} = this.props;
const {canDelete} = this.props;
if (canDelete) {
return (
<PostOption
destructive={true}
key='delete'
icon='trash'
text={formatMessage({id: 'post_info.del', defaultMessage: 'Delete'})}
onPress={this.handlePostDelete}
isLandscape={isLandscape}
/>
);
const key = 'delete';
const icon = 'trash';
const message = {id: t('post_info.del'), defaultMessage: 'Delete'};
const onPress = this.handlePostDelete;
const destructive = true;
return this.getOption(key, icon, message, onPress, destructive);
}
return null;
};
getEditOption = () => {
const {formatMessage} = this.context.intl;
const {canEdit, canEditUntil, isLandscape} = this.props;
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}
isLandscape={isLandscape}
/>
);
const key = 'edit';
const icon = 'edit';
const message = {id: t('post_info.edit'), defaultMessage: 'Edit'};
const onPress = this.handlePostEdit;
return this.getOption(key, icon, message, onPress);
}
return null;
};
getFlagOption = () => {
const {formatMessage} = this.context.intl;
const {canFlag, isFlagged, isLandscape} = this.props;
const {canFlag, isFlagged} = this.props;
if (!canFlag) {
return null;
}
let key;
let message;
let onPress;
const icon = 'flag';
if (isFlagged) {
return (
<PostOption
key='unflag'
icon='flag'
text={formatMessage({id: 'mobile.post_info.unflag', defaultMessage: 'Unflag'})}
onPress={this.handleUnflagPost}
isLandscape={isLandscape}
/>
);
key = 'unflag';
message = {id: t('mobile.post_info.unflag'), defaultMessage: 'Unflag'};
onPress = this.handleUnflagPost;
} else {
key = 'flagged';
message = {id: t('mobile.post_info.flag'), defaultMessage: 'Flag'};
onPress = this.handleFlagPost;
}
return (
<PostOption
key='flagged'
icon='flag'
text={formatMessage({id: 'mobile.post_info.flag', defaultMessage: 'Flag'})}
onPress={this.handleFlagPost}
isLandscape={isLandscape}
/>
);
return this.getOption(key, icon, message, onPress);
};
getPinOption = () => {
const {formatMessage} = this.context.intl;
const {canPin, post, isLandscape} = this.props;
const {canPin, post} = this.props;
if (!canPin) {
return null;
}
let key;
let message;
let onPress;
const icon = 'pin';
if (post.is_pinned) {
return (
<PostOption
key='unpin'
icon='pin'
text={formatMessage({id: 'mobile.post_info.unpin', defaultMessage: 'Unpin from Channel'})}
onPress={this.handleUnpinPost}
isLandscape={isLandscape}
/>
);
key = 'unpin';
message = {id: t('mobile.post_info.unpin'), defaultMessage: 'Unpin from Channel'};
onPress = this.handleUnpinPost;
} else {
key = 'pin';
message = {id: t('mobile.post_info.pin'), defaultMessage: 'Pin to Channel'};
onPress = this.handlePinPost;
}
return (
<PostOption
key='pin'
icon='pin'
text={formatMessage({id: 'mobile.post_info.pin', defaultMessage: 'Pin to Channel'})}
onPress={this.handlePinPost}
isLandscape={isLandscape}
/>
);
return this.getOption(key, icon, message, onPress);
};
getMyPostOptions = () => {
@ -410,7 +392,7 @@ export default class PostOptions extends PureComponent {
};
render() {
const {deviceHeight} = this.props;
const {deviceHeight, theme} = this.props;
const options = this.getPostOptions();
if (!options || !options.length) {
return null;
@ -428,6 +410,7 @@ export default class PostOptions extends PureComponent {
onRequestClose={this.close}
initialPosition={initialPosition}
key={marginFromTop}
theme={theme}
>
{options}
</SlideUpPanel>

View file

@ -5,7 +5,7 @@ exports[`ReactionHeader should match snapshot 1`] = `
<AnimatedComponent
style={
Object {
"backgroundColor": "#FFFFFF",
"backgroundColor": "#ffffff",
"borderTopLeftRadius": 10,
"borderTopRightRadius": 10,
"height": 36.5,

View file

@ -13,6 +13,34 @@ exports[`ReactionList should match snapshot 1`] = `
headerHeight={37.5}
initialPosition={0.55}
onRequestClose={[Function]}
theme={
Object {
"awayIndicator": "#ffbc42",
"buttonBg": "#166de0",
"buttonColor": "#ffffff",
"centerChannelBg": "#ffffff",
"centerChannelColor": "#3d3c40",
"codeTheme": "github",
"dndIndicator": "#f74343",
"errorTextColor": "#fd5960",
"linkColor": "#2389d7",
"mentionBj": "#ffffff",
"mentionColor": "#145dbf",
"mentionHighlightBg": "#ffe577",
"mentionHighlightLink": "#166de0",
"newMessageSeparator": "#ff8800",
"onlineIndicator": "#06d6a0",
"sidebarBg": "#145dbf",
"sidebarHeaderBg": "#1153ab",
"sidebarHeaderTextColor": "#ffffff",
"sidebarText": "#ffffff",
"sidebarTextActiveBorder": "#579eff",
"sidebarTextActiveColor": "#ffffff",
"sidebarTextHoverBg": "#4578bf",
"sidebarUnreadText": "#ffffff",
"type": "Mattermost",
}
}
>
<View
style={

View file

@ -7,10 +7,12 @@ import {
Animated,
Platform,
ScrollView,
StyleSheet,
} from 'react-native';
import {NativeViewGestureHandler} from 'react-native-gesture-handler';
import {paddingHorizontal as padding} from 'app/components/safe_area_view/iphone_x_spacing';
import {makeStyleSheetFromTheme} from 'app/utils/theme';
import ReactionHeaderItem from './reaction_header_item';
export default class ReactionHeader extends PureComponent {
@ -43,11 +45,14 @@ export default class ReactionHeader extends PureComponent {
};
render() {
const {theme} = this.props;
const style = getStyleSheet(theme);
return (
<NativeViewGestureHandler
ref={this.props.forwardedRef}
>
<Animated.View style={styles.container}>
<Animated.View style={style.container}>
<ScrollView
alwaysBounceHorizontal={false}
horizontal={true}
@ -62,20 +67,22 @@ export default class ReactionHeader extends PureComponent {
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: '#FFFFFF',
height: 36.5,
paddingHorizontal: 0,
...Platform.select({
android: {
borderTopRightRadius: 2,
borderTopLeftRadius: 2,
},
ios: {
borderTopRightRadius: 10,
borderTopLeftRadius: 10,
},
}),
},
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
return {
container: {
backgroundColor: theme.centerChannelBg,
height: 36.5,
paddingHorizontal: 0,
...Platform.select({
android: {
borderTopRightRadius: 2,
borderTopLeftRadius: 2,
},
ios: {
borderTopRightRadius: 10,
borderTopLeftRadius: 10,
},
}),
},
};
});

View file

@ -181,7 +181,8 @@ export default class ReactionList extends PureComponent {
};
render() {
const style = getStyleSheet(this.props.theme);
const {theme} = this.props;
const style = getStyleSheet(theme);
return (
<View style={style.flex}>
@ -191,6 +192,7 @@ export default class ReactionList extends PureComponent {
initialPosition={0.55}
header={this.renderHeader}
headerHeight={37.5}
theme={theme}
>
{this.renderReactionRows()}
</SlideUpPanel>

View file

@ -55,6 +55,7 @@ exports[`ReactionRow should match snapshot, renderContent 1`] = `
<Text
style={
Object {
"color": "#3d3c40",
"fontSize": 14,
"paddingRight": 5,
}
@ -68,7 +69,7 @@ exports[`ReactionRow should match snapshot, renderContent 1`] = `
<Text
style={
Object {
"color": "rgba(0,0,0,0.5)",
"color": "rgba(61,60,64,0.5)",
"fontSize": 14,
}
}

View file

@ -7,7 +7,6 @@ import {intlShape} from 'react-intl';
import {
Text,
TouchableOpacity,
StyleSheet,
View,
} from 'react-native';
@ -15,7 +14,7 @@ import {displayUsername} from 'mattermost-redux/utils/user_utils';
import ProfilePicture from 'app/components/profile_picture';
import {preventDoubleTap} from 'app/utils/tap';
import {changeOpacity} from 'app/utils/theme';
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
import {paddingHorizontal as padding} from 'app/components/safe_area_view/iphone_x_spacing';
import Emoji from 'app/components/emoji';
@ -58,6 +57,7 @@ export default class ReactionRow extends React.PureComponent {
teammateNameDisplay,
user,
isLandscape,
theme,
} = this.props;
if (!user.id) {
@ -67,6 +67,8 @@ export default class ReactionRow extends React.PureComponent {
const {id, username} = user;
const usernameDisplay = '@' + username;
const style = getStyleSheet(theme);
return (
<View style={style.container}>
<View style={[style.profileContainer, padding(isLandscape)]}>
@ -107,36 +109,39 @@ export default class ReactionRow extends React.PureComponent {
}
}
const style = StyleSheet.create({
container: {
flexDirection: 'row',
justifyContent: 'flex-start',
height: 44,
width: '100%',
alignItems: 'center',
},
profileContainer: {
alignItems: 'center',
width: '13%',
},
profile: {
paddingTop: 3,
},
textContainer: {
width: '74%',
flexDirection: 'row',
},
username: {
fontSize: 14,
paddingRight: 5,
},
displayName: {
fontSize: 14,
color: changeOpacity('#000', 0.5),
},
emoji: {
alignItems: 'center',
width: '13%',
justifyContent: 'center',
},
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
return {
container: {
flexDirection: 'row',
justifyContent: 'flex-start',
height: 44,
width: '100%',
alignItems: 'center',
},
profileContainer: {
alignItems: 'center',
width: '13%',
},
profile: {
paddingTop: 3,
},
textContainer: {
width: '74%',
flexDirection: 'row',
},
username: {
fontSize: 14,
paddingRight: 5,
color: theme.centerChannelColor,
},
displayName: {
fontSize: 14,
color: changeOpacity(theme.centerChannelColor, 0.5),
},
emoji: {
alignItems: 'center',
width: '13%',
justifyContent: 'center',
},
};
});

View file

@ -157,7 +157,10 @@ class NotificationSettingsMobileIos extends NotificationSettingsMobileBase {
const style = getStyleSheet(theme);
return (
<SafeAreaView>
<SafeAreaView
excludeHeader={true}
excludeFooter={true}
>
<View style={style.container}>
<StatusBar/>
<ScrollView
@ -196,7 +199,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
backgroundColor: changeOpacity(theme.centerChannelColor, 0.06),
},
scrollViewContent: {
paddingVertical: 35,
paddingVertical: 30,
},
disabled: {
color: theme.centerChannelColor,

View file

@ -501,8 +501,6 @@
"post_info.system": "System",
"post_message_view.edited": "(edited)",
"posts_view.newMsg": "New Messages",
"rename_channel.handleHolder": "lowercase alphanumeric characters",
"rename_channel.url": "URL",
"rhs_thread.rootPostDeletedMessage.body": "Part of this thread has been deleted due to a data retention policy. You can no longer reply to this thread.",
"search_bar.search": "Search",
"search_header.results": "Search Results",