Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/workflows/react-native-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,13 @@ jobs:
with:
xcode-version: "16.4"

- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.3'
bundler-cache: true
working-directory: react-native

- name: Install Ruby gems
working-directory: react-native
run: bundle install
Expand Down
1 change: 1 addition & 0 deletions react-native/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ local.properties
.cxx/
*.keystore
!debug.keystore
.kotlin/

# node.js
#
Expand Down
2 changes: 0 additions & 2 deletions react-native/.prettierrc.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
module.exports = {
arrowParens: 'avoid',
bracketSameLine: true,
bracketSpacing: false,
singleQuote: true,
trailingComma: 'all',
};
1 change: 1 addition & 0 deletions react-native/.ruby-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.3.0
874 changes: 0 additions & 874 deletions react-native/.yarn/releases/yarn-3.6.4.cjs

This file was deleted.

74 changes: 38 additions & 36 deletions react-native/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import {
PermissionsAndroid,
Platform,
View,
SafeAreaView,
FlatList,
Button,
} from 'react-native';
import {SafeAreaProvider, SafeAreaView} from 'react-native-safe-area-context';
import {
Authenticator,
Ditto,
Expand Down Expand Up @@ -216,41 +216,43 @@ const App = () => {
);

return (
<SafeAreaView style={styles.container}>
{!hasPermissions && (
<View style={styles.permissionBanner}>
<Text style={styles.permissionText}>
⚠️ Limited functionality: Grant Bluetooth & WiFi permissions for peer-to-peer sync
</Text>
</View>
)}
<DittoInfo appId={DITTO_APP_ID} token={DITTO_PLAYGROUND_TOKEN} />
<DittoSync value={syncEnabled} onChange={toggleSync} />
<Fab onPress={() => setModalVisible(true)} />
<NewTaskModal
visible={modalVisible}
onSubmit={task => {
createTask(task);
setModalVisible(false);
}}
onClose={() => setModalVisible(false)}
/>
<EditTaskModal
visible={editingTask !== null}
task={editingTask}
onSubmit={(taskId, newTitle) => {
updateTaskTitle(taskId, newTitle);
setEditingTask(null);
}}
onClose={() => setEditingTask(null)}
/>
<FlatList
contentContainerStyle={styles.listContainer}
data={tasks}
renderItem={renderItem}
keyExtractor={item => item.id}
/>
</SafeAreaView>
<SafeAreaProvider>
<SafeAreaView style={styles.container}>
{!hasPermissions && (
<View style={styles.permissionBanner}>
<Text style={styles.permissionText}>
⚠️ Limited functionality: Grant Bluetooth & WiFi permissions for peer-to-peer sync
</Text>
</View>
)}
<DittoInfo appId={DITTO_APP_ID} token={DITTO_PLAYGROUND_TOKEN} />
<DittoSync value={syncEnabled} onChange={toggleSync} />
<Fab onPress={() => setModalVisible(true)} />
<NewTaskModal
visible={modalVisible}
onSubmit={task => {
createTask(task);
setModalVisible(false);
}}
onClose={() => setModalVisible(false)}
/>
<EditTaskModal
visible={editingTask !== null}
task={editingTask}
onSubmit={(taskId, newTitle) => {
updateTaskTitle(taskId, newTitle);
setEditingTask(null);
}}
onClose={() => setEditingTask(null)}
/>
<FlatList
contentContainerStyle={styles.listContainer}
data={tasks}
renderItem={renderItem}
keyExtractor={item => item.id}
/>
</SafeAreaView>
</SafeAreaProvider>
);
};

