|
23 | 23 |
|
24 | 24 | </div> |
25 | 25 |
|
26 | | -A suite of SDKs that provides UI components and data models to quickly build a |
27 | | -peer-to-peer chat application using the Ditto Platform. |
| 26 | +# DittoChat Quickstart Guide |
28 | 27 |
|
29 | | -## Features |
| 28 | +This guide walks you through adding DittoChat to an iOS or Android app from scratch. By the end you'll have a working peer-to-peer chat experience that syncs over Bluetooth, Wi-Fi, and the cloud. |
30 | 29 |
|
31 | | -- Real-time, peer-to-peer chat |
| 30 | +--- |
32 | 31 |
|
33 | | -- Group chat and private messaging |
| 32 | +## Prerequisites (Both Platforms) |
34 | 33 |
|
35 | | -- User presence and typing indicators |
| 34 | +Before you begin, make sure you have the following: |
36 | 35 |
|
37 | | -- Easy-to-integrate SwiftUI views |
| 36 | +1. **A Ditto account** — Sign up free at the [Ditto Portal](https://portal.ditto.live). |
| 37 | +2. **An App ID and Online Playground Token** — Create a new app in the portal and copy these credentials. You'll need them to initialize the SDK. |
38 | 38 |
|
39 | | -- Built on the Ditto Sync Platform |
| 39 | +--- |
40 | 40 |
|
41 | | -## Requirements: |
| 41 | +## iOS Quickstart (Swift / SwiftUI) |
42 | 42 |
|
43 | | -### iOS |
| 43 | +### Step 1 — Create or Open Your Xcode Project |
44 | 44 |
|
45 | | -- iOS 18.0+ |
46 | | -- Xcode 15.6+ |
47 | | -- Swift 5.7+ |
48 | | -- A Ditto Account, AppId, and baseline knowledge of the [DittoSwift SDK](https://github.com/getditto/DittoSwiftPackage) |
| 45 | +Open an existing iOS project or create a new one in Xcode (**File → New → Project → App**). Select **SwiftUI** as the interface and **Swift** as the language. |
49 | 46 |
|
50 | | -### Android |
| 47 | +### Step 2 — Add the DittoChat Swift Package |
51 | 48 |
|
52 | | -- TBD |
| 49 | +1. In Xcode, go to **File → Add Package Dependencies…** |
| 50 | +2. In the search bar, paste the DittoChat repository URL: |
53 | 51 |
|
54 | | -### Web |
| 52 | + ``` |
| 53 | + https://github.com/getditto/DittoChat.git |
| 54 | + ``` |
55 | 55 |
|
56 | | -- Node.js 18.0+ |
57 | | -- React 18.0+ or 19.0+ |
58 | | -- TypeScript 4.5+ |
59 | | -- A Ditto Account, AppId, and baseline knowledge of the [Ditto JavaScript SDK](https://docs.ditto.live/sdk/latest/install-guides/js) |
| 56 | +3. Under **Dependency Rule**, choose **Up to Next Major Version** and set it to the latest release (check the [Releases page](https://github.com/getditto/DittoChat/releases) for the current version). |
| 57 | +4. Click **Add Package**. |
| 58 | +5. When prompted, select the DittoChat library product and add it to your app target. |
60 | 59 |
|
61 | | -#### Packages |
| 60 | +### Step 3 — Configure Permissions |
62 | 61 |
|
63 | | -The JavaScript implementation consists of two packages: |
| 62 | +Ditto uses Bluetooth LE and local networking for peer-to-peer sync. You need to declare usage descriptions so iOS can prompt the user for permission. |
64 | 63 |
|
65 | | -**[@dittolive/ditto-chat-core](./sdks/js/ditto-chat-core/README.md)** - Core data models and React hooks for real-time chat functionalities |
| 64 | +Add the following keys to your project's **Info.plist**: |
66 | 65 |
|
67 | | -```bash |
68 | | -npm install @dittolive/ditto-chat-core |
69 | | -# or |
70 | | -yarn add @dittolive/ditto-chat-core |
| 66 | +```xml |
| 67 | +<key>NSBluetoothAlwaysUsageDescription</key> |
| 68 | +<string>Uses Bluetooth to connect and sync with nearby devices</string> |
| 69 | + |
| 70 | +<key>NSBluetoothPeripheralUsageDescription</key> |
| 71 | +<string>Uses Bluetooth to connect and sync with nearby devices</string> |
| 72 | + |
| 73 | +<key>NSLocalNetworkUsageDescription</key> |
| 74 | +<string>Uses WiFi to connect and sync with nearby devices</string> |
| 75 | + |
| 76 | +<key>NSBonjourServices</key> |
| 77 | +<array> |
| 78 | + <string>_http-alt._tcp.</string> |
| 79 | +</array> |
71 | 80 | ``` |
72 | 81 |
|
73 | | -**[@dittolive/ditto-chat-ui](./sdks/js/ditto-chat-ui/README.md)** - Ready-to-use React components for building chat UIs |
| 82 | +### Step 4 — Enable Background Modes (Optional but Recommended) |
| 83 | + |
| 84 | +To keep chat syncing when your app is in the background: |
| 85 | + |
| 86 | +1. Select your project in the navigator, then your app target. |
| 87 | +2. Go to **Signing & Capabilities → + Capability → Background Modes**. |
| 88 | +3. Enable the following: |
| 89 | + - **Uses Bluetooth LE accessories** |
| 90 | + - **Acts as a Bluetooth LE accessory** |
| 91 | + |
| 92 | +### Step 5 — Initialize Ditto and Present the Chat UI |
| 93 | + |
| 94 | +In your SwiftUI app entry point (e.g. `App.swift` or a root view), initialize a Ditto instance with your portal credentials and present the DittoChat view: |
| 95 | + |
| 96 | +```swift |
| 97 | +import SwiftUI |
| 98 | +import DittoSwift |
| 99 | +import DittoChat |
| 100 | + |
| 101 | +@main |
| 102 | +struct MyChatApp: App { |
| 103 | + @StateObject private var dittoInstance = DittoManager() |
| 104 | + |
| 105 | + var body: some Scene { |
| 106 | + WindowGroup { |
| 107 | + // Replace with the DittoChat view provided by the SDK. |
| 108 | + // See the example app in the `apps/` directory for |
| 109 | + // a complete working implementation. |
| 110 | + ContentView() |
| 111 | + .environmentObject(dittoInstance) |
| 112 | + } |
| 113 | + } |
| 114 | +} |
| 115 | + |
| 116 | +/// A simple singleton that owns the Ditto instance. |
| 117 | +class DittoManager: ObservableObject { |
| 118 | + let ditto: Ditto |
| 119 | + |
| 120 | + init() { |
| 121 | + ditto = Ditto( |
| 122 | + identity: .onlinePlayground( |
| 123 | + appID: "YOUR_APP_ID", |
| 124 | + token: "YOUR_PLAYGROUND_TOKEN" |
| 125 | + ) |
| 126 | + ) |
| 127 | + |
| 128 | + // Start syncing with nearby peers |
| 129 | + do { |
| 130 | + try ditto.startSync() |
| 131 | + } catch { |
| 132 | + print("Failed to start Ditto sync: \(error)") |
| 133 | + } |
| 134 | + } |
| 135 | +} |
| 136 | +``` |
| 137 | + |
| 138 | +> **Important:** Replace `YOUR_APP_ID` and `YOUR_PLAYGROUND_TOKEN` with the credentials from your Ditto Portal app. Never commit these values to source control — use environment variables or a configuration file excluded from Git. |
| 139 | +
|
| 140 | +### Step 6 — Build and Run |
| 141 | + |
| 142 | +1. Connect a physical iOS device (Bluetooth is not available in the Simulator). |
| 143 | +2. Select your device as the run destination and press **⌘R**. |
| 144 | +3. Grant Bluetooth and local network permissions when prompted. |
| 145 | +4. Run the app on a second device to see peer-to-peer chat in action. |
| 146 | + |
| 147 | +--- |
| 148 | + |
| 149 | +## Android Quickstart (Kotlin) |
| 150 | + |
| 151 | +> **Note:** The DittoChat Android SDK is under active development. The steps below show how to integrate the Ditto SDK in a Kotlin Android project and prepare for the DittoChat library. Check the [Releases page](https://github.com/getditto/DittoChat/releases) and the `sdks/kotlin/` directory for the latest availability. |
| 152 | +
|
| 153 | +### Step 1 — Create or Open Your Android Studio Project |
| 154 | + |
| 155 | +Open an existing project or create a new one in Android Studio (**File → New → New Project → Empty Activity**). Choose **Kotlin** as the language and set the minimum SDK to **API 23 (Android 6.0)** or higher. |
74 | 156 |
|
75 | | -```bash |
76 | | -npm install @dittolive/ditto-chat-ui |
77 | | -# or |
78 | | -yarn add @dittolive/ditto-chat-ui |
| 157 | +### Step 2 — Add the Ditto SDK Dependency |
| 158 | + |
| 159 | +1. In your **project-level** `build.gradle` (or `settings.gradle.kts`), make sure Maven Central is included: |
| 160 | + |
| 161 | + ```groovy |
| 162 | + // build.gradle (project-level) |
| 163 | + allprojects { |
| 164 | + repositories { |
| 165 | + mavenCentral() |
| 166 | + } |
| 167 | + } |
| 168 | + ``` |
| 169 | + |
| 170 | +2. In your **app-level** `build.gradle`, add the Ditto SDK: |
| 171 | + |
| 172 | + ```groovy |
| 173 | + // build.gradle (app-level) |
| 174 | + dependencies { |
| 175 | + implementation "live.ditto:ditto:4.14.1" // Check docs.ditto.live for the latest version |
| 176 | + } |
| 177 | + ``` |
| 178 | + |
| 179 | +3. Sync your project: **File → Sync Project with Gradle Files**. |
| 180 | + |
| 181 | +> Once the DittoChat Android library is published, you will add it alongside the core Ditto SDK. Watch this repo for release announcements. |
| 182 | +
|
| 183 | +### Step 3 — Configure Permissions |
| 184 | + |
| 185 | +The Ditto SDK's `AndroidManifest.xml` automatically merges the required Bluetooth and network permissions into your app. However, you should be aware of what's being added: |
| 186 | + |
| 187 | +```xml |
| 188 | +<!-- These are automatically merged by the Ditto SDK --> |
| 189 | +<uses-permission android:name="android.permission.BLUETOOTH" |
| 190 | + android:maxSdkVersion="30" /> |
| 191 | +<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" |
| 192 | + android:maxSdkVersion="30" /> |
| 193 | +<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" |
| 194 | + tools:targetApi="s" /> |
| 195 | +<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" |
| 196 | + tools:targetApi="s" /> |
| 197 | +<uses-permission android:name="android.permission.BLUETOOTH_SCAN" |
| 198 | + android:usesPermissionFlags="neverForLocation" |
| 199 | + tools:targetApi="s" /> |
| 200 | +<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" |
| 201 | + android:maxSdkVersion="32" /> |
| 202 | +<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" |
| 203 | + android:maxSdkVersion="30" /> |
| 204 | +<uses-permission android:name="android.permission.INTERNET" /> |
| 205 | +<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> |
| 206 | +<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> |
| 207 | +<uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" /> |
79 | 208 | ``` |
80 | 209 |
|
81 | | -## Publishing |
| 210 | +### Step 4 — Request Runtime Permissions |
82 | 211 |
|
83 | | -This monorepo uses [Changesets](https://github.com/changesets/changesets) for version management and publishing. |
| 212 | +Android requires that certain permissions (like Bluetooth and location) be requested from the user at runtime. Use the `DittoSyncPermissions` helper provided by the SDK: |
| 213 | + |
| 214 | +```kotlin |
| 215 | +import live.ditto.transports.DittoSyncPermissions |
| 216 | + |
| 217 | +// In your Activity's onCreate or a Composable's LaunchedEffect: |
| 218 | +fun requestPermissions() { |
| 219 | + val permissions = DittoSyncPermissions(this) |
| 220 | + val missing = permissions.missingPermissions() |
| 221 | + if (missing.isNotEmpty()) { |
| 222 | + this.requestPermissions(missing, 0) |
| 223 | + } |
| 224 | +} |
| 225 | +``` |
84 | 226 |
|
85 | | -### For Contributors |
| 227 | +Call this early in your app's lifecycle — before starting Ditto sync — so the user sees the permission prompts right away. |
86 | 228 |
|
87 | | -When making changes to the packages, please create a changeset to document your changes: |
| 229 | +### Step 5 — Initialize Ditto |
88 | 230 |
|
89 | | -```bash |
90 | | -npm run changeset |
| 231 | +Create a singleton `Application` class (or use your existing one) to initialize Ditto at app startup: |
| 232 | + |
| 233 | +```kotlin |
| 234 | +import android.app.Application |
| 235 | +import android.util.Log |
| 236 | +import live.ditto.* |
| 237 | +import live.ditto.android.DefaultAndroidDittoDependencies |
| 238 | + |
| 239 | +class MyChatApplication : Application() { |
| 240 | + |
| 241 | + lateinit var ditto: Ditto |
| 242 | + |
| 243 | + override fun onCreate() { |
| 244 | + super.onCreate() |
| 245 | + |
| 246 | + try { |
| 247 | + DittoLogger.minimumLogLevel = DittoLogLevel.DEBUG |
| 248 | + |
| 249 | + val androidDependencies = DefaultAndroidDittoDependencies(applicationContext) |
| 250 | + val identity = DittoIdentity.OnlinePlayground( |
| 251 | + androidDependencies, |
| 252 | + appId = "YOUR_APP_ID", |
| 253 | + token = "YOUR_PLAYGROUND_TOKEN" |
| 254 | + ) |
| 255 | + |
| 256 | + ditto = Ditto(androidDependencies, identity) |
| 257 | + ditto.startSync() |
| 258 | + } catch (e: DittoError) { |
| 259 | + Log.e("DittoChat", "Failed to start Ditto: ${e.message}") |
| 260 | + } |
| 261 | + } |
| 262 | +} |
| 263 | +``` |
| 264 | + |
| 265 | +Register the application class in your `AndroidManifest.xml`: |
| 266 | + |
| 267 | +```xml |
| 268 | +<application |
| 269 | + android:name=".MyChatApplication" |
| 270 | + ... > |
91 | 271 | ``` |
92 | 272 |
|
93 | | -This will prompt you to select which packages are affected and describe your changes. |
| 273 | +> **Important:** Replace `YOUR_APP_ID` and `YOUR_PLAYGROUND_TOKEN` with your portal credentials. Store secrets securely — use `BuildConfig` fields or a `local.properties` file that is excluded from version control. |
| 274 | +
|
| 275 | +### Step 6 — Build and Run |
| 276 | + |
| 277 | +1. Connect a physical Android device (Bluetooth is unavailable in the emulator). |
| 278 | +2. Run the app and grant all requested permissions. |
| 279 | +3. Deploy to a second device on the same network (or within Bluetooth range) to test peer-to-peer sync. |
| 280 | + |
| 281 | +--- |
| 282 | + |
| 283 | +## Verifying Peer-to-Peer Sync |
| 284 | + |
| 285 | +Once you have the app running on two or more devices: |
| 286 | + |
| 287 | +1. Make sure both devices have **Bluetooth** and **Wi-Fi** enabled. |
| 288 | +2. Both apps must be configured with the **same App ID** from the Ditto Portal. |
| 289 | +3. Send a message on one device — it should appear on the other within seconds. |
| 290 | +4. To test offline sync, enable **Airplane Mode** on both devices (but keep Bluetooth on). Messages will still sync directly over Bluetooth LE. |
| 291 | + |
| 292 | +--- |
| 293 | + |
| 294 | +## Troubleshooting |
| 295 | + |
| 296 | +| Symptom | Possible Cause | Fix | |
| 297 | +|---|---|---| |
| 298 | +| Devices don't discover each other | Missing permissions | Verify all Bluetooth and network permissions are granted in device settings | |
| 299 | +| Sync works on Wi-Fi but not Bluetooth | Background Modes not enabled (iOS) | Enable BLE Background Modes in Xcode capabilities | |
| 300 | +| `DittoError` on startup | Invalid App ID or token | Double-check your credentials in the [Ditto Portal](https://portal.ditto.live) | |
| 301 | +| Messages appear only on one device | Different App IDs | Ensure both devices use the same App ID | |
| 302 | +| Permissions prompt doesn't appear (Android) | `requestPermissions` not called | Call `DittoSyncPermissions.missingPermissions()` before `startSync()` | |
| 303 | +| Build fails after adding package (iOS) | Xcode version too old | DittoChat requires Xcode 15.6+; update Xcode | |
| 304 | + |
| 305 | +--- |
| 306 | + |
| 307 | +## Next Steps |
| 308 | + |
| 309 | +- **Explore the example apps** in the [`apps/`](https://github.com/getditto/DittoChat/tree/main/apps) directory for complete, runnable implementations. |
| 310 | +- **Web integration?** See the [Web (React/TypeScript) section](./README.md#web-react--typescript) in the main README. |
| 311 | +- **Customize the UI** — DittoChat components are designed to be themed and extended. Check the platform-specific SDK READMEs in `sdks/` for API details. |
| 312 | +- **Go to production** — Replace `OnlinePlayground` authentication with `OnlineWithAuthentication` for production apps. See the [Ditto Cloud Authentication docs](https://docs.ditto.live/auth-and-authorization/cloud-authentication) for a full walkthrough. |
| 313 | +- **Learn more about Ditto** — Visit [docs.ditto.live](https://docs.ditto.live) for comprehensive platform documentation. |
| 314 | + |
| 315 | +--- |
94 | 316 |
|
95 | | -### Release Process |
| 317 | +## Support |
96 | 318 |
|
97 | | -Releases are automated via GitHub Actions: |
| 319 | +If you run into issues: |
98 | 320 |
|
99 | | -1. When changesets are merged to `main`, a "Version Packages" PR is automatically created |
100 | | -2. Merging the "Version Packages" PR publishes the packages to NPM |
| 321 | +- **GitHub Issues:** [github.com/getditto/DittoChat/issues](https://github.com/getditto/DittoChat/issues) |
| 322 | +- **Ditto Support:** [support@ditto.live](mailto:support@ditto.live) |
| 323 | +- **Documentation:** [docs.ditto.live](https://docs.ditto.live) |
0 commit comments