multi remote instances
This commit is contained in:
parent
00ba7cad81
commit
18ad23435b
@ -404,7 +404,7 @@ class _RemotePageState extends State<RemotePage> with WindowListener {
|
|||||||
icon: Icon(Icons.tv),
|
icon: Icon(Icons.tv),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
setState(() => _showEdit = false);
|
setState(() => _showEdit = false);
|
||||||
showOptions();
|
showOptions(widget.id);
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
] +
|
] +
|
||||||
@ -972,8 +972,9 @@ RadioListTile<String> getRadio(String name, String toValue, String curValue,
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void showOptions() {
|
void showOptions(String id) async {
|
||||||
String quality = FFI.getByName('image_quality');
|
// String quality = FFI.getByName('image_quality');
|
||||||
|
String quality = await FFI.rustdeskImpl.getImageQuality(id: id) ?? 'balanced';
|
||||||
if (quality == '') quality = 'balanced';
|
if (quality == '') quality = 'balanced';
|
||||||
String viewStyle = FFI.getByName('peer_option', 'view-style');
|
String viewStyle = FFI.getByName('peer_option', 'view-style');
|
||||||
var displays = <Widget>[];
|
var displays = <Widget>[];
|
||||||
|
@ -6,6 +6,7 @@ import 'dart:ui' as ui;
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_hbb/generated_bridge.dart';
|
||||||
import 'package:flutter_hbb/models/chat_model.dart';
|
import 'package:flutter_hbb/models/chat_model.dart';
|
||||||
import 'package:flutter_hbb/models/file_model.dart';
|
import 'package:flutter_hbb/models/file_model.dart';
|
||||||
import 'package:flutter_hbb/models/server_model.dart';
|
import 'package:flutter_hbb/models/server_model.dart';
|
||||||
@ -598,17 +599,17 @@ class CursorModel with ChangeNotifier {
|
|||||||
final rgba = Uint8List.fromList(colors.map((s) => s as int).toList());
|
final rgba = Uint8List.fromList(colors.map((s) => s as int).toList());
|
||||||
var pid = FFI.id;
|
var pid = FFI.id;
|
||||||
ui.decodeImageFromPixels(rgba, width, height, ui.PixelFormat.rgba8888,
|
ui.decodeImageFromPixels(rgba, width, height, ui.PixelFormat.rgba8888,
|
||||||
(image) {
|
(image) {
|
||||||
if (FFI.id != pid) return;
|
if (FFI.id != pid) return;
|
||||||
_image = image;
|
_image = image;
|
||||||
_images[id] = Tuple3(image, _hotx, _hoty);
|
_images[id] = Tuple3(image, _hotx, _hoty);
|
||||||
try {
|
try {
|
||||||
// my throw exception, because the listener maybe already dispose
|
// my throw exception, because the listener maybe already dispose
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('notify cursor: $e');
|
print('notify cursor: $e');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateCursorId(Map<String, dynamic> evt) {
|
void updateCursorId(Map<String, dynamic> evt) {
|
||||||
@ -637,7 +638,8 @@ class CursorModel with ChangeNotifier {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateDisplayOriginWithCursor(double x, double y, double xCursor, double yCursor) {
|
void updateDisplayOriginWithCursor(
|
||||||
|
double x, double y, double xCursor, double yCursor) {
|
||||||
_displayOriginX = x;
|
_displayOriginX = x;
|
||||||
_displayOriginY = y;
|
_displayOriginY = y;
|
||||||
_x = xCursor;
|
_x = xCursor;
|
||||||
@ -765,7 +767,7 @@ class FFI {
|
|||||||
return peers
|
return peers
|
||||||
.map((s) => s as List<dynamic>)
|
.map((s) => s as List<dynamic>)
|
||||||
.map((s) =>
|
.map((s) =>
|
||||||
Peer.fromJson(s[0] as String, s[1] as Map<String, dynamic>))
|
Peer.fromJson(s[0] as String, s[1] as Map<String, dynamic>))
|
||||||
.toList();
|
.toList();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('peers(): $e');
|
print('peers(): $e');
|
||||||
@ -779,7 +781,11 @@ class FFI {
|
|||||||
setByName('connect_file_transfer', id);
|
setByName('connect_file_transfer', id);
|
||||||
} else {
|
} else {
|
||||||
FFI.chatModel.resetClientMode();
|
FFI.chatModel.resetClientMode();
|
||||||
setByName('connect', id);
|
// setByName('connect', id);
|
||||||
|
final stream =
|
||||||
|
FFI.rustdeskImpl.connect(id: id, isFileTransfer: isFileTransfer);
|
||||||
|
// listen stream ...
|
||||||
|
// every instance will bind a stream
|
||||||
}
|
}
|
||||||
FFI.id = id;
|
FFI.id = id;
|
||||||
}
|
}
|
||||||
@ -833,6 +839,8 @@ class FFI {
|
|||||||
PlatformFFI.setByName(name, value);
|
PlatformFFI.setByName(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static RustdeskImpl get rustdeskImpl => PlatformFFI.rustdeskImpl;
|
||||||
|
|
||||||
static handleMouse(Map<String, dynamic> evt) {
|
static handleMouse(Map<String, dynamic> evt) {
|
||||||
var type = '';
|
var type = '';
|
||||||
var isMove = false;
|
var isMove = false;
|
||||||
|
@ -30,9 +30,12 @@ class PlatformFFI {
|
|||||||
static String _homeDir = '';
|
static String _homeDir = '';
|
||||||
static F2? _getByName;
|
static F2? _getByName;
|
||||||
static F3? _setByName;
|
static F3? _setByName;
|
||||||
|
static late RustdeskImpl _rustdeskImpl;
|
||||||
static void Function(Map<String, dynamic>)? _eventCallback;
|
static void Function(Map<String, dynamic>)? _eventCallback;
|
||||||
static void Function(Uint8List)? _rgbaCallback;
|
static void Function(Uint8List)? _rgbaCallback;
|
||||||
|
|
||||||
|
static RustdeskImpl get rustdeskImpl => _rustdeskImpl;
|
||||||
|
|
||||||
static Future<String> getVersion() async {
|
static Future<String> getVersion() async {
|
||||||
PackageInfo packageInfo = await PackageInfo.fromPlatform();
|
PackageInfo packageInfo = await PackageInfo.fromPlatform();
|
||||||
return packageInfo.version;
|
return packageInfo.version;
|
||||||
@ -88,7 +91,8 @@ class PlatformFFI {
|
|||||||
dylib.lookupFunction<Void Function(Pointer<Utf8>, Pointer<Utf8>), F3>(
|
dylib.lookupFunction<Void Function(Pointer<Utf8>, Pointer<Utf8>), F3>(
|
||||||
'set_by_name');
|
'set_by_name');
|
||||||
_dir = (await getApplicationDocumentsDirectory()).path;
|
_dir = (await getApplicationDocumentsDirectory()).path;
|
||||||
_startListenEvent(RustdeskImpl(dylib));
|
_rustdeskImpl = RustdeskImpl(dylib);
|
||||||
|
_startListenEvent(_rustdeskImpl); // global event
|
||||||
try {
|
try {
|
||||||
_homeDir = (await ExternalPath.getExternalStorageDirectories())[0];
|
_homeDir = (await ExternalPath.getExternalStorageDirectories())[0];
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
311
src/flutter.rs
311
src/flutter.rs
@ -26,17 +26,22 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
static ref SESSION: Arc<RwLock<Option<Session>>> = Default::default();
|
// static ref SESSION: Arc<RwLock<Option<Session>>> = Default::default();
|
||||||
|
static ref SESSIONS: RwLock<HashMap<String,Session>> = Default::default();
|
||||||
pub static ref EVENT_STREAM: RwLock<Option<StreamSink<String>>> = Default::default(); // rust to dart event channel
|
pub static ref EVENT_STREAM: RwLock<Option<StreamSink<String>>> = Default::default(); // rust to dart event channel
|
||||||
pub static ref RGBA_STREAM: RwLock<Option<StreamSink<ZeroCopyBuffer<Vec<u8>>>>> = Default::default(); // rust to dart rgba (big u8 list) channel
|
pub static ref RGBA_STREAM: RwLock<Option<StreamSink<ZeroCopyBuffer<Vec<u8>>>>> = Default::default(); // rust to dart rgba (big u8 list) channel
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
pub fn get_session(id: &str) -> Option<&Session> {
|
||||||
|
SESSIONS.read().unwrap().get(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Session {
|
pub struct Session {
|
||||||
id: String,
|
id: String,
|
||||||
sender: Arc<RwLock<Option<mpsc::UnboundedSender<Data>>>>,
|
sender: Arc<RwLock<Option<mpsc::UnboundedSender<Data>>>>, // UI to rust
|
||||||
lc: Arc<RwLock<LoginConfigHandler>>,
|
lc: Arc<RwLock<LoginConfigHandler>>,
|
||||||
events2ui: Arc<RwLock<VecDeque<String>>>,
|
events2ui: Arc<RwLock<StreamSink<String>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Session {
|
impl Session {
|
||||||
@ -46,40 +51,47 @@ impl Session {
|
|||||||
///
|
///
|
||||||
/// * `id` - The id of the remote session.
|
/// * `id` - The id of the remote session.
|
||||||
/// * `is_file_transfer` - If the session is used for file transfer.
|
/// * `is_file_transfer` - If the session is used for file transfer.
|
||||||
pub fn start(id: &str, is_file_transfer: bool) {
|
pub fn start(id: &str, is_file_transfer: bool, events2ui: StreamSink<String>) {
|
||||||
LocalConfig::set_remote_id(id);
|
LocalConfig::set_remote_id(&id);
|
||||||
Self::close();
|
// TODO check same id
|
||||||
let mut session = Session::default();
|
// TODO close
|
||||||
|
// Self::close();
|
||||||
|
let events2ui = Arc::new(RwLock::new(events2ui));
|
||||||
|
let mut session = Session {
|
||||||
|
id: id.to_owned(),
|
||||||
|
sender: Default::default(),
|
||||||
|
lc: Default::default(),
|
||||||
|
events2ui,
|
||||||
|
};
|
||||||
session
|
session
|
||||||
.lc
|
.lc
|
||||||
.write()
|
.write()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.initialize(id.to_owned(), false, false);
|
.initialize(id.to_owned(), false, false);
|
||||||
session.id = id.to_owned();
|
SESSIONS
|
||||||
*SESSION.write().unwrap() = Some(session.clone());
|
.write()
|
||||||
|
.unwrap()
|
||||||
|
.insert(id.to_owned(), session.clone());
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
Connection::start(session, is_file_transfer);
|
Connection::start(session, is_file_transfer);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the current session instance.
|
/// Get the current session instance.
|
||||||
pub fn get() -> Arc<RwLock<Option<Session>>> {
|
// pub fn get() -> Arc<RwLock<Option<Session>>> {
|
||||||
SESSION.clone()
|
// SESSION.clone()
|
||||||
}
|
// }
|
||||||
|
|
||||||
/// Get the option of the current session.
|
/// Get the option of the current session.
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// * `name` - The name of the option to get. Currently only `remote_dir` is supported.
|
/// * `name` - The name of the option to get. Currently only `remote_dir` is supported.
|
||||||
pub fn get_option(name: &str) -> String {
|
pub fn get_option(&self, name: &str) -> String {
|
||||||
if let Some(session) = SESSION.read().unwrap().as_ref() {
|
if name == "remote_dir" {
|
||||||
if name == "remote_dir" {
|
return self.lc.read().unwrap().get_remote_dir();
|
||||||
return session.lc.read().unwrap().get_remote_dir();
|
|
||||||
}
|
|
||||||
return session.lc.read().unwrap().get_option(name);
|
|
||||||
}
|
}
|
||||||
"".to_owned()
|
self.lc.read().unwrap().get_option(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the option of the current session.
|
/// Set the option of the current session.
|
||||||
@ -88,78 +100,59 @@ impl Session {
|
|||||||
///
|
///
|
||||||
/// * `name` - The name of the option to set. Currently only `remote_dir` is supported.
|
/// * `name` - The name of the option to set. Currently only `remote_dir` is supported.
|
||||||
/// * `value` - The value of the option to set.
|
/// * `value` - The value of the option to set.
|
||||||
pub fn set_option(name: String, value: String) {
|
pub fn set_option(&self, name: String, value: String) {
|
||||||
if let Some(session) = SESSION.read().unwrap().as_ref() {
|
let mut value = value;
|
||||||
let mut value = value;
|
let lc = self.lc.write().unwrap();
|
||||||
if name == "remote_dir" {
|
if name == "remote_dir" {
|
||||||
value = session.lc.write().unwrap().get_all_remote_dir(value);
|
value = lc.get_all_remote_dir(value);
|
||||||
}
|
|
||||||
return session.lc.write().unwrap().set_option(name, value);
|
|
||||||
}
|
}
|
||||||
|
lc.set_option(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Input the OS password.
|
/// Input the OS password.
|
||||||
pub fn input_os_password(pass: String, activate: bool) {
|
pub fn input_os_password(&self, pass: String, activate: bool) {
|
||||||
if let Some(session) = SESSION.read().unwrap().as_ref() {
|
input_os_password(pass, activate, self.clone());
|
||||||
input_os_password(pass, activate, session.clone());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// impl Interface
|
||||||
/// Send message to the remote session.
|
/// Send message to the remote session.
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// * `data` - The data to send. See [`Data`] for more details.
|
/// * `data` - The data to send. See [`Data`] for more details.
|
||||||
fn send(data: Data) {
|
// fn send(data: Data) {
|
||||||
if let Some(session) = SESSION.read().unwrap().as_ref() {
|
// if let Some(session) = SESSION.read().unwrap().as_ref() {
|
||||||
session.send(data);
|
// session.send(data);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
/// Pop a event from the event queue.
|
|
||||||
pub fn pop_event() -> Option<String> {
|
|
||||||
if let Some(session) = SESSION.read().unwrap().as_ref() {
|
|
||||||
session.events2ui.write().unwrap().pop_front()
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Toggle an option.
|
/// Toggle an option.
|
||||||
pub fn toggle_option(name: &str) {
|
pub fn toggle_option(&self, name: &str) {
|
||||||
if let Some(session) = SESSION.read().unwrap().as_ref() {
|
let msg = self.lc.write().unwrap().toggle_option(name.to_owned());
|
||||||
let msg = session.lc.write().unwrap().toggle_option(name.to_owned());
|
if let Some(msg) = msg {
|
||||||
if let Some(msg) = msg {
|
self.send_msg(msg);
|
||||||
session.send_msg(msg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send a refresh command.
|
/// Send a refresh command.
|
||||||
pub fn refresh() {
|
pub fn refresh(&self) {
|
||||||
Self::send(Data::Message(LoginConfigHandler::refresh()));
|
self.send(Data::Message(LoginConfigHandler::refresh()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get image quality.
|
/// Get image quality.
|
||||||
pub fn get_image_quality() -> String {
|
pub fn get_image_quality(&self) -> String {
|
||||||
if let Some(session) = SESSION.read().unwrap().as_ref() {
|
self.lc.read().unwrap().image_quality.clone()
|
||||||
session.lc.read().unwrap().image_quality.clone()
|
|
||||||
} else {
|
|
||||||
"".to_owned()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set image quality.
|
/// Set image quality.
|
||||||
pub fn set_image_quality(value: &str) {
|
pub fn set_image_quality(&self, value: &str) {
|
||||||
if let Some(session) = SESSION.read().unwrap().as_ref() {
|
let msg = self
|
||||||
let msg = session
|
.lc
|
||||||
.lc
|
.write()
|
||||||
.write()
|
.unwrap()
|
||||||
.unwrap()
|
.save_image_quality(value.to_owned());
|
||||||
.save_image_quality(value.to_owned());
|
if let Some(msg) = msg {
|
||||||
if let Some(msg) = msg {
|
self.send_msg(msg);
|
||||||
session.send_msg(msg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,12 +162,8 @@ impl Session {
|
|||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// * `name` - The name of the option to get.
|
/// * `name` - The name of the option to get.
|
||||||
pub fn get_toggle_option(name: &str) -> Option<bool> {
|
pub fn get_toggle_option(&self, name: &str) -> bool {
|
||||||
if let Some(session) = SESSION.read().unwrap().as_ref() {
|
self.lc.write().unwrap().get_toggle_option(name)
|
||||||
Some(session.lc.write().unwrap().get_toggle_option(name))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Login.
|
/// Login.
|
||||||
@ -183,36 +172,28 @@ impl Session {
|
|||||||
///
|
///
|
||||||
/// * `password` - The password to login.
|
/// * `password` - The password to login.
|
||||||
/// * `remember` - If the password should be remembered.
|
/// * `remember` - If the password should be remembered.
|
||||||
pub fn login(password: &str, remember: bool) {
|
pub fn login(&self, password: &str, remember: bool) {
|
||||||
Session::send(Data::Login((password.to_owned(), remember)));
|
self.send(Data::Login((password.to_owned(), remember)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Close the session.
|
/// Close the session.
|
||||||
pub fn close() {
|
pub fn close(&self) {
|
||||||
Session::send(Data::Close);
|
self.send(Data::Close);
|
||||||
SESSION.write().unwrap().take();
|
let _ = SESSIONS.write().unwrap().remove(&self.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reconnect to the current session.
|
/// Reconnect to the current session.
|
||||||
pub fn reconnect() {
|
pub fn reconnect(&self) {
|
||||||
if let Some(session) = SESSION.read().unwrap().as_ref() {
|
self.send(Data::Close);
|
||||||
if let Some(sender) = session.sender.read().unwrap().as_ref() {
|
let session = self.clone();
|
||||||
sender.send(Data::Close).ok();
|
std::thread::spawn(move || {
|
||||||
}
|
Connection::start(session, false);
|
||||||
let session = session.clone();
|
});
|
||||||
std::thread::spawn(move || {
|
|
||||||
Connection::start(session, false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get `remember` flag in [`LoginConfigHandler`].
|
/// Get `remember` flag in [`LoginConfigHandler`].
|
||||||
pub fn get_remember() -> bool {
|
pub fn get_remember(&self) -> bool {
|
||||||
if let Some(session) = SESSION.read().unwrap().as_ref() {
|
self.lc.read().unwrap().remember
|
||||||
session.lc.read().unwrap().remember
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send message over the current session.
|
/// Send message over the current session.
|
||||||
@ -222,9 +203,7 @@ impl Session {
|
|||||||
/// * `msg` - The message to send.
|
/// * `msg` - The message to send.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn send_msg(&self, msg: Message) {
|
pub fn send_msg(&self, msg: Message) {
|
||||||
if let Some(sender) = self.sender.read().unwrap().as_ref() {
|
self.send(Data::Message(msg));
|
||||||
sender.send(Data::Message(msg)).ok();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send chat message over the current session.
|
/// Send chat message over the current session.
|
||||||
@ -232,7 +211,7 @@ impl Session {
|
|||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// * `text` - The message to send.
|
/// * `text` - The message to send.
|
||||||
pub fn send_chat(text: String) {
|
pub fn send_chat(&self, text: String) {
|
||||||
let mut misc = Misc::new();
|
let mut misc = Misc::new();
|
||||||
misc.set_chat_message(ChatMessage {
|
misc.set_chat_message(ChatMessage {
|
||||||
text,
|
text,
|
||||||
@ -240,49 +219,46 @@ impl Session {
|
|||||||
});
|
});
|
||||||
let mut msg_out = Message::new();
|
let mut msg_out = Message::new();
|
||||||
msg_out.set_misc(misc);
|
msg_out.set_misc(misc);
|
||||||
Self::send_msg_static(msg_out);
|
self.send_msg(msg_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// file trait
|
||||||
/// Send file over the current session.
|
/// Send file over the current session.
|
||||||
pub fn send_files(
|
// pub fn send_files(
|
||||||
id: i32,
|
// id: i32,
|
||||||
path: String,
|
// path: String,
|
||||||
to: String,
|
// to: String,
|
||||||
file_num: i32,
|
// file_num: i32,
|
||||||
include_hidden: bool,
|
// include_hidden: bool,
|
||||||
is_remote: bool,
|
// is_remote: bool,
|
||||||
) {
|
// ) {
|
||||||
if let Some(session) = SESSION.write().unwrap().as_mut() {
|
// if let Some(session) = SESSION.write().unwrap().as_mut() {
|
||||||
session.send_files(id, path, to, file_num, include_hidden, is_remote);
|
// session.send_files(id, path, to, file_num, include_hidden, is_remote);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
// TODO into file trait
|
||||||
/// Confirm file override.
|
/// Confirm file override.
|
||||||
pub fn set_confirm_override_file(
|
pub fn set_confirm_override_file(
|
||||||
|
&self,
|
||||||
id: i32,
|
id: i32,
|
||||||
file_num: i32,
|
file_num: i32,
|
||||||
need_override: bool,
|
need_override: bool,
|
||||||
remember: bool,
|
remember: bool,
|
||||||
is_upload: bool,
|
is_upload: bool,
|
||||||
) {
|
) {
|
||||||
if let Some(session) = SESSION.read().unwrap().as_ref() {
|
log::info!(
|
||||||
if let Some(sender) = session.sender.read().unwrap().as_ref() {
|
"confirm file transfer, job: {}, need_override: {}",
|
||||||
log::info!(
|
id,
|
||||||
"confirm file transfer, job: {}, need_override: {}",
|
need_override
|
||||||
id,
|
);
|
||||||
need_override
|
self.send(Data::SetConfirmOverrideFile((
|
||||||
);
|
id,
|
||||||
sender
|
file_num,
|
||||||
.send(Data::SetConfirmOverrideFile((
|
need_override,
|
||||||
id,
|
remember,
|
||||||
file_num,
|
is_upload,
|
||||||
need_override,
|
)));
|
||||||
remember,
|
|
||||||
is_upload,
|
|
||||||
)))
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Static method to send message over the current session.
|
/// Static method to send message over the current session.
|
||||||
@ -290,12 +266,12 @@ impl Session {
|
|||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// * `msg` - The message to send.
|
/// * `msg` - The message to send.
|
||||||
#[inline]
|
// #[inline]
|
||||||
pub fn send_msg_static(msg: Message) {
|
// pub fn send_msg_static(msg: Message) {
|
||||||
if let Some(session) = SESSION.read().unwrap().as_ref() {
|
// if let Some(session) = SESSION.read().unwrap().as_ref() {
|
||||||
session.send_msg(msg);
|
// session.send_msg(msg);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
/// Push an event to the event queue.
|
/// Push an event to the event queue.
|
||||||
/// An event is stored as json in the event queue.
|
/// An event is stored as json in the event queue.
|
||||||
@ -309,9 +285,10 @@ impl Session {
|
|||||||
assert!(h.get("name").is_none());
|
assert!(h.get("name").is_none());
|
||||||
h.insert("name", name);
|
h.insert("name", name);
|
||||||
|
|
||||||
if let Some(s) = EVENT_STREAM.read().unwrap().as_ref() {
|
self.events2ui
|
||||||
s.add(serde_json::ser::to_string(&h).unwrap_or("".to_owned()));
|
.read()
|
||||||
};
|
.unwrap()
|
||||||
|
.add(serde_json::ser::to_string(&h).unwrap_or("".to_owned()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get platform of peer.
|
/// Get platform of peer.
|
||||||
@ -321,15 +298,13 @@ impl Session {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Quick method for sending a ctrl_alt_del command.
|
/// Quick method for sending a ctrl_alt_del command.
|
||||||
pub fn ctrl_alt_del() {
|
pub fn ctrl_alt_del(&self) {
|
||||||
if let Some(session) = SESSION.read().unwrap().as_ref() {
|
if self.peer_platform() == "Windows" {
|
||||||
if session.peer_platform() == "Windows" {
|
let k = Key::ControlKey(ControlKey::CtrlAltDel);
|
||||||
let k = Key::ControlKey(ControlKey::CtrlAltDel);
|
self.key_down_or_up(1, k, false, false, false, false);
|
||||||
session.key_down_or_up(1, k, false, false, false, false);
|
} else {
|
||||||
} else {
|
let k = Key::ControlKey(ControlKey::Delete);
|
||||||
let k = Key::ControlKey(ControlKey::Delete);
|
self.key_down_or_up(3, k, true, true, false, false);
|
||||||
session.key_down_or_up(3, k, true, true, false, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,7 +313,7 @@ impl Session {
|
|||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// * `display` - The display to switch to.
|
/// * `display` - The display to switch to.
|
||||||
pub fn switch_display(display: i32) {
|
pub fn switch_display(&self, display: i32) {
|
||||||
let mut misc = Misc::new();
|
let mut misc = Misc::new();
|
||||||
misc.set_switch_display(SwitchDisplay {
|
misc.set_switch_display(SwitchDisplay {
|
||||||
display,
|
display,
|
||||||
@ -346,15 +321,13 @@ impl Session {
|
|||||||
});
|
});
|
||||||
let mut msg_out = Message::new();
|
let mut msg_out = Message::new();
|
||||||
msg_out.set_misc(misc);
|
msg_out.set_misc(misc);
|
||||||
Self::send_msg_static(msg_out);
|
self.send_msg(msg_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send lock screen command.
|
/// Send lock screen command.
|
||||||
pub fn lock_screen() {
|
pub fn lock_screen(&self) {
|
||||||
if let Some(session) = SESSION.read().unwrap().as_ref() {
|
let k = Key::ControlKey(ControlKey::LockScreen);
|
||||||
let k = Key::ControlKey(ControlKey::LockScreen);
|
self.key_down_or_up(1, k, false, false, false, false);
|
||||||
session.key_down_or_up(1, k, false, false, false, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send key input command.
|
/// Send key input command.
|
||||||
@ -369,6 +342,7 @@ impl Session {
|
|||||||
/// * `shift` - If the shift key is also pressed.
|
/// * `shift` - If the shift key is also pressed.
|
||||||
/// * `command` - If the command key is also pressed.
|
/// * `command` - If the command key is also pressed.
|
||||||
pub fn input_key(
|
pub fn input_key(
|
||||||
|
&self,
|
||||||
name: &str,
|
name: &str,
|
||||||
down: bool,
|
down: bool,
|
||||||
press: bool,
|
press: bool,
|
||||||
@ -377,15 +351,13 @@ impl Session {
|
|||||||
shift: bool,
|
shift: bool,
|
||||||
command: bool,
|
command: bool,
|
||||||
) {
|
) {
|
||||||
if let Some(session) = SESSION.read().unwrap().as_ref() {
|
let chars: Vec<char> = name.chars().collect();
|
||||||
let chars: Vec<char> = name.chars().collect();
|
if chars.len() == 1 {
|
||||||
if chars.len() == 1 {
|
let key = Key::_Raw(chars[0] as _);
|
||||||
let key = Key::_Raw(chars[0] as _);
|
self._input_key(key, down, press, alt, ctrl, shift, command);
|
||||||
session._input_key(key, down, press, alt, ctrl, shift, command);
|
} else {
|
||||||
} else {
|
if let Some(key) = KEY_MAP.get(name) {
|
||||||
if let Some(key) = KEY_MAP.get(name) {
|
self._input_key(key.clone(), down, press, alt, ctrl, shift, command);
|
||||||
session._input_key(key.clone(), down, press, alt, ctrl, shift, command);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -396,12 +368,12 @@ impl Session {
|
|||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// * `value` - The text to input.
|
/// * `value` - The text to input.
|
||||||
pub fn input_string(value: &str) {
|
pub fn input_string(&self, value: &str) {
|
||||||
let mut key_event = KeyEvent::new();
|
let mut key_event = KeyEvent::new();
|
||||||
key_event.set_seq(value.to_owned());
|
key_event.set_seq(value.to_owned());
|
||||||
let mut msg_out = Message::new();
|
let mut msg_out = Message::new();
|
||||||
msg_out.set_key_event(key_event);
|
msg_out.set_key_event(key_event);
|
||||||
Self::send_msg_static(msg_out);
|
self.send_msg(msg_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _input_key(
|
fn _input_key(
|
||||||
@ -425,6 +397,7 @@ impl Session {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_mouse(
|
pub fn send_mouse(
|
||||||
|
&self,
|
||||||
mask: i32,
|
mask: i32,
|
||||||
x: i32,
|
x: i32,
|
||||||
y: i32,
|
y: i32,
|
||||||
@ -433,9 +406,7 @@ impl Session {
|
|||||||
shift: bool,
|
shift: bool,
|
||||||
command: bool,
|
command: bool,
|
||||||
) {
|
) {
|
||||||
if let Some(session) = SESSION.read().unwrap().as_ref() {
|
send_mouse(mask, x, y, alt, ctrl, shift, command, self);
|
||||||
send_mouse(mask, x, y, alt, ctrl, shift, command, session);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn key_down_or_up(
|
fn key_down_or_up(
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::client::file_trait::FileManager;
|
use crate::client::file_trait::FileManager;
|
||||||
use crate::flutter::connection_manager::{self, get_clients_length, get_clients_state};
|
use crate::flutter::connection_manager::{self, get_clients_length, get_clients_state};
|
||||||
use crate::flutter::{self, make_fd_to_json, Session};
|
use crate::flutter::{self, get_session, make_fd_to_json, Session};
|
||||||
use crate::start_server;
|
use crate::start_server;
|
||||||
use crate::ui_interface;
|
use crate::ui_interface;
|
||||||
use flutter_rust_bridge::{StreamSink, ZeroCopyBuffer};
|
use flutter_rust_bridge::{StreamSink, ZeroCopyBuffer};
|
||||||
@ -69,6 +69,15 @@ pub fn start_rgba_stream(s: StreamSink<ZeroCopyBuffer<Vec<u8>>>) -> ResultType<(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn connect(id: String, is_file_transfer: bool, events2ui: StreamSink<String>) {
|
||||||
|
Session::start(&id, is_file_transfer, events2ui);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_image_quality(id: String) -> Option<String> {
|
||||||
|
let session = get_session(&id)?;
|
||||||
|
Some(session.get_image_quality())
|
||||||
|
}
|
||||||
|
|
||||||
/// FFI for **get** commands which are idempotent.
|
/// FFI for **get** commands which are idempotent.
|
||||||
/// Return result in c string.
|
/// Return result in c string.
|
||||||
///
|
///
|
||||||
@ -100,11 +109,6 @@ unsafe extern "C" fn get_by_name(name: *const c_char, arg: *const c_char) -> *co
|
|||||||
"remember" => {
|
"remember" => {
|
||||||
res = Session::get_remember().to_string();
|
res = Session::get_remember().to_string();
|
||||||
}
|
}
|
||||||
"event" => {
|
|
||||||
if let Some(e) = Session::pop_event() {
|
|
||||||
res = e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"toggle_option" => {
|
"toggle_option" => {
|
||||||
if let Ok(arg) = arg.to_str() {
|
if let Ok(arg) = arg.to_str() {
|
||||||
if let Some(v) = Session::get_toggle_option(arg) {
|
if let Some(v) = Session::get_toggle_option(arg) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user