0% found this document useful (0 votes)
114 views

CPAD Practicals Merged

The document discusses setting up a React Native development environment on Windows and building a simple application. It explains how to install Node.js, React Native CLI, create a new React Native project, and run the application on an Android emulator. The theory section provides an overview of React Native, JavaScript, and JSX and how they are used to build mobile applications.

Uploaded by

Kaushik Shukla
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
114 views

CPAD Practicals Merged

The document discusses setting up a React Native development environment on Windows and building a simple application. It explains how to install Node.js, React Native CLI, create a new React Native project, and run the application on an Android emulator. The theory section provides an overview of React Native, JavaScript, and JSX and how they are used to build mobile applications.

Uploaded by

Kaushik Shukla
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 72

Advait Naik (222050008)

Experiment 1

Aim: Designing user interface and wireframe for multiple layouts using Figma.

Theory:
Wireframe design is a visual representation of a digital product's layout, structure, and
functionality. It is a simplified, low-fidelity sketch or blueprint of a website, app, or software
interface that outlines the essential elements of the design without getting into details such
as colours, typography, or images. Wireframes are typically created during the early stages
of the design process to establish the overall layout, information architecture, and user
flow. They help designers and stakeholders to focus on the structure and functionality of the
product before delving into more complex design decisions. Wireframes are usually created
using design software such as Figma, Sketch, or Adobe XD, or even hand-drawn on paper.
They can be interactive or static, depending on the level of detail required.
Figma is a web-based design tool used for creating user interfaces, digital prototypes, and
vector graphics. It is a collaborative tool that allows multiple users to work on the same
design project simultaneously in real-time. Figma provides designers with a variety of
features such as vector editing tools, design libraries, and team collaboration options. It also
has a cloud-based system that allows users to store and access their design files from
anywhere. Figma is widely used by UX and UI designers, product managers, developers, and
other professionals in the design and tech industry. Its popularity is due to its ease of use,
collaborative features, and ability to streamline the design process.
Project Description
MyNotes
The proposed application ‘MyNotes’ will allow users to capture their ideas and take notes.
The application is developed using React Native so that it can run on Android as well as IOS.
The Backend runs on Google’s Firebase Datastore.
The Application has the following features:

• User Registration and Login


• Create Note
• Coloured categories for notes
• Update Note
• Delete Note
• Change Password
• Delete Account
• Cloud Storage of Data
Outcome:
Welcome Screen, Register Screen and Login Screen
Main Screen and Edit Note Screen
Account Modal and Change Password
Conclusion:
We understood the importance of User interface design and used Figma to create a User
Interface for a Note taking application. Figma is widely used by UX and UI designers, product
managers, developers, and other professionals in the design and tech industry. Its popularity
is due to its ease of use, collaborative features, and ability to streamline the design process.
Advait Naik (222050008)

Experiment 2

Aim: Setting up the development environment of React Native and .NET MAUI on Windows
and building first simple application.

Theory:

React-Native
React Native is an open-source framework for building mobile applications, developed by
Facebook. It allows developers to create mobile apps for iOS, Android, and other platforms
using the React framework for building user interfaces. With React Native, developers can
write code in JavaScript, and the framework compiles the code into native code for the
target platform. This means that developers can use a single codebase to build apps for
multiple platforms, saving time and effort.
React Native uses a "learn once, write anywhere" approach, meaning that developers can
use their existing knowledge of React to build mobile apps, without having to learn new
programming languages or tools. React Native has gained popularity in recent years because
of its ease of use, performance, and the ability to reuse code between web and mobile
applications. It is used by many popular apps, including Facebook, Instagram, and Uber.
Here are the steps to create a basic React Native project:
1. Install Node.js: React Native requires Node.js to be installed on your computer. You
can download the installer from the official Node.js website.
2. Install the React Native CLI: The React Native CLI is a command-line interface tool
that is used to create and manage React Native projects using the command: npm
install -g react-native-cli
3. Create a new React Native project: Once you have installed the React Native CLI, you
can use it to create a new project using the command: react-native init MyProject
4. This will create a new directory called MyProject in your current directory, which
contains the basic files and folders required for a React Native project
5. Start the development server: To start the development server, navigate to the
project directory and run the following command: react-native start
6. This will start the development server, which compiles your code and serves it to the
app running on your device or emulator.
7. Run the app on your device or emulator: To run the app on your device or emulator,
open another terminal window and navigate to the project directory, then run one
of the following commands depending on your platform:
a. Android: react-native run-ios
b. IOS: react-native run-android
8. This will build the app and launch it on your device or emulator.
9. That's it! You now have a basic React Native project up and running, and you can
start building your app by modifying the code in the App.js file.
Output:
1. Install NodeJs
2. Install react-native using npm

3. Create react-native project


4. Run the Project
Conclusion:
We understood how to setup a react-native project. We installed Nodejs and installed react-
native using node package manager. We created the react-native project and ran the
application on an Android Emulator.
Advait Naik (222050008)

Experiment 3

Aim: Programs regarding concepts of JavaScript, JSX, XAML and C#.

Theory:
Javascript
JavaScript is a programming language used primarily for web development. It is a high-level,
interpreted language that can be run on web browsers as well as server-side environments
using tools like Node.js.
JavaScript was created in 1995 by Brendan Eich while he was working at Netscape
Communications Corporation. Initially, it was used for basic website interactions, such as
form validations and simple animations. However, over time, its capabilities have expanded
to include more complex web applications, server-side programming, and even desktop and
mobile applications.
JavaScript is a dynamic language, meaning it does not require variable declarations and its
data types can change dynamically. It supports object-oriented, functional, and procedural
programming paradigms. JavaScript code is executed by the browser or server-side
environment and can interact with the Document Object Model (DOM) and the Browser
Object Model (BOM) to manipulate web pages and interact with the user.
Today, JavaScript is one of the most widely used programming languages in the world, and
is an essential tool for web developers. It is also used in other fields such as game
development, robotics, and machine learning.
JSX
JSX (JavaScript XML) is a syntax extension for JavaScript that allows developers to write
HTML-like code in their JavaScript files. It is used primarily in React, a popular JavaScript
library for building user interfaces.
With JSX, developers can write code that looks like HTML, but it is actually a combination of
JavaScript and XML syntax. JSX makes it easier to write and visualize the structure of
complex user interfaces in React, as it allows developers to create and manipulate React
elements using a syntax that is similar to HTML.
Code:
import styles from '../styles';
import React, { useState } from 'react'
import { StatusBar, SafeAreaView, StyleSheet, Text, View, Alert } from 'react-native';
import { Button, TextInput } from 'react-native-paper';
import auth, { FirebaseAuthTypes } from '@react-native-firebase/auth';

import { RegisterScreenProps } from '../../../App';

