diff --git a/src/assets/repeat.svg b/src/assets/repeat.svg new file mode 100644 index 0000000..db3c5b8 --- /dev/null +++ b/src/assets/repeat.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/shuffle.svg b/src/assets/shuffle.svg new file mode 100644 index 0000000..35990e0 --- /dev/null +++ b/src/assets/shuffle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/Typography.ts b/src/components/Typography.ts index 288f206..4ad000f 100644 --- a/src/components/Typography.ts +++ b/src/components/Typography.ts @@ -4,4 +4,9 @@ export const Header = styled.Text` margin: 24px 0 12px 0; font-size: 36px; font-weight: bold; +`; + +export const SubHeader = styled.Text` + font-size: 24px; + margin: 12px 0; `; \ No newline at end of file diff --git a/src/screens/Player/components/MediaControls.tsx b/src/screens/Player/components/MediaControls.tsx index c83165f..f75b240 100644 --- a/src/screens/Player/components/MediaControls.tsx +++ b/src/screens/Player/components/MediaControls.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState, useCallback, useEffect, useRef } from 'react'; import TrackPlayer, { usePlaybackState, STATE_PLAYING, STATE_PAUSED } from 'react-native-track-player'; import { TouchableOpacity } from 'react-native'; import styled from 'styled-components/native'; @@ -7,9 +7,13 @@ import ForwardIcon from 'assets/forwards.svg'; import BackwardIcon from 'assets/backwards.svg'; import PlayIcon from 'assets/play.svg'; import PauseIcon from 'assets/pause.svg'; +import RepeatIcon from 'assets/repeat.svg'; +// import ShuffleIcon from 'assets/shuffle.svg'; import { useColorScheme } from 'react-native-appearance'; +import { THEME_COLOR } from 'CONSTANTS'; const BUTTON_SIZE = 40; +const BUTTON_SIZE_SMALL = 25; const pause = () => TrackPlayer.pause(); const play = () => TrackPlayer.play(); @@ -47,6 +51,14 @@ export default function MediaControls() { + + + + ); } @@ -71,6 +83,67 @@ export function NextButton({ fill }: { fill: string }) { ); } +export function RepeatButton({ fill }: { fill: string}) { + const [isRepeating, setRepeating] = useState(false); + const handlePress = useCallback(() => setRepeating(!isRepeating), [isRepeating, setRepeating]); + const listener = useRef(null); + + // The callback that should determine whether we need to repeeat or not + const handleEndEvent = useCallback(async () => { + if (isRepeating) { + // Retrieve all current tracks + const tracks = await TrackPlayer.getQueue(); + + // Then skip to the first track + await TrackPlayer.skip(tracks[0].id); + + // Cautiously reset the seek time, as there might only be a single + // item in queue. + await TrackPlayer.seekTo(0); + + // Then play the item + await TrackPlayer.play(); + } + }, [isRepeating]); + + // Subscribe to ended event handler so that we can restart the queue from + // the start if looping is enabled + useEffect(() => { + // Set the event listener + listener.current = TrackPlayer.addEventListener('playback-queue-ended', handleEndEvent); + + // Then clean up after + return function cleanup() { + listener?.current?.remove(); + }; + }, [handleEndEvent]); + + return ( + + + + ); +} + +// export function ShuffleButton({ fill }: { fill: string}) { +// const [isShuffling, setShuffling] = useState(false); +// const handlePress = useCallback(() => setShuffling(!isShuffling), [isShuffling, setShuffling]); + +// return ( +// +// +// +// ); +// } + export function MainButton({ fill }: { fill: string }) { const state = usePlaybackState();