Fix native image processor messages not reporting to flutter

This commit is contained in:
Ming Ming 2023-09-01 19:14:47 +08:00
parent 68007d5d3e
commit 8841673b88
18 changed files with 183 additions and 82 deletions

View file

@ -17,12 +17,14 @@ import 'package:nc_photos/event/event.dart';
import 'package:nc_photos/event/native_event.dart';
import 'package:nc_photos/exception.dart';
import 'package:nc_photos/progress_util.dart';
import 'package:nc_photos/stream_extension.dart';
import 'package:nc_photos/throttler.dart';
import 'package:nc_photos/use_case/ls.dart';
import 'package:nc_photos/use_case/scan_dir.dart';
import 'package:nc_photos/use_case/scan_dir_offline.dart';
import 'package:nc_photos/use_case/sync_dir.dart';
import 'package:np_codegen/np_codegen.dart';
import 'package:np_platform_image_processor/np_platform_image_processor.dart';
import 'package:np_platform_util/np_platform_util.dart';
import 'package:to_string/to_string.dart';
@ -132,7 +134,8 @@ class ScanAccountDirBloc
_accountPrefUpdatedEventListener.begin();
_nativeFileExifUpdatedListener?.begin();
_imageProcessorUploadSuccessListener?.begin();
_imageProcessorUploadSuccessListener = _imageProcessorUploadSuccessStream
?.listen(_onImageProcessorUploadSuccessEvent);
on<ScanAccountDirBlocEvent>(_onEvent, transformer: ((events, mapper) {
return events.distinct((a, b) {
@ -166,7 +169,7 @@ class ScanAccountDirBloc
}
@override
close() {
Future<void> close() {
_fileRemovedEventListener.end();
_filePropertyUpdatedEventListener.end();
_fileTrashbinRestoredEventListener.end();
@ -176,7 +179,8 @@ class ScanAccountDirBloc
_accountPrefUpdatedEventListener.end();
_nativeFileExifUpdatedListener?.end();
_imageProcessorUploadSuccessListener?.end();
_imageProcessorUploadSuccessListener?.cancel();
_imageProcessorUploadSuccessListener = null;
_refreshThrottler.clear();
return super.close();
@ -526,11 +530,13 @@ class ScanAccountDirBloc
late final _nativeFileExifUpdatedListener = getRawPlatform() == NpPlatform.web
? null
: NativeEventListener<FileExifUpdatedEvent>(_onNativeFileExifUpdated);
late final _imageProcessorUploadSuccessListener =
getRawPlatform() == NpPlatform.web
Stream<ImageProcessorUploadSuccessEvent>?
get _imageProcessorUploadSuccessStream => getRawPlatform() ==
NpPlatform.web
? null
: NativeEventListener<ImageProcessorUploadSuccessEvent>(
_onImageProcessorUploadSuccessEvent);
: ImageProcessor.stream.whereType<ImageProcessorUploadSuccessEvent>();
StreamSubscription? _imageProcessorUploadSuccessListener;
late final _refreshThrottler = Throttler(
onTriggered: (_) {

View file

@ -31,9 +31,6 @@ class NativeEventListener<T> {
case FileExifUpdatedEvent._id:
return FileExifUpdatedEvent.fromEvent(ev);
case ImageProcessorUploadSuccessEvent._id:
return ImageProcessorUploadSuccessEvent.fromEvent(ev);
default:
throw ArgumentError("Invalid event: ${ev.event}");
}
@ -66,15 +63,3 @@ class FileExifUpdatedEvent {
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

@ -22,7 +22,6 @@ import 'package:nc_photos/entity/file_descriptor.dart';
import 'package:nc_photos/entity/pref.dart';
import 'package:nc_photos/entity/sqlite/database.dart' as sql;
import 'package:nc_photos/event/event.dart';
import 'package:nc_photos/event/native_event.dart';
import 'package:nc_photos/exception_util.dart' as exception_util;
import 'package:nc_photos/k.dart' as k;
import 'package:nc_photos/language_util.dart' as language_util;
@ -31,6 +30,7 @@ import 'package:nc_photos/object_extension.dart';
import 'package:nc_photos/service.dart' as service;
import 'package:nc_photos/share_handler.dart';
import 'package:nc_photos/snack_bar_manager.dart';
import 'package:nc_photos/stream_extension.dart';
import 'package:nc_photos/theme.dart';
import 'package:nc_photos/theme/dimension.dart';
import 'package:nc_photos/throttler.dart';
@ -52,6 +52,7 @@ import 'package:nc_photos/widget/viewer.dart';
import 'package:nc_photos/widget/zoom_menu_button.dart';
import 'package:np_async/np_async.dart';
import 'package:np_codegen/np_codegen.dart';
import 'package:np_platform_image_processor/np_platform_image_processor.dart';
import 'package:np_platform_util/np_platform_util.dart';
import 'package:visibility_detector/visibility_detector.dart';
@ -87,7 +88,8 @@ class _HomePhotosState extends State<HomePhotos>
_initBloc();
_web?.onInitState();
_prefUpdatedListener.begin();
_imageProcessorUploadSuccessListener?.begin();
_imageProcessorUploadSuccessListener = _imageProcessorUploadSuccessStream
?.listen(_onImageProcessorUploadSuccessEvent);
_onBackToTopListener.begin();
}
@ -95,7 +97,8 @@ class _HomePhotosState extends State<HomePhotos>
dispose() {
_onBackToTopListener.end();
_prefUpdatedListener.end();
_imageProcessorUploadSuccessListener?.end();
_imageProcessorUploadSuccessListener?.cancel();
_imageProcessorUploadSuccessListener = null;
_web?.onDispose();
super.dispose();
}
@ -726,14 +729,16 @@ class _HomePhotosState extends State<HomePhotos>
late final _prefUpdatedListener =
AppEventListener<PrefUpdatedEvent>(_onPrefUpdated);
late final _imageProcessorUploadSuccessListener =
getRawPlatform() == NpPlatform.web
? null
: NativeEventListener<ImageProcessorUploadSuccessEvent>(
_onImageProcessorUploadSuccessEvent);
late final _onBackToTopListener =
AppEventListener<HomePhotosBackToTopEvent>(_onBackToTop);
Stream<ImageProcessorUploadSuccessEvent>?
get _imageProcessorUploadSuccessStream => getRawPlatform() ==
NpPlatform.web
? null
: ImageProcessor.stream.whereType<ImageProcessorUploadSuccessEvent>();
StreamSubscription? _imageProcessorUploadSuccessListener;
late final _Web? _web =
getRawPlatform() == NpPlatform.web ? _Web(this) : null;

View file

@ -1,13 +1,13 @@
package com.nkming.nc_photos.np_platform_image_processor
import android.net.Uri
internal interface ImageProcessorEvent {
fun getId(): String
}
internal interface MessageEvent
internal class ImageProcessorUploadSuccessEvent : ImageProcessorEvent {
companion object {
const val id = "ImageProcessorUploadSuccessEvent"
}
internal data class ImageProcessorCompletedEvent(
val result: Uri,
) : MessageEvent
internal data class ImageProcessorFailedEvent(
val exception: Throwable,
) : MessageEvent
override fun getId() = id
}

View file

@ -23,8 +23,22 @@ import java.io.Serializable
internal class ImageProcessorChannelHandler(context: Context) :
MethodChannel.MethodCallHandler, EventChannel.StreamHandler {
companion object {
const val EVENT_CHANNEL = "${K.LIB_ID}/image_processor_event"
const val METHOD_CHANNEL = "${K.LIB_ID}/image_processor_method"
fun fire(ev: ImageProcessorEvent) {
synchronized(eventSinks) {
for (s in eventSinks.values) {
s.success(buildMap {
put("event", ev.getId())
})
}
}
}
private val eventSinks = mutableMapOf<Int, EventChannel.EventSink>()
private var nextId = 0
private const val TAG = "ImageProcessorChannelHandler"
}
@ -158,11 +172,15 @@ internal class ImageProcessorChannelHandler(context: Context) :
}
override fun onListen(arguments: Any?, events: EventChannel.EventSink) {
eventSink = events
synchronized(eventSinks) {
eventSinks[id] = events
}
}
override fun onCancel(arguments: Any?) {
eventSink = null
synchronized(eventSinks) {
eventSinks.remove(id)
}
}
private fun zeroDce(
@ -271,7 +289,7 @@ internal class ImageProcessorChannelHandler(context: Context) :
}
private val context = context
private var eventSink: EventChannel.EventSink? = null
private val id = nextId++
}
internal interface ImageFilter {

View file

@ -399,9 +399,9 @@ internal class ImageProcessorService : Service() {
private fun notifyResult(event: MessageEvent, shouldFireEvent: Boolean) {
if (event is ImageProcessorCompletedEvent) {
if (shouldFireEvent) {
// NativeEventChannelHandler.fire(
// ImageProcessorUploadSuccessEvent()
// )
ImageProcessorChannelHandler.fire(
ImageProcessorUploadSuccessEvent()
)
}
notificationManager.notify(
RESULT_NOTIFICATION_ID, buildResultNotification(event.result)

View file

@ -0,0 +1,13 @@
package com.nkming.nc_photos.np_platform_image_processor
import android.net.Uri
internal interface MessageEvent
internal data class ImageProcessorCompletedEvent(
val result: Uri,
) : MessageEvent
internal data class ImageProcessorFailedEvent(
val exception: Throwable,
) : MessageEvent

View file

@ -1,15 +0,0 @@
package com.nkming.nc_photos.np_platform_image_processor
// To be removed
internal interface NativeEvent {
fun getId(): String
fun getData(): String? = null
}
internal class ImageProcessorUploadSuccessEvent : NativeEvent {
companion object {
const val id = "ImageProcessorUploadSuccessEvent"
}
override fun getId() = id
}

View file

@ -19,38 +19,28 @@ class NpPlatformImageProcessorPlugin : FlutterPlugin {
override fun onAttachedToEngine(
@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding
) {
val imageProcessorHandler = ImageProcessorChannelHandler(
flutterPluginBinding.applicationContext
)
imageProcessorEventChannel = EventChannel(
flutterPluginBinding.binaryMessenger,
ImageProcessorChannelHandler.EVENT_CHANNEL
)
imageProcessorEventChannel.setStreamHandler(imageProcessorHandler)
imageProcessorMethodChannel = MethodChannel(
flutterPluginBinding.binaryMessenger,
ImageProcessorChannelHandler.METHOD_CHANNEL
)
imageProcessorMethodChannel.setMethodCallHandler(
ImageProcessorChannelHandler(
flutterPluginBinding.applicationContext
)
)
val nativeEventHandler = NativeEventChannelHandler()
nativeEventChannel = EventChannel(
flutterPluginBinding.binaryMessenger,
NativeEventChannelHandler.EVENT_CHANNEL
)
nativeEventChannel.setStreamHandler(nativeEventHandler)
nativeEventMethodChannel = MethodChannel(
flutterPluginBinding.binaryMessenger,
NativeEventChannelHandler.METHOD_CHANNEL
)
nativeEventMethodChannel.setMethodCallHandler(nativeEventHandler)
imageProcessorMethodChannel.setMethodCallHandler(imageProcessorHandler)
}
override fun onDetachedFromEngine(
@NonNull binding: FlutterPlugin.FlutterPluginBinding
) {
imageProcessorEventChannel.setStreamHandler(null)
imageProcessorMethodChannel.setMethodCallHandler(null)
nativeEventChannel.setStreamHandler(null)
nativeEventMethodChannel.setMethodCallHandler(null)
}
private lateinit var imageProcessorMethodChannel: MethodChannel
private lateinit var nativeEventChannel: EventChannel
private lateinit var nativeEventMethodChannel: MethodChannel
private lateinit var imageProcessorEventChannel: EventChannel
}

View file

@ -1,3 +1,4 @@
library np_platform_image_processor;
export 'src/event.dart';
export 'src/image_processor.dart';

View file

@ -0,0 +1,22 @@
abstract class ImageProcessorEvent {
static ImageProcessorEvent fromNativeEvent(dynamic ev) {
final id = ev["event"];
switch (id) {
case ImageProcessorUploadSuccessEvent._id:
return ImageProcessorUploadSuccessEvent.fromNativeEvent(ev);
default:
throw UnsupportedError("Unknown event: $id");
}
}
}
class ImageProcessorUploadSuccessEvent implements ImageProcessorEvent {
const ImageProcessorUploadSuccessEvent._();
factory ImageProcessorUploadSuccessEvent.fromNativeEvent(dynamic ev) {
assert(ev.event == _id);
return const ImageProcessorUploadSuccessEvent._();
}
static const _id = "ImageProcessorUploadSuccessEvent";
}

View file

@ -0,0 +1,30 @@
import 'package:flutter/services.dart';
import 'package:logging/logging.dart';
import 'package:np_codegen/np_codegen.dart';
import 'package:np_platform_image_processor/src/event.dart';
import 'package:np_platform_image_processor/src/k.dart' as k;
part 'event_handler.g.dart';
@npLog
class EventHandler {
static Stream<ImageProcessorEvent> get stream =>
_eventChannel.receiveBroadcastStream().map(_toEvent).whereNotNull();
static ImageProcessorEvent? _toEvent(dynamic ev) {
try {
return ImageProcessorEvent.fromNativeEvent(ev);
} catch (e, stackTrace) {
_log.severe("Failed while parsing native events", e, stackTrace);
return null;
}
}
static const _eventChannel = EventChannel("${k.libId}/image_processor_event");
static final _log = _$EventHandlerNpLog.log;
}
extension<T> on Stream<T?> {
Stream<T> whereNotNull() => where((e) => e != null).cast<T>();
}

View file

@ -0,0 +1,14 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'event_handler.dart';
// **************************************************************************
// NpLogGenerator
// **************************************************************************
extension _$EventHandlerNpLog on EventHandler {
// ignore: unused_element
Logger get _log => log;
static final log = Logger("src.event_handler.EventHandler");
}

View file

@ -1,6 +1,8 @@
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:np_platform_image_processor/src/event.dart';
import 'package:np_platform_image_processor/src/event_handler.dart';
import 'package:np_platform_image_processor/src/k.dart' as k;
import 'package:np_platform_raw_image/np_platform_raw_image.dart';
@ -75,6 +77,8 @@ class TransformOrientationFilter implements ImageFilter {
}
class ImageProcessor {
static Stream<ImageProcessorEvent> get stream => EventHandler.stream;
static Future<void> zeroDce(
String fileUrl,
String filename,

View file

@ -11,11 +11,17 @@ environment:
dependencies:
flutter:
sdk: flutter
collection: ^1.15.0
logging: ^1.1.1
np_codegen:
path: ../codegen
np_platform_raw_image:
path: ../np_platform_raw_image
dev_dependencies:
build_runner: ^2.2.1
np_codegen_build:
path: ../codegen_build
np_lints:
path: ../np_lints

View file

@ -0,0 +1,6 @@
package com.nkming.nc_photos.plugin
internal interface NativeEvent {
fun getId(): String
fun getData(): String? = null
}

View file

@ -1,4 +1,4 @@
package com.nkming.nc_photos.np_platform_image_processor
package com.nkming.nc_photos.plugin
import io.flutter.plugin.common.EventChannel
import io.flutter.plugin.common.MethodCall

View file

@ -60,6 +60,18 @@ class NcPhotosPlugin : FlutterPlugin, ActivityAware,
PreferenceChannelHandler.METHOD_CHANNEL
)
preferenceMethodChannel.setMethodCallHandler(preferenceChannelHandler)
val nativeEventHandler = NativeEventChannelHandler()
nativeEventChannel = EventChannel(
flutterPluginBinding.binaryMessenger,
NativeEventChannelHandler.EVENT_CHANNEL
)
nativeEventChannel.setStreamHandler(nativeEventHandler)
nativeEventMethodChannel = MethodChannel(
flutterPluginBinding.binaryMessenger,
NativeEventChannelHandler.METHOD_CHANNEL
)
nativeEventMethodChannel.setMethodCallHandler(nativeEventHandler)
}
override fun onDetachedFromEngine(
@ -70,6 +82,8 @@ class NcPhotosPlugin : FlutterPlugin, ActivityAware,
mediaStoreMethodChannel.setMethodCallHandler(null)
contentUriMethodChannel.setMethodCallHandler(null)
preferenceMethodChannel.setMethodCallHandler(null)
nativeEventChannel.setStreamHandler(null)
nativeEventMethodChannel.setMethodCallHandler(null)
}
override fun onAttachedToActivity(binding: ActivityPluginBinding) {
@ -122,6 +136,8 @@ class NcPhotosPlugin : FlutterPlugin, ActivityAware,
private lateinit var mediaStoreMethodChannel: MethodChannel
private lateinit var contentUriMethodChannel: MethodChannel
private lateinit var preferenceMethodChannel: MethodChannel
private lateinit var nativeEventChannel: EventChannel
private lateinit var nativeEventMethodChannel: MethodChannel
private lateinit var mediaStoreChannelHandler: MediaStoreChannelHandler
}