diff --git a/source/deprecation.txt b/source/deprecation.txt index eca488448..224eaab20 100644 --- a/source/deprecation.txt +++ b/source/deprecation.txt @@ -24,7 +24,7 @@ Previously Deprecated Services ------------------------------ As of March 12, 2024, GraphQL and Static Hosting are deprecated for Atlas App -Services. GraphQL and Static Hosting services will be discontinued and removed on +Services. GraphQL and Static Hosting services will be discontinued on **September 30, 2025**. To learn more about these deprecations, refer to the :ref:`Migrate Static diff --git a/source/images/migration/react_native_guide/image1.png b/source/images/migration/react_native_guide/image1.png new file mode 100644 index 000000000..27f9869ea Binary files /dev/null and b/source/images/migration/react_native_guide/image1.png differ diff --git a/source/images/migration/react_native_guide/image10.png b/source/images/migration/react_native_guide/image10.png new file mode 100644 index 000000000..01a07654d Binary files /dev/null and b/source/images/migration/react_native_guide/image10.png differ diff --git a/source/images/migration/react_native_guide/image11.png b/source/images/migration/react_native_guide/image11.png new file mode 100644 index 000000000..5240978c9 Binary files /dev/null and b/source/images/migration/react_native_guide/image11.png differ diff --git a/source/images/migration/react_native_guide/image12.png b/source/images/migration/react_native_guide/image12.png new file mode 100644 index 000000000..0a108fb0f Binary files /dev/null and b/source/images/migration/react_native_guide/image12.png differ diff --git a/source/images/migration/react_native_guide/image13.png b/source/images/migration/react_native_guide/image13.png new file mode 100644 index 000000000..9280b57df Binary files /dev/null and b/source/images/migration/react_native_guide/image13.png differ diff --git a/source/images/migration/react_native_guide/image14.png b/source/images/migration/react_native_guide/image14.png new file mode 100644 index 000000000..06e5a0590 Binary files /dev/null and b/source/images/migration/react_native_guide/image14.png differ diff --git a/source/images/migration/react_native_guide/image15.gif b/source/images/migration/react_native_guide/image15.gif new file mode 100644 index 000000000..3bba16365 Binary files /dev/null and b/source/images/migration/react_native_guide/image15.gif differ diff --git a/source/images/migration/react_native_guide/image16.png b/source/images/migration/react_native_guide/image16.png new file mode 100644 index 000000000..4e90f155a Binary files /dev/null and b/source/images/migration/react_native_guide/image16.png differ diff --git a/source/images/migration/react_native_guide/image17.png b/source/images/migration/react_native_guide/image17.png new file mode 100644 index 000000000..4a5c7b978 Binary files /dev/null and b/source/images/migration/react_native_guide/image17.png differ diff --git a/source/images/migration/react_native_guide/image18.png b/source/images/migration/react_native_guide/image18.png new file mode 100644 index 000000000..a11d71dbe Binary files /dev/null and b/source/images/migration/react_native_guide/image18.png differ diff --git a/source/images/migration/react_native_guide/image19.png b/source/images/migration/react_native_guide/image19.png new file mode 100644 index 000000000..cc36429d2 Binary files /dev/null and b/source/images/migration/react_native_guide/image19.png differ diff --git a/source/images/migration/react_native_guide/image2.png b/source/images/migration/react_native_guide/image2.png new file mode 100644 index 000000000..149b56979 Binary files /dev/null and b/source/images/migration/react_native_guide/image2.png differ diff --git a/source/images/migration/react_native_guide/image20.png b/source/images/migration/react_native_guide/image20.png new file mode 100644 index 000000000..68717a7ab Binary files /dev/null and b/source/images/migration/react_native_guide/image20.png differ diff --git a/source/images/migration/react_native_guide/image21.png b/source/images/migration/react_native_guide/image21.png new file mode 100644 index 000000000..9ab46b1b2 Binary files /dev/null and b/source/images/migration/react_native_guide/image21.png differ diff --git a/source/images/migration/react_native_guide/image22.png b/source/images/migration/react_native_guide/image22.png new file mode 100644 index 000000000..807a5de44 Binary files /dev/null and b/source/images/migration/react_native_guide/image22.png differ diff --git a/source/images/migration/react_native_guide/image23.png b/source/images/migration/react_native_guide/image23.png new file mode 100644 index 000000000..7e21f8973 Binary files /dev/null and b/source/images/migration/react_native_guide/image23.png differ diff --git a/source/images/migration/react_native_guide/image24.png b/source/images/migration/react_native_guide/image24.png new file mode 100644 index 000000000..c35c1818a Binary files /dev/null and b/source/images/migration/react_native_guide/image24.png differ diff --git a/source/images/migration/react_native_guide/image25.gif b/source/images/migration/react_native_guide/image25.gif new file mode 100644 index 000000000..ae0ad13e6 Binary files /dev/null and b/source/images/migration/react_native_guide/image25.gif differ diff --git a/source/images/migration/react_native_guide/image26.png b/source/images/migration/react_native_guide/image26.png new file mode 100644 index 000000000..d1a97d0ea Binary files /dev/null and b/source/images/migration/react_native_guide/image26.png differ diff --git a/source/images/migration/react_native_guide/image27.png b/source/images/migration/react_native_guide/image27.png new file mode 100644 index 000000000..b576be723 Binary files /dev/null and b/source/images/migration/react_native_guide/image27.png differ diff --git a/source/images/migration/react_native_guide/image3.png b/source/images/migration/react_native_guide/image3.png new file mode 100644 index 000000000..e2e0d5f28 Binary files /dev/null and b/source/images/migration/react_native_guide/image3.png differ diff --git a/source/images/migration/react_native_guide/image4b.png b/source/images/migration/react_native_guide/image4b.png new file mode 100644 index 000000000..552df514d Binary files /dev/null and b/source/images/migration/react_native_guide/image4b.png differ diff --git a/source/images/migration/react_native_guide/image5.png b/source/images/migration/react_native_guide/image5.png new file mode 100644 index 000000000..e1610f8fd Binary files /dev/null and b/source/images/migration/react_native_guide/image5.png differ diff --git a/source/images/migration/react_native_guide/image6.png b/source/images/migration/react_native_guide/image6.png new file mode 100644 index 000000000..d6bde644d Binary files /dev/null and b/source/images/migration/react_native_guide/image6.png differ diff --git a/source/images/migration/react_native_guide/image7.gif b/source/images/migration/react_native_guide/image7.gif new file mode 100644 index 000000000..57b34ab0d Binary files /dev/null and b/source/images/migration/react_native_guide/image7.gif differ diff --git a/source/images/migration/react_native_guide/image8.png b/source/images/migration/react_native_guide/image8.png new file mode 100644 index 000000000..8121c2d01 Binary files /dev/null and b/source/images/migration/react_native_guide/image8.png differ diff --git a/source/images/migration/react_native_guide/image9.png b/source/images/migration/react_native_guide/image9.png new file mode 100644 index 000000000..3634838a0 Binary files /dev/null and b/source/images/migration/react_native_guide/image9.png differ diff --git a/source/migrate-hosting-graphql.txt b/source/migrate-hosting-graphql.txt index 639c5687a..215735b5f 100644 --- a/source/migrate-hosting-graphql.txt +++ b/source/migrate-hosting-graphql.txt @@ -24,8 +24,8 @@ Migrate Static Hosting and GraphQL From App Services GraphQL and Static Hosting are deprecated and will be discontinued on **September 30, 2025**. -As of March 12, 2024, GraphQL and Static Hosting are deprecated for Atlas App -Services. GraphQL and Static Hosting services will be discontinued on September +As of **September 30, 2024** , GraphQL and Static Hosting are deprecated for Atlas App +Services. GraphQL and Static Hosting services will be discontinued on September 30, 2025. If you use GraphQL or Static Hosting, you should migrate to other providers diff --git a/source/sync/device-sync-deprecation.txt b/source/sync/device-sync-deprecation.txt index 9321067cd..1c3f26044 100644 --- a/source/sync/device-sync-deprecation.txt +++ b/source/sync/device-sync-deprecation.txt @@ -12,6 +12,7 @@ Device Sync Deprecation :hidden: Migrate to AWS AppSync + Tutorial: Migrate an RN App to PowerSync As of September 2024, Device Sync is deprecated for Atlas App Services. Device Sync will reach end-of-life and be removed on **September 30, 2025**. If you @@ -31,7 +32,7 @@ Ditto Ditto is a real-time edge sync platform for mobile, web, IoT, and server apps. -- `Ditto Reference Architecture Guide `__ +- `Ditto Reference Architecture Guide (PDF) `__ - `Atlas Device Sync to Ditto migration guide `__ - `MongoDB Partner Page `__ - `Ditto documentation `__ @@ -44,8 +45,9 @@ SQLite databases. For more information on migration, refer to the following: -- `PowerSync Reference Architecture Guide `__ +- `PowerSync Reference Architecture Guide (PDF) `__ - `Atlas Device Sync to PowerSync migration guide `__ +- :ref:`Tutorial: Migrate a React Native Application from Device Sync to PowerSync ` ObjectBox ~~~~~~~~~ @@ -75,7 +77,7 @@ secure data movement to and from connected IoT devices. For more information on migration, refer to the following: -- `HiveMQ Reference Architecture Guide `__ +- `HiveMQ Reference Architecture Guide (PDF) `__ - `HiveMQ documentation `__ Ably @@ -86,7 +88,7 @@ variety of SDKs to power live experiences. For more information on migration, refer to the following: -- `Ably Reference Architecture Guide `__ +- `Ably Reference Architecture Guide (PDF) `__ - `Ably documentation `__ Parse (Open Source) diff --git a/source/sync/migration/awsappsync.txt b/source/sync/migration/awsappsync.txt index 46961a9a0..28633135e 100644 --- a/source/sync/migration/awsappsync.txt +++ b/source/sync/migration/awsappsync.txt @@ -99,7 +99,7 @@ AWS Lambda Resolver - Create a Lambda resolver based on the ``MongoDB-DataAPI`` template. For details on this process, refer to the Readme in the `MongoDB-API GitHub repo `__. - - Configure Lambda authorization via IAM +- Configure Lambda authorization via IAM AWS AppSync ``````````` diff --git a/source/sync/migration/reactnativetutorial.txt b/source/sync/migration/reactnativetutorial.txt new file mode 100644 index 000000000..59421c6dd --- /dev/null +++ b/source/sync/migration/reactnativetutorial.txt @@ -0,0 +1,1957 @@ +.. meta:: + :robots: nosnippet + +.. _react_native-powersync: + +========================================================= +Tutorial: Migrate a React Native Application to PowerSync +========================================================= + +.. contents:: On this page + :local: + :backlinks: none + :depth: 2 + :class: singlecol + + +As of September 2024, the Atlas Device SDKs (Realm), Device Sync, and +App Services have been deprecated. This means that users of these services +will have to migrate to another solution by September 2025. If you need more +time, reach out to support. + +PowerSync is a top alternative to Atlas Device Sync. It is an SQLite-based +solution and could be the right solution to migrate to if you have a mobile +application using Device Sync. + +This tutorial will guide you through the steps needed to +migrate a Device Sync mobile application, written in React Native, to +PowerSync. Your backend data will stay in Atlas, so you will need to +configure the PowerSync service, update the local database schemas and +bindings, and set up a backend service for writing to Atlas. + +This tutorial uses a Realm todo list application for React Native available in the +`realm2powersync example repository `__. + +Phase 1: Preparation and Setup +------------------------------ + +Deploy an Atlas Cluster +~~~~~~~~~~~~~~~~~~~~~~~ + +First, you need to deploy an Atlas Cluster and put in some test data. This +will guide you as if you are setting up Atlas for the first time. If you +already have a cluster deployed, feel free to skip ahead. + +1. Navigate to MongoDB Atlas and register for an Atlas account, or sign in + if you already have an account. +2. Next, create a cluster. + + .. image:: /images/migration/react_native_guide/image16.png + :alt: Screenshot of the UI + :lightbox: + + For test purposes, select the M0 (free) cluster with the default settings. + Feel free to make any additional changes to suit your needs. + +3. Click **Create Deployment**. + + .. image:: /images/migration/react_native_guide/image1.png + :alt: Screenshot of the UI + :lightbox: + + You are returned to your dashboard. The **Connect to Cluster** modal displays + automatically. + +4. Click **Choose a connection method**, then select **Drivers**. + + .. image:: /images/migration/react_native_guide/image2.png + :alt: Screenshot of the UI + :lightbox: + + From this screen, copy the URL that displays in step 3. + + .. image:: /images/migration/react_native_guide/image27.png + :alt: Screenshot of the UI + :lightbox: + + **Add your connection string into your application code.** This is your + connection string; it is required to access your MongoDB instance. Save the + connection string for future reference. + + You will create a username and password in the next steps that the PowerSync + instance will use to connect to the database. + +5. Click **Done** to close the modal. + + After your cluster finishes deploying, your dashboard should look similar + to the following. + +6. Click **Add data** to create a new database. + + .. image:: /images/migration/react_native_guide/image12.png + :alt: Screenshot of the UI + :lightbox: + + From the **Create a Database on Atlas** card, click **START**. + + .. image:: /images/migration/react_native_guide/image17.png + :alt: Screenshot of the UI + :lightbox: + + Create a database called PowerSync and a collection called Item, then click + **Create Database**. + + .. image:: /images/migration/react_native_guide/image26.png + :alt: Screenshot of the UI + :lightbox: + + You are returned to the dashboard and should see the newly created database + and collection: + + .. image:: /images/migration/react_native_guide/image3.png + :alt: Screenshot of the UI + :lightbox: + + Finally, you need to create a new user that PowerSync will use to connect to + this database. + + In the left sidebar, click **Database Access** under the Security heading. + + .. image:: /images/migration/react_native_guide/image4b.png + :alt: Screenshot of the UI + :lightbox: + + Click **Add New Database User**, and create a new user called ``powersync`` and + provide a password. Note the username and password to use in the connection + string you copied earlier. + + .. note:: + + If your username or password contains any of the following special + characters, you must convert them to a URL-safe format for your connection + string: ``$``, ``:``, ``/``, ``?``, ``!``, ``#``, ``[``, ``]``, ``@``. You can do this manually + or use a URL-encoding application, such as `urlencoder.org `__. + + In the **Database User Privileges** section, click **Add Specific Privilege** and + add a privilege for a ``readWrite`` and a ``dbAdmin`` role for the PowerSync + database. + + .. image:: /images/migration/react_native_guide/image22.png + :alt: Screenshot of the UI + :lightbox: + + Click **Add User**. + + You should see the newly created user with the required database permissions. + + .. image:: /images/migration/react_native_guide/image24.png + :alt: Screenshot of the UI + :lightbox: + +For more details on user permissions, refer to the MongoDB section of the +`PowerSync Source Database Setup `__ +guide. + +Add PowerSync IPs to IP Access List +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In order for PowerSync to access the database running in Atlas, you must add +the service IP addresses to the IP access list. These IP addresses are listed +in the +`PowerSync Security & IP Filtering `__ +documentation. + +In the left sidebar, click **Network Access** under the Security heading. + +Click **+ Add IP Address** and enter the IP address. To better assist anyone +administering this list in the future, we also recommend entering **PowerSync** +as the optional comment. + +Click **Confirm**, and repeat for each IP. + +Import Sample Data +~~~~~~~~~~~~~~~~~~ + +If you haven’t already, update the placeholders in the connection string that +you copied earlier with the username and password for your database user. + +In this step, you will import some sample data that will be used to sync data +in future steps. + +First, install MongoDB Database Tools to gain access to ``mongoimport``. +Refer to the `Installation guide `__ +instructions for your operating system. + +After you have installed ``database-tools``, enter the following in the terminal +to confirm that you can access ``mongoimport``: + +.. code-block:: bash + + mongoimport --version + +This should return the version of the tool. Consult the above Installation +guide if you are having problems. + +Next, create a JSON file called ``sample.json`` with the following contents: + +.. code-block:: bash + + [ + { + "isComplete": false, + "summary": "Complete project documentation", + "owner_id": "mockUserId" + }, + { + "isComplete": true, + "summary": "Buy groceries", + "owner_id": "mockUserId" + }, + { + "isComplete": false, + "summary": "Schedule dentist appointment", + "owner_id": "mockUserId" + }, + { + "isComplete": false, + "summary": "Prepare presentation for next week", + "owner_id": "mockUserId" + }, + { + "isComplete": true, + "summary": "Pay utility bills", + "owner_id": "mockUserId" + }, + { + "isComplete": false, + "summary": "Fix bug in login system", + "owner_id": "mockUserId2" + }, + { + "isComplete": false, + "summary": "Call mom", + "owner_id": "mockUserId" + }, + { + "isComplete": true, + "summary": "Submit expense reports", + "owner_id": "mockUserId2" + }, + { + "isComplete": false, + "summary": "Plan team building event", + "owner_id": "mockUserId2" + }, + { + "isComplete": false, + "summary": "Review pull requests", + "owner_id": "mockUserId2" + } + ] + +This sample data contains some to-do list items. The ``owner_id`` will be used +for filtering examples later in this tutorial. + +To import this JSON, enter the following command, replacing the +```` placeholder with your connection string: + +.. code-block:: bash + + mongoimport --uri="" --db=PowerSync --collection=Item + --file=sample.json --jsonArray + +You should see the following message: + +.. code-block:: bash + + 10 document(s) imported successfully. 0 document(s) failed to import. + +If not, confirm that your command parameters (including connection string) +are correct and that your Atlas user has the correct database access. + +You can view and manage the inserted documents by either navigating to your +collection in the Atlas UI or using the MongoDB Compass visual desktop +application. To view and manage your database and collections through MongoDB +Compass, you must connect using the same connection string. + +.. image:: /images/migration/react_native_guide/image10.png + :alt: Screenshot of the UI + :lightbox: + +Setup PowerSync +~~~~~~~~~~~~~~~ + +Now navigate to `PowerSync `__ and register or sign in. + +If you are signing in for the first time, you will need to create a new +instance to get started. + +Create a new instance called ``TodoList``. + +.. image:: /images/migration/react_native_guide/image5.png + :alt: Screenshot of the UI + :lightbox: + +Select MongoDB as the connecting database. + +.. image:: /images/migration/react_native_guide/image13.png + :alt: Screenshot of the UI + :lightbox: + +Use your Atlas connection string to populate the connection settings. + +.. important:: + + Use a shortened version of your connection string that does not contain + your username, password, or other URL parameters. For example, your + connection will look like ``mongodb+srv://m0cluster.h6folge.mongodb.net/``. + +Enter the Database name ("PowerSync"), username ("powersync"), and the password +you assigned to this account in a previous step. + +.. image:: /images/migration/react_native_guide/image20.png + :alt: Screenshot of the UI + :lightbox: + +Click **Test connection** to ensure you can connect successfully. + +If you see the following error, confirm that all of the required PowerSync +service IPs are in your Atlas IP access list. + +.. image:: /images/migration/react_native_guide/image21.png + :alt: Screenshot of the UI + :lightbox: + +If you are still having issues, refer to the +`PowerSync Database Connection Guide `__ +for MongoDB connections. + +Click **Next** to deploy your new PowerSync instance. This can take a few +minutes to complete. + +After your instance is deployed, you can ensure that you can view the migrated +data by creating some basic sync rules. + +First, remove the default sync rules and replace them with the following: + +.. code-block:: yaml + + bucket_definitions: + user_buckets: + parameters: SELECT request.user_id() as user_id + data: + - SELECT _id as id, * FROM "Item" WHERE bucket.user_id = 'global' + OR owner_id = bucket.user_id + +For items to sync correctly to the PowerSync service, note the following: + +- The ``_id`` must be mapped to ``id``. +- The collection name “Item” must be enclosed in quotation marks. This is + because our collection name starts with a capital letter. +- The user-specific buckets must match to a ``user_id`` of ``global``, which provides + access to the entire database. Otherwise, you will match on the provided + ``user_id``, which will be retrieved from the auth token. + +Note that PowerSync Sync Rules are a pretty deep topic. To learn more, you can check out this +`Sync Rules blog post `__ +or the +`PowerSync Sync Rules `__ documentation. + +Click **Save and Deploy**. Once again, it may take quite a few minutes for the +deployment to finish. + +After the deployment completes, you should see the following: + +.. image:: /images/migration/react_native_guide/image23.png + :alt: Screenshot of the UI + :lightbox: + +After the deployment completes, you should see the appropriate status. + +If you get any errors, ensure that the `PowerSync` user is set up with the +permissions listed in the +`PowerSync Source Database Setup `__ +documentation. + +Click **Manage instances** to review the sync rules and deployment status. + +View Synced Data +~~~~~~~~~~~~~~~~ + +To finalize this setup, you will use the +PowerSync Diagnostics App to view the to-do list items you have just created and +added to your sync rules. To use this tool, you first need to create a development +token. + +- At the top of the PowerSync page, click ``Manage Instances``. +- In the left sidebar, click the ellipsis (…) next to TodoList to open the context menu for this instance, +and then select **Edit Instance**. +- Select the **Client Auth** tab, and click **Enable development tokens**. +- Click **Save and deploy**. + +.. image:: /images/migration/react_native_guide/image14.png + :alt: Screenshot of the UI + :lightbox: + +Click the ellipsis (…) next to TodoList to open the context menu for this +instance again, and select **Generate Development Token**. + +You will be asked to provide a token subject/user_id. This will act as the +``user_id``, and you can set up your sync rules to act upon it. + +With the sync rules we defined earlier, you can set the subject/user_id to +``global`` to generate a token that will have access to the entire dataset. You +can also set this to ``mockUserId`` or ``mockUserId2`` to sync on a specific +``owner_id``. + +Copy the generated token, then open the +`Diagnostics App `__ and paste in +the Development Token. + +.. note:: + + The Development Token will expire in 12 hours. The diagnostics tool will + stop syncing with Atlas after expiry, so you must generate a new token if + you want it to resume syncing. + +You should see a page similar to this one. + +.. image:: /images/migration/react_native_guide/image11.png + :alt: Screenshot of the UI + :lightbox: + +In the left sidebar, click **SQL Console**. + +Create a ``SELECT`` query to view all items: + +.. code-block:: bash + + SELECT * FROM Item + +.. image:: /images/migration/react_native_guide/image8.png + :width: 350px + :alt: Screenshot of the UI + :lightbox: + +You now have all the services necessary to sync your MongoDB database to a +mobile application. + +Phase 2: Prepare Realm App for Migration +---------------------------------------- + +Clone Initial Project +~~~~~~~~~~~~~~~~~~~~~ + +In this phase, you are going to clone a Realm todo list application for React +Native. The ``main`` branch of the `example repository `__ +contains the final result of the migration. + +To follow along with this guide using the example repo, checkout the ``00-Start-Here`` +branch: + +.. code-block:: bash + + git clone https://github.com/takameyer/realm2powersync + cd realm2powersync + git checkout 00-Start-Here + +Next, install the dependencies, so that the editor can pick up any imports and +ensure there are no errors as you’re editing this project. + +.. important:: + + This tutorial assumes you have the latest version of + `Node.js `__ installed. + +.. code-block:: bash + + npm install + +Because the application assumes there is an Atlas cluster with an active Device +Sync service, it is not yet runnable. In the next steps, you will make the +modifications needed to run the project as a local-only application. + +Refactor Device Sync Project to Local Only +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You must remove the Atlas Device Sync parts so that the application is +running with local-only data. + +First, open ``source/AppWrapper.txs``, and remove the ``AppProvider``, +``UserProvider``, and ``sync`` configuration. + +The updated ``AppWrapper.txs`` file should resemble the following: + +.. code-block:: javascript + + import React from 'react'; + import { StyleSheet, View, ActivityIndicator } from 'react-native'; + import { RealmProvider } from '@realm/react'; + + import { App } from './App'; + + import { Item } from './ItemSchema'; + + const LoadingIndicator = () => { + return ( + + + + ); + }; + + export const AppWrapper = () => { + return ( + + + + ); + }; + + const styles = StyleSheet.create({ + activityContainer: { + flex: 1, + flexDirection: 'row', + justifyContent: 'space-around', + padding: 10, + }, + }); + +Next, open ``source/App.tsx``, and remove the parts about ``dataExplorerLink`` +and the header buttons for ``OfflineMode`` and ``Logout`` (this will be implemented +later). + +The updated ``App.tsx`` file should resemble the following: + +.. code-block:: javascript + + import React from 'react'; + import { SafeAreaProvider } from 'react-native-safe-area-context'; + import { StyleSheet, Text, View } from 'react-native'; + import { NavigationContainer } from '@react-navigation/native'; + import { createStackNavigator } from '@react-navigation/stack'; + + import { LogoutButton } from './LogoutButton'; + import { ItemListView } from './ItemListView'; + import { OfflineModeButton } from './OfflineModeButton'; + + const Stack = createStackNavigator(); + + const headerRight = () => { + return ; + }; + + const headerLeft = () => { + return ; + }; + + export const App = () => { + return ( + <> + {/* All screens nested in RealmProvider have access + to the configured realm's hooks. */} + + + + + + + + + + Log in with the same account on another device or simulator to see + your list sync in real time. + + + + + ); + }; + + const styles = StyleSheet.create({ + footerText: { + fontSize: 12, + textAlign: 'center', + marginVertical: 4, + }, + hyperlink: { + color: 'blue', + }, + footer: { + paddingHorizontal: 24, + paddingVertical: 12, + }, + }); + + +Finally, open ``source/ItemListView.tsx``, and make the following updates: + +- Remove the flexible sync subscription code +- Replace user with a mock user: + - ``const user={ id: 'mockUserId' };`` +- Remove any ``dataExplorerer`` references +- Remove functionality of the ``Show All Tasks`` switch (this will be implemented + later) + +The updated ``ItemListView.tsx`` file should resemble the following: + +.. code-block:: javascript + + import React, { useCallback, useState, useEffect } from 'react'; + import { BSON } from 'realm'; + import { useRealm, useQuery } from '@realm/react'; + import { SafeAreaProvider } from 'react-native-safe-area-context'; + import { Alert, FlatList, StyleSheet, Switch, Text, View } from 'react-native'; + import { Button, Overlay, ListItem } from '@rneui/base'; + + import { CreateToDoPrompt } from './CreateToDoPrompt'; + + import { Item } from './ItemSchema'; + import { colors } from './Colors'; + + export function ItemListView() { + const realm = useRealm(); + const items = useQuery(Item).sorted('_id'); + const user = { id: 'mockUserId' }; + + const [showNewItemOverlay, setShowNewItemOverlay] = useState(false); + + const [showAllItems, setShowAllItems] = useState(true); + + // createItem() takes in a summary and then creates an Item object with that summary + const createItem = useCallback( + ({ summary }: { summary: string }) => { + // if the realm exists, create an Item + realm.write(() => { + return new Item(realm, { + summary, + owner_id: user?.id, + }); + }); + }, + [realm, user], + ); + + // deleteItem() deletes an Item with a particular _id + const deleteItem = useCallback( + (id: BSON.ObjectId) => { + // if the realm exists, get the Item with a particular _id and delete it + const item = realm.objectForPrimaryKey(Item, id); // search for a realm object with a primary key that is an objectId + if (item) { + if (item.owner_id !== user?.id) { + Alert.alert("You can't delete someone else's task!"); + } else { + realm.write(() => { + realm.delete(item); + }); + } + } + }, + [realm, user], + ); + // toggleItemIsComplete() updates an Item with a particular _id to be 'completed' + const toggleItemIsComplete = useCallback( + (id: BSON.ObjectId) => { + // if the realm exists, get the Item with a particular _id and update it's 'isCompleted' field + const item = realm.objectForPrimaryKey(Item, id); // search for a realm object with a primary key that is an objectId + if (item) { + if (item.owner_id !== user?.id) { + Alert.alert("You can't modify someone else's task!"); + } else { + realm.write(() => { + item.isComplete = !item.isComplete; + }); + } + } + }, + [realm, user], + ); + + return ( + + + + Show All Tasks + { + setShowAllItems(!showAllItems); + }} + value={showAllItems} + /> + + setShowNewItemOverlay(false)}> + { + setShowNewItemOverlay(false); + createItem({ summary }); + }} + /> + + item._id.toString()} + data={items} + renderItem={({ item }) => ( + + + {item.summary} + + + {item.owner_id === user?.id ? '(mine)' : ''} + + + {!item.isComplete && ( +