Merge pull request #1754 from famedly/krille/move-file-storage-to-mixin
refactor: Move file storage to mixin to not import dart:io
This commit is contained in:
commit
4ef461bb79
|
|
@ -47,6 +47,11 @@ jobs:
|
||||||
rm -r example
|
rm -r example
|
||||||
./scripts/prepare.sh
|
./scripts/prepare.sh
|
||||||
./scripts/test.sh
|
./scripts/test.sh
|
||||||
|
- name: Ensure SDK compiles on web
|
||||||
|
run: |
|
||||||
|
pushd web_test
|
||||||
|
dart pub get
|
||||||
|
dart run webdev build
|
||||||
|
|
||||||
coverage_without_olm:
|
coverage_without_olm:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
import 'dart:io';
|
||||||
|
import 'dart:typed_data';
|
||||||
|
|
||||||
|
import 'package:matrix/matrix.dart';
|
||||||
|
|
||||||
|
mixin DatabaseFileStorage {
|
||||||
|
bool get supportsFileStoring => fileStorageLocation != null;
|
||||||
|
|
||||||
|
late final Uri? fileStorageLocation;
|
||||||
|
late final Duration? deleteFilesAfterDuration;
|
||||||
|
|
||||||
|
Future<void> storeFile(Uri mxcUri, Uint8List bytes, int time) async {
|
||||||
|
final fileStorageLocation = this.fileStorageLocation;
|
||||||
|
if (!supportsFileStoring || fileStorageLocation == null) return;
|
||||||
|
|
||||||
|
final dir = Directory.fromUri(fileStorageLocation);
|
||||||
|
|
||||||
|
final file = File('${dir.path}/${mxcUri.toString().split('/').last}');
|
||||||
|
|
||||||
|
if (await file.exists()) return;
|
||||||
|
await file.writeAsBytes(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Uint8List?> getFile(Uri mxcUri) async {
|
||||||
|
final fileStorageLocation = this.fileStorageLocation;
|
||||||
|
if (!supportsFileStoring || fileStorageLocation == null) return null;
|
||||||
|
|
||||||
|
final dir = Directory.fromUri(fileStorageLocation);
|
||||||
|
|
||||||
|
final file = File('${dir.path}/${mxcUri.toString().split('/').last}');
|
||||||
|
|
||||||
|
if (await file.exists()) return await file.readAsBytes();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> deleteOldFiles(int savedAt) async {
|
||||||
|
final dirUri = fileStorageLocation;
|
||||||
|
final deleteFilesAfterDuration = this.deleteFilesAfterDuration;
|
||||||
|
if (!supportsFileStoring ||
|
||||||
|
dirUri == null ||
|
||||||
|
deleteFilesAfterDuration == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final dir = Directory.fromUri(dirUri);
|
||||||
|
final entities = await dir.list().toList();
|
||||||
|
for (final file in entities) {
|
||||||
|
if (file is! File) continue;
|
||||||
|
final stat = await file.stat();
|
||||||
|
if (DateTime.now().difference(stat.modified) > deleteFilesAfterDuration) {
|
||||||
|
Logs().v('Delete old file', file.path);
|
||||||
|
await file.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
import 'dart:typed_data';
|
||||||
|
|
||||||
|
mixin DatabaseFileStorage {
|
||||||
|
bool get supportsFileStoring => false;
|
||||||
|
|
||||||
|
late final Uri? fileStorageLocation;
|
||||||
|
late final Duration? deleteFilesAfterDuration;
|
||||||
|
|
||||||
|
Future<void> storeFile(Uri mxcUri, Uint8List bytes, int time) async {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Uint8List?> getFile(Uri mxcUri) async {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> deleteOldFiles(int savedAt) async {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -18,9 +18,7 @@
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
import 'dart:typed_data';
|
|
||||||
|
|
||||||
import 'package:sqflite_common/sqflite.dart';
|
import 'package:sqflite_common/sqflite.dart';
|
||||||
|
|
||||||
|
|
@ -36,6 +34,9 @@ import 'package:matrix/src/utils/run_benchmarked.dart';
|
||||||
import 'package:matrix/src/database/indexeddb_box.dart'
|
import 'package:matrix/src/database/indexeddb_box.dart'
|
||||||
if (dart.library.io) 'package:matrix/src/database/sqflite_box.dart';
|
if (dart.library.io) 'package:matrix/src/database/sqflite_box.dart';
|
||||||
|
|
||||||
|
import 'package:matrix/src/database/database_file_storage_stub.dart'
|
||||||
|
if (dart.library.io) 'package:matrix/src/database/database_file_storage_io.dart';
|
||||||
|
|
||||||
/// Database based on SQlite3 on native and IndexedDB on web. For native you
|
/// Database based on SQlite3 on native and IndexedDB on web. For native you
|
||||||
/// have to pass a `Database` object, which can be created with the sqflite
|
/// have to pass a `Database` object, which can be created with the sqflite
|
||||||
/// package like this:
|
/// package like this:
|
||||||
|
|
@ -50,7 +51,7 @@ import 'package:matrix/src/database/indexeddb_box.dart'
|
||||||
/// [sqflite_common_ffi](https://pub.dev/packages/sqflite_common_ffi).
|
/// [sqflite_common_ffi](https://pub.dev/packages/sqflite_common_ffi).
|
||||||
/// Learn more at:
|
/// Learn more at:
|
||||||
/// https://github.com/famedly/matrix-dart-sdk/issues/1642#issuecomment-1865827227
|
/// https://github.com/famedly/matrix-dart-sdk/issues/1642#issuecomment-1865827227
|
||||||
class MatrixSdkDatabase extends DatabaseApi {
|
class MatrixSdkDatabase extends DatabaseApi with DatabaseFileStorage {
|
||||||
static const int version = 7;
|
static const int version = 7;
|
||||||
final String name;
|
final String name;
|
||||||
late BoxCollection _collection;
|
late BoxCollection _collection;
|
||||||
|
|
@ -100,12 +101,15 @@ class MatrixSdkDatabase extends DatabaseApi {
|
||||||
late Box<String> _seenDeviceIdsBox;
|
late Box<String> _seenDeviceIdsBox;
|
||||||
|
|
||||||
late Box<String> _seenDeviceKeysBox;
|
late Box<String> _seenDeviceKeysBox;
|
||||||
@override
|
|
||||||
bool get supportsFileStoring => fileStoragePath != null;
|
|
||||||
@override
|
@override
|
||||||
final int maxFileSize;
|
final int maxFileSize;
|
||||||
final Directory? fileStoragePath;
|
|
||||||
final Duration? deleteFilesAfterDuration;
|
// there was a field of type `dart:io:Directory` here. This one broke the
|
||||||
|
// dart js standalone compiler. Migration via URI as file system identifier.
|
||||||
|
@Deprecated(
|
||||||
|
'Breaks support for web standalone. Use [fileStorageLocation] instead.')
|
||||||
|
Object? get fileStoragePath => fileStorageLocation?.toFilePath();
|
||||||
|
|
||||||
static const String _clientBoxName = 'box_client';
|
static const String _clientBoxName = 'box_client';
|
||||||
|
|
||||||
|
|
@ -168,9 +172,18 @@ class MatrixSdkDatabase extends DatabaseApi {
|
||||||
this.idbFactory,
|
this.idbFactory,
|
||||||
this.sqfliteFactory,
|
this.sqfliteFactory,
|
||||||
this.maxFileSize = 0,
|
this.maxFileSize = 0,
|
||||||
this.fileStoragePath,
|
// TODO : remove deprecated member migration on next major release
|
||||||
this.deleteFilesAfterDuration,
|
@Deprecated(
|
||||||
});
|
'Breaks support for web standalone. Use [fileStorageLocation] instead.')
|
||||||
|
dynamic fileStoragePath,
|
||||||
|
Uri? fileStorageLocation,
|
||||||
|
Duration? deleteFilesAfterDuration,
|
||||||
|
}) {
|
||||||
|
final legacyPath = fileStoragePath?.path;
|
||||||
|
this.fileStorageLocation = fileStorageLocation ??
|
||||||
|
(legacyPath is String ? Uri.tryParse(legacyPath) : null);
|
||||||
|
this.deleteFilesAfterDuration = deleteFilesAfterDuration;
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> open() async {
|
Future<void> open() async {
|
||||||
_collection = await BoxCollection.open(
|
_collection = await BoxCollection.open(
|
||||||
|
|
@ -309,26 +322,6 @@ class MatrixSdkDatabase extends DatabaseApi {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> deleteOldFiles(int savedAt) async {
|
|
||||||
final dir = fileStoragePath;
|
|
||||||
final deleteFilesAfterDuration = this.deleteFilesAfterDuration;
|
|
||||||
if (!supportsFileStoring ||
|
|
||||||
dir == null ||
|
|
||||||
deleteFilesAfterDuration == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final entities = await dir.list().toList();
|
|
||||||
for (final file in entities) {
|
|
||||||
if (file is! File) continue;
|
|
||||||
final stat = await file.stat();
|
|
||||||
if (DateTime.now().difference(stat.modified) > deleteFilesAfterDuration) {
|
|
||||||
Logs().v('Delete old file', file.path);
|
|
||||||
await file.delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> forgetRoom(String roomId) async {
|
Future<void> forgetRoom(String roomId) async {
|
||||||
await _timelineFragmentsBox.delete(TupleKey(roomId, '').toString());
|
await _timelineFragmentsBox.delete(TupleKey(roomId, '').toString());
|
||||||
|
|
@ -451,18 +444,6 @@ class MatrixSdkDatabase extends DatabaseApi {
|
||||||
return await _getEventsByIds(eventIds.cast<String>(), room);
|
return await _getEventsByIds(eventIds.cast<String>(), room);
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
|
||||||
Future<Uint8List?> getFile(Uri mxcUri) async {
|
|
||||||
final fileStoragePath = this.fileStoragePath;
|
|
||||||
if (!supportsFileStoring || fileStoragePath == null) return null;
|
|
||||||
|
|
||||||
final file =
|
|
||||||
File('${fileStoragePath.path}/${mxcUri.toString().split('/').last}');
|
|
||||||
|
|
||||||
if (await file.exists()) return await file.readAsBytes();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<StoredInboundGroupSession?> getInboundGroupSession(
|
Future<StoredInboundGroupSession?> getInboundGroupSession(
|
||||||
String roomId,
|
String roomId,
|
||||||
|
|
@ -1136,18 +1117,6 @@ class MatrixSdkDatabase extends DatabaseApi {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> storeFile(Uri mxcUri, Uint8List bytes, int time) async {
|
|
||||||
final fileStoragePath = this.fileStoragePath;
|
|
||||||
if (!supportsFileStoring || fileStoragePath == null) return;
|
|
||||||
|
|
||||||
final file =
|
|
||||||
File('${fileStoragePath.path}/${mxcUri.toString().split('/').last}');
|
|
||||||
|
|
||||||
if (await file.exists()) return;
|
|
||||||
await file.writeAsBytes(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> storeInboundGroupSession(
|
Future<void> storeInboundGroupSession(
|
||||||
String roomId,
|
String roomId,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
# https://dart.dev/guides/libraries/private-files
|
||||||
|
# Created by `dart pub`
|
||||||
|
.dart_tool/
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
This is a bare-bone sample project in order to ensure webdev can compile the SDK.
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
name: web_test
|
||||||
|
description: A test project for the webdev compiler.
|
||||||
|
version: 1.0.0
|
||||||
|
publish_to: none
|
||||||
|
|
||||||
|
environment:
|
||||||
|
sdk: ^3.2.0
|
||||||
|
|
||||||
|
# Add regular dependencies here.
|
||||||
|
dependencies:
|
||||||
|
matrix:
|
||||||
|
path: ..
|
||||||
|
|
||||||
|
dev_dependencies:
|
||||||
|
build_runner: ^2.4.9
|
||||||
|
build_web_compilers: ^4.0.10
|
||||||
|
webdev: ^3.4.0
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
import 'package:matrix/matrix.dart';
|
||||||
|
|
||||||
|
Future<void> main() async {
|
||||||
|
final client = Client('web_test');
|
||||||
|
await client.init();
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue