diff --git a/app/screens/settings/config.ts b/app/screens/settings/config.ts index 4617dcebbf..84d477468c 100644 --- a/app/screens/settings/config.ts +++ b/app/screens/settings/config.ts @@ -66,6 +66,12 @@ export const SettingOptionConfig: Record = { i18nId: t('general_settings.help'), testID: 'general_settings.help', }, + report_problem: { + defaultMessage: 'Report a Problem', + i18nId: t('general_settings.report_problem'), + testID: 'general_settings.report_problem', + }, + }; export const NotificationsOptionConfig: Record = { diff --git a/app/screens/settings/index.tsx b/app/screens/settings/index.tsx index be37c6c31f..4b6608b791 100644 --- a/app/screens/settings/index.tsx +++ b/app/screens/settings/index.tsx @@ -14,14 +14,14 @@ import Settings from './settings'; import type {WithDatabaseArgs} from '@typings/database/database'; const enhanced = withObservables([], ({database}: WithDatabaseArgs) => { - const siteName = observeConfigValue(database, 'SiteName'); const helpLink = observeConfigValue(database, 'HelpLink'); - const showHelp = helpLink.pipe(switchMap((link) => of$(link ? isValidUrl(link) : false))); + const showHelp = helpLink.pipe(switchMap((link: string) => of$(link ? isValidUrl(link) : false))); + const siteName = observeConfigValue(database, 'SiteName'); return { + helpLink, showHelp, siteName, - helpLink, }; }); diff --git a/app/screens/settings/report_problem/index.ts b/app/screens/settings/report_problem/index.ts new file mode 100644 index 0000000000..683f3f659a --- /dev/null +++ b/app/screens/settings/report_problem/index.ts @@ -0,0 +1,29 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider'; +import withObservables from '@nozbe/with-observables'; + +import {observeConfigValue, observeCurrentUserId, observeCurrentTeamId} from '@queries/servers/system'; + +import ReportProblem from './report_problem'; + +import type {WithDatabaseArgs} from '@typings/database/database'; + +const enhanced = withObservables([], ({database}: WithDatabaseArgs) => { + const buildNumber = observeConfigValue(database, 'BuildNumber'); + const currentTeamId = observeCurrentTeamId(database); + const currentUserId = observeCurrentUserId(database); + const supportEmail = observeConfigValue(database, 'SupportEmail'); + const version = observeConfigValue(database, 'Version'); + + return { + buildNumber, + currentTeamId, + currentUserId, + supportEmail, + version, + }; +}); + +export default withDatabase(enhanced(ReportProblem)); diff --git a/app/screens/settings/report_problem/report_problem.tsx b/app/screens/settings/report_problem/report_problem.tsx new file mode 100644 index 0000000000..d73cf949f2 --- /dev/null +++ b/app/screens/settings/report_problem/report_problem.tsx @@ -0,0 +1,71 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import TurboLogger from '@mattermost/react-native-turbo-log'; +import TurboMailer from '@mattermost/react-native-turbo-mailer'; +import React from 'react'; +import {Alert, Platform} from 'react-native'; +import DeviceInfo from 'react-native-device-info'; + +import {useTheme} from '@context/theme'; +import {preventDoubleTap} from '@utils/tap'; + +import SettingItem from '../setting_item'; + +type ReportProblemProps = { + buildNumber: string; + currentTeamId: string; + currentUserId: string; + supportEmail: string; + version: string; + siteName: string; +}; + +const ReportProblem = ({buildNumber, currentTeamId, currentUserId, siteName, supportEmail, version}: ReportProblemProps) => { + const theme = useTheme(); + + const openEmailClient = preventDoubleTap(async () => { + const appVersion = DeviceInfo.getVersion(); + const appBuild = DeviceInfo.getBuildNumber(); + const deviceId = DeviceInfo.getDeviceId(); + + const logPaths = await TurboLogger.getLogPaths(); + + const attachments = logPaths.map((path) => ({ + path, + mimeType: 'message/rfc822', + })); + + try { + await TurboMailer.sendMail({ + subject: `Problem with ${siteName} React Native app`, + recipients: [supportEmail], + body: [ + 'Please share a description of the problem:\n\n', + `Current User Id: ${currentUserId}`, + `Current Team Id: ${currentTeamId}`, + `Server Version: ${version} (Build ${buildNumber})`, + `App Version: ${appVersion} (Build ${appBuild})`, + `App Platform: ${Platform.OS}`, + `Device Model: ${deviceId}`, // added this one + ].join('\n'), + attachments, + }); + } catch (e: any) { + Alert.alert('Error', e.message); + } + }); + + return ( + + ); +}; + +export default ReportProblem; diff --git a/app/screens/settings/settings.tsx b/app/screens/settings/settings.tsx index 9e387e0fef..649bd53ebf 100644 --- a/app/screens/settings/settings.tsx +++ b/app/screens/settings/settings.tsx @@ -17,6 +17,7 @@ import {preventDoubleTap} from '@utils/tap'; import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme'; import {tryOpenURL} from '@utils/url'; +import ReportProblem from './report_problem'; import SettingItem from './setting_item'; const CLOSE_BUTTON_ID = 'close-settings'; @@ -146,15 +147,16 @@ const Settings = ({componentId, helpLink, showHelp, siteName}: SettingsProps) => /> {Platform.OS === 'android' && } {showHelp && - + } + ); }; diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 94ec0e7497..592370082c 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -365,6 +365,8 @@ PODS: - RCTTypeSafety - React-Core - ReactCommon/turbomodule/core + - react-native-turbo-mailer (0.1.0): + - React-Core - react-native-user-agent (2.3.1): - React - react-native-video (5.2.1): @@ -614,6 +616,7 @@ DEPENDENCIES: - react-native-notifications (from `../node_modules/react-native-notifications`) - "react-native-paste-input (from `../node_modules/@mattermost/react-native-paste-input`)" - react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`) + - "react-native-turbo-mailer (from `../node_modules/@mattermost/react-native-turbo-mailer`)" - react-native-user-agent (from `../node_modules/react-native-user-agent`) - react-native-video (from `../node_modules/react-native-video`) - react-native-webrtc (from `../node_modules/react-native-webrtc`) @@ -768,6 +771,8 @@ EXTERNAL SOURCES: :path: "../node_modules/@mattermost/react-native-paste-input" react-native-safe-area-context: :path: "../node_modules/react-native-safe-area-context" + react-native-turbo-mailer: + :path: "../node_modules/@mattermost/react-native-turbo-mailer" react-native-user-agent: :path: "../node_modules/react-native-user-agent" react-native-video: @@ -918,6 +923,7 @@ SPEC CHECKSUMS: react-native-notifications: 83b4fd4a127a6c918fc846cae90da60f84819e44 react-native-paste-input: 183ad7dc224e192719616f4258dde5b548627d08 react-native-safe-area-context: 99b24a0c5acd0d5dcac2b1a7f18c49ea317be99a + react-native-turbo-mailer: c709786e47b70c535a356cd7ee6fe1c185ed7c53 react-native-user-agent: a90a1e839b99801baad67a73dd6f361a52aa3cf1 react-native-video: c26780b224543c62d5e1b2a7244a5cd1b50e8253 react-native-webrtc: 86d841823e66d68cc1f86712db1c2956056bf0c2 diff --git a/package-lock.json b/package-lock.json index 15c25b6ced..052011467f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "@mattermost/react-native-network-client": "1.0.0", "@mattermost/react-native-paste-input": "0.5.1", "@mattermost/react-native-turbo-log": "0.2.0", + "@mattermost/react-native-turbo-mailer": "0.1.0", "@msgpack/msgpack": "2.8.0", "@nozbe/watermelondb": "0.24.0", "@nozbe/with-observables": "1.4.1", @@ -3223,6 +3224,18 @@ "react-native": "*" } }, + "node_modules/@mattermost/react-native-turbo-mailer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@mattermost/react-native-turbo-mailer/-/react-native-turbo-mailer-0.1.0.tgz", + "integrity": "sha512-Q6GY5sxdokJRuS/3DeAeqfmzWRboI9xDip2pEdw7K6CZCBdNXMNoPhqhq+KEV+/sJzfmx6qFGVipMyj5uGIyYA==", + "engines": { + "node": ">= 16.0.0" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, "node_modules/@msgpack/msgpack": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-2.8.0.tgz", @@ -24041,6 +24054,12 @@ "integrity": "sha512-w5SnCUnmxr3ynvaaxgMrrS3ZlkeNhR2BnPnSCQE1YInJvgju9B9VFWU37L83jfvuJN6r9+43sxImjNVLLAmlLA==", "requires": {} }, + "@mattermost/react-native-turbo-mailer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@mattermost/react-native-turbo-mailer/-/react-native-turbo-mailer-0.1.0.tgz", + "integrity": "sha512-Q6GY5sxdokJRuS/3DeAeqfmzWRboI9xDip2pEdw7K6CZCBdNXMNoPhqhq+KEV+/sJzfmx6qFGVipMyj5uGIyYA==", + "requires": {} + }, "@msgpack/msgpack": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-2.8.0.tgz", diff --git a/package.json b/package.json index d3024cb734..c441273c32 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "@mattermost/react-native-network-client": "1.0.0", "@mattermost/react-native-paste-input": "0.5.1", "@mattermost/react-native-turbo-log": "0.2.0", + "@mattermost/react-native-turbo-mailer": "0.1.0", "@msgpack/msgpack": "2.8.0", "@nozbe/watermelondb": "0.24.0", "@nozbe/with-observables": "1.4.1",