Skip to content

getditto/react-native-ditto-tools

Repository files navigation

@dittolive/ditto-react-native-tools

Diagonistic and Debugging Tools for Ditto in React Native

⚠️ Platform Compatibility Notice
These tools currently do not support the React Native MacOS platform. They are designed for mobile (iOS, Android) platforms where Ditto's peer-to-peer functionality and file system access are available.

Required Dependencies

This library requires the following peer dependencies to be installed in your app:

  • @dittolive/ditto - Core Ditto SDK (>=4.11.6 - Tested on 4.11.6 and 4.12.2)
  • @dr.pogodin/react-native-fs - File system operations for log export and data directory cleanup
  • react-native-zip-archive - Directory compression for data export functionality

Warning

Some tools require iOS version 15.5 or higher. You may need to update your iOS target version.

Note

The required version of @dr.pogodin/react-native-fs depends on your React Native version. Please refer to the @dr.pogodin/react-native-fs releases to select the correct version for your project.

Installation

npm install @dittolive/ditto-react-native-tools @dittolive/ditto @dr.pogodin/react-native-fs react-native-zip-archive

or

yarn add @dittolive/ditto-react-native-tools @dittolive/ditto @dr.pogodin/react-native-fs react-native-zip-archive

iOS Setup

After installing dependencies, run:

cd ios && pod install && cd ..

Android Setup

For React Native 0.77.1+, auto-linking should handle Android setup automatically. If you encounter linking issues, clean your build:

cd android && ./gradlew clean && cd ..

Platform Setup

After installing this library, you need to configure your React Native app for Ditto.

Please follow the official Ditto React Native quickstart guide: React Native Setup

Usage

import React from 'react';
import { PeersList, DiskUsage, SystemSettings, QueryEditor } from '@dittolive/ditto-react-native-tools';
import { Ditto } from '@dittolive/ditto';

// Initialize your Ditto instance
const ditto = new Ditto({
  type: 'offlinePlayground',
  appID: 'your-app-id',
  offlineToken: 'your-offline-token',
});

function App() {
  return (
    <>
      <PeersList 
        ditto={ditto}
      />
    </>
  );
}

Note

Ditto instance should always be kept in a provider.

Components

PeersList

Display and monitor Ditto peer connections in real-time.

import { PeersList } from '@dittolive/ditto-react-native-tools';

<PeersList 
  ditto={ditto}
  showConnectionDetails={true}
  style={{ flex: 1 }}
/>

Props:

  • ditto (required): Your Ditto instance
  • showConnectionDetails?: boolean - Whether to show detailed connection information (default: true)
  • style?: ViewStyle - Custom styling for the main container
  • headerComponent?: () => React.ReactElement - Optional header component

Style Customization: The component's styling is controlled through built-in StyleSheet with the following key areas that can be customized via the style prop:

  • Main container: Background color, flex properties, padding
  • List content: Bottom padding and scroll behavior
  • Peer items: Card-style containers with shadows and rounded corners
  • Loading/Error states: Centered content with appropriate typography
// Example custom styling
<PeersList 
  ditto={ditto}
  style={{ 
    flex: 1, 
    backgroundColor: '#1a1a1a',  // Dark theme background
    paddingHorizontal: 8         // Reduce horizontal margins
  }}
/>

DiskUsage

Monitor and display Ditto's disk usage breakdown with export functionality.

import { DiskUsage } from '@dittolive/ditto-react-native-tools';

<DiskUsage 
  ditto={ditto}
  style={{ flex: 1 }}
/>

Props:

  • ditto (required): Your Ditto instance
  • style?: ViewStyle - Custom styling for the main container

Features:

  • Automatic Log Export: The "Export Logs" button uses Ditto's built-in Logger.exportToFile() method to save log files
  • Disk Usage Display: Shows real-time disk usage breakdown for different Ditto components (store, replication, attachments, auth)
  • Last Updated Time: Footer displays when the data was last refreshed

Style Customization: The component's styling is controlled through built-in StyleSheet with the following key areas that can be customized via the style prop:

  • Main container: Background color, flex properties, padding
  • Content layout: Card-style containers with proper spacing
  • Usage displays: Progress bars, labels, and value formatting
  • Action buttons: Export button styling and disabled states
  • Footer information: Last updated timestamp styling
// Example custom styling
<DiskUsage 
  ditto={ditto}
  style={{ 
    flex: 1, 
    backgroundColor: '#f8f9fa',  // Light gray background
    padding: 16                   // Add container padding
  }}
/>

