diff --git a/flutter/lib/desktop/pages/desktop_home_page.dart b/flutter/lib/desktop/pages/desktop_home_page.dart index f949f538d..9c1b5827a 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 780fd7e99..c85f4dfca 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 000000000..45accf650 --- /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 554ca09cb..252d5fbdc 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 a80b1da9a..76cbd2f2a 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 e0705a16c..e70c7d9e5 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 8b6832a0b..fc27774f5 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 f1a39ea28..8b31d90cb 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 bb7a86ed4..458a8c552 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 547bf9816..cd26b5ab5 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 b63f592a6..d593e6838 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 4e4a768d6..e1183ce22 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 3ff011881..6d9ff9408 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 052c90d60..baeadea16 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 b8e31805d..2f197c486 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 0265d36b1..2cec2cc58 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 76f8e81ee..e2391cfad 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 59995d8ab..436de89e9 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 cf2ad3bf4..8450e1ffc 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 936bc8d42..907d26515 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 774308465..82a539491 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 867144cb8..a9dc6b0b8 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 557d274b0..608b7bbef 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 03c215d87..2f7b03ec0 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 11ce9c467..a6e2d843a 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 9b514ca5c..eba62ca61 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 283e7f721..9f5e8f3ee 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 1269e5f27..68a2af723 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 5fb966e4c..987eb3a01 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 1d639f4ef..f34be7fc1 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 a7b671e75..30b414f16 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 57e2e595b..9b90aed84 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 b88cb4ea6..2ea5a98eb 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 ab0c22166..73da503a5 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 cfb644db5..2b53000b5 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 245fc89a5..634c9b927 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 4d415640f..b55210aa5 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 a4754fc08..d4ee91299 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()), + ); + } }