const RegisterScreen: React.FC<RegisterScreenProps> = ({ navigation, route }) => {

const [email, setEmail] = useState('');


const [pass1, setPass1] = useState('');
const [pass2, setPass2] = useState('');
const onPressRegister = () => {
console.log(`Registering ${email} - ${pass1}, ${pass2}`);

if (email == "") {
Alert.alert('Email field empty!', 'Please enter your email', [{ text: 'Okay' }])
return;
}
if (pass1 === pass2) {
registerUser();
} else {
Alert.alert(
"Passwords don't match"
, 'Please enter matching passwords',
[{ text: 'Okay', onPress: () => { } }]);
}
}
const registerUser = () => {
auth()
.createUserWithEmailAndPassword(email, pass1)
.then(() => {
console.log('User account created & signed in!');
Alert.alert(
'User registered successfully',
'Proceed for login',
[
{
text: 'Login',
onPress: () => {
navigation.replace('Login');
}
}
]);
})
.catch(error => {
if (error.code === 'auth/email-already-in-use') {
// console.log('That email address is already in use!');
Alert.alert('Email address already in use', 'Please use another
email', [{ text: 'Okay' }])
}
else if (error.code === 'auth/invalid-email') {
// console.log('That email address is invalid!');
Alert.alert('Invalid Email address', 'Please enter correct email
adddress', [{ text: 'Okay' }])
} else {
Alert.alert('Registration Error', `${error.message}`, [{ text: 'Okay'
}])
}
console.error(error);
});
};
return (
<SafeAreaView>
<StatusBar
animated={true}
backgroundColor="#f1d74e"
barStyle='dark-content'
/>
<View style={styles.container}>
<Text style={styles.title}>
Register
</Text>
<TextInput
style={styles.inputs}
label='email' value={email}
onChangeText={(t) => { setEmail(t) }}
/>
<TextInput
style={styles.inputs}
label='password'
secureTextEntry={true}
value={pass1}
onChangeText={(t) => { setPass1(t) }}
/>
<TextInput
style={styles.inputs}
label='re-enter password'
secureTextEntry={true}
value={pass2}
onChangeText={(t) => { setPass2(t) }}
/>

<Button mode='contained' style={styles.regLoginButton} onPress={() => {


onPressRegister() }}>
Register
</Button>
</View>
</SafeAreaView>
);
}

export default RegisterScreen


Output:

Conclusion:
Javascript is a high-level interpreted language that can be used for Web Development,
Backend Development and Mobile App Development using the React-Native framework. We
use JSX for declaring UI components in React-Native.
Advait Naik (222050008)

Experiment 4

Aim: Basic user interface design using react components, Stylesheet, Flexbox and XAML,
manipulation of components using States and Props.

Theory:

React Components

React Native components are reusable building blocks that can be used to create user
interfaces in a React Native application. Components in React Native are similar to
components in React, but they are specifically designed to work with mobile devices. React
Native provides a set of pre-built components that can be used out of the box, such as Text,
View, Image, Button, TextInput, ScrollView, and many others. These components are
designed to be simple and easy to use, but they can be customized with styles and props to
achieve the desired look and behavior.

React Stylesheets
React Native stylesheets are used to define the visual appearance and layout of components
in a React Native application. Stylesheets allow you to define styles for components using a
syntax that is similar to CSS, but with some differences. In React Native, styles are defined as
JavaScript objects that contain properties and values that describe the visual appearance of
a component. These properties can include things like color, font size, padding, margin,
border, and more.
Flexbox
React Native uses a flexible box layout model, also known as flexbox, to define the layout
and positioning of components in a mobile app. Flexbox is a popular layout model used in
web development, and it works similarly in React Native. With flexbox, you can define a
container element that contains one or more child elements, and then use various
properties to control the layout of the child elements within the container.
React State and Props
React State and Props are two fundamental concepts in React and React Native that are
used to manage data and the rendering of components. State refers to the internal data of a
component that can change over time. State is used to store and manage the dynamic data
of a component, such as user input, UI interactions, and other changes that occur during the
lifecycle of a component. Props, on the other hand, are properties that are passed down to
a component from its parent component. Props are used to customize the behavior and
appearance of a component, and they are read-only and cannot be changed by the
component itself.
Code:
EditScreen Component
import React, { useState } from 'react'
import { EditScreenProps } from '../../App';
import { StatusBar, SafeAreaView, View, Text, TextInput, ScrollView, Alert } from 'react-native';
import { Colour, Note } from '../../Models/GlobalState';
import * as rnp from 'react-native-paper';
import Header from './Header';
import styles from './styles';
import ColourPicker from './ColourPicker';
import useGlobalContext from '../../Models/GlobalContext';
import firestore, { FirebaseFirestoreTypes } from '@react-native-firebase/firestore';
import auth from '@react-native-firebase/auth';

export type Mode = 'edit' | 'add';

const EditScreen: React.FC<EditScreenProps> = ({ navigation, route }) => {


const [note, setNote] = useState<Note>(route.params.note);
const [colourPickerVisible, setColourPickerVisible] = useState<boolean>(false);
const [mode, setMode] = useState<Mode>(route.params.mode);
const { state, dispatcher } = useGlobalContext();

const onBackPressed = () => {


// console.log('Back button pressed');
navigation.goBack();
}

const onPressColourPicker = () => {


//Open colour picking modal
console.log('Pressed colour picker button');
setColourPickerVisible(true);
}

const onColourSelected = (colour: Colour) => {


console.log(`Selected colour: ${colour.label}`);
setNote({ ...note, colour: colour });
}

const onPressSave = () => {


//Save the note and call navigation.goBack()
console.log('Pressed save button');
if (note.title !== "") {
if (mode === 'edit') {
const updation_date = new Date();

updateNote(updation_date)
.then(() => {
setNote({...note, updation_date: updation_date.toISOString()});
dispatcher({ type: 'NOTE_UPDATE', payload: note });
// navigation.pop();
})
.catch(e => {
Alert.alert(
'Note Updation Error!',
e.message,
[
{
text: 'Okay'
}
]
);
// navigation.pop();
});

} else {
console.log('Creating note');
const creation_date = new Date();
createNote(creation_date)
.then((doc) => {
console.log('before dispatcher');
dispatcher(
{
type: 'NOTE_ADD',
payload: { ...note, creation_date: creation_date.toISOString(), id: doc.id }
});
navigation.pop();
})
.catch((e: any) => {
console.log('Error');
Alert.alert(
'Note Creation Error!',
e.message,
[
{
text: 'Okay'
}
]
);
navigation.pop();
});
}
} else {
console.log('Title empty error');
}
};

const onPressDelete = () => {


Alert.alert('Delete Note', 'Do you want to delete this note?', [
{
text: 'Cancel',
onPress: () => console.log('Cancel Pressed'),
style: 'cancel',
},
{
text: 'OK',
onPress: () => {
console.log('OK Pressed')
onPressConfirmDelete();
}
},
]);
};

const onPressConfirmDelete = () => {


console.log('Pressed delete button');
deleteNote()
.then(() => {
dispatcher({ type: 'NOTE_DELETE', payload: note });
navigation.pop();
}).catch(e => {
Alert.alert(
'Note Updation Error!',
e.message,
[
{
text: 'Okay'
}
]
);
});
};

const createNote = (creationDate: Date):


Promise<FirebaseFirestoreTypes.DocumentReference<FirebaseFirestoreTypes.DocumentData>> => {
console.log('inside createNote');
return firestore()
.collection('users')
.doc(auth().currentUser?.email as string)
.collection('notes')
// .doc(note.id)
.add({
title: note.title,
text: note.text,
colour: note.colour,
creation_date: creationDate,
updation_date: null,
});
};

const updateNote = (updationDate: Date) => {


return firestore()
.collection('users')
.doc(auth().currentUser?.email as string)
.collection('notes')
.doc(note.id)
.update({
title: note.title,
text: note.text,
colour: note.colour,
updation_date: updationDate,
});
};

const deleteNote = () => {


return firestore()
.collection('users')
.doc(auth().currentUser?.email as string)
.collection('notes')
.doc(note.id)
.delete();
};

let title: string;


if (mode == 'add') {
title = 'Create Note'
} else {
title = 'Edit Note'
}

return (
<SafeAreaView style={[styles.edit, { backgroundColor: note.colour.hexcode }]}>
<StatusBar
animated={true}
backgroundColor={note.colour.hexcode}
barStyle='dark-content'
/>
<Header
title={title}
onBackPress={onBackPressed}
onPressColourPicker={onPressColourPicker}
onPressSave={onPressSave}
onPressDelete={onPressDelete}
/>

<ColourPicker
modalVisible={colourPickerVisible}
setModalVisible={setColourPickerVisible}
pickedColour={note.colour}
onColourSelected={onColourSelected}
/>

<View style={styles.edit__title}>
<TextInput
defaultValue={note.title}
placeholder='Title'
onChangeText={(text) => {
setNote({ ...note, title: text })
}}
style={styles.edit__title__input}
/>
</View>
<ScrollView>
<View style={styles.edit__text}>
<TextInput
multiline
defaultValue={note.text}
placeholder='Edit your note'
onChangeText={(text) => {
setNote({ ...note, text: text })
}}
style={styles.edit__text__input}
/>
</View>
</ScrollView>
{
mode === 'edit' ?
<View style={styles.edit__timeView}>
<Text
style={styles.edit__timeView__creationText}
>
Created on {(new Date(note.creation_date)).toLocaleString()}
</Text>
{note.updation_date !== '' ?
<Text
style={styles.edit__timeView__updationText}
>
Updated on {(new Date(note.updation_date)).toLocaleString()}</Text>
:
<></>
}
</View>
:
<></>
}
</SafeAreaView>
)
}

export default EditScreen

Header Component
import React, { useState } from 'react';
import IconAntDesign from 'react-native-vector-icons/AntDesign';
import IconMaterial from 'react-native-vector-icons/MaterialIcons';
import { View, Text, TouchableNativeFeedback } from 'react-native';
import styles from './styles';

interface Props {
title: string;
onBackPress: () => void;
onPressColourPicker: () => void;
onPressSave: () => void;
onPressDelete: () => void;
}

const Header: React.FC<Props> = ({ title, onBackPress, onPressColourPicker, onPressSave, onPressDelete }) => {

return (
<View style={styles.edit__header}>
<TouchableNativeFeedback
onPress={() => { onBackPress() }}
>
<View
style={styles.edit__header__backButton}
>
<IconAntDesign
name='arrowleft'
style={{ color: 'black' }}
size={33}
/>
</View>
</TouchableNativeFeedback>

<View style={styles.edit__header__title}>
<Text style={styles.edit__header__title__text}>
{title}
</Text>
</View>

<TouchableNativeFeedback
onPress={() => { onPressDelete() }}
disabled={title.toLowerCase().includes('create')}
>
<View
style={styles.edit__header__colorPickerButton}
>
<IconMaterial
name='delete'
size={33}
/>
</View>
</TouchableNativeFeedback>
<TouchableNativeFeedback
onPress={() => { onPressColourPicker() }}
>
<View
style={styles.edit__header__colorPickerButton}
>
<IconMaterial
name='color-lens'
size={33}
/>
</View>
</TouchableNativeFeedback>
<TouchableNativeFeedback
onPress={() => { onPressSave() }}
>
<View
style={styles.edit__header__saveButton}
>
<IconMaterial
name='save'
size={33}
/>
</View>
</TouchableNativeFeedback>

</View>
);
}

export default Header

Stylesheet
import {StyleSheet} from 'react-native';
const styles = StyleSheet.create({
edit:{
width: '100%',
height: '100%'
},
edit__header: {
height: 60,
borderBottomColor: 'black',
borderBottomWidth: 1,
padding: 3,
flexDirection: 'row',
justifyContent: 'flex-start',
alignItems: 'center',
},
edit__header__backButton: {
marginLeft: 10
},
edit__header__title: {
fontWeight: 'bold',
marginLeft: 10,
flex: 1
},
edit__header__title__text: {
//fontWeight: 'bold',
fontSize: 23
},
edit__header__saveButton: {
margin: 10
},
edit__header__colorPickerButton: {
margin: 10
},

//Body
edit__title:{
margin: 5,
padding: 5
},
edit__title__input: {
fontWeight: 'bold',
fontSize: 32
},
edit__text:{
margin: 5,
marginTop: 0,
padding: 5
},
edit__text__input: {
fontSize: 25
},

//Times
edit__timeView: {
borderTopWidth: 0.5,
padding: 5
},
edit__timeView__creationText: {
fontStyle: 'italic',
fontSize: 13
},
edit__timeView__updationText: {
fontStyle: 'italic',
fontSize: 13
}
});

export default styles;


Output:

Conclusion:
React Native components are reusable building blocks that can be used to create user
interfaces in a React Native application. React Native stylesheets are used to define the
visual appearance and layout of components in a React Native application. React Native
uses a flexible box layout model, also known as flexbox, to define the layout and positioning
of components in a mobile app. React State and Props are two fundamental concepts in
React and React Native that are used to manage data and the rendering of components.
Advait Naik (222050008)

Experiment 5

Aim: Adding user interactivity in the base components and customization of layout using
functions provided by React Native and XAML.

Theory:
Adding user interactivity to a React Native application involves using various built-in React
Native components, state management, and handling user input events.
Here are some common techniques used to add interactivity to React Native applications:
1. Using Touchable Components: React Native provides a set of touchable components
such as TouchableOpacity, TouchableHighlight, and TouchableWithoutFeedback that
can be used to handle user touch events on various elements of the app's UI.
2. Handling User Input Events: You can handle user input events such as button clicks,
form submissions, and text input changes by attaching event handlers to the
corresponding React Native components. For example, you can use the onPress
property of a Button component to handle button clicks.
3. State Management: State management is a core concept in React and React Native
that allows you to manage the dynamic data of a component. By using state
management techniques, you can update the UI of the app in response to user
actions. You can use the useState hook or a state management library such as Redux
to manage state in your React Native application.
4. Navigation: Navigation is an important aspect of user interactivity in a mobile app.
You can use React Navigation, a popular library for implementing navigation in React
Native, to add screens and navigate between them based on user actions.
By using these techniques, you can create interactive and engaging React Native
applications that provide a great user experience.
Code:
EditScreen Component
import React, { useState } from 'react'
import { EditScreenProps } from '../../App';
import { StatusBar, SafeAreaView, View, Text, TextInput, ScrollView, Alert } from 'react-native';
import { Colour, Note } from '../../Models/GlobalState';
import * as rnp from 'react-native-paper';
import Header from './Header';
import styles from './styles';
import ColourPicker from './ColourPicker';
import useGlobalContext from '../../Models/GlobalContext';
import firestore, { FirebaseFirestoreTypes } from '@react-native-firebase/firestore';
import auth from '@react-native-firebase/auth';

export type Mode = 'edit' | 'add';

const EditScreen: React.FC<EditScreenProps> = ({ navigation, route }) => {


const [note, setNote] = useState<Note>(route.params.note);
const [colourPickerVisible, setColourPickerVisible] = useState<boolean>(false);
const [mode, setMode] = useState<Mode>(route.params.mode);
const { state, dispatcher } = useGlobalContext();

const onBackPressed = () => {


// console.log('Back button pressed');
navigation.goBack();
}

const onPressColourPicker = () => {


//Open colour picking modal
console.log('Pressed colour picker button');
setColourPickerVisible(true);
}

const onColourSelected = (colour: Colour) => {


console.log(`Selected colour: ${colour.label}`);
setNote({ ...note, colour: colour });
}

const onPressSave = () => {


//Save the note and call navigation.goBack()
console.log('Pressed save button');
if (note.title !== "") {
if (mode === 'edit') {
const updation_date = new Date();

updateNote(updation_date)
.then(() => {
setNote({...note, updation_date: updation_date.toISOString()});
dispatcher({ type: 'NOTE_UPDATE', payload: note });
// navigation.pop();
})
.catch(e => {
Alert.alert(
'Note Updation Error!',
e.message,
[
{
text: 'Okay'
}
]
);
// navigation.pop();
});

} else {
console.log('Creating note');
const creation_date = new Date();
createNote(creation_date)
.then((doc) => {
console.log('before dispatcher');
dispatcher(
{
type: 'NOTE_ADD',
payload: { ...note, creation_date: creation_date.toISOString(), id: doc.id }
});
navigation.pop();
})
.catch((e: any) => {
console.log('Error');
Alert.alert(
'Note Creation Error!',
e.message,
[
{
text: 'Okay'
}
]
);
navigation.pop();
});
}
} else {
console.log('Title empty error');
}
};

const onPressDelete = () => {


Alert.alert('Delete Note', 'Do you want to delete this note?', [
{
text: 'Cancel',
onPress: () => console.log('Cancel Pressed'),
style: 'cancel',
},
{
text: 'OK',
onPress: () => {
console.log('OK Pressed')
onPressConfirmDelete();
}
},
]);
};

const onPressConfirmDelete = () => {


console.log('Pressed delete button');
deleteNote()
.then(() => {
dispatcher({ type: 'NOTE_DELETE', payload: note });
navigation.pop();
}).catch(e => {
Alert.alert(
'Note Updation Error!',
e.message,
[
{
text: 'Okay'
}
]
);
});
};

const createNote = (creationDate: Date):


Promise<FirebaseFirestoreTypes.DocumentReference<FirebaseFirestoreTypes.DocumentData>> => {
console.log('inside createNote');
return firestore()
.collection('users')
.doc(auth().currentUser?.email as string)
.collection('notes')
// .doc(note.id)
.add({
title: note.title,
text: note.text,
colour: note.colour,
creation_date: creationDate,
updation_date: null,
});
};

const updateNote = (updationDate: Date) => {


return firestore()
.collection('users')
.doc(auth().currentUser?.email as string)
.collection('notes')
.doc(note.id)
.update({
title: note.title,
text: note.text,
colour: note.colour,
updation_date: updationDate,
});
};

const deleteNote = () => {


return firestore()
.collection('users')
.doc(auth().currentUser?.email as string)
.collection('notes')
.doc(note.id)
.delete();
};
let title: string;
if (mode == 'add') {
title = 'Create Note'
} else {
title = 'Edit Note'
}

return (
<SafeAreaView style={[styles.edit, { backgroundColor: note.colour.hexcode }]}>
<StatusBar
animated={true}
backgroundColor={note.colour.hexcode}
barStyle='dark-content'
/>
<Header
title={title}
onBackPress={onBackPressed}
onPressColourPicker={onPressColourPicker}
onPressSave={onPressSave}
onPressDelete={onPressDelete}
/>

<ColourPicker
modalVisible={colourPickerVisible}
setModalVisible={setColourPickerVisible}
pickedColour={note.colour}
onColourSelected={onColourSelected}
/>

<View style={styles.edit__title}>
<TextInput
defaultValue={note.title}
placeholder='Title'
onChangeText={(text) => {
setNote({ ...note, title: text })
}}
style={styles.edit__title__input}
/>
</View>
<ScrollView>
<View style={styles.edit__text}>
<TextInput
multiline
defaultValue={note.text}
placeholder='Edit your note'
onChangeText={(text) => {
setNote({ ...note, text: text })
}}
style={styles.edit__text__input}
/>
</View>
</ScrollView>
{
mode === 'edit' ?
<View style={styles.edit__timeView}>
<Text
style={styles.edit__timeView__creationText}
>
Created on {(new Date(note.creation_date)).toLocaleString()}
</Text>
{note.updation_date !== '' ?
<Text
style={styles.edit__timeView__updationText}
>
Updated on {(new Date(note.updation_date)).toLocaleString()}</Text>
:
<></>
}
</View>
:
<></>
}
</SafeAreaView>
)
}
export default EditScreen

Colour Picker Modal


import React from 'react'
import { Modal, View, Text, StyleSheet, TouchableNativeFeedback } from 'react-native';
import { Colour, Colours } from '../../Models/GlobalState';
import IconMaterial from 'react-native-vector-icons/MaterialIcons';

const CIRCLE_DIAMETER = 50;

interface Props {
modalVisible: boolean;
setModalVisible: React.Dispatch<React.SetStateAction<boolean>>;
pickedColour: Colour;
onColourSelected: (colour: Colour) => void
}

const ColourPicker: React.FC<Props> = ({ modalVisible, setModalVisible, pickedColour, onColourSelected }) => {


return (
<Modal
animationType="fade"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
setModalVisible(!modalVisible)
}

}
>
<View
style={myStyles.modalView}
>
<View style={myStyles.header}>
<View style={{ flex: 1 }}></View>
<TouchableNativeFeedback
onPress={() => { setModalVisible(false) }}
>
<View
style={myStyles.header__close}
>
<IconMaterial
name='close'
style={{ color: 'black' }}
size={35}
/>
</View>
</TouchableNativeFeedback>
</View>
<View style={myStyles.body}>
{Colours.map(c => <ColourButton key={c.hexcode} colour={c} isSelected={c.hexcode == pickedColour.hexcode}
onSelected={onColourSelected} />)}
</View>
</View>
</Modal>
)
}
type ColourButtonProps = {
colour: Colour;
isSelected: boolean;
onSelected: (colour: Colour) => void;
}

const ColourButton: React.FC<ColourButtonProps> = ({ colour, isSelected, onSelected }) => {


let stl = { backgroundColor: colour.hexcode }
if (isSelected) {
stl = { ...stl, ...myStyles.selectedCirle };
return (
<TouchableNativeFeedback style={myStyles.circle} onPress={() => onSelected(colour)}>
<View
style={[myStyles.circle, stl]}
>
<IconMaterial
name='check'
style={{ color: 'black' }}
size={35}
/>
</View>
</TouchableNativeFeedback>)
} else {
return (
<TouchableNativeFeedback style={myStyles.circle} onPress={() => onSelected(colour)}>
<View
style={[myStyles.circle, stl]}
>
</View>
</TouchableNativeFeedback>)
}
}

const myStyles = StyleSheet.create({


modal: {

},
modalView: {
//margin: 20,
backgroundColor: 'white',
borderRadius: 10,
padding: 15,
alignItems: 'center',
width: 280,
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 4,
elevation: 5,
position: 'absolute',
top: '35%',
alignSelf: 'center',
},

header: {
flexDirection: 'row',
height: 44,
marginBottom: 15,
},
header__close: {

},
body: {
flexDirection: 'row',
flexWrap: 'wrap',
alignContent: 'center',
width: 180
},
circle: {
margin: 5,
width: CIRCLE_DIAMETER,
height: CIRCLE_DIAMETER,
borderRadius: CIRCLE_DIAMETER / 2,
borderColor: 'grey',
borderWidth: 1
},
selectedCirle: {
borderColor: 'black',
borderWidth: 2,
alignItems: 'center',
justifyContent: 'space-around'
}
});

