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"
},