2020-11-17 01:22:14 +08:00
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'common.dart';
|
|
|
|
import 'package:flutter/services.dart';
|
2020-11-17 11:12:55 +08:00
|
|
|
import 'dart:ui' as ui;
|
2020-11-17 12:08:31 +08:00
|
|
|
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
2020-11-18 16:11:19 +08:00
|
|
|
import 'dart:convert';
|
2020-11-17 12:08:31 +08:00
|
|
|
import 'dart:async';
|
2020-11-17 01:22:14 +08:00
|
|
|
|
|
|
|
class RemotePage extends StatefulWidget {
|
|
|
|
RemotePage({Key key, this.id}) : super(key: key);
|
|
|
|
|
|
|
|
final String id;
|
|
|
|
|
|
|
|
@override
|
|
|
|
_RemotePageState createState() => _RemotePageState();
|
|
|
|
}
|
|
|
|
|
2020-11-17 12:08:31 +08:00
|
|
|
// https://github.com/hanxu317317/flutter_plan_demo/blob/master/lib/src/enter.dart
|
2020-11-17 01:22:14 +08:00
|
|
|
class _RemotePageState extends State<RemotePage> {
|
2020-11-17 12:08:31 +08:00
|
|
|
Timer _interval;
|
2020-11-18 16:11:19 +08:00
|
|
|
ui.Image _image;
|
|
|
|
PeerInfo _pi = PeerInfo();
|
|
|
|
Display _display = Display();
|
2020-11-18 18:12:43 +08:00
|
|
|
bool _decoding = false;
|
2020-11-17 12:08:31 +08:00
|
|
|
|
2020-11-17 11:12:55 +08:00
|
|
|
@override
|
|
|
|
void initState() {
|
|
|
|
super.initState();
|
|
|
|
FFI.connect(widget.id);
|
2020-11-17 12:08:31 +08:00
|
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
2020-11-18 18:20:13 +08:00
|
|
|
// https://stackoverflow.com/questions/46640116/make-flutter-application-fullscreen
|
|
|
|
SystemChrome.setEnabledSystemUIOverlays([]);
|
2020-11-18 00:28:55 +08:00
|
|
|
showLoading('Connecting...');
|
2020-11-17 12:08:31 +08:00
|
|
|
_interval =
|
|
|
|
Timer.periodic(Duration(milliseconds: 30), (timer) => interval());
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
void dispose() {
|
|
|
|
super.dispose();
|
2020-11-17 12:41:23 +08:00
|
|
|
FFI.close();
|
2020-11-17 12:08:31 +08:00
|
|
|
_interval.cancel();
|
|
|
|
dismissLoading();
|
2020-11-18 18:12:43 +08:00
|
|
|
_decoding = null;
|
2020-11-18 18:20:13 +08:00
|
|
|
SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
|
2020-11-17 12:08:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void interval() {
|
2020-11-17 16:53:02 +08:00
|
|
|
var evt = FFI.popEvent();
|
2020-11-18 16:11:19 +08:00
|
|
|
if (evt != null) {
|
|
|
|
var name = evt['name'];
|
|
|
|
if (name == 'msgbox') {
|
|
|
|
handleMsgbox(evt);
|
|
|
|
} else if (name == 'peer_info') {
|
|
|
|
handlePeerInfo(evt);
|
|
|
|
} else if (name == 'switch_display') {
|
|
|
|
handleSwitchDisplay(evt);
|
|
|
|
}
|
2020-11-17 16:53:02 +08:00
|
|
|
}
|
2020-11-18 18:12:43 +08:00
|
|
|
if (!_decoding) {
|
|
|
|
var rgba = FFI.getRgba();
|
|
|
|
if (rgba != null) {
|
|
|
|
_decoding = true;
|
|
|
|
ui.decodeImageFromPixels(
|
|
|
|
rgba, _display.width, _display.height, ui.PixelFormat.bgra8888,
|
|
|
|
(__image) {
|
|
|
|
FFI.clearRgbaFrame();
|
|
|
|
if (_decoding == null) return;
|
|
|
|
_decoding = false;
|
|
|
|
setState(() {
|
|
|
|
_image = __image;
|
|
|
|
});
|
2020-11-18 00:28:55 +08:00
|
|
|
});
|
2020-11-18 18:12:43 +08:00
|
|
|
}
|
2020-11-18 00:28:55 +08:00
|
|
|
}
|
2020-11-17 16:53:02 +08:00
|
|
|
}
|
|
|
|
|
2020-11-18 16:11:19 +08:00
|
|
|
void handleSwitchDisplay(Map<String, dynamic> evt) {
|
|
|
|
_pi.currentDisplay = int.parse(evt['display']);
|
|
|
|
_display.x = int.parse(evt['x']);
|
|
|
|
_display.y = int.parse(evt['y']);
|
|
|
|
_display.width = int.parse(evt['width']);
|
|
|
|
_display.height = int.parse(evt['height']);
|
|
|
|
setState(() {});
|
|
|
|
}
|
|
|
|
|
|
|
|
void handlePeerInfo(Map<String, dynamic> evt) {
|
|
|
|
dismissLoading();
|
|
|
|
_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<dynamic> displays = json.decode(evt['displays']);
|
|
|
|
_pi.displays = List<Display>();
|
|
|
|
for (int i = 0; i < displays.length; ++i) {
|
|
|
|
Map<String, dynamic> d0 = displays[i];
|
|
|
|
var d = Display();
|
|
|
|
d.x = d0['x'];
|
|
|
|
d.y = d0['y'];
|
|
|
|
d.width = d0['width'];
|
|
|
|
d.height = d0['height'];
|
|
|
|
_pi.displays.add(d);
|
|
|
|
}
|
|
|
|
if (_pi.currentDisplay < _pi.displays.length) {
|
|
|
|
_display = _pi.displays[_pi.currentDisplay];
|
|
|
|
}
|
|
|
|
setState(() {});
|
|
|
|
}
|
|
|
|
|
2020-11-18 01:55:26 +08:00
|
|
|
void handleMsgbox(Map<String, dynamic> evt) {
|
2020-11-18 00:28:55 +08:00
|
|
|
var type = evt['type'];
|
|
|
|
var title = evt['title'];
|
|
|
|
var text = evt['text'];
|
2020-11-18 01:55:26 +08:00
|
|
|
if (type == 're-input-password') {
|
2020-11-18 00:28:55 +08:00
|
|
|
wrongPasswordDialog(widget.id, context);
|
|
|
|
} else if (type == 'input-password') {
|
|
|
|
enterPasswordDialog(widget.id, context);
|
2020-11-18 01:55:26 +08:00
|
|
|
} else {
|
|
|
|
msgbox(type, title, text, context);
|
2020-11-18 00:28:55 +08:00
|
|
|
}
|
2020-11-17 11:12:55 +08:00
|
|
|
}
|
2020-11-17 01:22:14 +08:00
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
2020-11-17 12:08:31 +08:00
|
|
|
// Size size = MediaQueryData.fromWindow(ui.window).size;
|
2020-11-17 12:41:23 +08:00
|
|
|
// MediaQuery.of(context).size.height;
|
2020-11-17 12:08:31 +08:00
|
|
|
return FlutterEasyLoading(
|
2020-11-18 17:36:11 +08:00
|
|
|
child: InteractiveViewer(
|
|
|
|
constrained: false,
|
|
|
|
panEnabled: true,
|
|
|
|
onInteractionUpdate: (details) {
|
|
|
|
print("$details");
|
|
|
|
},
|
|
|
|
child: Container(
|
|
|
|
child: CustomPaint(
|
|
|
|
painter: new ImageEditor(image: _image),
|
|
|
|
),
|
|
|
|
color: MyTheme.grayBg),
|
|
|
|
));
|
2020-11-17 11:12:55 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class ImageEditor extends CustomPainter {
|
|
|
|
ImageEditor({
|
|
|
|
this.image,
|
|
|
|
});
|
|
|
|
|
|
|
|
ui.Image image;
|
|
|
|
|
|
|
|
@override
|
|
|
|
void paint(Canvas canvas, Size size) {
|
2020-11-17 12:08:31 +08:00
|
|
|
if (image == null) return;
|
2020-11-18 17:36:11 +08:00
|
|
|
canvas.drawImage(image, new Offset(0, 0), new Paint());
|
2020-11-17 11:12:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
bool shouldRepaint(CustomPainter oldDelegate) {
|
2020-11-17 12:08:31 +08:00
|
|
|
return oldDelegate != this;
|
2020-11-17 01:22:14 +08:00
|
|
|
}
|
|
|
|
}
|
2020-11-18 16:11:19 +08:00
|
|
|
|
|
|
|
class Display {
|
|
|
|
int x = 0;
|
|
|
|
int y = 0;
|
|
|
|
int width = 0;
|
|
|
|
int height = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
class PeerInfo {
|
|
|
|
String username;
|
|
|
|
String hostname;
|
|
|
|
String platform;
|
|
|
|
bool sasEnabled;
|
|
|
|
int currentDisplay;
|
|
|
|
List<Display> displays;
|
|
|
|
}
|