Skip to content

Commit

Permalink
Merge branch 'main' into test-random-github-action-experiments
Browse files Browse the repository at this point in the history
  • Loading branch information
mattermost-build committed Sep 20, 2024
2 parents 876566b + a4c346e commit 7155e7f
Show file tree
Hide file tree
Showing 94 changed files with 4,149 additions and 2,156 deletions.
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ android {
applicationId "com.mattermost.rnbeta"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 550
versionName "2.20.0"
versionCode 559
versionName "2.21.0"
testBuildType System.getProperty('testBuildType', 'debug')
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
}
Expand Down
2 changes: 0 additions & 2 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO"/>
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" tools:ignore="SelectedPhotoAccess" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" tools:ignore="SelectedPhotoAccess" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" tools:ignore="SelectedPhotoAccess" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Expand Down
762 changes: 762 additions & 0 deletions app/actions/remote/channel.test.ts

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions app/actions/remote/channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -798,7 +798,7 @@ export async function createDirectChannel(serverUrl: string, userId: string, dis
const config = await getConfig(database);
const teammateDisplayNameSetting = getTeammateNameDisplaySetting(preferences || [], config.LockTeammateNameDisplay, config.TeammateNameDisplay, license);
const {directChannels, users} = await fetchMissingDirectChannelsInfo(serverUrl, [created], currentUser.locale, teammateDisplayNameSetting, currentUser.id, true);
created.display_name = directChannels?.[0].display_name || created.display_name;
created.display_name = (directChannels?.length && directChannels?.[0].display_name) || created.display_name;
if (users?.length) {
profiles.push(...users);
}
Expand Down Expand Up @@ -1243,7 +1243,7 @@ export const handleKickFromChannel = async (serverUrl: string, channelId: string

const currentChannelId = await getCurrentChannelId(database);
if (currentChannelId !== channelId) {
return;
return {};
}

const currentServer = await getActiveServer();
Expand Down Expand Up @@ -1273,8 +1273,10 @@ export const handleKickFromChannel = async (serverUrl: string, channelId: string
} else {
await setCurrentChannelId(operator, '');
}
return {};
} catch (error) {
logDebug('cannot kick user from channel', error);
return {error};
}
};

Expand Down
27 changes: 19 additions & 8 deletions app/actions/remote/entry/common.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

import {nativeApplicationVersion} from 'expo-application';
import {RESULTS, checkNotifications} from 'react-native-permissions';

import {fetchMissingDirectChannelsInfo, fetchMyChannelsForTeam, handleKickFromChannel, type MyChannelsRequest} from '@actions/remote/channel';
import {fetchGroupsForMember} from '@actions/remote/groups';
import {fetchPostsForUnreadChannels} from '@actions/remote/post';
Expand All @@ -22,12 +25,12 @@ import {getDeviceToken} from '@queries/app/global';
import {getChannelById, queryAllChannelsForTeam, queryChannelsById} from '@queries/servers/channel';
import {prepareModels, truncateCrtRelatedTables} from '@queries/servers/entry';
import {getHasCRTChanged} from '@queries/servers/preference';
import {getConfig, getCurrentChannelId, getCurrentTeamId, getIsDataRetentionEnabled, getPushVerificationStatus, getLastFullSync, setCurrentTeamAndChannelId} from '@queries/servers/system';
import {getConfig, getCurrentChannelId, getCurrentTeamId, getIsDataRetentionEnabled, getPushVerificationStatus, getLastFullSync, setCurrentTeamAndChannelId, getConfigValue} from '@queries/servers/system';
import {deleteMyTeams, getAvailableTeamIds, getTeamChannelHistory, queryMyTeams, queryMyTeamsByIds, queryTeamsById} from '@queries/servers/team';
import NavigationStore from '@store/navigation_store';
import {isDMorGM, sortChannelsByDisplayName} from '@utils/channel';
import {getFullErrorMessage, isErrorWithStatusCode} from '@utils/errors';
import {isTablet} from '@utils/helpers';
import {isMinimumServerVersion, isTablet} from '@utils/helpers';
import {logDebug} from '@utils/log';
import {processIsCRTEnabled} from '@utils/thread';

Expand Down Expand Up @@ -413,17 +416,25 @@ async function restDeferredAppEntryActions(
}, FETCH_MISSING_DM_TIMEOUT);
}

