feat: add general ui handler
This commit is contained in:
parent
1a3c6ce254
commit
1e03dfb1d0
@ -13,6 +13,7 @@ import 'package:flutter_hbb/desktop/screen/desktop_port_forward_screen.dart';
|
||||
import 'package:flutter_hbb/desktop/screen/desktop_remote_screen.dart';
|
||||
import 'package:flutter_hbb/desktop/widgets/refresh_wrapper.dart';
|
||||
import 'package:flutter_hbb/models/state_model.dart';
|
||||
import 'package:flutter_hbb/plugin/handlers.dart';
|
||||
import 'package:flutter_hbb/utils/multi_window_manager.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:get/get.dart';
|
||||
@ -428,4 +429,10 @@ _registerEventHandler() {
|
||||
reloadAllWindows();
|
||||
});
|
||||
}
|
||||
// Register native handlers.
|
||||
if (isDesktop) {
|
||||
platformFFI.registerEventHandler('native_ui', 'native_ui', (evt) async {
|
||||
NativeUiHandler.instance.onEvent(evt);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
43
flutter/lib/plugin/handlers.dart
Normal file
43
flutter/lib/plugin/handlers.dart
Normal file
@ -0,0 +1,43 @@
|
||||
import 'dart:ffi';
|
||||
|
||||
abstract class NativeHandler {
|
||||
bool onEvent(Map<String, dynamic> evt);
|
||||
}
|
||||
|
||||
typedef OnSelectPeersCallback = Bool Function(Int returnCode,
|
||||
Pointer<Void> data, Uint64 dataLength, Pointer<Void> userData);
|
||||
typedef OnSelectPeersCallbackDart = bool Function(
|
||||
int returnCode, Pointer<Void> data, int dataLength, Pointer<Void> userData);
|
||||
|
||||
class NativeUiHandler extends NativeHandler {
|
||||
NativeUiHandler._();
|
||||
|
||||
static NativeUiHandler instance = NativeUiHandler._();
|
||||
|
||||
@override
|
||||
bool onEvent(Map<String, dynamic> evt) {
|
||||
final name = evt['name'];
|
||||
final action = evt['action'];
|
||||
if (name != "native_ui") {
|
||||
return false;
|
||||
}
|
||||
switch (action) {
|
||||
case "select_peers":
|
||||
int cb = evt['cb'];
|
||||
int userData = evt['user_data'] ?? 0;
|
||||
final cbFuncNative = Pointer.fromAddress(cb)
|
||||
.cast<NativeFunction<OnSelectPeersCallback>>();
|
||||
final cbFuncDart = cbFuncNative.asFunction<OnSelectPeersCallbackDart>();
|
||||
onSelectPeers(cbFuncDart, userData);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void onSelectPeers(OnSelectPeersCallbackDart cb, int userData) async {
|
||||
// TODO: design a UI interface to pick peers.
|
||||
cb(0, Pointer.fromAddress(0), 0, Pointer.fromAddress(userData));
|
||||
}
|
||||
}
|
@ -10,12 +10,13 @@ use serde_json::Map;
|
||||
|
||||
use crate::return_if_not_method;
|
||||
|
||||
use self::session::PluginNativeSessionHandler;
|
||||
use self::{session::PluginNativeSessionHandler, ui::PluginNativeUIHandler};
|
||||
|
||||
use super::cstr_to_string;
|
||||
|
||||
mod macros;
|
||||
pub mod session;
|
||||
pub mod ui;
|
||||
|
||||
pub type NR = super::native::NativeReturnValue;
|
||||
pub type PluginNativeHandlerRegistrar = NativeHandlerRegistrar<Box<dyn Callable + Send + Sync>>;
|
||||
@ -33,10 +34,11 @@ pub struct NativeHandlerRegistrar<H> {
|
||||
impl Default for PluginNativeHandlerRegistrar {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
handlers: Arc::new(RwLock::new(vec![Box::new(
|
||||
handlers: Arc::new(RwLock::new(vec![
|
||||
// Add prebuilt native handlers here.
|
||||
PluginNativeSessionHandler::default(),
|
||||
)])),
|
||||
Box::new(PluginNativeSessionHandler::default()),
|
||||
Box::new(PluginNativeUIHandler::default()),
|
||||
])),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
100
src/plugin/native_handlers/ui.rs
Normal file
100
src/plugin/native_handlers/ui.rs
Normal file
@ -0,0 +1,100 @@
|
||||
use std::{collections::HashMap, ffi::c_void, os::raw::c_int};
|
||||
|
||||
use serde_json::json;
|
||||
|
||||
use crate::{
|
||||
define_method_prefix,
|
||||
flutter::{APP_TYPE_MAIN},
|
||||
};
|
||||
|
||||
use super::PluginNativeHandler;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct PluginNativeUIHandler;
|
||||
|
||||
/// Callback for UI interface.
|
||||
///
|
||||
/// [Note]
|
||||
/// We will transfer the native callback to u64 and post it to flutter.
|
||||
/// The flutter thread will directly call this method.
|
||||
///
|
||||
/// an example of `data` is:
|
||||
/// ```
|
||||
/// {
|
||||
/// "cb": 0x1234567890
|
||||
/// }
|
||||
/// ```
|
||||
/// [Safety]
|
||||
/// Please make sure the callback u provided is VALID, or memory or calling issues may occur to cause the program crash!
|
||||
pub type OnUIReturnCallback = extern "C" fn(return_code: c_int, data: *const c_void, data_len: u64, user_data: *const c_void);
|
||||
|
||||
impl PluginNativeHandler for PluginNativeUIHandler {
|
||||
define_method_prefix!("ui_");
|
||||
|
||||
fn on_message(
|
||||
&self,
|
||||
method: &str,
|
||||
data: &serde_json::Map<String, serde_json::Value>,
|
||||
) -> Option<super::NR> {
|
||||
match method {
|
||||
"select_peers_async" => {
|
||||
if let Some(cb) = data.get("cb") {
|
||||
if let Some(cb) = cb.as_u64() {
|
||||
let user_data = match data.get("user_data") {
|
||||
Some(user_data) => {
|
||||
user_data.as_u64().unwrap_or(0)
|
||||
},
|
||||
None => 0,
|
||||
};
|
||||
self.select_peers_async(cb, user_data);
|
||||
return Some(super::NR {
|
||||
return_type: 0,
|
||||
data: std::ptr::null(),
|
||||
});
|
||||
}
|
||||
}
|
||||
return Some(super::NR {
|
||||
return_type: -1,
|
||||
data: "missing cb field message".as_ptr() as _,
|
||||
});
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn on_message_raw(
|
||||
&self,
|
||||
method: &str,
|
||||
data: &serde_json::Map<String, serde_json::Value>,
|
||||
raw: *const std::ffi::c_void,
|
||||
_raw_len: usize,
|
||||
) -> Option<super::NR> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl PluginNativeUIHandler {
|
||||
/// Call with method `select_peers_async` and the following json:
|
||||
/// ```json
|
||||
/// {
|
||||
/// "cb": 0, // The function address
|
||||
/// "user_data": 0 // An opaque pointer value passed to the callback.
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [Arguments]
|
||||
/// @param cb: the function address with type [OnUIReturnCallback].
|
||||
/// @param user_data: the function will be called with this value.
|
||||
fn select_peers_async(&self, cb: u64, user_data: u64) {
|
||||
let mut param = HashMap::new();
|
||||
param.insert("name", json!("native_ui"));
|
||||
param.insert("action", json!("select_peers"));
|
||||
param.insert("cb", json!(cb));
|
||||
param.insert("user_data", json!(user_data));
|
||||
crate::flutter::push_global_event(
|
||||
APP_TYPE_MAIN,
|
||||
serde_json::to_string(¶m).unwrap_or("".to_string()),
|
||||
);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user