Pomodoro en React Native - Pomodoro in React Native
Table of contents
- Introducción - Introduction
- npm Packages
- Servicio - Service
- constants.ts
- Importaciones
- Definición de la lista de pistas
- Imports
- musicPlayerServices.js
- Importaciones
- setupPlayer()
- addTrack()
- playbackService()
- Imports
- setupPlayer()
- index.js
- Importaciones
- Registro del Componente
- Configuración del Reproductor y Registro del Servicio de Reproducción
- Imports
- Component Registration
- Player Setup and Playback Service Registration
- Components
- FiveMinutesScreen.tsx
- Importaciones
- Función FiveMinutesScreen
- Eventos y Funciones de Control de Reproducción
- Lógica del Temporizador
- Imports
- FiveMinutesScreen Function
- Playback Control Events and Functions
- Timer Logic
- TenMinutesScreen.tsx
- TwentyFiveMinutesScreen.tsx
- App.tsx
- Importaciones
- Función App
- Inicialización del Reproductor de Música
- Lógica de las Pestañas
- Imports
- App Function
- Music Player Initialization
- Tab Logic
- Video & Github
Introducción - Introduction
Nuestra aplicación Timer Pomodoro te ofrece intervalos de 5, 10 y 25 minutos para ayudarte a enfocarte y ser más productivo. Cuando cada intervalo llega a su fin, se activa una alarma que te ayuda a mantener la concentración. Además, la aplicación cuenta con un modo de fondo que te permite seguir utilizando tu dispositivo mientras el temporizador está en funcionamiento.
Our Pomodoro Timer app provides you with intervals of 5, 10, and 25 minutes to help you stay focused and be more productive. When each interval comes to an end, an alarm sounds to help you maintain concentration. Additionally, the app features a background mode that allows you to continue using your device while the timer is running.
npm Packages
https://www.npmjs.com/package/react-native-safe-area-context
https://www.npmjs.com/package/@sayem314/react-native-keep-awake
Servicio - Service
constants.ts
import { Track } from "react-native-track-player";
export const playListData: Track[] = [
{
id: 1,
title: 'alarma',
artist: 'personal',
album: 'personal',
artwork:
'',
url: require('./assets/audio/alarma.mp3'),
}
];
Importaciones
import { Track } from "react-native-track-player";
Aquí estamos importando el modelo Track
de la biblioteca react-native-track-player
, que representa una pista de audio.
Definición de la lista de pistas
export const playListData: Track[] = [
{
id: 1,
title: 'alarma',
artist: 'personal',
album: 'personal',
artwork: '',
url: require('./assets/audio/alarma.mp3'),
}
];
Definimos una lista de pistas de tipo Track[]
llamada playListData
que contiene un objeto con los datos de una pista: id, título, artista, álbum, portada y URL.
Imports
import { Track } from "react-native-track-player";
Here we are importing the Track
model from the react-native-track-player
library, which represents an audio track.
musicPlayerServices.js
import TrackPlayer, { Event, RepeatMode, Capability } from "react-native-track-player";
import { playListData } from './src/constants';
export async function setupPlayer() {
let isSetup = false;
try {
await TrackPlayer.getCurrentTrack();
isSetup = true;
} catch (error) {
await TrackPlayer.setupPlayer();
isSetup = true;
} finally {
return isSetup;
}
}
export async function addTrack() {
await TrackPlayer.add(playListData);
await TrackPlayer.setRepeatMode(RepeatMode.Queue);
}
export async function playbackService() {
await TrackPlayer.updateOptions({
capabilities: [
Capability.Play,
Capability.Pause,
Capability.SkipToNext,
Capability.SkipToPrevious,
Capability.Stop
],
compactCapabilities: [Capability.Play, Capability.Pause, Capability.Stop],
});
TrackPlayer.addEventListener(Event.RemotePause, () => {
TrackPlayer.pause();
});
TrackPlayer.addEventListener(Event.RemotePlay, () => {
TrackPlayer.play();
});
TrackPlayer.addEventListener(Event.RemoteNext, () => {
TrackPlayer.skipToNext();
});
TrackPlayer.addEventListener(Event.RemotePrevious, () => {
TrackPlayer.skipToPrevious();
});
TrackPlayer.addEventListener(Event.RemoteStop, () => {
TrackPlayer.stop();
});
}
Importaciones
import TrackPlayer, { Event, RepeatMode, Capability } from "react-native-track-player";
import { playListData } from './src/constants';
Aquí estamos importando el módulo TrackPlayer
de la biblioteca react-native-track-player
, que nos permite reproducir audio en segundo plano en una aplicación React Native. También importamos algunas constantes específicas de este módulo: Event
, RepeatMode
y Capability
. Además, importamos playListData
de un archivo de constantes en nuestro proyecto.
setupPlayer()
export async function setupPlayer() {
let isSetup = false;
try {
await TrackPlayer.getCurrentTrack();
isSetup = true;
} catch (error) {
await TrackPlayer.setupPlayer();
isSetup = true;
} finally {
return isSetup;
}
}
Esta función asincrónica intenta obtener la pista actual que se está reproduciendo. Si puede obtenerla, significa que el reproductor ya está configurado, por lo que establece isSetup
en true
. Si no puede obtenerla y se produce un error, entonces configura el reproductor y establece isSetup
en true
. Finalmente, la función devuelve el valor de isSetup
.
addTrack()
export async function addTrack() {
await TrackPlayer.add(playListData);
await TrackPlayer.setRepeatMode(RepeatMode.Queue);
}
Esta función asincrónica agrega las pistas de playListData
al reproductor y establece el modo de repetición en RepeatMode.Queue
, lo que significa que la lista de reproducción comenzará de nuevo una vez que se hayan reproducido todas las pistas.
playbackService()
export async function playbackService() {
await TrackPlayer.updateOptions({
capabilities: [
Capability.Play,
Capability.Pause,
Capability.SkipToNext,
Capability.SkipToPrevious,
Capability.Stop
],
compactCapabilities: [Capability.Play, Capability.Pause, Capability.Stop],
});
TrackPlayer.addEventListener(Event.RemotePause, () => {
TrackPlayer.pause();
});
TrackPlayer.addEventListener(Event.RemotePlay, () => {
TrackPlayer.play();
});
TrackPlayer.addEventListener(Event.RemoteNext, () => {
TrackPlayer.skipToNext();
});
TrackPlayer.addEventListener(Event.RemotePrevious, () => {
TrackPlayer.skipToPrevious();
});
TrackPlayer.addEventListener(Event.RemoteStop, () => {
TrackPlayer.stop();
});
}
Esta función asincrónica actualiza las opciones del reproductor, estableciendo las capacidades que puede manejar (reproducir, pausar, saltar a la siguiente pista, saltar a la pista anterior, detener) y las capacidades compactas (reproducir, pausar, detener). Luego, configura varios oyentes de eventos para manejar los controles remotos de pausa, reproducción, siguiente, anterior y detener.
Imports
import TrackPlayer, { Event, RepeatMode, Capability } from "react-native-track-player";
import { playListData } from './src/constants';
Here we are importing the TrackPlayer
module from the react-native-track-player
library, which allows us to play audio in the background in a React Native application. We also import some specific constants from this module: Event
, RepeatMode
, and Capability
. In addition, we import playListData
from a constants file in our project.
setupPlayer()
export async function setupPlayer() {
let isSetup = false;
try {
await TrackPlayer.getCurrentTrack();
isSetup = true;
} catch (error) {
await TrackPlayer.setupPlayer();
isSetup = true;
} finally {
return isSetup;
}
}
This asynchronous function tries to get the current track that is playing. If it can get it, it means the player is already set up, so it sets isSetup
to true
. If it can't get it and an error occurs, then it sets up the player and sets isSetup
to true
. Finally, the function returns the value of isSetup
.
index.js
import {AppRegistry} from 'react-native';
import App from './src/App';
import {name as appName} from './app.json';
import TrackPlayer from 'react-native-track-player';
import { setupPlayer, playbackService } from './musicPlayerServices';
AppRegistry.registerComponent(appName, () => App);
(async () => {
await setupPlayer();
TrackPlayer.registerPlaybackService(() => playbackService);
})();
Importaciones
import {AppRegistry} from 'react-native';
import App from './src/App';
import {name as appName} from './app.json';
import TrackPlayer from 'react-native-track-player';
import { setupPlayer, playbackService } from './musicPlayerServices';
Aquí estamos importando los módulos necesarios para configurar la aplicación y el reproductor de pistas de música. AppRegistry
se utiliza para registrar el componente principal de la aplicación, App
es el componente principal de la aplicación, appName
es el nombre de la aplicación, TrackPlayer
es el reproductor de pistas de música, y setupPlayer
y playbackService
son funciones para configurar y controlar el reproductor de pistas de música.
Registro del Componente
AppRegistry.registerComponent(appName, () => App);
Aquí estamos registrando el componente principal de la aplicación utilizando AppRegistry
.
Configuración del Reproductor y Registro del Servicio de Reproducción
(async () => {
await setupPlayer();
TrackPlayer.registerPlaybackService(() => playbackService);
})();
Esta función asincrónica se autoinvoca y primero configura el reproductor de pistas de música utilizando la función setupPlayer
. Luego registra el servicio de reproducción utilizando TrackPlayer.registerPlaybackService
y la función playbackService
.
Imports
import {AppRegistry} from 'react-native';
import App from './src/App';
import {name as appName} from './app.json';
import TrackPlayer from 'react-native-track-player';
import { setupPlayer, playbackService } from './musicPlayerServices';
Here we are importing the necessary modules to set up the application and the music track player. AppRegistry
is used to register the main component of the application, App
is the main component of the application, appName
is the name of the application, TrackPlayer
is the music track player, and setupPlayer
and playbackService
are functions to set up and control the music track player.
Component Registration
AppRegistry.registerComponent(appName, () => App);
Here we are registering the main component of the application using AppRegistry
.
Player Setup and Playback Service Registration
(async () => {
await setupPlayer();
TrackPlayer.registerPlaybackService(() => playbackService);
})();
This self-invoking asynchronous function first sets up the music track player using the setupPlayer
function. It then registers the playback service using TrackPlayer.registerPlaybackService
and the playbackService
function.
Components
FiveMinutesScreen.tsx
import React, { useEffect, useState } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import TrackPlayer, { State, usePlaybackState, Event, Track, useTrackPlayerEvents } from 'react-native-track-player';
import BackgroundTimer from 'react-native-background-timer';
import { setupPlayer, playbackService } from '../../musicPlayerServices';
import KeepAwake, { useKeepAwake,activateKeepAwake, deactivateKeepAwake } from '@sayem314/react-native-keep-awake';
const FiveMinutesScreen = () => {
const [stopped, setStopped] = useState(true);
const [paused, setPaused] = useState(true);
const [minutes, setMinutes] = useState(5);
const [seconds, setSeconds] = useState(0);
const [temporizadorFinalizado, setTemporizadorFinalizado] = useState(false);
const [track, setTrack] = useState<Track | null>();
useTrackPlayerEvents([Event.PlaybackTrackChanged], async event => {
switch (event.type) {
case Event.PlaybackTrackChanged:
const playingTrack = await TrackPlayer.getTrack(event.nextTrack)
setTrack(playingTrack)
break;
}
});
const playbackState = usePlaybackState();
const play = async (playback: State) => {
const currentTrack = await TrackPlayer.getCurrentTrack()
if (currentTrack !== null) {
if (playback === State.Stopped || playback === State.Ready) {
await TrackPlayer.play()
}
}
}
const stop = async (playback: State) => {
const currentTrack = await TrackPlayer.getCurrentTrack()
if (currentTrack !== null) {
if (playback === State.Playing) {
await TrackPlayer.pause();
await TrackPlayer.seekTo(0);
}
}
}
const startTimer = () => {
if (temporizadorFinalizado) {
setMinutes(5);
setSeconds(0);
}
setStopped(false);
setPaused(false);
setTemporizadorFinalizado(false);
};
const pauseTimer = () => {
setPaused(true);
setTemporizadorFinalizado(false);
};
const stopTimer = () => {
setStopped(true);
setPaused(false);
setMinutes(5);
setSeconds(0);
stop(playbackState);
setTemporizadorFinalizado(true);
};
const resetTimer = () => {
setStopped(true);
setPaused(true);
setMinutes(5);
setSeconds(0);
};
useEffect(() => {
let interval: number;
if (!stopped && !paused) {
interval = BackgroundTimer.setInterval(() => {
if (seconds > 0) {
setSeconds(seconds - 1);
} else {
if (minutes === 0) {
BackgroundTimer.clearInterval(interval);
setStopped(true);
setTemporizadorFinalizado(true);
play(playbackState);
} else {
setMinutes(minutes - 1);
setSeconds(59);
}
}
}, 1000);
}
return () => {
if (interval) {
BackgroundTimer.clearInterval(interval);
}
};
}, [stopped, paused, minutes, seconds]);
return (
<View style={styles.container}>
<KeepAwake />
<Text style={styles.timerText}>
0{minutes}:{seconds < 10 ? `0${seconds}` : seconds}
</Text>
<View style={styles.iconContainer}>
<Icon
name={paused ? 'play-box' : 'pause-octagon'}
size={100}
color="#192A56"
onPress={paused ? startTimer : pauseTimer}
/>
<Icon
name={temporizadorFinalizado ? 'stop' : 'restore'}
size={100}
color="#192A56"
onPress={temporizadorFinalizado ? stopTimer : resetTimer}
/>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#F0DF87',
},
timerText: {
fontSize: 100,
fontWeight: 'bold',
marginBottom: 10,
color: '#192A56',
},
iconContainer: {
flexDirection: 'row',
justifyContent: 'space-around',
marginTop: 20,
},
});
export default FiveMinutesScreen;
El código proporcionado es un componente de React llamado FiveMinutesScreen
que utiliza varios hooks y módulos de React Native para implementar un temporizador de cuenta regresiva de cinco minutos. Aquí está el desglose paso a paso del código:
Importaciones
import React, { useEffect, useState } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import TrackPlayer, { State, usePlaybackState, Event, Track, useTrackPlayerEvents } from 'react-native-track-player';
import BackgroundTimer from 'react-native-background-timer';
import { setupPlayer, playbackService } from '../../musicPlayerServices';
import KeepAwake, { useKeepAwake,activateKeepAwake, deactivateKeepAwake } from '@sayem314/react-native-keep-awake';
Aquí se importan los módulos y hooks necesarios para el componente, incluyendo componentes de React Native, iconos, TrackPlayer para la reproducción de audio, BackgroundTimer para el temporizador en segundo plano, y KeepAwake para mantener despierto el dispositivo.
Función FiveMinutesScreen
La función FiveMinutesScreen
es el componente principal que renderiza la pantalla del temporizador de cinco minutos. Utiliza estados locales para controlar el estado del temporizador, los minutos, los segundos, etc. También utiliza varios hooks de React, como useEffect
y useState
, para manejar la lógica del temporizador y la reproducción de audio.
Eventos y Funciones de Control de Reproducción
El componente utiliza el hook useTrackPlayerEvents
para manejar eventos de cambio de pista de reproducción. También define funciones para controlar la reproducción y pausa de pistas de audio.
Lógica del Temporizador
Dentro del hook useEffect
, se implementa la lógica del temporizador utilizando BackgroundTimer
para contar el tiempo y actualizar el estado del temporizador.
The provided code is a React component called FiveMinutesScreen
that uses various React Native hooks and modules to implement a five-minute countdown timer. Here's the step-by-step breakdown of the code:
Imports
import React, { useEffect, useState } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import TrackPlayer, { State, usePlaybackState, Event, Track, useTrackPlayerEvents } from 'react-native-track-player';
import BackgroundTimer from 'react-native-background-timer';
import { setupPlayer, playbackService } from '../../musicPlayerServices';
import KeepAwake, { useKeepAwake,activateKeepAwake, deactivateKeepAwake } from '@sayem314/react-native-keep-awake';
Here, the necessary modules and hooks for the component are imported, including React Native components, icons, TrackPlayer for audio playback, BackgroundTimer for background timer, and KeepAwake for keeping the device awake.
FiveMinutesScreen
Function
The FiveMinutesScreen
function is the main component that renders the five-minute timer screen. It uses local states to control the timer state, minutes, seconds, etc. It also uses various React hooks such as useEffect
and useState
to handle the timer logic and audio playback.
Playback Control Events and Functions
The component uses the useTrackPlayerEvents
hook to handle playback track change events. It also defines functions to control the playback and pause of audio tracks.
Timer Logic
Inside the useEffect
hook, the timer logic is implemented using BackgroundTimer
to count time and update the timer state.
TenMinutesScreen.tsx
import React, { useEffect, useState } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import TrackPlayer, { State, usePlaybackState, Event, Track, useTrackPlayerEvents } from 'react-native-track-player';
import BackgroundTimer from 'react-native-background-timer';
import { setupPlayer, playbackService } from '../../musicPlayerServices';
import KeepAwake, { useKeepAwake,activateKeepAwake, deactivateKeepAwake } from '@sayem314/react-native-keep-awake';
const TenMinutesScreen = () => {
const [stopped, setStopped] = useState(true);
const [paused, setPaused] = useState(true);
const [minutes, setMinutes] = useState(10);
const [seconds, setSeconds] = useState(0);
const [temporizadorFinalizado, setTemporizadorFinalizado] = useState(false);
const [track, setTrack] = useState<Track | null>();
useTrackPlayerEvents([Event.PlaybackTrackChanged], async event => {
switch (event.type) {
case Event.PlaybackTrackChanged:
const playingTrack = await TrackPlayer.getTrack(event.nextTrack)
setTrack(playingTrack)
break;
}
});
const playbackState = usePlaybackState();
const play = async (playback: State) => {
const currentTrack = await TrackPlayer.getCurrentTrack()
if (currentTrack !== null) {
if (playback === State.Stopped || playback === State.Ready) {
await TrackPlayer.play()
}
}
}
const stop = async (playback: State) => {
const currentTrack = await TrackPlayer.getCurrentTrack()
if (currentTrack !== null) {
if (playback === State.Playing) {
await TrackPlayer.pause();
await TrackPlayer.seekTo(0);
}
}
}
const startTimer = async () => {
if (temporizadorFinalizado) {
setMinutes(10);
setSeconds(0);
}
setStopped(false);
setPaused(false);
setTemporizadorFinalizado(false);
};
const pauseTimer = async () => {
setPaused(true);
setTemporizadorFinalizado(false);
};
const stopTimer = async () => {
setStopped(true);
setPaused(false);
setMinutes(10);
setSeconds(0);
stop(playbackState);
setTemporizadorFinalizado(true);
};
const resetTimer = async () => {
setStopped(true);
setPaused(true);
setMinutes(10);
setSeconds(0);
};
useEffect(() => {
let interval: number;
if (!stopped && !paused) {
interval = BackgroundTimer.setInterval(() => {
if (seconds > 0) {
setSeconds(seconds - 1);
} else {
if (minutes === 0) {
BackgroundTimer.clearInterval(interval);
setStopped(true);
setTemporizadorFinalizado(true);
play(playbackState);
} else {
setMinutes(minutes - 1);
setSeconds(59);
}
}
}, 1000);
}
return () =>{
if(interval){
BackgroundTimer.clearInterval(interval);
}
};
}, [stopped, paused, minutes, seconds]);
return (
<View style={styles.container}>
<KeepAwake/>
<Text style={styles.timerText}>
{minutes<10 ? `0${minutes}`: minutes}:{seconds < 10 ? `0${seconds}` : seconds}
</Text>
<View style={styles.iconContainer}>
<Icon name={paused ? 'play-box' : 'pause-octagon'}
size={100}
color="#192A56"
onPress={paused ? startTimer : pauseTimer}
/>
<Icon
name={temporizadorFinalizado ? 'stop' : 'restore'}
size={100}
color="#192A56"
onPress={temporizadorFinalizado ? stopTimer : resetTimer}
/>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#EA425C'
},
timerText: {
fontSize: 100,
fontWeight: 'bold',
marginBottom: 10,
color: '#192A56'
},
iconContainer: {
flexDirection: 'row',
justifyContent: 'space-around',
marginTop: 20,
},
});
export default TenMinutesScreen;
TwentyFiveMinutesScreen.tsx
import React, { useEffect, useState } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import TrackPlayer, { State, usePlaybackState, Event, Track, useTrackPlayerEvents } from 'react-native-track-player';
import BackgroundTimer from 'react-native-background-timer';
import { setupPlayer, playbackService } from '../../musicPlayerServices';
import KeepAwake from '@sayem314/react-native-keep-awake';
const TwentyFiveMinutesScreen = () => {
const [stopped, setStopped] = useState(true);
const [paused, setPaused] = useState(true);
const [minutes, setMinutes] = useState(25);
const [seconds, setSeconds] = useState(0);
const [temporizadorFinalizado, setTemporizadorFinalizado] = useState(false);
const [track, setTrack] = useState<Track | null>();
useTrackPlayerEvents([Event.PlaybackTrackChanged], async event => {
switch (event.type) {
case Event.PlaybackTrackChanged:
const playingTrack = await TrackPlayer.getTrack(event.nextTrack)
setTrack(playingTrack)
break;
}
});
const playbackState = usePlaybackState();
const play = async (playback: State) => {
const currentTrack = await TrackPlayer.getCurrentTrack()
if (currentTrack !== null) {
if (playback === State.Stopped || playback === State.Ready) {
await TrackPlayer.play()
}
}
}
const stop = async (playback: State) => {
const currentTrack = await TrackPlayer.getCurrentTrack()
if (currentTrack !== null) {
if (playback === State.Playing) {
await TrackPlayer.pause();
await TrackPlayer.seekTo(0);
}
}
}
const startTimer = async () => {
if (temporizadorFinalizado) {
setMinutes(25);
setSeconds(0);
}
setStopped(false);
setPaused(false);
setTemporizadorFinalizado(false);
};
const pauseTimer = async () => {
setPaused(true);
setTemporizadorFinalizado(false);
};
const stopTimer = async () => {
setStopped(true);
setPaused(false);
setMinutes(25);
setSeconds(0);
stop(playbackState);
setTemporizadorFinalizado(true);
};
const resetTimer = async () => {
setStopped(true);
setPaused(true);
setMinutes(25);
setSeconds(0);
};
useEffect(() => {
let interval: number;
if (!stopped && !paused) {
interval = BackgroundTimer.setInterval(() => {
if (seconds > 0) {
setSeconds(seconds - 1);
} else {
if (minutes === 0) {
BackgroundTimer.clearInterval(interval);
setStopped(true);
setTemporizadorFinalizado(true);
play(playbackState);
} else {
setMinutes(minutes - 1);
setSeconds(59);
}
}
}, 1000);
}
return () =>{
if(interval){
BackgroundTimer.clearInterval(interval);
}
};
}, [stopped, paused, minutes, seconds]);
return (
<View style={styles.container}>
<KeepAwake/>
<Text style={styles.timerText}>
{minutes<10 ? `0${minutes}`: minutes}:{seconds < 10 ? `0${seconds}` : seconds}
</Text>
<View style={styles.iconContainer}>
<Icon name={paused ? 'play-box' : 'pause-octagon'}
size={100}
color="#192A56"
onPress={paused ? startTimer : pauseTimer}
/>
<Icon
name={temporizadorFinalizado ? 'stop' : 'restore'}
size={100}
color="#192A56"
onPress={temporizadorFinalizado ? stopTimer : resetTimer}
/>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#0ABDE3'
},
timerText: {
fontSize: 100,
fontWeight: 'bold',
marginBottom: 10,
color: '#192A56'
},
iconContainer: {
flexDirection: 'row',
justifyContent: 'space-around',
marginTop: 20,
},
});
export default TwentyFiveMinutesScreen;
App.tsx
import React, { useEffect, useState } from 'react';
import { ActivityIndicator, SafeAreaView, StatusBar, StyleSheet } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import { NavigationContainer } from '@react-navigation/native';
import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';
import FiveMinutesScreen from './components/FiveMinutesScreen';
import TenMinutesScreen from './components/TenMinutesScreen';
import TwentyFiveMinutesScreen from './components/TwentyFiveMinutesScreen';
import { setupPlayer, addTrack } from "../musicPlayerServices";
const Tab = createMaterialTopTabNavigator();
function App(): React.JSX.Element {
const [activeTab, setActiveTab] = useState('Short Break');
const [isPlayerReady, setIsPlayerReady] = useState(false);
useEffect(() => {
const initializePlayer = async () => {
const isSetup = await setupPlayer();
if (isSetup) {
await addTrack();
}
setIsPlayerReady(isSetup);
};
initializePlayer();
}, []);
if (!isPlayerReady) {
return (
<SafeAreaView>
<ActivityIndicator />
</SafeAreaView>
)
}
const getTabColor = (tabName: string) => {
switch (tabName) {
case 'Short Break':
return '#F0DF87';
case 'Pomodoro':
return '#0ABDE3';
case 'Long Break':
return '#EA425C';
default:
return 'powderblue';
}
};
return (
<NavigationContainer>
<StatusBar hidden />
<Tab.Navigator
screenOptions={{
tabBarLabelStyle: { fontSize: 12, fontWeight: 'bold', color: '#2C3335' },
tabBarStyle: { backgroundColor: 'powderblue' },
}}
>
<Tab.Screen
name="Short Break"
component={FiveMinutesScreen}
listeners={{
focus: () => setActiveTab('Short Break'),
}}
options={{
title: 'Short Break',
tabBarIcon: ({ focused }) => (
<Icon name={focused ? 'numeric-5-circle' : 'numeric-5-circle-outline'} size={25} color="#192A56" />
),
tabBarStyle: { backgroundColor: getTabColor('Short Break') },
}}
/>
<Tab.Screen
name="Pomodoro"
component={TwentyFiveMinutesScreen}
listeners={{
focus: () => setActiveTab('Pomodoro'),
}}
options={{
title: 'Pomodoro',
tabBarIcon: ({ focused }) => (
<Icon name={focused ? 'timer' : 'timer-outline'} size={25} color="#192A56" />
),
tabBarStyle: { backgroundColor: getTabColor('Pomodoro') },
}}
/>
<Tab.Screen
name="Long Break"
component={TenMinutesScreen}
listeners={{
focus: () => setActiveTab('Long Break'),
}}
options={{
title: 'Long Break',
tabBarIcon: ({ focused }) => (
<Icon name={focused ? 'numeric-10-circle' : 'numeric-10-circle-outline'} size={25} color="#192A56" />
),
tabBarStyle: { backgroundColor: getTabColor('Long Break') },
}}
/>
</Tab.Navigator>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
});
export default App;
El código proporcionado es una aplicación de React que utiliza el componente NavigationContainer
de @react-navigation/native
para crear una interfaz de pestañas con tres pantallas diferentes: FiveMinutesScreen
, TenMinutesScreen
y TwentyFiveMinutesScreen
. Aquí está el desglose paso a paso del código:
Importaciones
import React, { useEffect, useState } from 'react';
import { ActivityIndicator, SafeAreaView, StatusBar, StyleSheet } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import { NavigationContainer } from '@react-navigation/native';
import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';
import FiveMinutesScreen from './components/FiveMinutesScreen';
import TenMinutesScreen from './components/TenMinutesScreen';
import TwentyFiveMinutesScreen from './components/TwentyFiveMinutesScreen';
import { setupPlayer, addTrack } from "../musicPlayerServices";
Se importan los módulos y componentes necesarios para la aplicación, incluyendo componentes de React Native, iconos, NavigationContainer
y createMaterialTopTabNavigator
de @react-navigation/native
, así como las pantallas de temporizador.
Función App
La función App
es el componente principal que renderiza la aplicación. Utiliza el Tab.Navigator
para crear las pestañas y asignar las pantallas correspondientes a cada pestaña. También inicializa el reproductor de música y muestra un indicador de actividad mientras se carga.
Inicialización del Reproductor de Música
Dentro del efecto useEffect
, se inicializa el reproductor de música utilizando la función setupPlayer
y se agrega una pista utilizando la función addTrack
.
Lógica de las Pestañas
Cada pestaña tiene su propia pantalla correspondiente (FiveMinutesScreen
, TenMinutesScreen
, TwentyFiveMinutesScreen
) y se configura con un ícono y un color de fondo basado en la pestaña activa.
The provided code is a React application that uses the NavigationContainer
component from @react-navigation/native
to create a tabbed interface with three different screens: FiveMinutesScreen
, TenMinutesScreen
, and TwentyFiveMinutesScreen
. Here's the step-by-step breakdown of the code:
Imports
import React, { useEffect, useState } from 'react';
import { ActivityIndicator, SafeAreaView, StatusBar, StyleSheet } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import { NavigationContainer } from '@react-navigation/native';
import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';
import FiveMinutesScreen from './components/FiveMinutesScreen';
import TenMinutesScreen from './components/TenMinutesScreen';
import TwentyFiveMinutesScreen from './components/TwentyFiveMinutesScreen';
import { setupPlayer, addTrack } from "../musicPlayerServices";
The necessary modules and components for the application are imported, including React Native components, icons, NavigationContainer
, and createMaterialTopTabNavigator
from @react-navigation/native
, as well as the timer screens.
App
Function
The App
function is the main component that renders the application. It uses the Tab.Navigator
to create the tabs and assign the corresponding screens to each tab. It also initializes the music player and shows an activity indicator while loading.
Music Player Initialization
Inside the useEffect
effect, the music player is initialized using the setupPlayer
function and a track is added using the addTrack
function.
Tab Logic
Each tab has its own corresponding screen (FiveMinutesScreen
, TenMinutesScreen
, TwentyFiveMinutesScreen
) and is configured with an icon and background color based on the active tab.
Video & Github
Subscribe to my newsletter
Read articles from jorge alexander valencia valencia directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by