export default ColourPicker


Output:

Conclusion:
Adding user interactivity to a React Native application involves using various built-in React
Native components, state management, and handling user input events. We have created
colour modal picker to change the colour of the note using these components.
Advait Naik (222050008)

Experiment 6

Aim: Integrating third party components into our application and XAML pages using shared
resources.

Theory:

React Native provides a set of built-in components that you can use to build your mobile
applications. However, sometimes these built-in components may not meet your specific
needs or requirements, and you may need to use third-party components to enhance the
functionality and appearance of your app. There are many third-party component libraries
available for React Native, and they offer a wide range of functionalities, from UI
components to integrations with various services and APIs.

To use third-party components in your React Native application, you can follow these steps:
1. Install the library: You can install a third-party library using a package manager such
as npm or yarn.
2. Import the component: Once the library is installed, you can import the component
you want to use in your application.
3. Use the component: You can use the imported component in your application by
adding it to your JSX code.
React-Native-Paper
React Native Paper is another popular UI component library for React Native applications,
similar to React Native Elements. It provides a set of ready-to-use and customizable UI
components that are designed to follow Material Design guidelines.
Some key features of React Native Paper include:
1. Material Design compliant: The library provides a wide range of components that are
designed to be consistent with Material Design principles and guidelines.
2. Customizable: React Native Paper allows you to customize the appearance and
behavior of its components, such as colors, typography, and shapes, to fit the
branding of your application.
3. Cross-platform: The library is designed to work on both iOS and Android platforms,
providing a consistent user experience across different devices.
4. Accessibility support: React Native Paper components are built with accessibility in
mind, making it easier for users with disabilities to interact with your application.
5. Theme provider: The library provides a ThemeProvider component that allows you
to define and apply global themes to your application, making it easy to maintain a
consistent look and feel across different screens and components.
Code:
import React, { useState, useEffect } from 'react';
import { SafeAreaView, Text, View, ScrollView, FlatList, StatusBar, Alert } from 'react-native';
import { ActivityIndicator } from 'react-native-paper';
import useGlobalContext from '../../Models/GlobalContext';
import Header from './Header';
import NoteCard from './Note';
import styles from './Styles';
import navigation, { useNavigation } from '@react-navigation/native';
import GlobalState, { Colour, Colours, createNote, Note } from '../../Models/GlobalState';
import { MainScreenProps } from '../../App';
import FloatingActionButtion from './FloatingActionButtion';
import AccountModal from './AccountModal';

import auth from '@react-native-firebase/auth';


import firestore from '@react-native-firebase/firestore';

