Commit 66491651 authored by Malsha Jayakody's avatar Malsha Jayakody

Merge remote-tracking branch 'origin/exercise-manage' into final-app

parents 02666913 03d5b126
......@@ -85,6 +85,15 @@ android {
versionName "1.0"
}
signingConfigs {
release {
if (project.hasProperty('MYAPP_UPLOAD_STORE_FILE')) {
storeFile file(MYAPP_UPLOAD_STORE_FILE)
storePassword MYAPP_UPLOAD_STORE_PASSWORD
keyAlias MYAPP_UPLOAD_KEY_ALIAS
keyPassword MYAPP_UPLOAD_KEY_PASSWORD
}
}
debug {
storeFile file('debug.keystore')
storePassword 'android'
......@@ -99,7 +108,7 @@ android {
release {
// Caution! In production, you need to generate your own keystore file.
// see https://reactnative.dev/docs/signed-apk-android.
signingConfig signingConfigs.debug
signingConfig signingConfigs.release
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
......
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
......
......@@ -39,3 +39,8 @@ newArchEnabled=false
# Use this property to enable or disable the Hermes JS engine.
# If set to false, you will be using JSC instead.
hermesEnabled=true
MYAPP_UPLOAD_STORE_FILE=my-upload-key.keystore
MYAPP_UPLOAD_KEY_ALIAS=my-key-alias
MYAPP_UPLOAD_STORE_PASSWORD=midwife
MYAPP_UPLOAD_KEY_PASSWORD=midwife
\ No newline at end of file
import React, { useState, useRef, useEffect } from 'react';
import { StyleSheet, Text, View, ActivityIndicator, TouchableOpacity } from 'react-native';
import Video from 'react-native-video';
import { Camera, useCameraDevice, CameraPermissionStatus } from 'react-native-vision-camera';
import CircleProgressBar from '../../../components/CircleProgressBar';
import { COLORS, ROUTES } from '../../../constants';
import Dot from '../../../assets/icons/dot.svg';
......@@ -9,10 +10,14 @@ const ExerciseView = (props) => {
const { route } = props;
const { data } = route.params; // Assuming you pass videoUrl as a route parameter
const videoRef = useRef(null);
const cameraRef = useRef(null);
const [loading, setLoading] = useState(true);
const [videoPaused, setVideoPaused] = useState(true);
const [remainingTime, setRemainingTime] = useState(data.duration);
const [remainingTime, setRemainingTime] = useState(null);
const [startCountDown, setStartCountDown] = useState(false);
const [isRecording, setIsRecording] = useState(false);
const [videoSource, setVideoSource] = useState('');
const device = useCameraDevice('front')
const handleLoad = () => {
setLoading(false);
......@@ -32,24 +37,112 @@ const ExerciseView = (props) => {
const handleVideoEnd = () => {
setVideoPaused(true);
setStartCountDown(true);
// setStartCountDown(true);
setRemainingTime(data.duration); // Reset remaining time
};
const startRecording = async () => {
if (cameraRef.current && !isRecording) {
setIsRecording(true);
const video = await cameraRef.current.startRecording({
onRecordingFinished: (video) => {
setVideoSource(video.path);
setIsRecording(false);
console.log(video.path);
},
onRecordingError: (error) => {
console.error(`Recording Error: ${error.message}`);
setIsRecording(false);
},
});
}
};
const stopRecording = () => {
if (cameraRef.current && isRecording) {
cameraRef.current.stopRecording();
setIsRecording(false);
}
};
useEffect(() => {
if (remainingTime > 0 && startCountDown) {
const interval = setInterval(() => {
setRemainingTime((prevTime) => prevTime - 1);
// Initialize remainingTime when component mounts
setRemainingTime(data.duration * 2);
}, [data.duration]);
useEffect(() => {
let interval;
if (!videoPaused && remainingTime > 0) {
interval = setInterval(() => {
setRemainingTime(prevTime => prevTime - 1);
}, 1000);
}
return () => clearInterval(interval);
}, [videoPaused, remainingTime]);
useEffect(() => {
async function requestPermissions() {
const cameraPermission = await Camera.requestCameraPermission();
const microphonePermission = await Camera.requestMicrophonePermission();
if (cameraPermission !== CameraPermissionStatus.AUTHORIZED || microphonePermission !== CameraPermissionStatus.AUTHORIZED) {
Linking.openSettings();
}
}, [remainingTime, startCountDown]);
}
requestPermissions();
}, []);
return (
<View style={styles.container}>
<Text style={styles.title}>Exercise Details</Text>
<View style={styles.videoContainer}>
<Video
ref={videoRef}
source={{ uri: data.exercise_video_url }}
style={styles.video}
controls={true}
paused={videoPaused}
resizeMode="contain"
onLoad={handleLoad}
onBuffer={handleBuffer}
/>
{loading && <ActivityIndicator style={styles.loader} size="large" color="#0000ff" />}
</View>
<View style={styles.progressMainView}>
<CircleProgressBar percentage={(remainingTime / (data.duration * 2)) * 100} />
<View style={styles.progressSecondView}>
<Text>Remaining</Text>
<Text>{remainingTime} seconds</Text>
</View>
</View>
<View style={styles.buttonsContainer}>
<TouchableOpacity style={styles.button} onPress={videoPaused ? handlePlay : handlePause}>
<Text style={styles.buttonText}>{videoPaused ? 'Play' : 'Pause'}</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.buttonRed} onPress={handlePause}>
<Text style={styles.buttonText}>Stop</Text>
</TouchableOpacity>
</View>
<View>
{device != null && (
<View style={styles.cameraContainer}>
<Camera
ref={cameraRef}
style={styles.camera}
device={device}
isActive={true}
video={true}
audio={true}
/>
</View>
)}
</View>
{/* <View style={styles.videoContainer}>
<Video
ref={videoRef}
source={{ uri: data.exercise_video_url }}
......@@ -89,22 +182,23 @@ const ExerciseView = (props) => {
))}
</View>
</View>
</View>
</View> */}
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
width: '100%',
height: 'auto'
},
title: {
fontSize: 20,
fontWeight: 'bold',
marginBottom: 20,
marginTop: 10,
textAlign: 'center',
},
videoContainer: {
......@@ -112,9 +206,8 @@ const styles = StyleSheet.create({
aspectRatio: 16 / 9,
justifyContent: 'center',
alignItems: 'center',
marginTop: 40,
marginTop: 10,
position: 'relative',
top: '25%',
},
video: {
width: '100%',
......@@ -133,10 +226,22 @@ const styles = StyleSheet.create({
paddingBottom: 10,
},
button: {
backgroundColor: '#2196F3',
padding: 10,
borderRadius: 50,
marginHorizontal: 5,
backgroundColor: COLORS.primary,
justifyContent: 'center',
alignItems: 'center',
width: 80, // Adjust width and height as needed
height: 80,
borderRadius: 40, // Make the radius half of the width/height to make it circular
marginRight: 10
},
buttonRed: {
backgroundColor: COLORS.warning,
justifyContent: 'center',
alignItems: 'center',
width: 80, // Adjust width and height as needed
height: 80,
borderRadius: 40, // Make the radius half of the width/height to make it circular
marginRight: 10
},
buttonText: {
color: 'white',
......@@ -157,7 +262,7 @@ const styles = StyleSheet.create({
backgroundColor: COLORS.white,
marginHorizontal: 20,
borderRadius: 15,
marginTop: 10,
marginTop: 20,
paddingVertical: 10,
},
progressSecondView: {
......@@ -197,6 +302,11 @@ const styles = StyleSheet.create({
backgroundColor: 'black',
marginHorizontal: 5,
},
cameraContainer: {
width: '100%',
aspectRatio: 16 / 9,
marginTop: 20,
},
});
export default ExerciseView;
......
......@@ -9,7 +9,8 @@ import {
Image,
View,
ScrollView,
Button
Button,
ActivityIndicator
} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
import Logo from '../../../assets/icons/progress.svg';
......@@ -20,26 +21,6 @@ import { getAllExerciseDay } from '../../../services/exercises/index';
import AsyncStorage from '@react-native-async-storage/async-storage';
const moment = require('moment');
// import Button from '../../../components/Button';
// import Carousel from 'react-native-snap-carousel-v4';
// const carouselRef = useRef(null);
// const sliderrenderItem = ({ item, index }) => {
// return (
// <View style={{
// backgroundColor: 'floralwhite',
// borderRadius: 5,
// height: 250,
// padding: 50,
// marginLeft: 25,
// marginRight: 25,
// }}>
// <Text style={{ fontSize: 30 }}>{item.title}</Text>
// <Text>{item.text}</Text>
// </View>
// );
// };
const Item = ({ item, onPress, backgroundColor, textColor }) => (
<TouchableOpacity onPress={onPress} style={[styles.item, { backgroundColor, flexDirection: "row", width: '100%' }]}>
<Image
......@@ -58,6 +39,7 @@ const Item = ({ item, onPress, backgroundColor, textColor }) => (
);
const MainMenuExercise = (props) => {
const [loading, setLoading] = useState(true);
const { navigation } = props;
const [selectedId, setSelectedId] = useState(null);
const [exerciseDataArray, setExerciseData] = useState();
......@@ -99,6 +81,7 @@ const MainMenuExercise = (props) => {
};
const retriveExerciseList = async () => {
setLoading(true)
let userDataString = await AsyncStorage.getItem('userData');
let userData = JSON.parse(userDataString);
let todayDate = moment().format();
......@@ -111,7 +94,7 @@ const MainMenuExercise = (props) => {
dataNum = 2;
}
if (todayDateByFormat === "Friday" || todayDateByFormat === "Saturday" || todayDateByFormat === "Sunday") {
dataNum = 3;
dataNum = 2;
}
let exerciseData = await getAllExerciseDay(userData._id, dataNum);
let dataArray = exerciseData.data.data;
......@@ -147,6 +130,8 @@ const MainMenuExercise = (props) => {
}
setExerciseData(exerciseModifiedAarray);
setLoading(false)
console.log("new data ",exerciseModifiedAarray )
}
}
......@@ -172,6 +157,7 @@ const MainMenuExercise = (props) => {
extraData={selectedId}
style={{ marginBottom: 20 }}
/>
{loading && <ActivityIndicator style={styles.loader} size="large" color="#0000ff" />}
</ScrollView>
<Text style={styles.topText}>Progress</Text>
<View style={styles.progressMainView}>
......@@ -279,6 +265,12 @@ const styles = StyleSheet.create({
marginVertical: 5,
marginHorizontal: 16,
},
loader: {
position: 'absolute',
top: '50%',
left: '50%',
transform: [{ translateX: -25 }, { translateY: -25 }],
},
title: {
fontSize: 14,
},
......
import axios from 'axios';
const BASE_PATH = 'http://10.0.2.2:8070/api/mother';
const BASE_PATH = 'https://emidwife-api.onrender.com/api/mother';
import AsyncStorage from '@react-native-async-storage/async-storage';
//signIn API Call
......
import axios from "axios";
const BASE_PATH = 'http://16.170.242.186:8080';
const BASE_PATH2 = 'http://10.0.2.2:8070/api/mother';
let BASE_PATH = 'http://16.170.242.186:8080';
let BASE_PATH2 = 'https://emidwife-api.onrender.com/api/mother';
import AsyncStorage from '@react-native-async-storage/async-storage';
......@@ -34,9 +34,9 @@ export let addInitialExercises = async (id, riskLevel) => {
}
export let getAllExerciseDay = async (id, dateNum) => {
try {
console.log("id", id)
let value = await axios.post(BASE_PATH2 + '/get_all_exercise_day', {
_id: id,
day: dateNum
......@@ -47,7 +47,6 @@ export let getAllExerciseDay = async (id, dateNum) => {
}
}
export let updateDeviceStatus = async (id, deviceStatus) => {
try {
let value = await axios.post(BASE_PATH2 + '/update_device_status', {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment