added seeking to now playing/notification

This commit is contained in:
austinried 2021-08-10 15:27:20 +09:00
parent 9705a95aaa
commit 2d2efe3dcf
7 changed files with 78 additions and 20 deletions

View File

@ -21,8 +21,8 @@ const ProgressBar = () => {
return (
<View style={progressStyles.container}>
<View style={{ ...progressStyles.left, flex: progress }} />
<View style={{ ...progressStyles.right, flex: 1 - progress }} />
<View style={[progressStyles.left, { flex: progress }]} />
<View style={[progressStyles.right, { flex: 1 - progress }]} />
</View>
)
}
@ -52,8 +52,6 @@ const NowPlayingBar = () => {
switch (playerState) {
case State.Playing:
case State.Buffering:
case State.Connecting:
playPauseIcon = 'pause'
playPauseAction = pause
break

View File

@ -60,6 +60,13 @@ export const useSkipTo = () => {
})
}
export const useSeekTo = () => {
return (position: number) =>
trackPlayerCommands.enqueue(async () => {
await TrackPlayer.seekTo(position)
})
}
export const useToggleRepeat = () => {
const setRepeatMode = useStore(selectTrackPlayer.setRepeatMode)

View File

@ -82,6 +82,12 @@ const createService = async () => {
TrackPlayer.addEventListener(Event.PlaybackMetadataReceived, () => {
setCurrentTrackIdx(useStore.getState().currentTrackIdx)
})
TrackPlayer.addEventListener(Event.RemoteSeek, data => {
trackPlayerCommands.enqueue(async () => {
await TrackPlayer.seekTo(data.position)
})
})
}
module.exports = async function () {

View File

@ -3,7 +3,15 @@ import ImageGradientBackground from '@app/components/ImageGradientBackground'
import PressableOpacity from '@app/components/PressableOpacity'
import Star from '@app/components/Star'
import { useStarred } from '@app/hooks/music'
import { useNext, usePause, usePlay, usePrevious, useToggleRepeat, useToggleShuffle } from '@app/hooks/trackplayer'
import {
useNext,
usePause,
usePlay,
usePrevious,
useSeekTo,
useToggleRepeat,
useToggleShuffle,
} from '@app/hooks/trackplayer'
import { selectMusic } from '@app/state/music'
import { useStore } from '@app/state/store'
import { QueueContextType, selectTrackPlayer } from '@app/state/trackplayer'
@ -12,7 +20,7 @@ import dimensions from '@app/styles/dimensions'
import font from '@app/styles/font'
import formatDuration from '@app/util/formatDuration'
import { useNavigation } from '@react-navigation/native'
import React, { useCallback, useEffect } from 'react'
import React, { useCallback, useEffect, useState } from 'react'
import { StatusBar, StyleSheet, Text, View } from 'react-native'
import { NativeStackScreenProps } from 'react-native-screens/native-stack'
import { RepeatMode, State } from 'react-native-track-player'
@ -21,6 +29,7 @@ import IconFA5 from 'react-native-vector-icons/FontAwesome5'
import Icon from 'react-native-vector-icons/Ionicons'
import IconMatCom from 'react-native-vector-icons/MaterialCommunityIcons'
import IconMat from 'react-native-vector-icons/MaterialIcons'
import Slider from '@react-native-community/slider'
function getContextName(type?: QueueContextType) {
switch (type) {
@ -131,7 +140,8 @@ const coverArtStyles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
paddingBottom: 20,
paddingBottom: 10,
paddingHorizontal: 10,
},
image: {
height: '100%',
@ -169,6 +179,7 @@ const infoStyles = StyleSheet.create({
container: {
width: '100%',
flexDirection: 'row',
paddingHorizontal: 10,
},
details: {
flex: 1,
@ -193,21 +204,46 @@ const infoStyles = StyleSheet.create({
const SeekBar = () => {
const { position, duration } = useStore(selectTrackPlayer.progress)
const seekTo = useSeekTo()
const [value, setValue] = useState(0)
const [sliding, setSliding] = useState(false)
let progress = 0
if (duration > 0) {
progress = position / duration
useEffect(() => {
if (sliding) {
return
}
setValue(position)
}, [position, sliding])
const onSlidingStart = useCallback(() => {
setSliding(true)
}, [])
const onSlidingComplete = useCallback(
async (val: number) => {
await seekTo(val)
setSliding(false)
},
[seekTo],
)
return (
<View style={seekStyles.container}>
<View style={seekStyles.barContainer}>
<View style={{ ...seekStyles.bars, ...seekStyles.barLeft, flex: progress }} />
<View style={{ ...seekStyles.indicator }} />
<View style={{ ...seekStyles.bars, ...seekStyles.barRight, flex: 1 - progress }} />
<Slider
style={seekStyles.slider}
minimumTrackTintColor="white"
maximumTrackTintColor={colors.text.secondary}
thumbTintColor="white"
maximumValue={duration}
value={value}
onSlidingStart={onSlidingStart}
onSlidingComplete={onSlidingComplete}
/>
</View>
<View style={seekStyles.textContainer}>
<Text style={seekStyles.text}>{formatDuration(position)}</Text>
<Text style={seekStyles.text}>{formatDuration(value)}</Text>
<Text style={seekStyles.text}>{formatDuration(duration)}</Text>
</View>
</View>
@ -217,17 +253,21 @@ const SeekBar = () => {
const seekStyles = StyleSheet.create({
container: {
width: '100%',
marginTop: 26,
marginTop: 16,
},
barContainer: {
flexDirection: 'row',
alignItems: 'center',
marginBottom: 6,
marginBottom: 0,
},
bars: {
backgroundColor: colors.text.primary,
height: 4,
},
slider: {
flex: 1,
height: 40,
},
barLeft: {
marginRight: -6,
},
@ -245,6 +285,7 @@ const seekStyles = StyleSheet.create({
textContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
paddingHorizontal: 10,
},
text: {
fontFamily: font.regular,
@ -271,8 +312,6 @@ const PlayerControls = () => {
switch (state) {
case State.Playing:
case State.Buffering:
case State.Connecting:
disabled = false
playPauseIcon = 'pause-circle'
playPauseAction = pause
@ -327,6 +366,7 @@ const PlayerControls = () => {
const controlsStyles = StyleSheet.create({
container: {
width: '100%',
paddingHorizontal: 10,
},
top: {
flexDirection: 'row',
@ -395,7 +435,7 @@ const styles = StyleSheet.create({
},
content: {
flex: 1,
paddingHorizontal: 30,
paddingHorizontal: 20,
},
})

View File

@ -24,6 +24,7 @@ async function start() {
Capability.Stop,
Capability.SkipToNext,
Capability.SkipToPrevious,
Capability.SeekTo,
],
compactCapabilities: [
Capability.Play, //

View File

@ -13,6 +13,7 @@
"@react-native-async-storage/async-storage": "^1.15.5",
"@react-native-community/hooks": "^2.6.0",
"@react-native-community/masked-view": "^0.1.11",
"@react-native-community/slider": "^3.0.3",
"@react-navigation/bottom-tabs": "^5.11.11",
"@react-navigation/material-top-tabs": "^5.3.15",
"@react-navigation/native": "^5.9.4",

View File

@ -1118,6 +1118,11 @@
resolved "https://registry.yarnpkg.com/@react-native-community/masked-view/-/masked-view-0.1.11.tgz#2f4c6e10bee0786abff4604e39a37ded6f3980ce"
integrity sha512-rQfMIGSR/1r/SyN87+VD8xHHzDYeHaJq6elOSCAD+0iLagXkSI2pfA0LmSXP21uw5i3em7GkkRjfJ8wpqWXZNw==
"@react-native-community/slider@^3.0.3":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@react-native-community/slider/-/slider-3.0.3.tgz#830167fd757ba70ac638747ba3169b2dbae60330"
integrity sha512-8IeHfDwJ9/CTUwFs6x90VlobV3BfuPgNLjTgC6dRZovfCWigaZwVNIFFJnHBakK3pW2xErAPwhdvNR4JeNoYbw==
"@react-native/assets@1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@react-native/assets/-/assets-1.0.0.tgz#c6f9bf63d274bafc8e970628de24986b30a55c8e"