const MainScreen: React.FC<MainScreenProps> = ({ navigation, route }) => {


const [accountModalVisible, setAccountModalVisible] = useState(false);
const [isLoading, setIsLoading] = useState(true);
const global = useGlobalContext();

const avatarLetter = global.state.userLogin.email.charAt(0).toUpperCase();

useEffect(() => {
const user = auth().currentUser;
console.log('Current user: ' + user?.email);
// console.log('Current user: ' + user?.getIdToken());
const newGlobalState: GlobalState = {
notes: [],
userLogin: {
email: user?.email as string,
}
};
firestore()
.collection('users')
.doc(newGlobalState.userLogin.email)
.collection('notes')
.get()
.then(notes => {
notes.docs.forEach((note) => {
const n = note.data();
// console.log(note.id);
newGlobalState.notes.push({
title: n.title,
text: n.text,
colour: n.colour,
id: note.id,
creation_date: n.creation_date.toDate().toISOString(),
updation_date: n.updation_date ? n.updation_date.toDate().toISOString() : '',
isVisible: true,
});
});
global.dispatcher({ type: 'INIT', payload: newGlobalState });
setIsLoading(false);
})
.catch(e => {
console.log(e);
});
}, []);

const onPressLogoutModal = () => {


setAccountModalVisible(false);

auth().signOut()
.then(() => {
Alert.alert(
'User logger out successfully',
'Thank you!',
[{
text: 'Okay',
}]
);
if (navigation.canGoBack()) {
navigation.popToTop();
} else {
navigation.replace('Welcome');
}
})
.catch((e) => {
Alert.alert('Logout error', e.message, [{ text: 'Okay' }]);
if (navigation.canGoBack()) {
navigation.popToTop();
} else {
navigation.replace('Welcome');
}
});
}

const onPressDeleteAcc = () => {


deleteAccount()
.then(() => {
Alert.alert(
'Account Deleted successfully',
'Please register again to continue',
[
{
text: 'Okay',
onPress: () => {
if (navigation.canGoBack()) {
navigation.popToTop();
} else {
navigation.replace('Welcome');
}
}
}
]
)
}).catch((e) => {
Alert.alert(
'Account Deletion error',
e.message,
[
{
text: 'Okay',
onPress: () => {
if (navigation.canGoBack()) {
navigation.popToTop();
} else {
navigation.replace('Welcome');
}
}
}
]
)
});
};

const deleteAccount = async () => {


const db = firestore();
const snap = await db.collection('users')
.doc(global.state.userLogin.email)
.collection('notes')
.get()
const batch = db.batch()
snap.forEach((doc) => {
// console.log(doc.ref);
batch.delete(doc.ref);
});
await batch.commit()
await auth().currentUser?.delete();
};

const onPressChangePassModal = () => {


setAccountModalVisible(false);
navigation.push('ChangePass');
}

const handlerOnClick = (note: Note) => {


console.log('Pressed ' + note.title);
navigation.navigate('Edit', { note: note, mode: 'edit' });
};

const handlerAddNote = () => {


navigation.navigate('Edit', { mode: 'add', note: createNote("", "", Colours[0]) });
}

const notes = global.state.notes.filter(n => n.isVisible);


const noteDivs: React.ReactElement[] = [];

for (let i = 0; i < notes.length; i = i + 2) {


noteDivs.push(
<View key={notes[i].id} style={styles.main__body__noteDiv}>
<NoteCard note={notes[i]} onClick={handlerOnClick} />
{i + 1 < notes.length ? <NoteCard note={notes[i + 1]} onClick={handlerOnClick} />
:
<View style={styles.main__body__noteCard}></View>}
</View>
);
}

if (isLoading) {
return (<SafeAreaView style={[styles.main, { alignItems: 'center', justifyContent: 'center' }]}>
<StatusBar
animated={true}
backgroundColor="#f1d74e"
barStyle='dark-content'
/>
<ActivityIndicator animating={true} size={'large'} />
</SafeAreaView>)
}

return (
<SafeAreaView style={styles.main}>
<StatusBar
animated={true}
backgroundColor="#f1d74e"
barStyle='dark-content'
/>
<Header
avatarLetter={avatarLetter}
setAccountModalVisible={setAccountModalVisible}
/>
<AccountModal
email={global.state.userLogin.email}
isVisible={accountModalVisible}
setIsVisible={setAccountModalVisible}
onPressLogout={onPressLogoutModal}
onPressChangePass={onPressChangePassModal}
onPressDeleteAcc={onPressDeleteAcc}
/>
<FloatingActionButtion
onClickHandler={handlerAddNote}
/>
<ScrollView
style={styles.main__body}
>
{noteDivs}
</ScrollView>

{/* <FlatList
style={styles.main__body}
data={noteDivs}
renderItem={({ item }) => <item />}
keyExtractor={(item,index) => noteIds[index]} /> */}
</SafeAreaView >);
};

export default MainScreen;

Output:

Conclusion:
React Native provides a set of built-in components that you can use to build your mobile
applications. However, sometimes these built-in components may not meet your specific
needs or requirements, and you may need to use third-party components to enhance the
functionality and appearance of your app.
Advait Naik (222050008)

Experiment 7

Aim: Implementing multiple screen navigation and nested navigation using solutions
provided by React Navigation and .NET MAUI.

Theory:

React Native Navigation is a popular library that provides native navigation for React Native
applications. It offers a set of components and APIs that allow you to create a smooth and
responsive navigation experience for your mobile application, with support for both iOS and
Android platforms.

React Native Navigation provides several key features, including:

1. Native performance: The library uses native navigation components, which offer a
more performant and responsive navigation experience than using JavaScript-based
navigation solutions.

2. Customizable transitions: You can customize the navigation transitions and


animations to create a unique and branded navigation experience for your
application.

3. Deep linking support: React Native Navigation supports deep linking, allowing users
to navigate directly to a specific screen within your application from an external link.

4. Tab bar support: The library includes a built-in tab bar component that allows you to
easily create a tab-based navigation structure for your application.

5. Screen tracking: React Native Navigation provides built-in analytics and screen
tracking capabilities, allowing you to track user navigation and engagement within
your application.

Overall, React Native Navigation is a powerful and flexible library that can help you create a
fast and responsive navigation experience for your mobile application, with support for
many advanced features and customization options.
Code:
import React, { useReducer, createContext } from 'react';
import { DefaultTheme, Provider as PaperProvider } from 'react-native-paper';
import { GlobalContextProvider } from './Models/GlobalContext';
import MainScreen from './Screens/MainScreen/MainScreen';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator, NativeStackScreenProps } from '@react-navigation/native-stack';
import EditScreen, { Mode } from './Screens/EditScreen/EditScreen';
import { Note } from './Models/GlobalState';
import LoginScreen from './Screens/User/LoginScreen/LoginScreen';
import RegisterScreen from './Screens/User/RegisterScreen/RegisterScreen';
import WelcomeScreen from './Screens/User/WelcomeScreen/WelcomeScreen';
import ChangePassScreen from './Screens/User/ChangePassScreen/ChangePassScreen';
import auth from '@react-native-firebase/auth';

/*const theme = {
...DefaultTheme,
colors: {
...DefaultTheme.colors,
primary: 'tomato',
secondary: 'yellow',
},
}; */

type StackParamList = {
Welcome: undefined,
Register: undefined,
Login: undefined,
ChangePass: undefined,
Main: undefined,
Edit: {
mode: Mode;
note: Note;
}
};
const Stack = createNativeStackNavigator<StackParamList>();
export type WelcomeScreenProps = NativeStackScreenProps<StackParamList,'Welcome'>;
export type LoginScreenProps = NativeStackScreenProps<StackParamList,'Login'>;
export type RegisterScreenProps = NativeStackScreenProps<StackParamList,'Register'>;
export type ChangePassScreenProps = NativeStackScreenProps<StackParamList,'ChangePass'>;
export type MainScreenProps = NativeStackScreenProps<StackParamList,'Main'>;
export type EditScreenProps = NativeStackScreenProps<StackParamList,'Edit'>;

const App: React.FC = () => {

return (
<GlobalContextProvider>
<NavigationContainer>
<Stack.Navigator
screenOptions={{headerShown: false}}
initialRouteName={auth().currentUser === null ? 'Welcome': 'Main'}
// initialRouteName='ChangePass'
>
{/* <PaperProvider> */}
<Stack.Screen
name='Welcome'
component={WelcomeScreen}
/>
<Stack.Screen
name='Login'
component={LoginScreen}
/>
<Stack.Screen
name='Register'
component={RegisterScreen}
/>
<Stack.Screen
name='ChangePass'
component={ChangePassScreen}
/>
<Stack.Screen
name="Main"
component={MainScreen}
/>
<Stack.Screen
name="Edit"
component={EditScreen}
/>
</Stack.Navigator>
</NavigationContainer>
</GlobalContextProvider>
);
};

export default App;


Output:

