ditto_live_web_alpha 0.0.3 ditto_live_web_alpha: ^0.0.3 copied to clipboard
An alpha build of the Ditto SDK for Flutter Web
import 'dart:async';
import 'package:ditto_live_web_alpha/ditto_live_web_alpha.dart';
import 'package:flutter/material.dart';
import 'dialog.dart';
import 'task.dart';
import 'task_view.dart';
const appID = "caf9e870-d416-4b1c-9ab4-fb6e8319dd25";
const token = "cb639c76-5633-44dd-ad28-03a5a43f092e";
const authAppID = "3cffb689-8a99-4b4c-bca1-0809a5135748";
const collection = "tasks13";
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
// Loads the WebAssembly binary from the local assets
await initWasm();
// For loading the WebAssembly binary from a hosted URL, ensure valid CORS
// headers and mimetype application/wasm. For local development, you can use a
// local server like `npx serve ../lib/assets --cors`
//
// await initWasm("http://localhost:3000/ditto.wasm");
// final identity = await OnlinePlaygroundIdentity.create(
// appID: appID,
// token: token,
// );
final authenticationHandler = AuthenticationHandler(
authenticationExpiringSoon: (authenticator, secondsRemaining) async {
await authenticator.login(token: token, provider: "auth-webhook");
},
authenticationRequired: (authenticator) async {
await authenticator.login(token: token, provider: "auth-webhook");
},
);
final identity = await OnlineWithAuthenticationIdentity.create(
appID: authAppID,
authenticationHandler: authenticationHandler,
);
assert(identity.appID == authAppID);
assert(identity.enableDittoCloudSync == true);
assert(identity.customAuthUrl == null);
assert(identity.authenticationHandler == authenticationHandler);
//
// DittoLogger
//
DittoLogger.setMinimumLogLevel(LogLevel.info);
DittoLogger.setEmojiLogLevelHeadingsEnabled(true);
assert(await DittoLogger.getEnabled() == true);
DittoLogger.setEnabled(false);
assert(await DittoLogger.getEnabled() == false);
DittoLogger.setEnabled(true);
DittoLogger.setCustomLogCallback((level, message) {
print("[$level] => $message");
});
DittoLogger.error("Glad this is not a real error");
DittoLogger.setCustomLogCallback(null);
final ditto = await Ditto.open(
identity: identity,
persistenceDirectory: "foo",
);
// Commented out because this is called automatically and will only result in
// a warning.
// await ditto.disableSyncWithV3();
await ditto.startSync();
print("deviceName: ${ditto.deviceName}");
await ditto.setDeviceName("web2");
assert(ditto.deviceName == "web2");
print("persistence directory: ${ditto.persistenceDirectoryString}");
assert(ditto.isActivated == true);
print("Version: ${Ditto.version}");
// try {
// await ditto.store.execute("aksdjhfazksdjfakjs");
// } on JSObject catch (e) {
// print("exception");
// } on DittoError catch (e) {
// print("error");
// } catch (e) {
// print("failed successfully");
// print("type: ${e.runtimeType}");
// }
//
// Ditto closing
//
// assert(ditto.isClosed == false);
// await ditto.close();
// assert(ditto.isClosed == true);
// assert(ditto.store.observers.isEmpty);
// assert(ditto.store.attachmentFetchers.isEmpty);
// assert(ditto.sync.subscriptions.isEmpty);
//
// Small Peer Info
//
assert(await ditto.smallPeerInfo.getEnabled() == true);
await ditto.smallPeerInfo.setEnabled(false);
assert(await ditto.smallPeerInfo.getEnabled() == false);
assert((await ditto.smallPeerInfo.getMetadata()).isEmpty);
await ditto.smallPeerInfo.setMetadata({"foo": "bar"});
print("metadata: ${await ditto.smallPeerInfo.getMetadata()}");
assert(await ditto.smallPeerInfo.getSyncScope() ==
SmallPeerInfoSyncScope.bigPeerOnly);
await ditto.smallPeerInfo.setSyncScope(SmallPeerInfoSyncScope.localPeerOnly);
assert(await ditto.smallPeerInfo.getSyncScope() ==
SmallPeerInfoSyncScope.localPeerOnly);
runApp(MaterialApp(
debugShowCheckedModeBanner: false,
home: MyApp(ditto: ditto),
));
}
class MyApp extends StatefulWidget {
final Ditto ditto;
const MyApp({super.key, required this.ditto});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
QueryResult? _queryResult;
var _syncing = true;
StoreObserver? _storeObserver;
SyncSubscription? _syncSubscription;
@override
void initState() {
super.initState();
_init();
}
Future<void> _init() async {
if (widget.ditto.store.observers.isNotEmpty) {
throw "aaa";
}
_storeObserver = await widget.ditto.store.registerObserver(
"SELECT * FROM COLLECTION $collection (${Task.schema}) WHERE deleted = false",
onChange: (qr) => setState(() => _queryResult = qr),
);
assert(_storeObserver?.isCancelled == false);
assert(_storeObserver?.queryString ==
"SELECT * FROM COLLECTION $collection (${Task.schema}) WHERE deleted = false");
assert(_storeObserver?.queryArguments.isEmpty == true);
assert(widget.ditto.store.observers.first == _storeObserver);
// await _storeObserver!.cancel();
// if (widget.ditto.store.observers.isNotEmpty) {
// throw "aaa";
// }
_storeObserver!.changes.listen((queryResult) {
print({
"items": queryResult.items.map((item) => item.value).toList(),
"mutatedDocumentIDs":
queryResult.mutatedDocumentIDs.map((id) => id.toString()).toList(),
});
});
_syncSubscription = await widget.ditto.sync.registerSubscription(
"SELECT * FROM $collection WHERE deleted = false",
);
}
@override
void dispose() {
_storeObserver?.cancel();
_syncSubscription?.cancel();
super.dispose();
}
Future<void> _addTask() async {
final pair = await showAddTaskDialog(context, widget.ditto);
if (pair == null) return;
final (task, attachment) = pair;
try {
await widget.ditto.store.execute(
"INSERT INTO COLLECTION $collection (${Task.schema}) DOCUMENTS (:task)",
arguments: {
"task": {
...task.toJson(),
"image": attachment.toJson(),
},
},
);
} on DittoException catch (e) {
print("Ditto Exception");
print(e.message);
}
}
Future<void> _clearTasks() async {
await widget.ditto.store.execute(
"EVICT FROM COLLECTION $collection (${Task.schema}) WHERE true",
);
}
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: const Text("Ditto Tasks"),
actions: [
IconButton(
onPressed: _clearTasks,
icon: const Icon(Icons.clear),
),
],
),
floatingActionButton: FloatingActionButton(
onPressed: _addTask,
child: const Icon(Icons.add),
),
body: Center(
child: ListView(
children: [
_syncTile,
...?_queryResult?.items.map(
(item) => TaskView(
ditto: widget.ditto,
task: Task.fromJson(item.value),
token: item.value["image"],
),
),
],
),
),
);
Widget get _syncTile => SwitchListTile(
title: const Text("Syncing"),
value: _syncing,
onChanged: (value) async {
if (value) {
await widget.ditto.startSync();
} else {
await widget.ditto.stopSync();
}
widget.ditto
.isSyncActive()
.then((value) => print("isSyncActive: $value"));
setState(() => _syncing = value);
},
);
}