From 61de50cebecc8af0903752091fd3fde179e73d99 Mon Sep 17 00:00:00 2001 From: wreiske Date: Thu, 5 Sep 2019 03:39:26 -0400 Subject: [PATCH 01/11] Initial commit test proof of concept for user statuses in mobile app --- app/lib/rocketchat.js | 5 +++-- app/views/ProfileView/index.js | 30 +++++++++++++++++++++++------ app/views/RoomActionsView/index.js | 7 +++++-- app/views/RoomActionsView/styles.js | 6 ++++++ app/views/RoomInfoView/index.js | 4 +++- app/views/RoomInfoView/styles.js | 6 ++++++ app/views/RoomView/index.js | 6 +++++- app/views/RoomView/styles.js | 13 ++++++++++++- app/views/SidebarView/index.js | 21 ++++++++++++++++++++ 9 files changed, 85 insertions(+), 13 deletions(-) diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js index 05a1f6c6df8..2e5a7530c71 100644 --- a/app/lib/rocketchat.js +++ b/app/lib/rocketchat.js @@ -209,12 +209,12 @@ const RocketChat = { const { eventName } = ddpMessage.fields; if (eventName === 'user-status') { const userStatus = ddpMessage.fields.args[0]; - const [id, username, status] = userStatus; + const [id, username, status, statusText] = userStatus; if (username) { database.memoryDatabase.write(() => { try { database.memoryDatabase.create('activeUsers', { - id, username, status: STATUSES[status] + id, username, status: STATUSES[status], statusText }, true); } catch (error) { console.log(error); @@ -326,6 +326,7 @@ const RocketChat = { name: result.me.name, language: result.me.language, status: result.me.status, + statusText: result.me.statusText, customFields: result.me.customFields, emails: result.me.emails, roles: result.me.roles diff --git a/app/views/ProfileView/index.js b/app/views/ProfileView/index.js index aab3c76d3aa..2224307e1e1 100644 --- a/app/views/ProfileView/index.js +++ b/app/views/ProfileView/index.js @@ -53,7 +53,8 @@ class ProfileView extends React.Component { avatarUrl: null, avatar: {}, avatarSuggestions: {}, - customFields: {} + customFields: {}, + statusText: null } async componentDidMount() { @@ -102,13 +103,14 @@ class ProfileView extends React.Component { currentPassword: null, avatarUrl: null, avatar: {}, - customFields: customFields || {} + customFields: customFields || {}, + statusText: null }); } formIsChanged = () => { const { - name, username, email, newPassword, avatar, customFields + name, username, email, newPassword, avatar, customFields, statusText } = this.state; const { user } = this.props; let customFieldsChanged = false; @@ -128,6 +130,7 @@ class ProfileView extends React.Component { && (user.emails && user.emails[0].address === email) && !avatar.data && !customFieldsChanged + && !(user.statusText === statusText) ); } @@ -156,11 +159,16 @@ class ProfileView extends React.Component { this.setState({ saving: true }); const { - name, username, email, newPassword, currentPassword, avatar, customFields + name, username, email, newPassword, currentPassword, avatar, customFields, statusText } = this.state; const { user, setUser } = this.props; const params = {}; + // Status Text + if (user.statusText !== statusText) { + params.statusText = statusText; + } + // Name if (user.name !== name) { params.name = name; @@ -364,7 +372,7 @@ class ProfileView extends React.Component { render() { const { - name, username, email, newPassword, avatarUrl, customFields, avatar, saving, showPasswordAlert + name, username, email, newPassword, avatarUrl, customFields, avatar, saving, showPasswordAlert, statusText } = this.state; const { baseUrl, user } = this.props; @@ -390,6 +398,15 @@ class ProfileView extends React.Component { token={user.token} /> + { this.statusText = e; }} + label={I18n.t('Status')} + placeholder={I18n.t('Status')} + value={statusText} + onChangeText={value => this.setState({ statusText: value })} + onSubmitEditing={() => { this.statusText.focus(); }} + testID='profile-view-status' + /> { this.name = e; }} label={I18n.t('Name')} @@ -481,7 +498,8 @@ const mapStateToProps = state => ({ username: state.login.user && state.login.user.username, customFields: state.login.user && state.login.user.customFields, emails: state.login.user && state.login.user.emails, - token: state.login.user && state.login.user.token + token: state.login.user && state.login.user.token, + statusText: state.login.user && state.login.user.statusText }, Accounts_CustomFields: state.settings.Accounts_CustomFields, baseUrl: state.settings.Site_Url || state.server ? state.server.server : '' diff --git a/app/views/RoomActionsView/index.js b/app/views/RoomActionsView/index.js index fb7c0319244..bbf94447c49 100644 --- a/app/views/RoomActionsView/index.js +++ b/app/views/RoomActionsView/index.js @@ -36,7 +36,8 @@ class RoomActionsView extends React.Component { navigation: PropTypes.object, user: PropTypes.shape({ id: PropTypes.string, - token: PropTypes.string + token: PropTypes.string, + statusText: PropTypes.string }), leaveRoom: PropTypes.func } @@ -417,6 +418,7 @@ class RoomActionsView extends React.Component { ) } {t === 'd' ? `@${ name }` : topic} + {t === 'd' ? {user.statusText} : null } , ], item) @@ -484,7 +486,8 @@ class RoomActionsView extends React.Component { const mapStateToProps = state => ({ user: { id: state.login.user && state.login.user.id, - token: state.login.user && state.login.user.token + token: state.login.user && state.login.user.token, + statusText: state.login.user && state.login.user.statusText }, baseUrl: state.settings.Site_Url || state.server ? state.server.server : '' }); diff --git a/app/views/RoomActionsView/styles.js b/app/views/RoomActionsView/styles.js index ee0939aba94..a929146ae56 100644 --- a/app/views/RoomActionsView/styles.js +++ b/app/views/RoomActionsView/styles.js @@ -72,5 +72,11 @@ export default StyleSheet.create({ roomTitleRow: { flexDirection: 'row', alignItems: 'center' + }, + statusText: { + paddingTop: 5, + fontSize: 14, + ...sharedStyles.textColorDescription, + ...sharedStyles.textMedium } }); diff --git a/app/views/RoomInfoView/index.js b/app/views/RoomInfoView/index.js index 70aba107187..97e9d7d4786 100644 --- a/app/views/RoomInfoView/index.js +++ b/app/views/RoomInfoView/index.js @@ -273,6 +273,7 @@ class RoomInfoView extends React.Component { {this.renderAvatar(room, roomUser)} { getRoomTitle(room, this.t, roomUser && roomUser.name) } + {this.t === 'd' ? {roomUser.statusText} : null } {this.isDirect() ? this.renderDirect() : this.renderChannel()} @@ -285,7 +286,8 @@ const mapStateToProps = state => ({ baseUrl: state.settings.Site_Url || state.server ? state.server.server : '', user: { id: state.login.user && state.login.user.id, - token: state.login.user && state.login.user.token + token: state.login.user && state.login.user.token, + statusText: state.login.user && state.login.user.statusText }, Message_TimeFormat: state.settings.Message_TimeFormat }); diff --git a/app/views/RoomInfoView/styles.js b/app/views/RoomInfoView/styles.js index faeaf9101c4..bf1bad732a0 100644 --- a/app/views/RoomInfoView/styles.js +++ b/app/views/RoomInfoView/styles.js @@ -74,5 +74,11 @@ export default StyleSheet.create({ fontSize: 14, ...sharedStyles.textColorNormal, ...sharedStyles.textRegular + }, + statusText: { + paddingTop: 10, + fontSize: 18, + ...sharedStyles.textColorDescription, + ...sharedStyles.textMedium } }); diff --git a/app/views/RoomView/index.js b/app/views/RoomView/index.js index 9667476b57f..c4fdfbfd37b 100644 --- a/app/views/RoomView/index.js +++ b/app/views/RoomView/index.js @@ -624,6 +624,9 @@ class RoomView extends React.Component { return ( + + {this.t === 'd' ? {user.statusText} : null } + {this.renderFooter()} {this.renderActions()} @@ -652,7 +655,8 @@ const mapStateToProps = state => ({ user: { id: state.login.user && state.login.user.id, username: state.login.user && state.login.user.username, - token: state.login.user && state.login.user.token + token: state.login.user && state.login.user.token, + statusText: state.login.user && state.login.user.statusText }, actionMessage: state.messages.actionMessage, editing: state.messages.editing, diff --git a/app/views/RoomView/styles.js b/app/views/RoomView/styles.js index 11fcfd6707f..0979ce20c3f 100644 --- a/app/views/RoomView/styles.js +++ b/app/views/RoomView/styles.js @@ -1,7 +1,7 @@ import { StyleSheet } from 'react-native'; import { - COLOR_SEPARATOR, COLOR_PRIMARY, COLOR_WHITE, COLOR_TEXT_DESCRIPTION + COLOR_SEPARATOR, COLOR_PRIMARY, COLOR_WHITE, COLOR_TEXT_DESCRIPTION, COLOR_BACKGROUND_NOTIFICATION } from '../../constants/colors'; import sharedStyles from '../Styles'; @@ -64,5 +64,16 @@ export default StyleSheet.create({ fontSize: 16, ...sharedStyles.textMedium, ...sharedStyles.textColorNormal + }, + statusTextContainer: { + padding: 10, + backgroundColor: '#292929', + justifyContent: 'flex-end', + alignItems: 'center' + }, + statusText: { + fontSize: 14, + color: COLOR_WHITE, + ...sharedStyles.textMedium } }); diff --git a/app/views/SidebarView/index.js b/app/views/SidebarView/index.js index 0e944e1142b..c256dba8b4b 100644 --- a/app/views/SidebarView/index.js +++ b/app/views/SidebarView/index.js @@ -88,6 +88,9 @@ class Sidebar extends Component { if (nextProps.user.status !== user.status) { return true; } + if (nextProps.user.statusText !== user.statusText) { + return true; + } if (nextProps.user.username !== user.username) { return true; } @@ -210,6 +213,21 @@ class Sidebar extends Component { ); } + renderStatusText = () => { + const { activeItemKey, user } = this.props; + return ( + + } + onPress={() => this.sidebarNavigate('RoomsListView')} + testID='sidebar-status' + current={activeItemKey === 'StatusStack'} + /> + + ); + } + renderStatus = () => { const { status } = this.state; const { user } = this.props; @@ -261,6 +279,8 @@ class Sidebar extends Component { + {this.renderStatusText()} + {!showStatus ? this.renderNavigation() : null} {showStatus ? this.renderStatus() : null} @@ -275,6 +295,7 @@ const mapStateToProps = state => ({ id: state.login.user && state.login.user.id, language: state.login.user && state.login.user.language, status: state.login.user && state.login.user.status, + statusText: state.login.user && state.login.user.statusText, username: state.login.user && state.login.user.username, token: state.login.user && state.login.user.token, roles: state.login.user && state.login.user.roles From 3bc9199f928934a01438697699b90910cfe0314d Mon Sep 17 00:00:00 2001 From: wreiske Date: Thu, 5 Sep 2019 04:28:43 -0400 Subject: [PATCH 02/11] i18n and fixed prop issue + don't show unless we're in a direct message --- app/i18n/locales/en.js | 2 ++ app/views/RoomView/index.js | 11 +++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/app/i18n/locales/en.js b/app/i18n/locales/en.js index a8f814da049..a542232a799 100644 --- a/app/i18n/locales/en.js +++ b/app/i18n/locales/en.js @@ -345,6 +345,7 @@ export default { Server: 'Server', Servers: 'Servers', Server_version: 'Server version: {{version}}', + Set_custom_status: 'Set custom status', Set_username_subtitle: 'The username is used to allow others to mention you in messages', Settings: 'Settings', Settings_succesfully_changed: 'Settings succesfully changed!', @@ -364,6 +365,7 @@ export default { Starred: 'Starred', Start_of_conversation: 'Start of conversation', Started_discussion: 'Started a discussion:', + Status: 'Status', Submit: 'Submit', Table: 'Table', Take_a_photo: 'Take a photo', diff --git a/app/views/RoomView/index.js b/app/views/RoomView/index.js index c4fdfbfd37b..94f0fec4f48 100644 --- a/app/views/RoomView/index.js +++ b/app/views/RoomView/index.js @@ -89,7 +89,8 @@ class RoomView extends React.Component { user: PropTypes.shape({ id: PropTypes.string.isRequired, username: PropTypes.string.isRequired, - token: PropTypes.string.isRequired + token: PropTypes.string.isRequired, + statusText: PropTypes.string }), showActions: PropTypes.bool, showErrorActions: PropTypes.bool, @@ -624,9 +625,11 @@ class RoomView extends React.Component { return ( - - {this.t === 'd' ? {user.statusText} : null } - + {this.t === 'd' ? ( + + {user.statusText} + + ) : null } {this.renderFooter()} {this.renderActions()} From f90b76f8345410edfa3f8dd1741c56ea5b6517e5 Mon Sep 17 00:00:00 2001 From: wreiske Date: Thu, 5 Sep 2019 04:34:31 -0400 Subject: [PATCH 03/11] Fixed editing user status from profile page --- app/views/ProfileView/index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/ProfileView/index.js b/app/views/ProfileView/index.js index 2224307e1e1..cc362dac35e 100644 --- a/app/views/ProfileView/index.js +++ b/app/views/ProfileView/index.js @@ -92,7 +92,7 @@ class ProfileView extends React.Component { init = (user) => { const { user: userProps } = this.props; const { - name, username, emails, customFields + name, username, emails, customFields, statusText } = user || userProps; this.setState({ @@ -104,7 +104,7 @@ class ProfileView extends React.Component { avatarUrl: null, avatar: {}, customFields: customFields || {}, - statusText: null + statusText }); } @@ -130,7 +130,7 @@ class ProfileView extends React.Component { && (user.emails && user.emails[0].address === email) && !avatar.data && !customFieldsChanged - && !(user.statusText === statusText) + && user.statusText === statusText ); } From ad6990b9f4d89172117cda7848ac3f817ac60dea Mon Sep 17 00:00:00 2001 From: wreiske Date: Thu, 5 Sep 2019 04:44:46 -0400 Subject: [PATCH 04/11] Removed unused variable COLOR_BACKGROUND_NOTIFICATION --- app/views/RoomView/styles.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/RoomView/styles.js b/app/views/RoomView/styles.js index 0979ce20c3f..3963bdfb688 100644 --- a/app/views/RoomView/styles.js +++ b/app/views/RoomView/styles.js @@ -1,7 +1,7 @@ import { StyleSheet } from 'react-native'; import { - COLOR_SEPARATOR, COLOR_PRIMARY, COLOR_WHITE, COLOR_TEXT_DESCRIPTION, COLOR_BACKGROUND_NOTIFICATION + COLOR_SEPARATOR, COLOR_PRIMARY, COLOR_WHITE, COLOR_TEXT_DESCRIPTION } from '../../constants/colors'; import sharedStyles from '../Styles'; From 2d66de949ed2b06c587e5353f360cf82f002db0b Mon Sep 17 00:00:00 2001 From: wreiske Date: Thu, 5 Sep 2019 05:01:17 -0400 Subject: [PATCH 05/11] Don't show the status view bar unless there is actually a status to show --- app/views/RoomView/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/RoomView/index.js b/app/views/RoomView/index.js index 94f0fec4f48..7f5d95eb5af 100644 --- a/app/views/RoomView/index.js +++ b/app/views/RoomView/index.js @@ -625,7 +625,7 @@ class RoomView extends React.Component { return ( - {this.t === 'd' ? ( + {this.t === 'd' && user && user.statusText ? ( {user.statusText} From 7acaf7f90979aa21ff62c8cf91332bb6d11fe20d Mon Sep 17 00:00:00 2001 From: Prateek Jain Date: Sun, 19 Jan 2020 22:21:01 +0530 Subject: [PATCH 06/11] added-changes-of-wreiske --- app/i18n/locales/en.js | 2 ++ app/lib/rocketchat.js | 5 +++-- app/views/ProfileView/index.js | 32 ++++++++++++++++++++++------- app/views/RoomActionsView/index.js | 8 ++++++-- app/views/RoomActionsView/styles.js | 6 ++++++ app/views/RoomInfoView/index.js | 6 +++++- app/views/RoomInfoView/styles.js | 6 ++++++ app/views/RoomView/index.js | 14 +++++++++++-- app/views/RoomView/styles.js | 11 ++++++++++ app/views/SidebarView/index.js | 24 +++++++++++++++++++++- 10 files changed, 99 insertions(+), 15 deletions(-) diff --git a/app/i18n/locales/en.js b/app/i18n/locales/en.js index ebe96061f0b..33c8665eef4 100644 --- a/app/i18n/locales/en.js +++ b/app/i18n/locales/en.js @@ -358,6 +358,7 @@ export default { Server: 'Server', Servers: 'Servers', Server_version: 'Server version: {{version}}', + Set_custom_status: 'Set custom status', Set_username_subtitle: 'The username is used to allow others to mention you in messages', Settings: 'Settings', Settings_succesfully_changed: 'Settings succesfully changed!', @@ -378,6 +379,7 @@ export default { Start_of_conversation: 'Start of conversation', Started_discussion: 'Started a discussion:', Started_call: 'Call started by {{userBy}}', + Status: 'Status', Submit: 'Submit', Table: 'Table', Take_a_photo: 'Take a photo', diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js index fb79d6b45f3..865b966076d 100644 --- a/app/lib/rocketchat.js +++ b/app/lib/rocketchat.js @@ -244,9 +244,9 @@ const RocketChat = { }, 10000); } const userStatus = ddpMessage.fields.args[0]; - const [id,, status] = userStatus; + const [id,, status, statusText] = userStatus; this.activeUsers[id] = STATUSES[status]; - + this.activeUsers[statusText] = statusText; const { user: loggedUser } = reduxStore.getState().login; if (loggedUser && loggedUser.id === id) { reduxStore.dispatch(setUser({ status: STATUSES[status] })); @@ -381,6 +381,7 @@ const RocketChat = { name: result.me.name, language: result.me.language, status: result.me.status, + statusText: result.me.statusText, customFields: result.me.customFields, emails: result.me.emails, roles: result.me.roles diff --git a/app/views/ProfileView/index.js b/app/views/ProfileView/index.js index 1f89d017f14..ec843597fd0 100644 --- a/app/views/ProfileView/index.js +++ b/app/views/ProfileView/index.js @@ -65,7 +65,8 @@ class ProfileView extends React.Component { avatarUrl: null, avatar: {}, avatarSuggestions: {}, - customFields: {} + customFields: {}, + statusText: null } async componentDidMount() { @@ -103,7 +104,7 @@ class ProfileView extends React.Component { init = (user) => { const { user: userProps } = this.props; const { - name, username, emails, customFields + name, username, emails, customFields, statusText } = user || userProps; this.setState({ @@ -114,13 +115,14 @@ class ProfileView extends React.Component { currentPassword: null, avatarUrl: null, avatar: {}, - customFields: customFields || {} + customFields: customFields || {}, + statusText }); } formIsChanged = () => { const { - name, username, email, newPassword, avatar, customFields + name, username, email, newPassword, avatar, customFields, statusText } = this.state; const { user } = this.props; let customFieldsChanged = false; @@ -140,6 +142,7 @@ class ProfileView extends React.Component { && (user.emails && user.emails[0].address === email) && !avatar.data && !customFieldsChanged + && user.statusText === statusText ); } @@ -168,10 +171,14 @@ class ProfileView extends React.Component { this.setState({ saving: true }); const { - name, username, email, newPassword, currentPassword, avatar, customFields + name, username, email, newPassword, currentPassword, avatar, customFields, statusText } = this.state; const { user, setUser } = this.props; const params = {}; + // Status Text + if (user.statusText !== statusText) { + params.statusText = statusText; + } // Name if (user.name !== name) { @@ -377,7 +384,8 @@ class ProfileView extends React.Component { render() { const { - name, username, email, newPassword, avatarUrl, customFields, avatar, saving, showPasswordAlert + name, username, email, newPassword, avatarUrl, customFields, avatar, saving, showPasswordAlert, statusText + } = this.state; const { baseUrl, user, theme, Accounts_CustomFields @@ -416,6 +424,15 @@ class ProfileView extends React.Component { testID='profile-view-name' theme={theme} /> + { this.statusText = e; }} + label={I18n.t('Status')} + placeholder={I18n.t('Status')} + value={statusText} + onChangeText={value => this.setState({ statusText: value })} + onSubmitEditing={() => { this.statusText.focus(); }} + testID='profile-view-status' + /> { this.username = e; }} label={I18n.t('Username')} @@ -503,7 +520,8 @@ const mapStateToProps = state => ({ username: state.login.user && state.login.user.username, customFields: state.login.user && state.login.user.customFields, emails: state.login.user && state.login.user.emails, - token: state.login.user && state.login.user.token + token: state.login.user && state.login.user.token, + statusText: state.login.user && state.login.user.statusText }, Accounts_CustomFields: state.settings.Accounts_CustomFields, baseUrl: state.settings.Site_Url || state.server ? state.server.server : '' diff --git a/app/views/RoomActionsView/index.js b/app/views/RoomActionsView/index.js index 363c6cf2397..9193e904f8b 100644 --- a/app/views/RoomActionsView/index.js +++ b/app/views/RoomActionsView/index.js @@ -42,7 +42,8 @@ class RoomActionsView extends React.Component { navigation: PropTypes.object, user: PropTypes.shape({ id: PropTypes.string, - token: PropTypes.string + token: PropTypes.string, + statusText: PropTypes.string }), leaveRoom: PropTypes.func, jitsiEnabled: PropTypes.bool, @@ -426,6 +427,8 @@ class RoomActionsView extends React.Component { ) } {t === 'd' ? `@${ name }` : topic} + {t === 'd' ? {user.statusText} : null } + , ], item) @@ -500,7 +503,8 @@ class RoomActionsView extends React.Component { const mapStateToProps = state => ({ user: { id: state.login.user && state.login.user.id, - token: state.login.user && state.login.user.token + token: state.login.user && state.login.user.token, + statusText: state.login.user && state.login.user.statusText }, baseUrl: state.settings.Site_Url || state.server ? state.server.server : '', jitsiEnabled: state.settings.Jitsi_Enabled || false diff --git a/app/views/RoomActionsView/styles.js b/app/views/RoomActionsView/styles.js index 1461cba3785..f954185082d 100644 --- a/app/views/RoomActionsView/styles.js +++ b/app/views/RoomActionsView/styles.js @@ -58,5 +58,11 @@ export default StyleSheet.create({ roomTitleRow: { flexDirection: 'row', alignItems: 'center' + }, + statusText: { + paddingTop: 5, + fontSize: 14, + ...sharedStyles.textColorDescription, + ...sharedStyles.textMedium } }); diff --git a/app/views/RoomInfoView/index.js b/app/views/RoomInfoView/index.js index f7c2cbd4e9c..3f649bf9091 100644 --- a/app/views/RoomInfoView/index.js +++ b/app/views/RoomInfoView/index.js @@ -299,7 +299,10 @@ class RoomInfoView extends React.Component { {this.renderAvatar(room, roomUser)} { getRoomTitle(room, this.t, roomUser && roomUser.name, theme) } + {this.t === 'd' ? {roomUser.statusText} : null } + + {this.isDirect() ? this.renderDirect() : this.renderChannel()} @@ -311,7 +314,8 @@ const mapStateToProps = state => ({ baseUrl: state.settings.Site_Url || state.server ? state.server.server : '', user: { id: state.login.user && state.login.user.id, - token: state.login.user && state.login.user.token + token: state.login.user && state.login.user.token, + statusText: state.login.user && state.login.user.statusText }, Message_TimeFormat: state.settings.Message_TimeFormat }); diff --git a/app/views/RoomInfoView/styles.js b/app/views/RoomInfoView/styles.js index 00901410a52..a9574767717 100644 --- a/app/views/RoomInfoView/styles.js +++ b/app/views/RoomInfoView/styles.js @@ -66,5 +66,11 @@ export default StyleSheet.create({ role: { fontSize: 14, ...sharedStyles.textRegular + }, + statusText: { + paddingTop: 10, + fontSize: 18, + ...sharedStyles.textColorDescription, + ...sharedStyles.textMedium } }); diff --git a/app/views/RoomView/index.js b/app/views/RoomView/index.js index 4d55a21f285..48daa7f6552 100644 --- a/app/views/RoomView/index.js +++ b/app/views/RoomView/index.js @@ -126,7 +126,9 @@ class RoomView extends React.Component { user: PropTypes.shape({ id: PropTypes.string.isRequired, username: PropTypes.string.isRequired, - token: PropTypes.string.isRequired + token: PropTypes.string.isRequired, + + statusText: PropTypes.string }), appState: PropTypes.string, useRealName: PropTypes.bool, @@ -140,6 +142,7 @@ class RoomView extends React.Component { useMarkdown: PropTypes.bool, theme: PropTypes.string, replyBroadcast: PropTypes.func + }; constructor(props) { @@ -885,6 +888,12 @@ class RoomView extends React.Component { forceInset={{ vertical: 'never' }} > + {this.t === 'd' && user && user.statusText ? ( + + + {user.statusText} + + ) : null } ({ user: { id: state.login.user && state.login.user.id, username: state.login.user && state.login.user.username, - token: state.login.user && state.login.user.token + token: state.login.user && state.login.user.token, + statusText: state.login.user && state.login.user.statusText }, appState: state.app.ready && state.app.foreground ? 'foreground' : 'background', useRealName: state.settings.UI_Use_Real_Name, diff --git a/app/views/RoomView/styles.js b/app/views/RoomView/styles.js index 9f011413ebd..e2cc343c94d 100644 --- a/app/views/RoomView/styles.js +++ b/app/views/RoomView/styles.js @@ -12,6 +12,17 @@ export default StyleSheet.create({ list: { flex: 1 }, + statusTextContainer: { + padding: 10, + backgroundColor: '#292929', + justifyContent: 'flex-end', + alignItems: 'center' + }, + statusText: { + fontSize: 14, + color: 'white', + ...sharedStyles.textMedium + }, contentContainer: { paddingTop: 10 }, diff --git a/app/views/SidebarView/index.js b/app/views/SidebarView/index.js index 2d7d784ce84..b5e4dce1a5a 100644 --- a/app/views/SidebarView/index.js +++ b/app/views/SidebarView/index.js @@ -89,6 +89,9 @@ class Sidebar extends Component { if (nextProps.Site_Name !== Site_Name) { return true; } + if (nextProps.user.statusText !== user.statusText) { + return true; + } if (nextProps.baseUrl !== baseUrl) { return true; } @@ -139,6 +142,7 @@ class Sidebar extends Component { }); } + async setIsAdmin() { const db = database.active; const { user } = this.props; @@ -157,6 +161,22 @@ class Sidebar extends Component { } } + renderStatusText = () => { + const { activeItemKey, user } = this.props; + return ( + <> + } + onPress={() => this.sidebarNavigate('RoomsListView')} + testID='sidebar-status' + current={activeItemKey === 'StatusStack'} + /> + + ); + } + + logout = () => { const { logout } = this.props; logout(); @@ -299,8 +319,9 @@ class Sidebar extends Component { {!split || showStatus ? : null} - + {this.renderStatusText()} {!showStatus && !split ? this.renderNavigation() : null} + {showStatus ? this.renderStatus() : null} @@ -314,6 +335,7 @@ const mapStateToProps = state => ({ id: state.login.user && state.login.user.id, language: state.login.user && state.login.user.language, status: state.login.user && state.login.user.status, + statusText: state.login.user && state.login.user.statusText, username: state.login.user && state.login.user.username, token: state.login.user && state.login.user.token, roles: state.login.user && state.login.user.roles From 4e8ceaab5cadba12ec9b67f4e5684838490851f2 Mon Sep 17 00:00:00 2001 From: Prateek Jain Date: Sun, 19 Jan 2020 22:42:57 +0530 Subject: [PATCH 07/11] fixed-status-text-not-updating-issue --- app/lib/rocketchat.js | 2 +- app/views/SidebarView/index.js | 29 +++++++++++------------------ 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/app/lib/rocketchat.js b/app/lib/rocketchat.js index 865b966076d..d6175bf9a0f 100644 --- a/app/lib/rocketchat.js +++ b/app/lib/rocketchat.js @@ -249,7 +249,7 @@ const RocketChat = { this.activeUsers[statusText] = statusText; const { user: loggedUser } = reduxStore.getState().login; if (loggedUser && loggedUser.id === id) { - reduxStore.dispatch(setUser({ status: STATUSES[status] })); + reduxStore.dispatch(setUser({ status: STATUSES[status], statusText })); } } })); diff --git a/app/views/SidebarView/index.js b/app/views/SidebarView/index.js index b5e4dce1a5a..2f99f478947 100644 --- a/app/views/SidebarView/index.js +++ b/app/views/SidebarView/index.js @@ -161,22 +161,6 @@ class Sidebar extends Component { } } - renderStatusText = () => { - const { activeItemKey, user } = this.props; - return ( - <> - } - onPress={() => this.sidebarNavigate('RoomsListView')} - testID='sidebar-status' - current={activeItemKey === 'StatusStack'} - /> - - ); - } - - logout = () => { const { logout } = this.props; logout(); @@ -215,9 +199,18 @@ class Sidebar extends Component { renderNavigation = () => { const { isAdmin } = this.state; - const { activeItemKey, theme } = this.props; + const { activeItemKey, theme, user } = this.props; return ( <> + + } + onPress={() => this.sidebarNavigate('RoomsListView')} + testID='sidebar-status' + current={activeItemKey === 'StatusStack'} + /> + } @@ -319,7 +312,7 @@ class Sidebar extends Component { {!split || showStatus ? : null} - {this.renderStatusText()} + {!showStatus && !split ? this.renderNavigation() : null} {showStatus ? this.renderStatus() : null} From 0a8592ce68dc4838f8b726add28ac46b258b6658 Mon Sep 17 00:00:00 2001 From: Prateek Jain Date: Mon, 20 Jan 2020 19:02:55 +0530 Subject: [PATCH 08/11] implemented-status-text-feature --- app/containers/StatusModal.js | 198 +++++++++++++++++++++++++++++ app/i18n/locales/en.js | 3 + app/views/ProfileView/index.js | 9 +- app/views/RoomActionsView/index.js | 18 ++- app/views/RoomInfoView/index.js | 2 +- app/views/RoomView/Header/index.js | 5 +- app/views/RoomView/index.js | 3 +- app/views/SidebarView/index.js | 39 +++++- 8 files changed, 259 insertions(+), 18 deletions(-) create mode 100644 app/containers/StatusModal.js diff --git a/app/containers/StatusModal.js b/app/containers/StatusModal.js new file mode 100644 index 00000000000..f8341b12fed --- /dev/null +++ b/app/containers/StatusModal.js @@ -0,0 +1,198 @@ +import React, { Component } from 'react'; +import { + View, Text, StyleSheet, ScrollView, TouchableHighlight +} from 'react-native'; +import PropTypes from 'prop-types'; +import Modal from 'react-native-modal'; +import { responsive } from 'react-native-responsive-ui'; + +import TextInput from './TextInput'; +import Button from './Button'; +import I18n from '../i18n'; +import sharedStyles from '../views/Styles'; +import { isIOS } from '../utils/deviceInfo'; +import { themes } from '../constants/colors'; +import { withTheme } from '../theme'; +import { withSplit } from '../split'; + +const styles = StyleSheet.create({ + modal: { + width: '100%', + alignItems: 'center', + margin: 0 + }, + titleContainer: { + flexDirection: 'row', + paddingHorizontal: 16, + paddingTop: 16 + }, + title: { + fontSize: 14, + ...sharedStyles.textBold + }, + container: { + height: 230, + flexDirection: 'column' + }, + scrollView: { + flex: 1, + padding: 16 + }, + buttonContainer: { + flexDirection: 'row', + justifyContent: 'space-between', + padding: 16 + }, + button: { + marginBottom: 0 + }, + androidButton: { + paddingHorizontal: 15, + justifyContent: 'center', + height: 48, + borderRadius: 2 + }, + androidButtonText: { + fontSize: 18, + textAlign: 'center' + } + +}); + +class StatusModal extends Component { + static propTypes = { + isVisible: PropTypes.bool, + close: PropTypes.func, + submit: PropTypes.func, + window: PropTypes.object, + theme: PropTypes.string, + statusText: PropTypes.string, + split: PropTypes.bool + } + + state = { + statusText: '', + saving: false + }; + + componentDidMount() { + const { statusText } = this.props; + this.setState({ statusText }); + } + + shouldComponentUpdate(nextProps, nextState) { + const { statusText } = this.state; + const { + window, isVisible, split, theme + } = this.props; + + if (nextState.statusText !== statusText) { + return true; + } + if (nextProps.split !== split) { + return true; + } + if (nextProps.theme !== theme) { + return true; + } + if (nextProps.isVisible !== isVisible) { + return true; + } + if (nextProps.window.width !== window.width) { + return true; + } + return false; + } + + submit = () => { + this.setState({ saving: true }); + const { submit } = this.props; + const { statusText } = this.state; + submit(statusText); + } + + renderButtons = () => { + const { close, theme } = this.props; + const { saving } = this.state; + if (isIOS) { + return ( + +