From 3d77365edc782ef1bfc4051c21f7c65cb343f083 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Wed, 26 Jan 2022 12:48:16 +0800 Subject: [PATCH] refactor --- lib/home_page.dart | 8 +- lib/main.dart | 2 +- lib/model.dart | 108 +------ lib/native_model.dart | 100 ++++++ lib/remote_page.dart | 6 +- lib/web_model.dart | 698 +----------------------------------------- web/index.html | 1 + 7 files changed, 132 insertions(+), 791 deletions(-) create mode 100644 lib/native_model.dart diff --git a/lib/home_page.dart b/lib/home_page.dart index 09da3d04b..7daa30814 100644 --- a/lib/home_page.dart +++ b/lib/home_page.dart @@ -5,7 +5,7 @@ import 'package:package_info/package_info.dart'; import 'package:url_launcher/url_launcher.dart'; import 'dart:async'; import 'common.dart'; -import 'model.dart' if (dart.library.html) 'web_model.dart'; +import 'model.dart'; import 'remote_page.dart'; class HomePage extends StatefulWidget { @@ -325,13 +325,13 @@ void showServer(BuildContext context) { formKey.currentState.save(); if (id != id0) FFI.setByName('option', - '{"name": "custom-rendezvous-server", "value": "${id}"}'); + '{"name": "custom-rendezvous-server", "value": "$id"}'); if (relay != relay0) FFI.setByName('option', - '{"name": "relay-server", "value": "${relay}"}'); + '{"name": "relay-server", "value": "$relay"}'); if (key != key0) FFI.setByName( - 'option', '{"name": "key", "value": "${key}"}'); + 'option', '{"name": "key", "value": "$key"}'); Navigator.pop(context); } }, diff --git a/lib/main.dart b/lib/main.dart index 29d9ad0ed..32af66665 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,7 +3,7 @@ import 'package:provider/provider.dart'; import 'package:firebase_analytics/firebase_analytics.dart'; import 'package:firebase_analytics/observer.dart'; import 'package:firebase_core/firebase_core.dart'; -import 'model.dart' if (dart.library.html) 'web_model.dart'; +import 'model.dart'; import 'home_page.dart'; Future main() async { diff --git a/lib/model.dart b/lib/model.dart index 73dc375ec..d914e5b0f 100644 --- a/lib/model.dart +++ b/lib/model.dart @@ -1,11 +1,6 @@ -import 'package:ffi/ffi.dart'; import 'package:flutter/services.dart'; -import 'package:path_provider/path_provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import 'package:device_info/device_info.dart'; -import 'dart:io'; import 'dart:math'; -import 'dart:ffi'; import 'dart:convert'; import 'dart:typed_data'; import 'dart:ui' as ui; @@ -13,17 +8,7 @@ import 'package:flutter/material.dart'; import 'package:tuple/tuple.dart'; import 'dart:async'; import 'common.dart'; - -class RgbaFrame extends Struct { - @Uint32() - int len; - Pointer data; -} - -typedef F2 = Pointer Function(Pointer, Pointer); -typedef F3 = void Function(Pointer, Pointer); -typedef F4 = void Function(Pointer); -typedef F5 = Pointer Function(); +import 'native_model.dart' if (dart.library.html) 'web_model.dart'; class FfiModel with ChangeNotifier { PeerInfo _pi; @@ -43,13 +28,10 @@ class FfiModel with ChangeNotifier { get pi => _pi; FfiModel() { - isIOS = Platform.isIOS; - isAndroid = Platform.isAndroid; - isWeb = false; Translator.call = translate; clear(); () async { - await FFI.init(); + await PlatformFFI.init(); _initialized = true; print("FFI initialized"); notifyListeners(); @@ -136,7 +118,7 @@ class FfiModel with ChangeNotifier { } if (pos != null) FFI.cursorModel.updateCursorPosition(pos); if (!_decoding) { - var rgba = FFI.getRgba(); + var rgba = PlatformFFI.getRgba(); if (rgba != null) { if (_waitForImage) { _waitForImage = false; @@ -147,7 +129,7 @@ class FfiModel with ChangeNotifier { ui.decodeImageFromPixels( rgba, _display.width, _display.height, ui.PixelFormat.bgra8888, (image) { - FFI.clearRgbaFrame(); + PlatformFFI.clearRgbaFrame(); _decoding = false; if (FFI.id != pid) return; try { @@ -510,12 +492,6 @@ class CursorModel with ChangeNotifier { class FFI { static String id = ""; - static String _dir = ''; - static F2 _getByName; - static F3 _setByName; - static F4 _freeRgba; - static F5 _getRgba; - static Pointer _lastRgbaFrame; static var shift = false; static var ctrl = false; static var alt = false; @@ -595,19 +571,6 @@ class FFI { FFI.id = id; } - static void clearRgbaFrame() { - if (_lastRgbaFrame != null && _lastRgbaFrame != nullptr) - _freeRgba(_lastRgbaFrame); - } - - static Uint8List getRgba() { - if (_getRgba == null) return null; - _lastRgbaFrame = _getRgba(); - if (_lastRgbaFrame == null || _lastRgbaFrame == nullptr) return null; - final ref = _lastRgbaFrame.ref; - return Uint8List.sublistView(ref.data.asTypedList(ref.len)); - } - static Map popEvent() { var s = getByName('event'); if (s == '') return null; @@ -641,60 +604,12 @@ class FFI { resetModifiers(); } - static void setByName(String name, [String value = '']) { - if (_setByName == null) return; - var a = name.toNativeUtf8(); - var b = value.toNativeUtf8(); - _setByName(a, b); - calloc.free(a); - calloc.free(b); - } - static String getByName(String name, [String arg = '']) { - if (_getByName == null) return ''; - var a = name.toNativeUtf8(); - var b = arg.toNativeUtf8(); - var p = _getByName(a, b); - assert(p != nullptr && p != null); - var res = p.toDartString(); - calloc.free(p); - calloc.free(a); - calloc.free(b); - return res; + return PlatformFFI.getByName(name, arg); } - static Future init() async { - final dylib = Platform.isAndroid - ? DynamicLibrary.open('librustdesk.so') - : DynamicLibrary.process(); - print('initializing FFI'); - try { - _getByName = dylib.lookupFunction('get_by_name'); - _setByName = - dylib.lookupFunction, Pointer), F3>( - 'set_by_name'); - _freeRgba = dylib - .lookupFunction), F4>('free_rgba'); - _getRgba = dylib.lookupFunction('get_rgba'); - _dir = (await getApplicationDocumentsDirectory()).path; - String id = 'NA'; - String name = 'Flutter'; - DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); - if (Platform.isAndroid) { - AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; - name = '${androidInfo.brand}-${androidInfo.model}'; - id = androidInfo.id.hashCode.toString(); - } else { - IosDeviceInfo iosInfo = await deviceInfo.iosInfo; - name = iosInfo.utsname.machine; - id = iosInfo.identifierForVendor.hashCode.toString(); - } - setByName('info1', id); - setByName('info2', name); - setByName('init', _dir); - } catch (e) { - print(e); - } + static void setByName(String name, [String value = '']) { + PlatformFFI.setByName(name, value); } } @@ -775,10 +690,6 @@ void initializeCursorAndCanvas() async { FFI.canvasModel.update(xCanvas, yCanvas, scale); } -final locale = Platform.localeName; -final bool isCn = - locale.startsWith('zh') && (locale.endsWith('CN') || locale.endsWith('SG')); - final langs = >{ 'cn': { 'Remote ID': '远程ID', @@ -791,6 +702,9 @@ final langs = >{ 'en': {} }; +final bool isCn = localeName.startsWith('zh') && + (localeName.endsWith('CN') || localeName.endsWith('SG')); + String translate(String name) { if (name.startsWith('Failed') && name.contains(':')) { return name.split(': ').map((x) => translate(x)).join(': '); @@ -799,7 +713,7 @@ String translate(String name) { final v = tmp[name]; if (v == null) { var a = 'translate'; - var b = '{"locale": "${Platform.localeName}", "text": "$name"}'; + var b = '{"locale": "$localeName", "text": "$name"}'; return FFI.getByName(a, b); } else { return v; diff --git a/lib/native_model.dart b/lib/native_model.dart new file mode 100644 index 000000000..cee8bd0bb --- /dev/null +++ b/lib/native_model.dart @@ -0,0 +1,100 @@ +import 'dart:io'; +import 'dart:typed_data'; +import 'dart:ffi'; +import 'package:ffi/ffi.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:device_info/device_info.dart'; +import "common.dart"; + +class RgbaFrame extends Struct { + @Uint32() + int len; + Pointer data; +} + +typedef F2 = Pointer Function(Pointer, Pointer); +typedef F3 = void Function(Pointer, Pointer); +typedef F4 = void Function(Pointer); +typedef F5 = Pointer Function(); + +class PlatformFFI { + static Pointer _lastRgbaFrame; + static String _dir = ''; + static F2 _getByName; + static F3 _setByName; + static F4 _freeRgba; + static F5 _getRgba; + + static void clearRgbaFrame() { + if (_lastRgbaFrame != null && _lastRgbaFrame != nullptr) + _freeRgba(_lastRgbaFrame); + } + + static Uint8List getRgba() { + if (_getRgba == null) return null; + _lastRgbaFrame = _getRgba(); + if (_lastRgbaFrame == null || _lastRgbaFrame == nullptr) return null; + final ref = _lastRgbaFrame.ref; + return Uint8List.sublistView(ref.data.asTypedList(ref.len)); + } + + static String getByName(String name, [String arg = '']) { + if (_getByName == null) return ''; + var a = name.toNativeUtf8(); + var b = arg.toNativeUtf8(); + var p = _getByName(a, b); + assert(p != nullptr && p != null); + var res = p.toDartString(); + calloc.free(p); + calloc.free(a); + calloc.free(b); + return res; + } + + static void setByName(String name, [String value = '']) { + if (_setByName == null) return; + var a = name.toNativeUtf8(); + var b = value.toNativeUtf8(); + _setByName(a, b); + calloc.free(a); + calloc.free(b); + } + + static Future init() async { + isIOS = Platform.isIOS; + isAndroid = Platform.isAndroid; + final dylib = Platform.isAndroid + ? DynamicLibrary.open('librustdesk.so') + : DynamicLibrary.process(); + print('initializing FFI'); + try { + _getByName = dylib.lookupFunction('get_by_name'); + _setByName = + dylib.lookupFunction, Pointer), F3>( + 'set_by_name'); + _freeRgba = dylib + .lookupFunction), F4>('free_rgba'); + _getRgba = dylib.lookupFunction('get_rgba'); + _dir = (await getApplicationDocumentsDirectory()).path; + String id = 'NA'; + String name = 'Flutter'; + DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); + if (Platform.isAndroid) { + AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; + name = '${androidInfo.brand}-${androidInfo.model}'; + id = androidInfo.id.hashCode.toString(); + } else { + IosDeviceInfo iosInfo = await deviceInfo.iosInfo; + name = iosInfo.utsname.machine; + id = iosInfo.identifierForVendor.hashCode.toString(); + } + setByName('info1', id); + setByName('info2', name); + setByName('init', _dir); + } catch (e) { + print(e); + } + } +} + +final localeName = Platform.localeName; diff --git a/lib/remote_page.dart b/lib/remote_page.dart index d36be7155..c5733c83c 100644 --- a/lib/remote_page.dart +++ b/lib/remote_page.dart @@ -7,7 +7,7 @@ import 'dart:async'; import 'package:tuple/tuple.dart'; import 'package:wakelock/wakelock.dart'; import 'common.dart'; -import 'model.dart' if (dart.library.html) 'web_model.dart'; +import 'model.dart'; final initText = '\1' * 1024; @@ -485,7 +485,7 @@ class _RemotePageState extends State { } else if (value == 'touch_mode') { _touchMode = !_touchMode; final v = _touchMode ? 'Y' : ''; - FFI.setByName('peer_option', '{"name": "touch-mode", "value": "${v}"}'); + FFI.setByName('peer_option', '{"name": "touch-mode", "value": "$v"}'); } else if (value == 'reset_canvas') { FFI.cursorModel.reset(); } @@ -947,7 +947,7 @@ void showSetOSPassword(BuildContext context, bool login) { onPressed: () { var text = controller.text.trim(); FFI.setByName('peer_option', - '{"name": "os-password", "value": "${text}"}'); + '{"name": "os-password", "value": "$text"}'); FFI.setByName('peer_option', '{"name": "auto-login", "value": "${autoLogin ? 'Y' : ''}"}'); if (text != "" && login) { diff --git a/lib/web_model.dart b/lib/web_model.dart index c84d20059..6000401b3 100644 --- a/lib/web_model.dart +++ b/lib/web_model.dart @@ -1,700 +1,26 @@ -import 'package:path_provider/path_provider.dart'; -import 'package:shared_preferences/shared_preferences.dart'; -import 'package:device_info/device_info.dart'; -import 'dart:math'; -import 'dart:convert'; import 'dart:typed_data'; -import 'dart:ui' as ui; -import 'package:flutter/material.dart'; -import 'package:tuple/tuple.dart'; -import 'dart:async'; +import 'dart:js' as js; import 'common.dart'; -class FfiModel with ChangeNotifier { - PeerInfo _pi; - Display _display; - var _decoding = false; - bool _waitForImage; - bool _initialized = false; - final _permissions = Map(); - bool _secure; - bool _direct; - - get permissions => _permissions; - get initialized => _initialized; - get display => _display; - get secure => _secure; - get direct => _direct; - get pi => _pi; - - FfiModel() { - isIOS = false; - isAndroid = false; - isWeb = true; - Translator.call = translate; - clear(); - () async { - await FFI.init(); - _initialized = true; - print("FFI initialized"); - notifyListeners(); - }(); - } - - void updatePermission(Map evt) { - evt.forEach((k, v) { - if (k == 'name') return; - _permissions[k] = v == 'true'; - }); - print('$_permissions'); - } - - bool keyboard() => _permissions['keyboard'] != false; - - void clear() { - _pi = PeerInfo(); - _display = Display(); - _waitForImage = false; - _secure = null; - _direct = null; - clearPermissions(); - } - - void setConnectionType(bool secure, bool direct) { - _secure = secure; - _direct = direct; - } - - Image getConnectionImage() { - String icon; - if (secure == true && direct == true) { - icon = 'secure'; - } else if (secure == false && direct == true) { - icon = 'insecure'; - } else if (secure == false && direct == false) { - icon = 'insecure_relay'; - } else if (secure == true && direct == false) { - icon = 'secure_relay'; - } - return icon == null - ? null - : Image.asset('assets/$icon.png', width: 48, height: 48); - } - - void clearPermissions() { - _permissions.clear(); - } - - void update( - String id, - BuildContext context, - void Function( - Map evt, - String id, - ) - handleMsgbox) { - var pos; - for (;;) { - var evt = FFI.popEvent(); - if (evt == null) break; - var name = evt['name']; - if (name == 'msgbox') { - handleMsgbox(evt, id); - } else if (name == 'peer_info') { - handlePeerInfo(evt, context); - } else if (name == 'connection_ready') { - FFI.ffiModel.setConnectionType( - evt['secure'] == 'true', evt['direct'] == 'true'); - } else if (name == 'switch_display') { - handleSwitchDisplay(evt); - } else if (name == 'cursor_data') { - FFI.cursorModel.updateCursorData(evt); - } else if (name == 'cursor_id') { - FFI.cursorModel.updateCursorId(evt); - } else if (name == 'cursor_position') { - pos = evt; - } else if (name == 'clipboard') { - } else if (name == 'permission') { - FFI.ffiModel.updatePermission(evt); - } - } - if (pos != null) FFI.cursorModel.updateCursorPosition(pos); - if (!_decoding) { - var rgba = FFI.getRgba(); - if (rgba != null) { - if (_waitForImage) { - _waitForImage = false; - dismissLoading(); - } - _decoding = true; - final pid = FFI.id; - ui.decodeImageFromPixels( - rgba, _display.width, _display.height, ui.PixelFormat.bgra8888, - (image) { - FFI.clearRgbaFrame(); - _decoding = false; - if (FFI.id != pid) return; - try { - // my throw exception, because the listener maybe already dispose - FFI.imageModel.update(image); - } catch (e) { - print('update image: $e'); - } - }); - } - } - } - - void handleSwitchDisplay(Map evt) { - var old = _pi.currentDisplay; - _pi.currentDisplay = int.parse(evt['display']); - _display.x = double.parse(evt['x']); - _display.y = double.parse(evt['y']); - _display.width = int.parse(evt['width']); - _display.height = int.parse(evt['height']); - if (old != _pi.currentDisplay) - FFI.cursorModel.updateDisplayOrigin(_display.x, _display.y); - notifyListeners(); - } - - void handlePeerInfo(Map evt, BuildContext context) { - dismissLoading(); - _pi.version = evt['version']; - _pi.username = evt['username']; - _pi.hostname = evt['hostname']; - _pi.platform = evt['platform']; - _pi.sasEnabled = evt['sas_enabled'] == "true"; - _pi.currentDisplay = int.parse(evt['current_display']); - List displays = json.decode(evt['displays']); - _pi.displays = []; - for (int i = 0; i < displays.length; ++i) { - Map d0 = displays[i]; - var d = Display(); - d.x = d0['x'].toDouble(); - d.y = d0['y'].toDouble(); - d.width = d0['width']; - d.height = d0['height']; - _pi.displays.add(d); - } - if (_pi.currentDisplay < _pi.displays.length) { - _display = _pi.displays[_pi.currentDisplay]; - initializeCursorAndCanvas(); - } - if (displays.length > 0) { - showLoading(translate('Connected, waiting for image...'), context); - _waitForImage = true; - } - notifyListeners(); - } -} - -class ImageModel with ChangeNotifier { - ui.Image _image; - - ui.Image get image => _image; - - void update(ui.Image image) { - if (_image == null && image != null) { - final size = MediaQueryData.fromWindow(ui.window).size; - final xscale = size.width / image.width; - final yscale = size.height / image.height; - FFI.canvasModel.scale = max(xscale, yscale); - } - _image = image; - if (image != null) notifyListeners(); - } - - double get maxScale { - if (_image == null) return 1.0; - final size = MediaQueryData.fromWindow(ui.window).size; - final xscale = size.width / _image.width; - final yscale = size.height / _image.height; - return max(1.0, max(xscale, yscale)); - } - - double get minScale { - if (_image == null) return 1.0; - final size = MediaQueryData.fromWindow(ui.window).size; - final xscale = size.width / _image.width; - final yscale = size.height / _image.height; - return min(xscale, yscale); - } -} - -class CanvasModel with ChangeNotifier { - double _x; - double _y; - double _scale; - - CanvasModel() { - clear(); - } - - double get x => _x; - double get y => _y; - double get scale => _scale; - - void update(double x, double y, double scale) { - _x = x; - _y = y; - _scale = scale; - notifyListeners(); - } - - set scale(v) { - _scale = v; - notifyListeners(); - } - - void panX(double dx) { - _x += dx; - notifyListeners(); - } - - void resetOffset() { - _x = 0; - _y = 0; - notifyListeners(); - } - - void panY(double dy) { - _y += dy; - notifyListeners(); - } - - void updateScale(double v) { - if (FFI.imageModel.image == null) return; - final offset = FFI.cursorModel.offset; - var r = FFI.cursorModel.getVisibleRect(); - final px0 = (offset.dx - r.left) * _scale; - final py0 = (offset.dy - r.top) * _scale; - _scale *= v; - final maxs = FFI.imageModel.maxScale; - final mins = FFI.imageModel.minScale; - if (_scale > maxs) _scale = maxs; - if (_scale < mins) _scale = mins; - r = FFI.cursorModel.getVisibleRect(); - final px1 = (offset.dx - r.left) * _scale; - final py1 = (offset.dy - r.top) * _scale; - _x -= px1 - px0; - _y -= py1 - py0; - notifyListeners(); - } - - void clear([bool notify = false]) { - _x = 0; - _y = 0; - _scale = 1.0; - if (notify) notifyListeners(); - } -} - -class CursorModel with ChangeNotifier { - ui.Image _image; - final _images = Map>(); - double _x = -10000; - double _y = -10000; - double _hotx = 0; - double _hoty = 0; - double _displayOriginX = 0; - double _displayOriginY = 0; - - ui.Image get image => _image; - double get x => _x - _displayOriginX; - double get y => _y - _displayOriginY; - Offset get offset => Offset(_x, _y); - double get hotx => _hotx; - double get hoty => _hoty; - - // remote physical display coordinate - Rect getVisibleRect() { - final size = MediaQueryData.fromWindow(ui.window).size; - final xoffset = FFI.canvasModel.x; - final yoffset = FFI.canvasModel.y; - final scale = FFI.canvasModel.scale; - final x0 = _displayOriginX - xoffset / scale; - final y0 = _displayOriginY - yoffset / scale; - return Rect.fromLTWH(x0, y0, size.width / scale, size.height / scale); - } - - double adjustForKeyboard() { - final m = MediaQueryData.fromWindow(ui.window); - var keyboardHeight = m.viewInsets.bottom; - final size = m.size; - if (keyboardHeight < 100) return 0; - final s = FFI.canvasModel.scale; - final thresh = (size.height - keyboardHeight) / 2; - var h = (_y - getVisibleRect().top) * s; // local physical display height - return h - thresh; - } - - void touch(double x, double y, bool right) { - final scale = FFI.canvasModel.scale; - final xoffset = FFI.canvasModel.x; - final yoffset = FFI.canvasModel.y; - _x = (x - xoffset) / scale + _displayOriginX; - _y = (y - yoffset) / scale + _displayOriginY; - FFI.moveMouse(_x, _y); - FFI.tap(right); - notifyListeners(); - } - - void reset() { - _x = _displayOriginX; - _y = _displayOriginY; - FFI.moveMouse(_x, _y); - FFI.canvasModel.clear(true); - notifyListeners(); - } - - void updatePan(double dx, double dy, bool touchMode, bool drag) { - if (FFI.imageModel.image == null) return; - if (touchMode) { - if (drag) { - final scale = FFI.canvasModel.scale; - _x += dx / scale; - _y += dy / scale; - FFI.moveMouse(_x, _y); - notifyListeners(); - } else { - FFI.canvasModel.panX(dx); - FFI.canvasModel.panY(dy); - } - return; - } - final scale = FFI.canvasModel.scale; - dx /= scale; - dy /= scale; - final r = getVisibleRect(); - var cx = r.center.dx; - var cy = r.center.dy; - var tryMoveCanvasX = false; - if (dx > 0) { - final maxCanvasCanMove = - _displayOriginX + FFI.imageModel.image.width - r.right; - tryMoveCanvasX = _x + dx > cx && maxCanvasCanMove > 0; - if (tryMoveCanvasX) { - dx = min(dx, maxCanvasCanMove); - } else { - final maxCursorCanMove = r.right - _x; - dx = min(dx, maxCursorCanMove); - } - } else if (dx < 0) { - final maxCanvasCanMove = _displayOriginX - r.left; - tryMoveCanvasX = _x + dx < cx && maxCanvasCanMove < 0; - if (tryMoveCanvasX) { - dx = max(dx, maxCanvasCanMove); - } else { - final maxCursorCanMove = r.left - _x; - dx = max(dx, maxCursorCanMove); - } - } - var tryMoveCanvasY = false; - if (dy > 0) { - final mayCanvasCanMove = - _displayOriginY + FFI.imageModel.image.height - r.bottom; - tryMoveCanvasY = _y + dy > cy && mayCanvasCanMove > 0; - if (tryMoveCanvasY) { - dy = min(dy, mayCanvasCanMove); - } else { - final mayCursorCanMove = r.bottom - _y; - dy = min(dy, mayCursorCanMove); - } - } else if (dy < 0) { - final mayCanvasCanMove = _displayOriginY - r.top; - tryMoveCanvasY = _y + dy < cy && mayCanvasCanMove < 0; - if (tryMoveCanvasY) { - dy = max(dy, mayCanvasCanMove); - } else { - final mayCursorCanMove = r.top - _y; - dy = max(dy, mayCursorCanMove); - } - } - - if (dx == 0 && dy == 0) return; - _x += dx; - _y += dy; - if (tryMoveCanvasX && dx != 0) { - FFI.canvasModel.panX(-dx); - } - if (tryMoveCanvasY && dy != 0) { - FFI.canvasModel.panY(-dy); - } - - FFI.moveMouse(_x, _y); - notifyListeners(); - } - - void updateCursorData(Map evt) { - var id = int.parse(evt['id']); - _hotx = double.parse(evt['hotx']); - _hoty = double.parse(evt['hoty']); - var width = int.parse(evt['width']); - var height = int.parse(evt['height']); - List colors = json.decode(evt['colors']); - final rgba = Uint8List.fromList(colors.map((s) => s as int).toList()); - var pid = FFI.id; - ui.decodeImageFromPixels(rgba, width, height, ui.PixelFormat.rgba8888, - (image) { - if (FFI.id != pid) return; - _image = image; - _images[id] = Tuple3(image, _hotx, _hoty); - try { - // my throw exception, because the listener maybe already dispose - notifyListeners(); - } catch (e) { - print('notify cursor: $e'); - } - }); - } - - void updateCursorId(Map evt) { - final tmp = _images[int.parse(evt['id'])]; - if (tmp != null) { - _image = tmp.item1; - _hotx = tmp.item2; - _hoty = tmp.item3; - notifyListeners(); - } - } - - void updateCursorPosition(Map evt) { - _x = double.parse(evt['x']); - _y = double.parse(evt['y']); - notifyListeners(); - } - - void updateDisplayOrigin(double x, double y) { - _displayOriginX = x; - _displayOriginY = y; - _x = x + 1; - _y = y + 1; - FFI.moveMouse(x, y); - FFI.canvasModel.resetOffset(); - notifyListeners(); - } - - void updateDisplayOriginWithCursor( - double x, double y, double xCursor, double yCursor) { - _displayOriginX = x; - _displayOriginY = y; - _x = xCursor; - _y = yCursor; - FFI.moveMouse(x, y); - notifyListeners(); - } - - void clear() { - _x = -10000; - _x = -10000; - _image = null; - _images.clear(); - } -} - -class FFI { - static String id = ""; - static String _dir = ''; - static var shift = false; - static var ctrl = false; - static var alt = false; - static var command = false; - static final imageModel = ImageModel(); - static final ffiModel = FfiModel(); - static final cursorModel = CursorModel(); - static final canvasModel = CanvasModel(); - - static String getId() { - return getByName('remote_id'); - } - - static void tap(bool right) { - sendMouse('down', right ? 'right' : 'left'); - sendMouse('up', right ? 'right' : 'left'); - } - - static void scroll(double y) { - var y2 = y.round(); - if (y2 == 0) return; - setByName('send_mouse', - json.encode(modify({'type': 'wheel', 'y': y2.toString()}))); - } - - static void reconnect() { - setByName('reconnect'); - FFI.ffiModel.clearPermissions(); - } - - static void resetModifiers() { - shift = ctrl = alt = command = false; - } - - static Map modify(Map evt) { - if (ctrl) evt['ctrl'] = 'true'; - if (shift) evt['shift'] = 'true'; - if (alt) evt['alt'] = 'true'; - if (command) evt['command'] = 'true'; - return evt; - } - - static void sendMouse(String type, String buttons) { - if (!ffiModel.keyboard()) return; - setByName( - 'send_mouse', json.encode(modify({'type': type, 'buttons': buttons}))); - } - - static void inputKey(String name) { - if (!ffiModel.keyboard()) return; - setByName('input_key', json.encode(modify({'name': name}))); - } - - static void moveMouse(double x, double y) { - if (!ffiModel.keyboard()) return; - var x2 = x.toInt(); - var y2 = y.toInt(); - setByName('send_mouse', json.encode(modify({'x': '$x2', 'y': '$y2'}))); - } - - static List peers() { - try { - List peers = json.decode(getByName('peers')); - return peers - .map((s) => s as List) - .map((s) => - Peer.fromJson(s[0] as String, s[1] as Map)) - .toList(); - } catch (e) { - print('peers(): $e'); - } - return []; - } - - static void connect(String id) { - setByName('connect', id); - FFI.id = id; - } - +class PlatformFFI { static void clearRgbaFrame() {} - static Uint8List getRgba() {} - - static Map popEvent() { - var s = getByName('event'); - if (s == '') return null; - try { - Map event = json.decode(s); - return event; - } catch (e) { - print('popEvent(): $e'); - } - return null; + static Uint8List getRgba() { + return js.context.callMethod(js.context.callMethod('getRgba')); + // return Uint8List.sublistView(ref.data.asTypedList(ref.len)); } - static void login(String password, bool remember) { - setByName( - 'login', - json.encode({ - 'password': password, - 'remember': remember ? 'true' : 'false', - })); + static String getByName(String name, [String arg = '']) { + return js.context.callMethod('getByName', [name, arg]); } - static void close() { - savePreference(id, cursorModel.x, cursorModel.y, canvasModel.x, - canvasModel.y, canvasModel.scale, ffiModel.pi.currentDisplay); - id = ""; - setByName('close', ''); - imageModel.update(null); - cursorModel.clear(); - ffiModel.clear(); - canvasModel.clear(); - resetModifiers(); + static void setByName(String name, [String value = '']) { + js.context.callMethod('setByName', [name, value]); } - static void setByName(String name, [String value = '']) {} - - static String getByName(String name, [String arg = '']) {} - - static Future init() async {} -} - -class Peer { - final String id; - final String username; - final String hostname; - final String platform; - - Peer.fromJson(String id, Map json) - : id = id, - username = json['username'], - hostname = json['hostname'], - platform = json['platform']; -} - -class Display { - double x = 0; - double y = 0; - int width = 0; - int height = 0; -} - -class PeerInfo { - String version; - String username; - String hostname; - String platform; - bool sasEnabled; - int currentDisplay; - List displays; -} - -void savePreference(String id, double xCursor, double yCursor, double xCanvas, - double yCanvas, double scale, int currentDisplay) async { - SharedPreferences prefs = await SharedPreferences.getInstance(); - final p = Map(); - p['xCursor'] = xCursor; - p['yCursor'] = yCursor; - p['xCanvas'] = xCanvas; - p['yCanvas'] = yCanvas; - p['scale'] = scale; - p['currentDisplay'] = currentDisplay; - prefs.setString('peer' + id, json.encode(p)); -} - -Future> getPreference(String id) async { - SharedPreferences prefs = await SharedPreferences.getInstance(); - var p = prefs.getString('peer' + id); - if (p == null) return null; - Map m = json.decode(p); - return m; -} - -void removePreference(String id) async { - SharedPreferences prefs = await SharedPreferences.getInstance(); - prefs.remove('peer' + id); -} - -void initializeCursorAndCanvas() async { - var p = await getPreference(FFI.id); - int currentDisplay = 0; - if (p != null) { - currentDisplay = p['currentDisplay']; + static Future init() async { + isWeb = true; } - if (p == null || currentDisplay != FFI.ffiModel.pi.currentDisplay) { - FFI.cursorModel - .updateDisplayOrigin(FFI.ffiModel.display.x, FFI.ffiModel.display.y); - return; - } - double xCursor = p['xCursor']; - double yCursor = p['yCursor']; - double xCanvas = p['xCanvas']; - double yCanvas = p['yCanvas']; - double scale = p['scale']; - FFI.cursorModel.updateDisplayOriginWithCursor( - FFI.ffiModel.display.x, FFI.ffiModel.display.y, xCursor, yCursor); - FFI.canvasModel.update(xCanvas, yCanvas, scale); } -String translate(String name) { - return name; -} +final localeName = js.context.callMethod('getLanguage') as String; diff --git a/web/index.html b/web/index.html index 377445124..57cef37e2 100644 --- a/web/index.html +++ b/web/index.html @@ -31,6 +31,7 @@ RustDesk +