forked from AppFlowy-IO/AppFlowy
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: observe file upload state (AppFlowy-IO#6172)
* chore: observe file upload state * chore: observe file upload state * chore: upgrade client api * Update frontend/appflowy_flutter/lib/startup/tasks/file_storage_task.dart Co-authored-by: Lucas.Xu <[email protected]> * chore: fix tauri build --------- Co-authored-by: Lucas.Xu <[email protected]>
- Loading branch information
Showing
29 changed files
with
484 additions
and
123 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
149 changes: 149 additions & 0 deletions
149
frontend/appflowy_flutter/lib/startup/tasks/file_storage_task.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
import 'dart:async'; | ||
import 'dart:convert'; | ||
import 'dart:ffi'; | ||
import 'dart:isolate'; | ||
|
||
import 'package:appflowy_backend/dispatch/dispatch.dart'; | ||
import 'package:appflowy_backend/log.dart'; | ||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; | ||
import 'package:appflowy_backend/protobuf/flowy-storage/protobuf.dart'; | ||
import 'package:appflowy_result/appflowy_result.dart'; | ||
import 'package:flutter/foundation.dart'; | ||
import 'package:fixnum/fixnum.dart'; | ||
|
||
import '../startup.dart'; | ||
|
||
class FileStorageTask extends LaunchTask { | ||
const FileStorageTask(); | ||
|
||
@override | ||
Future<void> initialize(LaunchContext context) async { | ||
context.getIt.registerSingleton( | ||
FileStorageService(), | ||
dispose: (service) async { | ||
await service.dispose(); | ||
}, | ||
); | ||
} | ||
|
||
@override | ||
Future<void> dispose() async {} | ||
} | ||
|
||
class FileStorageService { | ||
FileStorageService() { | ||
_port.handler = _controller.add; | ||
_subscription = _controller.stream.listen( | ||
(event) { | ||
final fileProgress = FileProgress.fromJsonString(event); | ||
if (fileProgress != null) { | ||
Log.debug( | ||
"Upload progress: file: ${fileProgress.fileUrl} ${fileProgress.progress}", | ||
); | ||
final notifier = _notifierList[fileProgress.fileUrl]; | ||
if (notifier != null) { | ||
notifier.value = fileProgress; | ||
} | ||
} | ||
}, | ||
); | ||
|
||
final payload = RegisterStreamPB()..port = Int64(_port.sendPort.nativePort); | ||
FileStorageEventRegisterStream(payload).send(); | ||
} | ||
|
||
final Map<String, AutoRemoveNotifier<FileProgress>> _notifierList = {}; | ||
final RawReceivePort _port = RawReceivePort(); | ||
final StreamController<String> _controller = StreamController.broadcast(); | ||
late StreamSubscription<String> _subscription; | ||
|
||
AutoRemoveNotifier<FileProgress> onFileProgress({required String fileUrl}) { | ||
_notifierList.remove(fileUrl)?.dispose(); | ||
|
||
final notifier = AutoRemoveNotifier<FileProgress>( | ||
FileProgress(fileUrl: fileUrl, progress: 0), | ||
notifierList: _notifierList, | ||
fileId: fileUrl, | ||
); | ||
_notifierList[fileUrl] = notifier; | ||
|
||
// trigger the initial file state | ||
getFileState(fileUrl); | ||
|
||
return notifier; | ||
} | ||
|
||
Future<FlowyResult<FileStatePB, FlowyError>> getFileState(String url) { | ||
final payload = QueryFilePB()..url = url; | ||
return FileStorageEventQueryFile(payload).send(); | ||
} | ||
|
||
Future<void> dispose() async { | ||
// dispose all notifiers | ||
for (final notifier in _notifierList.values) { | ||
notifier.dispose(); | ||
} | ||
|
||
await _controller.close(); | ||
await _subscription.cancel(); | ||
_port.close(); | ||
} | ||
} | ||
|
||
class FileProgress { | ||
FileProgress({ | ||
required this.fileUrl, | ||
required this.progress, | ||
this.error, | ||
}); | ||
|
||
static FileProgress? fromJson(Map<String, dynamic>? json) { | ||
if (json == null) { | ||
return null; | ||
} | ||
|
||
try { | ||
if (json.containsKey('file_url') && json.containsKey('progress')) { | ||
return FileProgress( | ||
fileUrl: json['file_url'] as String, | ||
progress: (json['progress'] as num).toDouble(), | ||
error: json['error'] as String?, | ||
); | ||
} | ||
} catch (e) { | ||
Log.error('unable to parse file progress: $e'); | ||
} | ||
return null; | ||
} | ||
|
||
// Method to parse a JSON string and return a FileProgress object or null | ||
static FileProgress? fromJsonString(String jsonString) { | ||
try { | ||
final Map<String, dynamic> jsonMap = jsonDecode(jsonString); | ||
return FileProgress.fromJson(jsonMap); | ||
} catch (e) { | ||
return null; | ||
} | ||
} | ||
|
||
final double progress; | ||
final String fileUrl; | ||
final String? error; | ||
} | ||
|
||
class AutoRemoveNotifier<T> extends ValueNotifier<T> { | ||
AutoRemoveNotifier( | ||
super.value, { | ||
required this.fileId, | ||
required Map<String, AutoRemoveNotifier<FileProgress>> notifierList, | ||
}) : _notifierList = notifierList; | ||
|
||
final String fileId; | ||
final Map<String, AutoRemoveNotifier<FileProgress>> _notifierList; | ||
|
||
@override | ||
void dispose() { | ||
_notifierList.remove(fileId); | ||
super.dispose(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.