Draft on songplayer
This commit is contained in:
13
App.js
13
App.js
@@ -27,6 +27,7 @@ import { useSnapshot } from 'valtio';
|
|||||||
import GlobalState from './contexts/GlobalState.js';
|
import GlobalState from './contexts/GlobalState.js';
|
||||||
import NewGroup from './Views/NewGroup.js';
|
import NewGroup from './Views/NewGroup.js';
|
||||||
import Slideshow from './Views/Slideshow.js';
|
import Slideshow from './Views/Slideshow.js';
|
||||||
|
import SongPlayer from './Views/SongPlayer.js';
|
||||||
|
|
||||||
|
|
||||||
const Tab = createBottomTabNavigator();
|
const Tab = createBottomTabNavigator();
|
||||||
@@ -267,7 +268,11 @@ export default function App() {
|
|||||||
props.navigation.goBack();
|
props.navigation.goBack();
|
||||||
}} /> : <Appbar.Action icon="menu" style={{ padding: 0, margin: 0 }} onPress={() => { props.navigation.navigate('Menu'); }} />}
|
}} /> : <Appbar.Action icon="menu" style={{ padding: 0, margin: 0 }} onPress={() => { props.navigation.navigate('Menu'); }} />}
|
||||||
<Appbar.Content title="EMI Fellowship" titleStyle={{}} />
|
<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="search" onPress={() => { props.navigation.navigate("Search") }} />
|
||||||
<Appbar.Action icon="notifications" onPress={() => { props.navigation.navigate("Notifications") }} />
|
<Appbar.Action icon="notifications" onPress={() => { props.navigation.navigate("Notifications") }} />
|
||||||
</Appbar.Header>
|
</Appbar.Header>
|
||||||
@@ -310,10 +315,14 @@ export default function App() {
|
|||||||
name="Notifications"
|
name="Notifications"
|
||||||
component={NotificationsView}
|
component={NotificationsView}
|
||||||
/>
|
/>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name="Slideshow"
|
name="Slideshow"
|
||||||
component={Slideshow}
|
component={Slideshow}
|
||||||
/>
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="SongPlayer"
|
||||||
|
component={SongPlayer}
|
||||||
|
/>
|
||||||
<Stack.Screen name="SinglePost" component={SinglePost} />
|
<Stack.Screen name="SinglePost" component={SinglePost} />
|
||||||
<Stack.Screen name="Login" component={Login} options={{ headerShown: false }} />
|
<Stack.Screen name="Login" component={Login} options={{ headerShown: false }} />
|
||||||
<Tab.Screen name="Logout" component={Login} />
|
<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": {
|
"dependencies": {
|
||||||
"@react-native-async-storage/async-storage": "~1.17.3",
|
"@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/bottom-tabs": "^6.2.0",
|
||||||
"@react-navigation/native": "^6.0.8",
|
"@react-navigation/native": "^6.0.8",
|
||||||
"@react-navigation/native-stack": "^6.5.0",
|
"@react-navigation/native-stack": "^6.5.0",
|
||||||
@@ -20,6 +21,7 @@
|
|||||||
"expo-dev-client": "~2.0.1",
|
"expo-dev-client": "~2.0.1",
|
||||||
"expo-device": "~5.0.0",
|
"expo-device": "~5.0.0",
|
||||||
"expo-image-picker": "~14.0.2",
|
"expo-image-picker": "~14.0.2",
|
||||||
|
"expo-linking": "~3.3.1",
|
||||||
"expo-localization": "~14.0.0",
|
"expo-localization": "~14.0.0",
|
||||||
"expo-notifications": "~0.17.0",
|
"expo-notifications": "~0.17.0",
|
||||||
"expo-status-bar": "~1.4.2",
|
"expo-status-bar": "~1.4.2",
|
||||||
@@ -28,7 +30,7 @@
|
|||||||
"moment": "^2.29.1",
|
"moment": "^2.29.1",
|
||||||
"react": "18.1.0",
|
"react": "18.1.0",
|
||||||
"react-dom": "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-autoheight-webview": "^1.6.1",
|
||||||
"react-native-hyperlink": "0.0.19",
|
"react-native-hyperlink": "0.0.19",
|
||||||
"react-native-paper": "^4.11.2",
|
"react-native-paper": "^4.11.2",
|
||||||
@@ -37,9 +39,7 @@
|
|||||||
"react-native-vector-icons": "^9.1.0",
|
"react-native-vector-icons": "^9.1.0",
|
||||||
"react-native-web": "~0.18.7",
|
"react-native-web": "~0.18.7",
|
||||||
"react-native-webview": "11.23.1",
|
"react-native-webview": "11.23.1",
|
||||||
"valtio": "^1.4.0",
|
"valtio": "^1.4.0"
|
||||||
"@react-native-community/netinfo": "9.3.5",
|
|
||||||
"expo-linking": "~3.3.1"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.19.3"
|
"@babel/core": "^7.19.3"
|
||||||
|
|||||||
Reference in New Issue
Block a user