Draft on songplayer
This commit is contained in:
11
App.js
11
App.js
@@ -27,6 +27,7 @@ import { useSnapshot } from 'valtio';
|
||||
import GlobalState from './contexts/GlobalState.js';
|
||||
import NewGroup from './Views/NewGroup.js';
|
||||
import Slideshow from './Views/Slideshow.js';
|
||||
import SongPlayer from './Views/SongPlayer.js';
|
||||
|
||||
|
||||
const Tab = createBottomTabNavigator();
|
||||
@@ -267,7 +268,11 @@ export default function App() {
|
||||
props.navigation.goBack();
|
||||
}} /> : <Appbar.Action icon="menu" style={{ padding: 0, margin: 0 }} onPress={() => { props.navigation.navigate('Menu'); }} />}
|
||||
<Appbar.Content title="EMI Fellowship" titleStyle={{}} />
|
||||
<Appbar.Action icon="chat" onPress={() => { alert("Chats are comming soon.") }} />
|
||||
<Appbar.Action icon="chat" onPress={() => {
|
||||
alert("Chats are comming soon.");
|
||||
}} onLongPress={()=>{
|
||||
props.navigation.navigate("SongPlayer");
|
||||
}} />
|
||||
<Appbar.Action icon="search" onPress={() => { props.navigation.navigate("Search") }} />
|
||||
<Appbar.Action icon="notifications" onPress={() => { props.navigation.navigate("Notifications") }} />
|
||||
</Appbar.Header>
|
||||
@@ -314,6 +319,10 @@ export default function App() {
|
||||
name="Slideshow"
|
||||
component={Slideshow}
|
||||
/>
|
||||
<Stack.Screen
|
||||
name="SongPlayer"
|
||||
component={SongPlayer}
|
||||
/>
|
||||
<Stack.Screen name="SinglePost" component={SinglePost} />
|
||||
<Stack.Screen name="Login" component={Login} options={{ headerShown: false }} />
|
||||
<Tab.Screen name="Logout" component={Login} />
|
||||
|
||||
184
Views/SongPlayer.js
Normal file
184
Views/SongPlayer.js
Normal file
@@ -0,0 +1,184 @@
|
||||
import React from 'react';
|
||||
import { StyleSheet, TouchableHighlight, Text, Animated, View } from 'react-native';
|
||||
|
||||
|
||||
let songExample = {
|
||||
lyrics: [
|
||||
'Our [C ..]God is an awe[G ..]some God',
|
||||
'He rei[D ..]gns from [Em ..]heaven above',
|
||||
'With wis[C ..]dom, pow[G .]er and lo[Em .]ve',
|
||||
'Our [Am .]God is an aweso[D .]me [Em ..]God!'
|
||||
],
|
||||
title: 'Our God',
|
||||
key: 'C',
|
||||
tempo: 60,
|
||||
beatsPerTempo: 4,
|
||||
};
|
||||
|
||||
|
||||
let SongPlayer = (props) => {
|
||||
[song, setSong] = React.useState(songExample);
|
||||
[currentChord, setCurrentCord] = React.useState(0);
|
||||
[currentBeat, setCurrentBeat] = React.useState(0);
|
||||
[currentBeatGlobal, setCurrentBeatGlobal] = React.useState(0);
|
||||
const fadeAnim = React.useRef(new Animated.Value(1)).current;
|
||||
|
||||
let lyrics = song.lyrics;
|
||||
let chords = [];
|
||||
const replaceTextInBrackets = (str) => {
|
||||
const regex = /(\[(.*?)\])/g;
|
||||
const matches = str.match(regex);
|
||||
if (!matches) {
|
||||
return str;
|
||||
}
|
||||
let p = str.split(/(\[.*?\])/g).map((item, index) => {
|
||||
//console.log(item, index)
|
||||
if (item.match(/\[|\]/g)) {
|
||||
const dots = item.match(/\./g);
|
||||
const beats = dots ? dots.length : 0
|
||||
const content = item.replace(/\[|\]|\./g, '');
|
||||
chords.push([content, beats]);
|
||||
const key = chords.length - 1;
|
||||
return <View style={styles.chordView} key={"chord_" + key}>
|
||||
<Text style={currentChord !== key ? styles.chord : styles.currentChord}>
|
||||
{content}
|
||||
</Text>
|
||||
</View>;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
|
||||
return (
|
||||
<View>
|
||||
<Text style={styles.line}>
|
||||
{p}
|
||||
</Text>
|
||||
</View>
|
||||
)
|
||||
};
|
||||
const processedString = lyrics.map(replaceTextInBrackets);
|
||||
//console.log(processedString, chords);
|
||||
React.useEffect(() => {
|
||||
let timer = setInterval(() => {
|
||||
fadeIn();
|
||||
beatsInChord = chords[currentChord][1];
|
||||
//console.log(chords[currentChord])
|
||||
if (currentBeat >= beatsInChord - 1) {
|
||||
setCurrentCord((currentChord + 1) % chords.length);
|
||||
setCurrentBeat(0);
|
||||
} else {
|
||||
setCurrentBeat(currentBeat + 1);
|
||||
}
|
||||
setCurrentBeatGlobal(currentBeatGlobal + 1);
|
||||
//fadeOut();
|
||||
setTimeout(fadeOut, 50);
|
||||
}, (60 / song.tempo) * 1000);
|
||||
return () => {
|
||||
clearInterval(timer);
|
||||
}
|
||||
});
|
||||
|
||||
const fadeIn = () => {
|
||||
// Will change fadeAnim value to 1 in 5 seconds
|
||||
Animated.timing(fadeAnim, {
|
||||
toValue: 1,
|
||||
duration: 50,
|
||||
useNativeDriver: true,
|
||||
}).start();
|
||||
};
|
||||
|
||||
const fadeOut = () => {
|
||||
// Will change fadeAnim value to 0 in 3 seconds
|
||||
Animated.timing(fadeAnim, {
|
||||
toValue: 0.9,
|
||||
duration: 270,
|
||||
useNativeDriver: true,
|
||||
}).start();
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={styles.view}>
|
||||
<Text style={{
|
||||
fontSize: 20,
|
||||
position: "absolute",
|
||||
padding: 20
|
||||
}}>
|
||||
Beat: {(currentBeatGlobal) % 4 + 1}
|
||||
</Text>
|
||||
<View style={{
|
||||
height: 100,
|
||||
}}>
|
||||
{
|
||||
currentChord > 0 ?
|
||||
<View style={{
|
||||
transform: [{ translateX: 40 }, { translateY: 20 }],
|
||||
position: "absolute",
|
||||
width: 60,
|
||||
height: 20,
|
||||
}}><Text style={{
|
||||
fontSize: 20,
|
||||
opacity: 0.6
|
||||
}}>
|
||||
{chords[currentChord - 1][0]} {".".repeat(chords[currentChord - 1][1])}
|
||||
</Text></View> : <></>
|
||||
}
|
||||
<Animated.Text style={{
|
||||
fontSize: 50,
|
||||
textAlign: "center",
|
||||
//opacity: fadeAnim,
|
||||
transform: [{ scale: fadeAnim }],
|
||||
}}>
|
||||
{chords[currentChord][0]} {".".repeat(chords[currentChord][1])}
|
||||
{
|
||||
chords[currentChord + 1] ?
|
||||
<View style={{
|
||||
transform: [{ translateX: 50 }, { translateY: -35 }],
|
||||
position: "absolute",
|
||||
width: 40,
|
||||
height: 20,
|
||||
}}><Text style={{
|
||||
fontSize: 20,
|
||||
opacity: 0.6
|
||||
}}>
|
||||
{chords[currentChord + 1][0]}
|
||||
</Text></View> : <></>
|
||||
}
|
||||
</Animated.Text>
|
||||
</View>
|
||||
{processedString}
|
||||
</View>
|
||||
)
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
chordView: {
|
||||
position: 'absolute',
|
||||
},
|
||||
chord: {
|
||||
opacity: 0.5,
|
||||
color: "red",
|
||||
position: "absolute",
|
||||
top: -35
|
||||
},
|
||||
currentChord: {
|
||||
opacity: 0.5,
|
||||
color: "green",
|
||||
position: "absolute",
|
||||
top: -40,
|
||||
transform: [{ scale: 1.5 }]
|
||||
},
|
||||
view: {
|
||||
padding: 15,
|
||||
paddingTop: 40,
|
||||
},
|
||||
line: {
|
||||
height: 60,
|
||||
fontSize: 20,
|
||||
textAlign: "center"
|
||||
},
|
||||
chordViewer: {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
export default SongPlayer;
|
||||
1952
package-lock.json
generated
1952
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-native-async-storage/async-storage": "~1.17.3",
|
||||
"@react-native-community/netinfo": "9.3.5",
|
||||
"@react-navigation/bottom-tabs": "^6.2.0",
|
||||
"@react-navigation/native": "^6.0.8",
|
||||
"@react-navigation/native-stack": "^6.5.0",
|
||||
@@ -20,6 +21,7 @@
|
||||
"expo-dev-client": "~2.0.1",
|
||||
"expo-device": "~5.0.0",
|
||||
"expo-image-picker": "~14.0.2",
|
||||
"expo-linking": "~3.3.1",
|
||||
"expo-localization": "~14.0.0",
|
||||
"expo-notifications": "~0.17.0",
|
||||
"expo-status-bar": "~1.4.2",
|
||||
@@ -28,7 +30,7 @@
|
||||
"moment": "^2.29.1",
|
||||
"react": "18.1.0",
|
||||
"react-dom": "18.1.0",
|
||||
"react-native": "0.70.5",
|
||||
"react-native": "0.70.8",
|
||||
"react-native-autoheight-webview": "^1.6.1",
|
||||
"react-native-hyperlink": "0.0.19",
|
||||
"react-native-paper": "^4.11.2",
|
||||
@@ -37,9 +39,7 @@
|
||||
"react-native-vector-icons": "^9.1.0",
|
||||
"react-native-web": "~0.18.7",
|
||||
"react-native-webview": "11.23.1",
|
||||
"valtio": "^1.4.0",
|
||||
"@react-native-community/netinfo": "9.3.5",
|
||||
"expo-linking": "~3.3.1"
|
||||
"valtio": "^1.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.19.3"
|
||||
|
||||
Reference in New Issue
Block a user