From bb42692b823f76fffc4992ee71cc7bb9a3f2c761 Mon Sep 17 00:00:00 2001 From: YoussefFouadd Date: Wed, 16 Oct 2024 15:36:39 +0300 Subject: [PATCH] feat(example): add features and buttons implementation (#1280) Jira ID: RL-224 --- examples/default/src/navigation/HomeStack.tsx | 10 ++ .../src/screens/CrashReportingScreen.tsx | 12 +- .../src/screens/FeatureRequestsScreen.tsx | 17 +- examples/default/src/screens/HomeScreen.tsx | 1 + .../default/src/screens/LegacyModeScreen.tsx | 83 +++++++++ .../default/src/screens/SettingsScreen.tsx | 34 +++- .../default/src/screens/apm/APMScreen.tsx | 16 +- .../default/src/screens/apm/HttpScreen.tsx | 167 ++++++++++++++++++ .../default/src/screens/apm/NetworkScreen.tsx | 8 +- .../default/src/utils/showNotification.ts | 9 + 10 files changed, 351 insertions(+), 6 deletions(-) create mode 100644 examples/default/src/screens/LegacyModeScreen.tsx create mode 100644 examples/default/src/screens/apm/HttpScreen.tsx create mode 100644 examples/default/src/utils/showNotification.ts diff --git a/examples/default/src/navigation/HomeStack.tsx b/examples/default/src/navigation/HomeStack.tsx index b4a8ca3e6..716ea05d9 100644 --- a/examples/default/src/navigation/HomeStack.tsx +++ b/examples/default/src/navigation/HomeStack.tsx @@ -26,6 +26,8 @@ import { TracesScreen } from '../screens/apm/TracesScreen'; import { NetworkScreen } from '../screens/apm/NetworkScreen'; import { FlowsScreen } from '../screens/apm/FlowsScreen'; import { SessionReplayScreen } from '../screens/SessionReplayScreen'; +import { LegacyModeScreen } from '../screens/LegacyModeScreen'; +import { HttpScreen } from '../screens/apm/HttpScreen'; export type HomeStackParamList = { Home: undefined; @@ -45,6 +47,8 @@ export type HomeStackParamList = { LargeImageList: undefined; SessionReplay: undefined; BackAndForthScreen: BackAndForthScreenProp; + LegacyMode: undefined; + HttpScreen: undefined; // APM // APM: undefined; @@ -132,6 +136,12 @@ export const HomeStackNavigator: React.FC = () => { + + ); }; diff --git a/examples/default/src/screens/CrashReportingScreen.tsx b/examples/default/src/screens/CrashReportingScreen.tsx index c5a53567f..397565ecd 100644 --- a/examples/default/src/screens/CrashReportingScreen.tsx +++ b/examples/default/src/screens/CrashReportingScreen.tsx @@ -1,5 +1,5 @@ import React, { useState } from 'react'; -import { Alert, Platform, ScrollView, StyleSheet, Text, View } from 'react-native'; +import { Alert, Platform, ScrollView, StyleSheet, Text, View, Switch } from 'react-native'; import { CrashReporting, NonFatalErrorLevel } from 'instabug-reactnative'; @@ -12,6 +12,7 @@ import { VerticalListTile } from '../components/VerticalListTile'; import { Button, VStack } from 'native-base'; import { InputField } from '../components/InputField'; import { Select } from '../components/Select'; +import { showNotification } from '../utils/showNotification'; const styles = StyleSheet.create({ inputWrapper: { @@ -61,6 +62,7 @@ export const CrashReportingScreen: React.FC = () => { throw error; } } + const [isEnabled, setIsEnabled] = useState(false); const [userAttributeKey, setUserAttributeKey] = useState(''); const [userAttributeValue, setUserAttributeValue] = useState(''); @@ -70,6 +72,12 @@ export const CrashReportingScreen: React.FC = () => { NonFatalErrorLevel.error, ); + const toggleSwitch = (value: boolean) => { + setIsEnabled(value); + CrashReporting.setEnabled(value); + showNotification('Crash Reporting status', 'Crash Reporting enabled set to ' + value); + }; + function sendCrash() { try { const error = new Error(crashNameValue); @@ -99,6 +107,8 @@ export const CrashReportingScreen: React.FC = () => { return ( + Crash Reporting Enabled: +
{ + const [isEnabled, setIsEnabled] = useState(false); + + const toggleSwitch = (value: boolean) => { + setIsEnabled(value); + + FeatureRequests.setEmailFieldRequired(value, ActionType.requestNewFeature); + showNotification('Email status', 'Email field required set to ' + value); + }; return ( + Email field Required: + FeatureRequests.show()} /> ); diff --git a/examples/default/src/screens/HomeScreen.tsx b/examples/default/src/screens/HomeScreen.tsx index 690d41cc2..7a5aeeb46 100644 --- a/examples/default/src/screens/HomeScreen.tsx +++ b/examples/default/src/screens/HomeScreen.tsx @@ -19,6 +19,7 @@ export const HomeScreen: React.FC navigation.navigate('UserSteps')} /> navigation.navigate('APM')} /> navigation.navigate('SessionReplay')} /> + navigation.navigate('LegacyMode')} /> ); }; diff --git a/examples/default/src/screens/LegacyModeScreen.tsx b/examples/default/src/screens/LegacyModeScreen.tsx new file mode 100644 index 000000000..8790911c4 --- /dev/null +++ b/examples/default/src/screens/LegacyModeScreen.tsx @@ -0,0 +1,83 @@ +import React, { useState } from 'react'; +import { ActivityIndicator } from 'react-native'; +import Instabug from 'instabug-reactnative'; +import { ListTile } from '../components/ListTile'; +import { Screen } from '../components/Screen'; +import { showNotification } from '../utils/showNotification'; + +export const LegacyModeScreen: React.FC = () => { + const [loading, setLoading] = useState(false); + + const addMultipleInstabugLogs = async (numberOfLogs: number) => { + setLoading(true); + try { + for (let i = 0; i < numberOfLogs; i++) { + Instabug.logDebug(`log ${i}`); + } + showNotification('Success', 'Succeeded'); + } catch (error) { + showNotification('Error', 'Failed'); + } finally { + setLoading(false); + } + }; + + const addMultipleUserEvents = async (numberOfLogs: number) => { + setLoading(true); + try { + for (let i = 0; i < numberOfLogs; i++) { + Instabug.logUserEvent(`test user event ${i}`); + } + showNotification('Success', 'Succeeded'); + } catch (error) { + showNotification('Error', 'Failed'); + } finally { + setLoading(false); + } + }; + + const addMultipleTags = async (numberOfLogs: number) => { + setLoading(true); + try { + for (let i = 0; i < numberOfLogs; i++) { + Instabug.appendTags([`test tag ${i}`]); + } + showNotification('Success', 'Succeeded'); + } catch (error) { + showNotification('Error', 'Failed'); + } finally { + setLoading(false); + } + }; + + const addMultipleUserAttributes = async (numberOfLogs: number) => { + setLoading(true); + try { + for (let i = 0; i < numberOfLogs; i++) { + Instabug.setUserAttribute(`user${i}`, `user${i} value`); + } + showNotification('Success', 'Succeeded'); + } catch (error) { + showNotification('Error', 'Failed'); + } finally { + setLoading(false); + } + }; + + return ( + + {loading && } + + addMultipleInstabugLogs(10)} + /> + addMultipleUserEvents(10)} /> + addMultipleTags(10)} /> + addMultipleUserAttributes(10)} + /> + + ); +}; diff --git a/examples/default/src/screens/SettingsScreen.tsx b/examples/default/src/screens/SettingsScreen.tsx index 6390bb7a0..764753e70 100644 --- a/examples/default/src/screens/SettingsScreen.tsx +++ b/examples/default/src/screens/SettingsScreen.tsx @@ -1,6 +1,12 @@ import React, { useState } from 'react'; -import Instabug, { BugReporting, ColorTheme, InvocationEvent } from 'instabug-reactnative'; +import Instabug, { + BugReporting, + ColorTheme, + InvocationEvent, + Locale, + ReproStepsMode, +} from 'instabug-reactnative'; import { InputGroup, InputLeftAddon, useToast, VStack, Button } from 'native-base'; import { ListTile } from '../components/ListTile'; @@ -193,6 +199,32 @@ export const SettingsScreen: React.FC = () => { onValueChange={Instabug.setColorTheme} /> + { + Instabug.setLocale(Locale.arabic); + }} + /> + { + Instabug.setReproStepsConfig({ + all: ReproStepsMode.disabled, + }); + }} + /> + { + Instabug.addExperiments(['exp1', 'exp2']); + }} + /> + { + Instabug.removeExperiments(['exp1', 'exp2']); + }} + /> diff --git a/examples/default/src/screens/apm/APMScreen.tsx b/examples/default/src/screens/apm/APMScreen.tsx index 2bc4dbca0..0b04e6191 100644 --- a/examples/default/src/screens/apm/APMScreen.tsx +++ b/examples/default/src/screens/apm/APMScreen.tsx @@ -1,14 +1,28 @@ import type { NativeStackScreenProps } from '@react-navigation/native-stack'; import type { HomeStackParamList } from '../../navigation/HomeStack'; -import React from 'react'; +import React, { useState } from 'react'; import { ListTile } from '../../components/ListTile'; import { Screen } from '../../components/Screen'; +import { Text, Switch } from 'react-native'; +import { APM } from 'instabug-reactnative'; +import { showNotification } from '../../utils/showNotification'; export const APMScreen: React.FC> = ({ navigation, }) => { + const [isEnabled, setIsEnabled] = useState(false); + + const toggleSwitch = (value: boolean) => { + setIsEnabled(value); + APM.setEnabled(value); + showNotification('APM status', 'APM enabled set to ' + value); + }; + return ( + Enable APM: + + APM.endAppLaunch()} /> navigation.navigate('NetworkTraces')} /> navigation.navigate('ExecutionTraces')} /> navigation.navigate('AppFlows')} /> diff --git a/examples/default/src/screens/apm/HttpScreen.tsx b/examples/default/src/screens/apm/HttpScreen.tsx new file mode 100644 index 000000000..48f972ae4 --- /dev/null +++ b/examples/default/src/screens/apm/HttpScreen.tsx @@ -0,0 +1,167 @@ +import React, { useState } from 'react'; +import { ActivityIndicator } from 'react-native'; +import { ListTile } from '../../components/ListTile'; +import { Screen } from '../../components/Screen'; +import { showNotification } from '../../utils/showNotification'; + +export const HttpScreen: React.FC = () => { + const [loading, setLoading] = useState(false); + + const makeGetCall = async () => { + setLoading(true); + const url = 'https://httpbin.org/anything'; + try { + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }); + + const responseBody = await response.json(); + console.log('Response:', responseBody); + + setLoading(false); + showNotification('Success', 'Succeeded'); + } catch (error) { + console.error('Error:', error); + setLoading(false); + showNotification('Error', 'Failed'); + } + }; + + const makePostCall = async () => { + setLoading(true); + const url = 'https://httpbin.org/post'; + const requestBody = { + name: 'Islam', + }; + try { + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(requestBody), + }); + + const responseBody = await response.json(); + console.log('Response:', responseBody); + + setLoading(false); + showNotification('Success', 'Succeeded'); + } catch (error) { + console.error('Error:', error); + setLoading(false); + showNotification('Error', 'Failed'); + } + }; + + const makeDeleteCall = async () => { + setLoading(true); + const url = 'https://httpbin.org/delete'; + try { + const response = await fetch(url, { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + }, + }); + + const responseBody = await response.json(); + console.log('Response:', responseBody); + + setLoading(false); + showNotification('Success', 'Succeeded'); + } catch (error) { + console.error('Error:', error); + setLoading(false); + showNotification('Error', 'Failed'); + } + }; + + const makePutCall = async () => { + setLoading(true); + const url = 'https://httpbin.org/put'; + const requestBody = { + name: 'Islam', + }; + try { + const response = await fetch(url, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(requestBody), + }); + + const responseBody = await response.json(); + console.log('Response:', responseBody); + + setLoading(false); + showNotification('Success', 'Succeeded'); + } catch (error) { + console.error('Error:', error); + setLoading(false); + showNotification('Error', 'Failed'); + } + }; + + const makePatchCall = async () => { + setLoading(true); + const url = 'https://httpbin.org/patch'; + + const jsonInputString = JSON.stringify({ name: 'Islam' }); + + try { + const response = await fetch(url, { + method: 'PATCH', + headers: { + 'Content-Type': 'application/json', + }, + body: jsonInputString, + }); + + const responseBody = await response.json(); + console.log('Response:', responseBody); + setLoading(false); + showNotification('Success', 'Succeeded'); + } catch (error) { + console.error('Error:', error); + setLoading(false); + showNotification('Error', 'Failed'); + } + }; + + const makeDownloadImageCall = async () => { + setLoading(true); + const url = 'https://httpbin.org/image/jpeg'; + try { + const response = await fetch(url, { + method: 'GET', + }); + + const responseBody = await response.blob(); + console.log('Response:', responseBody); + + setLoading(false); + showNotification('Success', 'Succeeded'); + } catch (error) { + console.error('Error:', error); + setLoading(false); + showNotification('Error', 'Failed'); + } + }; + + return ( + + {loading && } + + + + + + + + ); +}; diff --git a/examples/default/src/screens/apm/NetworkScreen.tsx b/examples/default/src/screens/apm/NetworkScreen.tsx index 40ad2b5fa..8aa20f49f 100644 --- a/examples/default/src/screens/apm/NetworkScreen.tsx +++ b/examples/default/src/screens/apm/NetworkScreen.tsx @@ -8,8 +8,13 @@ import { HStack, VStack } from 'native-base'; import { gql, request } from 'graphql-request'; import { CustomButton } from '../../components/CustomButton'; import axios from 'axios'; +import type { HomeStackParamList } from '../../navigation/HomeStack'; +import type { NativeStackScreenProps } from '@react-navigation/native-stack'; +import { ListTile } from '../../components/ListTile'; -export const NetworkScreen: React.FC = () => { +export const NetworkScreen: React.FC< + NativeStackScreenProps +> = ({ navigation }) => { const [endpointUrl, setEndpointUrl] = useState(''); const { width, height } = useWindowDimensions(); const defaultRequestUrl = 'https://jsonplaceholder.typicode.com/posts/1'; @@ -128,6 +133,7 @@ export const NetworkScreen: React.FC = () => { ))}
+ navigation.navigate('HttpScreen')} />
); diff --git a/examples/default/src/utils/showNotification.ts b/examples/default/src/utils/showNotification.ts new file mode 100644 index 000000000..f7084b46e --- /dev/null +++ b/examples/default/src/utils/showNotification.ts @@ -0,0 +1,9 @@ +import { ToastAndroid, Platform, Alert } from 'react-native'; + +export function showNotification(title: string, message: string): void { + if (Platform.OS === 'android') { + ToastAndroid.show(message, ToastAndroid.SHORT); + } else { + Alert.alert(title, message); + } +}