diff --git a/jukebox/App.js b/jukebox/App.js index aedafe3..c6eae34 100644 --- a/jukebox/App.js +++ b/jukebox/App.js @@ -7,6 +7,7 @@ import HomeScreen from "./src/screens/HomeScreen"; import { createContext, useState, useContext } from "react"; import LikedTracksScreen from "./src/screens/LikedTracksScreen"; import AlbumScreen from "./src/screens/AlbumScreen"; +import { LibraryProvider } from "./src/contexts/LibraryContext"; const Stack = createNativeStackNavigator(); @@ -63,7 +64,9 @@ function RootLayout() { export default function App() { return ( - + + + ); } diff --git a/jukebox/package-lock.json b/jukebox/package-lock.json index 1f27ad9..04b6227 100644 --- a/jukebox/package-lock.json +++ b/jukebox/package-lock.json @@ -8939,9 +8939,9 @@ } }, "node_modules/tar": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.9.tgz", - "integrity": "sha512-BTLcK0xsDh2+PUe9F6c2TlRp4zOOBMTkoQHQIWSIzI0R7KG46uEwq4OPk2W7bZcprBMsuaeFsqwYr7pjh6CuHg==", + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.10.tgz", + "integrity": "sha512-8mOPs1//5q/rlkNSPcCegA6hiHJYDmSLEI8aMH/CdSQJNWztHC9WHNam5zdQlfpTwB9Xp7IBEsHfV5LKMJGVAw==", "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/fs-minipass": "^4.0.0", diff --git a/jukebox/src/components/DurationFormatter.js b/jukebox/src/components/DurationFormatter.js new file mode 100644 index 0000000..21b465e --- /dev/null +++ b/jukebox/src/components/DurationFormatter.js @@ -0,0 +1,13 @@ +export const durationFormatter = (totalSeconds = 0) => { + const s = Math.max(0, Math.floor(totalSeconds)); + + const hours = Math.floor(s / 3600); + const minutes = Math.floor((s % 3600) / 60); + const seconds = s % 60; + + if (hours > 0) { + return `${hours}:${String(minutes).padStart(2, "0")}:${String(seconds).padStart(2, "0")}`; + } + + return `${minutes}:${String(seconds).padStart(2, "0")}`; +}; \ No newline at end of file diff --git a/jukebox/src/components/TrackRow.js b/jukebox/src/components/TrackRow.js index 35c99d4..53500f2 100644 --- a/jukebox/src/components/TrackRow.js +++ b/jukebox/src/components/TrackRow.js @@ -1,5 +1,6 @@ import React from 'react'; import { Pressable, View, Text, StyleSheet, Image } from 'react-native'; +import { durationFormatter } from './DurationFormatter'; export default function TrackRow({ title, @@ -7,8 +8,8 @@ export default function TrackRow({ duration, cover, onPress, - showHeart = true, - liked = false, // new prop + liked = false, + onToggleLike, }) { return ( @@ -23,13 +24,13 @@ export default function TrackRow({ - {duration ? {duration} : null} + {duration ? {durationFormatter(duration)} : "0"} - {showHeart ? ( + {liked ? '♥' : '♡'} - ) : null} + ); } diff --git a/jukebox/src/components/album_cover.js b/jukebox/src/components/album_cover.js deleted file mode 100644 index e69de29..0000000 diff --git a/jukebox/src/contexts/LibraryContext.js b/jukebox/src/contexts/LibraryContext.js new file mode 100644 index 0000000..1226193 --- /dev/null +++ b/jukebox/src/contexts/LibraryContext.js @@ -0,0 +1,51 @@ +import React, { createContext, useContext, useMemo, useState } from "react"; +import initialLibrary from "../data/library"; + +const LibraryContext = createContext(null); + +export function LibraryProvider({ children }) { + const [albums, setAlbums] = useState(initialLibrary); + + const toggleLike = (albumId, trackId) => { + setAlbums((prev) => + prev.map((album) => + album.id !== albumId + ? album + : { + ...album, + tracks: album.tracks.map((t) => + t.id === trackId ? { ...t, liked: !t.liked } : t + ), + } + ) + ); + }; + + const likedTracks = useMemo( + () => + albums.flatMap((album) => + album.tracks + .filter((track) => track.liked) + .map((track) => ({ + ...track, + albumId: album.id, + albumTitle: album.title, + artist: album.artist, + cover: album.cover, + })) + ), + [albums] + ); + + return ( + + {children} + + ); +} + +export function useLibrary() { + const ctx = useContext(LibraryContext); + if (!ctx) throw new Error("useLibrary must be used inside LibraryProvider"); + return ctx; +} \ No newline at end of file diff --git a/jukebox/src/data/library.js b/jukebox/src/data/library.js index c76e2dc..2f5e4d3 100644 --- a/jukebox/src/data/library.js +++ b/jukebox/src/data/library.js @@ -5,35 +5,35 @@ const library = [ artist: 'Swans', date: '1996-11-29', label: 'Young God Records', - duration: '2:21:25', + duration: 8485, cover: require('../../assets/covers/soundtracksfortheblind.jpg'), tracks: [ - { id: 'a1t1', title: 'Red Velvet Corridor', duration: '3:03', liked: true }, - { id: 'a1t2', title: 'I Was a Prisoner in Your Skull', duration: '6:39', liked: false }, - { id: 'a1t3', title: 'Helpless Child', duration: '15:47', liked: true }, - { id: 'a1t4', title: 'Live Through Me', duration: '2:19', liked: false }, - { id: 'a1t5', title: 'Yum-Yab Killers', duration: '5:07', liked: false }, - { id: 'a1t6', title: 'The Beautiful Days', duration: '1:50', liked: false }, - { id: 'a1t7', title: 'Volcano', duration: '5:18', liked: false }, - { id: 'a1t8', title: 'Mellothumb', duration: '2:45', liked: false }, - { id: 'a1t9', title: 'All Lined Up', duration: '4:48', liked: false }, - { id: 'a1t10', title: 'Surrogate Drone', duration: '2:03', liked: false }, - { id: 'a1t11', title: 'How They Suffer', duration: '5:52', liked: false }, - { id: 'a1t12', title: 'Animus', duration: '10:43', liked: false }, - { id: 'a1t13', title: 'Red Velvet Wound', duration: '1:01', liked: false }, - { id: 'a1t14', title: 'The Sound', duration: '13:11', liked: true }, - { id: 'a1t15', title: 'Her Mouth Is Filled with Honey', duration: '3:18', liked: false }, - { id: 'a1t16', title: 'Blood Section', duration: '2:45', liked: false }, - { id: 'a1t17', title: 'Hypogirl', duration: '3:42', liked: false }, - { id: 'a1t18', title: 'Minus Something', duration: '4:14', liked: false }, - { id: 'a1t19', title: 'Empathy', duration: '6:45', liked: false }, - { id: 'a1t20', title: 'I Love You This Much', duration: '7:23', liked: false }, - { id: 'a1t21', title: "YRP", duration: '7:58', liked: false }, - { id: 'a1t22', title: "Fan's Lament", duration: '1:47', liked: false }, - { id: 'a1t23', title: 'Secret Friends', duration: '3:08', liked: false }, - { id: 'a1t24', title: 'The Final Sacrifice', duration: '9:51', liked: false }, - { id: 'a1t25', title: 'YRP 2', duration: '2:09', liked: false }, - { id: 'a1t26', title: 'Surrogate 2', duration: '1:55', liked: false }, + { id: 'a1t1', title: 'Red Velvet Corridor', duration: 183, liked: true }, + { id: 'a1t2', title: 'I Was a Prisoner in Your Skull', duration: 399, liked: false }, + { id: 'a1t3', title: 'Helpless Child', duration: 947, liked: true }, + { id: 'a1t4', title: 'Live Through Me', duration: 139, liked: false }, + { id: 'a1t5', title: 'Yum-Yab Killers', duration: 307, liked: false }, + { id: 'a1t6', title: 'The Beautiful Days', duration: 110, liked: false }, + { id: 'a1t7', title: 'Volcano', duration: 318, liked: false }, + { id: 'a1t8', title: 'Mellothumb', duration: 165, liked: false }, + { id: 'a1t9', title: 'All Lined Up', duration: 288, liked: false }, + { id: 'a1t10', title: 'Surrogate Drone', duration: 123, liked: false }, + { id: 'a1t11', title: 'How They Suffer', duration: 352, liked: false }, + { id: 'a1t12', title: 'Animus', duration: 643, liked: false }, + { id: 'a1t13', title: 'Red Velvet Wound', duration: 61, liked: false }, + { id: 'a1t14', title: 'The Sound', duration: 791, liked: true }, + { id: 'a1t15', title: 'Her Mouth Is Filled with Honey', duration: 198, liked: false }, + { id: 'a1t16', title: 'Blood Section', duration: 165, liked: false }, + { id: 'a1t17', title: 'Hypogirl', duration: 222, liked: false }, + { id: 'a1t18', title: 'Minus Something', duration: 254, liked: false }, + { id: 'a1t19', title: 'Empathy', duration: 405, liked: false }, + { id: 'a1t20', title: 'I Love You This Much', duration: 443, liked: false }, + { id: 'a1t21', title: "YRP", duration: 478, liked: false }, + { id: 'a1t22', title: "Fan's Lament", duration: 107, liked: false }, + { id: 'a1t23', title: 'Secret Friends', duration: 188, liked: false }, + { id: 'a1t24', title: 'The Final Sacrifice', duration: 591, liked: false }, + { id: 'a1t25', title: 'YRP 2', duration: 129, liked: false }, + { id: 'a1t26', title: 'Surrogate 2', duration: 115, liked: false }, ], }, { @@ -42,23 +42,23 @@ const library = [ artist: 'Daft Punk', date: '2001-03-12', label: 'Virgin Records', - duration: '1:00:50', + duration: 3650, cover: require('../../assets/covers/discovery.jpg'), tracks: [ - { id: 'a2t1', title: 'One More Time', duration: '5:20', liked: true }, - { id: 'a2t2', title: 'Aerodynamic', duration: '3:27', liked: false }, - { id: 'a2t3', title: 'Digital Love', duration: '4:58', liked: false }, - { id: 'a2t4', title: 'Harder, Better, Faster, Stronger', duration: '3:45', liked: false }, - { id: 'a2t5', title: 'Crescendolls', duration: '3:31', liked: false }, - { id: 'a2t6', title: 'Nightvision', duration: '1:44', liked: false }, - { id: 'a2t7', title: 'Superheroes', duration: '3:57', liked: false }, - { id: 'a2t8', title: 'High Life', duration: '3:21', liked: false }, - { id: 'a2t9', title: 'Something About Us', duration: '3:51', liked: false }, - { id: 'a2t10', title: 'Voyager', duration: '3:47', liked: false }, - { id: 'a2t11', title: 'Veridis Quo', duration: '5:44', liked: false }, - { id: 'a2t12', title: 'Short Circuit', duration: '3:26', liked: false }, - { id: 'a2t13', title: 'Face to Face', duration: '4:00', liked: false }, - { id: 'a2t14', title: 'Too Long', duration: '10:00', liked: false }, + { id: 'a2t1', title: 'One More Time', duration: 320, liked: true }, + { id: 'a2t2', title: 'Aerodynamic', duration: 207, liked: false }, + { id: 'a2t3', title: 'Digital Love', duration: 298, liked: false }, + { id: 'a2t4', title: 'Harder, Better, Faster, Stronger', duration: 225, liked: false }, + { id: 'a2t5', title: 'Crescendolls', duration: 211, liked: false }, + { id: 'a2t6', title: 'Nightvision', duration: 104, liked: false }, + { id: 'a2t7', title: 'Superheroes', duration: 237, liked: false }, + { id: 'a2t8', title: 'High Life', duration: 201, liked: false }, + { id: 'a2t9', title: 'Something About Us', duration: 231, liked: false }, + { id: 'a2t10', title: 'Voyager', duration: 227, liked: false }, + { id: 'a2t11', title: 'Veridis Quo', duration: 344, liked: false }, + { id: 'a2t12', title: 'Short Circuit', duration: 206, liked: false }, + { id: 'a2t13', title: 'Face to Face', duration: 240, liked: false }, + { id: 'a2t14', title: 'Too Long', duration: 600, liked: false }, ], }, ]; diff --git a/jukebox/src/screens/AlbumScreen.js b/jukebox/src/screens/AlbumScreen.js index 5a23488..bd7148e 100644 --- a/jukebox/src/screens/AlbumScreen.js +++ b/jukebox/src/screens/AlbumScreen.js @@ -1,122 +1,106 @@ -import React from 'react'; +import React, { useMemo } from 'react'; import { View, Text, StyleSheet, FlatList, Pressable, Image } from 'react-native'; import TrackRow from '../components/TrackRow'; +import { useLibrary } from '../contexts/LibraryContext'; +import { durationFormatter } from '../components/DurationFormatter'; export default function AlbumScreen({ route, navigation }) { - const { album } = route.params; - return ( - - navigation.goBack()} style={styles.backBtn}> - ← Back - - - - {album.title} - {album.artist} - {album.date} · {album.label} · {album.duration} - + const { album: routeAlbum } = route.params; + const { albums, toggleLike } = useLibrary(); - item.id ?? index.toString()} - renderItem={({ item }) => ( - { }} - showHeart={true} - liked={item.liked} - /> - )} - contentContainerStyle={styles.trackList} - /> - - ); + // Always use latest album from context (so likes stay in sync) + const album = useMemo( + () => albums.find((a) => a.id === routeAlbum.id) ?? routeAlbum, + [albums, routeAlbum] + ); + + return ( + + navigation.goBack()} style={styles.backBtn}> + ← Back + + + + + {album.title} + {album.artist} + + {album.date} · {album.label} · {durationFormatter(album.duration)} + + + + item.id ?? index.toString()} + renderItem={({ item }) => ( + {}} + showHeart={true} + liked={item.liked} + onToggleLike={() => toggleLike(album.id, item.id)} + /> + )} + contentContainerStyle={styles.trackList} + /> + + ); } const styles = StyleSheet.create({ - container: { - flex: 1, - backgroundColor: '#000', - paddingTop: 28, - paddingHorizontal: 16, - paddingBottom: 24, - }, - header: { - alignItems: 'center', - }, - cover: { - width: 180, - height: 180, - borderRadius: 8, - marginBottom: 12, - }, - title: { - color: '#fff', - fontSize: 32, - fontWeight: '700', - textAlign: 'center', - marginBottom: 1, - }, - artist: { - color: '#fff', - fontSize: 26, - fontWeight: '500', - textAlign: 'center', - marginTop: 1, - }, - meta: { - color: '#fff', - fontSize: 14, - fontWeight: '500', - textAlign: 'center', - marginTop: 8, - marginBottom: 24, - }, - trackList: { - width: '100%', - paddingHorizontal: 16, - paddingBottom: 180, - }, - trackItem: { - width: '100%', - minHeight: 62, - padding: 0, - flexDirection: 'row', - }, - trackTextBlock: { - flex: 1, - }, - trackTitle: { - color: '#ffffff', - fontSize: 15, - fontWeight: '700', - }, - trackArtist: { - color: '#ffffff', - fontSize: 15, - marginTop: 2, - }, - trackDuration: { - color: '#ffffff', - fontSize: 15, - paddingHorizontal: 18, - marginTop: 10, - }, - heart: { - fontSize: 22, - color: '#fff', - paddingHorizontal: 10, - marginTop: 5.5, - }, - backBtn: { - marginBottom: 10, - alignSelf: 'flex-start', - }, - backText: { - color: '#fff', - fontSize: 16, - fontWeight: '600', - }, + container: { + flex: 1, + backgroundColor: '#000', + paddingTop: 28, + paddingHorizontal: 16, + paddingBottom: 24, + }, + header: { + alignItems: 'center', + }, + cover: { + width: 180, + height: 180, + borderRadius: 8, + marginBottom: 12, + }, + title: { + color: '#fff', + fontSize: 32, + fontWeight: '700', + textAlign: 'center', + marginBottom: 1, + }, + artist: { + color: '#fff', + fontSize: 26, + fontWeight: '500', + textAlign: 'center', + marginTop: 1, + }, + meta: { + color: '#fff', + fontSize: 14, + fontWeight: '500', + textAlign: 'center', + marginTop: 8, + marginBottom: 24, + }, + trackList: { + width: '100%', + paddingHorizontal: 16, + paddingBottom: 180, + }, + backBtn: { + marginBottom: 10, + alignSelf: 'flex-start', + }, + backText: { + color: '#fff', + fontSize: 16, + fontWeight: '600', + }, }); \ No newline at end of file diff --git a/jukebox/src/screens/HomeScreen.js b/jukebox/src/screens/HomeScreen.js index 3be6647..3c3a90d 100644 --- a/jukebox/src/screens/HomeScreen.js +++ b/jukebox/src/screens/HomeScreen.js @@ -1,78 +1,67 @@ -import React from "react"; +import React, { useMemo } from "react"; import { View, Text, StyleSheet, FlatList, - ScrollView, Pressable, Image, } from "react-native"; import { Ionicons } from "@expo/vector-icons"; import { useNavigation } from "@react-navigation/native"; -import library from '../data/library'; -import TrackRow from '../components/TrackRow'; - -const likedAlbums = library; - -const likedTracks = library.flatMap((album) => - album.tracks - .filter((t) => t.liked) - .map((t) => ({ - ...t, - albumId: album.id, - albumTitle: album.title, - artist: album.artist, - cover: album.cover, - })) -); +import TrackRow from "../components/TrackRow"; +import { useLibrary } from "../contexts/LibraryContext"; export default function HomeScreen() { const navigation = useNavigation(); + const { albums, likedTracks, toggleLike } = useLibrary(); + + // Same behavior as before: show all albums in "Liked albums" section + const likedAlbums = albums; + + // Optional: limit shown liked tracks on Home + const homeLikedTracks = useMemo(() => likedTracks.slice(0, 5), [likedTracks]); + return ( Home - - { - // navigation.navigate("Login") - console.log("Login pressed"); - }} - > - - - - { - // navigation.navigate("Settings") - console.log("Settings pressed"); - }} - > - - + + { + console.log("Login pressed"); + }} + > + + + { + console.log("Settings pressed"); + }} + > + + - navigation.navigate("LikedTracks", { tracks: likedTracks })} - > + + navigation.navigate("LikedTracks")}> Liked tracks ➚ - {likedTracks.map((track) => { - const album = likedAlbums.find((a) => a.id === track.albumId); - + {homeLikedTracks.map((track) => { + const album = albums.find((a) => a.id === track.albumId); return ( toggleLike(track.albumId, track.id)} onPress={() => album && navigation.navigate("Album", { album })} /> ); @@ -116,12 +105,9 @@ const styles = StyleSheet.create({ headerActions: { flexDirection: "row", alignItems: "center", - gap: 8, // if gap not supported on your RN version, use marginLeft in iconBtn + gap: 8, }, - settingsBtn: { - padding: 2, - }, - loginBtn: { + iconBtn: { padding: 2, }, homeTitle: { @@ -136,38 +122,6 @@ const styles = StyleSheet.create({ fontWeight: "700", marginBottom: 12, }, - trackItem: { - minHeight: 62, - flexDirection: 'row', - alignItems: 'center', - }, - - trackCover: { - width: 46, - height: 46, - borderRadius: 6, - marginRight: 10, - }, - - trackTextBlock: { - flex: 1, - justifyContent: 'center', - }, - - trackTitle: { - color: '#ffffff', - fontSize: 15, - fontWeight: '700', - }, - - trackArtist: { - color: '#ffffff', - fontSize: 13, - marginTop: 2, - }, - tracksBox: { - maxHeight: 260, - }, albumList: { paddingBottom: 120, }, @@ -176,14 +130,14 @@ const styles = StyleSheet.create({ marginBottom: 12, }, albumItem: { - width: '48%', + width: "48%", aspectRatio: 1, borderRadius: 8, - overflow: 'hidden', - backgroundColor: '#222', + overflow: "hidden", + backgroundColor: "#222", }, cover: { - width: '100%', - height: '100%', + width: "100%", + height: "100%", }, -}); +}); \ No newline at end of file diff --git a/jukebox/src/screens/LikedTracksScreen.js b/jukebox/src/screens/LikedTracksScreen.js index 0e83da1..d78c266 100644 --- a/jukebox/src/screens/LikedTracksScreen.js +++ b/jukebox/src/screens/LikedTracksScreen.js @@ -1,23 +1,51 @@ -import React from "react"; -import { View, Text, StyleSheet, FlatList, Pressable } from "react-native"; -import library from "../data/library"; +import { useMemo, useState } from "react"; +import { + View, + Text, + StyleSheet, + FlatList, + Pressable, + TextInput, +} from "react-native"; import TrackRow from "../components/TrackRow"; +import { useLibrary } from "../contexts/LibraryContext"; export default function LikedTracksScreen({ navigation }) { - const likedTracks = library.flatMap((album) => - album.tracks - .filter((track) => track.liked) - .map((track) => ({ - ...track, - albumId: album.id, - albumTitle: album.title, - artist: album.artist, - cover: album.cover, - })) - ); + const [query, setQuery] = useState(""); + const [sortDir, setSortDir] = useState("desc"); + const { albums, likedTracks, toggleLike } = useLibrary(); - // testing only - const tracks = likedTracks.slice(0, 2); + const [sortBy, setSortBy] = useState("dateAdded"); + const [showSortMenu, setShowSortMenu] = useState(false); + + const filteredAndSortedTracks = useMemo(() => { + const q = query.trim().toLowerCase(); + + let result = !q + ? [...likedTracks] + : likedTracks.filter( + (item) => + item.title.toLowerCase().includes(q) || + item.artist.toLowerCase().includes(q) + ); + + if (sortBy === "name") { + result.sort((a, b) => a.title.localeCompare(b.title)); + } else if (sortBy === "length") { + result.sort((a, b) => a.duration - b.duration); + } else { + result.sort((a, b) => { + if (a.dateAdded && b.dateAdded) { + return new Date(b.dateAdded) - new Date(a.dateAdded); + } + return 0; + }); + } + + if (sortDir === "desc") result.reverse(); + + return result; + }, [likedTracks, query, sortBy, sortDir]); return ( @@ -27,8 +55,52 @@ export default function LikedTracksScreen({ navigation }) { Your liked tracks + + + + Sort by: + setShowSortMenu((v) => !v)} + > + + {sortBy === "dateAdded" ? "Date added" : sortBy === "name" ? "Name" : "Length"} ▾ + + + setSortDir((d) => (d === "asc" ? "desc" : "asc"))} + > + + {sortDir === "asc" ? "ASC ↑" : "DESC ↓"} + + + + + {showSortMenu && ( + + { setSortBy("dateAdded"); setShowSortMenu(false); }}> + Date added + + { setSortBy("name"); setShowSortMenu(false); }}> + Name + + { setSortBy("length"); setShowSortMenu(false); }}> + Length + + + )} + item.id} renderItem={({ item }) => ( toggleLike(item.albumId, item.id)} onPress={() => { - const album = library.find((a) => a.id === item.albumId); + const album = albums.find((a) => a.id === item.albumId); if (album) navigation.navigate("Album", { album }); }} /> )} + ListEmptyComponent={ + No liked tracks found. + } + keyboardShouldPersistTaps="handled" contentContainerStyle={{ paddingBottom: 180 }} /> @@ -72,4 +149,69 @@ const styles = StyleSheet.create({ fontWeight: "700", marginBottom: 12, }, + searchInput: { + backgroundColor: "#1f2937", + color: "#fff", + borderRadius: 10, + paddingHorizontal: 12, + paddingVertical: 10, + fontSize: 16, + marginBottom: 12, + }, + emptyText: { + color: "#9ca3af", + fontSize: 15, + marginTop: 16, + }, + sortRow: { + flexDirection: "row", + alignItems: "center", + marginBottom: 8, + }, + sortByText: { + color: "#9ca3af", + marginRight: 8, + fontSize: 14, + }, + sortButton: { + backgroundColor: "#111827", + borderRadius: 8, + paddingHorizontal: 10, + paddingVertical: 6, + }, + sortButtonText: { + color: "#fff", + fontSize: 14, + fontWeight: "600", + }, + sortMenu: { + backgroundColor: "#111827", + borderRadius: 10, + marginBottom: 10, + overflow: "hidden", + borderWidth: 1, + borderColor: "#1f2937", + }, + sortOption: { + paddingHorizontal: 12, + paddingVertical: 10, + borderBottomWidth: 1, + borderBottomColor: "#1f2937", + }, + sortOptionText: { + color: "#fff", + fontSize: 15, + }, + sortDirButton: { + backgroundColor: "#111827", + borderRadius: 8, + paddingHorizontal: 10, + paddingVertical: 6, + marginLeft: 8, + }, + sortDirButtonText: { + color: "#fff", + fontSize: 14, + fontWeight: "600", + }, }); \ No newline at end of file