Conclusion:
React Native Navigation is a well-known library that provides native navigation for React
Native apps. It provides a set of components and APIs that enable you to create a smooth
and responsive navigation experience for your mobile app, with support for both the iOS
and Android platforms.
Advait Naik (222050008)

Experiment 8

Aim: Implementing data communication between multiple screens using props and call-
back functions.

Theory:

React Native Navigation is a popular library that provides native navigation for React Native
applications. It offers a set of components and APIs that allow you to create a smooth and
responsive navigation experience for your mobile application, with support for both iOS and
Android platforms.

React Native Navigation provides several key features, including:

1. Native performance: The library uses native navigation components, which offer a
more performant and responsive navigation experience than using JavaScript-based
navigation solutions.

2. Customizable transitions: You can customize the navigation transitions and


animations to create a unique and branded navigation experience for your
application.

3. Deep linking support: React Native Navigation supports deep linking, allowing users
to navigate directly to a specific screen within your application from an external link.

4. Tab bar support: The library includes a built-in tab bar component that allows you to
easily create a tab-based navigation structure for your application.

5. Screen tracking: React Native Navigation provides built-in analytics and screen
tracking capabilities, allowing you to track user navigation and engagement within
your application.
In React Native, you can use the navigation prop to navigate between screens and pass data
between them. Here's how to use it:
1. In your component, import the useNavigation hook from the @react-
navigation/native package
2. Call the useNavigation hook to get the navigation object
3. Use the navigation object to navigate to a different screen.
4. You can also pass data between screens by passing a second argument to the
navigate method.
5. In the receiving screen you can access the passed data using the route object
Code:
Navigation Container
import React, { useReducer, createContext } from 'react';
import { DefaultTheme, Provider as PaperProvider } from 'react-native-paper';
import { GlobalContextProvider } from './Models/GlobalContext';
import MainScreen from './Screens/MainScreen/MainScreen';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator, NativeStackScreenProps } from '@react-navigation/native-stack';
import EditScreen, { Mode } from './Screens/EditScreen/EditScreen';
import { Note } from './Models/GlobalState';
import LoginScreen from './Screens/User/LoginScreen/LoginScreen';
import RegisterScreen from './Screens/User/RegisterScreen/RegisterScreen';
import WelcomeScreen from './Screens/User/WelcomeScreen/WelcomeScreen';
import ChangePassScreen from './Screens/User/ChangePassScreen/ChangePassScreen';
import auth from '@react-native-firebase/auth';
/*const theme = {
...DefaultTheme,
colors: {
...DefaultTheme.colors,
primary: 'tomato',
secondary: 'yellow',
},
}; */

type StackParamList = {
Welcome: undefined,
Register: undefined,
Login: undefined,
ChangePass: undefined,
Main: undefined,
Edit: {
mode: Mode;
note: Note;
}
};
const Stack = createNativeStackNavigator<StackParamList>();
export type WelcomeScreenProps = NativeStackScreenProps<StackParamList,'Welcome'>;
export type LoginScreenProps = NativeStackScreenProps<StackParamList,'Login'>;
export type RegisterScreenProps = NativeStackScreenProps<StackParamList,'Register'>;
export type ChangePassScreenProps = NativeStackScreenProps<StackParamList,'ChangePass'>;
export type MainScreenProps = NativeStackScreenProps<StackParamList,'Main'>;
export type EditScreenProps = NativeStackScreenProps<StackParamList,'Edit'>;

const App: React.FC = () => {

return (
<GlobalContextProvider>
<NavigationContainer>
<Stack.Navigator
screenOptions={{headerShown: false}}
initialRouteName={auth().currentUser === null ? 'Welcome': 'Main'}
// initialRouteName='ChangePass'
>
{/* <PaperProvider> */}
<Stack.Screen
name='Welcome'
component={WelcomeScreen}
/>
<Stack.Screen
name='Login'
component={LoginScreen}
/>
<Stack.Screen
name='Register'
component={RegisterScreen}
/>
<Stack.Screen
name='ChangePass'
component={ChangePassScreen}
/>
<Stack.Screen
name="Main"
component={MainScreen}
/>
<Stack.Screen
name="Edit"
component={EditScreen}
/>
</Stack.Navigator>
</NavigationContainer>
</GlobalContextProvider>
);
};

export default App;

MainScreen Component

const handlerAddNote = () => {


navigation.navigate('Edit', { mode: 'add', note: createNote("", "", Colours[0]) });
}

<FloatingActionButtion
onClickHandler={handlerAddNote}
/>

EditScreen Component

const EditScreen: React.FC<EditScreenProps> = ({ navigation, route }) => {


const [note, setNote] = useState<Note>(route.params.note);
const [colourPickerVisible, setColourPickerVisible] = useState<boolean>(false);
….

}
Output:

Conclusion:
We can use the navigate method on the navigation object to pass data between screens. In
the receiving screen we can use the useNavigation() hook or route.params in the props to
receive the sent data.
Advait Naik (222050008)

Experiment 9

Aim: Implementation of asynchronous functions and outside API calls in JavaScript, react
Native and .NET MAUI.

Theory:
In React Native, asynchronous functions are functions that allow you to perform time-
consuming tasks without blocking the user interface (UI). These functions are typically used
to fetch data from an external source, such as an API, or to perform computations that take
a long time to complete.
Asynchronous functions in React Native typically use the async and await keywords to
manage asynchronous operations. When a function is marked as async, it means that the
function will return a promise. A promise is an object that represents the eventual
completion (or failure) of an asynchronous operation.
The await keyword is used to pause the execution of an asynchronous function until the
promise is resolved. This allows the function to wait for the result of the asynchronous
operation before continuing with the rest of the function.
Promises in JavaScript are objects that represent the eventual completion (or failure) of an
asynchronous operation and its resulting value. They are used to handle asynchronous
operations in a more elegant and readable way than using callbacks.
A promise has three states:
• Pending: The initial state, meaning that the operation has not yet completed.
• Fulfilled: The operation completed successfully, and the promise returns a value.
• Rejected: The operation failed, and the promise returns a reason for the failure.
Promises have two main methods that are used to handle the completion of the operation:
• .then(): This method is called when the promise is fulfilled, and it takes a function
that will be called with the resolved value of the promise as its argument.
• .catch(): This method is called when the promise is rejected, and it takes a function
that will be called with the reason for the rejection as its argument.
Code:
import React, { useState } from 'react';
import styles from '../styles';
import { StatusBar, StyleSheet, Alert, SafeAreaView, View, Text } from 'react-native';
import { TextInput, Button } from 'react-native-paper';
import { ChangePassScreenProps } from '../../../App';

import auth, { FirebaseAuthTypes } from '@react-native-firebase/auth';

const ChangePassScreen: React.FC<ChangePassScreenProps> = ({ navigation, route }) => {


const [oldPass, setOldPass] = useState('');
const [pass1, setPass1] = useState('');
const [pass2, setPass2] = useState('');

const onPressConfirm = () => {


// navigation.popToTop();
if (oldPass === '' || pass1 === '' || pass2 === '') {
Alert.alert('Field empty', 'Please enter all the required fields', [{ text: 'Okay' }]);
return;
}
if (pass1 !== pass2) {
Alert.alert(
"Passwords don't match"
, 'Please enter matching passwords',
[{ text: 'Okay', onPress: () => { } }]);
return;
}
changePassword();
};

const changePassword = async () => {


try {
let user = auth().currentUser;
await user?.reauthenticateWithCredential(auth.EmailAuthProvider.credential(user.email as string,
oldPass));
//After reauthentication
user = auth().currentUser;
user?.updatePassword(pass1);

Alert.alert(
'Password updated successfully',
'Please login again to continue',
[
{
text: 'Okay',
onPress: () => {
auth().signOut()
.then(() => {
navigation.popToTop();
navigation.replace('Welcome');
})
.catch((e) => {
Alert.alert('Logout error', e.message, [{ text: 'Okay' }]);
navigation.popToTop();
navigation.replace('Welcome');
});
}
}
]
)

} catch (e: any) {


console.log(`${e.code} / ${e.message}`);
if (e.code === 'auth/wrong-password') {
Alert.alert(
"Incorrect Old Password"
, 'Please enter the correct old password',
[{ text: 'Okay', onPress: () => { } }]);
} else {
Alert.alert('Error', `${e.code} ${e.message}`, [{ text: 'Okay' }])
}
}
};

const onPressCancel = () => {


navigation.goBack();
};

return (
<SafeAreaView>
<StatusBar
animated={true}
backgroundColor="#f1d74e"
barStyle='dark-content'
/>
<View style={styles.container}>
<Text style={styles.title}>
Change {"\n"}Password
</Text>
<TextInput
style={styles.inputs}
label='Old Password'
secureTextEntry={true}
value={oldPass}
onChangeText={(t) => { setOldPass(t) }}
/>
<TextInput
style={styles.inputs}
label='New Password'
secureTextEntry={true}
value={pass1}
onChangeText={(t) => { setPass1(t) }}
/>
<TextInput
style={styles.inputs}
label='Re-enter New Password'
secureTextEntry={true}
value={pass2}
onChangeText={(t) => { setPass2(t) }}
/>

<Button
mode='contained'
style={styles.regLoginButton}
onPress={() => { onPressConfirm() }}
>
Confirm
</Button>
<Button
mode='contained'
style={styles.regLoginButton}
onPress={() => { onPressCancel() }}
>
Cancel
</Button>
</View>
</SafeAreaView>
)
}