export const registerDeviceToken = async (serverUrl: string) => {
export const setExtraSessionProps = async (serverUrl: string) => {
try {
const client = NetworkManager.getClient(serverUrl);

const {database} = DatabaseManager.getServerDatabaseAndOperator(serverUrl);
const serverVersion = await getConfigValue(database, 'Version');
const deviceToken = await getDeviceToken();
if (deviceToken) {
client.attachDevice(deviceToken);

// For new servers, we want to send all the information.
// For old servers, we only want to send the information when there
// is a device token. Sending the rest of the information should not
// create any issue.
if (isMinimumServerVersion(serverVersion, 10, 1, 0) || deviceToken) {
const res = await checkNotifications();
const granted = res.status === RESULTS.GRANTED || res.status === RESULTS.LIMITED;
const client = NetworkManager.getClient(serverUrl);
client.setExtraSessionProps(deviceToken, !granted, nativeApplicationVersion);
}
return {};
} catch (error) {
logDebug('error on registerDeviceToken', getFullErrorMessage(error));
logDebug('error on setExtraSessionProps', getFullErrorMessage(error));
return {error};
}
};
Expand Down
4 changes: 2 additions & 2 deletions app/actions/websocket/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
deferredAppEntryActions,
entry,
handleEntryAfterLoadNavigation,
registerDeviceToken,
setExtraSessionProps,
} from '@actions/remote/entry/common';
import {fetchPostsForChannel, fetchPostThread} from '@actions/remote/post';
import {openAllUnreadChannels} from '@actions/remote/preference';
Expand Down Expand Up @@ -37,7 +37,7 @@ import {isTablet} from '@utils/helpers';
import {logDebug, logInfo} from '@utils/log';

export async function handleFirstConnect(serverUrl: string) {
registerDeviceToken(serverUrl);
setExtraSessionProps(serverUrl);
autoUpdateTimezone(serverUrl);
return doReconnect(serverUrl);
}
Expand Down
13 changes: 10 additions & 3 deletions app/client/rest/users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export interface ClientUsersMix {
autocompleteUsers: (name: string, teamId: string, channelId?: string, options?: Record<string, any>) => Promise<{users: UserProfile[]; out_of_channel?: UserProfile[]}>;
getSessions: (userId: string) => Promise<Session[]>;
checkUserMfa: (loginId: string) => Promise<{mfa_required: boolean}>;
attachDevice: (deviceId: string) => Promise<any>;
setExtraSessionProps: (deviceId: string, notificationsEnabled: boolean, version: string | null) => Promise<{}>;
searchUsers: (term: string, options: SearchUserOptions) => Promise<UserProfile[]>;
getStatusesByIds: (userIds: string[]) => Promise<UserStatus[]>;
getStatus: (userId: string) => Promise<UserStatus>;
Expand Down Expand Up @@ -325,10 +325,17 @@ const ClientUsers = <TBase extends Constructor<ClientBase>>(superclass: TBase) =
);
};

