ditto_live 4.9.0-rc.4
ditto_live: ^4.9.0-rc.4 copied to clipboard
The Ditto Flutter SDK
example/lib/main.dart
// ignore_for_file: invalid_use_of_visible_for_testing_member
import 'package:ditto_live/ditto_live.dart';
import 'package:ditto_live_example/dialog.dart';
import 'package:ditto_live_example/dql_builder.dart';
import 'package:ditto_live_example/presence.dart';
import 'package:ditto_live_example/task.dart';
import 'package:ditto_live_example/task_view.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.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();
DittoLogger.isEnabled = true;
DittoLogger.minimumLogLevel = LogLevel.debug;
DittoLogger.customLogCallback = (level, message) {
print("[$level] => $message");
};
runApp(const MaterialApp(
debugShowCheckedModeBanner: false,
home: DittoExample(),
));
}
class DittoExample extends StatefulWidget {
const DittoExample({super.key});
@override
State<DittoExample> createState() => _DittoExampleState();
}
class _DittoExampleState extends State<DittoExample> {
Ditto? _ditto;
var _syncing = true;
int _pageIndex = 0;
@override
void initState() {
super.initState();
_initDitto();
}
Future<void> _initDitto() async {
await [
Permission.bluetoothConnect,
Permission.bluetoothAdvertise,
Permission.nearbyWifiDevices,
Permission.bluetoothScan
].request();
// final identity = await OnlinePlaygroundIdentity.create(
// appID: appID,
// token: token,
// );
final identity = OnlineWithAuthenticationIdentity(
appID: authAppID,
authenticationHandler: AuthenticationHandler(
authenticationExpiringSoon: (authenticator, secondsRemaining) async {
print(authenticator.status);
await authenticator.login(token: token, provider: "auth-webhook");
},
authenticationRequired: (authenticator) async {
print(authenticator.status);
await authenticator.login(token: token, provider: "auth-webhook");
},
),
);
final dataDir = await getApplicationDocumentsDirectory();
final persistenceDirectory = "${dataDir.path}/ditto";
print("dir: $persistenceDirectory");
final ditto = await Ditto.open(
identity: identity,
persistenceDirectory: persistenceDirectory,
);
ditto.updateTransportConfig((config) {
config.setAllPeerToPeerEnabled(true);
config.connect.webSocketUrls.add(
"wss://$authAppID.cloud.ditto.live",
);
});
ditto.deviceName = "Flutter (${ditto.deviceName})";
print("Device name: ${ditto.deviceName}");
print("Persistence directory path as string");
// print(ditto.persistenceDirectoryString);
ditto.smallPeerInfo.isEnabled = true;
ditto.smallPeerInfo.syncScope = SmallPeerInfoSyncScope.bigPeerOnly;
ditto.startSync();
setState(() => _ditto = ditto);
}
Future<void> _addTask() async {
final pair = await showAddTaskDialog(context, _ditto!);
if (pair == null) return;
final (task, attachment) = pair;
await _ditto!.store.execute(
"INSERT INTO COLLECTION $collection (${Task.schema}) DOCUMENTS (:task)",
arguments: {
"task": {
...task.toJson(),
"image": attachment,
// "image": { "_id": asasd, "_ditto_internal_...": 2},
},
},
);
}
Future<void> _clearTasks() async {
await _ditto!.store.execute(
"EVICT FROM COLLECTION $collection (${Task.schema}) WHERE true",
);
}
@override
Widget build(BuildContext context) {
final ditto = _ditto;
if (ditto == null) return _loading;
return Scaffold(
appBar: AppBar(
title: const Text("Ditto Tasks"),
actions: [
IconButton(
icon: const Icon(Icons.clear),
tooltip: "Clear",
onPressed: _clearTasks,
),
],
),
floatingActionButton: _pageIndex == 0 ? _fab : null,
body: switch (_pageIndex) {
0 => Column(
children: [
_syncTile,
const Divider(height: 1),
Expanded(child: _tasksList),
],
),
1 => PresenceView(ditto: _ditto!),
_ => throw "unreachable",
},
bottomNavigationBar: BottomNavigationBar(
items: const [
BottomNavigationBarItem(icon: Icon(Icons.task), label: "Tasks"),
BottomNavigationBarItem(icon: Icon(Icons.devices), label: "Presence"),
],
currentIndex: _pageIndex,
onTap: (value) => setState(() => _pageIndex = value),
),
);
}
Widget get _loading => Scaffold(
appBar: AppBar(title: const Text("Ditto Tasks")),
body: const Center(
child: CircularProgressIndicator(),
),
);
Widget get _fab => FloatingActionButton(
onPressed: _addTask,
child: const Icon(Icons.add_task),
);
Widget get _syncTile => SwitchListTile(
title: const Text("Syncing"),
value: _syncing,
onChanged: (value) {
if (value) {
_ditto!.startSync();
} else {
_ditto!.stopSync();
}
setState(() => _syncing = value);
},
);
Widget get _tasksList => DqlBuilder(
ditto: _ditto!,
query:
"SELECT * FROM COLLECTION $collection (${Task.schema}) WHERE deleted = false",
builder: (context, response) {
Widget makeTaskView(QueryResultItem result) {
final task = Task.fromJson(result.value);
final imageToken = result.value["image"];
return _singleTask(task, imageToken);
}
final tasks = response.items.map(makeTaskView);
return ListView(children: [...tasks]);
},
);
Widget _singleTask(Task task, Map<String, dynamic>? image) => Dismissible(
key: Key("${task.id}-${task.title}"),
onDismissed: (direction) async {
await _ditto!.store.execute(
"UPDATE $collection SET deleted = true WHERE _id = '${task.id}'",
);
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Deleted Task ${task.title}")),
);
}
},
background: _dismissibleBackground(true),
secondaryBackground: _dismissibleBackground(false),
child: TaskView(ditto: _ditto!, task: task, token: image),
);
Widget _dismissibleBackground(bool primary) => Container(
color: Colors.red,
child: Align(
alignment: primary ? Alignment.centerLeft : Alignment.centerRight,
child: const Padding(
padding: EdgeInsets.all(8.0),
child: Icon(Icons.delete),
),
),
);
}