SystemSettings

Display all Ditto system settings using the SHOW ALL DQL statement. Self-contained component with built-in refresh functionality.

import { SystemSettings } from '@dittolive/ditto-react-native-tools';

<SystemSettings 
  ditto={ditto}
  style={{ flex: 1, backgroundColor: '#f5f5f5' }}
/>

Props:

  • ditto (required): Your Ditto instance
  • style?: ViewStyle - Custom styling for the main container

Features:

  • Self-contained: No callbacks required - handles all interactions internally
  • System Settings Display: Shows all Ditto system settings from SHOW ALL DQL query
  • Real-time Search: Built-in search functionality with instant filtering
  • Search Capabilities: Case-insensitive search across both setting keys and values
  • Smart Count Display: Shows filtered results count (e.g., "5 of 141 settings")
  • Refresh Functionality: Built-in refresh button to reload settings
  • Performance Optimized: Uses FlatList virtualization and in-memory filtering for 200+ settings
  • Loading States: Automatic loading, error, and empty state handling
  • Visual Design: Clean search interface with bordered input and proper typography

Style Customization: The component's styling is controlled through built-in StyleSheet with the following key areas that can be customized via the style prop:

  • Main container: Background color, flex properties, padding
  • Header section: Settings count and refresh button layout
  • Settings list: Individual setting items with key-value pairs
  • Loading/Error states: Centered content with appropriate messaging
  • Footer information: Last updated timestamp styling

Search Functionality: The component includes a built-in search feature that:

  • Filters settings in real-time as you type
  • Searches both setting keys and values
  • Shows "X of Y settings" when actively searching
  • Displays "No settings match 'searchterm'" for no results
  • Includes a clear button (iOS) to reset the search
  • Maintains search state while refreshing data
// Example custom styling
<SystemSettings 
  ditto={ditto}
  style={{ 
    flex: 1, 
    backgroundColor: '#1a1a1a',  // Dark theme background
    paddingTop: 20               // Add top spacing
  }}
/>

QueryEditor

Execute DQL (Document Query Language) queries against your Ditto store with a comprehensive interface for query input, execution, and results display.

import { QueryEditor } from '@dittolive/ditto-react-native-tools';

<QueryEditor 
  ditto={ditto}
  style={{ flex: 1 }}
/>

Props:

  • ditto (required): Your Ditto instance
  • style?: ViewStyle - Custom styling for the main container

Features:

  • Multi-line Query Input: 3-line TextInput with word wrap and scrollable content for complex DQL queries
  • Smart Execution: Run button is disabled when query is empty, with loading state during execution
  • Results Display: Supports both SELECT queries (data results) and mutating queries (INSERT/UPDATE/DELETE with affected count)
  • Performance Optimized: Handles large result sets (20,000+ records) with FlatList virtualization
  • Expandable JSON View: Click any result row to view full JSON details in expandable format
  • Export Functionality: Share query results as formatted JSON using React Native's Share API
  • Cross-platform Compatible: Works on both iOS and Android with native share dialogs

Supported Query Types:

  • SELECT queries: Display results in a scrollable list with expandable JSON details
  • INSERT/UPDATE/DELETE: Show affected record count and operation success status
  • SHOW statements: Display system information and configuration

Style Customization: The QueryEditor component consists of three sub-components, each accepting custom styles:

interface QueryEditorStyles {
  container?: ViewStyle;           // Main container
  editorView?: ViewStyle;          // Query input section  
  headerView?: ViewStyle;          // Buttons section
  resultsView?: ViewStyle;         // Results display section
}

<QueryEditor 
  ditto={ditto}
  style={{
    container: { flex: 1, backgroundColor: '#f8f9fa' },
    editorView: { backgroundColor: 'white', padding: 16 },
    headerView: { backgroundColor: '#e9ecef', borderBottomWidth: 1 },
    resultsView: { flex: 1, backgroundColor: 'white' }
  }}
/>

Performance Features:

  • Virtual Scrolling: Uses FlatList with getItemLayout for optimal performance with large datasets
  • Memory Management: Results are dematerialized to prevent memory leaks
  • Efficient Rendering: Only visible rows are rendered, supporting 20,000+ records smoothly
  • Smart Loading States: Execution and sharing buttons show activity indicators during operations

Usage Examples:

// Basic usage for query testing
<QueryEditor ditto={ditto} />

// With custom container styling
<QueryEditor 
  ditto={ditto}
  style={{ 
    flex: 1, 
    backgroundColor: '#f5f5f5',
    margin: 10 
  }}
