Skip to content

Commit

Permalink
[#24] Add seek bar (#34)
Browse files Browse the repository at this point in the history
Adding interactive seekbar
  • Loading branch information
tekrei authored Nov 14, 2021
1 parent 87878dc commit d0d3861
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 71 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"@fortawesome/free-regular-svg-icons": "^5.15",
"@fortawesome/free-solid-svg-icons": "^5.15",
"@fortawesome/react-native-fontawesome": "^0.2",
"@react-native-community/slider": "4.1.7",
"@react-navigation/drawer": "^6.1",
"@react-navigation/native": "^6.0",
"expo": "^43",
Expand All @@ -42,7 +43,6 @@
"react-native-elements": "^3.4",
"react-native-gesture-handler": "~1.10.2",
"react-native-get-random-values": "~1.7.0",
"react-native-progress": "^5.0",
"react-native-reanimated": "~2.2.0",
"react-native-root-toast": "^3.3.0",
"react-native-safe-area-context": "3.3.2",
Expand Down
49 changes: 49 additions & 0 deletions src/components/controls.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React from "react";
import { View } from "react-native";
import {
faPause,
faPlay,
faReply,
faSort,
faStepBackward,
faStepForward,
faStop,
faTrash,
} from "@fortawesome/free-solid-svg-icons";
import { styles, BLUE, GRAY } from "../helpers/styles";
import { IconPress } from "./buttons";

const PlayerControls = ({
isPlaying,
isLooping,
previousTrack,
playPause,
stopPlayer,
nextTrack,
clearPlaylist,
sortPlaylist,
toggleLoop,
}) => (
<View style={styles.playlistButtons}>
<IconPress icon={faStepBackward} onPress={() => previousTrack()} />
<IconPress
icon={isPlaying ? faPause : faPlay}
onPress={() => playPause()}
/>
<IconPress
icon={faStop}
color={isPlaying ? BLUE : GRAY}
onPress={() => stopPlayer()}
/>
<IconPress icon={faStepForward} onPress={() => nextTrack()} />
<IconPress
icon={faReply}
color={isLooping ? BLUE : GRAY}
onPress={() => toggleLoop()}
/>
<IconPress icon={faSort} onPress={() => sortPlaylist()} />
<IconPress icon={faTrash} onPress={() => clearPlaylist()} />
</View>
);

export default PlayerControls;
76 changes: 28 additions & 48 deletions src/components/player.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,9 @@
import React, { useEffect, useState } from "react";
import { Text, View } from "react-native";
import { View } from "react-native";
import { Audio } from "expo-av";
import {
faPause,
faPlay,
faReply,
faSort,
faStepBackward,
faStepForward,
faStop,
faTrash,
} from "@fortawesome/free-solid-svg-icons";
import * as Progress from "react-native-progress";
import { styles, BLUE, GRAY } from "../helpers/styles";
import { IconPress } from "./buttons";
import { styles } from "../helpers/styles";
import PlayerControls from "./controls";
import SeekBar from "./seekbar";

const Player = ({
song,
Expand Down Expand Up @@ -52,6 +42,11 @@ const Player = ({
}
};

const onSeek = async (positionMillis) => {
const result = await player.getStatusAsync();
result.isLoaded && player.setPositionAsync(positionMillis);
};

const playPause = async () => {
const result = await player.getStatusAsync();
if (result.isLoaded) {
Expand Down Expand Up @@ -97,42 +92,27 @@ const Player = ({
}
};

const PlayerButtons = () => (
<View style={styles.playlistButtons}>
<IconPress icon={faStepBackward} onPress={() => previousTrack()} />
<IconPress
icon={status.isPlaying ? faPause : faPlay}
onPress={() => playPause()}
/>
<IconPress
icon={faStop}
color={status.isPlaying ? BLUE : GRAY}
onPress={() => stopPlayer()}
/>
<IconPress icon={faStepForward} onPress={() => nextTrack()} />
<IconPress
icon={faReply}
color={status.isLooping ? BLUE : GRAY}
onPress={() => toggleLoop()}
/>
<IconPress icon={faSort} onPress={() => sortPlaylist()} />
<IconPress icon={faTrash} onPress={() => clearPlaylist()} />
</View>
);

return (
<View style={styles.bottomView}>
{song && <Text style={styles.albumTitle}>{song.name}</Text>}
{status.positionMillis > 0 && (
<Progress.Bar
style={{ width: "100%" }}
color={BLUE}
width={null}
height={32}
progress={status.positionMillis / status.durationMillis}
/>
)}
<PlayerButtons />
<SeekBar
isPlaying={status.isLoaded}
onSeek={onSeek}
trackLength={status.positionMillis ? status.durationMillis : 1}
currentPosition={status.positionMillis ? status.positionMillis : 0}
/>
<PlayerControls
isPlaying={status.isPlaying}
isLooping={status.isLooping}
{...{
previousTrack,
playPause,
stopPlayer,
nextTrack,
clearPlaylist,
sortPlaylist,
toggleLoop,
}}
/>
</View>
);
};
Expand Down
44 changes: 44 additions & 0 deletions src/components/seekbar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from "react";

import { View, Text } from "react-native";
import Slider from "@react-native-community/slider";
import { styles, BLUE, GRAY } from "../helpers/styles";

function pad(n, width, z = 0) {
n = n + "";
return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
}

const minutesAndSeconds = (position) => [
Math.floor(position / 60000, 0),
pad(Math.floor((position / 1000) % 60, 2), 2),
];

const SeekBar = ({ isPlaying, trackLength, currentPosition, onSeek, onSlidingStart }) => {
const elapsed = minutesAndSeconds(currentPosition);
const remaining = minutesAndSeconds(trackLength - currentPosition);
return (
<View style={styles.deviceWidth}>
<View style={{ flexDirection: "row" }}>
<Text style={styles.text}>{elapsed[0] + ":" + elapsed[1]}</Text>
<View style={{ flex: 1 }} />
<Text style={styles.text}>
{trackLength > 1 && "-" + remaining[0] + ":" + remaining[1]}
</Text>
</View>
<Slider
style={styles.slider}
disabled={!isPlaying}
maximumValue={Math.max(trackLength, 1, currentPosition + 1)}
onSlidingStart={onSlidingStart}
onSlidingComplete={onSeek}
value={currentPosition}
minimumTrackTintColor={BLUE}
maximumTrackTintColor={GRAY}
thumbTintColor={isPlaying ? BLUE : GRAY}
/>
</View>
);
};

export default SeekBar;
2 changes: 1 addition & 1 deletion src/components/tabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const AnimatedTabView = ({ value, children }) => (
export const TabViewItem = ({ selected, children }) =>
selected && (
<TabView.Item
style={styles.tabViewItem}
style={styles.deviceWidth}
//Fix from: https://github.com/react-native-elements/react-native-elements/issues/3091#issuecomment-866226005
onMoveShouldSetResponder={(e) => e.stopPropagation()}
>
Expand Down
13 changes: 10 additions & 3 deletions src/helpers/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ export const songText = (selected) => {
};

export const styles = StyleSheet.create({
text: {
color: BLUE,
textAlign: "center"
},
slider: {
marginTop: 0,
height: 50
},
albumTitle: {
color: BLUE,
fontSize: 32,
Expand All @@ -65,7 +73,7 @@ export const styles = StyleSheet.create({
menuLabel: {
color: BLUE,
fontSize: 16,
padding:0
padding: 0,
},
webview: {
width: deviceWidth,
Expand Down Expand Up @@ -94,7 +102,7 @@ export const styles = StyleSheet.create({
backgroundColor: WHITE,
borderRadius: 10,
},
tabViewItem: {
deviceWidth: {
width: deviceWidth,
},
topView: {
Expand Down Expand Up @@ -160,7 +168,6 @@ export const styles = StyleSheet.create({
},
button: {
alignItems: "center",
//justifyContent: "center",
height: 50,
flexDirection: "row",
},
Expand Down
14 changes: 3 additions & 11 deletions src/screens/playlist.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,16 @@ export const Playlist = ({ navigation }) => {

const songs = getSongs();

const addSong = (no) => {
setPlaylist([...playlist, no]);
};

const removeSong = (no) => {
setPlaylist(playlist.filter((o) => o !== no));
};

const openUrl = (url) => {
navigation.navigate("Page", { url });
};

const toggleSong = ({ name, no }) => {
if (playlist.find((n) => n === no)) {
removeSong(no);
setPlaylist(playlist.filter((o) => o !== no));
Toast.show(`${name} listeden kaldırıldı`);
} else {
addSong(no);
setPlaylist([...playlist, no]);
Toast.show(`${name} listeye eklendi`);
}
};
Expand Down Expand Up @@ -74,7 +66,7 @@ export const Playlist = ({ navigation }) => {
};

const nextTrack = () => {
setCurrentIndex(currentIndex < playlist.length - 1 ? currentIndex + 1 : 0);
setCurrentIndex(currentIndex + 1 < playlist.length ? currentIndex + 1 : 0);
};

return (
Expand Down
19 changes: 12 additions & 7 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2189,6 +2189,13 @@
sudo-prompt "^9.0.0"
wcwidth "^1.0.1"

"@react-native-community/slider@4.1.7":
version "4.1.7"
resolved "https://registry.yarnpkg.com/@react-native-community/slider/-/slider-4.1.7.tgz#b2c4e9547dcdcbcf3d0a0cda8545abcfdc089859"
integrity sha512-zVcxi3chX/Je/3lo8jI/83VpY6DL2h+JWNV8sg6rkxjRTau/8DfM/e98RymH0ujejBkuYX342IKNnxOHRK6KbQ==
dependencies:
flow-bin "0.113.0"

"@react-native/assets@1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@react-native/assets/-/assets-1.0.0.tgz#c6f9bf63d274bafc8e970628de24986b30a55c8e"
Expand Down Expand Up @@ -6075,6 +6082,11 @@ find-yarn-workspace-root@~2.0.0:
dependencies:
micromatch "^4.0.2"

flow-bin@0.113.0:
version "0.113.0"
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.113.0.tgz#6457d250dbc6f71ca51e75f00a96d23cde5d987a"
integrity sha512-76uE2LGNe50wm+Jup8Np4FBcMbyy5V2iE+K25PPIYLaEMGHrL1jnQfP9L0hTzA5oh2ZJlexRLMlaPqIYIKH9nw==

flow-parser@0.*:
version "0.164.0"
resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.164.0.tgz#455e16fdba12f24aa1d7631adacc524f1977b6ad"
Expand Down Expand Up @@ -10928,13 +10940,6 @@ react-native-get-random-values@~1.7.0:
dependencies:
fast-base64-decode "^1.0.0"

react-native-progress@^5.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/react-native-progress/-/react-native-progress-5.0.0.tgz#f5ac6ceaeee27f184c660b00f29419e82a9d0ab0"
integrity sha512-KjnGIt3r9i5Kn2biOD9fXLJocf0bwxPRxOyAgXEnZTJQU2O+HyzgGFRCbM5h3izm9kKIkSc1txh8aGmMafCD9A==
dependencies:
prop-types "^15.7.2"

react-native-ratings@8.0.4:
version "8.0.4"
resolved "https://registry.yarnpkg.com/react-native-ratings/-/react-native-ratings-8.0.4.tgz#efd5ebad8acc08bf98d34d39b18fb7a6813ef991"
Expand Down

0 comments on commit d0d3861

Please sign in to comment.