diff --git a/App.js b/App.js index a16d6e5..d7dde6c 100755 --- a/App.js +++ b/App.js @@ -74,6 +74,7 @@ const App = () => { tabBar={(props) => } screenOptions={{ headerShown: false, + tabBarPosition: settings.isDesktop ? 'left' : 'bottom', tabBarStyle: { backgroundColor: theme.secondaryDark, borderTopColor: theme.secondaryDark, diff --git a/app.json b/app.json index d5ef125..433c185 100755 --- a/app.json +++ b/app.json @@ -3,7 +3,7 @@ "name": "Castafiore", "slug": "Castafiore", "description": "Mobile app for navidrome", - "version": "2024.12.03", + "version": "2024.12.05", "orientation": "portrait", "icon": "./assets/icon.png", "userInterfaceStyle": "light", diff --git a/app/components/TabBar.js b/app/components/TabBar.js index 032711f..81f5c8f 100755 --- a/app/components/TabBar.js +++ b/app/components/TabBar.js @@ -1,15 +1,19 @@ import React from 'react'; -import { Text, View, TouchableOpacity } from 'react-native'; +import { Text, View, TouchableOpacity, Image } from 'react-native'; import Icon from 'react-native-vector-icons/FontAwesome'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { ConfigContext } from '~/contexts/config'; +import { SettingsContext } from '~/contexts/settings'; import { ThemeContext } from '~/contexts/theme'; import Player from '~/components/player/Player'; +import settingStyles from '~/styles/settings'; +import pkg from '~/../package.json'; const TabBar = ({ state, descriptors, navigation }) => { const insets = useSafeAreaInsets(); const config = React.useContext(ConfigContext) + const settings = React.useContext(SettingsContext) const theme = React.useContext(ThemeContext) const [isFullScreen, setIsFullScreen] = React.useState(false) @@ -19,10 +23,9 @@ const TabBar = ({ state, descriptors, navigation }) => { } }, [config.query]) - return ( + const BottomTab = () => ( - - {!isFullScreen && { ); })} - } + + + ) + + const SideBar = () => ( + + + + + + Castafiore + Version {pkg.version} + + + + {state.routes.map((route, index) => { + const { options } = descriptors[route.key]; + const isFocused = state.index === index; + + const onPress = () => { + const event = navigation.emit({ + type: 'tabPress', + target: route.key, + canPreventDefault: true, + }); + + if (!isFocused && !event.defaultPrevented) { + navigation.navigate(route.name, route.params); + } + }; + + const onLongPress = () => { + navigation.emit({ + type: 'tabLongPress', + target: route.key, + }); + }; + + const getColor = () => { + if (isFocused) return theme.primaryTouch + if (!config.query && route.name !== 'Settings') return theme.secondaryLight + return theme.primaryLight + } + + return ( + + + + {options.title} + + + ); + })} + ) + + return ( + + {!isFullScreen ? settings.isDesktop ? : : null} + + ); } diff --git a/app/components/lists/SongsList.js b/app/components/lists/SongsList.js index 6c6d1a3..f558b4b 100644 --- a/app/components/lists/SongsList.js +++ b/app/components/lists/SongsList.js @@ -39,6 +39,7 @@ const SongsList = ({ config, songs, isIndex = false, listToPlay = null, isMargin } setIndexOptions(index)} + onContextMenu={() => setIndexOptions(index)} delayLongPress={200} onPress={() => playSong(config, songCon, songDispatch, listToPlay ? listToPlay : songs, index)}> { + const [song, songDispatch] = React.useContext(SongContext) + const config = React.useContext(ConfigContext) + const insets = useSafeAreaInsets(); + const theme = React.useContext(ThemeContext) + const [layoutBar, setLayoutBar] = React.useState({ width: 0, height: 0 }) + const [layoutBarTime, setLayoutBarTime] = React.useState({ width: 0, height: 0 }) + + const secondToTime = (second) => { + if (!second) return '00:00' + return `${String((second - second % 60) / 60).padStart(2, '0')}:${String((second - second % 1) % 60).padStart(2, '0')}` + } + + const setVolume = (vol) => { + if (vol < 0) vol = 0 + if (vol > 1) vol = 1 + song.sound.volume = vol + } + + return ( + + + + + + + + + + + {song?.songInfo?.track ? `${song?.songInfo?.track}. ` : null}{song?.songInfo?.title ? song.songInfo.title : 'Song title'} + {song?.songInfo?.artist ? song.songInfo.artist : 'Artist'} + + + + + { + songDispatch({ type: 'setActionEndOfSong', action: song.actionEndOfSong === 'repeat' ? 'next' : 'repeat' }) + }} + /> + previousSong(config, song, songDispatch)} + /> + song.isPlaying ? pauseSong(song.sound) : resumeSong(song.sound)} + /> + nextSong(config, song, songDispatch)} + /> + + + + {secondToTime(time.position)} + setPosition(song.sound, (nativeEvent.locationX / layoutBarTime.width) * time.duration)} + onPressOut={({ nativeEvent }) => setPosition(song.sound, (nativeEvent.locationX / layoutBarTime.width) * time.duration)} + onLayout={({ nativeEvent }) => setLayoutBarTime({ width: nativeEvent.layout.width, height: nativeEvent.layout.height })} + style={{ flex: 1, height: 6 }} > + + + + + {secondToTime(time.duration)} + + + + { + song?.sound?.volume ? + song.sound.volume = 0} + /> + : song.sound.volume = 1} + /> + } + setVolume(nativeEvent.locationX / layoutBar.width)} + onPressOut={({ nativeEvent }) => setVolume(nativeEvent.locationX / layoutBar.width)} + onLayout={({ nativeEvent }) => setLayoutBar({ width: nativeEvent.layout.width, height: nativeEvent.layout.height })} + > + + + + + + fullscreen.set(true)} + /> + + + ) +} + +const styles = { + boxPlayerImage: { + height: 56, + width: 56, + marginRight: 10, + borderRadius: 4, + }, + boxPlayerText: { + }, + boxPlayerButton: { + flex: Platform.OS === 'android' ? 0 : 'initial', + flexDirection: 'row', + }, + bitognoBar: (vol, theme) => ({ + position: 'absolute', + width: 12, + height: 12, + borderRadius: 6, + backgroundColor: theme.primaryTouch, + left: `calc(${vol * 100}% - 6px)`, top: 7 + }) +} + +export default BoxDesktopPlayer; \ No newline at end of file diff --git a/app/components/player/FullScreenPlayer.js b/app/components/player/FullScreenPlayer.js index 9972aa8..c567d3a 100644 --- a/app/components/player/FullScreenPlayer.js +++ b/app/components/player/FullScreenPlayer.js @@ -150,6 +150,8 @@ const FullScreenPlayer = ({ fullscreen, time }) => { setPosition(song.sound, (nativeEvent.locationX / layoutBar.width) * time.duration)} + onPressOut={({ nativeEvent }) => setPosition(song.sound, (nativeEvent.locationX / layoutBar.width) * time.duration)} + pressRetentionOffset={{ top: 20, left: 0, right: 0, bottom: 20 }} onLayout={({ nativeEvent }) => setLayoutBar({ width: nativeEvent.layout.width, height: nativeEvent.layout.height })} > @@ -251,7 +253,7 @@ const styles = { height: 12, borderRadius: 6, backgroundColor: theme.primaryTouch, - left: `${(time.position / time.duration - 0.01) * 100}%`, top: 7 + left: `calc(${(time.position / time.duration) * 100}% - 3px)`, top: 7 }) } diff --git a/app/components/player/Player.js b/app/components/player/Player.js index 3538106..64d64f2 100644 --- a/app/components/player/Player.js +++ b/app/components/player/Player.js @@ -1,16 +1,19 @@ import React from 'react'; -import { Platform } from 'react-native'; +import { Platform, View, Text } from 'react-native'; import { SongContext } from '~/contexts/song'; -import { nextSong, handleAction } from '~/utils/player'; +import { nextSong, handleAction, pauseSong, resumeSong, previousSong } from '~/utils/player'; +import { SettingsContext } from '~/contexts/settings'; import { ConfigContext } from '~/contexts/config'; import { getApi } from '~/utils/api'; import BoxPlayer from './BoxPlayer'; import FullScreenPlayer from './FullScreenPlayer'; +import BoxDesktopPlayer from './BoxDesktopPlayer'; const Player = ({ navigation, state, fullscreen }) => { const [song, songDispatch] = React.useContext(SongContext) const config = React.useContext(ConfigContext) + const settings = React.useContext(SettingsContext) const [time, setTime] = React.useState(null) React.useEffect(() => { @@ -22,9 +25,27 @@ const Player = ({ navigation, state, fullscreen }) => { fullscreen.set(false) }, [state.index]) + React.useEffect(() => { + addEventListener('keydown', onKeyEvent) + return () => removeEventListener('keydown', onKeyEvent) + }, [song]) + + const onKeyEvent = (e) => { + if (e.code === 'Space') { + if (song.sound) { + if (song.isPlaying) pauseSong(song.sound) + else resumeSong(song.sound) + } + } else if (e.code === 'ArrowRight') nextSong(config, song, songDispatch) + else if (e.code === 'ArrowLeft') previousSong(config, song, songDispatch) + } + if (!song?.songInfo) return null if (fullscreen.value) return - else return + else { + if (settings.isDesktop) return + return + } } export default Player; \ No newline at end of file diff --git a/app/components/settings/ButtonSwitch.js b/app/components/settings/ButtonSwitch.js index 956e89c..741e445 100644 --- a/app/components/settings/ButtonSwitch.js +++ b/app/components/settings/ButtonSwitch.js @@ -4,7 +4,7 @@ import Icon from 'react-native-vector-icons/FontAwesome'; import { ThemeContext } from '~/contexts/theme'; -const ButtonSwitch = ({ title, value, onPress, isLast = false }) => { +const ButtonSwitch = ({ title, value, onPress, icon = null, isLast = false }) => { const theme = React.useContext(ThemeContext) return ( @@ -21,6 +21,21 @@ const ButtonSwitch = ({ title, value, onPress, isLast = false }) => { onPress={onPress} activeOpacity={1} > + {icon && + } {title} diff --git a/app/contexts/settings.js b/app/contexts/settings.js index c419f5f..4b34b28 100644 --- a/app/contexts/settings.js +++ b/app/contexts/settings.js @@ -20,6 +20,7 @@ export const defaultSettings = { orderPlaylist: 'title', pinPlaylist: [], previewFavorited: 3, + isDesktop: false, servers: [ { name: 'Demo', diff --git a/app/contexts/theme.js b/app/contexts/theme.js index d63adea..eab12a5 100644 --- a/app/contexts/theme.js +++ b/app/contexts/theme.js @@ -16,6 +16,7 @@ export const themes = { // Use for background primaryDark: '#121212', secondaryDark: '#1e1e1e', + tertiaryDark: '#2e2e2e', // Use for text primaryLight: '#f5f5dc', secondaryLight: 'gray', @@ -33,6 +34,7 @@ export const themes = { deezer: { primaryDark: '#000000', secondaryDark: '#191414', + tertiaryDark: '#2e2e2e', primaryLight: '#FFFFFF', secondaryLight: '#B3B3B3', primaryTouch: '#a238ff', @@ -47,6 +49,7 @@ export const themes = { spotify: { primaryDark: '#000000', secondaryDark: '#191414', + tertiaryDark: '#2e2e2e', primaryLight: '#FFFFFF', secondaryLight: '#B3B3B3', primaryTouch: '#1DB954', @@ -61,6 +64,7 @@ export const themes = { appleMusic: { primaryDark: '#000000', secondaryDark: '#1C1C1E', + tertiaryDark: '#2e2e2e', primaryLight: '#FFFFFF', secondaryLight: '#B3B3B3', primaryTouch: '#FF2D55', @@ -75,6 +79,7 @@ export const themes = { reddit: { primaryDark: '#1A1A1B', secondaryDark: '#141415', + tertiaryDark: '#2e2e2e', primaryLight: '#FFFFFF', secondaryLight: '#D7DADC', primaryTouch: '#FF4500', @@ -89,6 +94,7 @@ export const themes = { soundCloud: { primaryDark: '#FFFFFF', secondaryDark: '#f2f2f2', + tertiaryDark: '#f3f3f3', primaryLight: '#000000', secondaryLight: '##f2f2f2', primaryTouch: '#FF7700', @@ -103,6 +109,7 @@ export const themes = { lightMode: { primaryDark: '#f6f6ef', secondaryDark: '#eaeae1', + tertiaryDark: '#dcdcd4', primaryLight: '#121212', secondaryLight: '#1e1e1e', primaryTouch: '#cd1921', diff --git a/app/screens/tabs/Settings.js b/app/screens/tabs/Settings.js index 5dda36f..475241e 100755 --- a/app/screens/tabs/Settings.js +++ b/app/screens/tabs/Settings.js @@ -5,17 +5,19 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context'; import Icon from 'react-native-vector-icons/FontAwesome'; import { ConfigContext, SetConfigContext } from '~/contexts/config'; -import { SetSettingsContext, defaultSettings } from '~/contexts/settings'; +import { SetSettingsContext, defaultSettings, SettingsContext } from '~/contexts/settings'; import mainStyles from '~/styles/main'; import { ThemeContext } from '~/contexts/theme'; import settingStyles from '~/styles/settings'; import ButtonMenu from '~/components/settings/ButtonMenu'; +import ButtonSwitch from '~/components/settings/ButtonSwitch'; const Settings = ({ navigation }) => { const insets = useSafeAreaInsets(); const config = React.useContext(ConfigContext) - const theme = React.useContext(ThemeContext) + const theme = React.useContext(ThemeContext) const setSettings = React.useContext(SetSettingsContext) + const setting = React.useContext(SettingsContext) const tuktuktuk = () => { if (Platform.OS === 'web') { @@ -35,7 +37,7 @@ const Settings = ({ navigation }) => { style={mainStyles.mainContainer(insets, theme)} contentContainerStyle={{ ...settingStyles.contentMainContainer(insets), paddingTop: 40 }} > - + { - + { /> - + + setSettings({ ...setting, isDesktop: !setting.isDesktop })} + isLast={true} /> + + + { /> - + =10.0.0" } }, + "node_modules/@egjs/hammerjs": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz", + "integrity": "sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/hammerjs": "^2.0.36" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/@expo/bunyan": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@expo/bunyan/-/bunyan-4.0.0.tgz", @@ -6339,42 +6353,45 @@ } }, "node_modules/@react-navigation/bottom-tabs": { - "version": "6.5.11", - "resolved": "https://registry.npmjs.org/@react-navigation/bottom-tabs/-/bottom-tabs-6.5.11.tgz", - "integrity": "sha512-CBN/NOdxnMvmjw+AJQI1kltOYaClTZmGec5pQ3ZNTPX86ytbIOylDIITKMfTgHZcIEFQDymx1SHeS++PIL3Szw==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@react-navigation/bottom-tabs/-/bottom-tabs-7.1.3.tgz", + "integrity": "sha512-cK5zE7OpZAgZLpFBnoH9AhZbSZfH9Qavdi3kIRd2vpQDtCfnnG5bQ2eM2u/IKHDLdI50Mhsf+srqYJgG2VcmVQ==", + "license": "MIT", "dependencies": { - "@react-navigation/elements": "^1.3.21", - "color": "^4.2.3", - "warn-once": "^0.1.0" + "@react-navigation/elements": "^2.2.4", + "color": "^4.2.3" }, "peerDependencies": { - "@react-navigation/native": "^6.0.0", - "react": "*", + "@react-navigation/native": "^7.0.13", + "react": ">= 18.2.0", "react-native": "*", - "react-native-safe-area-context": ">= 3.0.0", - "react-native-screens": ">= 3.0.0" + "react-native-safe-area-context": ">= 4.0.0", + "react-native-screens": ">= 4.0.0" } }, "node_modules/@react-navigation/core": { - "version": "6.4.10", - "resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-6.4.10.tgz", - "integrity": "sha512-oYhqxETRHNHKsipm/BtGL0LI43Hs2VSFoWMbBdHK9OqgQPjTVUitslgLcPpo4zApCcmBWoOLX2qPxhsBda644A==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-7.3.0.tgz", + "integrity": "sha512-mfUPRdFCuHkaC+uU5iczqevn0PCTKzf6ApxFwgG9E8DfAVbAT7/piZEzFye2inaIRkipBwyNW40h+mEvYqE1og==", + "license": "MIT", "dependencies": { - "@react-navigation/routers": "^6.1.9", + "@react-navigation/routers": "^7.1.1", "escape-string-regexp": "^4.0.0", - "nanoid": "^3.1.23", + "nanoid": "3.3.7", "query-string": "^7.1.3", - "react-is": "^16.13.0", - "use-latest-callback": "^0.1.7" + "react-is": "^18.2.0", + "use-latest-callback": "^0.2.1", + "use-sync-external-store": "^1.2.2" }, "peerDependencies": { - "react": "*" + "react": ">= 18.2.0" } }, "node_modules/@react-navigation/core/node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -6383,56 +6400,92 @@ } }, "node_modules/@react-navigation/core/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "license": "MIT" + }, + "node_modules/@react-navigation/drawer": { + "version": "7.0.19", + "resolved": "https://registry.npmjs.org/@react-navigation/drawer/-/drawer-7.0.19.tgz", + "integrity": "sha512-rpUA+nxYAwBHi8TKQs8dOVQ1KyyByjNneuIb4KJ6xusCttMpUwstSJ7m3E/D2KC9BDQ8hxdfeABFvKsf2wmeug==", + "license": "MIT", + "dependencies": { + "@react-navigation/elements": "^2.2.4", + "color": "^4.2.3", + "react-native-drawer-layout": "^4.0.4", + "use-latest-callback": "^0.2.1" + }, + "peerDependencies": { + "@react-navigation/native": "^7.0.13", + "react": ">= 18.2.0", + "react-native": "*", + "react-native-gesture-handler": ">= 2.0.0", + "react-native-reanimated": ">= 2.0.0", + "react-native-safe-area-context": ">= 4.0.0", + "react-native-screens": ">= 4.0.0" + } }, "node_modules/@react-navigation/elements": { - "version": "1.3.21", - "resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.3.21.tgz", - "integrity": "sha512-eyS2C6McNR8ihUoYfc166O1D8VYVh9KIl0UQPI8/ZJVsStlfSTgeEEh+WXge6+7SFPnZ4ewzEJdSAHH+jzcEfg==", + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-2.2.4.tgz", + "integrity": "sha512-/H6Gu/Hn2E/pBQTkZEMbP5SDi7C2q96PrHGvsDJiFtxFgOJusA3+ygUguqTeTP402s/5KvJm47g0UloCMiECwA==", + "license": "MIT", + "dependencies": { + "color": "^4.2.3" + }, "peerDependencies": { - "@react-navigation/native": "^6.0.0", - "react": "*", + "@react-native-masked-view/masked-view": ">= 0.2.0", + "@react-navigation/native": "^7.0.13", + "react": ">= 18.2.0", "react-native": "*", - "react-native-safe-area-context": ">= 3.0.0" + "react-native-safe-area-context": ">= 4.0.0" + }, + "peerDependenciesMeta": { + "@react-native-masked-view/masked-view": { + "optional": true + } } }, "node_modules/@react-navigation/native": { - "version": "6.1.9", - "resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-6.1.9.tgz", - "integrity": "sha512-AMuJDpwXE7UlfyhIXaUCCynXmv69Kb8NzKgKJO7v0k0L+u6xUTbt6xvshmJ79vsvaFyaEH9Jg5FMzek5/S5qNw==", + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-7.0.13.tgz", + "integrity": "sha512-HLoMyp453qIDGjG72cJ2xLeGHHpP4PQve5gQvSn3o/6r2+DAmDuIcd/jXTMJGCHd2LeR9LfuqIvpiIlihg1iBg==", + "license": "MIT", "dependencies": { - "@react-navigation/core": "^6.4.10", + "@react-navigation/core": "^7.3.0", "escape-string-regexp": "^4.0.0", "fast-deep-equal": "^3.1.3", - "nanoid": "^3.1.23" + "nanoid": "3.3.7", + "use-latest-callback": "^0.2.1" }, "peerDependencies": { - "react": "*", + "react": ">= 18.2.0", "react-native": "*" } }, "node_modules/@react-navigation/native-stack": { - "version": "6.9.17", - "resolved": "https://registry.npmjs.org/@react-navigation/native-stack/-/native-stack-6.9.17.tgz", - "integrity": "sha512-X8p8aS7JptQq7uZZNFEvfEcPf6tlK4PyVwYDdryRbG98B4bh2wFQYMThxvqa+FGEN7USEuHdv2mF0GhFKfX0ew==", + "version": "7.1.14", + "resolved": "https://registry.npmjs.org/@react-navigation/native-stack/-/native-stack-7.1.14.tgz", + "integrity": "sha512-MH3iktneSL8JSttcgJBIb6zmDpaurbtMSQcYwCcsGoyq4fJ2pBIwJaViSa0KrNkMsWAMZEOY9O72rf1umu7VKw==", + "license": "MIT", "dependencies": { - "@react-navigation/elements": "^1.3.21", - "warn-once": "^0.1.0" + "@react-navigation/elements": "^2.2.4", + "warn-once": "^0.1.1" }, "peerDependencies": { - "@react-navigation/native": "^6.0.0", - "react": "*", + "@react-navigation/native": "^7.0.13", + "react": ">= 18.2.0", "react-native": "*", - "react-native-safe-area-context": ">= 3.0.0", - "react-native-screens": ">= 3.0.0" + "react-native-safe-area-context": ">= 4.0.0", + "react-native-screens": ">= 4.0.0" } }, "node_modules/@react-navigation/native/node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -6441,11 +6494,12 @@ } }, "node_modules/@react-navigation/routers": { - "version": "6.1.9", - "resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-6.1.9.tgz", - "integrity": "sha512-lTM8gSFHSfkJvQkxacGM6VJtBt61ip2XO54aNfswD+KMw6eeZ4oehl7m0me3CR9hnDE4+60iAZR8sAhvCiI3NA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-7.1.1.tgz", + "integrity": "sha512-OycWRj95p+/zENl9HU6tvvT6IUuxgVJirgsA0W9rQn3RC+9Hb0UVYA0+8avdt+WpMoWdrvwTxTXneB5mjYzHrw==", + "license": "MIT", "dependencies": { - "nanoid": "^3.1.23" + "nanoid": "3.3.7" } }, "node_modules/@rollup/plugin-babel": { @@ -6684,6 +6738,13 @@ "@types/node": "*" } }, + "node_modules/@types/hammerjs": { + "version": "2.0.46", + "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.46.tgz", + "integrity": "sha512-ynRvcq6wvqexJ9brDMS4BnBLzmr0e14d6ZJTEShTBWKymQiHwlAyGu0ZPEFI2Fh1U53F7tN9ufClWM5KvqkKOw==", + "license": "MIT", + "peer": true + }, "node_modules/@types/html-minifier-terser": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", @@ -8407,6 +8468,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "license": "MIT", "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" @@ -8432,6 +8494,7 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" @@ -8441,6 +8504,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -8451,7 +8515,8 @@ "node_modules/color/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" }, "node_modules/colord": { "version": "2.9.3", @@ -9279,6 +9344,7 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "license": "MIT", "engines": { "node": ">=0.10" } @@ -10760,6 +10826,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -11447,6 +11514,23 @@ "node": ">=8" } }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hoist-non-react-statics/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT", + "peer": true + }, "node_modules/hosted-git-info": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz", @@ -16596,6 +16680,7 @@ "version": "7.1.3", "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz", "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==", + "license": "MIT", "dependencies": { "decode-uri-component": "^0.2.2", "filter-obj": "^1.1.0", @@ -16748,9 +16833,10 @@ } }, "node_modules/react-freeze": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/react-freeze/-/react-freeze-1.0.3.tgz", - "integrity": "sha512-ZnXwLQnGzrDpHBHiC56TXFXvmolPeMjTn1UOm610M4EXGzbEDR7oOIyS2ZiItgbs6eZc4oU/a0hpk8PrcKvv5g==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/react-freeze/-/react-freeze-1.0.4.tgz", + "integrity": "sha512-r4F0Sec0BLxWicc7HEyo2x3/2icUTrRmDjaaRyzzn+7aDyFZliszMDOgLVwSnQnYENOlL1o569Ze2HZefk8clA==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -16816,6 +16902,63 @@ "react": "18.2.0" } }, + "node_modules/react-native-drawer-layout": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/react-native-drawer-layout/-/react-native-drawer-layout-4.0.4.tgz", + "integrity": "sha512-yskKj1Kxbf5w5gInNEW4YtDkTUcMsoQ0FGH0wjQ3nHPAJ3AAVnr/QgZ1Hr4LeAQR+7vgaG058DX4/32WbwvQzA==", + "license": "MIT", + "dependencies": { + "use-latest-callback": "^0.2.1" + }, + "peerDependencies": { + "react": ">= 18.2.0", + "react-native": "*", + "react-native-gesture-handler": ">= 2.0.0", + "react-native-reanimated": ">= 2.0.0" + } + }, + "node_modules/react-native-gesture-handler": { + "version": "2.21.2", + "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.21.2.tgz", + "integrity": "sha512-HcwB225K9aeZ8e/B8nFzEh+2T4EPWTeamO1l/y3PcQ9cyCDYO2zja/G31ITpYRIqkip7XzGs6wI/gnHOQn1LDQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@egjs/hammerjs": "^2.0.17", + "hoist-non-react-statics": "^3.3.0", + "invariant": "^2.2.4", + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/react-native-reanimated": { + "version": "3.16.3", + "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.16.3.tgz", + "integrity": "sha512-OWlA6e1oHhytTpc7WiSZ7Tmb8OYwLKYZz29Sz6d6WAg60Hm5GuAiKIWUG7Ako7FLcYhFkA0pEQ2xPMEYUo9vlw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/plugin-transform-arrow-functions": "^7.0.0-0", + "@babel/plugin-transform-class-properties": "^7.0.0-0", + "@babel/plugin-transform-classes": "^7.0.0-0", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.0.0-0", + "@babel/plugin-transform-optional-chaining": "^7.0.0-0", + "@babel/plugin-transform-shorthand-properties": "^7.0.0-0", + "@babel/plugin-transform-template-literals": "^7.0.0-0", + "@babel/plugin-transform-unicode-regex": "^7.0.0-0", + "@babel/preset-typescript": "^7.16.7", + "convert-source-map": "^2.0.0", + "invariant": "^2.2.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0", + "react": "*", + "react-native": "*" + } + }, "node_modules/react-native-safe-area-context": { "version": "4.6.3", "resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-4.6.3.tgz", @@ -16826,9 +16969,10 @@ } }, "node_modules/react-native-screens": { - "version": "3.22.1", - "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-3.22.1.tgz", - "integrity": "sha512-ffzwUdVKf+iLqhWSzN5DXBm0s2w5sN0P+TaHHPAx42LT7+DT0g8PkHT1QDvxpR5vCEPSS1i3EswyVK4HCuhTYg==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-4.3.0.tgz", + "integrity": "sha512-G0u8BPgu2vcRZoQTlRpBXKa0ElQSDvDBlRe6ncWwCeBmd5Uqa2I3tQ6Vn6trIE6+yneW/nD4p5wihEHlAWZPEw==", + "license": "MIT", "dependencies": { "react-freeze": "^1.0.0", "warn-once": "^0.1.0" @@ -17895,6 +18039,7 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "license": "MIT", "dependencies": { "is-arrayish": "^0.3.1" } @@ -17902,7 +18047,8 @@ "node_modules/simple-swizzle/node_modules/is-arrayish": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "license": "MIT" }, "node_modules/sirv": { "version": "2.0.4", @@ -18103,6 +18249,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", + "license": "MIT", "engines": { "node": ">=6" } @@ -18193,6 +18340,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", + "license": "MIT", "engines": { "node": ">=4" } @@ -19280,17 +19428,19 @@ } }, "node_modules/use-latest-callback": { - "version": "0.1.9", - "resolved": "https://registry.npmjs.org/use-latest-callback/-/use-latest-callback-0.1.9.tgz", - "integrity": "sha512-CL/29uS74AwreI/f2oz2hLTW7ZqVeV5+gxFeGudzQrgkCytrHw33G4KbnQOrRlAEzzAFXi7dDLMC9zhWcVpzmw==", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/use-latest-callback/-/use-latest-callback-0.2.3.tgz", + "integrity": "sha512-7vI3fBuyRcP91pazVboc4qu+6ZqM8izPWX9k7cRnT8hbD5svslcknsh3S9BUhaK11OmgTV4oWZZVSeQAiV53SQ==", + "license": "MIT", "peerDependencies": { "react": ">=16.8" } }, "node_modules/use-sync-external-store": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", - "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", + "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==", + "license": "MIT", "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } @@ -19360,7 +19510,8 @@ "node_modules/warn-once": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/warn-once/-/warn-once-0.1.1.tgz", - "integrity": "sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q==" + "integrity": "sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q==", + "license": "MIT" }, "node_modules/watchpack": { "version": "2.4.2", diff --git a/package.json b/package.json index ba198bc..1041934 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "castafiore", - "version": "2024.12.03", + "version": "2024.12.05", "main": "node_modules/expo/AppEntry.js", "homepage": ".", "scripts": { @@ -13,9 +13,10 @@ "dependencies": { "@expo/webpack-config": "^19.0.0", "@react-native-async-storage/async-storage": "1.18.2", - "@react-navigation/bottom-tabs": "^6.5.11", - "@react-navigation/native": "^6.1.9", - "@react-navigation/native-stack": "^6.9.17", + "@react-navigation/bottom-tabs": "^7.1.3", + "@react-navigation/drawer": "^7.0.19", + "@react-navigation/native": "^7.0.13", + "@react-navigation/native-stack": "^7.1.14", "expo": "~49.0.15", "expo-av": "~13.4.1", "md5": "^2.3.0", @@ -23,7 +24,7 @@ "react-dom": "18.2.0", "react-native": "0.72.10", "react-native-safe-area-context": "4.6.3", - "react-native-screens": "~3.22.0", + "react-native-screens": "^4.3.0", "react-native-vector-icons": "^10.0.2", "react-native-web": "~0.19.6" },