Skip to content

Commit

Permalink
Merge branch 'main' into fix/threads-list-does-not-show-channel-link
Browse files Browse the repository at this point in the history
  • Loading branch information
mattermost-build authored Sep 17, 2024
2 parents c53b537 + f04838d commit 6d9a404
Show file tree
Hide file tree
Showing 74 changed files with 2,258 additions and 2,015 deletions.
2 changes: 1 addition & 1 deletion android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ android {
applicationId "com.mattermost.rnbeta"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 555
versionCode 558
versionName "2.20.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
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
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
2 changes: 1 addition & 1 deletion app/screens/edit_profile/components/email_field.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import type {FloatingTextInputRef} from '@components/floating_text_input_label';
const services: Record<string, string> = {
gitlab: 'GitLab',
google: 'Google Apps',
office365: 'Office 365',
office365: 'Entra ID',
ldap: 'AD/LDAP',
saml: 'SAML',
};
Expand Down
6 changes: 3 additions & 3 deletions app/screens/gallery/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@

import RNUtils from '@mattermost/rnutils';
import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
import {useWindowDimensions, Platform} from 'react-native';
import {Platform} from 'react-native';

import {CaptionsEnabledContext} from '@calls/context';
import {hasCaptions} from '@calls/utils';
import useAndroidHardwareBackHandler from '@hooks/android_back_handler';
import {useIsTablet} from '@hooks/device';
import {useIsTablet, useWindowDimensions} from '@hooks/device';
import {useGalleryControls} from '@hooks/gallery';
import {dismissOverlay, setScreensOrientation} from '@screens/navigation';
import {freezeOtherScreens} from '@utils/gallery';
Expand All @@ -35,7 +35,7 @@ const GalleryScreen = ({componentId, galleryIdentifier, hideActions, initialInde
const [captionsEnabled, setCaptionsEnabled] = useState<boolean[]>(new Array(items.length).fill(true));
const [captionsAvailable, setCaptionsAvailable] = useState<boolean[]>([]);
const {setControlsHidden, headerStyles, footerStyles} = useGalleryControls();
const dimensions = useMemo(() => ({width: dim.width, height: dim.height}), [dim.width]);
const dimensions = useMemo(() => ({width: dim.width, height: dim.height}), [dim]);
const galleryRef = useRef<GalleryRef>(null);

useEffect(() => {
Expand Down
17 changes: 4 additions & 13 deletions app/screens/gallery/video_renderer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// See LICENSE.txt for license information.

import React, {useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react';
import {DeviceEventEmitter, StyleSheet, useWindowDimensions} from 'react-native';
import {DeviceEventEmitter, StyleSheet} from 'react-native';
import Animated, {
Easing,
useAnimatedStyle,
Expand Down Expand Up @@ -47,7 +47,6 @@ const styles = StyleSheet.create({
});

const VideoRenderer = ({height, index, initialIndex, item, isPageActive, onShouldHideControls, width}: VideoRendererProps) => {
const dimensions = useWindowDimensions();
const fullscreen = useSharedValue(false);
const {bottom} = useSafeAreaInsets();
const serverUrl = useServerUrl();
Expand Down Expand Up @@ -126,23 +125,15 @@ const VideoRenderer = ({height, index, initialIndex, item, isPageActive, onShoul
}, []);

const dimensionsStyle = useMemo(() => {
let w = width;
let h = height - (VIDEO_INSET + GALLERY_FOOTER_HEIGHT + bottom);
const w = width;
const h = height - (VIDEO_INSET + GALLERY_FOOTER_HEIGHT + bottom);

if (hasError) {
return {height: 0, width: 0};
}

if (fullscreen.value) {
w = dimensions.width;
h = dimensions.height;
} else if (dimensions.width > dimensions.height) {
w = h;
h = width;
}

return {width: w, height: h};
}, [hasError, fullscreen.value, dimensions.height]);
}, [hasError, fullscreen.value, height, width]);

const animatedStyle = useAnimatedStyle(() => {
return {
Expand Down
2 changes: 1 addition & 1 deletion app/screens/gallery/viewer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ const GalleryViewer = ({
}

return (<ImageRenderer {...props}/>);
}, [items]);
}, [items, width, height]);

return (
<Pager
Expand Down
4 changes: 2 additions & 2 deletions app/screens/login/sso_options.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ const SsoOptions = ({goToSso, ssoOnly, ssoOptions, theme}: Props) => {
sso.imageSrc = require('@assets/images/Icon_Google.png');
break;
case Sso.OFFICE365:
sso.text = formatMessage({id: 'mobile.login_options.office365', defaultMessage: 'Office 365'});
sso.imageSrc = require('@assets/images/Icon_Office.png');
sso.text = formatMessage({id: 'mobile.login_options.entraid', defaultMessage: 'Entra ID'});
sso.imageSrc = require('@assets/images/Icon_EntraID.png');
break;
case Sso.OPENID:
sso.text = options.text || formatMessage({id: 'mobile.login_options.openid', defaultMessage: 'Open ID'});
Expand Down
75 changes: 75 additions & 0 deletions app/screens/sso/components/auth_error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

import {Button} from '@rneui/base';
import React from 'react';
import {Text, View} from 'react-native';

import FormattedText from '@components/formatted_text';
import {buttonBackgroundStyle, buttonTextStyle} from '@utils/buttonStyles';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
import {typography} from '@utils/typography';

interface AuthErrorProps {
error: string;
retry: () => void;
theme: Theme;
}

const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => {
return {
button: {
marginTop: 25,
},
errorText: {
color: changeOpacity(theme.centerChannelColor, 0.72),
textAlign: 'center',
...typography('Body', 200, 'Regular'),
},
infoContainer: {
alignItems: 'center',
flex: 1,
justifyContent: 'center',
},
infoText: {
color: changeOpacity(theme.centerChannelColor, 0.72),
...typography('Body', 100, 'Regular'),
},
infoTitle: {
color: theme.centerChannelColor,
marginBottom: 4,
...typography('Heading', 700),
},
};
});

const AuthError = ({error, retry, theme}: AuthErrorProps) => {
const style = getStyleSheet(theme);

return (
<View style={style.infoContainer}>
<FormattedText
id='mobile.oauth.switch_to_browser.error_title'
testID='mobile.oauth.switch_to_browser.error_title'
defaultMessage='Sign in error'
style={style.infoTitle}
/>
<Text style={style.errorText}>
{`${error}.`}
</Text>
<Button
buttonStyle={[style.button, buttonBackgroundStyle(theme, 'lg', 'primary', 'default')]}
testID='mobile.oauth.try_again'
onPress={retry}
>
<FormattedText
id='mobile.oauth.try_again'
defaultMessage='Try again'
style={buttonTextStyle(theme, 'lg', 'primary', 'default')}
/>
</Button>
</View>
);
};

export default AuthError;
Loading

0 comments on commit 6d9a404

Please sign in to comment.