diff --git a/flutter/lib/desktop/pages/desktop_home_page.dart b/flutter/lib/desktop/pages/desktop_home_page.dart index f949f538..9c1b5827 100644 --- a/flutter/lib/desktop/pages/desktop_home_page.dart +++ b/flutter/lib/desktop/pages/desktop_home_page.dart @@ -14,6 +14,7 @@ import 'package:flutter_hbb/desktop/pages/desktop_tab_page.dart'; import 'package:flutter_hbb/desktop/widgets/scroll_wrapper.dart'; import 'package:flutter_hbb/models/platform_model.dart'; import 'package:flutter_hbb/models/server_model.dart'; +import 'package:flutter_hbb/plugin/ui_manager.dart'; import 'package:flutter_hbb/utils/multi_window_manager.dart'; import 'package:get/get.dart'; import 'package:provider/provider.dart'; @@ -88,6 +89,7 @@ class _DesktopHomePageState extends State } }, ), + buildPluginEntry() ], ), ), @@ -572,6 +574,22 @@ class _DesktopHomePageState extends State _updateTimer?.cancel(); super.dispose(); } + + Widget buildPluginEntry() { + final entries = PluginUiManager.instance.entries.entries; + return Offstage( + offstage: entries.isEmpty, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ... + entries.map((entry) { + return entry.value; + }) + ], + ), + ); + } } void setPasswordDialog() async { diff --git a/flutter/lib/plugin/handlers.dart b/flutter/lib/plugin/handlers.dart index 780fd7e9..c85f4dfc 100644 --- a/flutter/lib/plugin/handlers.dart +++ b/flutter/lib/plugin/handlers.dart @@ -2,6 +2,8 @@ import 'dart:convert'; import 'dart:ffi'; import 'package:ffi/ffi.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_hbb/plugin/ui_manager.dart'; import 'package:flutter_hbb/plugin/utils/dialogs.dart'; abstract class NativeHandler { @@ -34,6 +36,15 @@ class NativeUiHandler extends NativeHandler { final cbFuncDart = cbFuncNative.asFunction(); onSelectPeers(cbFuncDart, userData); break; + case "register_ui_entry": + int cb = evt['on_tap_cb']; + int userData = evt['user_data'] ?? 0; + String title = evt['title'] ?? ""; + final cbFuncNative = Pointer.fromAddress(cb) + .cast>(); + final cbFuncDart = cbFuncNative.asFunction(); + onRegisterUiEntry(title, cbFuncDart, userData); + break; default: return false; } @@ -50,4 +61,19 @@ class NativeUiHandler extends NativeHandler { malloc.free(native); }); } + + void onRegisterUiEntry(String title, OnSelectPeersCallbackDart cbFuncDart, int userData) { + Widget widget = InkWell( + child: Container( + height: 25.0, + child: Row( + children: [ + Expanded(child: Text(title)), + Icon(Icons.chevron_right_rounded, size: 12.0,) + ], + ), + ), + ); + PluginUiManager.instance.registerEntry(title, widget); + } } diff --git a/flutter/lib/plugin/ui_manager.dart b/flutter/lib/plugin/ui_manager.dart new file mode 100644 index 00000000..45accf65 --- /dev/null +++ b/flutter/lib/plugin/ui_manager.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; + +class PluginUiManager { + PluginUiManager._(); + + static PluginUiManager instance = PluginUiManager._(); + + Map entries = {}; + + void registerEntry(String key, Widget widget) { + entries[key] = widget; + } + + void unregisterEntry(String key) { + entries.remove(key); + } +} \ No newline at end of file diff --git a/src/lang/ca.rs b/src/lang/ca.rs index 554ca09c..252d5fbd 100644 --- a/src/lang/ca.rs +++ b/src/lang/ca.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", ""), ("no fingerprints", ""), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/cn.rs b/src/lang/cn.rs index a80b1da9..76cbd2f2 100644 --- a/src/lang/cn.rs +++ b/src/lang/cn.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", "复制指纹"), ("no fingerprints", "没有指纹"), ("Select a peer", "选择一个被控端"), - ("Select peers", "选择被控端") + ("Select peers", "选择被控"), + ("Plugins", "插件") ].iter().cloned().collect(); } diff --git a/src/lang/cs.rs b/src/lang/cs.rs index e0705a16..e70c7d9e 100644 --- a/src/lang/cs.rs +++ b/src/lang/cs.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", ""), ("no fingerprints", ""), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/da.rs b/src/lang/da.rs index 8b6832a0..fc27774f 100644 --- a/src/lang/da.rs +++ b/src/lang/da.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", ""), ("no fingerprints", ""), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/de.rs b/src/lang/de.rs index f1a39ea2..8b31d90c 100644 --- a/src/lang/de.rs +++ b/src/lang/de.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", "Fingerabdruck kopieren"), ("no fingerprints", "Keine Fingerabdrücke"), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/el.rs b/src/lang/el.rs index bb7a86ed..458a8c55 100644 --- a/src/lang/el.rs +++ b/src/lang/el.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", ""), ("no fingerprints", ""), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/eo.rs b/src/lang/eo.rs index 547bf981..cd26b5ab 100644 --- a/src/lang/eo.rs +++ b/src/lang/eo.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", ""), ("no fingerprints", ""), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/es.rs b/src/lang/es.rs index b63f592a..d593e683 100644 --- a/src/lang/es.rs +++ b/src/lang/es.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", "Copiar huella digital"), ("no fingerprints", "sin huellas digitales"), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/fa.rs b/src/lang/fa.rs index 4e4a768d..e1183ce2 100644 --- a/src/lang/fa.rs +++ b/src/lang/fa.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", "کپی کردن اثر انگشت"), ("no fingerprints", "بدون اثر انگشت"), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/fr.rs b/src/lang/fr.rs index 3ff01188..6d9ff940 100644 --- a/src/lang/fr.rs +++ b/src/lang/fr.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", ""), ("no fingerprints", ""), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/hu.rs b/src/lang/hu.rs index 052c90d6..baeadea1 100644 --- a/src/lang/hu.rs +++ b/src/lang/hu.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", ""), ("no fingerprints", ""), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/id.rs b/src/lang/id.rs index b8e31805..2f197c48 100644 --- a/src/lang/id.rs +++ b/src/lang/id.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", ""), ("no fingerprints", ""), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/it.rs b/src/lang/it.rs index 0265d36b..2cec2cc5 100644 --- a/src/lang/it.rs +++ b/src/lang/it.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", "Copia firma digitale"), ("no fingerprints", "Nessuna firma digitale"), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/ja.rs b/src/lang/ja.rs index 76f8e81e..e2391cfa 100644 --- a/src/lang/ja.rs +++ b/src/lang/ja.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", ""), ("no fingerprints", ""), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/ko.rs b/src/lang/ko.rs index 59995d8a..436de89e 100644 --- a/src/lang/ko.rs +++ b/src/lang/ko.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", ""), ("no fingerprints", ""), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/kz.rs b/src/lang/kz.rs index cf2ad3bf..8450e1ff 100644 --- a/src/lang/kz.rs +++ b/src/lang/kz.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", ""), ("no fingerprints", ""), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/lt.rs b/src/lang/lt.rs index 936bc8d4..907d2651 100644 --- a/src/lang/lt.rs +++ b/src/lang/lt.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", ""), ("no fingerprints", ""), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/nl.rs b/src/lang/nl.rs index 77430846..82a53949 100644 --- a/src/lang/nl.rs +++ b/src/lang/nl.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", "Kopieer Vingerafdruk"), ("no fingerprints", "geen vingerafdrukken"), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/pl.rs b/src/lang/pl.rs index 867144cb..a9dc6b0b 100644 --- a/src/lang/pl.rs +++ b/src/lang/pl.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", "Skopiuj sygnaturę"), ("no fingerprints", "brak sygnatur"), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/pt_PT.rs b/src/lang/pt_PT.rs index 557d274b..608b7bbe 100644 --- a/src/lang/pt_PT.rs +++ b/src/lang/pt_PT.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", ""), ("no fingerprints", ""), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/ptbr.rs b/src/lang/ptbr.rs index 03c215d8..2f7b03ec 100644 --- a/src/lang/ptbr.rs +++ b/src/lang/ptbr.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", ""), ("no fingerprints", ""), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/ro.rs b/src/lang/ro.rs index 11ce9c46..a6e2d843 100644 --- a/src/lang/ro.rs +++ b/src/lang/ro.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", ""), ("no fingerprints", ""), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/ru.rs b/src/lang/ru.rs index 9b514ca5..eba62ca6 100644 --- a/src/lang/ru.rs +++ b/src/lang/ru.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", "Копировать отпечаток"), ("no fingerprints", "отпечатки отсутствуют"), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/sk.rs b/src/lang/sk.rs index 283e7f72..9f5e8f3e 100644 --- a/src/lang/sk.rs +++ b/src/lang/sk.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", ""), ("no fingerprints", ""), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/sl.rs b/src/lang/sl.rs index 1269e5f2..68a2af72 100755 --- a/src/lang/sl.rs +++ b/src/lang/sl.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", ""), ("no fingerprints", ""), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/sq.rs b/src/lang/sq.rs index 5fb966e4..987eb3a0 100644 --- a/src/lang/sq.rs +++ b/src/lang/sq.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", ""), ("no fingerprints", ""), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/sr.rs b/src/lang/sr.rs index 1d639f4e..f34be7fc 100644 --- a/src/lang/sr.rs +++ b/src/lang/sr.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", ""), ("no fingerprints", ""), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/sv.rs b/src/lang/sv.rs index a7b671e7..30b414f1 100644 --- a/src/lang/sv.rs +++ b/src/lang/sv.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", ""), ("no fingerprints", ""), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/template.rs b/src/lang/template.rs index 57e2e595..9b90aed8 100644 --- a/src/lang/template.rs +++ b/src/lang/template.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", ""), ("no fingerprints", ""), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/th.rs b/src/lang/th.rs index b88cb4ea..2ea5a98e 100644 --- a/src/lang/th.rs +++ b/src/lang/th.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", ""), ("no fingerprints", ""), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/tr.rs b/src/lang/tr.rs index ab0c2216..73da503a 100644 --- a/src/lang/tr.rs +++ b/src/lang/tr.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", ""), ("no fingerprints", ""), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/tw.rs b/src/lang/tw.rs index cfb644db..2b53000b 100644 --- a/src/lang/tw.rs +++ b/src/lang/tw.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", "複製指紋"), ("no fingerprints", "沒有指紋"), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/ua.rs b/src/lang/ua.rs index 245fc89a..634c9b92 100644 --- a/src/lang/ua.rs +++ b/src/lang/ua.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", ""), ("no fingerprints", ""), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/lang/vn.rs b/src/lang/vn.rs index 4d415640..b55210aa 100644 --- a/src/lang/vn.rs +++ b/src/lang/vn.rs @@ -499,6 +499,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> = ("Copy Fingerprint", ""), ("no fingerprints", ""), ("Select a peer", ""), - ("Select peers", "") + ("Select peers", ""), + ("Plugins", "") ].iter().cloned().collect(); } diff --git a/src/plugin/native_handlers/ui.rs b/src/plugin/native_handlers/ui.rs index a4754fc0..d4ee9129 100644 --- a/src/plugin/native_handlers/ui.rs +++ b/src/plugin/native_handlers/ui.rs @@ -58,6 +58,33 @@ impl PluginNativeHandler for PluginNativeUIHandler { data: "missing cb field message".as_ptr() as _, }); } + "register_ui_entry" => { + let title; + if let Some(v) = data.get("title") { + title = v.as_str().unwrap_or(""); + } else { + title = ""; + } + if let Some(on_tap_cb) = data.get("on_tap_cb") { + if let Some(on_tap_cb) = on_tap_cb.as_u64() { + let user_data = match data.get("user_data") { + Some(user_data) => { + user_data.as_u64().unwrap_or(0) + }, + None => 0, + }; + self.register_ui_entry(title, on_tap_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 @@ -97,4 +124,26 @@ impl PluginNativeUIHandler { serde_json::to_string(¶m).unwrap_or("".to_string()), ); } + + /// Call with method `register_ui_entry` and the following json: + /// ``` + /// { + /// + /// "on_tap_cb": 0, // The function address + /// "user_data": 0, // An opaque pointer value passed to the callback. + /// "title": "entry name" + /// } + /// ``` + fn register_ui_entry(&self, title: &str, on_tap_cb: u64, user_data: u64) { + let mut param = HashMap::new(); + param.insert("name", json!("native_ui")); + param.insert("action", json!("register_ui_entry")); + param.insert("title", json!(title)); + param.insert("cb", json!(on_tap_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()), + ); + } }