Added styling for liked tracks, added album screen
This commit is contained in:
@@ -6,6 +6,7 @@ import MediaPlayer from "./src/components/MediaPlayer";
|
|||||||
import HomeScreen from "./src/screens/HomeScreen";
|
import HomeScreen from "./src/screens/HomeScreen";
|
||||||
import { createContext, useState, useContext } from "react";
|
import { createContext, useState, useContext } from "react";
|
||||||
import LikedTracksScreen from "./src/screens/LikedTracksScreen";
|
import LikedTracksScreen from "./src/screens/LikedTracksScreen";
|
||||||
|
import AlbumScreen from "./src/screens/AlbumScreen";
|
||||||
|
|
||||||
const Stack = createNativeStackNavigator();
|
const Stack = createNativeStackNavigator();
|
||||||
|
|
||||||
@@ -37,6 +38,7 @@ function AppNavigator() {
|
|||||||
<Stack.Navigator screenOptions={{ headerShown: false }}>
|
<Stack.Navigator screenOptions={{ headerShown: false }}>
|
||||||
<Stack.Screen name="Home" component={HomeScreen} />
|
<Stack.Screen name="Home" component={HomeScreen} />
|
||||||
<Stack.Screen name="LikedTracks" component={LikedTracksScreen} />
|
<Stack.Screen name="LikedTracks" component={LikedTracksScreen} />
|
||||||
|
<Stack.Screen name="Album" component={AlbumScreen} />
|
||||||
</Stack.Navigator>
|
</Stack.Navigator>
|
||||||
</NavigationContainer>
|
</NavigationContainer>
|
||||||
);
|
);
|
||||||
|
|||||||
BIN
jukebox/assets/covers/discovery.jpg
Normal file
BIN
jukebox/assets/covers/discovery.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
BIN
jukebox/assets/covers/soundtracksfortheblind.jpg
Normal file
BIN
jukebox/assets/covers/soundtracksfortheblind.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 81 KiB |
75
jukebox/package-lock.json
generated
75
jukebox/package-lock.json
generated
@@ -64,6 +64,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz",
|
||||||
"integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
|
"integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.29.0",
|
"@babel/code-frame": "^7.29.0",
|
||||||
"@babel/generator": "^7.29.0",
|
"@babel/generator": "^7.29.0",
|
||||||
@@ -1344,7 +1345,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz",
|
||||||
"integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==",
|
"integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.27.1"
|
"@babel/helper-plugin-utils": "^7.27.1"
|
||||||
},
|
},
|
||||||
@@ -1434,6 +1434,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz",
|
||||||
"integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==",
|
"integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
@@ -3000,9 +3001,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@react-native/codegen/node_modules/minimatch": {
|
"node_modules/@react-native/codegen/node_modules/minimatch": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
||||||
"integrity": "sha512-M2GCs7Vk83NxkUyQV1bkABc4yxgz9kILhHImZiBPAZ9ybuvCb0/H7lEl5XvIg3g+9d4eNotkZA5IWwYl0tibaA==",
|
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
@@ -3170,6 +3171,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-7.1.31.tgz",
|
"resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-7.1.31.tgz",
|
||||||
"integrity": "sha512-+YCUwtfDgsux59Q0LDHc3Zid9ih93ecUCFWZOH6/+eNoUGnWx77wjS6ZfvBO/7E+EiIup11IVShDzCHR4of8hw==",
|
"integrity": "sha512-+YCUwtfDgsux59Q0LDHc3Zid9ih93ecUCFWZOH6/+eNoUGnWx77wjS6ZfvBO/7E+EiIup11IVShDzCHR4of8hw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@react-navigation/core": "^7.15.1",
|
"@react-navigation/core": "^7.15.1",
|
||||||
"escape-string-regexp": "^4.0.0",
|
"escape-string-regexp": "^4.0.0",
|
||||||
@@ -4005,6 +4007,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"baseline-browser-mapping": "^2.9.0",
|
"baseline-browser-mapping": "^2.9.0",
|
||||||
"caniuse-lite": "^1.0.30001759",
|
"caniuse-lite": "^1.0.30001759",
|
||||||
@@ -4677,6 +4680,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/expo/-/expo-54.0.33.tgz",
|
"resolved": "https://registry.npmjs.org/expo/-/expo-54.0.33.tgz",
|
||||||
"integrity": "sha512-3yOEfAKqo+gqHcV8vKcnq0uA5zxlohnhA3fu4G43likN8ct5ZZ3LjAh9wDdKteEkoad3tFPvwxmXW711S5OHUw==",
|
"integrity": "sha512-3yOEfAKqo+gqHcV8vKcnq0uA5zxlohnhA3fu4G43likN8ct5ZZ3LjAh9wDdKteEkoad3tFPvwxmXW711S5OHUw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.20.0",
|
"@babel/runtime": "^7.20.0",
|
||||||
"@expo/cli": "54.0.23",
|
"@expo/cli": "54.0.23",
|
||||||
@@ -4729,6 +4733,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/expo-font/-/expo-font-14.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/expo-font/-/expo-font-14.0.11.tgz",
|
||||||
"integrity": "sha512-ga0q61ny4s/kr4k8JX9hVH69exVSIfcIc19+qZ7gt71Mqtm7xy2c6kwsPTCyhBW2Ro5yXTT8EaZOpuRi35rHbg==",
|
"integrity": "sha512-ga0q61ny4s/kr4k8JX9hVH69exVSIfcIc19+qZ7gt71Mqtm7xy2c6kwsPTCyhBW2Ro5yXTT8EaZOpuRi35rHbg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fontfaceobserver": "^2.1.0"
|
"fontfaceobserver": "^2.1.0"
|
||||||
},
|
},
|
||||||
@@ -5382,9 +5387,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/glob/node_modules/minimatch": {
|
"node_modules/glob/node_modules/minimatch": {
|
||||||
"version": "10.2.2",
|
"version": "10.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz",
|
||||||
"integrity": "sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw==",
|
"integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==",
|
||||||
"license": "BlueOak-1.0.0",
|
"license": "BlueOak-1.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^5.0.2"
|
"brace-expansion": "^5.0.2"
|
||||||
@@ -6992,12 +6997,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/minimatch": {
|
"node_modules/minimatch": {
|
||||||
"version": "9.0.6",
|
"version": "9.0.9",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz",
|
||||||
"integrity": "sha512-kQAVowdR33euIqeA0+VZTDqU+qo1IeVY+hrKYtZMio3Pg0P0vuh/kwRylLUddJhB6pf3q/botcOvRtx4IN1wqQ==",
|
"integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^5.0.2"
|
"brace-expansion": "^2.0.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16 || 14 >=14.17"
|
"node": ">=16 || 14 >=14.17"
|
||||||
@@ -7006,6 +7011,21 @@
|
|||||||
"url": "https://github.com/sponsors/isaacs"
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/minimatch/node_modules/balanced-match": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/minimatch/node_modules/brace-expansion": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"balanced-match": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/minimist": {
|
"node_modules/minimist": {
|
||||||
"version": "1.2.8",
|
"version": "1.2.8",
|
||||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
||||||
@@ -7668,6 +7688,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
|
||||||
"integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
|
"integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
@@ -7687,6 +7708,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz",
|
||||||
"integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
|
"integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"scheduler": "^0.26.0"
|
"scheduler": "^0.26.0"
|
||||||
},
|
},
|
||||||
@@ -7717,6 +7739,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-native/-/react-native-0.81.5.tgz",
|
"resolved": "https://registry.npmjs.org/react-native/-/react-native-0.81.5.tgz",
|
||||||
"integrity": "sha512-1w+/oSjEXZjMqsIvmkCRsOc8UBYv163bTWKTI8+1mxztvQPhCRYGTvZ/PL1w16xXHneIj/SLGfxWg2GWN2uexw==",
|
"integrity": "sha512-1w+/oSjEXZjMqsIvmkCRsOc8UBYv163bTWKTI8+1mxztvQPhCRYGTvZ/PL1w16xXHneIj/SLGfxWg2GWN2uexw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jest/create-cache-key-function": "^29.7.0",
|
"@jest/create-cache-key-function": "^29.7.0",
|
||||||
"@react-native/assets-registry": "0.81.5",
|
"@react-native/assets-registry": "0.81.5",
|
||||||
@@ -7774,6 +7797,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.28.0.tgz",
|
||||||
"integrity": "sha512-0msfJ1vRxXKVgTgvL+1ZOoYw3/0z1R+Ked0+udoJhyplC2jbVKIJ8Z1bzWdpQRCV3QcQ87Op0zJVE5DhKK2A0A==",
|
"integrity": "sha512-0msfJ1vRxXKVgTgvL+1ZOoYw3/0z1R+Ked0+udoJhyplC2jbVKIJ8Z1bzWdpQRCV3QcQ87Op0zJVE5DhKK2A0A==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@egjs/hammerjs": "^2.0.17",
|
"@egjs/hammerjs": "^2.0.17",
|
||||||
"hoist-non-react-statics": "^3.3.0",
|
"hoist-non-react-statics": "^3.3.0",
|
||||||
@@ -7827,6 +7851,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-5.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-5.6.2.tgz",
|
||||||
"integrity": "sha512-4XGqMNj5qjUTYywJqpdWZ9IG8jgkS3h06sfVjfw5yZQZfWnRFXczi0GnYyFyCc2EBps/qFmoCH8fez//WumdVg==",
|
"integrity": "sha512-4XGqMNj5qjUTYywJqpdWZ9IG8jgkS3h06sfVjfw5yZQZfWnRFXczi0GnYyFyCc2EBps/qFmoCH8fez//WumdVg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "*",
|
"react": "*",
|
||||||
"react-native": "*"
|
"react-native": "*"
|
||||||
@@ -7837,6 +7862,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-4.16.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-4.16.0.tgz",
|
||||||
"integrity": "sha512-yIAyh7F/9uWkOzCi1/2FqvNvK6Wb9Y1+Kzn16SuGfN9YFJDTbwlzGRvePCNTOX0recpLQF3kc2FmvMUhyTCH1Q==",
|
"integrity": "sha512-yIAyh7F/9uWkOzCi1/2FqvNvK6Wb9Y1+Kzn16SuGfN9YFJDTbwlzGRvePCNTOX0recpLQF3kc2FmvMUhyTCH1Q==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react-freeze": "^1.0.0",
|
"react-freeze": "^1.0.0",
|
||||||
"react-native-is-edge-to-edge": "^1.2.1",
|
"react-native-is-edge-to-edge": "^1.2.1",
|
||||||
@@ -7939,7 +7965,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-native-worklets/-/react-native-worklets-0.7.4.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-worklets/-/react-native-worklets-0.7.4.tgz",
|
||||||
"integrity": "sha512-NYOdM1MwBb3n+AtMqy1tFy3Mn8DliQtd8sbzAVRf9Gc+uvQ0zRfxN7dS8ZzoyX7t6cyQL5THuGhlnX+iFlQTag==",
|
"integrity": "sha512-NYOdM1MwBb3n+AtMqy1tFy3Mn8DliQtd8sbzAVRf9Gc+uvQ0zRfxN7dS8ZzoyX7t6cyQL5THuGhlnX+iFlQTag==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/plugin-transform-arrow-functions": "7.27.1",
|
"@babel/plugin-transform-arrow-functions": "7.27.1",
|
||||||
"@babel/plugin-transform-class-properties": "7.27.1",
|
"@babel/plugin-transform-class-properties": "7.27.1",
|
||||||
@@ -7964,7 +7989,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.27.1.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.27.1.tgz",
|
||||||
"integrity": "sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==",
|
"integrity": "sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-create-class-features-plugin": "^7.27.1",
|
"@babel/helper-create-class-features-plugin": "^7.27.1",
|
||||||
"@babel/helper-plugin-utils": "^7.27.1"
|
"@babel/helper-plugin-utils": "^7.27.1"
|
||||||
@@ -7981,7 +8005,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.4.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.4.tgz",
|
||||||
"integrity": "sha512-cFOlhIYPBv/iBoc+KS3M6et2XPtbT2HiCRfBXWtfpc9OAyostldxIf9YAYB6ypURBBbx+Qv6nyrLzASfJe+hBA==",
|
"integrity": "sha512-cFOlhIYPBv/iBoc+KS3M6et2XPtbT2HiCRfBXWtfpc9OAyostldxIf9YAYB6ypURBBbx+Qv6nyrLzASfJe+hBA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-annotate-as-pure": "^7.27.3",
|
"@babel/helper-annotate-as-pure": "^7.27.3",
|
||||||
"@babel/helper-compilation-targets": "^7.27.2",
|
"@babel/helper-compilation-targets": "^7.27.2",
|
||||||
@@ -8002,7 +8025,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.27.1.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.27.1.tgz",
|
||||||
"integrity": "sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==",
|
"integrity": "sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.27.1"
|
"@babel/helper-plugin-utils": "^7.27.1"
|
||||||
},
|
},
|
||||||
@@ -8018,7 +8040,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.27.1.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.27.1.tgz",
|
||||||
"integrity": "sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg==",
|
"integrity": "sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.27.1",
|
"@babel/helper-plugin-utils": "^7.27.1",
|
||||||
"@babel/helper-skip-transparent-expression-wrappers": "^7.27.1"
|
"@babel/helper-skip-transparent-expression-wrappers": "^7.27.1"
|
||||||
@@ -8035,7 +8056,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.27.1.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.27.1.tgz",
|
||||||
"integrity": "sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ==",
|
"integrity": "sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.27.1",
|
"@babel/helper-plugin-utils": "^7.27.1",
|
||||||
"@babel/helper-validator-option": "^7.27.1",
|
"@babel/helper-validator-option": "^7.27.1",
|
||||||
@@ -8055,7 +8075,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
|
||||||
"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
|
"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"peer": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"semver": "bin/semver.js"
|
"semver": "bin/semver.js"
|
||||||
},
|
},
|
||||||
@@ -8133,9 +8152,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-native/node_modules/minimatch": {
|
"node_modules/react-native/node_modules/minimatch": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
||||||
"integrity": "sha512-M2GCs7Vk83NxkUyQV1bkABc4yxgz9kILhHImZiBPAZ9ybuvCb0/H7lEl5XvIg3g+9d4eNotkZA5IWwYl0tibaA==",
|
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
@@ -8158,6 +8177,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz",
|
||||||
"integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==",
|
"integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
@@ -8384,9 +8404,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/rimraf/node_modules/minimatch": {
|
"node_modules/rimraf/node_modules/minimatch": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
||||||
"integrity": "sha512-M2GCs7Vk83NxkUyQV1bkABc4yxgz9kILhHImZiBPAZ9ybuvCb0/H7lEl5XvIg3g+9d4eNotkZA5IWwYl0tibaA==",
|
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
@@ -9044,9 +9064,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/test-exclude/node_modules/minimatch": {
|
"node_modules/test-exclude/node_modules/minimatch": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
||||||
"integrity": "sha512-M2GCs7Vk83NxkUyQV1bkABc4yxgz9kILhHImZiBPAZ9ybuvCb0/H7lEl5XvIg3g+9d4eNotkZA5IWwYl0tibaA==",
|
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
@@ -9120,6 +9140,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
|
||||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -10,9 +10,10 @@ export default function MediaPlayer({ title, onPress }) {
|
|||||||
return (
|
return (
|
||||||
<LinearGradient
|
<LinearGradient
|
||||||
colors={[
|
colors={[
|
||||||
"rgba(70,70,70,0.92)", // top
|
"rgba(25,25,25,0.95)", // top
|
||||||
"rgba(35,35,35,0.95)", // middle
|
"rgba(15,15,15,0.98)", // middle-top
|
||||||
"rgba(15,15,15,0.98)", // bottom
|
"rgba(5,5,5,1)", // middle-bottom
|
||||||
|
"rgba(5,5,5,1)", // bottom
|
||||||
]}
|
]}
|
||||||
locations={[0, 0.55, 1]}
|
locations={[0, 0.55, 1]}
|
||||||
start={{ x: 0.5, y: 0 }}
|
start={{ x: 0.5, y: 0 }}
|
||||||
|
|||||||
79
jukebox/src/components/TrackRow.js
Normal file
79
jukebox/src/components/TrackRow.js
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Pressable, View, Text, StyleSheet, Image } from 'react-native';
|
||||||
|
|
||||||
|
export default function TrackRow({
|
||||||
|
title,
|
||||||
|
artist,
|
||||||
|
duration,
|
||||||
|
cover,
|
||||||
|
onPress,
|
||||||
|
showHeart = true,
|
||||||
|
liked = false, // new prop
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Pressable style={styles.trackItem} onPress={onPress}>
|
||||||
|
{cover ? <Image source={cover} style={styles.trackCover} resizeMode="cover" /> : null}
|
||||||
|
|
||||||
|
<View style={styles.trackTextBlock}>
|
||||||
|
<Text style={styles.trackTitle} numberOfLines={1}>
|
||||||
|
{title}
|
||||||
|
</Text>
|
||||||
|
<Text style={styles.trackArtist} numberOfLines={1}>
|
||||||
|
{artist}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{duration ? <Text style={styles.trackDuration}>{duration}</Text> : null}
|
||||||
|
|
||||||
|
{showHeart ? (
|
||||||
|
<Text style={[styles.heart, liked && styles.heartLiked]}>
|
||||||
|
{liked ? '♥' : '♡'}
|
||||||
|
</Text>
|
||||||
|
) : null}
|
||||||
|
</Pressable>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
trackItem: {
|
||||||
|
width: '100%',
|
||||||
|
minHeight: 62,
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
marginBottom: 10,
|
||||||
|
},
|
||||||
|
trackCover: {
|
||||||
|
width: 46,
|
||||||
|
height: 46,
|
||||||
|
borderRadius: 6,
|
||||||
|
marginRight: 10,
|
||||||
|
},
|
||||||
|
trackTextBlock: {
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
trackTitle: {
|
||||||
|
color: '#ffffff',
|
||||||
|
fontSize: 15,
|
||||||
|
fontWeight: '700',
|
||||||
|
},
|
||||||
|
trackArtist: {
|
||||||
|
color: '#ffffff',
|
||||||
|
fontSize: 15,
|
||||||
|
marginTop: 2,
|
||||||
|
},
|
||||||
|
trackDuration: {
|
||||||
|
color: '#ffffff',
|
||||||
|
fontSize: 15,
|
||||||
|
paddingHorizontal: 18,
|
||||||
|
},
|
||||||
|
heart: {
|
||||||
|
fontSize: 22,
|
||||||
|
color: '#fff',
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
},
|
||||||
|
heartLiked: {
|
||||||
|
fontSize: 22,
|
||||||
|
color: '#ff4d6d',
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
},
|
||||||
|
});
|
||||||
66
jukebox/src/data/library.js
Normal file
66
jukebox/src/data/library.js
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
const library = [
|
||||||
|
{
|
||||||
|
id: 'album1',
|
||||||
|
title: 'Soundtracks For The Blind',
|
||||||
|
artist: 'Swans',
|
||||||
|
date: '1996-11-29',
|
||||||
|
label: 'Young God Records',
|
||||||
|
duration: '2:21:25',
|
||||||
|
cover: require('../../assets/covers/soundtracksfortheblind.jpg'),
|
||||||
|
tracks: [
|
||||||
|
{ id: 'a1t1', title: 'Red Velvet Corridor', duration: '3:03', liked: true },
|
||||||
|
{ id: 'a1t2', title: 'I Was a Prisoner in Your Skull', duration: '6:39', liked: false },
|
||||||
|
{ id: 'a1t3', title: 'Helpless Child', duration: '15:47', liked: true },
|
||||||
|
{ id: 'a1t4', title: 'Live Through Me', duration: '2:19', liked: false },
|
||||||
|
{ id: 'a1t5', title: 'Yum-Yab Killers', duration: '5:07', liked: false },
|
||||||
|
{ id: 'a1t6', title: 'The Beautiful Days', duration: '1:50', liked: false },
|
||||||
|
{ id: 'a1t7', title: 'Volcano', duration: '5:18', liked: false },
|
||||||
|
{ id: 'a1t8', title: 'Mellothumb', duration: '2:45', liked: false },
|
||||||
|
{ id: 'a1t9', title: 'All Lined Up', duration: '4:48', liked: false },
|
||||||
|
{ id: 'a1t10', title: 'Surrogate Drone', duration: '2:03', liked: false },
|
||||||
|
{ id: 'a1t11', title: 'How They Suffer', duration: '5:52', liked: false },
|
||||||
|
{ id: 'a1t12', title: 'Animus', duration: '10:43', liked: false },
|
||||||
|
{ id: 'a1t13', title: 'Red Velvet Wound', duration: '1:01', liked: false },
|
||||||
|
{ id: 'a1t14', title: 'The Sound', duration: '13:11', liked: true },
|
||||||
|
{ id: 'a1t15', title: 'Her Mouth Is Filled with Honey', duration: '3:18', liked: false },
|
||||||
|
{ id: 'a1t16', title: 'Blood Section', duration: '2:45', liked: false },
|
||||||
|
{ id: 'a1t17', title: 'Hypogirl', duration: '3:42', liked: false },
|
||||||
|
{ id: 'a1t18', title: 'Minus Something', duration: '4:14', liked: false },
|
||||||
|
{ id: 'a1t19', title: 'Empathy', duration: '6:45', liked: false },
|
||||||
|
{ id: 'a1t20', title: 'I Love You This Much', duration: '7:23', liked: false },
|
||||||
|
{ id: 'a1t21', title: "YRP", duration: '7:58', liked: false },
|
||||||
|
{ id: 'a1t22', title: "Fan's Lament", duration: '1:47', liked: false },
|
||||||
|
{ id: 'a1t23', title: 'Secret Friends', duration: '3:08', liked: false },
|
||||||
|
{ id: 'a1t24', title: 'The Final Sacrifice', duration: '9:51', liked: false },
|
||||||
|
{ id: 'a1t25', title: 'YRP 2', duration: '2:09', liked: false },
|
||||||
|
{ id: 'a1t26', title: 'Surrogate 2', duration: '1:55', liked: false },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'album2',
|
||||||
|
title: 'Discovery',
|
||||||
|
artist: 'Daft Punk',
|
||||||
|
date: '2001-03-12',
|
||||||
|
label: 'Virgin Records',
|
||||||
|
duration: '1:00:50',
|
||||||
|
cover: require('../../assets/covers/discovery.jpg'),
|
||||||
|
tracks: [
|
||||||
|
{ id: 'a2t1', title: 'One More Time', duration: '5:20', liked: true },
|
||||||
|
{ id: 'a2t2', title: 'Aerodynamic', duration: '3:27', liked: false },
|
||||||
|
{ id: 'a2t3', title: 'Digital Love', duration: '4:58', liked: false },
|
||||||
|
{ id: 'a2t4', title: 'Harder, Better, Faster, Stronger', duration: '3:45', liked: false },
|
||||||
|
{ id: 'a2t5', title: 'Crescendolls', duration: '3:31', liked: false },
|
||||||
|
{ id: 'a2t6', title: 'Nightvision', duration: '1:44', liked: false },
|
||||||
|
{ id: 'a2t7', title: 'Superheroes', duration: '3:57', liked: false },
|
||||||
|
{ id: 'a2t8', title: 'High Life', duration: '3:21', liked: false },
|
||||||
|
{ id: 'a2t9', title: 'Something About Us', duration: '3:51', liked: false },
|
||||||
|
{ id: 'a2t10', title: 'Voyager', duration: '3:47', liked: false },
|
||||||
|
{ id: 'a2t11', title: 'Veridis Quo', duration: '5:44', liked: false },
|
||||||
|
{ id: 'a2t12', title: 'Short Circuit', duration: '3:26', liked: false },
|
||||||
|
{ id: 'a2t13', title: 'Face to Face', duration: '4:00', liked: false },
|
||||||
|
{ id: 'a2t14', title: 'Too Long', duration: '10:00', liked: false },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default library;
|
||||||
122
jukebox/src/screens/AlbumScreen.js
Normal file
122
jukebox/src/screens/AlbumScreen.js
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { View, Text, StyleSheet, FlatList, Pressable, Image } from 'react-native';
|
||||||
|
import TrackRow from '../components/TrackRow';
|
||||||
|
|
||||||
|
export default function AlbumScreen({ route, navigation }) {
|
||||||
|
const { album } = route.params;
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<Pressable onPress={() => navigation.goBack()} style={styles.backBtn}>
|
||||||
|
<Text style={styles.backText}>← Back</Text>
|
||||||
|
</Pressable>
|
||||||
|
<View style={styles.header}>
|
||||||
|
<Image source={album.cover} style={styles.cover} resizeMode="cover" />
|
||||||
|
<Text style={styles.title}>{album.title}</Text>
|
||||||
|
<Text style={styles.artist}>{album.artist}</Text>
|
||||||
|
<Text style={styles.meta}>{album.date} · {album.label} · {album.duration}</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<FlatList
|
||||||
|
data={album.tracks}
|
||||||
|
keyExtractor={(item, index) => item.id ?? index.toString()}
|
||||||
|
renderItem={({ item }) => (
|
||||||
|
<TrackRow
|
||||||
|
title={typeof item === 'string' ? item : item.title}
|
||||||
|
artist={album.artist}
|
||||||
|
duration={item.duration}
|
||||||
|
onPress={() => { }}
|
||||||
|
showHeart={true}
|
||||||
|
liked={item.liked}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
contentContainerStyle={styles.trackList}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: '#000',
|
||||||
|
paddingTop: 28,
|
||||||
|
paddingHorizontal: 16,
|
||||||
|
paddingBottom: 24,
|
||||||
|
},
|
||||||
|
header: {
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
cover: {
|
||||||
|
width: 180,
|
||||||
|
height: 180,
|
||||||
|
borderRadius: 8,
|
||||||
|
marginBottom: 12,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 32,
|
||||||
|
fontWeight: '700',
|
||||||
|
textAlign: 'center',
|
||||||
|
marginBottom: 1,
|
||||||
|
},
|
||||||
|
artist: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 26,
|
||||||
|
fontWeight: '500',
|
||||||
|
textAlign: 'center',
|
||||||
|
marginTop: 1,
|
||||||
|
},
|
||||||
|
meta: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: '500',
|
||||||
|
textAlign: 'center',
|
||||||
|
marginTop: 8,
|
||||||
|
marginBottom: 24,
|
||||||
|
},
|
||||||
|
trackList: {
|
||||||
|
width: '100%',
|
||||||
|
paddingHorizontal: 16,
|
||||||
|
paddingBottom: 180,
|
||||||
|
},
|
||||||
|
trackItem: {
|
||||||
|
width: '100%',
|
||||||
|
minHeight: 62,
|
||||||
|
padding: 0,
|
||||||
|
flexDirection: 'row',
|
||||||
|
},
|
||||||
|
trackTextBlock: {
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
trackTitle: {
|
||||||
|
color: '#ffffff',
|
||||||
|
fontSize: 15,
|
||||||
|
fontWeight: '700',
|
||||||
|
},
|
||||||
|
trackArtist: {
|
||||||
|
color: '#ffffff',
|
||||||
|
fontSize: 15,
|
||||||
|
marginTop: 2,
|
||||||
|
},
|
||||||
|
trackDuration: {
|
||||||
|
color: '#ffffff',
|
||||||
|
fontSize: 15,
|
||||||
|
paddingHorizontal: 18,
|
||||||
|
marginTop: 10,
|
||||||
|
},
|
||||||
|
heart: {
|
||||||
|
fontSize: 22,
|
||||||
|
color: '#fff',
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
marginTop: 5.5,
|
||||||
|
},
|
||||||
|
backBtn: {
|
||||||
|
marginBottom: 10,
|
||||||
|
alignSelf: 'flex-start',
|
||||||
|
},
|
||||||
|
backText: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: '600',
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -6,56 +6,94 @@ import {
|
|||||||
FlatList,
|
FlatList,
|
||||||
ScrollView,
|
ScrollView,
|
||||||
Pressable,
|
Pressable,
|
||||||
|
Image,
|
||||||
} from "react-native";
|
} from "react-native";
|
||||||
|
import { Ionicons } from "@expo/vector-icons";
|
||||||
import { useNavigation } from "@react-navigation/native";
|
import { useNavigation } from "@react-navigation/native";
|
||||||
|
import library from '../data/library';
|
||||||
|
import TrackRow from '../components/TrackRow';
|
||||||
|
|
||||||
const likedTracks = [
|
const likedAlbums = library;
|
||||||
"Track 1",
|
|
||||||
"Track 2",
|
|
||||||
"Track 3",
|
|
||||||
"Track 4",
|
|
||||||
"Track 5",
|
|
||||||
"Track 6",
|
|
||||||
];
|
|
||||||
|
|
||||||
const likedAlbums = [
|
const likedTracks = library.flatMap((album) =>
|
||||||
"Album 1",
|
album.tracks
|
||||||
"Album 2",
|
.filter((t) => t.liked)
|
||||||
"Album 3",
|
.map((t) => ({
|
||||||
"Album 4",
|
...t,
|
||||||
"Album 5",
|
albumId: album.id,
|
||||||
"Album 6",
|
albumTitle: album.title,
|
||||||
"Album 7",
|
artist: album.artist,
|
||||||
"Album 8",
|
cover: album.cover,
|
||||||
];
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
export default function HomeScreen() {
|
export default function HomeScreen() {
|
||||||
const navigation = useNavigation();
|
const navigation = useNavigation();
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
|
<View style={styles.headerRow}>
|
||||||
|
<Text style={styles.homeTitle}>Home</Text>
|
||||||
|
<View style={styles.headerActions}>
|
||||||
|
<Pressable
|
||||||
|
style={styles.iconBtn}
|
||||||
|
onPress={() => {
|
||||||
|
// navigation.navigate("Login")
|
||||||
|
console.log("Login pressed");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Ionicons name="person-outline" size={24} color="#fff" />
|
||||||
|
</Pressable>
|
||||||
|
|
||||||
|
<Pressable
|
||||||
|
style={styles.iconBtn}
|
||||||
|
onPress={() => {
|
||||||
|
// navigation.navigate("Settings")
|
||||||
|
console.log("Settings pressed");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Ionicons name="settings-outline" size={24} color="#fff" />
|
||||||
|
</Pressable>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
<Pressable
|
<Pressable
|
||||||
onPress={() =>
|
onPress={() => navigation.navigate("LikedTracks", { tracks: likedTracks })}
|
||||||
navigation.navigate("LikedTracks", { tracks: likedTracks })
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<Text style={styles.sectionTitle}>Liked tracks ➚</Text>
|
<Text style={styles.sectionTitle}>Liked tracks ➚</Text>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
|
|
||||||
{likedTracks.map((item, index) => (
|
{likedTracks.map((track) => {
|
||||||
<View key={index} style={styles.trackItem} />
|
const album = likedAlbums.find((a) => a.id === track.albumId);
|
||||||
))}
|
|
||||||
|
|
||||||
<Text style={[styles.sectionTitle, { marginTop: 24 }]}>
|
return (
|
||||||
Liked albums ➚
|
<TrackRow
|
||||||
</Text>
|
key={track.id}
|
||||||
|
title={track.title}
|
||||||
|
artist={album?.artist ?? "Unknown artist"}
|
||||||
|
duration={track.duration}
|
||||||
|
cover={album?.cover}
|
||||||
|
showHeart={true}
|
||||||
|
liked={track.liked}
|
||||||
|
onPress={() => album && navigation.navigate("Album", { album })}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
|
||||||
|
<Text style={[styles.sectionTitle, { marginTop: 24 }]}>Liked albums</Text>
|
||||||
|
|
||||||
<FlatList
|
<FlatList
|
||||||
data={likedAlbums}
|
data={likedAlbums}
|
||||||
keyExtractor={(_, index) => index.toString()}
|
keyExtractor={(item) => item.id}
|
||||||
numColumns={2}
|
numColumns={2}
|
||||||
columnWrapperStyle={styles.albumRow}
|
columnWrapperStyle={styles.albumRow}
|
||||||
contentContainerStyle={styles.albumList}
|
contentContainerStyle={styles.albumList}
|
||||||
renderItem={() => <View style={styles.albumItem} />}
|
renderItem={({ item }) => (
|
||||||
|
<Pressable
|
||||||
|
style={styles.albumItem}
|
||||||
|
onPress={() => navigation.navigate("Album", { album: item })}
|
||||||
|
>
|
||||||
|
<Image source={item.cover} style={styles.cover} resizeMode="cover" />
|
||||||
|
</Pressable>
|
||||||
|
)}
|
||||||
showsVerticalScrollIndicator={false}
|
showsVerticalScrollIndicator={false}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
@@ -69,34 +107,83 @@ const styles = StyleSheet.create({
|
|||||||
paddingTop: 24,
|
paddingTop: 24,
|
||||||
paddingHorizontal: 16,
|
paddingHorizontal: 16,
|
||||||
},
|
},
|
||||||
|
headerRow: {
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
marginBottom: 12,
|
||||||
|
},
|
||||||
|
headerActions: {
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: 8, // if gap not supported on your RN version, use marginLeft in iconBtn
|
||||||
|
},
|
||||||
|
settingsBtn: {
|
||||||
|
padding: 2,
|
||||||
|
},
|
||||||
|
loginBtn: {
|
||||||
|
padding: 2,
|
||||||
|
},
|
||||||
|
homeTitle: {
|
||||||
|
color: "#ffffff",
|
||||||
|
fontSize: 32,
|
||||||
|
fontWeight: "700",
|
||||||
|
marginBottom: 12,
|
||||||
|
},
|
||||||
sectionTitle: {
|
sectionTitle: {
|
||||||
color: "#fff",
|
color: "#ffffff",
|
||||||
fontSize: 34,
|
fontSize: 24,
|
||||||
fontWeight: "700",
|
fontWeight: "700",
|
||||||
marginBottom: 12,
|
marginBottom: 12,
|
||||||
},
|
},
|
||||||
trackItem: {
|
trackItem: {
|
||||||
height: 42,
|
minHeight: 62,
|
||||||
backgroundColor: "#ffd9d9",
|
flexDirection: 'row',
|
||||||
borderWidth: 2,
|
alignItems: 'center',
|
||||||
borderColor: "#ff4d4d",
|
},
|
||||||
borderRadius: 8,
|
|
||||||
marginBottom: 10,
|
trackCover: {
|
||||||
|
width: 46,
|
||||||
|
height: 46,
|
||||||
|
borderRadius: 6,
|
||||||
|
marginRight: 10,
|
||||||
|
},
|
||||||
|
|
||||||
|
trackTextBlock: {
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
|
||||||
|
trackTitle: {
|
||||||
|
color: '#ffffff',
|
||||||
|
fontSize: 15,
|
||||||
|
fontWeight: '700',
|
||||||
|
},
|
||||||
|
|
||||||
|
trackArtist: {
|
||||||
|
color: '#ffffff',
|
||||||
|
fontSize: 13,
|
||||||
|
marginTop: 2,
|
||||||
},
|
},
|
||||||
tracksBox: {
|
tracksBox: {
|
||||||
maxHeight: 260, // about 5 track rows
|
maxHeight: 260,
|
||||||
},
|
},
|
||||||
albumList: {
|
albumList: {
|
||||||
paddingBottom: 120, // keep room for your media player at bottom
|
paddingBottom: 120,
|
||||||
},
|
},
|
||||||
albumRow: {
|
albumRow: {
|
||||||
justifyContent: "space-between",
|
justifyContent: "space-between",
|
||||||
marginBottom: 12,
|
marginBottom: 12,
|
||||||
},
|
},
|
||||||
albumItem: {
|
albumItem: {
|
||||||
width: "48%",
|
width: '48%',
|
||||||
aspectRatio: 1, // square
|
aspectRatio: 1,
|
||||||
backgroundColor: "#f7d7a6",
|
borderRadius: 8,
|
||||||
borderRadius: 18,
|
overflow: 'hidden',
|
||||||
|
backgroundColor: '#222',
|
||||||
|
},
|
||||||
|
cover: {
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,8 +1,23 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { View, Text, StyleSheet, FlatList, Pressable } from "react-native";
|
import { View, Text, StyleSheet, FlatList, Pressable } from "react-native";
|
||||||
|
import library from "../data/library";
|
||||||
|
import TrackRow from "../components/TrackRow";
|
||||||
|
|
||||||
export default function LikedTracksScreen({ route, navigation }) {
|
export default function LikedTracksScreen({ navigation }) {
|
||||||
const tracks = route.params?.tracks ?? [];
|
const likedTracks = library.flatMap((album) =>
|
||||||
|
album.tracks
|
||||||
|
.filter((track) => track.liked)
|
||||||
|
.map((track) => ({
|
||||||
|
...track,
|
||||||
|
albumId: album.id,
|
||||||
|
albumTitle: album.title,
|
||||||
|
artist: album.artist,
|
||||||
|
cover: album.cover,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
|
// testing only
|
||||||
|
const tracks = likedTracks.slice(0, 2);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
@@ -14,13 +29,22 @@ export default function LikedTracksScreen({ route, navigation }) {
|
|||||||
|
|
||||||
<FlatList
|
<FlatList
|
||||||
data={tracks}
|
data={tracks}
|
||||||
keyExtractor={(_, index) => index.toString()}
|
keyExtractor={(item) => item.id}
|
||||||
renderItem={({ item }) => (
|
renderItem={({ item }) => (
|
||||||
<View style={styles.trackItem}>
|
<TrackRow
|
||||||
<Text style={styles.trackText}>{item}</Text>
|
title={item.title}
|
||||||
</View>
|
artist={item.artist}
|
||||||
|
duration={item.duration}
|
||||||
|
cover={item.cover}
|
||||||
|
showHeart={true}
|
||||||
|
liked={item.liked}
|
||||||
|
onPress={() => {
|
||||||
|
const album = library.find((a) => a.id === item.albumId);
|
||||||
|
if (album) navigation.navigate("Album", { album });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
contentContainerStyle={{ paddingBottom: 24 }}
|
contentContainerStyle={{ paddingBottom: 180 }}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
@@ -33,18 +57,19 @@ const styles = StyleSheet.create({
|
|||||||
paddingTop: 24,
|
paddingTop: 24,
|
||||||
paddingHorizontal: 16,
|
paddingHorizontal: 16,
|
||||||
},
|
},
|
||||||
backBtn: { marginBottom: 10 },
|
backBtn: {
|
||||||
backText: { color: "#fff", fontSize: 16 },
|
|
||||||
title: { color: "#fff", fontSize: 30, fontWeight: "700", marginBottom: 12 },
|
|
||||||
trackItem: {
|
|
||||||
height: 50,
|
|
||||||
justifyContent: "center",
|
|
||||||
paddingHorizontal: 12,
|
|
||||||
backgroundColor: "#ffd9d9",
|
|
||||||
borderWidth: 2,
|
|
||||||
borderColor: "#ff4d4d",
|
|
||||||
borderRadius: 8,
|
|
||||||
marginBottom: 10,
|
marginBottom: 10,
|
||||||
|
alignSelf: "flex-start",
|
||||||
},
|
},
|
||||||
trackText: { color: "#111", fontWeight: "600" },
|
backText: {
|
||||||
});
|
color: "#fff",
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: "600",
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
color: "#fff",
|
||||||
|
fontSize: 30,
|
||||||
|
fontWeight: "700",
|
||||||
|
marginBottom: 12,
|
||||||
|
},
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user