From 3e04a69245ab1b4346399a894d5c3aaf447e6aac Mon Sep 17 00:00:00 2001
From: Suryaa <0x0is1@protonmail.com>
Date: Thu, 10 Oct 2024 10:37:21 +0530
Subject: [PATCH] Biome: Fix formatting
---
app.json | 78 ++--
babel.config.js | 10 +-
eas.json | 40 +-
jsconfig.json | 25 +-
package.json | 106 ++---
src/App.js | 100 +++--
src/constants/constants.js | 61 ++-
src/contexts/PlayerContext.jsx | 373 +++++++++--------
src/index.js | 10 +-
src/libs/APIParser.js | 280 +++++++------
src/screens/AboutScreen/AboutScreen.jsx | 20 +-
.../AlbumViewerScreen/AlbumViewerScreen.jsx | 132 +++---
.../components/AlbumItemsContainer.jsx | 155 +++----
.../components/DurationText.jsx | 34 +-
.../components/PlayerBanner.jsx | 200 +++++----
.../components/PlayerFooter.jsx | 389 +++++++++---------
.../components/ProgressBarContainer.jsx | 134 +++---
.../components/UtilityButtons.jsx | 144 ++++---
src/screens/AlbumsScreen/AlbumsScreen.jsx | 29 +-
src/screens/AlbumsScreen/components/Card.jsx | 143 ++++---
.../AlbumsScreen/components/Category.jsx | 66 ++-
.../AlbumsScreen/components/Navbar.jsx | 60 +--
.../DashboardScreen/DashboardScreen.jsx | 206 +++++-----
.../components/CenterHeader.jsx | 92 +++--
.../DashboardScreen/components/Footer.jsx | 119 +++---
.../components/RightHeaderButton.jsx | 23 +-
.../DownloadsScreen/DownloadsScreen.jsx | 20 +-
src/screens/LibraryScreen/LibraryScreen.jsx | 20 +-
src/screens/PlayerScreen/PlayerScreen.jsx | 132 +++---
.../components/AlbumItemsContainer.jsx | 162 ++++----
.../components/CustomStatusBar.jsx | 60 +--
.../PlayerScreen/components/DurationText.jsx | 34 +-
.../PlayerScreen/components/PlayerBanner.jsx | 205 ++++-----
.../PlayerScreen/components/PlayerFooter.jsx | 389 +++++++++---------
.../components/ProgressBarContainer.jsx | 134 +++---
src/screens/SearchScreen/SearchScreen.jsx | 77 ++--
.../SearchScreen/components/ModeSelector.jsx | 58 +--
.../SearchScreen/components/Navbar.jsx | 84 ++--
.../SearchScreen/components/SearchList.jsx | 48 +--
src/screens/SettingsScreen/SettingsScreen.jsx | 20 +-
src/screens/VersionScreen/VersionScreen.jsx | 20 +-
src/utils/RNTPService.js | 8 +-
src/utils/albumParser.js | 243 ++++++-----
src/utils/setupPlayer.js | 49 ++-
src/utils/utilityButtonActions.js | 89 ++--
45 files changed, 2562 insertions(+), 2319 deletions(-)
diff --git a/app.json b/app.json
index c1a5340..972c28c 100644
--- a/app.json
+++ b/app.json
@@ -1,41 +1,41 @@
{
- "expo": {
- "name": "lissen-mobile",
- "slug": "lissen-mobile",
- "displayName": "Lissen",
- "version": "0.1.5",
- "orientation": "portrait",
- "icon": "./assets/icon.png",
- "displayLogo": "./assets/icon.png",
- "userInterfaceStyle": "light",
- "splash": {
- "image": "./assets/splash.png",
- "resizeMode": "contain",
- "backgroundColor": "#ffffff"
- },
- "ios": {
- "supportsTablet": true
- },
- "android": {
- "adaptiveIcon": {
- "backgroundColor": "#ffffff"
- },
- "package": "com.lissenmobile"
- },
- "web": {
- "favicon": "./assets/favicon.png"
- },
- "runtimeVersion": {
- "policy": "appVersion"
- },
- "updates": {
- "url": "https://u.expo.dev/edf2085f-2a08-4fbe-990f-e33ee757f0d6"
- },
- "owner": "0x0is1",
- "extra": {
- "eas": {
- "projectId": "edf2085f-2a08-4fbe-990f-e33ee757f0d6"
- }
- }
- }
+ "expo": {
+ "name": "lissen-mobile",
+ "slug": "lissen-mobile",
+ "displayName": "Lissen",
+ "version": "0.1.5",
+ "orientation": "portrait",
+ "icon": "./assets/icon.png",
+ "displayLogo": "./assets/icon.png",
+ "userInterfaceStyle": "light",
+ "splash": {
+ "image": "./assets/splash.png",
+ "resizeMode": "contain",
+ "backgroundColor": "#ffffff"
+ },
+ "ios": {
+ "supportsTablet": true
+ },
+ "android": {
+ "adaptiveIcon": {
+ "backgroundColor": "#ffffff"
+ },
+ "package": "com.lissenmobile"
+ },
+ "web": {
+ "favicon": "./assets/favicon.png"
+ },
+ "runtimeVersion": {
+ "policy": "appVersion"
+ },
+ "updates": {
+ "url": "https://u.expo.dev/edf2085f-2a08-4fbe-990f-e33ee757f0d6"
+ },
+ "owner": "0x0is1",
+ "extra": {
+ "eas": {
+ "projectId": "edf2085f-2a08-4fbe-990f-e33ee757f0d6"
+ }
+ }
+ }
}
diff --git a/babel.config.js b/babel.config.js
index 2900afe..4cb208f 100644
--- a/babel.config.js
+++ b/babel.config.js
@@ -1,6 +1,6 @@
-module.exports = function(api) {
- api.cache(true);
- return {
- presets: ['babel-preset-expo'],
- };
+module.exports = function (api) {
+ api.cache(true);
+ return {
+ presets: ["babel-preset-expo"],
+ };
};
diff --git a/eas.json b/eas.json
index 8bfcb10..378ee68 100644
--- a/eas.json
+++ b/eas.json
@@ -1,22 +1,22 @@
{
- "cli": {
- "version": ">= 7.6.1"
- },
- "build": {
- "development": {
- "developmentClient": true,
- "distribution": "internal",
- "channel": "development"
- },
- "preview": {
- "distribution": "internal",
- "channel": "preview"
- },
- "production": {
- "channel": "production"
- }
- },
- "submit": {
- "production": {}
- }
+ "cli": {
+ "version": ">= 7.6.1"
+ },
+ "build": {
+ "development": {
+ "developmentClient": true,
+ "distribution": "internal",
+ "channel": "development"
+ },
+ "preview": {
+ "distribution": "internal",
+ "channel": "preview"
+ },
+ "production": {
+ "channel": "production"
+ }
+ },
+ "submit": {
+ "production": {}
+ }
}
diff --git a/jsconfig.json b/jsconfig.json
index 80636cc..ff4799f 100644
--- a/jsconfig.json
+++ b/jsconfig.json
@@ -1,15 +1,12 @@
{
- "compilerOptions": {
- "module": "ESNext",
- "moduleResolution": "Bundler",
- "target": "ES2022",
- "jsx": "react",
- "allowImportingTsExtensions": true,
- "strictNullChecks": true,
- "strictFunctionTypes": true
- },
- "exclude": [
- "node_modules",
- "**/node_modules/*"
- ]
-}
\ No newline at end of file
+ "compilerOptions": {
+ "module": "ESNext",
+ "moduleResolution": "Bundler",
+ "target": "ES2022",
+ "jsx": "react",
+ "allowImportingTsExtensions": true,
+ "strictNullChecks": true,
+ "strictFunctionTypes": true
+ },
+ "exclude": ["node_modules", "**/node_modules/*"]
+}
diff --git a/package.json b/package.json
index f93b1d4..d023dd5 100644
--- a/package.json
+++ b/package.json
@@ -1,55 +1,55 @@
{
- "name": "lissen-mobile",
- "version": "0.1.4",
- "main": "./src/index.js",
- "repository": {
- "url": "https://github.com/0x0is1/lissen-mobile"
- },
- "scripts": {
- "start": "expo start",
- "android": "expo run:android",
- "ios": "expo run:ios",
- "web": "expo start --web"
- },
- "dependencies": {
- "@react-native-async-storage/async-storage": "1.23.1",
- "@react-native-community/datetimepicker": "8.0.1",
- "@react-native-community/progress-bar-android": "^1.0.5",
- "@react-native-community/slider": "^4.5.2",
- "@react-native-picker/picker": "2.7.5",
- "@react-native-seoul/masonry-list": "^1.4.2",
- "@react-navigation/drawer": "^6.7.2",
- "@react-navigation/native": "^6.1.18",
- "@react-navigation/stack": "^6.4.1",
- "axios": "^1.7.3",
- "expo": "~51.0.34",
- "expo-dev-client": "~4.0.27",
- "expo-font": "^12.0.10",
- "expo-status-bar": "~1.12.1",
- "expo-updates": "~0.25.25",
- "html-entities": "^2.5.2",
- "react": "18.2.0",
- "react-native": "0.74.5",
- "react-native-chart-kit": "^6.12.0",
- "react-native-circular-progress": "^1.4.0",
- "react-native-gesture-handler": "~2.16.1",
- "react-native-linear-gradient": "^2.8.3",
- "react-native-masonry-list": "^2.16.2",
- "react-native-reanimated": "~3.10.1",
- "react-native-reanimated-carousel": "^3.5.1",
- "react-native-safe-area-context": "4.10.5",
- "react-native-screens": "3.31.1",
- "react-native-snap-carousel": "^3.9.1",
- "react-native-svg": "^15.2.0",
- "react-native-switch-selector": "^2.3.0",
- "react-native-track-player": "^4.1.1",
- "react-native-vector-icons": "^10.1.0",
- "rn-circular-slider": "^1.1.0"
- },
- "devDependencies": {
- "@babel/core": "^7.20.0",
- "@types/react": "~18.2.79",
- "@types/react-native-vector-icons": "^6.4.18"
- },
- "private": true
+ "name": "lissen-mobile",
+ "version": "0.1.4",
+ "main": "./src/index.js",
+ "repository": {
+ "url": "https://github.com/0x0is1/lissen-mobile"
+ },
+ "scripts": {
+ "start": "expo start",
+ "android": "expo run:android",
+ "ios": "expo run:ios",
+ "web": "expo start --web"
+ },
+ "dependencies": {
+ "@react-native-async-storage/async-storage": "1.23.1",
+ "@react-native-community/datetimepicker": "8.0.1",
+ "@react-native-community/progress-bar-android": "^1.0.5",
+ "@react-native-community/slider": "^4.5.2",
+ "@react-native-picker/picker": "2.7.5",
+ "@react-native-seoul/masonry-list": "^1.4.2",
+ "@react-navigation/drawer": "^6.7.2",
+ "@react-navigation/native": "^6.1.18",
+ "@react-navigation/stack": "^6.4.1",
+ "axios": "^1.7.3",
+ "expo": "~51.0.34",
+ "expo-dev-client": "~4.0.27",
+ "expo-font": "^12.0.10",
+ "expo-status-bar": "~1.12.1",
+ "expo-updates": "~0.25.25",
+ "html-entities": "^2.5.2",
+ "react": "18.2.0",
+ "react-native": "0.74.5",
+ "react-native-chart-kit": "^6.12.0",
+ "react-native-circular-progress": "^1.4.0",
+ "react-native-gesture-handler": "~2.16.1",
+ "react-native-linear-gradient": "^2.8.3",
+ "react-native-masonry-list": "^2.16.2",
+ "react-native-reanimated": "~3.10.1",
+ "react-native-reanimated-carousel": "^3.5.1",
+ "react-native-safe-area-context": "4.10.5",
+ "react-native-screens": "3.31.1",
+ "react-native-snap-carousel": "^3.9.1",
+ "react-native-svg": "^15.2.0",
+ "react-native-switch-selector": "^2.3.0",
+ "react-native-track-player": "^4.1.1",
+ "react-native-vector-icons": "^10.1.0",
+ "rn-circular-slider": "^1.1.0"
+ },
+ "devDependencies": {
+ "@babel/core": "^7.20.0",
+ "@types/react": "~18.2.79",
+ "@types/react-native-vector-icons": "^6.4.18"
+ },
+ "private": true
}
diff --git a/src/App.js b/src/App.js
index 217d94f..e1423a2 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,50 +1,68 @@
-import React, { useEffect, useState } from 'react';
-import { NavigationContainer } from '@react-navigation/native';
-import { createStackNavigator } from '@react-navigation/stack';
-import PlayerScreen from './screens/PlayerScreen/PlayerScreen';
-import { StatusBar } from 'expo-status-bar';
-import { PlayerProvider } from './contexts/PlayerContext';
-import AlbumsScreen from './screens/AlbumsScreen/AlbumsScreen';
+import React, { useEffect, useState } from "react";
+import { NavigationContainer } from "@react-navigation/native";
+import { createStackNavigator } from "@react-navigation/stack";
+import PlayerScreen from "./screens/PlayerScreen/PlayerScreen";
+import { StatusBar } from "expo-status-bar";
+import { PlayerProvider } from "./contexts/PlayerContext";
+import AlbumsScreen from "./screens/AlbumsScreen/AlbumsScreen";
import setupPlayer from "./utils/setupPlayer";
-import TrackPlayer from 'react-native-track-player';
-import SearchScreen from './screens/SearchScreen/SearchScreen';
-import DashboardScreen from './screens/DashboardScreen/DashboardScreen';
-import AlbumViewerScreen from './screens/AlbumViewerScreen/AlbumViewerScreen';
-import Constants from './constants/constants';
+import TrackPlayer from "react-native-track-player";
+import SearchScreen from "./screens/SearchScreen/SearchScreen";
+import DashboardScreen from "./screens/DashboardScreen/DashboardScreen";
+import AlbumViewerScreen from "./screens/AlbumViewerScreen/AlbumViewerScreen";
+import Constants from "./constants/constants";
const Stack = createStackNavigator();
const constants = new Constants();
export default function App() {
- const [playerInitialized, setPlayerInitialized] = useState(false);
+ const [playerInitialized, setPlayerInitialized] = useState(false);
- useEffect(() => {
- const initializePlayer = async () => {
- try {
- if (!playerInitialized) {
- await setupPlayer();
- setPlayerInitialized(true);
- return async () => await TrackPlayer.destroy();
- }
- } catch (error) {
- console.error('Error setting up player', error);
- }
- };
- initializePlayer();
- }, [playerInitialized]);
+ useEffect(() => {
+ const initializePlayer = async () => {
+ try {
+ if (!playerInitialized) {
+ await setupPlayer();
+ setPlayerInitialized(true);
+ return async () => await TrackPlayer.destroy();
+ }
+ } catch (error) {
+ console.error("Error setting up player", error);
+ }
+ };
+ initializePlayer();
+ }, [playerInitialized]);
- return (
-
-
-
-
-
-
-
-
-
-
-
-
- );
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ );
}
diff --git a/src/constants/constants.js b/src/constants/constants.js
index 2525802..091600f 100644
--- a/src/constants/constants.js
+++ b/src/constants/constants.js
@@ -1,34 +1,33 @@
export default class Constants {
- constructor(){
- this.screenRoutes = {
- PLAYERSCREEN: 'PlayerScreen',
- ALBUMSCREEN: 'AlbumsScreen',
- SEARCHSCREEN: 'SearchScreen',
- DASHBOARDSCREEN: 'DashboardScreen',
- ALBUMVIEWERSCREEN: 'AlbumViewerScreen'
- }
+ constructor() {
+ this.screenRoutes = {
+ PLAYERSCREEN: "PlayerScreen",
+ ALBUMSCREEN: "AlbumsScreen",
+ SEARCHSCREEN: "SearchScreen",
+ DASHBOARDSCREEN: "DashboardScreen",
+ ALBUMVIEWERSCREEN: "AlbumViewerScreen",
+ };
- this.drawerRoutes = {
- ALBUMSCREEN: 'AlbumsScreen',
- LIBRARYSCREEN: 'LibraryScreen',
- DOWNLOADSCREEN: 'DownloadsScreen',
- SETTINGSCREEN: 'SettingsScreen',
- SEARCHSCREEN: 'SearchScreen',
- ABOUTSCREEN: 'AboutScreen',
- PLAYERSCREEN: 'PlayerScreen',
- VERSIONSCREEN: 'VersionScreen'
- }
-
- this.drawerTitles = {
- ALBUM: 'Home',
- LIBRARY: 'Library',
- DOWNLOADS: 'Downloads',
- SETTINGS: 'Settings',
- SEARCH: 'Search',
- ABOUT: 'About',
- PLAYER: 'Player',
- VERSION: 'Version'
- }
+ this.drawerRoutes = {
+ ALBUMSCREEN: "AlbumsScreen",
+ LIBRARYSCREEN: "LibraryScreen",
+ DOWNLOADSCREEN: "DownloadsScreen",
+ SETTINGSCREEN: "SettingsScreen",
+ SEARCHSCREEN: "SearchScreen",
+ ABOUTSCREEN: "AboutScreen",
+ PLAYERSCREEN: "PlayerScreen",
+ VERSIONSCREEN: "VersionScreen",
+ };
- }
-}
\ No newline at end of file
+ this.drawerTitles = {
+ ALBUM: "Home",
+ LIBRARY: "Library",
+ DOWNLOADS: "Downloads",
+ SETTINGS: "Settings",
+ SEARCH: "Search",
+ ABOUT: "About",
+ PLAYER: "Player",
+ VERSION: "Version",
+ };
+ }
+}
diff --git a/src/contexts/PlayerContext.jsx b/src/contexts/PlayerContext.jsx
index 7c1d825..7db9ff7 100644
--- a/src/contexts/PlayerContext.jsx
+++ b/src/contexts/PlayerContext.jsx
@@ -1,187 +1,196 @@
-import React, { createContext, useState, useRef } from 'react';
-import { Animated, PanResponder } from 'react-native';
-import ServiceProvider from '../libs/APIParser';
-import TrackPlayer, { Event, State, useTrackPlayerEvents } from "react-native-track-player";
-import { decode } from 'html-entities';
+import React, { createContext, useState, useRef } from "react";
+import { Animated, PanResponder } from "react-native";
+import ServiceProvider from "../libs/APIParser";
+import TrackPlayer, {
+ Event,
+ State,
+ useTrackPlayerEvents,
+} from "react-native-track-player";
+import { decode } from "html-entities";
export const PlayerContext = createContext();
export const PlayerProvider = ({ children }) => {
- const [albumMode, setAlbumMode] = useState(true);
- const [playingIndex, setPlayingIndex] = useState(0);
- const [onShuffle, setOnShuffle] = useState(false);
- const [playState, setPlayState] = useState(State.None);
- const [likedList, setLikedList] = useState({});
- const [isTrackAddingCompleted, setIsTrackAddingCompleted] = useState(true);
- const serviceProvider = new ServiceProvider();
-
- const heightAnim = useRef(new Animated.Value(350)).current;
- const progressBarOpacity = useRef(new Animated.Value(0)).current;
- const albumItemsOpacity = useRef(new Animated.Value(1)).current;
- const footerHeightAnim = useRef(new Animated.Value(80)).current;
-
- const formatTime = (totalSeconds) => {
- const minutes = Math.floor(totalSeconds / 60);
- const seconds = Math.floor(totalSeconds % 60);
- const formattedSeconds = seconds < 10 ? `0${seconds}` : seconds;
- return `${minutes}:${formattedSeconds}`;
- };
-
- const panResponder = useRef(
- PanResponder.create({
- onMoveShouldSetPanResponder: (evt, gestureState) => Math.abs(gestureState.dy) > 20,
- onPanResponderMove: (evt, gestureState) => {
- setAlbumMode(gestureState.dy <= -20);
- },
- })
- ).current;
-
- const addTracks = async (_playList, addAtIndex=-1) => {
- setIsTrackAddingCompleted(false);
- for (const [index, item] of _playList.items.entries()) {
- const reparsedItem = {
- id: item.id,
- url: item.playUrl,
- title: decode(item.songName),
- artwork: item.songCover,
- artist: item.artistName || _playList.artistName,
- isLiveStream: true,
- albumName: _playList.albumName,
- duration: item.duration
- };
- if(addAtIndex!==-1){
- await TrackPlayer.add(reparsedItem, addAtIndex);
- } else{
- await TrackPlayer.add(reparsedItem);
- }
- // await TrackPlayer.seekTo(0);
- // setPlayingIndex(0);
- }
- setIsTrackAddingCompleted(true);
- };
-
- const playurlOverrider = async (index) => {
- const trackPlayerQueue = await TrackPlayer.getQueue()
- if (!trackPlayerQueue[index].url.includes("https://")) {
- trackPlayerQueue[index].url = await serviceProvider.playByMediaUrl(trackPlayerQueue[index]?.url)
- }
- await TrackPlayer.reset();
- await TrackPlayer.add(trackPlayerQueue);
- await TrackPlayer.skip(index);
- await TrackPlayer.play();
- setPlayingIndex(index);
- };
-
- const nextActionOverrider = async () => {
- const _playList = await TrackPlayer.getQueue()
- const repeatMode = await TrackPlayer.getRepeatMode();
- if (onShuffle) {
- await playurlOverrider(Math.floor(Math.random() * _playList.length));
- }
- else if (repeatMode !== 0) {
- await playurlOverrider(playingIndex);
- }
- else {
- await playurlOverrider(playingIndex < _playList.length - 1 ? playingIndex + 1 : 0)
- }
- }
-
- const previousActionOverrider = async () => {
- const _playList = await TrackPlayer.getQueue()
- const repeatMode = await TrackPlayer.getRepeatMode();
- if (onShuffle) {
- await playurlOverrider(Math.floor(Math.random() * _playList.length));
- }
- else if (repeatMode !== 0) {
- await playurlOverrider(playingIndex);
- }
- else {
- await playurlOverrider(playingIndex > 0 ? playingIndex - 1 : _playList.length - 1)
- }
- }
-
- useTrackPlayerEvents([Event.PlaybackState], async (event) => {
- setPlayState(event.state);
- })
-
- useTrackPlayerEvents([Event.PlaybackProgressUpdated], async (event) => {
- if (event.duration - event.position < 5) {
- await nextActionOverrider();
- }
- const timeLeft = event.duration - event.position;
- const timeBuffered = event.buffered - event.position;
-
- if ((timeLeft > 5) && (timeBuffered < 5)) {
- await TrackPlayer.pause();
- } else {
- await TrackPlayer.play();
- }
- })
-
- // useTrackPlayerEvents([Event.PlaybackActiveTrackChanged], async (event) => {
- // if (event.type === Event.PlaybackActiveTrackChanged && event.index === undefined) {
- // await playurlOverrider(0);
- // return;
- // }
-
- // if (event.type === Event.PlaybackActiveTrackChanged && event.index !== null && event.index !== playingIndex) {
- // console.log(`Track changed to index: ${event.index}`);
- // await playurlOverrider(event.index);
- // }
- // });
-
- useTrackPlayerEvents([Event.PlaybackQueueEnded], async () => {
- const repeatMode = await TrackPlayer.getRepeatMode();
-
- if (repeatMode === 0) {
- await nextActionOverrider();
- } else {
- await TrackPlayer.seekTo(0);
- await playurlOverrider(playingIndex);
- }
- });
-
- useTrackPlayerEvents([Event.RemoteNext], async () => {
- await nextActionOverrider();
- });
-
- useTrackPlayerEvents([Event.RemotePrevious], async () => {
- await previousActionOverrider();
- });
-
- useTrackPlayerEvents([Event.RemotePlay], async () => {
- await playurlOverrider(playingIndex);
- });
-
- useTrackPlayerEvents([Event.RemoteSeek], async (event) => {
- if (event.position !== undefined) {
- await TrackPlayer.seekTo(event.position);
- }
- });
-
- return (
-
- {children}
-
- );
+ const [albumMode, setAlbumMode] = useState(true);
+ const [playingIndex, setPlayingIndex] = useState(0);
+ const [onShuffle, setOnShuffle] = useState(false);
+ const [playState, setPlayState] = useState(State.None);
+ const [likedList, setLikedList] = useState({});
+ const [isTrackAddingCompleted, setIsTrackAddingCompleted] = useState(true);
+ const serviceProvider = new ServiceProvider();
+
+ const heightAnim = useRef(new Animated.Value(350)).current;
+ const progressBarOpacity = useRef(new Animated.Value(0)).current;
+ const albumItemsOpacity = useRef(new Animated.Value(1)).current;
+ const footerHeightAnim = useRef(new Animated.Value(80)).current;
+
+ const formatTime = (totalSeconds) => {
+ const minutes = Math.floor(totalSeconds / 60);
+ const seconds = Math.floor(totalSeconds % 60);
+ const formattedSeconds = seconds < 10 ? `0${seconds}` : seconds;
+ return `${minutes}:${formattedSeconds}`;
+ };
+
+ const panResponder = useRef(
+ PanResponder.create({
+ onMoveShouldSetPanResponder: (evt, gestureState) =>
+ Math.abs(gestureState.dy) > 20,
+ onPanResponderMove: (evt, gestureState) => {
+ setAlbumMode(gestureState.dy <= -20);
+ },
+ }),
+ ).current;
+
+ const addTracks = async (_playList, addAtIndex = -1) => {
+ setIsTrackAddingCompleted(false);
+ for (const [index, item] of _playList.items.entries()) {
+ const reparsedItem = {
+ id: item.id,
+ url: item.playUrl,
+ title: decode(item.songName),
+ artwork: item.songCover,
+ artist: item.artistName || _playList.artistName,
+ isLiveStream: true,
+ albumName: _playList.albumName,
+ duration: item.duration,
+ };
+ if (addAtIndex !== -1) {
+ await TrackPlayer.add(reparsedItem, addAtIndex);
+ } else {
+ await TrackPlayer.add(reparsedItem);
+ }
+ // await TrackPlayer.seekTo(0);
+ // setPlayingIndex(0);
+ }
+ setIsTrackAddingCompleted(true);
+ };
+
+ const playurlOverrider = async (index) => {
+ const trackPlayerQueue = await TrackPlayer.getQueue();
+ if (!trackPlayerQueue[index].url.includes("https://")) {
+ trackPlayerQueue[index].url = await serviceProvider.playByMediaUrl(
+ trackPlayerQueue[index]?.url,
+ );
+ }
+ await TrackPlayer.reset();
+ await TrackPlayer.add(trackPlayerQueue);
+ await TrackPlayer.skip(index);
+ await TrackPlayer.play();
+ setPlayingIndex(index);
+ };
+
+ const nextActionOverrider = async () => {
+ const _playList = await TrackPlayer.getQueue();
+ const repeatMode = await TrackPlayer.getRepeatMode();
+ if (onShuffle) {
+ await playurlOverrider(Math.floor(Math.random() * _playList.length));
+ } else if (repeatMode !== 0) {
+ await playurlOverrider(playingIndex);
+ } else {
+ await playurlOverrider(
+ playingIndex < _playList.length - 1 ? playingIndex + 1 : 0,
+ );
+ }
+ };
+
+ const previousActionOverrider = async () => {
+ const _playList = await TrackPlayer.getQueue();
+ const repeatMode = await TrackPlayer.getRepeatMode();
+ if (onShuffle) {
+ await playurlOverrider(Math.floor(Math.random() * _playList.length));
+ } else if (repeatMode !== 0) {
+ await playurlOverrider(playingIndex);
+ } else {
+ await playurlOverrider(
+ playingIndex > 0 ? playingIndex - 1 : _playList.length - 1,
+ );
+ }
+ };
+
+ useTrackPlayerEvents([Event.PlaybackState], async (event) => {
+ setPlayState(event.state);
+ });
+
+ useTrackPlayerEvents([Event.PlaybackProgressUpdated], async (event) => {
+ if (event.duration - event.position < 5) {
+ await nextActionOverrider();
+ }
+ const timeLeft = event.duration - event.position;
+ const timeBuffered = event.buffered - event.position;
+
+ if (timeLeft > 5 && timeBuffered < 5) {
+ await TrackPlayer.pause();
+ } else {
+ await TrackPlayer.play();
+ }
+ });
+
+ // useTrackPlayerEvents([Event.PlaybackActiveTrackChanged], async (event) => {
+ // if (event.type === Event.PlaybackActiveTrackChanged && event.index === undefined) {
+ // await playurlOverrider(0);
+ // return;
+ // }
+
+ // if (event.type === Event.PlaybackActiveTrackChanged && event.index !== null && event.index !== playingIndex) {
+ // console.log(`Track changed to index: ${event.index}`);
+ // await playurlOverrider(event.index);
+ // }
+ // });
+
+ useTrackPlayerEvents([Event.PlaybackQueueEnded], async () => {
+ const repeatMode = await TrackPlayer.getRepeatMode();
+
+ if (repeatMode === 0) {
+ await nextActionOverrider();
+ } else {
+ await TrackPlayer.seekTo(0);
+ await playurlOverrider(playingIndex);
+ }
+ });
+
+ useTrackPlayerEvents([Event.RemoteNext], async () => {
+ await nextActionOverrider();
+ });
+
+ useTrackPlayerEvents([Event.RemotePrevious], async () => {
+ await previousActionOverrider();
+ });
+
+ useTrackPlayerEvents([Event.RemotePlay], async () => {
+ await playurlOverrider(playingIndex);
+ });
+
+ useTrackPlayerEvents([Event.RemoteSeek], async (event) => {
+ if (event.position !== undefined) {
+ await TrackPlayer.seekTo(event.position);
+ }
+ });
+
+ return (
+
+ {children}
+
+ );
};
diff --git a/src/index.js b/src/index.js
index 3a62aa7..9af1bee 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,7 +1,7 @@
-import registerRootComponent from 'expo/build/launch/registerRootComponent';
-import TrackPlayer from 'react-native-track-player'
-import { RNTPService } from './utils/RNTPService';
-import App from './App';
+import registerRootComponent from "expo/build/launch/registerRootComponent";
+import TrackPlayer from "react-native-track-player";
+import { RNTPService } from "./utils/RNTPService";
+import App from "./App";
registerRootComponent(App);
-TrackPlayer.registerPlaybackService(() => RNTPService)
\ No newline at end of file
+TrackPlayer.registerPlaybackService(() => RNTPService);
diff --git a/src/libs/APIParser.js b/src/libs/APIParser.js
index e26df6f..4f629f9 100644
--- a/src/libs/APIParser.js
+++ b/src/libs/APIParser.js
@@ -1,120 +1,168 @@
import { ToastAndroid } from "react-native";
import { Buffer } from "buffer";
class ServiceProvider {
- constructor() {
- this.baseURL = Buffer.from('aHR0cHM6Ly93d3cuamlvc2Fhdm4uY29tL2FwaS5waHA/X19jYWxsPQ==', 'base64').toString('utf-8');
- }
-
- async request(dir) {
- try {
- const response = await fetch(`${this.baseURL}${dir}`, {
- headers: {
- "Accept": "application/json, text/plain, */*",
- "Cookie": "B=ffe5a4383fa531151b96f993e2586d32; CT=MjgzNjUxNTc3; DL=english; L=hindi; geo=152.58.76.33%2CIN%2CPunjab%2CLudhiana%2C141007; mm_latlong=31.0048%2C75.9463; CH=G03%2CA07%2CO00%2CL03"
- }
- });
-
- const data = await response.json();
- return data;
- } catch (error) {
- ToastAndroid.show(error, ToastAndroid.LONG);
- }
- }
-
- async getLaunchData() {
- const data = await this.request(`webapi.getLaunchData&api_version=4&_format=json&_marker=0&ctx=web6dot0`);
- return data;
- }
-
- async getArtist(artist_id, song_count) {
- const data = await this.request(`artist.getArtistPageDetails&artistId=${artist_id}&type=songs&n_song=${song_count}&category=&sort_order=&_format=json&ctx=web6dot0`);
- return data;
- }
-
- async getTopSearches() {
- const data = await this.request(`content.getTopSearches&ctx=web6dot0&api_version=4&_format=json&_marker=0`);
- return data;
- }
-
- async getAlbums(count, page) {
- const data = await this.request(`content.getAlbums&n=${count}&p=${page}&api_version=4&_format=json&_marker=0&n=50&p=1&ctx=web6dot0`);
- return data;
- }
-
- async getCharts() {
- const data = await this.request(`content.getCharts&api_version=4&_format=json&_marker=0&ctx=web6dot0`);
- return data;
- }
-
- async getFeaturedPlaylists(count, page) {
- const data = await this.request(`content.getFeaturedPlaylists&fetch_from_serialized_files=true&p=${page}&n=${count}&_format=json&_marker=0&ctx=web6dot0`);
- return data;
- }
-
- async getTopShows(count, page) {
- const data = await this.request(`content.getTopShows&n=${count}&p=${page}&_format=json&_marker=0&ctx=web6dot0`);
- return data;
- }
-
- async getTopArtists() {
- const data = await this.request(`social.getTopArtists&_format=json&_marker=0&ctx=web6dot0`);
- return data;
- }
-
- async getFeaturedStations() {
- const data = await this.request(`webradio.getFeaturedStations&api_version=4&_format=json&_marker=0&ctx=web6dot0`);
- return data;
- }
-
- async getPlaylistById(id) {
- const data = await this.request(`playlist.getDetails&listid=${id}&_format=json`);
- return data;
- }
-
- async getStationById(name, count = 20) {
- const station_id = await this.request(`webradio.createFeaturedStation&language=hindi&pid=&query=&name=${name.replaceAll(" ", "+")}&mode=&artistid=&_format=json&_marker=0&ctx=web6dot0`);
- const data = await this.request(`webradio.getSong&stationid=${station_id.stationid}&k=${count}&next=1&_format=json&_marker=0&ctx=web6dot0&api_version=4`);
- return data;
- }
-
- async getAlbumById(album_id) {
- var data = await this.request(`webapi.get&token=${album_id}&type=album&includeMetaTags=0&ctx=web6dot0&api_version=4&_format=json&_marker=0`);
- return data;
- }
-
- async getSongById(id) {
- const data = await this.request(`song.getDetails&cc=in&_marker=0%3F_marker%3D0&_format=json&pids=${id}`);
- return data[id];
- }
-
- async getLyrics(id) {
- const data = await this.request(`lyrics.getLyrics&lyrics_id=${id}&ctx=web6dot0&api_version=4&_format=json&_marker=0`)
- return data;
- }
-
- async getSearch(query, page, type) {
- var command = ["getPlaylistResults", "getResults", "getAlbumResults", `getMoreResults¶ms=%7B%22type%22:%22podcasts%22%7D&query=${query.replaceAll(" ", "+")}`, "getArtistResults"][type]
- const data = await this.request(`search.${command}&p=${page}&q=${query}&_format=json&_marker=0&api_version=4&ctx=web6dot0&n=50`)
- return data;
- }
-
- async playById(id) {
- const songDetails = await this.request(`song.getDetails&cc=in&_marker=0%3F_marker%3D0&_format=json&pids=${id}`);
- const token = songDetails[id].encrypted_media_url;
- var authTokenData = await this.request(`song.generateAuthToken&url=${encodeURIComponent(token)}&bitrate=160&api_version=4&_format=json&ctx=web6dot0&_marker=0`);
- authTokenData.auth_url = authTokenData.auth_url.replace("ac.cf.", "aac.")
- const result = {
- ...songDetails[id],
- "streamurl": authTokenData
- };
-
- return result;
- }
-
- async playByMediaUrl(mediaUrl) {
- var authTokenData = await this.request(`song.generateAuthToken&url=${encodeURIComponent(mediaUrl)}&bitrate=160&api_version=4&_format=json&ctx=web6dot0&_marker=0`);
- const authUrl = await authTokenData.auth_url.replace("ac.cf.", "aac.");
- return authUrl
- }
+ constructor() {
+ this.baseURL = Buffer.from(
+ "aHR0cHM6Ly93d3cuamlvc2Fhdm4uY29tL2FwaS5waHA/X19jYWxsPQ==",
+ "base64",
+ ).toString("utf-8");
+ }
+
+ async request(dir) {
+ try {
+ const response = await fetch(`${this.baseURL}${dir}`, {
+ headers: {
+ Accept: "application/json, text/plain, */*",
+ Cookie:
+ "B=ffe5a4383fa531151b96f993e2586d32; CT=MjgzNjUxNTc3; DL=english; L=hindi; geo=152.58.76.33%2CIN%2CPunjab%2CLudhiana%2C141007; mm_latlong=31.0048%2C75.9463; CH=G03%2CA07%2CO00%2CL03",
+ },
+ });
+
+ const data = await response.json();
+ return data;
+ } catch (error) {
+ ToastAndroid.show(error, ToastAndroid.LONG);
+ }
+ }
+
+ async getLaunchData() {
+ const data = await this.request(
+ `webapi.getLaunchData&api_version=4&_format=json&_marker=0&ctx=web6dot0`,
+ );
+ return data;
+ }
+
+ async getArtist(artist_id, song_count) {
+ const data = await this.request(
+ `artist.getArtistPageDetails&artistId=${artist_id}&type=songs&n_song=${song_count}&category=&sort_order=&_format=json&ctx=web6dot0`,
+ );
+ return data;
+ }
+
+ async getTopSearches() {
+ const data = await this.request(
+ `content.getTopSearches&ctx=web6dot0&api_version=4&_format=json&_marker=0`,
+ );
+ return data;
+ }
+
+ async getAlbums(count, page) {
+ const data = await this.request(
+ `content.getAlbums&n=${count}&p=${page}&api_version=4&_format=json&_marker=0&n=50&p=1&ctx=web6dot0`,
+ );
+ return data;
+ }
+
+ async getCharts() {
+ const data = await this.request(
+ `content.getCharts&api_version=4&_format=json&_marker=0&ctx=web6dot0`,
+ );
+ return data;
+ }
+
+ async getFeaturedPlaylists(count, page) {
+ const data = await this.request(
+ `content.getFeaturedPlaylists&fetch_from_serialized_files=true&p=${page}&n=${count}&_format=json&_marker=0&ctx=web6dot0`,
+ );
+ return data;
+ }
+
+ async getTopShows(count, page) {
+ const data = await this.request(
+ `content.getTopShows&n=${count}&p=${page}&_format=json&_marker=0&ctx=web6dot0`,
+ );
+ return data;
+ }
+
+ async getTopArtists() {
+ const data = await this.request(
+ `social.getTopArtists&_format=json&_marker=0&ctx=web6dot0`,
+ );
+ return data;
+ }
+
+ async getFeaturedStations() {
+ const data = await this.request(
+ `webradio.getFeaturedStations&api_version=4&_format=json&_marker=0&ctx=web6dot0`,
+ );
+ return data;
+ }
+
+ async getPlaylistById(id) {
+ const data = await this.request(
+ `playlist.getDetails&listid=${id}&_format=json`,
+ );
+ return data;
+ }
+
+ async getStationById(name, count = 20) {
+ const station_id = await this.request(
+ `webradio.createFeaturedStation&language=hindi&pid=&query=&name=${name.replaceAll(" ", "+")}&mode=&artistid=&_format=json&_marker=0&ctx=web6dot0`,
+ );
+ const data = await this.request(
+ `webradio.getSong&stationid=${station_id.stationid}&k=${count}&next=1&_format=json&_marker=0&ctx=web6dot0&api_version=4`,
+ );
+ return data;
+ }
+
+ async getAlbumById(album_id) {
+ var data = await this.request(
+ `webapi.get&token=${album_id}&type=album&includeMetaTags=0&ctx=web6dot0&api_version=4&_format=json&_marker=0`,
+ );
+ return data;
+ }
+
+ async getSongById(id) {
+ const data = await this.request(
+ `song.getDetails&cc=in&_marker=0%3F_marker%3D0&_format=json&pids=${id}`,
+ );
+ return data[id];
+ }
+
+ async getLyrics(id) {
+ const data = await this.request(
+ `lyrics.getLyrics&lyrics_id=${id}&ctx=web6dot0&api_version=4&_format=json&_marker=0`,
+ );
+ return data;
+ }
+
+ async getSearch(query, page, type) {
+ var command = [
+ "getPlaylistResults",
+ "getResults",
+ "getAlbumResults",
+ `getMoreResults¶ms=%7B%22type%22:%22podcasts%22%7D&query=${query.replaceAll(" ", "+")}`,
+ "getArtistResults",
+ ][type];
+ const data = await this.request(
+ `search.${command}&p=${page}&q=${query}&_format=json&_marker=0&api_version=4&ctx=web6dot0&n=50`,
+ );
+ return data;
+ }
+
+ async playById(id) {
+ const songDetails = await this.request(
+ `song.getDetails&cc=in&_marker=0%3F_marker%3D0&_format=json&pids=${id}`,
+ );
+ const token = songDetails[id].encrypted_media_url;
+ var authTokenData = await this.request(
+ `song.generateAuthToken&url=${encodeURIComponent(token)}&bitrate=160&api_version=4&_format=json&ctx=web6dot0&_marker=0`,
+ );
+ authTokenData.auth_url = authTokenData.auth_url.replace("ac.cf.", "aac.");
+ const result = {
+ ...songDetails[id],
+ streamurl: authTokenData,
+ };
+
+ return result;
+ }
+
+ async playByMediaUrl(mediaUrl) {
+ var authTokenData = await this.request(
+ `song.generateAuthToken&url=${encodeURIComponent(mediaUrl)}&bitrate=160&api_version=4&_format=json&ctx=web6dot0&_marker=0`,
+ );
+ const authUrl = await authTokenData.auth_url.replace("ac.cf.", "aac.");
+ return authUrl;
+ }
}
-export default ServiceProvider
\ No newline at end of file
+export default ServiceProvider;
diff --git a/src/screens/AboutScreen/AboutScreen.jsx b/src/screens/AboutScreen/AboutScreen.jsx
index 2cc60c4..2f5847b 100644
--- a/src/screens/AboutScreen/AboutScreen.jsx
+++ b/src/screens/AboutScreen/AboutScreen.jsx
@@ -1,14 +1,14 @@
-import { StyleSheet, Text, View } from 'react-native'
-import React from 'react'
+import { StyleSheet, Text, View } from "react-native";
+import React from "react";
const AboutScreen = () => {
- return (
-
- AboutScreen
-
- )
-}
+ return (
+
+ AboutScreen
+
+ );
+};
-export default AboutScreen
+export default AboutScreen;
-const styles = StyleSheet.create({})
\ No newline at end of file
+const styles = StyleSheet.create({});
diff --git a/src/screens/AlbumViewerScreen/AlbumViewerScreen.jsx b/src/screens/AlbumViewerScreen/AlbumViewerScreen.jsx
index 7c8e7a2..a02c114 100644
--- a/src/screens/AlbumViewerScreen/AlbumViewerScreen.jsx
+++ b/src/screens/AlbumViewerScreen/AlbumViewerScreen.jsx
@@ -1,75 +1,95 @@
-import {
- StyleSheet,
- View,
-} from "react-native";
+import { StyleSheet, View } from "react-native";
import React, { useContext, useEffect, useState } from "react";
import { useRoute } from "@react-navigation/native";
-import { PlayerContext } from '../../contexts/PlayerContext';
+import { PlayerContext } from "../../contexts/PlayerContext";
import PlayerFooter from "./components/PlayerFooter";
import PlayerBanner from "./components/PlayerBanner";
import AlbumItemsContainer from "./components/AlbumItemsContainer";
import ProgressBarContainer from "./components/ProgressBarContainer";
import DurationText from "./components/DurationText";
-import TrackPlayer, { Event, useTrackPlayerEvents } from 'react-native-track-player'
+import TrackPlayer, {
+ Event,
+ useTrackPlayerEvents,
+} from "react-native-track-player";
import UtilityButtons from "./components/UtilityButtons";
import CustomStatusBar from "../PlayerScreen/components/CustomStatusBar";
const AlbumViewerScreen = () => {
- const {
- albumMode, playingIndex, onShuffle,
- setOnShuffle, playState, playurlOverrider,
- nextActionOverrider, previousActionOverrider,
- isTrackAddingCompleted
- } = useContext(PlayerContext);
- const route = useRoute()
- const trackList = route.params.data
- const [currentDuration, setCurrentDuration] = useState(0);
- const [totalDuration, setTotalDuration] = useState(0);
- const [queue, setQueue] = useState(null);
+ const {
+ albumMode,
+ playingIndex,
+ onShuffle,
+ setOnShuffle,
+ playState,
+ playurlOverrider,
+ nextActionOverrider,
+ previousActionOverrider,
+ isTrackAddingCompleted,
+ } = useContext(PlayerContext);
+ const route = useRoute();
+ const trackList = route.params.data;
+ const [currentDuration, setCurrentDuration] = useState(0);
+ const [totalDuration, setTotalDuration] = useState(0);
+ const [queue, setQueue] = useState(null);
- useEffect(() => {
- const fetchQueue = async () => {
- const queueres = await TrackPlayer.getQueue();
- setQueue(queueres);
- };
- isTrackAddingCompleted && fetchQueue();
- }, [isTrackAddingCompleted]);
+ useEffect(() => {
+ const fetchQueue = async () => {
+ const queueres = await TrackPlayer.getQueue();
+ setQueue(queueres);
+ };
+ isTrackAddingCompleted && fetchQueue();
+ }, [isTrackAddingCompleted]);
- useTrackPlayerEvents([Event.PlaybackProgressUpdated], async (event) => {
- setTotalDuration(event.duration);
- setCurrentDuration(event.position);
- });
-
- return (
- trackList && queue &&
-
- {
- albumMode
- ? (
- <>
-
-
-
- >
- ) : (
- <>
-
-
-
-
- >
- )
- }
-
- );
+ useTrackPlayerEvents([Event.PlaybackProgressUpdated], async (event) => {
+ setTotalDuration(event.duration);
+ setCurrentDuration(event.position);
+ });
+
+ return (
+ trackList &&
+ queue && (
+
+
+ {albumMode ? (
+ <>
+
+
+
+ >
+ ) : (
+ <>
+
+
+
+
+ >
+ )}
+
+ )
+ );
};
const styles = StyleSheet.create({
- container: {
- flex: 1,
- alignItems: "center",
- backgroundColor: "#e7e9eb",
- },
+ container: {
+ flex: 1,
+ alignItems: "center",
+ backgroundColor: "#e7e9eb",
+ },
});
export default AlbumViewerScreen;
diff --git a/src/screens/AlbumViewerScreen/components/AlbumItemsContainer.jsx b/src/screens/AlbumViewerScreen/components/AlbumItemsContainer.jsx
index a4798fa..f6476ef 100644
--- a/src/screens/AlbumViewerScreen/components/AlbumItemsContainer.jsx
+++ b/src/screens/AlbumViewerScreen/components/AlbumItemsContainer.jsx
@@ -1,86 +1,91 @@
-import { Animated, StyleSheet, Text, View } from 'react-native';
-import React, { useContext, useEffect } from 'react';
-import { FlatList, TouchableOpacity } from 'react-native-gesture-handler';
-import { PlayerContext } from '../../../contexts/PlayerContext';
-import { Easing } from 'react-native-reanimated';
-import { decode } from 'html-entities';
+import { Animated, StyleSheet, Text, View } from "react-native";
+import React, { useContext, useEffect } from "react";
+import { FlatList, TouchableOpacity } from "react-native-gesture-handler";
+import { PlayerContext } from "../../../contexts/PlayerContext";
+import { Easing } from "react-native-reanimated";
+import { decode } from "html-entities";
const AlbumItemsContainer = ({ trackList, playurlOverrider, queue }) => {
- const { formatTime, albumItemsOpacity, albumMode, playingIndex, addTracks } = useContext(PlayerContext);
- useEffect(() => {
- Animated.timing(albumItemsOpacity, {
- toValue: albumMode ? 1 : 0,
- duration: 400,
- useNativeDriver: true,
- easing: Easing.ease,
- }).start();
- }, [albumMode]);
+ const { formatTime, albumItemsOpacity, albumMode, playingIndex, addTracks } =
+ useContext(PlayerContext);
+ useEffect(() => {
+ Animated.timing(albumItemsOpacity, {
+ toValue: albumMode ? 1 : 0,
+ duration: 400,
+ useNativeDriver: true,
+ easing: Easing.ease,
+ }).start();
+ }, [albumMode]);
- const onItemPlayPressed = async (index) => {
- const _trackList = {
- ...trackList,
- items: [
- trackList.items[index],
- ]
- };
- addTracks(_trackList, playingIndex);
- await playurlOverrider(playingIndex);
- };
+ const onItemPlayPressed = async (index) => {
+ const _trackList = {
+ ...trackList,
+ items: [trackList.items[index]],
+ };
+ addTracks(_trackList, playingIndex);
+ await playurlOverrider(playingIndex);
+ };
- const renderAlbumItems = ({ item, index }) => (
- onItemPlayPressed(index)}>
-
-
- {decode(item.songName).length > 30
- ? `${decode(item.songName).substring(0, 30)}...`
- : decode(item.songName)}
-
-
- {formatTime(item.duration)}
-
-
-
- );
+ const renderAlbumItems = ({ item, index }) => (
+ onItemPlayPressed(index)}>
+
+
+ {decode(item.songName).length > 30
+ ? `${decode(item.songName).substring(0, 30)}...`
+ : decode(item.songName)}
+
+
+ {formatTime(item.duration)}
+
+
+
+ );
- return (
-
- index.toString()}
- />
-
- );
+ return (
+
+ index.toString()}
+ />
+
+ );
};
export default AlbumItemsContainer;
const styles = StyleSheet.create({
- albumItems: {
- flexDirection: 'row',
- minWidth: '100%',
- alignItems: 'center',
- justifyContent: 'space-between',
- paddingVertical: 10,
- paddingHorizontal: 40,
- },
- albumItemsContainer: {
- maxHeight: 390,
- marginTop: 10,
- overflow: 'scroll',
- },
- songItem: {
- fontSize: 15,
- fontWeight: '500',
- },
+ albumItems: {
+ flexDirection: "row",
+ minWidth: "100%",
+ alignItems: "center",
+ justifyContent: "space-between",
+ paddingVertical: 10,
+ paddingHorizontal: 40,
+ },
+ albumItemsContainer: {
+ maxHeight: 390,
+ marginTop: 10,
+ overflow: "scroll",
+ },
+ songItem: {
+ fontSize: 15,
+ fontWeight: "500",
+ },
});
diff --git a/src/screens/AlbumViewerScreen/components/DurationText.jsx b/src/screens/AlbumViewerScreen/components/DurationText.jsx
index bc1dd95..a8daca1 100644
--- a/src/screens/AlbumViewerScreen/components/DurationText.jsx
+++ b/src/screens/AlbumViewerScreen/components/DurationText.jsx
@@ -1,22 +1,20 @@
-import { StyleSheet, Text } from 'react-native'
-import React, { useContext } from 'react'
-import { PlayerContext } from '../../../contexts/PlayerContext';
+import { StyleSheet, Text } from "react-native";
+import React, { useContext } from "react";
+import { PlayerContext } from "../../../contexts/PlayerContext";
-const DurationText = ({currentDuration}) => {
- const { formatTime } = useContext(PlayerContext);
- return (
- {formatTime(currentDuration)}
- )
-}
+const DurationText = ({ currentDuration }) => {
+ const { formatTime } = useContext(PlayerContext);
+ return {formatTime(currentDuration)};
+};
-export default DurationText
+export default DurationText;
const styles = StyleSheet.create({
- durationText: {
- position: "relative",
- fontSize: 16,
- color: "black",
- marginTop: 70,
- marginBottom: 100,
- },
-})
\ No newline at end of file
+ durationText: {
+ position: "relative",
+ fontSize: 16,
+ color: "black",
+ marginTop: 70,
+ marginBottom: 100,
+ },
+});
diff --git a/src/screens/AlbumViewerScreen/components/PlayerBanner.jsx b/src/screens/AlbumViewerScreen/components/PlayerBanner.jsx
index e25b1f3..7680b0c 100644
--- a/src/screens/AlbumViewerScreen/components/PlayerBanner.jsx
+++ b/src/screens/AlbumViewerScreen/components/PlayerBanner.jsx
@@ -1,104 +1,124 @@
-import { StyleSheet, Text, View, Animated, ImageBackground } from 'react-native';
-import React, { useEffect, useContext, useState } from 'react';
-import { PlayerContext } from '../../../contexts/PlayerContext';
-import { Easing } from 'react-native-reanimated';
-import { decode } from 'html-entities';
+import {
+ StyleSheet,
+ Text,
+ View,
+ Animated,
+ ImageBackground,
+} from "react-native";
+import React, { useEffect, useContext, useState } from "react";
+import { PlayerContext } from "../../../contexts/PlayerContext";
+import { Easing } from "react-native-reanimated";
+import { decode } from "html-entities";
const getDecodedText = (text, maxLength) => {
- const decodedText = decode(text || 'None');
- return decodedText.length > maxLength
- ? `${decodedText.substring(0, maxLength)}...`
- : decodedText;
+ const decodedText = decode(text || "None");
+ return decodedText.length > maxLength
+ ? `${decodedText.substring(0, maxLength)}...`
+ : decodedText;
};
const PlayerBanner = ({ playingIndex, playList }) => {
- const { albumMode, heightAnim, panResponder } = useContext(PlayerContext);
+ const { albumMode, heightAnim, panResponder } = useContext(PlayerContext);
- useEffect(() => {
- Animated.timing(heightAnim, {
- toValue: albumMode ? 350 : 500,
- duration: 400,
- useNativeDriver: false,
- easing: Easing.ease,
- }).start();
- }, [albumMode]);
+ useEffect(() => {
+ Animated.timing(heightAnim, {
+ toValue: albumMode ? 350 : 500,
+ duration: 400,
+ useNativeDriver: false,
+ easing: Easing.ease,
+ }).start();
+ }, [albumMode]);
- const getImageSource = (imagePath) => {
- if (typeof imagePath === 'string' && imagePath.startsWith('http')) {
- return { uri: imagePath };
- } else {
- return imagePath;
- }
- };
+ const getImageSource = (imagePath) => {
+ if (typeof imagePath === "string" && imagePath.startsWith("http")) {
+ return { uri: imagePath };
+ } else {
+ return imagePath;
+ }
+ };
- return (
- (playList) && (
-
-
-
-
-
- {albumMode
- ? getDecodedText(playList?.albumName || 'Unknown Album', 15)
- : getDecodedText(playList[playingIndex]?.title || 'Unknown Title', 15)}
-
-
- {getDecodedText(playList[playingIndex]?.artist || playList?.items?.[playingIndex]?.artistName || 'Unknown Artist', 15)}
-
-
- )
- );
+ return (
+ playList && (
+
+
+
+
+
+ {albumMode
+ ? getDecodedText(playList?.albumName || "Unknown Album", 15)
+ : getDecodedText(
+ playList[playingIndex]?.title || "Unknown Title",
+ 15,
+ )}
+
+
+ {getDecodedText(
+ playList[playingIndex]?.artist ||
+ playList?.items?.[playingIndex]?.artistName ||
+ "Unknown Artist",
+ 15,
+ )}
+
+
+ )
+ );
};
export default PlayerBanner;
const styles = StyleSheet.create({
- overlay: {
- ...StyleSheet.absoluteFillObject,
- backgroundColor: 'rgba(0, 0, 0, 0.35)',
- },
- imgContainer: {
- width: 250,
- overflow: 'hidden',
- alignItems: 'center',
- justifyContent: 'center',
- borderBottomLeftRadius: 150,
- borderBottomRightRadius: 150,
- shadowColor: '#010101',
- shadowOffset: {
- width: 0,
- height: 12,
- },
- shadowOpacity: 1.0,
- shadowRadius: 16.0,
- elevation: 24,
- },
- image: {
- width: '100%',
- height: '100%',
- },
- text: {
- position: 'absolute',
- fontSize: 18,
- bottom: 80,
- color: '#fff',
- fontWeight: '500',
- },
- subtext: {
- bottom: 50,
- fontSize: 12,
- fontWeight: '300',
- textTransform: 'uppercase',
- },
+ overlay: {
+ ...StyleSheet.absoluteFillObject,
+ backgroundColor: "rgba(0, 0, 0, 0.35)",
+ },
+ imgContainer: {
+ width: 250,
+ overflow: "hidden",
+ alignItems: "center",
+ justifyContent: "center",
+ borderBottomLeftRadius: 150,
+ borderBottomRightRadius: 150,
+ shadowColor: "#010101",
+ shadowOffset: {
+ width: 0,
+ height: 12,
+ },
+ shadowOpacity: 1.0,
+ shadowRadius: 16.0,
+ elevation: 24,
+ },
+ image: {
+ width: "100%",
+ height: "100%",
+ },
+ text: {
+ position: "absolute",
+ fontSize: 18,
+ bottom: 80,
+ color: "#fff",
+ fontWeight: "500",
+ },
+ subtext: {
+ bottom: 50,
+ fontSize: 12,
+ fontWeight: "300",
+ textTransform: "uppercase",
+ },
});
diff --git a/src/screens/AlbumViewerScreen/components/PlayerFooter.jsx b/src/screens/AlbumViewerScreen/components/PlayerFooter.jsx
index 65ffa22..32fd493 100644
--- a/src/screens/AlbumViewerScreen/components/PlayerFooter.jsx
+++ b/src/screens/AlbumViewerScreen/components/PlayerFooter.jsx
@@ -1,199 +1,206 @@
-import { StyleSheet, View, Animated, TouchableOpacity } from 'react-native';
-import React, { useEffect, useContext, useState } from 'react';
-import { PlayerContext } from '../../../contexts/PlayerContext';
+import { StyleSheet, View, Animated, TouchableOpacity } from "react-native";
+import React, { useEffect, useContext, useState } from "react";
+import { PlayerContext } from "../../../contexts/PlayerContext";
import Feather from "react-native-vector-icons/Feather";
import Ionicons from "react-native-vector-icons/Ionicons";
-import { Easing } from 'react-native-reanimated';
-import TrackPlayer, { RepeatMode, State } from 'react-native-track-player';
-
-const PlayerFooter = ({ playState, onShuffle, setOnShuffle, playurlOverrider, playingIndex, nextActionOverrider, previousActionOverrider }) => {
- const [onRepeat, setOnRepeat] = useState(false)
- useEffect(()=>{
- const fetchRepeat = async () => {
- const repeatMode = await TrackPlayer.getRepeatMode();
- if(repeatMode !== RepeatMode.Off){
- setOnRepeat(true);
- }
- else{
- setOnRepeat(false);
- }
- }
- fetchRepeat();
- }, [])
- const {
- footerHeightAnim, albumMode,
- } = useContext(PlayerContext);
-
- useEffect(() => {
- Animated.timing(footerHeightAnim, {
- toValue: 100,
- duration: 400,
- useNativeDriver: false,
- easing: Easing.ease,
- }).start();
- }, [albumMode]);
-
-
- const handleOnRepeat = async () => {
- if(onRepeat){
- await TrackPlayer.setRepeatMode(RepeatMode.Off)
- setOnRepeat(false);
- }
- else {
- await TrackPlayer.setRepeatMode(RepeatMode.Queue);
- setOnRepeat(true);
- }
- };
-
- const handlePlayPause = async () => {
- if(playState===State.Playing){
- await TrackPlayer.pause();
- }
- else if(playState===State.Paused) {
- await TrackPlayer.play();
- }
- else if (playState===State.Error || playState===State.Ready || playState === State.None){
- await playurlOverrider(playingIndex);
- }
- };
-
- const handleOnShuffle = () => {
- setOnShuffle(!onShuffle);
- };
-
- const handleOnNext = async () => {
- await nextActionOverrider();
- };
-
- const handleOnPrevious = async () => {
- await previousActionOverrider();
- };
-
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
+import { Easing } from "react-native-reanimated";
+import TrackPlayer, { RepeatMode, State } from "react-native-track-player";
+
+const PlayerFooter = ({
+ playState,
+ onShuffle,
+ setOnShuffle,
+ playurlOverrider,
+ playingIndex,
+ nextActionOverrider,
+ previousActionOverrider,
+}) => {
+ const [onRepeat, setOnRepeat] = useState(false);
+ useEffect(() => {
+ const fetchRepeat = async () => {
+ const repeatMode = await TrackPlayer.getRepeatMode();
+ if (repeatMode !== RepeatMode.Off) {
+ setOnRepeat(true);
+ } else {
+ setOnRepeat(false);
+ }
+ };
+ fetchRepeat();
+ }, []);
+ const { footerHeightAnim, albumMode } = useContext(PlayerContext);
+
+ useEffect(() => {
+ Animated.timing(footerHeightAnim, {
+ toValue: 100,
+ duration: 400,
+ useNativeDriver: false,
+ easing: Easing.ease,
+ }).start();
+ }, [albumMode]);
+
+ const handleOnRepeat = async () => {
+ if (onRepeat) {
+ await TrackPlayer.setRepeatMode(RepeatMode.Off);
+ setOnRepeat(false);
+ } else {
+ await TrackPlayer.setRepeatMode(RepeatMode.Queue);
+ setOnRepeat(true);
+ }
+ };
+
+ const handlePlayPause = async () => {
+ if (playState === State.Playing) {
+ await TrackPlayer.pause();
+ } else if (playState === State.Paused) {
+ await TrackPlayer.play();
+ } else if (
+ playState === State.Error ||
+ playState === State.Ready ||
+ playState === State.None
+ ) {
+ await playurlOverrider(playingIndex);
+ }
+ };
+
+ const handleOnShuffle = () => {
+ setOnShuffle(!onShuffle);
+ };
+
+ const handleOnNext = async () => {
+ await nextActionOverrider();
+ };
+
+ const handleOnPrevious = async () => {
+ await previousActionOverrider();
+ };
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
};
export default PlayerFooter;
const styles = StyleSheet.create({
- footer: {
- minWidth: "100%",
- },
-
- footercontainer: {
- flex: 1,
- justifyContent: "space-between",
- alignItems: "center",
- flexDirection: "row",
- paddingHorizontal: 15,
- },
-
- shuffleRepeatButtons: {
- padding: 10,
- marginHorizontal: 5,
- borderRadius: 50,
- },
-
- prevNextSongMode: {
- backgroundColor: "#f5f5f4",
- shadowColor: "#010101",
- shadowOffset: {
- width: 0,
- height: 12,
- },
- shadowOpacity: 1.0,
- shadowRadius: 16.0,
- elevation: 24,
- zIndex: -2,
- },
-
- prevButton: {
- paddingRight: 15,
- marginRight: -5,
- paddingLeft: 10,
- borderBottomLeftRadius: 25,
- borderTopLeftRadius: 25,
- paddingVertical: 8,
- },
-
- nextButton: {
- paddingLeft: 15,
- marginLeft: -5,
- paddingRight: 10,
- borderBottomRightRadius: 25,
- borderTopRightRadius: 25,
- paddingVertical: 8,
- },
-
- playPauseControl: {
- flexDirection: "row",
- alignItems: "center",
- },
-
- playPauseButtonContainer: {
- height: 70,
- width: 70,
- borderRadius: 35,
- backgroundColor: "black",
- justifyContent: "center",
- alignItems: "center",
- },
-
- playPauseButton: {
- height: 30,
- width: 30,
- },
+ footer: {
+ minWidth: "100%",
+ },
+
+ footercontainer: {
+ flex: 1,
+ justifyContent: "space-between",
+ alignItems: "center",
+ flexDirection: "row",
+ paddingHorizontal: 15,
+ },
+
+ shuffleRepeatButtons: {
+ padding: 10,
+ marginHorizontal: 5,
+ borderRadius: 50,
+ },
+
+ prevNextSongMode: {
+ backgroundColor: "#f5f5f4",
+ shadowColor: "#010101",
+ shadowOffset: {
+ width: 0,
+ height: 12,
+ },
+ shadowOpacity: 1.0,
+ shadowRadius: 16.0,
+ elevation: 24,
+ zIndex: -2,
+ },
+
+ prevButton: {
+ paddingRight: 15,
+ marginRight: -5,
+ paddingLeft: 10,
+ borderBottomLeftRadius: 25,
+ borderTopLeftRadius: 25,
+ paddingVertical: 8,
+ },
+
+ nextButton: {
+ paddingLeft: 15,
+ marginLeft: -5,
+ paddingRight: 10,
+ borderBottomRightRadius: 25,
+ borderTopRightRadius: 25,
+ paddingVertical: 8,
+ },
+
+ playPauseControl: {
+ flexDirection: "row",
+ alignItems: "center",
+ },
+
+ playPauseButtonContainer: {
+ height: 70,
+ width: 70,
+ borderRadius: 35,
+ backgroundColor: "black",
+ justifyContent: "center",
+ alignItems: "center",
+ },
+
+ playPauseButton: {
+ height: 30,
+ width: 30,
+ },
});
diff --git a/src/screens/AlbumViewerScreen/components/ProgressBarContainer.jsx b/src/screens/AlbumViewerScreen/components/ProgressBarContainer.jsx
index 34e6b33..8de83d1 100644
--- a/src/screens/AlbumViewerScreen/components/ProgressBarContainer.jsx
+++ b/src/screens/AlbumViewerScreen/components/ProgressBarContainer.jsx
@@ -1,75 +1,69 @@
-import { StyleSheet, Animated, View } from 'react-native'
-import React, { useContext, useEffect } from 'react'
-import { PlayerContext } from '../../../contexts/PlayerContext'
-import { AnimatedCircularProgress } from 'react-native-circular-progress'
-import { Circle } from 'react-native-svg'
-import { Easing } from 'react-native-reanimated';
+import { StyleSheet, Animated, View } from "react-native";
+import React, { useContext, useEffect } from "react";
+import { PlayerContext } from "../../../contexts/PlayerContext";
+import { AnimatedCircularProgress } from "react-native-circular-progress";
+import { Circle } from "react-native-svg";
+import { Easing } from "react-native-reanimated";
-const ProgressBarContainer = ({totalDuration, currentDuration}) => {
- const { albumMode, progressBarOpacity } = useContext(PlayerContext);
- useEffect(() => {
- Animated.timing(progressBarOpacity, {
- toValue: albumMode ? 0 : 1,
- duration: 400,
- useNativeDriver: true,
- easing: Easing.ease,
- }).start();
- }, [albumMode])
+const ProgressBarContainer = ({ totalDuration, currentDuration }) => {
+ const { albumMode, progressBarOpacity } = useContext(PlayerContext);
+ useEffect(() => {
+ Animated.timing(progressBarOpacity, {
+ toValue: albumMode ? 0 : 1,
+ duration: 400,
+ useNativeDriver: true,
+ easing: Easing.ease,
+ }).start();
+ }, [albumMode]);
- return (
-
-
- (
-
- )}
- />
+ return (
+
+
+ (
+
+ )}
+ />
+
+
+ );
+};
-
-
- )
-}
-
-export default ProgressBarContainer
+export default ProgressBarContainer;
const styles = StyleSheet.create({
-
- progressBarContainer: {
- zIndex: -1,
- alignItems: "center",
- justifyContent: "center",
- minWidth: "100%",
- },
- progressBar: {
- marginTop: -240,
- width: 250,
- height: 100,
- borderBottomLeftRadius: 150,
- borderBottomRightRadius: 150,
- alignItems: "center",
- justifyContent: "center",
- transform: [{ rotateX: "180deg" }],
- },
-
-})
\ No newline at end of file
+ progressBarContainer: {
+ zIndex: -1,
+ alignItems: "center",
+ justifyContent: "center",
+ minWidth: "100%",
+ },
+ progressBar: {
+ marginTop: -240,
+ width: 250,
+ height: 100,
+ borderBottomLeftRadius: 150,
+ borderBottomRightRadius: 150,
+ alignItems: "center",
+ justifyContent: "center",
+ transform: [{ rotateX: "180deg" }],
+ },
+});
diff --git a/src/screens/AlbumViewerScreen/components/UtilityButtons.jsx b/src/screens/AlbumViewerScreen/components/UtilityButtons.jsx
index 199d0e4..b263ccc 100644
--- a/src/screens/AlbumViewerScreen/components/UtilityButtons.jsx
+++ b/src/screens/AlbumViewerScreen/components/UtilityButtons.jsx
@@ -9,79 +9,91 @@ import { PlayerContext } from "../../../contexts/PlayerContext";
import { useNavigation } from "@react-navigation/native";
const UtilityButtons = ({ trackList }) => {
- const [addedToPlaylist, setAddedToPlaylist] = useState(false);
- const { activePlaylistId, addTracks, likedList } = useContext(PlayerContext);
- const navigation = useNavigation();
- return (
-
- utilityButtonActions("like", { trackList, likedList })}
- accessibilityLabel="Like"
- >
-
-
+ const [addedToPlaylist, setAddedToPlaylist] = useState(false);
+ const { activePlaylistId, addTracks, likedList } = useContext(PlayerContext);
+ const navigation = useNavigation();
+ return (
+
+ utilityButtonActions("like", { trackList, likedList })}
+ accessibilityLabel="Like"
+ >
+
+
-
- utilityButtonActions("play", { trackList, activePlaylistId, addTracks, setAddedToPlaylist, addedToPlaylist, navigation })
- }
- style={[styles.button, { backgroundColor: "#38c999", borderWidth: 0 }]}
- accessibilityLabel="Play"
- >
-
-
+
+ utilityButtonActions("play", {
+ trackList,
+ activePlaylistId,
+ addTracks,
+ setAddedToPlaylist,
+ addedToPlaylist,
+ navigation,
+ })
+ }
+ style={[styles.button, { backgroundColor: "#38c999", borderWidth: 0 }]}
+ accessibilityLabel="Play"
+ >
+
+
-
- utilityButtonActions("download", { trackList: trackList })
- }
- >
-
-
+
+ utilityButtonActions("download", { trackList: trackList })
+ }
+ >
+
+
-
- utilityButtonActions("entanglement", { trackList: trackList })
- }
- >
-
-
+
+ utilityButtonActions("entanglement", { trackList: trackList })
+ }
+ >
+
+
- utilityButtonActions("share", { trackList: trackList })}
- >
-
-
-
- );
+ utilityButtonActions("share", { trackList: trackList })}
+ >
+
+
+
+ );
};
export default UtilityButtons;
const styles = StyleSheet.create({
- container: {
- flexDirection: "row",
- marginTop: 20,
- width: "100%",
- justifyContent: "center",
- alignItems: "center",
- },
- button: {
- marginHorizontal: 5,
- padding: 10,
- borderWidth: 1,
- borderColor: "#ccc",
- borderRadius: 50,
- backgroundColor: "#f0f0f0",
- },
- icon: {
- textAlign: "center",
- },
+ container: {
+ flexDirection: "row",
+ marginTop: 20,
+ width: "100%",
+ justifyContent: "center",
+ alignItems: "center",
+ },
+ button: {
+ marginHorizontal: 5,
+ padding: 10,
+ borderWidth: 1,
+ borderColor: "#ccc",
+ borderRadius: 50,
+ backgroundColor: "#f0f0f0",
+ },
+ icon: {
+ textAlign: "center",
+ },
});
diff --git a/src/screens/AlbumsScreen/AlbumsScreen.jsx b/src/screens/AlbumsScreen/AlbumsScreen.jsx
index bd5d998..0c7ec10 100644
--- a/src/screens/AlbumsScreen/AlbumsScreen.jsx
+++ b/src/screens/AlbumsScreen/AlbumsScreen.jsx
@@ -1,8 +1,8 @@
-import { StyleSheet, View, FlatList } from 'react-native';
-import React, { useState, useEffect } from 'react';
-import Category from './components/Category';
-import ServiceProvider from '../../libs/APIParser';
-import Navbar from './components/Navbar';
+import { StyleSheet, View, FlatList } from "react-native";
+import React, { useState, useEffect } from "react";
+import Category from "./components/Category";
+import ServiceProvider from "../../libs/APIParser";
+import Navbar from "./components/Navbar";
const AlbumsScreen = () => {
const serviceProvider = new ServiceProvider();
@@ -14,18 +14,20 @@ const AlbumsScreen = () => {
const data = await serviceProvider.getLaunchData();
setAlbumData(data);
} catch (error) {
- console.error('Error fetching album data:', error);
+ console.error("Error fetching album data:", error);
}
};
fetchData();
}, []);
- const categories = albumData ? Object.keys(albumData.modules).map((key) => ({
- id: key,
- title: albumData.modules[key].title,
- data: albumData[albumData.modules[key].source],
- })) : [];
+ const categories = albumData
+ ? Object.keys(albumData.modules).map((key) => ({
+ id: key,
+ title: albumData.modules[key].title,
+ data: albumData[albumData.modules[key].source],
+ }))
+ : [];
return (
@@ -34,10 +36,7 @@ const AlbumsScreen = () => {
data={categories}
keyExtractor={(item) => item.id}
renderItem={({ item }) => (
-
+
)}
style={styles.albumsContainer}
/>
diff --git a/src/screens/AlbumsScreen/components/Card.jsx b/src/screens/AlbumsScreen/components/Card.jsx
index d39a01e..65ba62c 100644
--- a/src/screens/AlbumsScreen/components/Card.jsx
+++ b/src/screens/AlbumsScreen/components/Card.jsx
@@ -1,71 +1,90 @@
-import { StyleSheet, Text, View, ImageBackground, TouchableOpacity } from 'react-native';
-import React from 'react';
-import { decode } from 'html-entities';
+import {
+ StyleSheet,
+ Text,
+ View,
+ ImageBackground,
+ TouchableOpacity,
+} from "react-native";
+import React from "react";
+import { decode } from "html-entities";
import handleAlbum from "../../../utils/albumParser";
-import { useNavigation } from '@react-navigation/native';
+import { useNavigation } from "@react-navigation/native";
const Card = ({ albumData, index }) => {
- const navigation = useNavigation();
- albumData.title = albumData.title ? albumData.title : albumData.name;
- return (
- handleAlbum({
- albumData: albumData,
- image_: albumData.image,
- title_: albumData.title,
- navigation: navigation
- })} style={[styles.card, { height: index % 3 === 0 ? 250 : 180 }]}>
-
-
- {decode(albumData.title.length > 15
- ? `${albumData.title.substring(0, 15)}...`
- : albumData.title)}
-
-
- );
+ const navigation = useNavigation();
+ albumData.title = albumData.title ? albumData.title : albumData.name;
+ return (
+
+ handleAlbum({
+ albumData: albumData,
+ image_: albumData.image,
+ title_: albumData.title,
+ navigation: navigation,
+ })
+ }
+ style={[styles.card, { height: index % 3 === 0 ? 250 : 180 }]}
+ >
+
+
+
+ {decode(
+ albumData.title.length > 15
+ ? `${albumData.title.substring(0, 15)}...`
+ : albumData.title,
+ )}
+
+
+
+ );
};
export default Card;
const styles = StyleSheet.create({
- card: {
- maxWidth: 180,
- minWidth: 165,
- backgroundColor: '#fff',
- borderRadius: 8,
- shadowColor: '#000',
- shadowOpacity: 0.2,
- shadowRadius: 4,
- shadowOffset: { width: 0, height: 2 },
- elevation: 5,
- overflow: "hidden",
- marginHorizontal: 8,
- marginVertical: 10,
- },
- image: {
- width: "100%",
- height: "100%",
- justifyContent: "flex-end",
- position: "relative",
- overflow: "hidden"
- },
- imageOverlay: {
- borderRadius: 8,
- },
- overlay: {
- ...StyleSheet.absoluteFillObject,
- backgroundColor: 'rgba(0, 0, 0, 0.35)',
- borderRadius: 8,
- },
- title: {
- position: "absolute",
- bottom: 10,
- left: 10,
- fontSize: 20,
- fontWeight: "800",
- color: "#fff",
- },
+ card: {
+ maxWidth: 180,
+ minWidth: 165,
+ backgroundColor: "#fff",
+ borderRadius: 8,
+ shadowColor: "#000",
+ shadowOpacity: 0.2,
+ shadowRadius: 4,
+ shadowOffset: { width: 0, height: 2 },
+ elevation: 5,
+ overflow: "hidden",
+ marginHorizontal: 8,
+ marginVertical: 10,
+ },
+ image: {
+ width: "100%",
+ height: "100%",
+ justifyContent: "flex-end",
+ position: "relative",
+ overflow: "hidden",
+ },
+ imageOverlay: {
+ borderRadius: 8,
+ },
+ overlay: {
+ ...StyleSheet.absoluteFillObject,
+ backgroundColor: "rgba(0, 0, 0, 0.35)",
+ borderRadius: 8,
+ },
+ title: {
+ position: "absolute",
+ bottom: 10,
+ left: 10,
+ fontSize: 20,
+ fontWeight: "800",
+ color: "#fff",
+ },
});
diff --git a/src/screens/AlbumsScreen/components/Category.jsx b/src/screens/AlbumsScreen/components/Category.jsx
index e522c75..414cfb1 100644
--- a/src/screens/AlbumsScreen/components/Category.jsx
+++ b/src/screens/AlbumsScreen/components/Category.jsx
@@ -1,43 +1,41 @@
-import { StyleSheet, Text, View } from 'react-native';
-import React from 'react';
-import MasonryList from '@react-native-seoul/masonry-list';
-import Card from './Card';
+import { StyleSheet, Text, View } from "react-native";
+import React from "react";
+import MasonryList from "@react-native-seoul/masonry-list";
+import Card from "./Card";
const Category = ({ categoryName, categoryData }) => {
- categoryData = categoryData.map((item, index) => ({
- ...item,
- index,
- }));
- const renderCard = ({ item }) => (
-
- );
+ categoryData = categoryData.map((item, index) => ({
+ ...item,
+ index,
+ }));
+ const renderCard = ({ item }) => ;
- return (
-
- {categoryName}
- item.id}
- numColumns={2}
- showsVerticalScrollIndicator={false}
- renderItem={renderCard}
- onEndReachedThreshold={0.1}
- />
-
- );
+ return (
+
+ {categoryName}
+ item.id}
+ numColumns={2}
+ showsVerticalScrollIndicator={false}
+ renderItem={renderCard}
+ onEndReachedThreshold={0.1}
+ />
+
+ );
};
export default Category;
const styles = StyleSheet.create({
- container: {
- flex: 1,
- padding: 5,
- },
- categoryTitle: {
- fontSize: 30,
- fontWeight: 'bold',
- marginBottom: 5,
- textAlign: 'center'
- },
+ container: {
+ flex: 1,
+ padding: 5,
+ },
+ categoryTitle: {
+ fontSize: 30,
+ fontWeight: "bold",
+ marginBottom: 5,
+ textAlign: "center",
+ },
});
diff --git a/src/screens/AlbumsScreen/components/Navbar.jsx b/src/screens/AlbumsScreen/components/Navbar.jsx
index 7c98413..6688d1b 100644
--- a/src/screens/AlbumsScreen/components/Navbar.jsx
+++ b/src/screens/AlbumsScreen/components/Navbar.jsx
@@ -1,36 +1,36 @@
-import { StyleSheet, TouchableOpacity, View } from 'react-native'
-import React from 'react'
+import { StyleSheet, TouchableOpacity, View } from "react-native";
+import React from "react";
import Feather from "react-native-vector-icons/Feather";
-import { useNavigation } from '@react-navigation/native';
+import { useNavigation } from "@react-navigation/native";
const Navbar = () => {
- const navigator = useNavigation();
- const handleSearch = () => {
- navigator.navigate("SearchScreen");
- }
- const handleDashboard = () => {
- navigator.navigate("DashboardScreen");
- }
- return (
-
-
-
-
-
-
-
-
- )
-}
+ const navigator = useNavigation();
+ const handleSearch = () => {
+ navigator.navigate("SearchScreen");
+ };
+ const handleDashboard = () => {
+ navigator.navigate("DashboardScreen");
+ };
+ return (
+
+
+
+
+
+
+
+
+ );
+};
-export default Navbar
+export default Navbar;
const styles = StyleSheet.create({
- searchInput: {
- marginTop: 15,
- flexDirection: 'row',
- paddingHorizontal: 20,
- paddingVertical: 15,
- justifyContent: 'space-between',
- },
-})
\ No newline at end of file
+ searchInput: {
+ marginTop: 15,
+ flexDirection: "row",
+ paddingHorizontal: 20,
+ paddingVertical: 15,
+ justifyContent: "space-between",
+ },
+});
diff --git a/src/screens/DashboardScreen/DashboardScreen.jsx b/src/screens/DashboardScreen/DashboardScreen.jsx
index 0e131bb..8b6f441 100644
--- a/src/screens/DashboardScreen/DashboardScreen.jsx
+++ b/src/screens/DashboardScreen/DashboardScreen.jsx
@@ -1,9 +1,9 @@
-import React from 'react';
-import { createDrawerNavigator } from '@react-navigation/drawer';
-import SearchScreen from '../../screens/SearchScreen/SearchScreen';
-import AlbumsScreen from '../../screens/AlbumsScreen/AlbumsScreen';
-import RightHeaderButton from './components/RightHeaderButton';
-import CenterHeader from './components/CenterHeader';
+import React from "react";
+import { createDrawerNavigator } from "@react-navigation/drawer";
+import SearchScreen from "../../screens/SearchScreen/SearchScreen";
+import AlbumsScreen from "../../screens/AlbumsScreen/AlbumsScreen";
+import RightHeaderButton from "./components/RightHeaderButton";
+import CenterHeader from "./components/CenterHeader";
import VersionScreen from "../VersionScreen/VersionScreen";
import AboutScreen from "../AboutScreen/AboutScreen";
import DownloadsScreen from "../DownloadsScreen/DownloadsScreen";
@@ -11,101 +11,115 @@ import SettingsScreen from "../SettingsScreen/SettingsScreen";
import LibraryScreen from "../LibraryScreen/LibraryScreen";
import Octicons from "react-native-vector-icons/Octicons";
import Ionicons from "react-native-vector-icons/Ionicons";
-import Footer from './components/Footer';
-import PlayerScreen from '../PlayerScreen/PlayerScreen';
-import Constants from '../../constants/constants';
+import Footer from "./components/Footer";
+import PlayerScreen from "../PlayerScreen/PlayerScreen";
+import Constants from "../../constants/constants";
const Drawer = createDrawerNavigator();
const constants = new Constants();
const DashboardScreen = ({ navigation }) => {
- return (
- RightHeaderButton({ navigation }),
- drawerActiveTintColor: '#6200ee',
- drawerInactiveTintColor: '#000',
- drawerStyle: {
- backgroundColor: '#f5f5f5',
- width: 280,
- },
- headerTitleAlign: 'left'
- }}
- drawerContent={(props) => }
- initialRouteName={constants.drawerRoutes.ALBUMSCREEN}
- >
- ,
- }}
- />
- ,
- }}
- />
- ,
- }}
- />
- ,
- }}
- />
- ,
- headerShown: false,
- }}
- />
- ,
- }}
- />
- ,
- drawerItemStyle: { display: 'none' }
- }}
- />
- ,
- headerShown: false
- }}
- />
-
- );
+ return (
+ RightHeaderButton({ navigation }),
+ drawerActiveTintColor: "#6200ee",
+ drawerInactiveTintColor: "#000",
+ drawerStyle: {
+ backgroundColor: "#f5f5f5",
+ width: 280,
+ },
+ headerTitleAlign: "left",
+ }}
+ drawerContent={(props) => }
+ initialRouteName={constants.drawerRoutes.ALBUMSCREEN}
+ >
+ (
+
+ ),
+ }}
+ />
+ (
+
+ ),
+ }}
+ />
+ (
+
+ ),
+ }}
+ />
+ (
+
+ ),
+ }}
+ />
+ (
+
+ ),
+ headerShown: false,
+ }}
+ />
+ (
+
+ ),
+ }}
+ />
+ (
+
+ ),
+ drawerItemStyle: { display: "none" },
+ }}
+ />
+ (
+
+ ),
+ headerShown: false,
+ }}
+ />
+
+ );
};
export default DashboardScreen;
-
-
diff --git a/src/screens/DashboardScreen/components/CenterHeader.jsx b/src/screens/DashboardScreen/components/CenterHeader.jsx
index de34e09..9277ecc 100644
--- a/src/screens/DashboardScreen/components/CenterHeader.jsx
+++ b/src/screens/DashboardScreen/components/CenterHeader.jsx
@@ -1,56 +1,60 @@
-import { StyleSheet, Text, View, Image } from 'react-native';
-import React, { useEffect, useState } from 'react';
+import { StyleSheet, Text, View, Image } from "react-native";
+import React, { useEffect, useState } from "react";
import { expo } from "../../../../app.json";
-import * as Font from 'expo-font';
+import * as Font from "expo-font";
const loadFonts = async () => {
- try {
- await Font.loadAsync({
- 'MonkeyBold': require('../../../../assets/fonts/MonkyBold.otf'),
- });
- } catch (error) {
- console.error('Error loading font:', error);
- }
+ try {
+ await Font.loadAsync({
+ MonkeyBold: require("../../../../assets/fonts/MonkyBold.otf"),
+ });
+ } catch (error) {
+ console.error("Error loading font:", error);
+ }
};
-
const CenterHeader = () => {
- const [fontsLoaded, setFontsLoaded] = useState(false);
-
- useEffect(() => {
- loadFonts().then(() => setFontsLoaded(true));
- }, []);
-
- if (!fontsLoaded) {
- return null;
- }
-
- return (
-
-
- {expo.displayName}
-
- );
+ const [fontsLoaded, setFontsLoaded] = useState(false);
+
+ useEffect(() => {
+ loadFonts().then(() => setFontsLoaded(true));
+ }, []);
+
+ if (!fontsLoaded) {
+ return null;
+ }
+
+ return (
+
+
+
+ {expo.displayName}
+
+
+ );
};
export default CenterHeader;
const styles = StyleSheet.create({
- title: {
- flex: 1,
- flexDirection: 'row',
- alignItems: 'center',
- justifyContent: 'center',
- minWidth: "100%",
- },
- icon: {
- width: 30,
- height: 30,
- marginRight: 8,
- },
- text: {
- fontWeight: '800',
- fontSize: 18,
- textTransform: 'capitalize'
- },
+ title: {
+ flex: 1,
+ flexDirection: "row",
+ alignItems: "center",
+ justifyContent: "center",
+ minWidth: "100%",
+ },
+ icon: {
+ width: 30,
+ height: 30,
+ marginRight: 8,
+ },
+ text: {
+ fontWeight: "800",
+ fontSize: 18,
+ textTransform: "capitalize",
+ },
});
diff --git a/src/screens/DashboardScreen/components/Footer.jsx b/src/screens/DashboardScreen/components/Footer.jsx
index 03d7b5e..b3bdf6d 100644
--- a/src/screens/DashboardScreen/components/Footer.jsx
+++ b/src/screens/DashboardScreen/components/Footer.jsx
@@ -1,63 +1,78 @@
-import { StyleSheet, Text, TouchableOpacity, View } from 'react-native'
-import React, { useEffect, useState } from 'react'
-import { useSafeAreaInsets } from 'react-native-safe-area-context';
-import { DrawerContentScrollView, DrawerItemList } from '@react-navigation/drawer';
+import { StyleSheet, Text, TouchableOpacity, View } from "react-native";
+import React, { useEffect, useState } from "react";
+import { useSafeAreaInsets } from "react-native-safe-area-context";
+import {
+ DrawerContentScrollView,
+ DrawerItemList,
+} from "@react-navigation/drawer";
import { expo } from "../../../../app.json";
import Ionicons from "react-native-vector-icons/MaterialIcons";
const Footer = (props) => {
- const [remoteVersion, setRemoteVersion] = useState(null);
-
- useEffect(() => {
- const versionFetch = async () => {
- const resp = await fetch('https://raw.githubusercontent.com/0x0is1/lissen-mobile/refs/heads/main/app.json')
- const data = await resp.json();
- setRemoteVersion(data.expo.version);
- }
- versionFetch();
- }, []);
+ const [remoteVersion, setRemoteVersion] = useState(null);
- const insets = useSafeAreaInsets();
- const isUpdateAvailable = remoteVersion && expo.version < remoteVersion;
+ useEffect(() => {
+ const versionFetch = async () => {
+ const resp = await fetch(
+ "https://raw.githubusercontent.com/0x0is1/lissen-mobile/refs/heads/main/app.json",
+ );
+ const data = await resp.json();
+ setRemoteVersion(data.expo.version);
+ };
+ versionFetch();
+ }, []);
- return (
-
-
-
-
-
-
- Current Version: {expo.version}
- Latest Version: {remoteVersion || 'NaN'}
-
- props.navigation.navigate('VersionScreen')} disabled={!isUpdateAvailable}>
-
-
-
-
- );
-}
+ const insets = useSafeAreaInsets();
+ const isUpdateAvailable = remoteVersion && expo.version < remoteVersion;
+
+ return (
+
+
+
+
+
+
+ Current Version: {expo.version}
+
+ Latest Version: {remoteVersion || "NaN"}
+
+
+ props.navigation.navigate("VersionScreen")}
+ disabled={!isUpdateAvailable}
+ >
+
+
+
+
+ );
+};
export default Footer;
const styles = StyleSheet.create({
- footerContainer: {
- borderTopWidth: 1,
- borderTopColor: '#e4e4e4',
- paddingVertical: 10,
- paddingHorizontal: 20,
- backgroundColor: '#f5f5f5',
- flexDirection: 'row',
- justifyContent: 'space-around',
- alignItems: 'center'
- },
- footerText: {
- fontSize: 14,
- color: '#666',
- textAlign: 'center',
- },
+ footerContainer: {
+ borderTopWidth: 1,
+ borderTopColor: "#e4e4e4",
+ paddingVertical: 10,
+ paddingHorizontal: 20,
+ backgroundColor: "#f5f5f5",
+ flexDirection: "row",
+ justifyContent: "space-around",
+ alignItems: "center",
+ },
+ footerText: {
+ fontSize: 14,
+ color: "#666",
+ textAlign: "center",
+ },
});
diff --git a/src/screens/DashboardScreen/components/RightHeaderButton.jsx b/src/screens/DashboardScreen/components/RightHeaderButton.jsx
index 51f51fa..cd1eb77 100644
--- a/src/screens/DashboardScreen/components/RightHeaderButton.jsx
+++ b/src/screens/DashboardScreen/components/RightHeaderButton.jsx
@@ -1,13 +1,18 @@
-import { StyleSheet, TouchableOpacity } from 'react-native'
+import { StyleSheet, TouchableOpacity } from "react-native";
import Feather from "react-native-vector-icons/Feather";
-import React from 'react'
+import React from "react";
-const RightHeaderButton = ({navigation}) => {
- return navigation.navigate('SearchScreen')}>
-
-
-}
+const RightHeaderButton = ({ navigation }) => {
+ return (
+ navigation.navigate("SearchScreen")}
+ >
+
+
+ );
+};
-export default RightHeaderButton
+export default RightHeaderButton;
-const styles = StyleSheet.create({})
\ No newline at end of file
+const styles = StyleSheet.create({});
diff --git a/src/screens/DownloadsScreen/DownloadsScreen.jsx b/src/screens/DownloadsScreen/DownloadsScreen.jsx
index b77fb0b..62fb3bb 100644
--- a/src/screens/DownloadsScreen/DownloadsScreen.jsx
+++ b/src/screens/DownloadsScreen/DownloadsScreen.jsx
@@ -1,14 +1,14 @@
-import { StyleSheet, Text, View } from 'react-native'
-import React from 'react'
+import { StyleSheet, Text, View } from "react-native";
+import React from "react";
const DownloadsScreen = () => {
- return (
-
- DownloadsScreen
-
- )
-}
+ return (
+
+ DownloadsScreen
+
+ );
+};
-export default DownloadsScreen
+export default DownloadsScreen;
-const styles = StyleSheet.create({})
\ No newline at end of file
+const styles = StyleSheet.create({});
diff --git a/src/screens/LibraryScreen/LibraryScreen.jsx b/src/screens/LibraryScreen/LibraryScreen.jsx
index 109e9b6..d22a6c8 100644
--- a/src/screens/LibraryScreen/LibraryScreen.jsx
+++ b/src/screens/LibraryScreen/LibraryScreen.jsx
@@ -1,14 +1,14 @@
-import { StyleSheet, Text, View } from 'react-native'
-import React from 'react'
+import { StyleSheet, Text, View } from "react-native";
+import React from "react";
const LibraryScreen = () => {
- return (
-
- LibraryScreen
-
- )
-}
+ return (
+
+ LibraryScreen
+
+ );
+};
-export default LibraryScreen
+export default LibraryScreen;
-const styles = StyleSheet.create({})
\ No newline at end of file
+const styles = StyleSheet.create({});
diff --git a/src/screens/PlayerScreen/PlayerScreen.jsx b/src/screens/PlayerScreen/PlayerScreen.jsx
index 8ff1e6b..cac368f 100644
--- a/src/screens/PlayerScreen/PlayerScreen.jsx
+++ b/src/screens/PlayerScreen/PlayerScreen.jsx
@@ -1,71 +1,93 @@
-import {
- StyleSheet,
- View,
-} from "react-native";
+import { StyleSheet, View } from "react-native";
import React, { useContext, useEffect, useState } from "react";
-import { PlayerContext } from '../../contexts/PlayerContext';
+import { PlayerContext } from "../../contexts/PlayerContext";
import PlayerFooter from "./components/PlayerFooter";
import PlayerBanner from "./components/PlayerBanner";
import AlbumItemsContainer from "./components/AlbumItemsContainer";
import ProgressBarContainer from "./components/ProgressBarContainer";
import DurationText from "./components/DurationText";
-import TrackPlayer, { Event, State, useTrackPlayerEvents } from 'react-native-track-player'
+import TrackPlayer, {
+ Event,
+ State,
+ useTrackPlayerEvents,
+} from "react-native-track-player";
import CustomStatusBar from "./components/CustomStatusBar";
const PlayerScreen = () => {
- const {
- albumMode, playingIndex, onShuffle, setOnShuffle, playState, playurlOverrider, nextActionOverrider, previousActionOverrider, isTrackAddingCompleted
- } = useContext(PlayerContext);
- const [currentDuration, setCurrentDuration] = useState(0);
- const [totalDuration, setTotalDuration] = useState(0);
- const [queue, setQueue] = useState(null);
-
- useTrackPlayerEvents([Event.PlaybackProgressUpdated], async (event) => {
- setTotalDuration(event.duration);
- setCurrentDuration(event.position);
- });
-
- useEffect(() => {
- if (isTrackAddingCompleted) {
- const fetchQueue = async () => {
- const queueres = await TrackPlayer.getQueue();
- setQueue(queueres);
- };
- fetchQueue();
- }
- }, [isTrackAddingCompleted]);
-
- useTrackPlayerEvents([Event.PlaybackActiveTrackChanged], async (event) => {
- const queueres = await TrackPlayer.getQueue();
- setQueue(queueres);
- });
+ const {
+ albumMode,
+ playingIndex,
+ onShuffle,
+ setOnShuffle,
+ playState,
+ playurlOverrider,
+ nextActionOverrider,
+ previousActionOverrider,
+ isTrackAddingCompleted,
+ } = useContext(PlayerContext);
+ const [currentDuration, setCurrentDuration] = useState(0);
+ const [totalDuration, setTotalDuration] = useState(0);
+ const [queue, setQueue] = useState(null);
- return (
- isTrackAddingCompleted &&
-
-
- {
- albumMode
- ? (
-
- ) : (
- <>
-
-
- >
- )
- }
-
-
- );
+ useTrackPlayerEvents([Event.PlaybackProgressUpdated], async (event) => {
+ setTotalDuration(event.duration);
+ setCurrentDuration(event.position);
+ });
+
+ useEffect(() => {
+ if (isTrackAddingCompleted) {
+ const fetchQueue = async () => {
+ const queueres = await TrackPlayer.getQueue();
+ setQueue(queueres);
+ };
+ fetchQueue();
+ }
+ }, [isTrackAddingCompleted]);
+
+ useTrackPlayerEvents([Event.PlaybackActiveTrackChanged], async (event) => {
+ const queueres = await TrackPlayer.getQueue();
+ setQueue(queueres);
+ });
+
+ return (
+ isTrackAddingCompleted && (
+
+
+
+ {albumMode ? (
+
+ ) : (
+ <>
+
+
+ >
+ )}
+
+
+ )
+ );
};
const styles = StyleSheet.create({
- container: {
- flex: 1,
- alignItems: "center",
- backgroundColor: "#e7e9eb",
- },
+ container: {
+ flex: 1,
+ alignItems: "center",
+ backgroundColor: "#e7e9eb",
+ },
});
export default PlayerScreen;
diff --git a/src/screens/PlayerScreen/components/AlbumItemsContainer.jsx b/src/screens/PlayerScreen/components/AlbumItemsContainer.jsx
index 465be25..c9f3cab 100644
--- a/src/screens/PlayerScreen/components/AlbumItemsContainer.jsx
+++ b/src/screens/PlayerScreen/components/AlbumItemsContainer.jsx
@@ -1,89 +1,97 @@
-import { Animated, StyleSheet, Text, View } from 'react-native';
-import React, { useContext, useEffect } from 'react';
-import { FlatList, TouchableOpacity } from 'react-native-gesture-handler';
-import { PlayerContext } from '../../../contexts/PlayerContext';
-import { Easing } from 'react-native-reanimated';
-import { decode } from 'html-entities';
+import { Animated, StyleSheet, Text, View } from "react-native";
+import React, { useContext, useEffect } from "react";
+import { FlatList, TouchableOpacity } from "react-native-gesture-handler";
+import { PlayerContext } from "../../../contexts/PlayerContext";
+import { Easing } from "react-native-reanimated";
+import { decode } from "html-entities";
const AlbumItemsContainer = ({ playList, playurlOverrider }) => {
- const { formatTime, albumItemsOpacity, albumMode, playingIndex } = useContext(PlayerContext);
+ const { formatTime, albumItemsOpacity, albumMode, playingIndex } =
+ useContext(PlayerContext);
- useEffect(() => {
- Animated.timing(albumItemsOpacity, {
- toValue: albumMode ? 1 : 0,
- duration: 400,
- useNativeDriver: true,
- easing: Easing.ease,
- }).start();
- }, [albumMode]);
+ useEffect(() => {
+ Animated.timing(albumItemsOpacity, {
+ toValue: albumMode ? 1 : 0,
+ duration: 400,
+ useNativeDriver: true,
+ easing: Easing.ease,
+ }).start();
+ }, [albumMode]);
- const onItemPlayPressed = async (index) => {
- await playurlOverrider(index);
- };
+ const onItemPlayPressed = async (index) => {
+ await playurlOverrider(index);
+ };
- const renderAlbumItems = ({ item, index }) => (
- onItemPlayPressed(index)}>
-
-
- {decode(item.title).length > 30
- ? `${decode(item.title).substring(0, 30)}...`
- : decode(item.title)}
-
-
- {formatTime(item.duration)}
-
-
-
- );
+ const renderAlbumItems = ({ item, index }) => (
+ onItemPlayPressed(index)}>
+
+
+ {decode(item.title).length > 30
+ ? `${decode(item.title).substring(0, 30)}...`
+ : decode(item.title)}
+
+
+ {formatTime(item.duration)}
+
+
+
+ );
- return (
- playList && playList.length > 0 ?
-
- index.toString()}
- />
-
- :
-
- No items to display
-
- );
+ return playList && playList.length > 0 ? (
+
+ index.toString()}
+ />
+
+ ) : (
+
+ No items to display
+
+ );
};
export default AlbumItemsContainer;
const styles = StyleSheet.create({
- placeholder: {
- height: 300
- },
-
- albumItems: {
- flexDirection: 'row',
- minWidth: '100%',
- alignItems: 'center',
- justifyContent: 'space-between',
- paddingVertical: 10,
- paddingHorizontal: 40,
- },
- albumItemsContainer: {
- maxHeight: 300,
- marginTop: 40,
- overflow: 'scroll',
- },
- songItem: {
- fontSize: 15,
- fontWeight: '500',
- },
+ placeholder: {
+ height: 300,
+ },
+
+ albumItems: {
+ flexDirection: "row",
+ minWidth: "100%",
+ alignItems: "center",
+ justifyContent: "space-between",
+ paddingVertical: 10,
+ paddingHorizontal: 40,
+ },
+ albumItemsContainer: {
+ maxHeight: 300,
+ marginTop: 40,
+ overflow: "scroll",
+ },
+ songItem: {
+ fontSize: 15,
+ fontWeight: "500",
+ },
});
diff --git a/src/screens/PlayerScreen/components/CustomStatusBar.jsx b/src/screens/PlayerScreen/components/CustomStatusBar.jsx
index 061b84f..91503af 100644
--- a/src/screens/PlayerScreen/components/CustomStatusBar.jsx
+++ b/src/screens/PlayerScreen/components/CustomStatusBar.jsx
@@ -1,30 +1,40 @@
-import { StyleSheet, ToastAndroid, TouchableOpacity, View } from 'react-native'
-import React from 'react'
+import { StyleSheet, ToastAndroid, TouchableOpacity, View } from "react-native";
+import React from "react";
import Ionicons from "react-native-vector-icons/Ionicons";
-import { useNavigation } from '@react-navigation/native';
+import { useNavigation } from "@react-navigation/native";
const CustomStatusBar = () => {
- const navigator = useNavigation();
- return (
-
- { navigator.goBack() }} style={[styles.icons, {right: 140}]}>
-
-
- { ToastAndroid.show('Not implemented yet', ToastAndroid.SHORT) }} style={[styles.icons, { left: 140 }]}>
-
-
-
- )
-}
+ const navigator = useNavigation();
+ return (
+
+ {
+ navigator.goBack();
+ }}
+ style={[styles.icons, { right: 140 }]}
+ >
+
+
+ {
+ ToastAndroid.show("Not implemented yet", ToastAndroid.SHORT);
+ }}
+ style={[styles.icons, { left: 140 }]}
+ >
+
+
+
+ );
+};
-export default CustomStatusBar
+export default CustomStatusBar;
const styles = StyleSheet.create({
- buttonContainer: {
- position: 'absolute',
- flexDirection: 'row',
- top: 25
- },
- icons: {
- borderRadius: 40,
- }
-})
\ No newline at end of file
+ buttonContainer: {
+ position: "absolute",
+ flexDirection: "row",
+ top: 25,
+ },
+ icons: {
+ borderRadius: 40,
+ },
+});
diff --git a/src/screens/PlayerScreen/components/DurationText.jsx b/src/screens/PlayerScreen/components/DurationText.jsx
index bc1dd95..a8daca1 100644
--- a/src/screens/PlayerScreen/components/DurationText.jsx
+++ b/src/screens/PlayerScreen/components/DurationText.jsx
@@ -1,22 +1,20 @@
-import { StyleSheet, Text } from 'react-native'
-import React, { useContext } from 'react'
-import { PlayerContext } from '../../../contexts/PlayerContext';
+import { StyleSheet, Text } from "react-native";
+import React, { useContext } from "react";
+import { PlayerContext } from "../../../contexts/PlayerContext";
-const DurationText = ({currentDuration}) => {
- const { formatTime } = useContext(PlayerContext);
- return (
- {formatTime(currentDuration)}
- )
-}
+const DurationText = ({ currentDuration }) => {
+ const { formatTime } = useContext(PlayerContext);
+ return {formatTime(currentDuration)};
+};
-export default DurationText
+export default DurationText;
const styles = StyleSheet.create({
- durationText: {
- position: "relative",
- fontSize: 16,
- color: "black",
- marginTop: 70,
- marginBottom: 100,
- },
-})
\ No newline at end of file
+ durationText: {
+ position: "relative",
+ fontSize: 16,
+ color: "black",
+ marginTop: 70,
+ marginBottom: 100,
+ },
+});
diff --git a/src/screens/PlayerScreen/components/PlayerBanner.jsx b/src/screens/PlayerScreen/components/PlayerBanner.jsx
index dad7e7b..636287a 100644
--- a/src/screens/PlayerScreen/components/PlayerBanner.jsx
+++ b/src/screens/PlayerScreen/components/PlayerBanner.jsx
@@ -1,107 +1,126 @@
-import { StyleSheet, Text, View, Animated, ImageBackground } from 'react-native';
-import React, { useEffect, useContext, useState } from 'react';
-import { PlayerContext } from '../../../contexts/PlayerContext';
-import { Easing } from 'react-native-reanimated';
-import { decode } from 'html-entities';
+import {
+ StyleSheet,
+ Text,
+ View,
+ Animated,
+ ImageBackground,
+} from "react-native";
+import React, { useEffect, useContext, useState } from "react";
+import { PlayerContext } from "../../../contexts/PlayerContext";
+import { Easing } from "react-native-reanimated";
+import { decode } from "html-entities";
const getDecodedText = (text, maxLength) => {
- const decodedText = decode(text || 'None');
- return decodedText.length > maxLength
- ? `${decodedText.substring(0, maxLength)}...`
- : decodedText;
+ const decodedText = decode(text || "None");
+ return decodedText.length > maxLength
+ ? `${decodedText.substring(0, maxLength)}...`
+ : decodedText;
};
const PlayerBanner = ({ playingIndex, playList }) => {
- const { albumMode, heightAnim, panResponder } = useContext(PlayerContext);
+ const { albumMode, heightAnim, panResponder } = useContext(PlayerContext);
- useEffect(() => {
- Animated.timing(heightAnim, {
- toValue: albumMode ? 350 : 500,
- duration: 400,
- useNativeDriver: false,
- easing: Easing.ease,
- }).start();
- }, [albumMode]);
+ useEffect(() => {
+ Animated.timing(heightAnim, {
+ toValue: albumMode ? 350 : 500,
+ duration: 400,
+ useNativeDriver: false,
+ easing: Easing.ease,
+ }).start();
+ }, [albumMode]);
- const getImageSource = (imagePath) => {
- if (typeof imagePath === 'string' && imagePath.startsWith('http')) {
- return { uri: imagePath };
- } else {
- return imagePath;
- }
- };
+ const getImageSource = (imagePath) => {
+ if (typeof imagePath === "string" && imagePath.startsWith("http")) {
+ return { uri: imagePath };
+ } else {
+ return imagePath;
+ }
+ };
- return (
- (playList) && (
-
-
-
-
-
- {albumMode
- ? "My Queue"
- : getDecodedText(playList[playingIndex]?.title || 'Unknown Title', 15)}
-
-
- {
- !albumMode
- ? getDecodedText(playList[playingIndex]?.artist || playList?.items?.[playingIndex]?.artistName || 'Unknown Artist', 15)
- : "You"}
-
-
- )
- );
+ return (
+ playList && (
+
+
+
+
+
+ {albumMode
+ ? "My Queue"
+ : getDecodedText(
+ playList[playingIndex]?.title || "Unknown Title",
+ 15,
+ )}
+
+
+ {!albumMode
+ ? getDecodedText(
+ playList[playingIndex]?.artist ||
+ playList?.items?.[playingIndex]?.artistName ||
+ "Unknown Artist",
+ 15,
+ )
+ : "You"}
+
+
+ )
+ );
};
export default PlayerBanner;
const styles = StyleSheet.create({
- overlay: {
- ...StyleSheet.absoluteFillObject,
- backgroundColor: 'rgba(0, 0, 0, 0.35)',
- },
- imgContainer: {
- width: 250,
- overflow: 'hidden',
- alignItems: 'center',
- justifyContent: 'center',
- borderBottomLeftRadius: 150,
- borderBottomRightRadius: 150,
- shadowColor: '#010101',
- shadowOffset: {
- width: 0,
- height: 12,
- },
- shadowOpacity: 1.0,
- shadowRadius: 16.0,
- elevation: 24,
- },
- image: {
- width: '100%',
- height: '100%',
- },
- text: {
- position: 'absolute',
- fontSize: 18,
- bottom: 80,
- color: '#fff',
- fontWeight: '500',
- },
- subtext: {
- bottom: 50,
- fontSize: 12,
- fontWeight: '300',
- textTransform: 'uppercase',
- },
+ overlay: {
+ ...StyleSheet.absoluteFillObject,
+ backgroundColor: "rgba(0, 0, 0, 0.35)",
+ },
+ imgContainer: {
+ width: 250,
+ overflow: "hidden",
+ alignItems: "center",
+ justifyContent: "center",
+ borderBottomLeftRadius: 150,
+ borderBottomRightRadius: 150,
+ shadowColor: "#010101",
+ shadowOffset: {
+ width: 0,
+ height: 12,
+ },
+ shadowOpacity: 1.0,
+ shadowRadius: 16.0,
+ elevation: 24,
+ },
+ image: {
+ width: "100%",
+ height: "100%",
+ },
+ text: {
+ position: "absolute",
+ fontSize: 18,
+ bottom: 80,
+ color: "#fff",
+ fontWeight: "500",
+ },
+ subtext: {
+ bottom: 50,
+ fontSize: 12,
+ fontWeight: "300",
+ textTransform: "uppercase",
+ },
});
diff --git a/src/screens/PlayerScreen/components/PlayerFooter.jsx b/src/screens/PlayerScreen/components/PlayerFooter.jsx
index 65ffa22..32fd493 100644
--- a/src/screens/PlayerScreen/components/PlayerFooter.jsx
+++ b/src/screens/PlayerScreen/components/PlayerFooter.jsx
@@ -1,199 +1,206 @@
-import { StyleSheet, View, Animated, TouchableOpacity } from 'react-native';
-import React, { useEffect, useContext, useState } from 'react';
-import { PlayerContext } from '../../../contexts/PlayerContext';
+import { StyleSheet, View, Animated, TouchableOpacity } from "react-native";
+import React, { useEffect, useContext, useState } from "react";
+import { PlayerContext } from "../../../contexts/PlayerContext";
import Feather from "react-native-vector-icons/Feather";
import Ionicons from "react-native-vector-icons/Ionicons";
-import { Easing } from 'react-native-reanimated';
-import TrackPlayer, { RepeatMode, State } from 'react-native-track-player';
-
-const PlayerFooter = ({ playState, onShuffle, setOnShuffle, playurlOverrider, playingIndex, nextActionOverrider, previousActionOverrider }) => {
- const [onRepeat, setOnRepeat] = useState(false)
- useEffect(()=>{
- const fetchRepeat = async () => {
- const repeatMode = await TrackPlayer.getRepeatMode();
- if(repeatMode !== RepeatMode.Off){
- setOnRepeat(true);
- }
- else{
- setOnRepeat(false);
- }
- }
- fetchRepeat();
- }, [])
- const {
- footerHeightAnim, albumMode,
- } = useContext(PlayerContext);
-
- useEffect(() => {
- Animated.timing(footerHeightAnim, {
- toValue: 100,
- duration: 400,
- useNativeDriver: false,
- easing: Easing.ease,
- }).start();
- }, [albumMode]);
-
-
- const handleOnRepeat = async () => {
- if(onRepeat){
- await TrackPlayer.setRepeatMode(RepeatMode.Off)
- setOnRepeat(false);
- }
- else {
- await TrackPlayer.setRepeatMode(RepeatMode.Queue);
- setOnRepeat(true);
- }
- };
-
- const handlePlayPause = async () => {
- if(playState===State.Playing){
- await TrackPlayer.pause();
- }
- else if(playState===State.Paused) {
- await TrackPlayer.play();
- }
- else if (playState===State.Error || playState===State.Ready || playState === State.None){
- await playurlOverrider(playingIndex);
- }
- };
-
- const handleOnShuffle = () => {
- setOnShuffle(!onShuffle);
- };
-
- const handleOnNext = async () => {
- await nextActionOverrider();
- };
-
- const handleOnPrevious = async () => {
- await previousActionOverrider();
- };
-
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
+import { Easing } from "react-native-reanimated";
+import TrackPlayer, { RepeatMode, State } from "react-native-track-player";
+
+const PlayerFooter = ({
+ playState,
+ onShuffle,
+ setOnShuffle,
+ playurlOverrider,
+ playingIndex,
+ nextActionOverrider,
+ previousActionOverrider,
+}) => {
+ const [onRepeat, setOnRepeat] = useState(false);
+ useEffect(() => {
+ const fetchRepeat = async () => {
+ const repeatMode = await TrackPlayer.getRepeatMode();
+ if (repeatMode !== RepeatMode.Off) {
+ setOnRepeat(true);
+ } else {
+ setOnRepeat(false);
+ }
+ };
+ fetchRepeat();
+ }, []);
+ const { footerHeightAnim, albumMode } = useContext(PlayerContext);
+
+ useEffect(() => {
+ Animated.timing(footerHeightAnim, {
+ toValue: 100,
+ duration: 400,
+ useNativeDriver: false,
+ easing: Easing.ease,
+ }).start();
+ }, [albumMode]);
+
+ const handleOnRepeat = async () => {
+ if (onRepeat) {
+ await TrackPlayer.setRepeatMode(RepeatMode.Off);
+ setOnRepeat(false);
+ } else {
+ await TrackPlayer.setRepeatMode(RepeatMode.Queue);
+ setOnRepeat(true);
+ }
+ };
+
+ const handlePlayPause = async () => {
+ if (playState === State.Playing) {
+ await TrackPlayer.pause();
+ } else if (playState === State.Paused) {
+ await TrackPlayer.play();
+ } else if (
+ playState === State.Error ||
+ playState === State.Ready ||
+ playState === State.None
+ ) {
+ await playurlOverrider(playingIndex);
+ }
+ };
+
+ const handleOnShuffle = () => {
+ setOnShuffle(!onShuffle);
+ };
+
+ const handleOnNext = async () => {
+ await nextActionOverrider();
+ };
+
+ const handleOnPrevious = async () => {
+ await previousActionOverrider();
+ };
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
};
export default PlayerFooter;
const styles = StyleSheet.create({
- footer: {
- minWidth: "100%",
- },
-
- footercontainer: {
- flex: 1,
- justifyContent: "space-between",
- alignItems: "center",
- flexDirection: "row",
- paddingHorizontal: 15,
- },
-
- shuffleRepeatButtons: {
- padding: 10,
- marginHorizontal: 5,
- borderRadius: 50,
- },
-
- prevNextSongMode: {
- backgroundColor: "#f5f5f4",
- shadowColor: "#010101",
- shadowOffset: {
- width: 0,
- height: 12,
- },
- shadowOpacity: 1.0,
- shadowRadius: 16.0,
- elevation: 24,
- zIndex: -2,
- },
-
- prevButton: {
- paddingRight: 15,
- marginRight: -5,
- paddingLeft: 10,
- borderBottomLeftRadius: 25,
- borderTopLeftRadius: 25,
- paddingVertical: 8,
- },
-
- nextButton: {
- paddingLeft: 15,
- marginLeft: -5,
- paddingRight: 10,
- borderBottomRightRadius: 25,
- borderTopRightRadius: 25,
- paddingVertical: 8,
- },
-
- playPauseControl: {
- flexDirection: "row",
- alignItems: "center",
- },
-
- playPauseButtonContainer: {
- height: 70,
- width: 70,
- borderRadius: 35,
- backgroundColor: "black",
- justifyContent: "center",
- alignItems: "center",
- },
-
- playPauseButton: {
- height: 30,
- width: 30,
- },
+ footer: {
+ minWidth: "100%",
+ },
+
+ footercontainer: {
+ flex: 1,
+ justifyContent: "space-between",
+ alignItems: "center",
+ flexDirection: "row",
+ paddingHorizontal: 15,
+ },
+
+ shuffleRepeatButtons: {
+ padding: 10,
+ marginHorizontal: 5,
+ borderRadius: 50,
+ },
+
+ prevNextSongMode: {
+ backgroundColor: "#f5f5f4",
+ shadowColor: "#010101",
+ shadowOffset: {
+ width: 0,
+ height: 12,
+ },
+ shadowOpacity: 1.0,
+ shadowRadius: 16.0,
+ elevation: 24,
+ zIndex: -2,
+ },
+
+ prevButton: {
+ paddingRight: 15,
+ marginRight: -5,
+ paddingLeft: 10,
+ borderBottomLeftRadius: 25,
+ borderTopLeftRadius: 25,
+ paddingVertical: 8,
+ },
+
+ nextButton: {
+ paddingLeft: 15,
+ marginLeft: -5,
+ paddingRight: 10,
+ borderBottomRightRadius: 25,
+ borderTopRightRadius: 25,
+ paddingVertical: 8,
+ },
+
+ playPauseControl: {
+ flexDirection: "row",
+ alignItems: "center",
+ },
+
+ playPauseButtonContainer: {
+ height: 70,
+ width: 70,
+ borderRadius: 35,
+ backgroundColor: "black",
+ justifyContent: "center",
+ alignItems: "center",
+ },
+
+ playPauseButton: {
+ height: 30,
+ width: 30,
+ },
});
diff --git a/src/screens/PlayerScreen/components/ProgressBarContainer.jsx b/src/screens/PlayerScreen/components/ProgressBarContainer.jsx
index 34e6b33..8de83d1 100644
--- a/src/screens/PlayerScreen/components/ProgressBarContainer.jsx
+++ b/src/screens/PlayerScreen/components/ProgressBarContainer.jsx
@@ -1,75 +1,69 @@
-import { StyleSheet, Animated, View } from 'react-native'
-import React, { useContext, useEffect } from 'react'
-import { PlayerContext } from '../../../contexts/PlayerContext'
-import { AnimatedCircularProgress } from 'react-native-circular-progress'
-import { Circle } from 'react-native-svg'
-import { Easing } from 'react-native-reanimated';
+import { StyleSheet, Animated, View } from "react-native";
+import React, { useContext, useEffect } from "react";
+import { PlayerContext } from "../../../contexts/PlayerContext";
+import { AnimatedCircularProgress } from "react-native-circular-progress";
+import { Circle } from "react-native-svg";
+import { Easing } from "react-native-reanimated";
-const ProgressBarContainer = ({totalDuration, currentDuration}) => {
- const { albumMode, progressBarOpacity } = useContext(PlayerContext);
- useEffect(() => {
- Animated.timing(progressBarOpacity, {
- toValue: albumMode ? 0 : 1,
- duration: 400,
- useNativeDriver: true,
- easing: Easing.ease,
- }).start();
- }, [albumMode])
+const ProgressBarContainer = ({ totalDuration, currentDuration }) => {
+ const { albumMode, progressBarOpacity } = useContext(PlayerContext);
+ useEffect(() => {
+ Animated.timing(progressBarOpacity, {
+ toValue: albumMode ? 0 : 1,
+ duration: 400,
+ useNativeDriver: true,
+ easing: Easing.ease,
+ }).start();
+ }, [albumMode]);
- return (
-
-
- (
-
- )}
- />
+ return (
+
+
+ (
+
+ )}
+ />
+
+
+ );
+};
-
-
- )
-}
-
-export default ProgressBarContainer
+export default ProgressBarContainer;
const styles = StyleSheet.create({
-
- progressBarContainer: {
- zIndex: -1,
- alignItems: "center",
- justifyContent: "center",
- minWidth: "100%",
- },
- progressBar: {
- marginTop: -240,
- width: 250,
- height: 100,
- borderBottomLeftRadius: 150,
- borderBottomRightRadius: 150,
- alignItems: "center",
- justifyContent: "center",
- transform: [{ rotateX: "180deg" }],
- },
-
-})
\ No newline at end of file
+ progressBarContainer: {
+ zIndex: -1,
+ alignItems: "center",
+ justifyContent: "center",
+ minWidth: "100%",
+ },
+ progressBar: {
+ marginTop: -240,
+ width: 250,
+ height: 100,
+ borderBottomLeftRadius: 150,
+ borderBottomRightRadius: 150,
+ alignItems: "center",
+ justifyContent: "center",
+ transform: [{ rotateX: "180deg" }],
+ },
+});
diff --git a/src/screens/SearchScreen/SearchScreen.jsx b/src/screens/SearchScreen/SearchScreen.jsx
index d4e020d..2c575e1 100644
--- a/src/screens/SearchScreen/SearchScreen.jsx
+++ b/src/screens/SearchScreen/SearchScreen.jsx
@@ -1,47 +1,50 @@
-import { StyleSheet, Text, View } from 'react-native'
-import React, { useEffect, useState } from 'react'
-import Navbar from './components/Navbar'
+import { StyleSheet, Text, View } from "react-native";
+import React, { useEffect, useState } from "react";
+import Navbar from "./components/Navbar";
import ModeSelector from "./components/ModeSelector";
import SearchList from "./components/SearchList";
import ServiceProvider from "../../libs/APIParser";
const SearchScreen = () => {
- const [searchInput, setSearchInput] = useState("");
- const [searchType, setSearchType] = useState(1);
- const [timer, setTimer] = useState(null);
- const [resp, setResp] = useState(null);
+ const [searchInput, setSearchInput] = useState("");
+ const [searchType, setSearchType] = useState(1);
+ const [timer, setTimer] = useState(null);
+ const [resp, setResp] = useState(null);
- const serviceProvider = new ServiceProvider();
+ const serviceProvider = new ServiceProvider();
- useEffect(() => {
- if (searchInput.trim() !== "") {
- if (timer) {
- clearTimeout(timer);
- }
- const newTimer = setTimeout(async () => {
- const response = await serviceProvider.getSearch(encodeURIComponent(searchInput), 1, searchType);
- setResp(response?.results);
- }, 1000);
- setTimer(newTimer);
- }
- else {
- const fetchRecommendData = async () => {
- const response = await serviceProvider.getTopSearches();
- setResp(response);
- }
- fetchRecommendData();
- }
- }, [searchInput, searchType]);
+ useEffect(() => {
+ if (searchInput.trim() !== "") {
+ if (timer) {
+ clearTimeout(timer);
+ }
+ const newTimer = setTimeout(async () => {
+ const response = await serviceProvider.getSearch(
+ encodeURIComponent(searchInput),
+ 1,
+ searchType,
+ );
+ setResp(response?.results);
+ }, 1000);
+ setTimer(newTimer);
+ } else {
+ const fetchRecommendData = async () => {
+ const response = await serviceProvider.getTopSearches();
+ setResp(response);
+ };
+ fetchRecommendData();
+ }
+ }, [searchInput, searchType]);
- return (
-
-
-
-
-
- )
-}
+ return (
+
+
+
+
+
+ );
+};
-export default SearchScreen
+export default SearchScreen;
-const styles = StyleSheet.create({})
\ No newline at end of file
+const styles = StyleSheet.create({});
diff --git a/src/screens/SearchScreen/components/ModeSelector.jsx b/src/screens/SearchScreen/components/ModeSelector.jsx
index c58a48d..91ad3e6 100644
--- a/src/screens/SearchScreen/components/ModeSelector.jsx
+++ b/src/screens/SearchScreen/components/ModeSelector.jsx
@@ -1,37 +1,37 @@
-import { StyleSheet, View } from 'react-native'
-import React from 'react'
+import { StyleSheet, View } from "react-native";
+import React from "react";
import SwitchSelector from "react-native-switch-selector";
const ModeSelector = ({ setSearchType, searchType }) => {
- const options = [
- { label: "Playlists", value: 0 },
- { label: "Songs", value: 1 },
- { label: "Albums", value: 2 },
- { label: "Artists", value: 4 }
- ];
+ const options = [
+ { label: "Playlists", value: 0 },
+ { label: "Songs", value: 1 },
+ { label: "Albums", value: 2 },
+ { label: "Artists", value: 4 },
+ ];
- return (
-
- setSearchType(value)}
- hasPadding
- buttonColor="#000"
- textColor="#333"
- height={48}
- fontSize={14}
- borderRadius={25}
- />
-
- )
-}
+ return (
+
+ setSearchType(value)}
+ hasPadding
+ buttonColor="#000"
+ textColor="#333"
+ height={48}
+ fontSize={14}
+ borderRadius={25}
+ />
+
+ );
+};
-export default ModeSelector
+export default ModeSelector;
const styles = StyleSheet.create({
- selectorContainer: {
- paddingHorizontal: 10,
- paddingBottom: 10
- }
+ selectorContainer: {
+ paddingHorizontal: 10,
+ paddingBottom: 10,
+ },
});
diff --git a/src/screens/SearchScreen/components/Navbar.jsx b/src/screens/SearchScreen/components/Navbar.jsx
index 88a39d8..f4a7074 100644
--- a/src/screens/SearchScreen/components/Navbar.jsx
+++ b/src/screens/SearchScreen/components/Navbar.jsx
@@ -1,49 +1,49 @@
-import { StyleSheet, TextInput, TouchableOpacity, View } from 'react-native'
-import React from 'react'
+import { StyleSheet, TextInput, TouchableOpacity, View } from "react-native";
+import React from "react";
import Ionicons from "react-native-vector-icons/Ionicons";
-import { useNavigation } from '@react-navigation/native';
+import { useNavigation } from "@react-navigation/native";
const Navbar = ({ setSearchInput }) => {
- const navigator = useNavigation();
- const handleBack = () => {
- navigator.goBack();
- }
- return (
-
-
-
-
- setSearchInput(input)}
- />
-
- );
-}
+ const navigator = useNavigation();
+ const handleBack = () => {
+ navigator.goBack();
+ };
+ return (
+
+
+
+
+ setSearchInput(input)}
+ />
+
+ );
+};
-export default Navbar
+export default Navbar;
const styles = StyleSheet.create({
- searchContainer: {
- flexDirection: 'row',
- alignItems: 'center',
- paddingHorizontal: 15,
- backgroundColor: '#f0f0f0',
- margin: 10,
- marginTop: 25
- },
- searchInputBox: {
- flex: 1,
- marginLeft: 15,
- backgroundColor: '#fff',
- borderRadius: 25,
- paddingVertical: 10,
- paddingHorizontal: 15,
- fontSize: 16,
- color: '#333',
- borderWidth: 1,
- borderColor: '#ddd',
- }
+ searchContainer: {
+ flexDirection: "row",
+ alignItems: "center",
+ paddingHorizontal: 15,
+ backgroundColor: "#f0f0f0",
+ margin: 10,
+ marginTop: 25,
+ },
+ searchInputBox: {
+ flex: 1,
+ marginLeft: 15,
+ backgroundColor: "#fff",
+ borderRadius: 25,
+ paddingVertical: 10,
+ paddingHorizontal: 15,
+ fontSize: 16,
+ color: "#333",
+ borderWidth: 1,
+ borderColor: "#ddd",
+ },
});
diff --git a/src/screens/SearchScreen/components/SearchList.jsx b/src/screens/SearchScreen/components/SearchList.jsx
index 0c6d3c4..638a512 100644
--- a/src/screens/SearchScreen/components/SearchList.jsx
+++ b/src/screens/SearchScreen/components/SearchList.jsx
@@ -1,27 +1,29 @@
-import { StyleSheet } from 'react-native'
-import React from 'react'
-import MasonryList from '@react-native-seoul/masonry-list';
+import { StyleSheet } from "react-native";
+import React from "react";
+import MasonryList from "@react-native-seoul/masonry-list";
import Card from "../../AlbumsScreen/components/Card";
-const SearchList = ({ searchData }) => {
- const renderCard = ({ item, index }) => (
-
- );
- return searchData && (
- item.id}
- numColumns={2}
- showsVerticalScrollIndicator={false}
- renderItem={renderCard}
- onEndReachedThreshold={0.1}
- />
- )
-}
+const SearchList = ({ searchData }) => {
+ const renderCard = ({ item, index }) => (
+
+ );
+ return (
+ searchData && (
+ item.id}
+ numColumns={2}
+ showsVerticalScrollIndicator={false}
+ renderItem={renderCard}
+ onEndReachedThreshold={0.1}
+ />
+ )
+ );
+};
-export default SearchList
+export default SearchList;
const styles = StyleSheet.create({
- container: {
- flex: 1
- },
-})
\ No newline at end of file
+ container: {
+ flex: 1,
+ },
+});
diff --git a/src/screens/SettingsScreen/SettingsScreen.jsx b/src/screens/SettingsScreen/SettingsScreen.jsx
index f2c94b5..aa5fc84 100644
--- a/src/screens/SettingsScreen/SettingsScreen.jsx
+++ b/src/screens/SettingsScreen/SettingsScreen.jsx
@@ -1,14 +1,14 @@
-import { StyleSheet, Text, View } from 'react-native'
-import React from 'react'
+import { StyleSheet, Text, View } from "react-native";
+import React from "react";
const SettingsScreen = () => {
- return (
-
- SettingsScreen
-
- )
-}
+ return (
+
+ SettingsScreen
+
+ );
+};
-export default SettingsScreen
+export default SettingsScreen;
-const styles = StyleSheet.create({})
\ No newline at end of file
+const styles = StyleSheet.create({});
diff --git a/src/screens/VersionScreen/VersionScreen.jsx b/src/screens/VersionScreen/VersionScreen.jsx
index a560963..5f6a3bb 100644
--- a/src/screens/VersionScreen/VersionScreen.jsx
+++ b/src/screens/VersionScreen/VersionScreen.jsx
@@ -1,14 +1,14 @@
-import { StyleSheet, Text, View } from 'react-native'
-import React from 'react'
+import { StyleSheet, Text, View } from "react-native";
+import React from "react";
import { expo } from "../../../app.json";
const VersionScreen = () => {
- return (
-
- {expo.version}
-
- )
-}
+ return (
+
+ {expo.version}
+
+ );
+};
-export default VersionScreen
+export default VersionScreen;
-const styles = StyleSheet.create({})
\ No newline at end of file
+const styles = StyleSheet.create({});
diff --git a/src/utils/RNTPService.js b/src/utils/RNTPService.js
index 7f56a43..6cda264 100644
--- a/src/utils/RNTPService.js
+++ b/src/utils/RNTPService.js
@@ -1,6 +1,6 @@
-import TrackPlayer, { Event } from 'react-native-track-player'
+import TrackPlayer, { Event } from "react-native-track-player";
export const RNTPService = async () => {
- TrackPlayer.addEventListener(Event.RemotePlay, () => TrackPlayer.play())
- TrackPlayer.addEventListener(Event.RemotePause, () => TrackPlayer.pause())
-}
\ No newline at end of file
+ TrackPlayer.addEventListener(Event.RemotePlay, () => TrackPlayer.play());
+ TrackPlayer.addEventListener(Event.RemotePause, () => TrackPlayer.pause());
+};
diff --git a/src/utils/albumParser.js b/src/utils/albumParser.js
index fb06774..0a97d62 100644
--- a/src/utils/albumParser.js
+++ b/src/utils/albumParser.js
@@ -1,130 +1,127 @@
-import ServiceProvider from '../libs/APIParser';
+import ServiceProvider from "../libs/APIParser";
const serviceProvider = new ServiceProvider();
-const handleAlbum = async ({
- albumData, image_, title_, navigation
-}) => {
- let playData = {};
- const albumType = albumData.type;
- let itemId;
- let data;
+const handleAlbum = async ({ albumData, image_, title_, navigation }) => {
+ let playData = {};
+ const albumType = albumData.type;
+ let itemId;
+ let data;
- try {
- switch (albumType) {
- case "show":
- console.log(albumData);
- break;
- case "album":
- itemId = albumData.perma_url.split("/").slice(-1);
- data = await serviceProvider.getAlbumById(itemId);
- playData = {
- id: itemId,
- albumName: data.title,
- albumCover: data.image.replace("150x150", "500x500"),
- items: data.list.map((item, i) => {
- return {
- id: item.id,
- songName: item.title,
- duration: item.more_info.duration,
- songCover: item.image.replace("150x150", "500x500"),
- playUrl: item.more_info.encrypted_media_url,
- artistName: data.subtitle,
- };
- }),
- };
- break;
- case "radio_station":
- itemId = albumData.id;
- data = await serviceProvider.getStationById(itemId);
- delete data["stationid"];
- playData = {
- id: itemId,
- albumName: title_,
- albumCover: image_.replace("150x150", "500x500"),
- items: Object.keys(data).map((key, i) => {
- const item = data[key].song;
- return {
- id: item.id,
- songName: item.title,
- duration: item.more_info.duration,
- songCover: item.image.replace("150x150", "500x500"),
- playUrl: item.more_info.encrypted_media_url,
- artistName: 'Various Artists',
- };
- }),
- };
- break;
- case "song":
- itemId = albumData.id;
- data = await serviceProvider.getSongById(itemId);
- playData = {
- id: itemId,
- albumName: data.song,
- albumCover: data.image.replace("150x150", "500x500"),
- items: [
- {
- id: itemId,
- songName: data.song,
- duration: data.duration,
- songCover: data.image.replace("150x150", "500x500"),
- playUrl: data.encrypted_media_url,
- artistName: data.primary_artists,
- }
- ]
- };
- break;
- case "playlist":
- itemId = albumData.id;
- data = await serviceProvider.getPlaylistById(itemId);
- playData = {
- id: itemId,
- albumName: data.listname,
- albumCover: data.image.replace("150x150", "500x500"),
- items: data.songs.map((item, i) => {
- return {
- id: item.id,
- songName: item.song,
- duration: item.duration,
- songCover: item.image.replace("150x150", "500x500"),
- playUrl: item.encrypted_media_url,
- artistName: data.firstname,
- };
- }),
- };
- break;
- case "artist":
- itemId = albumData.artistid || albumData.id;
- data = await serviceProvider.getArtist(itemId, 50);
- playData = {
- id: itemId,
- albumName: data.name,
- albumCover: data.image.replace("150x150", "500x500"),
- items: data.topSongs.map((item, i) => {
- return {
- id: item.id,
- songName: item.song,
- duration: item.duration,
- songCover: item.image.replace("150x150", "500x500"),
- playUrl: item.encrypted_media_url,
- artistName: 'Artist',
- };
- }),
- };
- break;
- default:
- break;
- }
+ try {
+ switch (albumType) {
+ case "show":
+ console.log(albumData);
+ break;
+ case "album":
+ itemId = albumData.perma_url.split("/").slice(-1);
+ data = await serviceProvider.getAlbumById(itemId);
+ playData = {
+ id: itemId,
+ albumName: data.title,
+ albumCover: data.image.replace("150x150", "500x500"),
+ items: data.list.map((item, i) => {
+ return {
+ id: item.id,
+ songName: item.title,
+ duration: item.more_info.duration,
+ songCover: item.image.replace("150x150", "500x500"),
+ playUrl: item.more_info.encrypted_media_url,
+ artistName: data.subtitle,
+ };
+ }),
+ };
+ break;
+ case "radio_station":
+ itemId = albumData.id;
+ data = await serviceProvider.getStationById(itemId);
+ delete data["stationid"];
+ playData = {
+ id: itemId,
+ albumName: title_,
+ albumCover: image_.replace("150x150", "500x500"),
+ items: Object.keys(data).map((key, i) => {
+ const item = data[key].song;
+ return {
+ id: item.id,
+ songName: item.title,
+ duration: item.more_info.duration,
+ songCover: item.image.replace("150x150", "500x500"),
+ playUrl: item.more_info.encrypted_media_url,
+ artistName: "Various Artists",
+ };
+ }),
+ };
+ break;
+ case "song":
+ itemId = albumData.id;
+ data = await serviceProvider.getSongById(itemId);
+ playData = {
+ id: itemId,
+ albumName: data.song,
+ albumCover: data.image.replace("150x150", "500x500"),
+ items: [
+ {
+ id: itemId,
+ songName: data.song,
+ duration: data.duration,
+ songCover: data.image.replace("150x150", "500x500"),
+ playUrl: data.encrypted_media_url,
+ artistName: data.primary_artists,
+ },
+ ],
+ };
+ break;
+ case "playlist":
+ itemId = albumData.id;
+ data = await serviceProvider.getPlaylistById(itemId);
+ playData = {
+ id: itemId,
+ albumName: data.listname,
+ albumCover: data.image.replace("150x150", "500x500"),
+ items: data.songs.map((item, i) => {
+ return {
+ id: item.id,
+ songName: item.song,
+ duration: item.duration,
+ songCover: item.image.replace("150x150", "500x500"),
+ playUrl: item.encrypted_media_url,
+ artistName: data.firstname,
+ };
+ }),
+ };
+ break;
+ case "artist":
+ itemId = albumData.artistid || albumData.id;
+ data = await serviceProvider.getArtist(itemId, 50);
+ playData = {
+ id: itemId,
+ albumName: data.name,
+ albumCover: data.image.replace("150x150", "500x500"),
+ items: data.topSongs.map((item, i) => {
+ return {
+ id: item.id,
+ songName: item.song,
+ duration: item.duration,
+ songCover: item.image.replace("150x150", "500x500"),
+ playUrl: item.encrypted_media_url,
+ artistName: "Artist",
+ };
+ }),
+ };
+ break;
+ default:
+ break;
+ }
- if (playData.items && playData.items.length > 0) {
- navigation.navigate('AlbumViewerScreen', {
- data: playData
- });
- }
- } catch (error) {
- console.error('Error handling album:', error);
- }
+ if (playData.items && playData.items.length > 0) {
+ navigation.navigate("AlbumViewerScreen", {
+ data: playData,
+ });
+ }
+ } catch (error) {
+ console.error("Error handling album:", error);
+ }
};
-
-export default handleAlbum
\ No newline at end of file
+export default handleAlbum;
diff --git a/src/utils/setupPlayer.js b/src/utils/setupPlayer.js
index 0028de4..fa4555a 100644
--- a/src/utils/setupPlayer.js
+++ b/src/utils/setupPlayer.js
@@ -1,30 +1,29 @@
import TrackPlayer, {
- AppKilledPlaybackBehavior,
- Capability,
-} from 'react-native-track-player'
+ AppKilledPlaybackBehavior,
+ Capability,
+} from "react-native-track-player";
const setupPlayer = async () => {
- await TrackPlayer.setupPlayer({
- autoHandleInterruptions: true
- })
+ await TrackPlayer.setupPlayer({
+ autoHandleInterruptions: true,
+ });
- await TrackPlayer.updateOptions({
- waitForBuffer: true,
- android: {
- appKilledPlaybackBehavior:
- AppKilledPlaybackBehavior.PausePlayback,
- alwaysPauseOnInterruption: true,
- },
- capabilities: [
- Capability.Play,
- Capability.Pause,
- Capability.SkipToNext,
- Capability.SkipToPrevious,
- Capability.SeekTo,
- ],
- compactCapabilities: [Capability.Play, Capability.Pause],
- progressUpdateEventInterval: 1,
- })
-}
+ await TrackPlayer.updateOptions({
+ waitForBuffer: true,
+ android: {
+ appKilledPlaybackBehavior: AppKilledPlaybackBehavior.PausePlayback,
+ alwaysPauseOnInterruption: true,
+ },
+ capabilities: [
+ Capability.Play,
+ Capability.Pause,
+ Capability.SkipToNext,
+ Capability.SkipToPrevious,
+ Capability.SeekTo,
+ ],
+ compactCapabilities: [Capability.Play, Capability.Pause],
+ progressUpdateEventInterval: 1,
+ });
+};
-export default setupPlayer
\ No newline at end of file
+export default setupPlayer;
diff --git a/src/utils/utilityButtonActions.js b/src/utils/utilityButtonActions.js
index 2fc6a04..47148f6 100644
--- a/src/utils/utilityButtonActions.js
+++ b/src/utils/utilityButtonActions.js
@@ -1,50 +1,53 @@
import { ToastAndroid } from "react-native";
const utilityButtonActions = async (action, props = {}) => {
- const handlePlayAction = async () => {
- if (props.addedToPlaylist) return;
- props.addTracks(props.trackList)
- props.setAddedToPlaylist(true);
- ToastAndroid.show(`${props.trackList.items.length} items added to playlist`, ToastAndroid.SHORT);
- props.navigation.navigate('PlayerScreen');
- }
+ const handlePlayAction = async () => {
+ if (props.addedToPlaylist) return;
+ props.addTracks(props.trackList);
+ props.setAddedToPlaylist(true);
+ ToastAndroid.show(
+ `${props.trackList.items.length} items added to playlist`,
+ ToastAndroid.SHORT,
+ );
+ props.navigation.navigate("PlayerScreen");
+ };
- const handleLikeAction = async () => {
- ToastAndroid.show('Not implemented yet', ToastAndroid.SHORT);
- Object.keys(props.likedList).includes(props.trackList)
- }
+ const handleLikeAction = async () => {
+ ToastAndroid.show("Not implemented yet", ToastAndroid.SHORT);
+ Object.keys(props.likedList).includes(props.trackList);
+ };
- const handleDownloadAction = async () => {
- ToastAndroid.show('Not implemented yet', ToastAndroid.SHORT);
- }
-
- const handleEntangleAction = async () => {
- ToastAndroid.show('Not implemented yet', ToastAndroid.SHORT);
- }
-
- const handleShareAction = async () => {
- ToastAndroid.show('Not implemented yet', ToastAndroid.SHORT);
- }
+ const handleDownloadAction = async () => {
+ ToastAndroid.show("Not implemented yet", ToastAndroid.SHORT);
+ };
- switch (action) {
- case 'like':
- await handleLikeAction()
- break;
- case 'play':
- await handlePlayAction();
- break;
- case 'download':
- await handleDownloadAction();
- break;
- case 'entanglement':
- await handleEntangleAction();
- break;
- case 'share':
- await handleShareAction();
- break;
- default:
- break;
- }
-}
+ const handleEntangleAction = async () => {
+ ToastAndroid.show("Not implemented yet", ToastAndroid.SHORT);
+ };
-export default utilityButtonActions
\ No newline at end of file
+ const handleShareAction = async () => {
+ ToastAndroid.show("Not implemented yet", ToastAndroid.SHORT);
+ };
+
+ switch (action) {
+ case "like":
+ await handleLikeAction();
+ break;
+ case "play":
+ await handlePlayAction();
+ break;
+ case "download":
+ await handleDownloadAction();
+ break;
+ case "entanglement":
+ await handleEntangleAction();
+ break;
+ case "share":
+ await handleShareAction();
+ break;
+ default:
+ break;
+ }
+};
+
+export default utilityButtonActions;