diff --git a/.changeset/eighty-pots-search.md b/.changeset/eighty-pots-search.md new file mode 100644 index 00000000..f366e354 --- /dev/null +++ b/.changeset/eighty-pots-search.md @@ -0,0 +1,5 @@ +--- +'django-react-native-todolist': minor +--- + +Use react hooks. Remove Mobx stores. diff --git a/demos/django-react-native-todolist/README.md b/demos/django-react-native-todolist/README.md index f532f1e8..fe033587 100644 --- a/demos/django-react-native-todolist/README.md +++ b/demos/django-react-native-todolist/README.md @@ -25,12 +25,31 @@ Run on Android pnpm android ``` -## Set up Django Backend +## Service Configuration + +This demo can be used with cloud or local services. + +### Local Services + +The [Self Hosting Demo](https://github.com/powersync-ja/self-host-demo) repository contains a Docker Compose Django backend demo which can be used with this client. +See [instructions](https://github.com/powersync-ja/self-host-demo/blob/feature/django-backend/demos/django/README.md) for starting the backend locally. + +#### Android + +Note that Android requires port forwarding of local services. These can be configured with ADB as below: + +```bash +adb reverse tcp:8080 tcp:8080 && adb reverse tcp:6061 tcp:6061 +``` + +### Cloud Services + +#### Set up Django Backend This demo requires that you have the [PowerSync Django Backend: Todo List Demo](https://github.com/powersync-ja/powersync-django-backend-todolist-demo) running on your machine. Follow the guide in the README of the PowerSync Django Backend to set it up. -## Set up PowerSync Instance +#### Set up PowerSync Instance Create a new PowerSync instance, connecting to the database of the Supabase project. @@ -42,11 +61,11 @@ bucket_definitions: # Separate bucket per todo list parameters: select id as list_id from lists where owner_id = token_parameters.user_id data: - - select * from api_list - - select * from api_todo + - select * from lists + - select * from todos ``` -## Configure The App +#### Configure The App Copy the `AppConfig.template.ts` to a usable file diff --git a/demos/django-react-native-todolist/app/_layout.tsx b/demos/django-react-native-todolist/app/_layout.tsx index 1b4616b0..790986d1 100644 --- a/demos/django-react-native-todolist/app/_layout.tsx +++ b/demos/django-react-native-todolist/app/_layout.tsx @@ -1,5 +1,6 @@ import { Stack } from 'expo-router'; -import React from 'react'; +import { PowerSyncContext } from '@powersync/react'; +import { useSystem } from '../library/stores/system'; /** * This App uses a nested navigation stack. @@ -16,14 +17,16 @@ import React from 'react'; * - Sign out. Psuedo view to initiate signout flow. Navigates back to first layer. */ const HomeLayout = () => { + const system = useSystem(); return ( - - - - - - - + + + + + + + + ); }; diff --git a/demos/django-react-native-todolist/app/index.tsx b/demos/django-react-native-todolist/app/index.tsx index 60482776..15fd1332 100644 --- a/demos/django-react-native-todolist/app/index.tsx +++ b/demos/django-react-native-todolist/app/index.tsx @@ -1,7 +1,5 @@ import * as React from 'react'; import { ActivityIndicator, View } from 'react-native'; -import { observer } from 'mobx-react-lite'; -import { useSystem } from '../library/stores/system'; import { router } from 'expo-router'; import Logger from 'js-logger'; /** @@ -10,27 +8,12 @@ import Logger from 'js-logger'; * - If one is present redirect to app views. * - If not, reditect to login/register flow */ -const App = observer(() => { - const { djangoConnector } = useSystem(); - +const App = () => { React.useEffect(() => { Logger.useDefaults(); Logger.setLevel(Logger.DEBUG); - const getSession = async () => { - const response = await fetch('http://127.0.0.1:8000/api/get_session', { - method: 'GET', - headers: { - 'Content-Type': 'application/json' - } - }); - const data = await response.json(); - if (data) { - router.replace('signin'); - } - }; - - getSession(); + setImmediate(() => router.replace('signin')); }, []); return ( @@ -38,6 +21,6 @@ const App = observer(() => { ); -}); +}; export default App; diff --git a/demos/django-react-native-todolist/app/register.tsx b/demos/django-react-native-todolist/app/register.tsx index 500e093d..665cdbfe 100644 --- a/demos/django-react-native-todolist/app/register.tsx +++ b/demos/django-react-native-todolist/app/register.tsx @@ -6,6 +6,7 @@ import { useSystem } from '../library/stores/system'; import { TextInputWidget } from '../library/widgets/TextInputWidget'; import { SignInStyles } from './signin'; import { Icon } from 'react-native-elements'; +import { router } from 'expo-router'; export default function Register() { const { djangoConnector } = useSystem(); @@ -24,6 +25,7 @@ export default function Register() { setCredentials({ ...credentials, username: value })} /> setCredentials({ ...credentials, username: value.toLowerCase().trim() })} /> setCredentials({ ...credentials, password: value })} /> {error ? {error} : null} diff --git a/demos/django-react-native-todolist/app/views/signout.tsx b/demos/django-react-native-todolist/app/views/signout.tsx index cdeb335c..24291940 100644 --- a/demos/django-react-native-todolist/app/views/signout.tsx +++ b/demos/django-react-native-todolist/app/views/signout.tsx @@ -5,12 +5,11 @@ import { router } from 'expo-router'; import { useSystem } from '../../library/stores/system'; export default function Signout() { - const { powersync, supabaseConnector } = useSystem(); + const { powersync } = useSystem(); React.useEffect(() => { (async () => { await powersync.disconnectAndClear(); - await supabaseConnector.supabaseClient.auth.signOut(); router.replace('signin'); })(); }, []); diff --git a/demos/django-react-native-todolist/app/views/todos/edit/[id].tsx b/demos/django-react-native-todolist/app/views/todos/edit/[id].tsx index c373f834..70b16bca 100644 --- a/demos/django-react-native-todolist/app/views/todos/edit/[id].tsx +++ b/demos/django-react-native-todolist/app/views/todos/edit/[id].tsx @@ -1,76 +1,29 @@ -import * as React from 'react'; -import { StatusBar } from 'expo-status-bar'; -import { ScrollView, View, Text } from 'react-native'; -import { FAB } from 'react-native-elements'; -import { observer } from 'mobx-react-lite'; -import { Stack, useLocalSearchParams } from 'expo-router'; -import prompt from 'react-native-prompt-android'; +import { View, Text, ActivityIndicator } from 'react-native'; +import { useLocalSearchParams } from 'expo-router'; +import { useQuery } from '@powersync/react'; +import { ListTodosWidget } from '../../../../library/widgets/ListTodosWidget'; +import { LIST_TABLE, ListRecord } from '../../../../library/powersync/AppSchema'; -import { useSystem } from '../../../../library/stores/system'; -import { TodoItemWidget } from '../../../../library/widgets/TodoItemWidget'; - -const TodoView = observer(() => { - const { listStore, todoStore } = useSystem(); +const TodoView = () => { const params = useLocalSearchParams<{ id: string }>(); const id = params.id; - const listModel = React.useMemo(() => { - if (!id) { - return null; - } - const listModel = listStore.getById(id); - - return listModel; - }, [id]); + const { data: result, isLoading } = useQuery(`SELECT * FROM ${LIST_TABLE} WHERE id = ?`, [id]); + const listRecord = result[0]; - if (!listModel) { + if (!listRecord && !isLoading) { return ( - No matching List found + No matching list found ); } - return ( - - - { - prompt( - 'Add a new Todo', - '', - (text) => { - if (!text) { - return; - } - - todoStore.createModel({ - list_id: listModel.id, - description: text, - completed: false - }); - }, - { placeholder: 'Todo description', style: 'shimo' } - ); - }} - /> - - {listModel.todos.map((t) => { - return ; - })} - + if (isLoading) { + return ; + } - - - ); -}); + return ; +}; export default TodoView; diff --git a/demos/django-react-native-todolist/app/views/todos/lists.tsx b/demos/django-react-native-todolist/app/views/todos/lists.tsx index 11aa0f93..6a9e8da9 100644 --- a/demos/django-react-native-todolist/app/views/todos/lists.tsx +++ b/demos/django-react-native-todolist/app/views/todos/lists.tsx @@ -1,16 +1,18 @@ -import * as React from 'react'; import { StatusBar } from 'expo-status-bar'; import { ScrollView, View } from 'react-native'; import { FAB } from 'react-native-elements'; -import { observer } from 'mobx-react-lite'; import prompt from 'react-native-prompt-android'; import { useSystem } from '../../../library/stores/system'; import { ListItemWidget } from '../../../library/widgets/ListItemWidget'; import { Stack } from 'expo-router'; +import { useQuery } from '@powersync/react'; +import { LIST_TABLE } from '../../../library/powersync/AppSchema'; + +const App = () => { + const system = useSystem(); + const { data: lists } = useQuery(`SELECT * FROM ${LIST_TABLE}`); -const App = observer(() => { - const { listStore } = useSystem(); return ( { prompt( 'Add a new list', '', - (text) => { + async (text) => { if (!text) { return; } - listStore.createModel({ - name: text - }); + const { userID } = await system.djangoConnector.fetchCredentials(); + + await system.powersync.execute( + `INSERT INTO ${LIST_TABLE} (id, created_at, name, owner_id) VALUES (uuid(), datetime(), ?, ?)`, + [text, userID] + ); }, { placeholder: 'List name', style: 'shimo' } ); }} /> - {listStore.collection.map((t) => ( - + {lists.map((t) => ( + ))} ); -}); +}; export default App; diff --git a/demos/django-react-native-todolist/database.sql b/demos/django-react-native-todolist/database.sql index cb71d1d3..98ab1ac7 100644 --- a/demos/django-react-native-todolist/database.sql +++ b/demos/django-react-native-todolist/database.sql @@ -1 +1 @@ -create publication powersync for table api_list, api_todo; +create publication powersync for table lists, todos; diff --git a/demos/django-react-native-todolist/ios/Podfile.lock b/demos/django-react-native-todolist/ios/Podfile.lock index 8c60dc03..e9771f59 100644 --- a/demos/django-react-native-todolist/ios/Podfile.lock +++ b/demos/django-react-native-todolist/ios/Podfile.lock @@ -1326,8 +1326,8 @@ PODS: - Yoga (0.0.0) DEPENDENCIES: - - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`) - - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) + - boost (from `../../../node_modules/react-native/third-party-podspecs/boost.podspec`) + - DoubleConversion (from `../../../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) - EXConstants (from `../../../node_modules/expo-constants/ios`) - Expo (from `../../../node_modules/expo`) - ExpoAsset (from `../../../node_modules/expo-asset/ios`) @@ -1337,69 +1337,69 @@ DEPENDENCIES: - ExpoKeepAwake (from `../../../node_modules/expo-keep-awake/ios`) - ExpoModulesCore (from `../../../node_modules/expo-modules-core`) - EXSplashScreen (from `../../../node_modules/expo-splash-screen/ios`) - - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) - - fmt (from `../node_modules/react-native/third-party-podspecs/fmt.podspec`) - - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) - - hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`) - - RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) - - RCT-Folly/Fabric (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) - - RCTDeprecation (from `../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation`) - - RCTRequired (from `../node_modules/react-native/Libraries/Required`) - - RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`) - - React (from `../node_modules/react-native/`) - - React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`) + - FBLazyVector (from `../../../node_modules/react-native/Libraries/FBLazyVector`) + - fmt (from `../../../node_modules/react-native/third-party-podspecs/fmt.podspec`) + - glog (from `../../../node_modules/react-native/third-party-podspecs/glog.podspec`) + - hermes-engine (from `../../../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`) + - RCT-Folly (from `../../../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) + - RCT-Folly/Fabric (from `../../../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) + - RCTDeprecation (from `../../../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation`) + - RCTRequired (from `../../../node_modules/react-native/Libraries/Required`) + - RCTTypeSafety (from `../../../node_modules/react-native/Libraries/TypeSafety`) + - React (from `../../../node_modules/react-native/`) + - React-callinvoker (from `../../../node_modules/react-native/ReactCommon/callinvoker`) - React-Codegen (from `build/generated/ios`) - - React-Core (from `../node_modules/react-native/`) - - React-Core/RCTWebSocket (from `../node_modules/react-native/`) - - React-CoreModules (from `../node_modules/react-native/React/CoreModules`) - - React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`) - - React-debug (from `../node_modules/react-native/ReactCommon/react/debug`) - - React-Fabric (from `../node_modules/react-native/ReactCommon`) - - React-FabricImage (from `../node_modules/react-native/ReactCommon`) - - React-featureflags (from `../node_modules/react-native/ReactCommon/react/featureflags`) - - React-graphics (from `../node_modules/react-native/ReactCommon/react/renderer/graphics`) - - React-hermes (from `../node_modules/react-native/ReactCommon/hermes`) - - React-ImageManager (from `../node_modules/react-native/ReactCommon/react/renderer/imagemanager/platform/ios`) - - React-jserrorhandler (from `../node_modules/react-native/ReactCommon/jserrorhandler`) - - React-jsi (from `../node_modules/react-native/ReactCommon/jsi`) - - React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`) - - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector-modern`) - - React-jsitracing (from `../node_modules/react-native/ReactCommon/hermes/executor/`) - - React-logger (from `../node_modules/react-native/ReactCommon/logger`) - - React-Mapbuffer (from `../node_modules/react-native/ReactCommon`) + - React-Core (from `../../../node_modules/react-native/`) + - React-Core/RCTWebSocket (from `../../../node_modules/react-native/`) + - React-CoreModules (from `../../../node_modules/react-native/React/CoreModules`) + - React-cxxreact (from `../../../node_modules/react-native/ReactCommon/cxxreact`) + - React-debug (from `../../../node_modules/react-native/ReactCommon/react/debug`) + - React-Fabric (from `../../../node_modules/react-native/ReactCommon`) + - React-FabricImage (from `../../../node_modules/react-native/ReactCommon`) + - React-featureflags (from `../../../node_modules/react-native/ReactCommon/react/featureflags`) + - React-graphics (from `../../../node_modules/react-native/ReactCommon/react/renderer/graphics`) + - React-hermes (from `../../../node_modules/react-native/ReactCommon/hermes`) + - React-ImageManager (from `../../../node_modules/react-native/ReactCommon/react/renderer/imagemanager/platform/ios`) + - React-jserrorhandler (from `../../../node_modules/react-native/ReactCommon/jserrorhandler`) + - React-jsi (from `../../../node_modules/react-native/ReactCommon/jsi`) + - React-jsiexecutor (from `../../../node_modules/react-native/ReactCommon/jsiexecutor`) + - React-jsinspector (from `../../../node_modules/react-native/ReactCommon/jsinspector-modern`) + - React-jsitracing (from `../../../node_modules/react-native/ReactCommon/hermes/executor/`) + - React-logger (from `../../../node_modules/react-native/ReactCommon/logger`) + - React-Mapbuffer (from `../../../node_modules/react-native/ReactCommon`) - react-native-encrypted-storage (from `../../../node_modules/react-native-encrypted-storage`) - "react-native-quick-sqlite (from `../../../node_modules/@journeyapps/react-native-quick-sqlite`)" - - react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`) - - React-nativeconfig (from `../node_modules/react-native/ReactCommon`) - - React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`) - - React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`) - - React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`) - - React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`) - - React-RCTAppDelegate (from `../node_modules/react-native/Libraries/AppDelegate`) - - React-RCTBlob (from `../node_modules/react-native/Libraries/Blob`) - - React-RCTFabric (from `../node_modules/react-native/React`) - - React-RCTImage (from `../node_modules/react-native/Libraries/Image`) - - React-RCTLinking (from `../node_modules/react-native/Libraries/LinkingIOS`) - - React-RCTNetwork (from `../node_modules/react-native/Libraries/Network`) - - React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`) - - React-RCTText (from `../node_modules/react-native/Libraries/Text`) - - React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`) - - React-rendererdebug (from `../node_modules/react-native/ReactCommon/react/renderer/debug`) - - React-rncore (from `../node_modules/react-native/ReactCommon`) - - React-RuntimeApple (from `../node_modules/react-native/ReactCommon/react/runtime/platform/ios`) - - React-RuntimeCore (from `../node_modules/react-native/ReactCommon/react/runtime`) - - React-runtimeexecutor (from `../node_modules/react-native/ReactCommon/runtimeexecutor`) - - React-RuntimeHermes (from `../node_modules/react-native/ReactCommon/react/runtime`) - - React-runtimescheduler (from `../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler`) - - React-utils (from `../node_modules/react-native/ReactCommon/react/utils`) - - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) + - react-native-safe-area-context (from `../../../node_modules/react-native-safe-area-context`) + - React-nativeconfig (from `../../../node_modules/react-native/ReactCommon`) + - React-NativeModulesApple (from `../../../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`) + - React-perflogger (from `../../../node_modules/react-native/ReactCommon/reactperflogger`) + - React-RCTActionSheet (from `../../../node_modules/react-native/Libraries/ActionSheetIOS`) + - React-RCTAnimation (from `../../../node_modules/react-native/Libraries/NativeAnimation`) + - React-RCTAppDelegate (from `../../../node_modules/react-native/Libraries/AppDelegate`) + - React-RCTBlob (from `../../../node_modules/react-native/Libraries/Blob`) + - React-RCTFabric (from `../../../node_modules/react-native/React`) + - React-RCTImage (from `../../../node_modules/react-native/Libraries/Image`) + - React-RCTLinking (from `../../../node_modules/react-native/Libraries/LinkingIOS`) + - React-RCTNetwork (from `../../../node_modules/react-native/Libraries/Network`) + - React-RCTSettings (from `../../../node_modules/react-native/Libraries/Settings`) + - React-RCTText (from `../../../node_modules/react-native/Libraries/Text`) + - React-RCTVibration (from `../../../node_modules/react-native/Libraries/Vibration`) + - React-rendererdebug (from `../../../node_modules/react-native/ReactCommon/react/renderer/debug`) + - React-rncore (from `../../../node_modules/react-native/ReactCommon`) + - React-RuntimeApple (from `../../../node_modules/react-native/ReactCommon/react/runtime/platform/ios`) + - React-RuntimeCore (from `../../../node_modules/react-native/ReactCommon/react/runtime`) + - React-runtimeexecutor (from `../../../node_modules/react-native/ReactCommon/runtimeexecutor`) + - React-RuntimeHermes (from `../../../node_modules/react-native/ReactCommon/react/runtime`) + - React-runtimescheduler (from `../../../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler`) + - React-utils (from `../../../node_modules/react-native/ReactCommon/react/utils`) + - ReactCommon/turbomodule/core (from `../../../node_modules/react-native/ReactCommon`) - "RNCAsyncStorage (from `../../../node_modules/@react-native-community/async-storage`)" - "RNCMaskedView (from `../../../node_modules/@react-native-community/masked-view`)" - - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) - - RNReanimated (from `../node_modules/react-native-reanimated`) - - RNScreens (from `../node_modules/react-native-screens`) + - RNGestureHandler (from `../../../node_modules/react-native-gesture-handler`) + - RNReanimated (from `../../../node_modules/react-native-reanimated`) + - RNScreens (from `../../../node_modules/react-native-screens`) - RNVectorIcons (from `../../../node_modules/react-native-vector-icons`) - - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) + - Yoga (from `../../../node_modules/react-native/ReactCommon/yoga`) SPEC REPOS: trunk: @@ -1408,9 +1408,9 @@ SPEC REPOS: EXTERNAL SOURCES: boost: - :podspec: "../node_modules/react-native/third-party-podspecs/boost.podspec" + :podspec: "../../../node_modules/react-native/third-party-podspecs/boost.podspec" DoubleConversion: - :podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec" + :podspec: "../../../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec" EXConstants: :path: "../../../node_modules/expo-constants/ios" Expo: @@ -1430,128 +1430,128 @@ EXTERNAL SOURCES: EXSplashScreen: :path: "../../../node_modules/expo-splash-screen/ios" FBLazyVector: - :path: "../node_modules/react-native/Libraries/FBLazyVector" + :path: "../../../node_modules/react-native/Libraries/FBLazyVector" fmt: - :podspec: "../node_modules/react-native/third-party-podspecs/fmt.podspec" + :podspec: "../../../node_modules/react-native/third-party-podspecs/fmt.podspec" glog: - :podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec" + :podspec: "../../../node_modules/react-native/third-party-podspecs/glog.podspec" hermes-engine: - :podspec: "../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec" + :podspec: "../../../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec" :tag: hermes-2024-04-25-RNv0.74.1-b54a3a01c531f4f5f1904cb0770033e8b7153dff RCT-Folly: - :podspec: "../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec" + :podspec: "../../../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec" RCTDeprecation: - :path: "../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation" + :path: "../../../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation" RCTRequired: - :path: "../node_modules/react-native/Libraries/Required" + :path: "../../../node_modules/react-native/Libraries/Required" RCTTypeSafety: - :path: "../node_modules/react-native/Libraries/TypeSafety" + :path: "../../../node_modules/react-native/Libraries/TypeSafety" React: - :path: "../node_modules/react-native/" + :path: "../../../node_modules/react-native/" React-callinvoker: - :path: "../node_modules/react-native/ReactCommon/callinvoker" + :path: "../../../node_modules/react-native/ReactCommon/callinvoker" React-Codegen: :path: build/generated/ios React-Core: - :path: "../node_modules/react-native/" + :path: "../../../node_modules/react-native/" React-CoreModules: - :path: "../node_modules/react-native/React/CoreModules" + :path: "../../../node_modules/react-native/React/CoreModules" React-cxxreact: - :path: "../node_modules/react-native/ReactCommon/cxxreact" + :path: "../../../node_modules/react-native/ReactCommon/cxxreact" React-debug: - :path: "../node_modules/react-native/ReactCommon/react/debug" + :path: "../../../node_modules/react-native/ReactCommon/react/debug" React-Fabric: - :path: "../node_modules/react-native/ReactCommon" + :path: "../../../node_modules/react-native/ReactCommon" React-FabricImage: - :path: "../node_modules/react-native/ReactCommon" + :path: "../../../node_modules/react-native/ReactCommon" React-featureflags: - :path: "../node_modules/react-native/ReactCommon/react/featureflags" + :path: "../../../node_modules/react-native/ReactCommon/react/featureflags" React-graphics: - :path: "../node_modules/react-native/ReactCommon/react/renderer/graphics" + :path: "../../../node_modules/react-native/ReactCommon/react/renderer/graphics" React-hermes: - :path: "../node_modules/react-native/ReactCommon/hermes" + :path: "../../../node_modules/react-native/ReactCommon/hermes" React-ImageManager: - :path: "../node_modules/react-native/ReactCommon/react/renderer/imagemanager/platform/ios" + :path: "../../../node_modules/react-native/ReactCommon/react/renderer/imagemanager/platform/ios" React-jserrorhandler: - :path: "../node_modules/react-native/ReactCommon/jserrorhandler" + :path: "../../../node_modules/react-native/ReactCommon/jserrorhandler" React-jsi: - :path: "../node_modules/react-native/ReactCommon/jsi" + :path: "../../../node_modules/react-native/ReactCommon/jsi" React-jsiexecutor: - :path: "../node_modules/react-native/ReactCommon/jsiexecutor" + :path: "../../../node_modules/react-native/ReactCommon/jsiexecutor" React-jsinspector: - :path: "../node_modules/react-native/ReactCommon/jsinspector-modern" + :path: "../../../node_modules/react-native/ReactCommon/jsinspector-modern" React-jsitracing: - :path: "../node_modules/react-native/ReactCommon/hermes/executor/" + :path: "../../../node_modules/react-native/ReactCommon/hermes/executor/" React-logger: - :path: "../node_modules/react-native/ReactCommon/logger" + :path: "../../../node_modules/react-native/ReactCommon/logger" React-Mapbuffer: - :path: "../node_modules/react-native/ReactCommon" + :path: "../../../node_modules/react-native/ReactCommon" react-native-encrypted-storage: :path: "../../../node_modules/react-native-encrypted-storage" react-native-quick-sqlite: :path: "../../../node_modules/@journeyapps/react-native-quick-sqlite" react-native-safe-area-context: - :path: "../node_modules/react-native-safe-area-context" + :path: "../../../node_modules/react-native-safe-area-context" React-nativeconfig: - :path: "../node_modules/react-native/ReactCommon" + :path: "../../../node_modules/react-native/ReactCommon" React-NativeModulesApple: - :path: "../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios" + :path: "../../../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios" React-perflogger: - :path: "../node_modules/react-native/ReactCommon/reactperflogger" + :path: "../../../node_modules/react-native/ReactCommon/reactperflogger" React-RCTActionSheet: - :path: "../node_modules/react-native/Libraries/ActionSheetIOS" + :path: "../../../node_modules/react-native/Libraries/ActionSheetIOS" React-RCTAnimation: - :path: "../node_modules/react-native/Libraries/NativeAnimation" + :path: "../../../node_modules/react-native/Libraries/NativeAnimation" React-RCTAppDelegate: - :path: "../node_modules/react-native/Libraries/AppDelegate" + :path: "../../../node_modules/react-native/Libraries/AppDelegate" React-RCTBlob: - :path: "../node_modules/react-native/Libraries/Blob" + :path: "../../../node_modules/react-native/Libraries/Blob" React-RCTFabric: - :path: "../node_modules/react-native/React" + :path: "../../../node_modules/react-native/React" React-RCTImage: - :path: "../node_modules/react-native/Libraries/Image" + :path: "../../../node_modules/react-native/Libraries/Image" React-RCTLinking: - :path: "../node_modules/react-native/Libraries/LinkingIOS" + :path: "../../../node_modules/react-native/Libraries/LinkingIOS" React-RCTNetwork: - :path: "../node_modules/react-native/Libraries/Network" + :path: "../../../node_modules/react-native/Libraries/Network" React-RCTSettings: - :path: "../node_modules/react-native/Libraries/Settings" + :path: "../../../node_modules/react-native/Libraries/Settings" React-RCTText: - :path: "../node_modules/react-native/Libraries/Text" + :path: "../../../node_modules/react-native/Libraries/Text" React-RCTVibration: - :path: "../node_modules/react-native/Libraries/Vibration" + :path: "../../../node_modules/react-native/Libraries/Vibration" React-rendererdebug: - :path: "../node_modules/react-native/ReactCommon/react/renderer/debug" + :path: "../../../node_modules/react-native/ReactCommon/react/renderer/debug" React-rncore: - :path: "../node_modules/react-native/ReactCommon" + :path: "../../../node_modules/react-native/ReactCommon" React-RuntimeApple: - :path: "../node_modules/react-native/ReactCommon/react/runtime/platform/ios" + :path: "../../../node_modules/react-native/ReactCommon/react/runtime/platform/ios" React-RuntimeCore: - :path: "../node_modules/react-native/ReactCommon/react/runtime" + :path: "../../../node_modules/react-native/ReactCommon/react/runtime" React-runtimeexecutor: - :path: "../node_modules/react-native/ReactCommon/runtimeexecutor" + :path: "../../../node_modules/react-native/ReactCommon/runtimeexecutor" React-RuntimeHermes: - :path: "../node_modules/react-native/ReactCommon/react/runtime" + :path: "../../../node_modules/react-native/ReactCommon/react/runtime" React-runtimescheduler: - :path: "../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler" + :path: "../../../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler" React-utils: - :path: "../node_modules/react-native/ReactCommon/react/utils" + :path: "../../../node_modules/react-native/ReactCommon/react/utils" ReactCommon: - :path: "../node_modules/react-native/ReactCommon" + :path: "../../../node_modules/react-native/ReactCommon" RNCAsyncStorage: :path: "../../../node_modules/@react-native-community/async-storage" RNCMaskedView: :path: "../../../node_modules/@react-native-community/masked-view" RNGestureHandler: - :path: "../node_modules/react-native-gesture-handler" + :path: "../../../node_modules/react-native-gesture-handler" RNReanimated: - :path: "../node_modules/react-native-reanimated" + :path: "../../../node_modules/react-native-reanimated" RNScreens: - :path: "../node_modules/react-native-screens" + :path: "../../../node_modules/react-native-screens" RNVectorIcons: :path: "../../../node_modules/react-native-vector-icons" Yoga: - :path: "../node_modules/react-native/ReactCommon/yoga" + :path: "../../../node_modules/react-native/ReactCommon/yoga" SPEC CHECKSUMS: boost: d3f49c53809116a5d38da093a8aa78bf551aed09 @@ -1576,7 +1576,7 @@ SPEC CHECKSUMS: RCTTypeSafety: a11979ff0570d230d74de9f604f7d19692157bc4 React: 88794fad7f460349dbc9df8a274d95f37a009f5d React-callinvoker: 7a7023e34a55c89ea2aa62486bb3c1164ab0be0c - React-Codegen: af31a9323ce23988c255c9afd0ae9415ff894939 + React-Codegen: f824dfd08f6c0e021580225427ae2fac6ec15f24 React-Core: 60075333bc22b5a793d3f62e207368b79bff2e64 React-CoreModules: 147c314d6b3b1e069c9ad64cbbbeba604854ff86 React-cxxreact: 5de27fd8bff4764acb2eac3ee66001e0e2b910e7 @@ -1623,7 +1623,7 @@ SPEC CHECKSUMS: RNCAsyncStorage: b03032fdbdb725bea0bd9e5ec5a7272865ae7398 RNCMaskedView: 0e1bc4bfa8365eba5fbbb71e07fbdc0555249489 RNGestureHandler: 2282cfbcf86c360d29f44ace393203afd5c6cff7 - RNReanimated: 35f9ac9c3ac42d0497ebd1cce5c39d7687a8493e + RNReanimated: 33c6135cdf421b795c2f1173075a11cca2a39bf2 RNScreens: b32a9ff15bea7fcdbe5dff6477bc503f792b1208 RNVectorIcons: 2a2f79274248390b80684ea3c4400bd374a15c90 SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d diff --git a/demos/django-react-native-todolist/ios/powersyncexample.xcodeproj/project.pbxproj b/demos/django-react-native-todolist/ios/powersyncexample.xcodeproj/project.pbxproj index 9ccc1985..cec1bcc1 100644 --- a/demos/django-react-native-todolist/ios/powersyncexample.xcodeproj/project.pbxproj +++ b/demos/django-react-native-todolist/ios/powersyncexample.xcodeproj/project.pbxproj @@ -481,7 +481,7 @@ "$(inherited)", " ", ); - REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; + REACT_NATIVE_PATH = "${PODS_ROOT}/../../../../node_modules/react-native"; SDKROOT = iphoneos; USE_HERMES = true; }; @@ -539,7 +539,7 @@ "$(inherited)", " ", ); - REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; + REACT_NATIVE_PATH = "${PODS_ROOT}/../../../../node_modules/react-native"; SDKROOT = iphoneos; USE_HERMES = true; VALIDATE_PRODUCT = YES; diff --git a/demos/django-react-native-todolist/library/django/ApiClient.ts b/demos/django-react-native-todolist/library/django/ApiClient.ts index 3cd13f5b..531a3880 100644 --- a/demos/django-react-native-todolist/library/django/ApiClient.ts +++ b/demos/django-react-native-todolist/library/django/ApiClient.ts @@ -23,8 +23,21 @@ export class ApiClient { return await response.json(); } + async register(username: string, password: string) { + const requestBody = { username, password }; + const response = await fetch(`${this.baseUrl}/api/register/`, { + method: 'POST', + body: JSON.stringify(requestBody), + headers: this.headers + }); + if (response.status !== 200) { + throw new Error(`Server returned HTTP ${response.status}, ${await response.text()}`); + } + return await response.json(); + } + async getToken(userId: string) { - const response = await fetch(`${this.baseUrl}/api/get_token/`, { + const response = await fetch(`${this.baseUrl}/api/get_powersync_token/`, { method: 'GET', headers: this.headers }); @@ -34,6 +47,16 @@ export class ApiClient { return await response.json(); } + async getSession() { + const response = await fetch(`${this.baseUrl}/api/get_session/`, { + method: 'GET', + headers: this.headers + }); + if (response.status !== 200) { + throw new Error(`Server returned HTTP ${response.status}`); + } + } + async update(data: any): Promise { const response = await fetch(`${this.baseUrl}/api/upload_data/`, { method: 'PATCH', diff --git a/demos/django-react-native-todolist/library/django/AppConfig.template.ts b/demos/django-react-native-todolist/library/django/AppConfig.template.ts index d887cb35..9f4f47dc 100644 --- a/demos/django-react-native-todolist/library/django/AppConfig.template.ts +++ b/demos/django-react-native-todolist/library/django/AppConfig.template.ts @@ -1,4 +1,5 @@ export const AppConfig = { - djangoUrl: '', // This is base url to the Django project - powersyncUrl: '' // This is the PowerSync instance url provided in the PowerSync dashboard + // These defaults are applicable when using local services + djangoUrl: 'http://localhost:6061', // This is base url to the Django project + powersyncUrl: 'http://localhost:8080' // This is the PowerSync instance url provided in the PowerSync dashboard }; diff --git a/demos/django-react-native-todolist/library/django/DjangoConnector.ts b/demos/django-react-native-todolist/library/django/DjangoConnector.ts index 59e9eb9c..1218472e 100644 --- a/demos/django-react-native-todolist/library/django/DjangoConnector.ts +++ b/demos/django-react-native-todolist/library/django/DjangoConnector.ts @@ -31,6 +31,10 @@ export class DjangoConnector implements PowerSyncBackendConnector { } } + async register(username: string, password: string) { + return this.apiClient.register(username, password); + } + async fetchCredentials() { // The demo does not invalidate or update a user token, you should implement this in your app // The app stores the user id in local storage @@ -40,7 +44,7 @@ export class DjangoConnector implements PowerSyncBackendConnector { } const session = await this.apiClient.getToken(userId); return { - endpoint: session.powersync_url, + endpoint: AppConfig.powersyncUrl, token: session.token ?? '', expiresAt: undefined, userID: userId diff --git a/demos/django-react-native-todolist/library/models/AbstractModel.ts b/demos/django-react-native-todolist/library/models/AbstractModel.ts deleted file mode 100644 index 83088454..00000000 --- a/demos/django-react-native-todolist/library/models/AbstractModel.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Transaction } from '@powersync/react-native'; -import { System } from '../stores/system'; -export interface ModelRecord { - id: string; -} - -export abstract class AbstractModel { - abstract table: string; - - constructor( - public record: Record, - protected system: System - ) {} - - get id() { - return this.record.id; - } - - async setField(field: F, value: Record[F]) { - await this.system.powersync.execute(`UPDATE ${this.table} SET ? = ? WHERE id = ?`, [field, value, this.id]); - this.record[field] = value; - } - - abstract update(record: Record): Promise; - - /** - * Removes a model from the DB. Takes an optional transaction. - */ - async delete(tx?: Transaction) { - if (tx) { - return this._delete(tx); - } - return this.system.powersync.writeTransaction((tx) => this._delete(tx)); - } - - protected abstract _delete(tx: Transaction): Promise; -} diff --git a/demos/django-react-native-todolist/library/models/ListModel.ts b/demos/django-react-native-todolist/library/models/ListModel.ts deleted file mode 100644 index 120d3d78..00000000 --- a/demos/django-react-native-todolist/library/models/ListModel.ts +++ /dev/null @@ -1,43 +0,0 @@ -import _ from 'lodash'; -import { AbstractModel, ModelRecord } from './AbstractModel'; -import { Transaction } from '@powersync/react-native'; - -export interface ListRecord extends ModelRecord { - name: string; - created_at: string; - owner_id: string; -} - -export const LIST_TABLE = 'api_list'; - -export class ListModel extends AbstractModel { - get table() { - return LIST_TABLE; - } - - get todos() { - return this.system.todoStore.collection.filter((todo) => todo.record.list_id == this.id); - } - - get description() { - const todos = this.todos; - const completedCount = _.sumBy(todos, (todo) => (todo.record.completed ? 1 : 0)); - return `${todos.length - completedCount} pending, ${completedCount} completed`; - } - - async update(record: ListRecord): Promise { - await this.system.powersync.execute( - `UPDATE ${this.table} SET name = ?, created_at = ?, owner_id = ? WHERE id = ?`, - [record.name, record.created_at, record.owner_id, this.id] - ); - _.merge(this.record, record); - } - - async _delete(tx: Transaction): Promise { - for (const todo of this.todos) { - await todo.delete(tx); - } - await tx.execute(`DELETE FROM ${this.table} WHERE id = ?`, [this.id]); - this.system.listStore.removeModel(this); - } -} diff --git a/demos/django-react-native-todolist/library/models/TodoModel.ts b/demos/django-react-native-todolist/library/models/TodoModel.ts deleted file mode 100644 index 7c3284e1..00000000 --- a/demos/django-react-native-todolist/library/models/TodoModel.ts +++ /dev/null @@ -1,55 +0,0 @@ -import _ from 'lodash'; -import { AbstractModel, ModelRecord } from './AbstractModel'; -import { Transaction } from '@powersync/react-native'; - -export interface TodoRecord extends ModelRecord { - created_at: string; - completed: boolean; - description: string; - completed_at?: string; - - created_by: string; - completed_by?: string; - list_id: string; -} - -export const TODO_TABLE = 'api_todo'; - -export class TodoModel extends AbstractModel { - get table() { - return TODO_TABLE; - } - - async update(record: TodoRecord): Promise { - await this.system.powersync.execute( - `UPDATE ${this.table} SET created_at = ?, completed = ?, completed_at = ?, description = ?, created_by = ?, completed_by = ?, list_id = ? WHERE id = ?`, - [ - record.created_at, - record.completed, - record.completed_at, - record.description, - record.created_by, - record.completed_by, - record.list_id, - record.id - ] - ); - _.merge(this.record, record); - } - - async toggleCompletion(completed: boolean) { - const { userID } = await this.system.djangoConnector.fetchCredentials(); - - return this.update({ - ...this.record, - completed_at: completed ? new Date().toISOString() : undefined, - completed, - completed_by: completed ? userID : undefined - }); - } - - async _delete(tx: Transaction): Promise { - await tx.execute(`DELETE FROM ${this.table} WHERE id = ?`, [this.id]); - this.system.todoStore.removeModel(this); - } -} diff --git a/demos/django-react-native-todolist/library/powersync/AppSchema.ts b/demos/django-react-native-todolist/library/powersync/AppSchema.ts index bf44e517..00ab261f 100644 --- a/demos/django-react-native-todolist/library/powersync/AppSchema.ts +++ b/demos/django-react-native-todolist/library/powersync/AppSchema.ts @@ -1,25 +1,33 @@ -import { Column, ColumnType, Index, IndexedColumn, Schema, Table } from '@powersync/react-native'; +import { column, Schema, TableV2 } from '@powersync/react-native'; -export const AppSchema = new Schema([ - new Table({ - name: 'api_todo', - columns: [ - new Column({ name: 'list_id', type: ColumnType.TEXT }), - new Column({ name: 'created_at', type: ColumnType.TEXT }), - new Column({ name: 'completed_at', type: ColumnType.TEXT }), - new Column({ name: 'description', type: ColumnType.TEXT }), - new Column({ name: 'completed', type: ColumnType.INTEGER }), - new Column({ name: 'created_by', type: ColumnType.TEXT }), - new Column({ name: 'completed_by', type: ColumnType.TEXT }) - ], - indexes: [new Index({ name: 'list', columns: [new IndexedColumn({ name: 'list_id' })] })] - }), - new Table({ - name: 'api_list', - columns: [ - new Column({ name: 'created_at', type: ColumnType.TEXT }), - new Column({ name: 'name', type: ColumnType.TEXT }), - new Column({ name: 'owner_id', type: ColumnType.TEXT }) - ] - }) -]); +export const LIST_TABLE = 'lists'; +export const TODO_TABLE = 'todos'; + +const todos = new TableV2( + { + list_id: column.text, + created_at: column.text, + completed_at: column.text, + description: column.text, + created_by: column.text, + completed_by: column.text, + completed: column.integer, + photo_id: column.text + }, + { indexes: { list: ['list_id'] } } +); + +const lists = new TableV2({ + created_at: column.text, + name: column.text, + owner_id: column.text +}); + +export const AppSchema = new Schema({ + lists, + todos +}); + +export type Database = (typeof AppSchema)['types']; +export type TodoRecord = Database['todos']; +export type ListRecord = Database['lists']; diff --git a/demos/django-react-native-todolist/library/stores/AbstractStore.ts b/demos/django-react-native-todolist/library/stores/AbstractStore.ts deleted file mode 100644 index 1c16ac6c..00000000 --- a/demos/django-react-native-todolist/library/stores/AbstractStore.ts +++ /dev/null @@ -1,57 +0,0 @@ -import _ from 'lodash'; -import { action, makeObservable, observable } from 'mobx'; -import { AbstractModel } from '../models/AbstractModel'; -import { System } from './system'; - -export abstract class AbstractStore { - collection: Model[]; - - constructor(protected system: System) { - this.collection = []; - - makeObservable(this, { - collection: observable, - createModel: action, - removeModel: action - }); - } - - getById(id: string): Model | undefined { - return this.collection.find((i) => i.id == id); - } - - init() { - this.watchItems(); - } - - /** - * Create the model and persist in DB - */ - protected abstract _createModel(record: Partial): Promise; - - /** - * Creates a model and updates stored collection - */ - async createModel(record: Partial) { - const model = await this._createModel(record); - this.collection.push(model); - return model; - } - - /** - * Removes a model from the collection. Does not delete from DB. - */ - removeModel(model: Model) { - _.pullAllWith(this.collection, [model], (a, b) => a.id == b.id); - } - - protected abstract _watchItems(): AsyncIterable; - /** - * Watches the collection and updates the store - */ - protected async watchItems() { - for await (const items of this._watchItems()) { - this.collection = items; - } - } -} diff --git a/demos/django-react-native-todolist/library/stores/ListStore.ts b/demos/django-react-native-todolist/library/stores/ListStore.ts deleted file mode 100644 index 74fd453a..00000000 --- a/demos/django-react-native-todolist/library/stores/ListStore.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { LIST_TABLE, ListModel, ListRecord } from '../models/ListModel'; -import { AbstractStore } from './AbstractStore'; - -export class ListStore extends AbstractStore { - async *_watchItems(): AsyncIterable { - for await (const update of this.system.powersync.watch(`select * from ${LIST_TABLE}`, [])) { - yield update.rows?._array.map((r) => new ListModel(r, this.system)) || this.collection; - } - } - - async _load(): Promise { - const records = await this.system.powersync.getAll(`SELECT * from ${LIST_TABLE}`); - return records.map((r) => new ListModel(r, this.system)); - } - - async _createModel(record: ListRecord): Promise { - const { userID } = await this.system.djangoConnector.fetchCredentials(); - - const res = await this.system.powersync.execute( - `INSERT INTO ${LIST_TABLE} (id, created_at, name, owner_id) VALUES (uuid(), datetime(), ?, ?) RETURNING *`, - [record.name, record.owner_id || userID] - ); - - const resultRecord = res.rows?.item(0); - if (!resultRecord) { - throw new Error('Could not create list'); - } - - return new ListModel(resultRecord, this.system); - } -} diff --git a/demos/django-react-native-todolist/library/stores/TodoStore.ts b/demos/django-react-native-todolist/library/stores/TodoStore.ts deleted file mode 100644 index 6f97203b..00000000 --- a/demos/django-react-native-todolist/library/stores/TodoStore.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { TODO_TABLE, TodoModel, TodoRecord } from '../models/TodoModel'; -import { AbstractStore } from './AbstractStore'; - -export class TodoStore extends AbstractStore { - async *_watchItems(): AsyncIterable { - for await (const update of this.system.powersync.watch(`select * from ${TODO_TABLE}`, [], { - tables: [TODO_TABLE] - })) { - yield update.rows?._array.map((r) => new TodoModel(r, this.system)) || this.collection; - } - } - - async _createModel(record: TodoRecord): Promise { - const { userID } = await this.system.djangoConnector.fetchCredentials(); - - await this.system.powersync.execute( - `INSERT INTO ${TODO_TABLE} (id, created_at, completed, completed_at, description, created_by, completed_by, list_id) VALUES (uuid(), datetime(), ?, ?, ?, ?, ?, ?)`, - [ - record.completed, - record.completed_at, - record.description, - record.created_by ?? userID, - record.completed_by, - record.list_id - ] - ); - - return new TodoModel(record, this.system); - } -} diff --git a/demos/django-react-native-todolist/library/stores/system.ts b/demos/django-react-native-todolist/library/stores/system.ts index f284d770..5e00329b 100644 --- a/demos/django-react-native-todolist/library/stores/system.ts +++ b/demos/django-react-native-todolist/library/stores/system.ts @@ -1,53 +1,38 @@ import '@azure/core-asynciterator-polyfill'; import 'react-native-polyfill-globals/auto'; import React from 'react'; -import { configure, makeAutoObservable, makeObservable, observable } from 'mobx'; -import { AbstractPowerSyncDatabase, RNQSPowerSyncDatabaseOpenFactory } from '@powersync/react-native'; +import { AbstractPowerSyncDatabase, PowerSyncDatabase, SyncStreamConnectionMethod } from '@powersync/react-native'; +import { Buffer } from '@craftzdog/react-native-buffer'; import { AppSchema } from '../powersync/AppSchema'; import { DjangoConnector } from '../django/DjangoConnector'; -import { ListStore } from './ListStore'; -import { TodoStore } from './TodoStore'; -configure({ - enforceActions: 'never' // TODO for when PowerSyncDatabase is more observable friendly -}); +if (typeof process.nextTick == 'undefined') { + process.nextTick = setImmediate; +} + +if (typeof global.Buffer == 'undefined') { + // @ts-ignore + global.Buffer = Buffer; +} export class System { djangoConnector: DjangoConnector; powersync: AbstractPowerSyncDatabase; - listStore: ListStore; - todoStore: TodoStore; - storage: any; constructor() { - const factory = new RNQSPowerSyncDatabaseOpenFactory({ + this.powersync = new PowerSyncDatabase({ schema: AppSchema, - dbFilename: 'sqlite.db' + database: { dbFilename: 'sqlite.db' } }); this.djangoConnector = new DjangoConnector(); - this.powersync = factory.getInstance(); - - this.listStore = new ListStore(this); - this.todoStore = new TodoStore(this); - - makeObservable(this.powersync, { - currentStatus: observable, - closed: observable - }); - makeAutoObservable(this); } async init() { await this.powersync.init(); - await this.powersync.connect(this.djangoConnector); - - // Make sure to only watch queries after PowerSync has been initialized as those tables - // might not exist yet. - this.listStore.init(); - this.todoStore.init(); + await this.powersync.connect(this.djangoConnector, { connectionMethod: SyncStreamConnectionMethod.WEB_SOCKET }); } } diff --git a/demos/django-react-native-todolist/library/widgets/HeaderWidget.tsx b/demos/django-react-native-todolist/library/widgets/HeaderWidget.tsx index f139be2a..e3982195 100644 --- a/demos/django-react-native-todolist/library/widgets/HeaderWidget.tsx +++ b/demos/django-react-native-todolist/library/widgets/HeaderWidget.tsx @@ -5,12 +5,11 @@ import { useNavigation } from 'expo-router'; import { useSystem } from '../stores/system'; import { useStatus } from '@powersync/react'; import { Header } from 'react-native-elements'; -import { observer } from 'mobx-react-lite'; import { DrawerActions } from '@react-navigation/native'; export const HeaderWidget: React.FC<{ title?: string; -}> = observer((props) => { +}> = (props) => { const { title } = props; const { powersync } = useSystem(); const status = useStatus(); @@ -39,7 +38,8 @@ export const HeaderWidget: React.FC<{ onPress={() => { Alert.alert( 'Status', - `${status.connected ? 'Connected' : 'Disconnected'}. \nLast Synced at ${status.lastSyncedAt?.toISOString() ?? '-' + `${status.connected ? 'Connected' : 'Disconnected'}. \nLast Synced at ${ + status.lastSyncedAt?.toISOString() ?? '-' }\nVersion: ${powersync.sdkVersion}` ); }} @@ -48,4 +48,4 @@ export const HeaderWidget: React.FC<{ centerComponent={{title}} /> ); -}); +}; diff --git a/demos/django-react-native-todolist/library/widgets/ListItemWidget.tsx b/demos/django-react-native-todolist/library/widgets/ListItemWidget.tsx index 283510b9..f6b4a523 100644 --- a/demos/django-react-native-todolist/library/widgets/ListItemWidget.tsx +++ b/demos/django-react-native-todolist/library/widgets/ListItemWidget.tsx @@ -1,20 +1,21 @@ import React from 'react'; -import { ListModel } from '../models/ListModel'; import { Alert, View } from 'react-native'; import { ListItem, Icon } from 'react-native-elements'; import { router } from 'expo-router'; +import { usePowerSync } from '@powersync/react'; +import { LIST_TABLE, ListRecord } from '../powersync/AppSchema'; export const ListItemWidget: React.FC<{ - model: ListModel; + record: ListRecord; }> = (props) => { - const { model } = props; + const { record } = props; + const powerSync = usePowerSync(); return ( - {model.record.name} - {model.description} + {record.name} model.delete() }], + [ + { text: 'Cancel' }, + { + text: 'Delete', + onPress: async () => powerSync.execute(`DELETE FROM ${LIST_TABLE} WHERE id = ?`, [record.id]) + } + ], { cancelable: true } ); }} @@ -33,10 +40,9 @@ export const ListItemWidget: React.FC<{ onPress={() => { router.push({ pathname: 'views/todos/edit/[id]', - params: { id: model.id } + params: { id: record.id } }); - }} - > + }}> ); diff --git a/demos/django-react-native-todolist/library/widgets/ListTodosWidget.tsx b/demos/django-react-native-todolist/library/widgets/ListTodosWidget.tsx new file mode 100644 index 00000000..00bf53d0 --- /dev/null +++ b/demos/django-react-native-todolist/library/widgets/ListTodosWidget.tsx @@ -0,0 +1,56 @@ +import React from 'react'; +import { ScrollView, StatusBar, View } from 'react-native'; +import { usePowerSync, useQuery } from '@powersync/react'; +import { Stack } from 'expo-router'; +import { FAB } from 'react-native-elements'; +import { TodoItemWidget } from './TodoItemWidget'; +import prompt from 'react-native-prompt-android'; +import { ListRecord, TODO_TABLE, TodoRecord } from '../powersync/AppSchema'; + +export const ListTodosWidget: React.FC<{ + record: ListRecord; +}> = (props) => { + const { record } = props; + + const { data: todos } = useQuery(`SELECT * FROM ${TODO_TABLE} WHERE list_id = ?`, [record.id]); + const powerSync = usePowerSync(); + return ( + + + { + prompt( + 'Add a new Todo', + '', + async (text) => { + if (!text) { + return; + } + + await powerSync.execute( + `INSERT INTO ${TODO_TABLE} (id, created_at, description, list_id, completed) VALUES (uuid(), datetime(), ?, ?, ?)`, + [text, record.id, false] + ); + }, + { placeholder: 'Todo description', style: 'shimo' } + ); + }} + /> + + {todos.map((t) => { + return ; + })} + + + + + ); +}; diff --git a/demos/django-react-native-todolist/library/widgets/TodoItemWidget.tsx b/demos/django-react-native-todolist/library/widgets/TodoItemWidget.tsx index 1091fed7..326c2b0d 100644 --- a/demos/django-react-native-todolist/library/widgets/TodoItemWidget.tsx +++ b/demos/django-react-native-todolist/library/widgets/TodoItemWidget.tsx @@ -1,14 +1,15 @@ import React from 'react'; import { ActivityIndicator, Alert, View } from 'react-native'; import { ListItem, Icon } from 'react-native-elements'; -import { TodoModel } from '../models/TodoModel'; +import { usePowerSync } from '@powersync/react'; +import { TODO_TABLE, TodoRecord } from '../powersync/AppSchema'; export const TodoItemWidget: React.FC<{ - model: TodoModel; + record: TodoRecord; }> = (props) => { - const { model } = props; + const { record } = props; const [loading, setLoading] = React.useState(false); - + const powerSync = usePowerSync(); return ( @@ -19,11 +20,14 @@ export const TodoItemWidget: React.FC<{ iconType="material-community" checkedIcon="checkbox-marked" uncheckedIcon="checkbox-blank-outline" - checked={!!model.record.completed} + checked={!!record.completed} onPress={async () => { setLoading(true); try { - await model.toggleCompletion(!model.record.completed); + await powerSync.execute(`UPDATE ${TODO_TABLE} SET completed =? WHERE id = ?`, [ + !record.completed, + record.id + ]); } catch (ex) { console.error(ex); } finally { @@ -33,7 +37,7 @@ export const TodoItemWidget: React.FC<{ /> )} - {model.record.description} + {record.description} model.delete() }], + [ + { text: 'Cancel' }, + { + text: 'Delete', + onPress: () => powerSync.execute(`DELETE FROM ${TODO_TABLE} WHERE id = ?`, [record.id]) + } + ], { cancelable: true } ); }} diff --git a/demos/django-react-native-todolist/package.json b/demos/django-react-native-todolist/package.json index 09840aee..62f80ac2 100644 --- a/demos/django-react-native-todolist/package.json +++ b/demos/django-react-native-todolist/package.json @@ -9,6 +9,7 @@ }, "dependencies": { "@azure/core-asynciterator-polyfill": "^1.0.2", + "@craftzdog/react-native-buffer": "^6.0.5", "@expo/vector-icons": "^14.0.0", "@journeyapps/react-native-quick-sqlite": "^1.1.7", "@powersync/common": "workspace:*", @@ -31,8 +32,6 @@ "js-logger": "^1.6.1", "lodash": "^4.17.21", "metro": "~0.80.8", - "mobx": "^6.10.2", - "mobx-react-lite": "^4.0.4", "react": "18.2.0", "react-native": "0.74.1", "react-native-elements": "^3.4.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index da34fc02..b6979b62 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -96,6 +96,9 @@ importers: '@azure/core-asynciterator-polyfill': specifier: ^1.0.2 version: 1.0.2 + '@craftzdog/react-native-buffer': + specifier: ^6.0.5 + version: 6.0.5(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) '@expo/vector-icons': specifier: ^14.0.0 version: 14.0.1 @@ -119,7 +122,7 @@ importers: version: 0.1.11(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) '@react-navigation/drawer': specifier: ^6.6.15 - version: 6.6.15(owwheoto3z3xdqlq6aqxf7fs3q) + version: 6.6.15(@react-navigation/native@6.1.17(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-gesture-handler@2.16.2(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-reanimated@3.10.1(@babel/core@7.24.5)(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-screens@3.31.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) '@react-navigation/native': specifier: ^6.1.17 version: 6.1.17(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) @@ -146,7 +149,7 @@ importers: version: 1.11.1 expo-router: specifier: 3.5.15 - version: 3.5.15(zhsqofsf4gogouly7ufzyhgmtm) + version: 3.5.15(@react-navigation/drawer@6.6.15(@react-navigation/native@6.1.17(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-gesture-handler@2.16.2(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-reanimated@3.10.1(@babel/core@7.24.5)(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-screens@3.31.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(encoding@0.1.13)(expo-constants@16.0.2(expo@51.0.10(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(encoding@0.1.13)))(expo-linking@6.3.1(expo@51.0.10(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(encoding@0.1.13)))(expo-modules-autolinking@1.11.1)(expo-status-bar@1.12.1)(expo@51.0.10(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(encoding@0.1.13))(react-native-reanimated@3.10.1(@babel/core@7.24.5)(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-screens@3.31.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)(typescript@5.4.5) expo-splash-screen: specifier: ~0.27.4 version: 0.27.4(encoding@0.1.13)(expo-modules-autolinking@1.11.1)(expo@51.0.10(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(encoding@0.1.13)) @@ -162,12 +165,6 @@ importers: metro: specifier: ~0.80.8 version: 0.80.9(encoding@0.1.13) - mobx: - specifier: ^6.10.2 - version: 6.12.3 - mobx-react-lite: - specifier: ^4.0.4 - version: 4.0.7(mobx@6.12.3)(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) react: specifier: 18.2.0 version: 18.2.0 @@ -215,7 +212,7 @@ importers: version: 10.1.0 react-navigation-stack: specifier: ^2.10.4 - version: 2.10.4(mbbvdrtmcupym3r3ey4slwiq3e) + version: 2.10.4(@react-native-community/masked-view@0.1.11(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-gesture-handler@2.16.2(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-screens@3.31.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react-navigation@4.4.4(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react@18.2.0) text-encoding: specifier: ^0.7.0 version: 0.7.0 @@ -690,7 +687,7 @@ importers: version: 6.3.1(expo@51.0.10(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(encoding@0.1.13)) expo-router: specifier: ^3.5.15 - version: 3.5.15(iu3x6tw54vldjunpzhvco4zm64) + version: 3.5.15(@react-navigation/drawer@6.6.15(@react-navigation/native@6.1.17(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-gesture-handler@2.16.2(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-reanimated@3.10.1(@babel/core@7.24.5)(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-screens@3.31.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(encoding@0.1.13)(expo-constants@16.0.2(expo@51.0.10(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(encoding@0.1.13)))(expo-linking@6.3.1(expo@51.0.10(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(encoding@0.1.13)))(expo-modules-autolinking@1.11.1)(expo-status-bar@1.12.1)(expo@51.0.10(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(encoding@0.1.13))(react-native-reanimated@3.10.1(@babel/core@7.24.5)(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-screens@3.31.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)(typescript@5.3.3) expo-splash-screen: specifier: ~0.27.4 version: 0.27.4(encoding@0.1.13)(expo-modules-autolinking@1.11.1)(expo@51.0.10(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(encoding@0.1.13)) @@ -805,7 +802,7 @@ importers: version: 0.1.11(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) '@react-navigation/drawer': specifier: ^6.6.3 - version: 6.6.15(owwheoto3z3xdqlq6aqxf7fs3q) + version: 6.6.15(@react-navigation/native@6.1.17(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-gesture-handler@2.16.2(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-reanimated@3.10.1(@babel/core@7.24.5)(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-screens@3.31.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) '@react-navigation/native': specifier: ^6.0.0 version: 6.1.17(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) @@ -841,7 +838,7 @@ importers: version: 6.3.1(expo@51.0.10(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(encoding@0.1.13)) expo-router: specifier: 3.5.15 - version: 3.5.15(iu3x6tw54vldjunpzhvco4zm64) + version: 3.5.15(@react-navigation/drawer@6.6.15(@react-navigation/native@6.1.17(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-gesture-handler@2.16.2(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-reanimated@3.10.1(@babel/core@7.24.5)(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-screens@3.31.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(encoding@0.1.13)(expo-constants@16.0.2(expo@51.0.10(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(encoding@0.1.13)))(expo-linking@6.3.1(expo@51.0.10(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(encoding@0.1.13)))(expo-modules-autolinking@1.11.1)(expo-status-bar@1.12.1)(expo@51.0.10(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(encoding@0.1.13))(react-native-reanimated@3.10.1(@babel/core@7.24.5)(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-screens@3.31.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)(typescript@5.3.3) expo-secure-store: specifier: ~13.0.1 version: 13.0.1(expo@51.0.10(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(encoding@0.1.13)) @@ -907,7 +904,7 @@ importers: version: 10.1.0 react-navigation-stack: specifier: ^2.10.4 - version: 2.10.4(mbbvdrtmcupym3r3ey4slwiq3e) + version: 2.10.4(@react-native-community/masked-view@0.1.11(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-gesture-handler@2.16.2(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-screens@3.31.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react-navigation@4.4.4(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react@18.2.0) text-encoding: specifier: ^0.7.0 version: 0.7.0 @@ -11697,22 +11694,6 @@ packages: mlly@1.7.0: resolution: {integrity: sha512-U9SDaXGEREBYQgfejV97coK0UL1r+qnF2SyO9A3qcI8MzKnsIFKHNVEkrDyNncQTKQQumsasmeq84eNMdBfsNQ==} - mobx-react-lite@4.0.7: - resolution: {integrity: sha512-RjwdseshK9Mg8On5tyJZHtGD+J78ZnCnRaxeQDSiciKVQDUbfZcXhmld0VMxAwvcTnPEHZySGGewm467Fcpreg==} - peerDependencies: - mobx: ^6.9.0 - react: ^16.8.0 || ^17 || ^18 - react-dom: '*' - react-native: '*' - peerDependenciesMeta: - react-dom: - optional: true - react-native: - optional: true - - mobx@6.12.3: - resolution: {integrity: sha512-c8NKkO4R2lShkSXZ2Ongj1ycjugjzFFo/UswHBnS62y07DMcTc9Rvo03/3nRyszIvwPNljlkd4S828zIBv/piw==} - moment@2.30.1: resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==} @@ -22061,8 +22042,8 @@ snapshots: react-is: 16.13.1 use-latest-callback: 0.1.9(react@18.2.0) - '@react-navigation/drawer@6.6.15(owwheoto3z3xdqlq6aqxf7fs3q)': - dependencies: + ? '@react-navigation/drawer@6.6.15(@react-navigation/native@6.1.17(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-gesture-handler@2.16.2(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-reanimated@3.10.1(@babel/core@7.24.5)(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-screens@3.31.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)' + : dependencies: '@react-navigation/elements': 1.3.30(@react-navigation/native@6.1.17(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) '@react-navigation/native': 6.1.17(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) color: 4.2.3 @@ -27767,8 +27748,8 @@ snapshots: dependencies: invariant: 2.2.4 - expo-router@3.5.15(iu3x6tw54vldjunpzhvco4zm64): - dependencies: + ? expo-router@3.5.15(@react-navigation/drawer@6.6.15(@react-navigation/native@6.1.17(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-gesture-handler@2.16.2(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-reanimated@3.10.1(@babel/core@7.24.5)(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-screens@3.31.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(encoding@0.1.13)(expo-constants@16.0.2(expo@51.0.10(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(encoding@0.1.13)))(expo-linking@6.3.1(expo@51.0.10(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(encoding@0.1.13)))(expo-modules-autolinking@1.11.1)(expo-status-bar@1.12.1)(expo@51.0.10(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(encoding@0.1.13))(react-native-reanimated@3.10.1(@babel/core@7.24.5)(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-screens@3.31.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)(typescript@5.3.3) + : dependencies: '@expo/metro-runtime': 3.2.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0)) '@expo/server': 0.4.2(typescript@5.3.3) '@radix-ui/react-slot': 1.0.1(react@18.2.0) @@ -27785,7 +27766,7 @@ snapshots: react-native-screens: 3.31.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) schema-utils: 4.2.0 optionalDependencies: - '@react-navigation/drawer': 6.6.15(owwheoto3z3xdqlq6aqxf7fs3q) + '@react-navigation/drawer': 6.6.15(@react-navigation/native@6.1.17(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-gesture-handler@2.16.2(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-reanimated@3.10.1(@babel/core@7.24.5)(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-screens@3.31.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) react-native-reanimated: 3.10.1(@babel/core@7.24.5)(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) transitivePeerDependencies: - encoding @@ -27795,8 +27776,8 @@ snapshots: - supports-color - typescript - expo-router@3.5.15(zhsqofsf4gogouly7ufzyhgmtm): - dependencies: + ? expo-router@3.5.15(@react-navigation/drawer@6.6.15(@react-navigation/native@6.1.17(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-gesture-handler@2.16.2(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-reanimated@3.10.1(@babel/core@7.24.5)(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-screens@3.31.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(encoding@0.1.13)(expo-constants@16.0.2(expo@51.0.10(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(encoding@0.1.13)))(expo-linking@6.3.1(expo@51.0.10(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(encoding@0.1.13)))(expo-modules-autolinking@1.11.1)(expo-status-bar@1.12.1)(expo@51.0.10(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(encoding@0.1.13))(react-native-reanimated@3.10.1(@babel/core@7.24.5)(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-screens@3.31.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0)(typescript@5.4.5) + : dependencies: '@expo/metro-runtime': 3.2.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0)) '@expo/server': 0.4.2(typescript@5.4.5) '@radix-ui/react-slot': 1.0.1(react@18.2.0) @@ -27813,7 +27794,7 @@ snapshots: react-native-screens: 3.31.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) schema-utils: 4.2.0 optionalDependencies: - '@react-navigation/drawer': 6.6.15(owwheoto3z3xdqlq6aqxf7fs3q) + '@react-navigation/drawer': 6.6.15(@react-navigation/native@6.1.17(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-gesture-handler@2.16.2(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-reanimated@3.10.1(@babel/core@7.24.5)(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-screens@3.31.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) react-native-reanimated: 3.10.1(@babel/core@7.24.5)(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) transitivePeerDependencies: - encoding @@ -31317,16 +31298,6 @@ snapshots: pkg-types: 1.1.0 ufo: 1.5.3 - mobx-react-lite@4.0.7(mobx@6.12.3)(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0): - dependencies: - mobx: 6.12.3 - react: 18.2.0 - use-sync-external-store: 1.2.2(react@18.2.0) - optionalDependencies: - react-native: 0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0) - - mobx@6.12.3: {} - moment@2.30.1: {} moti@0.25.4(react-dom@18.2.0(react@18.2.0))(react-native-reanimated@3.10.1(@babel/core@7.24.5)(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react@18.2.0): @@ -33214,8 +33185,8 @@ snapshots: - supports-color - utf-8-validate - react-navigation-stack@2.10.4(mbbvdrtmcupym3r3ey4slwiq3e): - dependencies: + ? react-navigation-stack@2.10.4(@react-native-community/masked-view@0.1.11(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-gesture-handler@2.16.2(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-safe-area-context@4.10.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native-screens@3.31.1(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react-navigation@4.4.4(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0))(react@18.2.0) + : dependencies: '@react-native-community/masked-view': 0.1.11(react-native@0.74.1(@babel/core@7.24.5)(@babel/preset-env@7.24.5(@babel/core@7.24.5))(@types/react@18.2.79)(encoding@0.1.13)(react@18.2.0))(react@18.2.0) color: 3.2.1 react: 18.2.0