/>

// Example queries to try:
// SELECT * FROM myCollection
// INSERT INTO myCollection (name, value) VALUES ('test', 123)
// UPDATE myCollection SET value = 456 WHERE name = 'test'
// DELETE FROM myCollection WHERE name = 'test'
// SHOW ALL

Example App

This repository includes a fully functional example app demonstrating all features. See the example directory for setup instructions and implementation details.

Development of the Library

Testing Changes During Development

When making changes to the root library code and testing them in the example app, the project is setup with symlinks for testing.

package.json:

    "@dittolive/ditto-react-native-tools": "file:.."

To stop packages from bleeding from the library to the example app, the example app's metro.config.js is setup to only use the modules we need from the library:

    // Explicitly map only the modules we need from the library
    extraNodeModules: (() => {
      const modules = [
        'react',
        'react-native',
        '@dittolive/ditto',
        '@dr.pogodin/react-native-fs',
        'react-native-zip-archive',
      ];
      const result = {};
      for (const mod of modules) {
        try {
          // Try to resolve the module from the example app first, then from the library
          let resolvedPath;
          try {
            resolvedPath = path.dirname(require.resolve(`${mod}/package.json`, { paths: [path.resolve(__dirname, 'node_modules')] }));
          } catch (e) {
            resolvedPath = path.dirname(require.resolve(`${mod}/package.json`, { paths: [path.resolve(libraryPath, 'node_modules')] }));
          }
          if (fs.existsSync(resolvedPath)) {
            result[mod] = resolvedPath;
          }
        } catch (e) {
          // Module not found, skip
        }
      }
      return result;
    })(),
    
    // Enable symlinks (default in RN 0.77.1, but explicit for clarity)
    unstable_enableSymlinks: true,

Development for the Library Workflow

After the initial setup, changes to the library source code will be immediately available in the example app:

  1. Make changes to the library source code in src/

  2. Clean all caches and reset development environment:

    cd example
    ./clear-cache.sh
  3. Start Metro (if not already running):

    npx react-native start --reset-cache
  4. Run the app:

    # In a new terminal:
    yarn ios --simulator="iPhone 16 Pro"
    # or
    yarn android

Note: With this setup, changes to the library code are immediately reflected in the example app through Fast Refresh. No need to rebuild or reinstall the library after each change!

Important: The Metro configuration includes a custom resolver that directly points to the library's TypeScript source files, enabling live updates without compilation.

Deploying example app to connected Android Device

To build and deploy the example app to a connected Android device:

Prerequisites

  1. Enable Developer Mode on your Android device:

    • Go to Settings → About phone
    • Tap "Build number" 7 times
    • Go back to Settings → Developer options
    • Enable "USB debugging"
  2. Connect your device via USB and verify connection:

    adb devices

    You should see your device listed (e.g., R5CN30DYCWA device)

Building and Installing

There are two methods to deploy to your device:

Method 1: Direct Installation (Recommended if yarn android fails)
  1. Clean previous builds (if needed):

    cd example/android
    ./gradlew clean
  2. Build the APK:

    ./gradlew assembleDebug
  3. Install the APK:

    adb install app/build/outputs/apk/debug/app-debug.apk
  4. Start Metro bundler:

    cd ../  # Back to example directory
    npx react-native start --reset-cache
  5. Launch the app:

    adb shell monkey -p com.ditto.example -c android.intent.category.LAUNCHER 1
Method 2: Using React Native CLI
cd example
yarn android

This command will automatically build and deploy to the connected device.

Troubleshooting

  • App not launching: Make sure the Metro bundler is running before launching the app
  • Device not found: Ensure USB debugging is enabled and the device is properly connected

Reverting to Normal Dependencies

If you need to revert to the standard file:.. dependency:

cd example
yarn unlink "@dittolive/ditto-react-native-tools"
yarn install --force

Environment Variables

The example app uses environment variables for Ditto configuration. After changing values in the .env file:

  1. Restart Metro with cache reset:

    npx react-native start --reset-cache
  2. Rebuild the app to pick up the new environment values:

    yarn ios --simulator="iPhone 16 Pro"

Note: Environment variables are compiled into the JavaScript bundle at build time, so you must rebuild the app after changing .env values.

Credits

This library utilizes the following open-source projects:

We greatly appreciate the maintainers and contributors of these projects for making this library possible.

Core Dependencies

  • Ditto - Edge sync platform for building real-time collaborative apps

About

Diagnostic and Debugging Tools for Ditto for React Native SDK

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 5