Trigger a Photos tab refresh after image processor is done

This commit is contained in:
Ming Ming 2022-09-10 12:03:49 +08:00
parent abdded09ca
commit a4a4d952f7
6 changed files with 75 additions and 11 deletions

View file

@ -121,6 +121,7 @@ class ScanAccountDirBloc
_accountPrefUpdatedEventListener.begin(); _accountPrefUpdatedEventListener.begin();
_nativeFileExifUpdatedListener?.begin(); _nativeFileExifUpdatedListener?.begin();
_imageProcessorUploadSuccessListener?.begin();
on<ScanAccountDirBlocEvent>(_onEvent, transformer: ((events, mapper) { on<ScanAccountDirBlocEvent>(_onEvent, transformer: ((events, mapper) {
return events.asyncExpand(mapper).distinct((a, b) { return events.asyncExpand(mapper).distinct((a, b) {
@ -164,6 +165,7 @@ class ScanAccountDirBloc
_accountPrefUpdatedEventListener.end(); _accountPrefUpdatedEventListener.end();
_nativeFileExifUpdatedListener?.end(); _nativeFileExifUpdatedListener?.end();
_imageProcessorUploadSuccessListener?.end();
_refreshThrottler.clear(); _refreshThrottler.clear();
return super.close(); return super.close();
@ -333,6 +335,14 @@ class ScanAccountDirBloc
); );
} }
void _onImageProcessorUploadSuccessEvent(
ImageProcessorUploadSuccessEvent ev) {
_refreshThrottler.trigger(
maxResponceTime: const Duration(seconds: 3),
maxPendingCount: 10,
);
}
/// Query a small amount of files to give an illusion of quick startup /// Query a small amount of files to give an illusion of quick startup
Future<List<File>> _queryOfflineMini(ScanAccountDirBlocQueryBase ev) async { Future<List<File>> _queryOfflineMini(ScanAccountDirBlocQueryBase ev) async {
return await ScanDirOfflineMini(_c)( return await ScanDirOfflineMini(_c)(
@ -540,6 +550,10 @@ class ScanAccountDirBloc
late final _nativeFileExifUpdatedListener = platform_k.isWeb late final _nativeFileExifUpdatedListener = platform_k.isWeb
? null ? null
: NativeEventListener<FileExifUpdatedEvent>(_onNativeFileExifUpdated); : NativeEventListener<FileExifUpdatedEvent>(_onNativeFileExifUpdated);
late final _imageProcessorUploadSuccessListener = platform_k.isWeb
? null
: NativeEventListener<ImageProcessorUploadSuccessEvent>(
_onImageProcessorUploadSuccessEvent);
late final _refreshThrottler = Throttler( late final _refreshThrottler = Throttler(
onTriggered: (_) { onTriggered: (_) {

View file

@ -31,6 +31,9 @@ class NativeEventListener<T> {
case FileExifUpdatedEvent._id: case FileExifUpdatedEvent._id:
return FileExifUpdatedEvent.fromEvent(ev); return FileExifUpdatedEvent.fromEvent(ev);
case ImageProcessorUploadSuccessEvent._id:
return ImageProcessorUploadSuccessEvent.fromEvent(ev);
default: default:
throw ArgumentError("Invalid event: ${ev.event}"); throw ArgumentError("Invalid event: ${ev.event}");
} }
@ -63,3 +66,15 @@ class FileExifUpdatedEvent {
final List<int> fileIds; final List<int> fileIds;
} }
class ImageProcessorUploadSuccessEvent {
const ImageProcessorUploadSuccessEvent();
factory ImageProcessorUploadSuccessEvent.fromEvent(NativeEventObject ev) {
assert(ev.event == _id);
assert(ev.data == null);
return const ImageProcessorUploadSuccessEvent();
}
static const _id = "ImageProcessorUploadSuccessEvent";
}

View file

@ -611,12 +611,12 @@ class _MyAppState extends State<MyApp>
} else if (settings.name?.startsWith("${ResultViewer.routeName}?") == } else if (settings.name?.startsWith("${ResultViewer.routeName}?") ==
true) { true) {
final queries = Uri.parse(settings.name!).queryParameters; final queries = Uri.parse(settings.name!).queryParameters;
final fileUrl = Uri.decodeQueryComponent(queries["url"]!); final args = ResultViewerArguments(queries["url"]!);
final args = ResultViewerArguments(fileUrl);
return ResultViewer.buildRoute(args); return ResultViewer.buildRoute(args);
} }
} catch (e) { } catch (e, stackTrace) {
_log.severe("[_handleResultViewerRoute] Failed while handling route", e); _log.severe("[_handleResultViewerRoute] Failed while handling route", e,
stackTrace);
} }
return null; return null;
} }

View file

@ -372,6 +372,7 @@ class ImageProcessorService : Service() {
private fun notifyResult(event: MessageEvent) { private fun notifyResult(event: MessageEvent) {
if (event is ImageProcessorCompletedEvent) { if (event is ImageProcessorCompletedEvent) {
NativeEventChannelHandler.fire(ImageProcessorUploadSuccessEvent())
notificationManager.notify( notificationManager.notify(
RESULT_NOTIFICATION_ID, buildResultNotification(event.result) RESULT_NOTIFICATION_ID, buildResultNotification(event.result)
) )

View file

@ -0,0 +1,14 @@
package com.nkming.nc_photos.plugin
interface NativeEvent {
fun getId(): String
fun getData(): String? = null
}
class ImageProcessorUploadSuccessEvent : NativeEvent {
companion object {
const val id = "ImageProcessorUploadSuccessEvent"
}
override fun getId() = id
}

View file

@ -10,6 +10,20 @@ class NativeEventChannelHandler : MethodChannel.MethodCallHandler,
const val EVENT_CHANNEL = "${K.LIB_ID}/native_event" const val EVENT_CHANNEL = "${K.LIB_ID}/native_event"
const val METHOD_CHANNEL = "${K.LIB_ID}/native_event_method" const val METHOD_CHANNEL = "${K.LIB_ID}/native_event_method"
/**
* Fire native events on the native side
*/
fun fire(eventObj: NativeEvent) {
synchronized(eventSinks) {
for (s in eventSinks.values) {
s.success(buildMap {
put("event", eventObj.getId())
eventObj.getData()?.also { put("data", it) }
})
}
}
}
private val eventSinks = mutableMapOf<Int, EventChannel.EventSink>() private val eventSinks = mutableMapOf<Int, EventChannel.EventSink>()
private var nextId = 0 private var nextId = 0
} }
@ -29,21 +43,27 @@ class NativeEventChannelHandler : MethodChannel.MethodCallHandler,
} }
override fun onListen(arguments: Any?, events: EventChannel.EventSink) { override fun onListen(arguments: Any?, events: EventChannel.EventSink) {
eventSinks[id] = events synchronized(eventSinks) {
eventSinks[id] = events
}
} }
override fun onCancel(arguments: Any?) { override fun onCancel(arguments: Any?) {
eventSinks.remove(id) synchronized(eventSinks) {
eventSinks.remove(id)
}
} }
private fun fire( private fun fire(
event: String, data: String?, result: MethodChannel.Result event: String, data: String?, result: MethodChannel.Result
) { ) {
for (s in eventSinks.values) { synchronized(eventSinks) {
s.success(buildMap { for (s in eventSinks.values) {
put("event", event) s.success(buildMap {
if (data != null) put("data", data) put("event", event)
}) if (data != null) put("data", data)
})
}
} }
result.success(null) result.success(null)
} }