add events to ui
Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
parent
94d7339457
commit
4200734593
@ -16,6 +16,8 @@ import 'package:flutter_hbb/models/peer_tab_model.dart';
|
|||||||
import 'package:flutter_hbb/models/server_model.dart';
|
import 'package:flutter_hbb/models/server_model.dart';
|
||||||
import 'package:flutter_hbb/models/user_model.dart';
|
import 'package:flutter_hbb/models/user_model.dart';
|
||||||
import 'package:flutter_hbb/models/state_model.dart';
|
import 'package:flutter_hbb/models/state_model.dart';
|
||||||
|
import 'package:flutter_hbb/plugin/event.dart';
|
||||||
|
import 'package:flutter_hbb/plugin/reloader.dart';
|
||||||
import 'package:flutter_hbb/common/shared_state.dart';
|
import 'package:flutter_hbb/common/shared_state.dart';
|
||||||
import 'package:tuple/tuple.dart';
|
import 'package:tuple/tuple.dart';
|
||||||
import 'package:image/image.dart' as img2;
|
import 'package:image/image.dart' as img2;
|
||||||
@ -226,6 +228,13 @@ class FfiModel with ChangeNotifier {
|
|||||||
parent.target?.serverModel.updateVoiceCallState(evt);
|
parent.target?.serverModel.updateVoiceCallState(evt);
|
||||||
} else if (name == "fingerprint") {
|
} else if (name == "fingerprint") {
|
||||||
FingerprintState.find(peerId).value = evt['fingerprint'] ?? '';
|
FingerprintState.find(peerId).value = evt['fingerprint'] ?? '';
|
||||||
|
} else if (name == "plugin_desc") {
|
||||||
|
handleReloading(evt, peerId);
|
||||||
|
} else if (name == "plugin_event") {
|
||||||
|
handlePluginEvent(
|
||||||
|
evt, peerId, (Map<String, dynamic> e) => handleMsgBox(e, peerId));
|
||||||
|
} else if (name == "plugin_reload") {
|
||||||
|
handleReloading(evt, peerId);
|
||||||
} else {
|
} else {
|
||||||
debugPrint("Unknown event name: $name");
|
debugPrint("Unknown event name: $name");
|
||||||
}
|
}
|
||||||
|
135
flutter/lib/plugin/desc.dart
Normal file
135
flutter/lib/plugin/desc.dart
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
import 'dart:collection';
|
||||||
|
|
||||||
|
class UiButton {
|
||||||
|
String key;
|
||||||
|
String text;
|
||||||
|
String icon;
|
||||||
|
String tooltip;
|
||||||
|
String action;
|
||||||
|
|
||||||
|
UiButton(this.key, this.text, this.icon, this.tooltip, this.action);
|
||||||
|
UiButton.fromJson(Map<String, dynamic> json)
|
||||||
|
: key = json['key'] ?? '',
|
||||||
|
text = json['text'] ?? '',
|
||||||
|
icon = json['icon'] ?? '',
|
||||||
|
tooltip = json['tooltip'] ?? '',
|
||||||
|
action = json['action'] ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
class UiCheckbox {
|
||||||
|
String key;
|
||||||
|
String text;
|
||||||
|
String tooltip;
|
||||||
|
String action;
|
||||||
|
|
||||||
|
UiCheckbox(this.key, this.text, this.tooltip, this.action);
|
||||||
|
UiCheckbox.fromJson(Map<String, dynamic> json)
|
||||||
|
: key = json['key'] ?? '',
|
||||||
|
text = json['text'] ?? '',
|
||||||
|
tooltip = json['tooltip'] ?? '',
|
||||||
|
action = json['action'] ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
class UiType {
|
||||||
|
UiButton? button;
|
||||||
|
UiCheckbox? checkbox;
|
||||||
|
|
||||||
|
UiType.fromJson(Map<String, dynamic> json)
|
||||||
|
: button = json['t'] == 'Button' ? UiButton.fromJson(json['c']) : null,
|
||||||
|
checkbox =
|
||||||
|
json['t'] != 'Checkbox' ? UiCheckbox.fromJson(json['c']) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Location {
|
||||||
|
HashMap<String, UiType> ui;
|
||||||
|
|
||||||
|
Location(this.ui);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConfigItem {
|
||||||
|
String key;
|
||||||
|
String value;
|
||||||
|
String description;
|
||||||
|
String defaultValue;
|
||||||
|
|
||||||
|
ConfigItem(this.key, this.value, this.defaultValue, this.description);
|
||||||
|
ConfigItem.fromJson(Map<String, dynamic> json)
|
||||||
|
: key = json['key'] ?? '',
|
||||||
|
value = json['value'] ?? '',
|
||||||
|
description = json['description'] ?? '',
|
||||||
|
defaultValue = json['default'] ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
class Config {
|
||||||
|
List<ConfigItem> local;
|
||||||
|
List<ConfigItem> peer;
|
||||||
|
|
||||||
|
Config(this.local, this.peer);
|
||||||
|
Config.fromJson(Map<String, dynamic> json)
|
||||||
|
: local = (json['local'] as List<dynamic>)
|
||||||
|
.map((e) => ConfigItem.fromJson(e))
|
||||||
|
.toList(),
|
||||||
|
peer = (json['peer'] as List<dynamic>)
|
||||||
|
.map((e) => ConfigItem.fromJson(e))
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
class Desc {
|
||||||
|
String id;
|
||||||
|
String name;
|
||||||
|
String version;
|
||||||
|
String description;
|
||||||
|
String author;
|
||||||
|
String home;
|
||||||
|
String license;
|
||||||
|
String published;
|
||||||
|
String released;
|
||||||
|
String github;
|
||||||
|
Location location;
|
||||||
|
Config config;
|
||||||
|
|
||||||
|
Desc(
|
||||||
|
this.id,
|
||||||
|
this.name,
|
||||||
|
this.version,
|
||||||
|
this.description,
|
||||||
|
this.author,
|
||||||
|
this.home,
|
||||||
|
this.license,
|
||||||
|
this.published,
|
||||||
|
this.released,
|
||||||
|
this.github,
|
||||||
|
this.location,
|
||||||
|
this.config);
|
||||||
|
|
||||||
|
Desc.fromJson(Map<String, dynamic> json)
|
||||||
|
: id = json['id'] ?? '',
|
||||||
|
name = json['name'] ?? '',
|
||||||
|
version = json['version'] ?? '',
|
||||||
|
description = json['description'] ?? '',
|
||||||
|
author = json['author'] ?? '',
|
||||||
|
home = json['home'] ?? '',
|
||||||
|
license = json['license'] ?? '',
|
||||||
|
published = json['published'] ?? '',
|
||||||
|
released = json['released'] ?? '',
|
||||||
|
github = json['github'] ?? '',
|
||||||
|
location = Location(HashMap<String, UiType>.from(json['location'])),
|
||||||
|
config = Config(
|
||||||
|
(json['config'] as List<dynamic>)
|
||||||
|
.map((e) => ConfigItem.fromJson(e))
|
||||||
|
.toList(),
|
||||||
|
(json['config'] as List<dynamic>)
|
||||||
|
.map((e) => ConfigItem.fromJson(e))
|
||||||
|
.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
final mapPluginDesc = <String, Desc>{};
|
||||||
|
|
||||||
|
void updateDesc(Map<String, dynamic> desc) {
|
||||||
|
Desc d = Desc.fromJson(desc);
|
||||||
|
mapPluginDesc[d.id] = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
Desc? getDesc(String id) {
|
||||||
|
return mapPluginDesc[id];
|
||||||
|
}
|
60
flutter/lib/plugin/event.dart
Normal file
60
flutter/lib/plugin/event.dart
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
void handlePluginEvent(
|
||||||
|
Map<String, dynamic> evt,
|
||||||
|
String peer,
|
||||||
|
Function(Map<String, dynamic> e) handleMsgBox,
|
||||||
|
) {
|
||||||
|
// content
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// "t": "Option",
|
||||||
|
// "c": {
|
||||||
|
// "id": "id from RustDesk platform",
|
||||||
|
// "name": "Privacy Mode",
|
||||||
|
// "version": "v0.1.0",
|
||||||
|
// "location": "client|remote|toolbar|display",
|
||||||
|
// "key": "privacy-mode",
|
||||||
|
// "value": "1"
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// "t": "MsgBox",
|
||||||
|
// "c": {
|
||||||
|
// "type": "custom-nocancel",
|
||||||
|
// "title": "Privacy Mode",
|
||||||
|
// "text": "Failed unknown",
|
||||||
|
// "link": ""
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
if (evt['content']?['c'] == null) return;
|
||||||
|
final t = evt['content']?['t'];
|
||||||
|
if (t == 'Option') {
|
||||||
|
handleOptionEvent(evt['content']?['c'], peer);
|
||||||
|
} else if (t == 'MsgBox') {
|
||||||
|
handleMsgBox(evt['content']?['c']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleOptionEvent(Map<String, dynamic> evt, String peer) {
|
||||||
|
// content
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// "id": "id from RustDesk platform",
|
||||||
|
// "name": "Privacy Mode",
|
||||||
|
// "version": "v0.1.0",
|
||||||
|
// "location": "client|remote|toolbar|display",
|
||||||
|
// "key": "privacy-mode",
|
||||||
|
// "value": "1"
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
final key = evt['key'];
|
||||||
|
final value = evt['value'];
|
||||||
|
if (key == 'privacy-mode') {
|
||||||
|
if (value == '1') {
|
||||||
|
// enable privacy mode
|
||||||
|
} else {
|
||||||
|
// disable privacy mode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
29
flutter/lib/plugin/reloader.dart
Normal file
29
flutter/lib/plugin/reloader.dart
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
void handleReloading(Map<String, dynamic> evt, String peer) {
|
||||||
|
// location
|
||||||
|
// host|main|settings|display|others
|
||||||
|
// client|remote|toolbar|display
|
||||||
|
//
|
||||||
|
// ui
|
||||||
|
// {
|
||||||
|
// "t": "Button",
|
||||||
|
// "c": {
|
||||||
|
// "key": "key",
|
||||||
|
// "text": "text",
|
||||||
|
// "icon": "icon",
|
||||||
|
// "tooltip": "tooltip",
|
||||||
|
// "action": "action"
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// "t": "Checkbox",
|
||||||
|
// "c": {
|
||||||
|
// "key": "key",
|
||||||
|
// "text": "text",
|
||||||
|
// "tooltip": "tooltip",
|
||||||
|
// "action": "action"
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
|
||||||
|
}
|
17
flutter/lib/plugin/widget.dart
Normal file
17
flutter/lib/plugin/widget.dart
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
final Map<String, PluginWidget> pluginWidgets = {};
|
||||||
|
|
||||||
|
class PluginWidget {
|
||||||
|
final String id;
|
||||||
|
final String name;
|
||||||
|
final String location;
|
||||||
|
final Widget widget;
|
||||||
|
|
||||||
|
PluginWidget({
|
||||||
|
required this.id,
|
||||||
|
required this.name,
|
||||||
|
required this.location,
|
||||||
|
required this.widget,
|
||||||
|
});
|
||||||
|
}
|
@ -99,7 +99,7 @@ pub fn callback_msg(
|
|||||||
{
|
{
|
||||||
let _res = flutter::push_session_event(
|
let _res = flutter::push_session_event(
|
||||||
&peer,
|
&peer,
|
||||||
"plugin",
|
"plugin_event",
|
||||||
vec![("peer", &peer), ("content", &content)],
|
vec![("peer", &peer), ("content", &content)],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -28,12 +28,12 @@ pub enum UiType {
|
|||||||
Checkbox(UiCheckbox),
|
Checkbox(UiCheckbox),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct Location {
|
pub struct Location {
|
||||||
pub ui: HashMap<String, UiType>,
|
pub ui: HashMap<String, UiType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct ConfigItem {
|
pub struct ConfigItem {
|
||||||
pub key: String,
|
pub key: String,
|
||||||
pub value: String,
|
pub value: String,
|
||||||
@ -41,13 +41,13 @@ pub struct ConfigItem {
|
|||||||
pub description: String,
|
pub description: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub local: Vec<ConfigItem>,
|
pub local: Vec<ConfigItem>,
|
||||||
pub peer: Vec<ConfigItem>,
|
pub peer: Vec<ConfigItem>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct Desc {
|
pub struct Desc {
|
||||||
id: String,
|
id: String,
|
||||||
name: String,
|
name: String,
|
||||||
|
@ -165,7 +165,9 @@ pub fn load_plugin(path: &str) -> ResultType<()> {
|
|||||||
let desc = desc_res?;
|
let desc = desc_res?;
|
||||||
let id = desc.id().to_string();
|
let id = desc.id().to_string();
|
||||||
// to-do validate plugin
|
// to-do validate plugin
|
||||||
|
// to-do check the plugin id (make sure it does not use another plugin's id)
|
||||||
(plugin.fn_set_cb_msg)(callback_msg::callback_msg);
|
(plugin.fn_set_cb_msg)(callback_msg::callback_msg);
|
||||||
|
update_ui_plugin_desc(&desc);
|
||||||
update_config(&desc);
|
update_config(&desc);
|
||||||
reload_ui(&desc);
|
reload_ui(&desc);
|
||||||
plugin.desc = Some(desc);
|
plugin.desc = Some(desc);
|
||||||
@ -287,6 +289,8 @@ fn reload_ui(desc: &Desc) {
|
|||||||
if let Ok(ui) = serde_json::to_string(&ui) {
|
if let Ok(ui) = serde_json::to_string(&ui) {
|
||||||
let mut m = HashMap::new();
|
let mut m = HashMap::new();
|
||||||
m.insert("name", "plugin_reload");
|
m.insert("name", "plugin_reload");
|
||||||
|
m.insert("id", desc.id());
|
||||||
|
m.insert("location", &location);
|
||||||
m.insert("ui", &ui);
|
m.insert("ui", &ui);
|
||||||
flutter::push_global_event(v[1], serde_json::to_string(&m).unwrap());
|
flutter::push_global_event(v[1], serde_json::to_string(&m).unwrap());
|
||||||
}
|
}
|
||||||
@ -294,3 +298,18 @@ fn reload_ui(desc: &Desc) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn update_ui_plugin_desc(desc: &Desc) {
|
||||||
|
// This function is rarely used. There's no need to care about serialization efficiency here.
|
||||||
|
if let Ok(desc_str) = serde_json::to_string(desc) {
|
||||||
|
let mut m = HashMap::new();
|
||||||
|
m.insert("name", "plugin_desc");
|
||||||
|
m.insert("desc", &desc_str);
|
||||||
|
flutter::push_global_event(flutter::APP_TYPE_MAIN, serde_json::to_string(&m).unwrap());
|
||||||
|
flutter::push_global_event(
|
||||||
|
flutter::APP_TYPE_DESKTOP_REMOTE,
|
||||||
|
serde_json::to_string(&m).unwrap(),
|
||||||
|
);
|
||||||
|
flutter::push_global_event(flutter::APP_TYPE_CM, serde_json::to_string(&m).unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user