rustdesk/flutter_hbb/lib/common.dart

215 lines
5.3 KiB
Dart
Raw Normal View History

2020-11-15 20:04:05 +08:00
import 'package:flutter/material.dart';
2020-11-16 22:00:09 +08:00
import 'package:provider/provider.dart';
2020-11-15 20:04:05 +08:00
import 'package:ffi/ffi.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:io';
import 'dart:ffi';
import 'dart:async';
2020-11-16 11:36:53 +08:00
import 'dart:convert';
2020-11-16 21:21:27 +08:00
import 'package:flutter_easyloading/flutter_easyloading.dart';
2020-11-15 20:04:05 +08:00
class HexColor extends Color {
HexColor(final String hexColor) : super(_getColorFromHex(hexColor));
static int _getColorFromHex(String hexColor) {
hexColor = hexColor.toUpperCase().replaceAll('#', '');
if (hexColor.length == 6) {
hexColor = 'FF' + hexColor;
}
return int.parse(hexColor, radix: 16);
}
}
2020-11-16 01:13:26 +08:00
class MyTheme {
static const Color grayBg = Color(0xFFEEEEEE);
static const Color white = Color(0xFFFFFFFF);
2020-11-16 22:00:09 +08:00
static const Color accent = Color(0xFF0071FF);
2020-11-16 01:13:26 +08:00
}
typedef F1 = void Function(Pointer<Utf8>);
2020-11-16 22:00:09 +08:00
typedef F2 = Pointer<Utf8> Function(Pointer<Utf8>, Pointer<Utf8>);
2020-11-16 20:20:02 +08:00
typedef F3 = void Function(Pointer<Utf8>, Pointer<Utf8>);
2020-11-16 01:13:26 +08:00
2020-11-15 20:04:05 +08:00
// https://juejin.im/post/6844903864852807694
class FfiModel with ChangeNotifier {
2020-11-16 02:12:37 +08:00
F1 _freeCString;
2020-11-16 20:20:02 +08:00
F2 _getByName;
F3 _setByName;
2020-11-15 20:04:05 +08:00
FfiModel() {
initialzeFFI();
}
2020-11-17 00:47:27 +08:00
String getId() {
return getByName("remote_id");
}
List<Peer> peers() {
try {
List<dynamic> peers = json.decode(getByName("peers"));
return peers
.map((s) => s as List<dynamic>)
.map((s) =>
Peer.fromJson(s[0] as String, s[1] as Map<String, dynamic>))
.toList();
} catch (e) {
print(e);
}
return [];
}
2020-11-15 20:04:05 +08:00
void addRemote() {
notifyListeners();
}
void connect(String id) {
2020-11-16 20:20:02 +08:00
setByName("connect", id);
2020-11-17 00:47:27 +08:00
}
Map<String, String> popEvent() {
var s = getByName("event");
if (s == "") return null;
try {
Map<String, String> event = json.decode(s);
return event;
} catch (e) {
print(e);
}
return null;
}
void login(String password, bool remember) {
setByName(
"login",
json.encode({
"password": password,
"remember": remember ? "true" : "false",
}));
}
void close() {
setByName("close", "");
2020-11-16 20:20:02 +08:00
}
void setByName(String name, String value) {
_setByName(Utf8.toUtf8(name), Utf8.toUtf8(value));
}
2020-11-16 22:00:09 +08:00
String getByName(String name, {String arg = ""}) {
var p = _getByName(Utf8.toUtf8(name), Utf8.toUtf8(arg));
2020-11-17 00:47:27 +08:00
assert(p != null);
2020-11-16 20:20:02 +08:00
var res = Utf8.fromUtf8(p);
// https://github.com/brickpop/flutter-rust-ffi
_freeCString(p);
return res;
2020-11-15 20:04:05 +08:00
}
Future<Null> initialzeFFI() async {
final dylib = Platform.isAndroid
? DynamicLibrary.open('librustdesk.so')
: DynamicLibrary.process();
2020-11-16 20:20:02 +08:00
_getByName = dylib.lookupFunction<F2, F2>('get_by_name');
_setByName =
dylib.lookupFunction<Void Function(Pointer<Utf8>, Pointer<Utf8>), F3>(
'set_by_name');
2020-11-16 02:12:37 +08:00
_freeCString = dylib
.lookupFunction<Void Function(Pointer<Utf8>), F1>('rust_cstr_free');
2020-11-15 20:04:05 +08:00
final dir = (await getApplicationDocumentsDirectory()).path;
2020-11-16 20:20:02 +08:00
setByName("init", dir);
2020-11-15 20:04:05 +08:00
notifyListeners();
}
}
2020-11-16 11:36:53 +08:00
class Peer {
2020-11-16 20:20:02 +08:00
final String id;
final String username;
final String hostname;
final String platform;
2020-11-16 11:36:53 +08:00
2020-11-16 20:20:02 +08:00
Peer.fromJson(String id, Map<String, dynamic> json)
: id = id,
username = json['username'],
hostname = json['hostname'],
platform = json['platform'];
2020-11-16 11:36:53 +08:00
}
2020-11-16 21:21:27 +08:00
// https://github.com/huangjianke/flutter_easyloading
void showLoading(String text) {
EasyLoading.show(status: text);
}
void dismissLoading() {
EasyLoading.dismiss();
}
2020-11-16 22:00:09 +08:00
2020-11-16 22:12:32 +08:00
void showSuccess(String text) {
EasyLoading.showSuccess(text);
}
2020-11-16 22:14:50 +08:00
// https://material.io/develop/flutter/components/dialogs
2020-11-16 22:14:29 +08:00
void enterPasswordDialog(String id, BuildContext context) {
2020-11-16 22:00:09 +08:00
var ffi = Provider.of<FfiModel>(context);
var remember = ffi.getByName("remember", arg: id) == "true";
2020-11-16 22:14:29 +08:00
var dialog = AlertDialog(
2020-11-16 22:00:09 +08:00
title: Text('Please enter your password'),
contentPadding: EdgeInsets.zero,
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
obscureText: true,
decoration: const InputDecoration(
labelText: 'Password',
),
),
ListTile(
title: Text(
'Remember the password',
),
leading: Checkbox(
value: remember,
onChanged: (_) {},
),
),
],
),
actions: [
FlatButton(
textColor: MyTheme.accent,
onPressed: () => Navigator.pop(context),
child: Text('Cancel'),
),
FlatButton(
textColor: MyTheme.accent,
onPressed: () => Navigator.pop(context),
child: Text('OK'),
),
],
);
2020-11-16 22:14:29 +08:00
showDialog<void>(context: context, builder: (context) => dialog);
2020-11-16 22:00:09 +08:00
}
2020-11-16 22:12:32 +08:00
2020-11-16 22:14:29 +08:00
void wrongPasswordDialog(String id, BuildContext context) {
var dialog = AlertDialog(
2020-11-16 22:12:32 +08:00
title: Text('Please enter your password'),
contentPadding: EdgeInsets.zero,
content: Text('Do you want to enter again?'),
actions: [
FlatButton(
textColor: MyTheme.accent,
onPressed: () => Navigator.pop(context),
child: Text('Cancel'),
),
FlatButton(
textColor: MyTheme.accent,
onPressed: () {
Navigator.pop(context);
enterPasswordDialog(id, context);
},
child: Text('Retry'),
),
],
);
2020-11-16 22:14:29 +08:00
showDialog<void>(context: context, builder: (context) => dialog);
2020-11-16 22:12:32 +08:00
}