Expand Down
2 changes: 1 addition & 1 deletion react-native/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ gem 'concurrent-ruby', '< 1.3.4'
gem 'bigdecimal'
gem 'logger'
gem 'benchmark'
gem 'mutex_m'
gem 'mutex_m'
42 changes: 23 additions & 19 deletions react-native/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.7)
CFPropertyList (3.0.8)
activesupport (7.2.3)
base64
nkf
rexml
activesupport (6.1.7.10)
concurrent-ruby (~> 1.0, >= 1.0.2)
benchmark (>= 0.3)
bigdecimal
concurrent-ruby (~> 1.0, >= 1.3.1)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
logger (>= 1.4.2)
minitest (>= 5.1)
tzinfo (~> 2.0)
zeitwerk (~> 2.3)
securerandom (>= 0.3)
tzinfo (~> 2.0, >= 2.0.5)
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
algoliasearch (1.27.5)
httpclient (~> 2.8, >= 2.8.3)
json (>= 1.5.1)
atomos (0.1.3)
base64 (0.3.0)
benchmark (0.4.1)
bigdecimal (3.2.2)
benchmark (0.5.0)
bigdecimal (3.3.1)
claide (1.1.0)
cocoapods (1.15.2)
addressable (~> 2.8)
Expand Down Expand Up @@ -60,8 +63,10 @@ GEM
cocoapods-try (1.2.0)
colored2 (3.1.2)
concurrent-ruby (1.3.3)
connection_pool (2.5.4)
drb (2.2.3)
escape (0.0.4)
ethon (0.16.0)
ethon (0.15.0)
ffi (>= 1.15.0)
ffi (1.17.2)
fourflusher (2.3.1)
Expand All @@ -71,20 +76,20 @@ GEM
mutex_m
i18n (1.14.7)
concurrent-ruby (~> 1.0)
json (2.7.6)
json (2.16.0)
logger (1.7.0)
minitest (5.25.4)
minitest (5.26.2)
molinillo (0.8.0)
mutex_m (0.3.0)
nanaimo (0.3.0)
nap (1.1.0)
netrc (0.11.0)
nkf (0.2.0)
public_suffix (4.0.7)
rexml (3.4.1)
rexml (3.4.4)
ruby-macho (2.5.1)
typhoeus (1.4.1)
ethon (>= 0.9.0)
securerandom (0.4.1)
typhoeus (1.5.0)
ethon (>= 0.9.0, < 0.16.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
xcodeproj (1.25.1)
Expand All @@ -94,7 +99,6 @@ GEM
colored2 (~> 3.1)
nanaimo (~> 0.3.0)
rexml (>= 3.3.6, < 4.0)
zeitwerk (2.6.18)

PLATFORMS
ruby
Expand All @@ -110,7 +114,7 @@ DEPENDENCIES
xcodeproj (< 1.26.0)

RUBY VERSION
ruby 2.6.10p210
ruby 3.3.0p0

BUNDLED WITH
2.6.9
2.5.3
14 changes: 5 additions & 9 deletions react-native/__tests__/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,12 @@
* @format
*/

import 'react-native';
import React from 'react';
import ReactTestRenderer from 'react-test-renderer';
import App from '../App';

// Note: import explicitly to use the types shipped with jest.
import {it} from '@jest/globals';

// Note: test renderer must be required after react-native.
import renderer from 'react-test-renderer';

it('renders correctly', () => {
renderer.create(<App />);
test('renders correctly', async () => {
await ReactTestRenderer.act(() => {
Comment on lines +9 to +10
Copy link

Copilot AI Nov 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test has been changed from a synchronous it('renders correctly', ...) to an asynchronous test('renders correctly', async () => ...). While this aligns with React 18+ best practices and the use of ReactTestRenderer.act(), the test doesn't actually await any asynchronous operations within the act callback.

Consider whether the async keyword is necessary here. If there are no async operations to await, the test could remain synchronous:

test('renders correctly', () => {
  ReactTestRenderer.act(() => {
    ReactTestRenderer.create(<App />);
  });
});

However, if the App component or its children perform async operations during rendering, keeping it as async is correct.

Suggested change
test('renders correctly', async () => {
await ReactTestRenderer.act(() => {
test('renders correctly', () => {
ReactTestRenderer.act(() => {

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rejected. Trying to keep as close as possible to the RN template to minimize diffs and possible confusion.

ReactTestRenderer.create(<App />);
});
});
5 changes: 5 additions & 0 deletions react-native/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,17 @@ android {
compileSdk rootProject.ext.compileSdkVersion

namespace "com.dittoreactnativesampleapp"

buildFeatures {
buildConfig = true
}
defaultConfig {
applicationId "com.dittoreactnativesampleapp"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
buildConfigField("boolean", "IS_EDGE_TO_EDGE_ENABLED", "false")
}
signingConfigs {
debug {
Expand Down
8 changes: 4 additions & 4 deletions react-native/android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
buildscript {
ext {
buildToolsVersion = "35.0.0"
buildToolsVersion = "36.0.0"
minSdkVersion = 24
compileSdkVersion = 35
targetSdkVersion = 35
compileSdkVersion = 36
targetSdkVersion = 36
ndkVersion = "27.1.12297006"
kotlinVersion = "2.0.21"
kotlinVersion = "2.1.20"
}
repositories {
google()
Expand Down
5 changes: 5 additions & 0 deletions react-native/android/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,8 @@ newArchEnabled=true
# Use this property to enable or disable the Hermes JS engine.
# If set to false, you will be using JSC instead.
hermesEnabled=true

# Use this property to enable edge-to-edge display support.
# This allows your app to draw behind system bars for an immersive UI.
# Note: Only works with ReactActivity and should not be used with custom Activity.
edgeToEdgeEnabled=false
2 changes: 1 addition & 1 deletion react-native/app.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"name": "DittoReactNativeSampleApp",
"displayName": "DittoReactNativeSampleApp"
"displayName": "Ditto Task Sync"
}
4 changes: 2 additions & 2 deletions react-native/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
* @format
*/

import {AppRegistry} from 'react-native';
import { AppRegistry } from 'react-native';
import App from './App';
import {name as appName} from './app.json';
import { name as appName } from './app.json';

AppRegistry.registerComponent(appName, () => App);
4 changes: 4 additions & 0 deletions react-native/ios/DittoReactNativeSampleApp/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
Expand Down Expand Up @@ -41,6 +43,8 @@
<string>Uses WiFi to connect and sync with nearby devices.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>
<key>RCTNewArchEnabled</key>
<true/>
<key>UIBackgroundModes</key>
<array>
<string>bluetooth-central</string>
Expand Down
Loading
Loading