FurryChat/lib/utils/database/mobile.dart

92 lines
3.2 KiB
Dart
Raw Normal View History

import 'dart:ffi';
2020-07-20 15:33:52 +00:00
import 'dart:io';
import 'dart:isolate';
2020-05-13 13:58:59 +00:00
import 'package:famedlysdk/famedlysdk.dart';
2020-07-20 15:33:52 +00:00
import 'package:sqflite/sqflite.dart' show getDatabasesPath;
import 'package:path/path.dart' as p;
2020-05-13 13:58:59 +00:00
import 'package:flutter/material.dart';
2020-07-20 15:33:52 +00:00
import 'package:moor/moor.dart';
import 'package:moor/isolate.dart';
import '../platform_infos.dart';
2020-07-20 15:33:52 +00:00
import 'cipher_db.dart' as cipher;
import 'package:moor/ffi.dart' as moor;
import 'package:sqlite3/open.dart';
2020-05-13 13:58:59 +00:00
2020-07-20 15:33:52 +00:00
bool _inited = false;
// see https://moor.simonbinder.eu/docs/advanced-features/isolates/
void _startBackground(_IsolateStartRequest request) {
// this is the entry point from the background isolate! Let's create
// the database from the path we received
if (!_inited) {
cipher.init();
_inited = true;
}
final executor = cipher.VmDatabaseEncrypted(File(request.targetPath),
password: request.password, logStatements: request.logStatements);
// we're using MoorIsolate.inCurrent here as this method already runs on a
// background isolate. If we used MoorIsolate.spawn, a third isolate would be
// started which is not what we want!
final moorIsolate = MoorIsolate.inCurrent(
() => DatabaseConnection.fromExecutor(executor),
);
// inform the starting isolate about this, so that it can call .connect()
request.sendMoorIsolate.send(moorIsolate);
}
// used to bundle the SendPort and the target path, since isolate entry point
// functions can only take one parameter.
class _IsolateStartRequest {
final SendPort sendMoorIsolate;
final String targetPath;
final String password;
final bool logStatements;
_IsolateStartRequest(
this.sendMoorIsolate, this.targetPath, this.password, this.logStatements);
}
Future<Database> constructDb(
2020-05-22 10:21:16 +00:00
{bool logStatements = false,
String filename = 'database.sqlite',
2020-07-20 15:33:52 +00:00
String password = ''}) async {
if (PlatformInfos.isMobile || Platform.isMacOS) {
debugPrint('[Moor] using encrypted moor');
final dbFolder = await getDatabasesPath();
final targetPath = p.join(dbFolder, filename);
final receivePort = ReceivePort();
await Isolate.spawn(
_startBackground,
_IsolateStartRequest(
receivePort.sendPort, targetPath, password, logStatements),
);
final isolate = (await receivePort.first as MoorIsolate);
return Database.connect(await isolate.connect());
} else if (Platform.isLinux) {
debugPrint('[Moor] using desktop moor');
open.overrideFor(OperatingSystem.linux, _openOnLinux);
return Database(moor.VmDatabase.memory());
} else if (Platform.isWindows) {
debugPrint('[Moor] using desktop moor');
open.overrideFor(OperatingSystem.linux, _openOnWindows);
return Database(moor.VmDatabase.memory());
}
throw Exception('Platform not supported');
}
DynamicLibrary _openOnLinux() {
final libraryNextToScript = File('/usr/lib/x86_64-linux-gnu/libsqlite3.so');
return DynamicLibrary.open(libraryNextToScript.path);
}
DynamicLibrary _openOnWindows() {
final script = File(Platform.script.toFilePath());
final libraryNextToScript = File('${script.path}/sqlite3.dll');
return DynamicLibrary.open(libraryNextToScript.path);
2020-05-13 13:58:59 +00:00
}
Future<String> getLocalstorage(String key) async {
return null;
}