attachDevice = async (deviceId: string) => {
setExtraSessionProps = async (deviceId: string, deviceNotificationDisabled: boolean, version: string | null) => {
return this.doFetch(
`${this.getUsersRoute()}/sessions/device`,
{method: 'put', body: {device_id: deviceId}},
{
method: 'put',
body: {
device_id: deviceId,
device_notification_disabled: deviceNotificationDisabled ? 'true' : 'false',
mobile_version: version || '',
},
},
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {Button} from '@rneui/base';
import React, {useCallback, useEffect, useMemo, useState} from 'react';
import {useIntl, type IntlShape} from 'react-intl';
import {Alert, StyleSheet} from 'react-native';
import Animated from 'react-native-reanimated';
import {useSafeAreaInsets} from 'react-native-safe-area-context';

import {ITEM_HEIGHT} from '@components/option_item';
Expand Down Expand Up @@ -149,20 +150,19 @@ const ChannelBookmark = ({
}

return (
<Button
containerStyle={styles.container}
buttonStyle={styles.button}
onPress={onGestureEvent}
onLongPress={handleLongPress}

// @ts-expect-error ref not present in TS def
ref={ref}
>
<BookmarkDetails
bookmark={bookmark}
file={file}
/>
</Button>
<Animated.View ref={ref}>
<Button
containerStyle={styles.container}
buttonStyle={styles.button}
onPress={onGestureEvent}
onLongPress={handleLongPress}
>
<BookmarkDetails
bookmark={bookmark}
file={file}
/>
</Button>
</Animated.View>
);
};

Expand Down
6 changes: 2 additions & 4 deletions app/components/navigation_header/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ type Props = {
onTitlePress?: () => void;
rightButtons?: HeaderRightButton[];
scrollValue?: Animated.SharedValue<number>;
lockValue?: Animated.SharedValue<number | null>;
showBackButton?: boolean;
subtitle?: string;
subtitleCompanion?: React.ReactElement;
Expand Down Expand Up @@ -135,7 +134,6 @@ const Header = ({
onTitlePress,
rightButtons,
scrollValue,
lockValue,
showBackButton = true,
subtitle,
subtitleCompanion,
Expand All @@ -155,7 +153,7 @@ const Header = ({
}

const barHeight = heightOffset - ViewConstants.LARGE_HEADER_TITLE_HEIGHT;
const val = (scrollValue?.value ?? 0);
const val = (scrollValue?.value || 0);
const showDuration = 200;
const hideDuration = 50;
const duration = val >= barHeight ? showDuration : hideDuration;
Expand All @@ -168,7 +166,7 @@ const Header = ({
const containerAnimatedStyle = useAnimatedStyle(() => ({
height: defaultHeight,
paddingTop: insets.top,
}), [defaultHeight, lockValue]);
}), [defaultHeight]);

const containerStyle = useMemo(() => (
[styles.container, containerAnimatedStyle]), [styles, containerAnimatedStyle]);
Expand Down
31 changes: 13 additions & 18 deletions app/components/navigation_header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type Props = SearchProps & {
onTitlePress?: () => void;
rightButtons?: HeaderRightButton[];
scrollValue?: Animated.SharedValue<number>;
lockValue?: Animated.SharedValue<number | null>;
lockValue?: number;
hideHeader?: () => void;
showBackButton?: boolean;
subtitle?: string;
Expand Down Expand Up @@ -61,45 +61,40 @@ const NavigationHeader = forwardRef<SearchRef, Props>(({
const styles = getStyleSheet(theme);

const {largeHeight, defaultHeight, headerOffset} = useHeaderHeight();

const minScrollValue = useDerivedValue(() => scrollValue?.value || 0, [scrollValue]);

const containerHeight = useAnimatedStyle(() => {
const value = -(scrollValue?.value || 0);
const calculatedHeight = (isLargeTitle ? largeHeight : defaultHeight) + value;
const height = lockValue?.value ? lockValue.value : calculatedHeight;
const calculatedHeight = (isLargeTitle ? largeHeight : defaultHeight) - minScrollValue.value;
const height = lockValue || calculatedHeight;
return {
height: Math.max(height, defaultHeight),
minHeight: defaultHeight,
maxHeight: largeHeight + MAX_OVERSCROLL,
};
});

const minScrollValue = useDerivedValue(() => scrollValue?.value || 0, [scrollValue]);
}, [defaultHeight, largeHeight, lockValue, isLargeTitle]);

const translateY = useDerivedValue(() => (
lockValue?.value ? -lockValue.value : Math.min(-minScrollValue.value, headerOffset)
), [lockValue, minScrollValue, headerOffset]);
lockValue ? -lockValue : Math.min(-minScrollValue.value, headerOffset)
), [lockValue, headerOffset]);

const searchTopStyle = useAnimatedStyle(() => {
const margin = clamp(-minScrollValue.value, -headerOffset, headerOffset);
const marginTop = (lockValue?.value ? -lockValue?.value : margin) - SEARCH_INPUT_HEIGHT - SEARCH_INPUT_MARGIN;
const marginTop = (lockValue ? -lockValue : margin) - SEARCH_INPUT_HEIGHT - SEARCH_INPUT_MARGIN;
return {marginTop};
}, [lockValue, headerOffset, scrollValue]);

const heightOffset = useDerivedValue(() => (
lockValue?.value ? lockValue.value : headerOffset
), [lockValue, headerOffset]);
}, [lockValue, headerOffset]);

return (
<Animated.View style={[styles.container, containerHeight]}>
<Header
defaultHeight={defaultHeight}
hasSearch={hasSearch}
isLargeTitle={isLargeTitle}
heightOffset={heightOffset.value}
heightOffset={lockValue || headerOffset}
leftComponent={leftComponent}
onBackPress={onBackPress}
onTitlePress={onTitlePress}
rightButtons={rightButtons}
lockValue={lockValue}
scrollValue={scrollValue}
showBackButton={showBackButton}
subtitle={subtitle}
Expand All @@ -109,7 +104,7 @@ const NavigationHeader = forwardRef<SearchRef, Props>(({
/>
{isLargeTitle &&
<NavigationHeaderLargeTitle
heightOffset={heightOffset.value}
heightOffset={lockValue || headerOffset}
hasSearch={hasSearch}
subtitle={subtitle}
theme={theme}
Expand Down
1 change: 1 addition & 0 deletions app/constants/post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,5 @@ export default {
PostTypes.ADD_TO_TEAM,
PostTypes.REMOVE_FROM_TEAM,
],
POST_TIME_TO_FAIL,
};
19 changes: 18 additions & 1 deletion app/hooks/device.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

import RNUtils, {type WindowDimensions} from '@mattermost/rnutils';
import React, {type RefObject, useEffect, useRef, useState, useContext} from 'react';
import {AppState, DeviceEventEmitter, Keyboard, Platform, useWindowDimensions, View} from 'react-native';
import {AppState, DeviceEventEmitter, Keyboard, NativeEventEmitter, Platform, View} from 'react-native';
import {useSafeAreaInsets} from 'react-native-safe-area-context';

import {DeviceContext} from '@context/device';

import type {KeyboardTrackingViewRef, KeyboardWillShowEventData} from '@mattermost/keyboard-tracker';

const utilsEmitter = new NativeEventEmitter(RNUtils);

export function useSplitView() {
const {isSplit} = React.useContext(DeviceContext);
return isSplit;
Expand All @@ -28,6 +31,20 @@ export function useAppState() {
return appState;
}

export function useWindowDimensions() {
const [dimensions, setDimensions] = useState(RNUtils.getWindowDimensions());

useEffect(() => {
const listener = utilsEmitter.addListener('DimensionsChanged', (window: WindowDimensions) => {
setDimensions(window);
});

return () => listener.remove();
}, []);

return dimensions;
}

export function useIsTablet() {
const {isSplit, isTablet} = useContext(DeviceContext);
return isTablet && !isSplit;
Expand Down
Loading

0 comments on commit 7155e7f

Please sign in to comment.