export default ChangePassScreen


Output:

Conclusion:
Asynchronous functions are non-blocking functions that return immediately and the
processing happens without stopping the execution of the rest of the program. We have
used asynchronous features of JavaScript including async and await keywords to consume
an API in our application.
Advait Naik (222050008)

Experiment 10

Aim: Exploration of life cycle functions for components, hook functions and XAML pages.

Theory:
In React Native, hooks are functions that allow you to use state and other React features
without writing a class. They were introduced in React 16.8 as a way to simplify and
streamline the process of writing functional components.
There are several built-in hooks in React Native:
• useState: This hook allows you to add state to a functional component. It takes an
initial value as a parameter and returns an array with two elements: the current
state value and a function to update the state.
• useEffect: This hook allows you to perform side effects, such as fetching data or
updating the DOM, in a functional component. It takes a function as a parameter and
runs it after the component is rendered.
• useContext: This hook allows you to access context in a functional component. It
takes a context object as a parameter and returns the current context value.
• useRef: This hook allows you to create a mutable value that persists across renders.
It takes an initial value as a parameter and returns a mutable ref object.
• useCallback: This hook allows you to memoize a function so that it only changes
when its dependencies change. It takes a function and an array of dependencies as
parameters and returns a memoized version of the function.
• useMemo: This hook allows you to memoize a value so that it only changes when its
dependencies change. It takes a function and an array of dependencies as
parameters and returns a memoized version of the value.
• useReducer: This hook allows you to use the Redux-style reducer pattern in a
functional component. It takes a reducer function, an initial state value, and an
optional initializer function as parameters and returns an array with the current state
value and a dispatch function to update the state.
By using hooks, you can write more concise and readable code in your React Native
applications, while still having access to all the features of React.
Code:
useContext & useReducer

import React, { createContext, useContext, useReducer } from "react";


import { Text } from "react-native";
import { Action, GlobalReducer } from "./GlobalReducer";
import GlobalState, { initState } from "./GlobalState";

export type GlobalContextType = {


state: GlobalState;
dispatcher: React.Dispatch<Action>;
};

const GlobalContext = createContext<GlobalContextType>({ state: initState, dispatcher: (v) => { } });

const useGlobalContext = () => {


return useContext(GlobalContext);
}

export const GlobalContextProvider = ({ children }: { children: JSX.Element }) => {

const [globalState, globalDispatcher] = useReducer(GlobalReducer, initState);


return (
<GlobalContext.Provider value={{state: globalState,dispatcher:globalDispatcher }}>
{children}
</GlobalContext.Provider>
);
};

export default useGlobalContext;

useEffect & useState


import React, { useState, useEffect } from 'react';
import { SafeAreaView, Text, View, ScrollView, FlatList, StatusBar, Alert } from 'react-native';
import { ActivityIndicator } from 'react-native-paper';
import useGlobalContext from '../../Models/GlobalContext';
import Header from './Header';
import NoteCard from './Note';
import styles from './Styles';
import navigation, { useNavigation } from '@react-navigation/native';
import GlobalState, { Colour, Colours, createNote, Note } from '../../Models/GlobalState';
import { MainScreenProps } from '../../App';
import FloatingActionButtion from './FloatingActionButtion';
import AccountModal from './AccountModal';

import auth from '@react-native-firebase/auth';


import firestore from '@react-native-firebase/firestore';

const MainScreen: React.FC<MainScreenProps> = ({ navigation, route }) => {


const [accountModalVisible, setAccountModalVisible] = useState(false);
const [isLoading, setIsLoading] = useState(true);
const global = useGlobalContext();

const avatarLetter = global.state.userLogin.email.charAt(0).toUpperCase();

useEffect(() => {
const user = auth().currentUser;
console.log('Current user: ' + user?.email);
// console.log('Current user: ' + user?.getIdToken());
const newGlobalState: GlobalState = {
notes: [],
userLogin: {
email: user?.email as string,
}
};
firestore()
.collection('users')
.doc(newGlobalState.userLogin.email)
.collection('notes')
.get()
.then(notes => {
notes.docs.forEach((note) => {
const n = note.data();
// console.log(note.id);
newGlobalState.notes.push({
title: n.title,
text: n.text,
colour: n.colour,
id: note.id,
creation_date: n.creation_date.toDate().toISOString(),
updation_date: n.updation_date ? n.updation_date.toDate().toISOString() : '',
isVisible: true,
});
});
global.dispatcher({ type: 'INIT', payload: newGlobalState });
setIsLoading(false);
})
.catch(e => {
console.log(e);
});
}, []);

const onPressLogoutModal = () => {


setAccountModalVisible(false);

auth().signOut()
.then(() => {
Alert.alert(
'User logger out successfully',
'Thank you!',
[{
text: 'Okay',
}]
);
if (navigation.canGoBack()) {
navigation.popToTop();
} else {
navigation.replace('Welcome');
}
})
.catch((e) => {
Alert.alert('Logout error', e.message, [{ text: 'Okay' }]);
if (navigation.canGoBack()) {
navigation.popToTop();
} else {
navigation.replace('Welcome');
}
});
}

const onPressDeleteAcc = () => {


deleteAccount()
.then(() => {
Alert.alert(
'Account Deleted successfully',
'Please register again to continue',
[
{
text: 'Okay',
onPress: () => {
if (navigation.canGoBack()) {
navigation.popToTop();
} else {
navigation.replace('Welcome');
}
}
}
]
)
}).catch((e) => {
Alert.alert(
'Account Deletion error',
e.message,
[
{
text: 'Okay',
onPress: () => {
if (navigation.canGoBack()) {
navigation.popToTop();
} else {
navigation.replace('Welcome');
}
}
}
]
)
});
};

const deleteAccount = async () => {


const db = firestore();
const snap = await db.collection('users')
.doc(global.state.userLogin.email)
.collection('notes')
.get()
const batch = db.batch()
snap.forEach((doc) => {
// console.log(doc.ref);
batch.delete(doc.ref);
});
await batch.commit()
await auth().currentUser?.delete();
};

const onPressChangePassModal = () => {


setAccountModalVisible(false);
navigation.push('ChangePass');
}

const handlerOnClick = (note: Note) => {


console.log('Pressed ' + note.title);
navigation.navigate('Edit', { note: note, mode: 'edit' });
};

const handlerAddNote = () => {


navigation.navigate('Edit', { mode: 'add', note: createNote("", "", Colours[0]) });
}

const notes = global.state.notes.filter(n => n.isVisible);


const noteDivs: React.ReactElement[] = [];

for (let i = 0; i < notes.length; i = i + 2) {


noteDivs.push(
<View key={notes[i].id} style={styles.main__body__noteDiv}>
<NoteCard note={notes[i]} onClick={handlerOnClick} />
{i + 1 < notes.length ? <NoteCard note={notes[i + 1]} onClick={handlerOnClick} />
:
<View style={styles.main__body__noteCard}></View>}
</View>
);
}

if (isLoading) {
return (<SafeAreaView style={[styles.main, { alignItems: 'center', justifyContent: 'center' }]}>
<StatusBar
animated={true}
backgroundColor="#f1d74e"
barStyle='dark-content'
/>
<ActivityIndicator animating={true} size={'large'} />
</SafeAreaView>)
}

return (
<SafeAreaView style={styles.main}>
<StatusBar
animated={true}
backgroundColor="#f1d74e"
barStyle='dark-content'
/>
<Header
avatarLetter={avatarLetter}
setAccountModalVisible={setAccountModalVisible}
/>
<AccountModal
email={global.state.userLogin.email}
isVisible={accountModalVisible}
setIsVisible={setAccountModalVisible}
onPressLogout={onPressLogoutModal}
onPressChangePass={onPressChangePassModal}
onPressDeleteAcc={onPressDeleteAcc}
/>
<FloatingActionButtion
onClickHandler={handlerAddNote}
/>
<ScrollView
style={styles.main__body}
>
{noteDivs}
</ScrollView>

{/* <FlatList
style={styles.main__body}
data={noteDivs}
renderItem={({ item }) => <item />}
keyExtractor={(item,index) => noteIds[index]} /> */}
</SafeAreaView >);
};

