diff --git a/app/actions/views/channel.js b/app/actions/views/channel.js index b374723bf..509f41f1e 100644 --- a/app/actions/views/channel.js +++ b/app/actions/views/channel.js @@ -185,7 +185,7 @@ export function loadPostsIfNecessaryWithRetry(channelId) { // Get the first page of posts if it appears we haven't gotten it yet, like the webapp received = await retryGetPostsAction(getPosts(channelId), dispatch, getState); - if (received) { + if (received?.order) { const count = received.order.length; loadMorePostsVisible = count >= ViewTypes.POST_VISIBILITY_CHUNK_SIZE; actions.push({ @@ -213,7 +213,7 @@ export function loadPostsIfNecessaryWithRetry(channelId) { received = await retryGetPostsAction(getPostsSince(channelId, since), dispatch, getState); - if (received) { + if (received?.order) { const count = received.order.length; loadMorePostsVisible = postsIds.length + count >= ViewTypes.POST_VISIBILITY_CHUNK_SIZE; actions.push({ @@ -621,7 +621,7 @@ export function increasePostVisibility(channelId, postId) { }]; let hasMorePost = false; - if (result) { + if (result?.order) { const count = result.order.length; hasMorePost = count >= pageSize; diff --git a/app/components/autocomplete/at_mention/at_mention.js b/app/components/autocomplete/at_mention/at_mention.js index 5857eec75..80620bb55 100644 --- a/app/components/autocomplete/at_mention/at_mention.js +++ b/app/components/autocomplete/at_mention/at_mention.js @@ -41,6 +41,7 @@ export default class AtMention extends PureComponent { defaultChannel: {}, isSearch: false, value: '', + inChannel: [], }; constructor(props) { diff --git a/app/components/autocomplete/at_mention_item/at_mention_item.js b/app/components/autocomplete/at_mention_item/at_mention_item.js index 63c1f40dd..1d83fdbc1 100644 --- a/app/components/autocomplete/at_mention_item/at_mention_item.js +++ b/app/components/autocomplete/at_mention_item/at_mention_item.js @@ -24,6 +24,11 @@ export default class AtMentionItem extends PureComponent { theme: PropTypes.object.isRequired, }; + static defaultProps = { + firstName: '', + lastName: '', + }; + completeMention = () => { const {onPress, username} = this.props; onPress(username); diff --git a/app/components/autocomplete/channel_mention/channel_mention.js b/app/components/autocomplete/channel_mention/channel_mention.js index 8d080ccc8..d0dc707df 100644 --- a/app/components/autocomplete/channel_mention/channel_mention.js +++ b/app/components/autocomplete/channel_mention/channel_mention.js @@ -44,6 +44,11 @@ export default class ChannelMention extends PureComponent { static defaultProps = { isSearch: false, value: '', + publicChannels: [], + privateChannels: [], + directAndGroupMessages: [], + myChannels: [], + otherChannels: [], }; constructor(props) { diff --git a/app/components/channel_intro/channel_intro.js b/app/components/channel_intro/channel_intro.js index d3111f54a..d50e434d2 100644 --- a/app/components/channel_intro/channel_intro.js +++ b/app/components/channel_intro/channel_intro.js @@ -29,6 +29,10 @@ class ChannelIntro extends PureComponent { theme: PropTypes.object.isRequired, }; + static defaultProps = { + currentChannelMembers: [], + }; + goToUserProfile = (userId) => { const {intl, navigator, theme} = this.props; const options = { diff --git a/app/components/combined_system_message/last_users.js b/app/components/combined_system_message/last_users.js index 886fc0f47..5e026ad03 100644 --- a/app/components/combined_system_message/last_users.js +++ b/app/components/combined_system_message/last_users.js @@ -61,6 +61,10 @@ export default class LastUsers extends React.PureComponent { usernames: PropTypes.array.isRequired, }; + static defaultProps = { + usernames: [], + }; + constructor(props) { super(props); diff --git a/app/components/file_upload_preview/file_upload_preview.js b/app/components/file_upload_preview/file_upload_preview.js index c33987c5d..7c879930e 100644 --- a/app/components/file_upload_preview/file_upload_preview.js +++ b/app/components/file_upload_preview/file_upload_preview.js @@ -27,6 +27,10 @@ export default class FileUploadPreview extends PureComponent { theme: PropTypes.object.isRequired, }; + static defaultProps = { + files: [], + }; + buildFilePreviews = () => { return this.props.files.map((file) => { return ( diff --git a/app/components/post_add_channel_member/post_add_channel_member.js b/app/components/post_add_channel_member/post_add_channel_member.js index 3a8dba028..84fa69f37 100644 --- a/app/components/post_add_channel_member/post_add_channel_member.js +++ b/app/components/post_add_channel_member/post_add_channel_member.js @@ -36,6 +36,10 @@ export default class PostAddChannelMember extends React.PureComponent { textStyles: PropTypes.object, }; + static defaultProps = { + usernames: [], + }; + static contextTypes = { intl: intlShape, }; diff --git a/app/components/post_body/post_body.js b/app/components/post_body/post_body.js index c0285b85b..b6971cc9c 100644 --- a/app/components/post_body/post_body.js +++ b/app/components/post_body/post_body.js @@ -77,6 +77,7 @@ export default class PostBody extends PureComponent { onFailedPostPress: emptyFunction, onPress: emptyFunction, replyBarStyle: [], + message: '', }; static contextTypes = { diff --git a/app/components/post_list/post_list.js b/app/components/post_list/post_list.js index 90a75b758..c486ec5a7 100644 --- a/app/components/post_list/post_list.js +++ b/app/components/post_list/post_list.js @@ -74,6 +74,7 @@ export default class PostList extends PureComponent { refreshing: false, serverURL: '', siteURL: '', + postIds: [], }; constructor(props) { diff --git a/app/components/post_textbox/components/typing/typing.js b/app/components/post_textbox/components/typing/typing.js index 15f02df9b..6795136ab 100644 --- a/app/components/post_textbox/components/typing/typing.js +++ b/app/components/post_textbox/components/typing/typing.js @@ -19,6 +19,10 @@ export default class Typing extends PureComponent { typing: PropTypes.array.isRequired, }; + static defaultProps = { + typing: [], + }; + state = { typingHeight: new Animated.Value(0), } diff --git a/app/components/sidebars/main/channels_list/list/list.js b/app/components/sidebars/main/channels_list/list/list.js index eda71271a..fa8dd3d6e 100644 --- a/app/components/sidebars/main/channels_list/list/list.js +++ b/app/components/sidebars/main/channels_list/list/list.js @@ -44,6 +44,7 @@ export default class List extends PureComponent { static contextTypes = { intl: intlShape, + unreadChannelIds: [], }; constructor(props) { diff --git a/app/components/tooltip.js b/app/components/tooltip.js index 0ddac3047..066a5a047 100644 --- a/app/components/tooltip.js +++ b/app/components/tooltip.js @@ -14,6 +14,10 @@ export default class ToolTip extends PureComponent { actions: PropTypes.array.isRequired, }; + static defaultProps = { + actions: [], + } + handleHide = () => { if (this.props.onHide) { this.props.onHide(); diff --git a/app/fetch_preconfig.js b/app/fetch_preconfig.js index 09369443e..f5f74050f 100644 --- a/app/fetch_preconfig.js +++ b/app/fetch_preconfig.js @@ -29,10 +29,12 @@ const handleRedirectProtocol = (url, response) => { const serverUrl = Client4.getUrl(); const parsed = urlParse(url); const {redirects} = response.rnfbRespInfo; - const redirectUrl = urlParse(redirects[redirects.length - 1]); + if (redirects) { + const redirectUrl = urlParse(redirects[redirects.length - 1]); - if (serverUrl === parsed.origin && parsed.host === redirectUrl.host && parsed.protocol !== redirectUrl.protocol) { - Client4.setUrl(serverUrl.replace(parsed.protocol, redirectUrl.protocol)); + if (serverUrl === parsed.origin && parsed.host === redirectUrl.host && parsed.protocol !== redirectUrl.protocol) { + Client4.setUrl(serverUrl.replace(parsed.protocol, redirectUrl.protocol)); + } } }; diff --git a/app/screens/image_preview/image_preview.js b/app/screens/image_preview/image_preview.js index 28ac74c6e..f9965cca3 100644 --- a/app/screens/image_preview/image_preview.js +++ b/app/screens/image_preview/image_preview.js @@ -55,6 +55,10 @@ export default class ImagePreview extends PureComponent { theme: PropTypes.object.isRequired, }; + static defaultProps = { + files: [], + }; + static contextTypes = { intl: intlShape, }; diff --git a/app/screens/more_channels/more_channels.js b/app/screens/more_channels/more_channels.js index d1eacc941..09026b493 100644 --- a/app/screens/more_channels/more_channels.js +++ b/app/screens/more_channels/more_channels.js @@ -38,6 +38,10 @@ export default class MoreChannels extends PureComponent { theme: PropTypes.object.isRequired, }; + static defaultProps = { + channels: [], + }; + static contextTypes = { intl: intlShape.isRequired, }; diff --git a/app/screens/options_modal/options_modal_list.android.js b/app/screens/options_modal/options_modal_list.android.js index 5c02d1c20..f41de39a1 100644 --- a/app/screens/options_modal/options_modal_list.android.js +++ b/app/screens/options_modal/options_modal_list.android.js @@ -21,6 +21,10 @@ export default class OptionsModalList extends PureComponent { onItemPress: PropTypes.func, }; + static defaultProps = { + items: [], + }; + handleCancelPress = preventDoubleTap(() => { if (this.props.onCancelPress) { this.props.onCancelPress(); diff --git a/app/screens/options_modal/options_modal_list.ios.js b/app/screens/options_modal/options_modal_list.ios.js index 30a0b3447..e80a69cc7 100644 --- a/app/screens/options_modal/options_modal_list.ios.js +++ b/app/screens/options_modal/options_modal_list.ios.js @@ -25,6 +25,10 @@ export default class OptionsModalList extends PureComponent { ]), }; + static defaultProps = { + items: [], + }; + handleCancelPress = preventDoubleTap(() => { if (this.props.onCancelPress) { this.props.onCancelPress(); diff --git a/app/screens/reaction_list/reaction_list.js b/app/screens/reaction_list/reaction_list.js index 7834196dd..d20ef7009 100644 --- a/app/screens/reaction_list/reaction_list.js +++ b/app/screens/reaction_list/reaction_list.js @@ -35,6 +35,10 @@ export default class ReactionList extends PureComponent { userProfiles: PropTypes.array, }; + static defaultProps = { + userProfiles: [], + }; + static contextTypes = { intl: intlShape.isRequired, }; diff --git a/app/screens/select_team/select_team.js b/app/screens/select_team/select_team.js index 4b1b5f65f..d6d9971b8 100644 --- a/app/screens/select_team/select_team.js +++ b/app/screens/select_team/select_team.js @@ -53,6 +53,10 @@ export default class SelectTeam extends PureComponent { teamsRequest: PropTypes.object.isRequired, }; + static defaultProps = { + teams: [], + }; + constructor(props) { super(props); props.navigator.setOnNavigatorEvent(this.onNavigatorEvent); diff --git a/app/screens/settings/general/settings.js b/app/screens/settings/general/settings.js index 5257f0803..11efa9c97 100644 --- a/app/screens/settings/general/settings.js +++ b/app/screens/settings/general/settings.js @@ -38,6 +38,11 @@ class Settings extends PureComponent { theme: PropTypes.object, }; + static defaultProps = { + errors: [], + joinableTeams: [], + }; + constructor(props) { super(props); this.props.navigator.setOnNavigatorEvent(this.onNavigatorEvent); diff --git a/app/screens/settings/notification_settings_mentions/notification_settings_mention_base.js b/app/screens/settings/notification_settings_mentions/notification_settings_mention_base.js index fc2987eb8..79609d5f2 100644 --- a/app/screens/settings/notification_settings_mentions/notification_settings_mention_base.js +++ b/app/screens/settings/notification_settings_mentions/notification_settings_mention_base.js @@ -17,6 +17,10 @@ export default class NotificationSettingsMentionsBase extends PureComponent { theme: PropTypes.object.isRequired, }; + static defaultProps = { + currentUser: {}, + }; + constructor(props) { super(props); diff --git a/app/screens/settings/notification_settings_mentions/notification_settings_mentions.android.js b/app/screens/settings/notification_settings_mentions/notification_settings_mentions.android.js index 9f9da2923..a1a14b72c 100644 --- a/app/screens/settings/notification_settings_mentions/notification_settings_mentions.android.js +++ b/app/screens/settings/notification_settings_mentions/notification_settings_mentions.android.js @@ -284,7 +284,7 @@ class NotificationSettingsMentionsAndroid extends NotificationSettingsMentionsBa style={style.scrollView} contentContainerStyle={style.scrollViewContent} > - {currentUser.first_name.length > 0 && + {currentUser.first_name?.length > 0 && - {currentUser.first_name.length > 0 && + {currentUser.first_name?.length > 0 && 0) { + if (manualTimezone?.length > 0) { // Preserve state change in server if manualTimezone exists this.submitUser({ useAutomaticTimezone, diff --git a/app/store/middleware.js b/app/store/middleware.js index 1a7521ca9..6910aeef3 100644 --- a/app/store/middleware.js +++ b/app/store/middleware.js @@ -228,17 +228,17 @@ export function cleanUpState(action, keepCurrent = false) { nextEntities.posts.postsInChannel = cleanUpPostsInChannel(payload.entities.posts.postsInChannel, lastChannelForTeam, keepCurrent ? currentChannelId : ''); postIdsToKeep.push(...getAllFromPostsInChannel(nextEntities.posts.postsInChannel)); - // Keep any posts that appear in search resutls + // Keep any posts that appear in search results let searchResults = []; let flaggedPosts = []; if (payload.entities.search) { - if (payload.entities.search.results.length) { + if (payload.entities.search.results?.length) { const {results} = payload.entities.search; searchResults = results; postIdsToKeep.push(...results); } - if (payload.entities.search.flagged.length) { + if (payload.entities.search.flagged?.length) { const {flagged} = payload.entities.search; flaggedPosts = flagged; postIdsToKeep.push(...flagged); diff --git a/app/store/middleware.test.js b/app/store/middleware.test.js index e4bf720cd..55d793097 100644 --- a/app/store/middleware.test.js +++ b/app/store/middleware.test.js @@ -86,6 +86,10 @@ describe('cleanUpState', () => { postsInThread: {}, reactions: {}, }, + search: { + results: ['post1', 'post2'], + flagged: ['post1', 'post2', 'post3'], + }, }, views: { team: { @@ -101,6 +105,8 @@ describe('cleanUpState', () => { expect(result.payload.entities.posts.posts.post1).toBeDefined(); expect(result.payload.entities.posts.posts.post2).toBeUndefined(); expect(result.payload.entities.posts.postsInChannel.channel1).toEqual([{order: ['post1'], recent: true}]); + expect(result.payload.entities.search.results).toEqual(['post1', 'post2']); + expect(result.payload.entities.search.flagged).toEqual(['post1', 'post2', 'post3']); }); test('should keep failed pending post', () => {