opt: add event loop def
This commit is contained in:
parent
28ce635498
commit
6725c9544b
@ -4,7 +4,7 @@ import 'dart:io';
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hbb/common.dart';
|
import 'package:flutter_hbb/common.dart';
|
||||||
import 'package:flutter_hbb/consts.dart';
|
import 'package:flutter_hbb/utils/event_loop.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:path/path.dart' as path;
|
import 'package:path/path.dart' as path;
|
||||||
|
|
||||||
@ -45,6 +45,7 @@ class FileModel {
|
|||||||
|
|
||||||
late final GetSessionID getSessionID;
|
late final GetSessionID getSessionID;
|
||||||
String get sessionID => getSessionID();
|
String get sessionID => getSessionID();
|
||||||
|
late final _FileDialogEventLoop evtLoop;
|
||||||
|
|
||||||
FileModel(this.parent) {
|
FileModel(this.parent) {
|
||||||
getSessionID = () => parent.target?.id ?? "";
|
getSessionID = () => parent.target?.id ?? "";
|
||||||
@ -64,14 +65,17 @@ class FileModel {
|
|||||||
jobController: jobController,
|
jobController: jobController,
|
||||||
fileFetcher: fileFetcher,
|
fileFetcher: fileFetcher,
|
||||||
getOtherSideDirectoryData: () => localController.directoryData());
|
getOtherSideDirectoryData: () => localController.directoryData());
|
||||||
|
evtLoop = _FileDialogEventLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> onReady() async {
|
Future<void> onReady() async {
|
||||||
|
await evtLoop.onReady();
|
||||||
await localController.onReady();
|
await localController.onReady();
|
||||||
await remoteController.onReady();
|
await remoteController.onReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> close() async {
|
Future<void> close() async {
|
||||||
|
await evtLoop.close();
|
||||||
parent.target?.dialogManager.dismissAll();
|
parent.target?.dialogManager.dismissAll();
|
||||||
await localController.close();
|
await localController.close();
|
||||||
await remoteController.close();
|
await remoteController.close();
|
||||||
@ -90,14 +94,16 @@ class FileModel {
|
|||||||
fileFetcher.tryCompleteTask(evt['value'], evt['is_local']);
|
fileFetcher.tryCompleteTask(evt['value'], evt['is_local']);
|
||||||
}
|
}
|
||||||
|
|
||||||
void overrideFileConfirm(Map<String, dynamic> evt) async {
|
Future<void> overrideFileConfirm(Map<String, dynamic> evt,
|
||||||
final resp = await showFileConfirmDialog(
|
{bool? overrideConfirm}) async {
|
||||||
|
final resp = overrideConfirm ??
|
||||||
|
await showFileConfirmDialog(
|
||||||
translate("Overwrite"), "${evt['read_path']}", true);
|
translate("Overwrite"), "${evt['read_path']}", true);
|
||||||
final id = int.tryParse(evt['id']) ?? 0;
|
final id = int.tryParse(evt['id']) ?? 0;
|
||||||
if (false == resp) {
|
if (false == resp) {
|
||||||
final jobIndex = jobController.getJob(id);
|
final jobIndex = jobController.getJob(id);
|
||||||
if (jobIndex != -1) {
|
if (jobIndex != -1) {
|
||||||
jobController.cancelJob(id);
|
await jobController.cancelJob(id);
|
||||||
final job = jobController.jobTable[jobIndex];
|
final job = jobController.jobTable[jobIndex];
|
||||||
job.state = JobState.done;
|
job.state = JobState.done;
|
||||||
jobController.jobTable.refresh();
|
jobController.jobTable.refresh();
|
||||||
@ -111,7 +117,7 @@ class FileModel {
|
|||||||
// overwrite
|
// overwrite
|
||||||
need_override = true;
|
need_override = true;
|
||||||
}
|
}
|
||||||
bind.sessionSetConfirmOverrideFile(
|
await bind.sessionSetConfirmOverrideFile(
|
||||||
id: sessionID,
|
id: sessionID,
|
||||||
actId: id,
|
actId: id,
|
||||||
fileNum: int.parse(evt['file_num']),
|
fileNum: int.parse(evt['file_num']),
|
||||||
@ -677,8 +683,8 @@ class JobController {
|
|||||||
debugPrint("jobError $evt");
|
debugPrint("jobError $evt");
|
||||||
}
|
}
|
||||||
|
|
||||||
void cancelJob(int id) async {
|
Future<void> cancelJob(int id) async {
|
||||||
bind.sessionCancelJob(id: sessionID, actId: id);
|
await bind.sessionCancelJob(id: sessionID, actId: id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadLastJob(Map<String, dynamic> evt) {
|
void loadLastJob(Map<String, dynamic> evt) {
|
||||||
@ -1167,3 +1173,58 @@ List<Entry> _sortList(List<Entry> list, SortBy sortType, bool ascending) {
|
|||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Define a general queue which can accepts different dialog type.
|
||||||
|
///
|
||||||
|
/// [Visibility]
|
||||||
|
/// The `_FileDialogType` and `_DialogEvent` are invisible for other models.
|
||||||
|
enum _FileDialogType { overwrite, unknown }
|
||||||
|
|
||||||
|
class _FileDialogEvent
|
||||||
|
extends BaseEvent<_FileDialogType, Map<String, dynamic>> {
|
||||||
|
WeakReference<FileModel> fileModel;
|
||||||
|
bool? _overrideConfirm;
|
||||||
|
|
||||||
|
_FileDialogEvent(this.fileModel, super.type, super.data);
|
||||||
|
|
||||||
|
void setOverrideConfirm(bool? confirm) {
|
||||||
|
_overrideConfirm = confirm;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
EventCallback<Map<String, dynamic>>? findCallback(_FileDialogType type) {
|
||||||
|
final model = fileModel.target;
|
||||||
|
if (model == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
switch (type) {
|
||||||
|
case _FileDialogType.overwrite:
|
||||||
|
return (data) async {
|
||||||
|
return await model.overrideFileConfirm(data, overrideConfirm: _overrideConfirm);
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _FileDialogEventLoop extends BaseEventLoop<_FileDialogType, Map<String, dynamic>> {
|
||||||
|
|
||||||
|
bool? overrideConfirm;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> onPreConsume(BaseEvent<_FileDialogType, Map<String, dynamic>> evt) async {
|
||||||
|
var event = evt as _FileDialogEvent;
|
||||||
|
event.setOverrideConfirm(overrideConfirm);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> onEventsClear() {
|
||||||
|
overrideConfirm = null;
|
||||||
|
return super.onEventsClear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setOverrideConfirm(bool confirm) {
|
||||||
|
overrideConfirm = confirm;
|
||||||
|
}
|
||||||
|
}
|
79
flutter/lib/utils/event_loop.dart
Normal file
79
flutter/lib/utils/event_loop.dart
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
|
typedef EventCallback<Data> = Future<dynamic> Function(Data data);
|
||||||
|
|
||||||
|
abstract class BaseEvent<EventType, Data> {
|
||||||
|
EventType type;
|
||||||
|
Data data;
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
BaseEvent(this.type, this.data);
|
||||||
|
|
||||||
|
/// Consume this event
|
||||||
|
@visibleForTesting
|
||||||
|
Future<dynamic> consume() async {
|
||||||
|
final cb = findCallback(type);
|
||||||
|
if (cb == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return cb(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EventCallback<Data>? findCallback(EventType type);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class BaseEventLoop<EventType, Data> {
|
||||||
|
final List<BaseEvent<EventType, Data>> _evts = [];
|
||||||
|
Timer? _timer;
|
||||||
|
|
||||||
|
List<BaseEvent<EventType, Data>> get evts => _evts;
|
||||||
|
|
||||||
|
Future<void> onReady() async {
|
||||||
|
// Poll every 100ms.
|
||||||
|
_timer = Timer.periodic(Duration(milliseconds: 100), _handleTimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An Event is about to be consumed.
|
||||||
|
Future<void> onPreConsume(BaseEvent<EventType, Data> evt) async {}
|
||||||
|
/// An Event was consumed.
|
||||||
|
Future<void> onPostConsume(BaseEvent<EventType, Data> evt) async {}
|
||||||
|
/// Events are all handled and cleared.
|
||||||
|
Future<void> onEventsClear() async {}
|
||||||
|
/// Events start to consume.
|
||||||
|
Future<void> onEventsStartConsuming() async {}
|
||||||
|
|
||||||
|
Future<void> _handleTimer(Timer timer) async {
|
||||||
|
if (_evts.isEmpty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
timer.cancel();
|
||||||
|
_timer = null;
|
||||||
|
// handle logic
|
||||||
|
await onEventsStartConsuming();
|
||||||
|
while (_evts.isNotEmpty) {
|
||||||
|
final evt = _evts.first;
|
||||||
|
_evts.remove(evt);
|
||||||
|
await onPreConsume(evt);
|
||||||
|
await evt.consume();
|
||||||
|
await onPostConsume(evt);
|
||||||
|
}
|
||||||
|
await onEventsClear();
|
||||||
|
// Now events are all processed
|
||||||
|
_timer = Timer.periodic(Duration(milliseconds: 100), _handleTimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> close() async {
|
||||||
|
_timer?.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_event(BaseEvent<EventType, Data> evt) {
|
||||||
|
_evts.add(evt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
_evts.clear();
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user