(cherry picked from commit 073b836beb)
Co-authored-by: Elias Nahum <nahumhbl@gmail.com>
This commit is contained in:
parent
456ab53ecf
commit
5b5b7bc620
10 changed files with 63 additions and 37 deletions
|
|
@ -503,16 +503,7 @@ export function closeGMChannel(channel) {
|
|||
|
||||
export function refreshChannelWithRetry(channelId) {
|
||||
return async (dispatch) => {
|
||||
dispatch(setChannelRefreshing(true));
|
||||
const posts = await dispatch(fetchPostActionWithRetry(getPosts(channelId)));
|
||||
const actions = [setChannelRefreshing(false)];
|
||||
|
||||
if (posts) {
|
||||
actions.push(setChannelRetryFailed(false));
|
||||
}
|
||||
|
||||
dispatch(batchActions(actions, 'BATCH_REEFRESH_CHANNEL'));
|
||||
return posts;
|
||||
return dispatch(fetchPostActionWithRetry(getPosts(channelId)));
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import {connect} from 'react-redux';
|
|||
|
||||
import {handleSelectChannelByName, refreshChannelWithRetry} from '@actions/views/channel';
|
||||
import {closePermalink, showPermalink} from '@actions/views/permalink';
|
||||
import {getPostThread} from '@actions/views/post';
|
||||
import {setDeepLinkURL} from '@actions/views/root';
|
||||
import {getConfig, getCurrentUrl} from '@mm-redux/selectors/entities/general';
|
||||
import {getTheme} from '@mm-redux/selectors/entities/preferences';
|
||||
|
|
@ -48,6 +49,7 @@ function mapStateToProps() {
|
|||
|
||||
const mapDispatchToProps = {
|
||||
closePermalink,
|
||||
getPostThread,
|
||||
handleSelectChannelByName,
|
||||
refreshChannelWithRetry,
|
||||
setDeepLinkURL,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React, {ReactElement, useCallback, useEffect, useLayoutEffect, useRef} from 'react';
|
||||
import React, {ReactElement, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState} from 'react';
|
||||
import {injectIntl, intlShape} from 'react-intl';
|
||||
import {DeviceEventEmitter, FlatList, Platform, RefreshControl, StyleSheet, ViewToken} from 'react-native';
|
||||
|
||||
|
|
@ -34,6 +34,7 @@ type PostListProps = {
|
|||
currentTeamName: string;
|
||||
deepLinkURL?: string;
|
||||
extraData: never;
|
||||
getPostThread: (rootId: string) => Promise<ActionResult>;
|
||||
handleSelectChannelByName: (channelName: string, teamName: string, errorHandler: (intl: typeof intlShape) => void, intl: typeof intlShape) => Promise<ActionResult>;
|
||||
highlightPinnedOrFlagged?: boolean;
|
||||
highlightPostId?: string;
|
||||
|
|
@ -43,7 +44,9 @@ type PostListProps = {
|
|||
location: string;
|
||||
onLoadMoreUp: () => void;
|
||||
postIds: string[];
|
||||
refreshChannelWithRetry: (channelId: string) => Promise<ActionResult>;
|
||||
renderFooter: () => ReactElement | null;
|
||||
rootId?: string;
|
||||
scrollViewNativeID?: string;
|
||||
serverURL: string;
|
||||
shouldRenderReplyButton?: boolean;
|
||||
|
|
@ -81,8 +84,9 @@ const styles = StyleSheet.create({
|
|||
const buildExtraData = makeExtraData();
|
||||
|
||||
const PostList = ({
|
||||
channelId, currentTeamName = '', closePermalink, deepLinkURL, extraData, handleSelectChannelByName, highlightPostId, highlightPinnedOrFlagged, initialIndex, intl,
|
||||
loadMorePostsVisible, location, onLoadMoreUp = emptyFunction, postIds = [], renderFooter = (() => null),
|
||||
channelId, currentTeamName = '', closePermalink, deepLinkURL, extraData, getPostThread,
|
||||
handleSelectChannelByName, highlightPostId, highlightPinnedOrFlagged, initialIndex, intl, loadMorePostsVisible,
|
||||
location, onLoadMoreUp = emptyFunction, postIds = [], refreshChannelWithRetry, renderFooter = (() => null), rootId,
|
||||
serverURL = '', setDeepLinkURL, showMoreMessagesButton, showPermalink, siteURL = '', scrollViewNativeID, shouldRenderReplyButton, testID, theme,
|
||||
}: PostListProps) => {
|
||||
const prevChannelId = useRef(channelId);
|
||||
|
|
@ -90,6 +94,7 @@ const PostList = ({
|
|||
const flatListRef = useRef<FlatList<never>>(null);
|
||||
const onScrollEndIndexListener = useRef<onScrollEndIndexListenerEvent>();
|
||||
const onViewableItemsChangedListener = useRef<ViewableItemsChangedListenerEvent>();
|
||||
const [refreshing, setRefreshing] = useState(false);
|
||||
|
||||
const registerViewableItemsListener = useCallback((listener) => {
|
||||
onViewableItemsChangedListener.current = listener;
|
||||
|
|
@ -118,6 +123,18 @@ const PostList = ({
|
|||
showPermalink(intl, teamName, postId);
|
||||
};
|
||||
|
||||
const onRefresh = async () => {
|
||||
if (location === Screens.CHANNEL && channelId) {
|
||||
setRefreshing(true);
|
||||
await refreshChannelWithRetry(channelId);
|
||||
setRefreshing(false);
|
||||
} else if (location === Screens.THREAD && rootId) {
|
||||
setRefreshing(true);
|
||||
await getPostThread(rootId);
|
||||
setRefreshing(false);
|
||||
}
|
||||
};
|
||||
|
||||
const onScrollToIndexFailed = useCallback((info: ScrollIndexFailed) => {
|
||||
const animationFrameIndexFailed = requestAnimationFrame(() => {
|
||||
const index = Math.min(info.highestMeasuredFrameIndex, info.index);
|
||||
|
|
@ -283,17 +300,14 @@ const PostList = ({
|
|||
}
|
||||
}, [initialIndex, highlightPostId]);
|
||||
|
||||
let refreshControl;
|
||||
if (location === Screens.PERMALINK) {
|
||||
// Hack so that the scrolling the permalink does not dismisses the modal screens
|
||||
refreshControl = (
|
||||
<RefreshControl
|
||||
refreshing={false}
|
||||
enabled={Platform.OS === 'ios'}
|
||||
colors={[theme.centerChannelColor]}
|
||||
tintColor={theme.centerChannelColor}
|
||||
/>);
|
||||
}
|
||||
const refreshControl = useMemo(() => (
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
colors={[theme.onlineIndicator, theme.awayIndicator, theme.dndIndicator]}
|
||||
tintColor={theme.centerChannelColor}
|
||||
onRefresh={onRefresh}
|
||||
/>
|
||||
), [refreshing, theme]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ export default class ChannelPostList extends PureComponent {
|
|||
getPostThread: PropTypes.func.isRequired,
|
||||
increasePostVisibility: PropTypes.func.isRequired,
|
||||
selectPost: PropTypes.func.isRequired,
|
||||
refreshChannelWithRetry: PropTypes.func.isRequired,
|
||||
setChannelRefreshing: PropTypes.func,
|
||||
}).isRequired,
|
||||
channelId: PropTypes.string.isRequired,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ describe('ChannelPostList', () => {
|
|||
getPostThread: jest.fn(),
|
||||
increasePostVisibility: jest.fn(),
|
||||
selectPost: jest.fn(),
|
||||
refreshChannelWithRetry: jest.fn(),
|
||||
},
|
||||
channelId: 'channel-id',
|
||||
loadMorePostsVisible: false,
|
||||
|
|
|
|||
|
|
@ -4,11 +4,7 @@
|
|||
import {bindActionCreators} from 'redux';
|
||||
import {connect} from 'react-redux';
|
||||
|
||||
import {
|
||||
loadPostsIfNecessaryWithRetry,
|
||||
increasePostVisibility,
|
||||
refreshChannelWithRetry,
|
||||
} from '@actions/views/channel';
|
||||
import {loadPostsIfNecessaryWithRetry, increasePostVisibility} from '@actions/views/channel';
|
||||
import {getPostThread} from '@actions/views/post';
|
||||
import {Types} from '@constants';
|
||||
import {selectPost} from '@mm-redux/actions/posts';
|
||||
|
|
@ -45,7 +41,6 @@ function mapDispatchToProps(dispatch) {
|
|||
getPostThread,
|
||||
increasePostVisibility,
|
||||
selectPost,
|
||||
refreshChannelWithRetry,
|
||||
}, dispatch),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ exports[`thread should match snapshot, has root post 1`] = `
|
|||
style={Object {}}
|
||||
/>
|
||||
}
|
||||
rootId="root_id"
|
||||
scrollViewNativeID="threadPostList"
|
||||
testID="thread.post_list"
|
||||
/>
|
||||
|
|
@ -134,6 +135,7 @@ exports[`thread should match snapshot, render footer 1`] = `
|
|||
style={Object {}}
|
||||
/>
|
||||
}
|
||||
rootId="root_id"
|
||||
scrollViewNativeID="threadPostList"
|
||||
testID="thread.post_list"
|
||||
/>
|
||||
|
|
@ -153,6 +155,7 @@ exports[`thread should match snapshot, render footer 2`] = `
|
|||
]
|
||||
}
|
||||
renderFooter={null}
|
||||
rootId="root_id"
|
||||
scrollViewNativeID="threadPostList"
|
||||
testID="thread.post_list"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ export default class ThreadAndroid extends ThreadBase {
|
|||
currentUserId={myMember && myMember.user_id}
|
||||
lastViewedAt={this.state.lastViewedAt}
|
||||
location={THREAD}
|
||||
rootId={rootId}
|
||||
/>
|
||||
</Animated.View>
|
||||
<PostDraft
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ export default class ThreadIOS extends ThreadBase {
|
|||
currentUserId={myMember && myMember.user_id}
|
||||
lastViewedAt={this.state.lastViewedAt}
|
||||
location={THREAD}
|
||||
rootId={rootId}
|
||||
scrollViewNativeID={SCROLLVIEW_NATIVE_ID}
|
||||
/>
|
||||
</Animated.View>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,24 @@
|
|||
diff --git a/node_modules/react-native/Libraries/Components/ScrollView/ScrollView.js b/node_modules/react-native/Libraries/Components/ScrollView/ScrollView.js
|
||||
index a069a24..a21fa38 100644
|
||||
--- a/node_modules/react-native/Libraries/Components/ScrollView/ScrollView.js
|
||||
+++ b/node_modules/react-native/Libraries/Components/ScrollView/ScrollView.js
|
||||
@@ -1222,9 +1222,15 @@ class ScrollView extends React.Component<Props, State> {
|
||||
// Note: we should split props.style on the inner and outer props
|
||||
// however, the ScrollView still needs the baseStyle to be scrollable
|
||||
const {outer, inner} = splitLayoutProps(flattenStyle(props.style));
|
||||
+ let inverted;
|
||||
+ if (inner.scaleY) {
|
||||
+ inverted = {scaleY: -1};
|
||||
+ delete inner['scaleY']
|
||||
+ }
|
||||
+
|
||||
return React.cloneElement(
|
||||
refreshControl,
|
||||
- {style: [baseStyle, outer]},
|
||||
+ {style: [baseStyle, outer, inverted]},
|
||||
<ScrollViewClass
|
||||
{...props}
|
||||
style={[baseStyle, inner]}
|
||||
diff --git a/node_modules/react-native/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js b/node_modules/react-native/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js
|
||||
index dffccc4..dc426c2 100644
|
||||
--- a/node_modules/react-native/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js
|
||||
|
|
@ -40,10 +61,10 @@ index 2249d54..cc303b3 100644
|
|||
horizontallyInverted: {
|
||||
transform: [{scaleX: -1}],
|
||||
diff --git a/node_modules/react-native/react.gradle b/node_modules/react-native/react.gradle
|
||||
index 5995ad5..dbae7e3 100644
|
||||
index dd34c98..4d74938 100644
|
||||
--- a/node_modules/react-native/react.gradle
|
||||
+++ b/node_modules/react-native/react.gradle
|
||||
@@ -157,7 +157,7 @@ afterEvaluate {
|
||||
@@ -151,7 +151,7 @@ afterEvaluate {
|
||||
|
||||
// Set up dev mode
|
||||
def devEnabled = !(config."devDisabledIn${targetName}"
|
||||
|
|
@ -52,7 +73,7 @@ index 5995ad5..dbae7e3 100644
|
|||
|
||||
def extraArgs = config.extraPackagerArgs ?: [];
|
||||
|
||||
@@ -177,7 +177,7 @@ afterEvaluate {
|
||||
@@ -171,7 +171,7 @@ afterEvaluate {
|
||||
def hermesFlags;
|
||||
def hbcTempFile = file("${jsBundleFile}.hbc")
|
||||
exec {
|
||||
|
|
@ -61,7 +82,7 @@ index 5995ad5..dbae7e3 100644
|
|||
// Can't use ?: since that will also substitute valid empty lists
|
||||
hermesFlags = config.hermesFlagsRelease
|
||||
if (hermesFlags == null) hermesFlags = ["-O", "-output-source-map"]
|
||||
@@ -221,7 +221,7 @@ afterEvaluate {
|
||||
@@ -215,7 +215,7 @@ afterEvaluate {
|
||||
? config."bundleIn${targetName}"
|
||||
: config."bundleIn${variant.buildType.name.capitalize()}" != null
|
||||
? config."bundleIn${variant.buildType.name.capitalize()}"
|
||||
|
|
@ -70,7 +91,7 @@ index 5995ad5..dbae7e3 100644
|
|||
}
|
||||
|
||||
// Expose a minimal interface on the application variant and the task itself:
|
||||
@@ -318,7 +318,7 @@ afterEvaluate {
|
||||
@@ -312,7 +312,7 @@ afterEvaluate {
|
||||
// This should really be done by packaging all Hermes releated libs into
|
||||
// two separate HermesDebug and HermesRelease AARs, but until then we'll
|
||||
// kludge it by deleting the .so files out of the /transforms/ directory.
|
||||
|
|
|
|||
Loading…
Reference in a new issue