export default MainScreen;


Output:

Conclusion:
React Hooks provide a concise way to implement functions related to state, life cycle events
and data propagation. We have used useState for state management, useEffect for lifecycle
management, useReducer and useContext for global state management.
Advait Naik (222050008)

Experiment 11

Aim: Implementation and integration with firebase backend and application deployment.

Theory:
Firebase is a mobile and web application development platform that provides a range of
tools and services to help developers build high-quality apps. It was developed by Firebase
Inc., which was acquired by Google in 2014.
Firebase offers a range of services, including:
• Realtime Database: A NoSQL cloud database that allows developers to store and
sync data in real time.
• Authentication: A service that provides easy-to-use authentication and user
management functionality, including email and password authentication, social sign-
in, and more.
• Cloud Messaging: A service that allows developers to send notifications to their app
users across multiple platforms.
• Hosting: A service that provides fast and secure web hosting for static and dynamic
content.
• Cloud Functions: A serverless compute platform that allows developers to run
backend code in response to events triggered by Firebase services or other third-
party services.
• Storage: A cloud storage service that allows developers to store and serve user-
generated content, such as images and videos.
• Analytics: A service that provides insights into user behaviour and app performance.
Firebase is popular among developers because it provides an easy-to-use, scalable, and cost-
effective platform for building mobile and web applications. With Firebase, developers can
focus on building great apps without having to worry about infrastructure or server
management.
Code:
import React, { useState, useEffect } from 'react';
import { SafeAreaView, Text, View, ScrollView, FlatList, StatusBar, Alert } from 'react-native';
import { ActivityIndicator } from 'react-native-paper';
import useGlobalContext from '../../Models/GlobalContext';
import Header from './Header';
import NoteCard from './Note';
import styles from './Styles';
import navigation, { useNavigation } from '@react-navigation/native';
import GlobalState, { Colour, Colours, createNote, Note } from '../../Models/GlobalState';
import { MainScreenProps } from '../../App';
import FloatingActionButtion from './FloatingActionButtion';
import AccountModal from './AccountModal';

import auth from '@react-native-firebase/auth';


import firestore from '@react-native-firebase/firestore';

const MainScreen: React.FC<MainScreenProps> = ({ navigation, route }) => {


const [accountModalVisible, setAccountModalVisible] = useState(false);
const [isLoading, setIsLoading] = useState(true);
const global = useGlobalContext();

const avatarLetter = global.state.userLogin.email.charAt(0).toUpperCase();

useEffect(() => {
const user = auth().currentUser;
console.log('Current user: ' + user?.email);
// console.log('Current user: ' + user?.getIdToken());
const newGlobalState: GlobalState = {
notes: [],
userLogin: {
email: user?.email as string,
}
};
firestore()
.collection('users')
.doc(newGlobalState.userLogin.email)
.collection('notes')
.get()
.then(notes => {
notes.docs.forEach((note) => {
const n = note.data();
// console.log(note.id);
newGlobalState.notes.push({
title: n.title,
text: n.text,
colour: n.colour,
id: note.id,
creation_date: n.creation_date.toDate().toISOString(),
updation_date: n.updation_date ? n.updation_date.toDate().toISOString() : '',
isVisible: true,
});
});
global.dispatcher({ type: 'INIT', payload: newGlobalState });
setIsLoading(false);
})
.catch(e => {
console.log(e);
});
}, []);

const onPressLogoutModal = () => {


setAccountModalVisible(false);

auth().signOut()
.then(() => {
Alert.alert(
'User logger out successfully',
'Thank you!',
[{
text: 'Okay',
}]
);
if (navigation.canGoBack()) {
navigation.popToTop();
} else {
navigation.replace('Welcome');
}
})
.catch((e) => {
Alert.alert('Logout error', e.message, [{ text: 'Okay' }]);
if (navigation.canGoBack()) {
navigation.popToTop();
} else {
navigation.replace('Welcome');
}
});
}

const onPressDeleteAcc = () => {


deleteAccount()
.then(() => {
Alert.alert(
'Account Deleted successfully',
'Please register again to continue',
[
{
text: 'Okay',
onPress: () => {
if (navigation.canGoBack()) {
navigation.popToTop();
} else {
navigation.replace('Welcome');
}
}
}
]
)
}).catch((e) => {
Alert.alert(
'Account Deletion error',
e.message,
[
{
text: 'Okay',
onPress: () => {
if (navigation.canGoBack()) {
navigation.popToTop();
} else {
navigation.replace('Welcome');
}
}
}
]
)
});
};

const deleteAccount = async () => {


const db = firestore();
const snap = await db.collection('users')
.doc(global.state.userLogin.email)
.collection('notes')
.get()
const batch = db.batch()
snap.forEach((doc) => {
// console.log(doc.ref);
batch.delete(doc.ref);
});
await batch.commit()
await auth().currentUser?.delete();
};

const onPressChangePassModal = () => {


setAccountModalVisible(false);
navigation.push('ChangePass');
}

const handlerOnClick = (note: Note) => {


console.log('Pressed ' + note.title);
navigation.navigate('Edit', { note: note, mode: 'edit' });
};

const handlerAddNote = () => {


navigation.navigate('Edit', { mode: 'add', note: createNote("", "", Colours[0]) });
}

const notes = global.state.notes.filter(n => n.isVisible);


const noteDivs: React.ReactElement[] = [];

for (let i = 0; i < notes.length; i = i + 2) {


noteDivs.push(
<View key={notes[i].id} style={styles.main__body__noteDiv}>
<NoteCard note={notes[i]} onClick={handlerOnClick} />
{i + 1 < notes.length ? <NoteCard note={notes[i + 1]} onClick={handlerOnClick} />
:
<View style={styles.main__body__noteCard}></View>}
</View>
);
}

if (isLoading) {
return (<SafeAreaView style={[styles.main, { alignItems: 'center', justifyContent: 'center' }]}>
<StatusBar
animated={true}
backgroundColor="#f1d74e"
barStyle='dark-content'
/>
<ActivityIndicator animating={true} size={'large'} />
</SafeAreaView>)
}

return (
<SafeAreaView style={styles.main}>
<StatusBar
animated={true}
backgroundColor="#f1d74e"
barStyle='dark-content'
/>
<Header
avatarLetter={avatarLetter}
setAccountModalVisible={setAccountModalVisible}
/>
<AccountModal
email={global.state.userLogin.email}
isVisible={accountModalVisible}
setIsVisible={setAccountModalVisible}
onPressLogout={onPressLogoutModal}
onPressChangePass={onPressChangePassModal}
onPressDeleteAcc={onPressDeleteAcc}
/>
<FloatingActionButtion
onClickHandler={handlerAddNote}
/>
<ScrollView
style={styles.main__body}
>
{noteDivs}
</ScrollView>

{/* <FlatList
style={styles.main__body}
data={noteDivs}
renderItem={({ item }) => <item />}
keyExtractor={(item,index) => noteIds[index]} /> */}
</SafeAreaView >);
};

export default MainScreen;


Output:
Conclusion:
Firebase provides easy to use services to develop mobile and web applications. We have
used Firebase’s Firestore Database to store our app’s data. Firestore is a NoSQL Database
that provides the ability to store and retrieve data in real-time.

You might also like