refactor set/getByName "peers" "option"
This commit is contained in:
parent
0ef1659b87
commit
c5d0628291
@ -391,3 +391,10 @@ Future<void> initGlobalFFI() async {
|
||||
// global shared preference
|
||||
await Get.putAsync(() => SharedPreferences.getInstance());
|
||||
}
|
||||
|
||||
String translate(String name) {
|
||||
if (name.startsWith('Failed to') && name.contains(': ')) {
|
||||
return name.split(': ').map((x) => translate(x)).join(': ');
|
||||
}
|
||||
return platformFFI.translate(name, localeName);
|
||||
}
|
||||
|
@ -44,13 +44,22 @@ class _ConnectionPageState extends State<ConnectionPage> {
|
||||
|
||||
/// Update url. If it's not null, means an update is available.
|
||||
var _updateUrl = '';
|
||||
var _menuPos;
|
||||
|
||||
Timer? _updateTimer;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
if (_idController.text.isEmpty) {
|
||||
() async {
|
||||
final lastRemoteId = await bind.mainGetLastRemoteId();
|
||||
if (lastRemoteId != _idController.text) {
|
||||
setState(() {
|
||||
_idController.text = lastRemoteId;
|
||||
});
|
||||
}
|
||||
}();
|
||||
}
|
||||
_updateTimer = Timer.periodic(Duration(seconds: 1), (timer) {
|
||||
updateStatus();
|
||||
});
|
||||
@ -58,7 +67,6 @@ class _ConnectionPageState extends State<ConnectionPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (_idController.text.isEmpty) _idController.text = gFFI.getId();
|
||||
return Container(
|
||||
decoration: BoxDecoration(color: isDarkTheme() ? null : MyTheme.grayBg),
|
||||
child: Column(
|
||||
@ -428,7 +436,7 @@ class _ConnectionPageState extends State<ConnectionPage> {
|
||||
}
|
||||
|
||||
updateStatus() async {
|
||||
svcStopped.value = gFFI.getOption("stop-service") == "Y";
|
||||
svcStopped.value = bind.mainGetOption(key: "stop-service") == "Y";
|
||||
final status =
|
||||
jsonDecode(await bind.mainGetConnectStatus()) as Map<String, dynamic>;
|
||||
svcStatusCode.value = status["status_num"];
|
||||
@ -444,7 +452,7 @@ class _ConnectionPageState extends State<ConnectionPage> {
|
||||
}
|
||||
|
||||
Future<Widget> buildAddressBook(BuildContext context) async {
|
||||
final token = await gFFI.getLocalOption('access_token');
|
||||
final token = await bind.mainGetLocalOption(key: 'access_token');
|
||||
if (token.trim().isEmpty) {
|
||||
return Center(
|
||||
child: InkWell(
|
||||
|
@ -7,7 +7,6 @@ import 'package:flutter/services.dart';
|
||||
import 'package:flutter_hbb/common.dart';
|
||||
import 'package:flutter_hbb/desktop/pages/connection_page.dart';
|
||||
import 'package:flutter_hbb/desktop/widgets/titlebar_widget.dart';
|
||||
import 'package:flutter_hbb/models/model.dart';
|
||||
import 'package:flutter_hbb/models/platform_model.dart';
|
||||
import 'package:flutter_hbb/models/server_model.dart';
|
||||
import 'package:get/get.dart';
|
||||
@ -156,6 +155,8 @@ class _DesktopHomePageState extends State<DesktopHomePage> with TrayListener {
|
||||
},
|
||||
onTap: () async {
|
||||
final userName = await gFFI.userModel.getUserName();
|
||||
final enabledInput = await bind.mainGetOption(key: 'enable-audio');
|
||||
final defaultInput = await gFFI.getDefaultAudioInput();
|
||||
var menu = <PopupMenuEntry>[
|
||||
genEnablePopupMenuItem(
|
||||
translate("Enable Keyboard/Mouse"),
|
||||
@ -173,7 +174,7 @@ class _DesktopHomePageState extends State<DesktopHomePage> with TrayListener {
|
||||
translate("Enable TCP Tunneling"),
|
||||
'enable-tunnel',
|
||||
),
|
||||
genAudioInputPopupMenuItem(),
|
||||
genAudioInputPopupMenuItem(enabledInput != "N", defaultInput),
|
||||
PopupMenuDivider(),
|
||||
PopupMenuItem(
|
||||
child: Text(translate("ID/Relay Server")),
|
||||
@ -465,49 +466,60 @@ class _DesktopHomePageState extends State<DesktopHomePage> with TrayListener {
|
||||
Get.find<SharedPreferences>().setString("darkTheme", choice);
|
||||
}
|
||||
|
||||
void onSelectMenu(String value) {
|
||||
if (value.startsWith('enable-')) {
|
||||
final option = gFFI.getOption(value);
|
||||
gFFI.setOption(value, option == "N" ? "" : "N");
|
||||
} else if (value.startsWith('allow-')) {
|
||||
final option = gFFI.getOption(value);
|
||||
void onSelectMenu(String key) async {
|
||||
if (key.startsWith('enable-')) {
|
||||
final option = await bind.mainGetOption(key: key);
|
||||
bind.mainSetOption(key: key, value: option == "N" ? "" : "N");
|
||||
} else if (key.startsWith('allow-')) {
|
||||
final option = await bind.mainGetOption(key: key);
|
||||
final choice = option == "Y" ? "" : "Y";
|
||||
gFFI.setOption(value, choice);
|
||||
bind.mainSetOption(key: key, value: choice);
|
||||
changeTheme(choice);
|
||||
} else if (value == "stop-service") {
|
||||
final option = gFFI.getOption(value);
|
||||
gFFI.setOption(value, option == "Y" ? "" : "Y");
|
||||
} else if (value == "change-id") {
|
||||
} else if (key == "stop-service") {
|
||||
final option = await bind.mainGetOption(key: key);
|
||||
bind.mainSetOption(key: key, value: option == "Y" ? "" : "Y");
|
||||
} else if (key == "change-id") {
|
||||
changeId();
|
||||
} else if (value == "custom-server") {
|
||||
} else if (key == "custom-server") {
|
||||
changeServer();
|
||||
} else if (value == "whitelist") {
|
||||
} else if (key == "whitelist") {
|
||||
changeWhiteList();
|
||||
} else if (value == "socks5-proxy") {
|
||||
} else if (key == "socks5-proxy") {
|
||||
changeSocks5Proxy();
|
||||
} else if (value == "about") {
|
||||
} else if (key == "about") {
|
||||
about();
|
||||
} else if (value == "logout") {
|
||||
} else if (key == "logout") {
|
||||
logOut();
|
||||
} else if (value == "login") {
|
||||
} else if (key == "login") {
|
||||
login();
|
||||
}
|
||||
}
|
||||
|
||||
PopupMenuItem<String> genEnablePopupMenuItem(String label, String value) {
|
||||
final v = gFFI.getOption(value);
|
||||
final isEnable = value.startsWith('enable-') ? v != "N" : v == "Y";
|
||||
PopupMenuItem<String> genEnablePopupMenuItem(String label, String key) {
|
||||
Future<bool> getOptionEnable(String key) async {
|
||||
final v = await bind.mainGetOption(key: key);
|
||||
return key.startsWith('enable-') ? v != "N" : v == "Y";
|
||||
}
|
||||
|
||||
return PopupMenuItem(
|
||||
child: Row(
|
||||
children: [
|
||||
Offstage(offstage: !isEnable, child: Icon(Icons.check)),
|
||||
Text(
|
||||
label,
|
||||
style: genTextStyle(isEnable),
|
||||
),
|
||||
],
|
||||
),
|
||||
value: value,
|
||||
child: FutureBuilder<bool>(
|
||||
future: getOptionEnable(key),
|
||||
builder: (context, snapshot) {
|
||||
var enable = false;
|
||||
if (snapshot.hasData && snapshot.data!) {
|
||||
enable = true;
|
||||
}
|
||||
return Row(
|
||||
children: [
|
||||
Offstage(offstage: !enable, child: Icon(Icons.check)),
|
||||
Text(
|
||||
label,
|
||||
style: genTextStyle(enable),
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
value: key,
|
||||
);
|
||||
}
|
||||
|
||||
@ -518,10 +530,11 @@ class _DesktopHomePageState extends State<DesktopHomePage> with TrayListener {
|
||||
color: Colors.redAccent, decoration: TextDecoration.lineThrough);
|
||||
}
|
||||
|
||||
PopupMenuItem<String> genAudioInputPopupMenuItem() {
|
||||
final _enabledInput = gFFI.getOption('enable-audio');
|
||||
var defaultInput = gFFI.getDefaultAudioInput().obs;
|
||||
var enabled = (_enabledInput != "N").obs;
|
||||
PopupMenuItem<String> genAudioInputPopupMenuItem(
|
||||
bool enableInput, String defaultAudioInput) {
|
||||
final defaultInput = defaultAudioInput.obs;
|
||||
final enabled = enableInput.obs;
|
||||
|
||||
return PopupMenuItem(
|
||||
child: FutureBuilder<List<String>>(
|
||||
future: gFFI.getAudioInputs(),
|
||||
@ -569,12 +582,13 @@ class _DesktopHomePageState extends State<DesktopHomePage> with TrayListener {
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(translate("Audio Input"))),
|
||||
itemBuilder: (context) => inputList,
|
||||
onSelected: (dev) {
|
||||
onSelected: (dev) async {
|
||||
if (dev == "Mute") {
|
||||
gFFI.setOption(
|
||||
'enable-audio', _enabledInput == 'N' ? '' : 'N');
|
||||
enabled.value = gFFI.getOption('enable-audio') != 'N';
|
||||
} else if (dev != gFFI.getDefaultAudioInput()) {
|
||||
await bind.mainSetOption(
|
||||
key: 'enable-audio', value: enabled.value ? '' : 'N');
|
||||
enabled.value =
|
||||
await bind.mainGetOption(key: 'enable-audio') != 'N';
|
||||
} else if (dev != await gFFI.getDefaultAudioInput()) {
|
||||
gFFI.setDefaultAudioInput(dev);
|
||||
defaultInput.value = dev;
|
||||
}
|
||||
|
@ -89,7 +89,8 @@ class _PeerCardState extends State<_PeerCard>
|
||||
children: [
|
||||
Expanded(
|
||||
child: FutureBuilder<String>(
|
||||
future: gFFI.getPeerOption(peer.id, 'alias'),
|
||||
future: bind.mainGetPeerOption(
|
||||
id: peer.id, key: 'alias'),
|
||||
builder: (_, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
final name = snapshot.data!.isEmpty
|
||||
@ -304,7 +305,7 @@ class _PeerCardState extends State<_PeerCard>
|
||||
|
||||
void _rename(String id) async {
|
||||
var isInProgress = false;
|
||||
var name = await gFFI.getPeerOption(id, 'alias');
|
||||
var name = await bind.mainGetPeerOption(id: id, key: 'alias');
|
||||
if (widget.type == PeerType.ab) {
|
||||
final peer = gFFI.abModel.peers.firstWhere((p) => id == p['id']);
|
||||
if (peer == null) {
|
||||
@ -359,7 +360,8 @@ class _PeerCardState extends State<_PeerCard>
|
||||
if (k.currentState != null) {
|
||||
if (k.currentState!.validate()) {
|
||||
k.currentState!.save();
|
||||
await gFFI.setPeerOption(id, 'alias', name);
|
||||
await bind.mainSetPeerOption(
|
||||
id: id, key: 'alias', value: name);
|
||||
if (widget.type == PeerType.ab) {
|
||||
gFFI.abModel.setPeerOption(id, 'alias', name);
|
||||
await gFFI.abModel.updateAb();
|
||||
|
@ -7,6 +7,8 @@ import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
import '../../common.dart';
|
||||
import '../../models/model.dart';
|
||||
import '../../models/peer_model.dart';
|
||||
import '../../models/platform_model.dart';
|
||||
import 'home_page.dart';
|
||||
import 'remote_page.dart';
|
||||
import 'scan_page.dart';
|
||||
@ -41,6 +43,16 @@ class _ConnectionPageState extends State<ConnectionPage> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
if (_idController.text.isEmpty) {
|
||||
() async {
|
||||
final lastRemoteId = await bind.mainGetLastRemoteId();
|
||||
if (lastRemoteId != _idController.text) {
|
||||
setState(() {
|
||||
_idController.text = lastRemoteId;
|
||||
});
|
||||
}
|
||||
}();
|
||||
}
|
||||
if (isAndroid) {
|
||||
Timer(Duration(seconds: 5), () {
|
||||
_updateUrl = gFFI.getByName('software_update_url');
|
||||
@ -52,7 +64,6 @@ class _ConnectionPageState extends State<ConnectionPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Provider.of<FfiModel>(context);
|
||||
if (_idController.text.isEmpty) _idController.text = gFFI.getId();
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
@ -221,44 +232,52 @@ class _ConnectionPageState extends State<ConnectionPage> {
|
||||
final n = (windowWidth / (minWidth + 2 * space)).floor();
|
||||
width = windowWidth / n - 2 * space;
|
||||
}
|
||||
final cards = <Widget>[];
|
||||
var peers = gFFI.peers();
|
||||
peers.forEach((p) {
|
||||
cards.add(Container(
|
||||
width: width,
|
||||
child: Card(
|
||||
child: GestureDetector(
|
||||
onTap: !isWebDesktop ? () => connect('${p.id}') : null,
|
||||
onDoubleTap: isWebDesktop ? () => connect('${p.id}') : null,
|
||||
onLongPressStart: (details) {
|
||||
final x = details.globalPosition.dx;
|
||||
final y = details.globalPosition.dy;
|
||||
_menuPos = RelativeRect.fromLTRB(x, y, x, y);
|
||||
showPeerMenu(context, p.id);
|
||||
},
|
||||
child: ListTile(
|
||||
contentPadding: const EdgeInsets.only(left: 12),
|
||||
subtitle: Text('${p.username}@${p.hostname}'),
|
||||
title: Text('${p.id}'),
|
||||
leading: Container(
|
||||
padding: const EdgeInsets.all(6),
|
||||
child: getPlatformImage('${p.platform}'),
|
||||
color: str2color('${p.id}${p.platform}', 0x7f)),
|
||||
trailing: InkWell(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Icon(Icons.more_vert)),
|
||||
onTapDown: (e) {
|
||||
final x = e.globalPosition.dx;
|
||||
final y = e.globalPosition.dy;
|
||||
_menuPos = RelativeRect.fromLTRB(x, y, x, y);
|
||||
},
|
||||
onTap: () {
|
||||
showPeerMenu(context, p.id);
|
||||
}),
|
||||
)))));
|
||||
});
|
||||
return Wrap(children: cards, spacing: space, runSpacing: space);
|
||||
return FutureBuilder<List<Peer>>(
|
||||
future: gFFI.peers(),
|
||||
builder: (context, snapshot) {
|
||||
final cards = <Widget>[];
|
||||
if (snapshot.hasData) {
|
||||
final peers = snapshot.data!;
|
||||
peers.forEach((p) {
|
||||
cards.add(Container(
|
||||
width: width,
|
||||
child: Card(
|
||||
child: GestureDetector(
|
||||
onTap:
|
||||
!isWebDesktop ? () => connect('${p.id}') : null,
|
||||
onDoubleTap:
|
||||
isWebDesktop ? () => connect('${p.id}') : null,
|
||||
onLongPressStart: (details) {
|
||||
final x = details.globalPosition.dx;
|
||||
final y = details.globalPosition.dy;
|
||||
_menuPos = RelativeRect.fromLTRB(x, y, x, y);
|
||||
showPeerMenu(context, p.id);
|
||||
},
|
||||
child: ListTile(
|
||||
contentPadding: const EdgeInsets.only(left: 12),
|
||||
subtitle: Text('${p.username}@${p.hostname}'),
|
||||
title: Text('${p.id}'),
|
||||
leading: Container(
|
||||
padding: const EdgeInsets.all(6),
|
||||
child: getPlatformImage('${p.platform}'),
|
||||
color: str2color('${p.id}${p.platform}', 0x7f)),
|
||||
trailing: InkWell(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Icon(Icons.more_vert)),
|
||||
onTapDown: (e) {
|
||||
final x = e.globalPosition.dx;
|
||||
final y = e.globalPosition.dy;
|
||||
_menuPos = RelativeRect.fromLTRB(x, y, x, y);
|
||||
},
|
||||
onTap: () {
|
||||
showPeerMenu(context, p.id);
|
||||
}),
|
||||
)))));
|
||||
});
|
||||
}
|
||||
return Wrap(children: cards, spacing: space, runSpacing: space);
|
||||
});
|
||||
}
|
||||
|
||||
/// Show the peer menu and handle user's choice.
|
||||
|
@ -9,7 +9,7 @@ import 'package:qr_code_scanner/qr_code_scanner.dart';
|
||||
import 'package:zxing2/qrcode.dart';
|
||||
|
||||
import '../../common.dart';
|
||||
import '../../models/model.dart';
|
||||
import '../../models/platform_model.dart';
|
||||
|
||||
class ScanPage extends StatefulWidget {
|
||||
@override
|
||||
@ -153,54 +153,80 @@ class _ScanPageState extends State<ScanPage> {
|
||||
}
|
||||
|
||||
void showServerSettingsWithValue(
|
||||
String id, String relay, String key, String api) {
|
||||
final formKey = GlobalKey<FormState>();
|
||||
final id0 = gFFI.getByName('option', 'custom-rendezvous-server');
|
||||
final relay0 = gFFI.getByName('option', 'relay-server');
|
||||
final api0 = gFFI.getByName('option', 'api-server');
|
||||
final key0 = gFFI.getByName('option', 'key');
|
||||
String id, String relay, String key, String api) async {
|
||||
Map<String, dynamic> oldOptions = jsonDecode(await bind.mainGetOptions());
|
||||
String id0 = oldOptions['custom-rendezvous-server'] ?? "";
|
||||
String relay0 = oldOptions['relay-server'] ?? "";
|
||||
String api0 = oldOptions['api-server'] ?? "";
|
||||
String key0 = oldOptions['key'] ?? "";
|
||||
var isInProgress = false;
|
||||
final idController = TextEditingController(text: id);
|
||||
final relayController = TextEditingController(text: relay);
|
||||
final apiController = TextEditingController(text: api);
|
||||
|
||||
String? idServerMsg;
|
||||
String? relayServerMsg;
|
||||
String? apiServerMsg;
|
||||
|
||||
DialogManager.show((setState, close) {
|
||||
Future<bool> validate() async {
|
||||
if (idController.text != id) {
|
||||
final res = await validateAsync(idController.text);
|
||||
setState(() => idServerMsg = res);
|
||||
if (idServerMsg != null) return false;
|
||||
id = idController.text;
|
||||
}
|
||||
if (relayController.text != relay) {
|
||||
relayServerMsg = await validateAsync(relayController.text);
|
||||
if (relayServerMsg != null) return false;
|
||||
relay = relayController.text;
|
||||
}
|
||||
if (apiController.text != relay) {
|
||||
apiServerMsg = await validateAsync(apiController.text);
|
||||
if (apiServerMsg != null) return false;
|
||||
api = apiController.text;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return CustomAlertDialog(
|
||||
title: Text(translate('ID/Relay Server')),
|
||||
content: Form(
|
||||
key: formKey,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
TextFormField(
|
||||
initialValue: id,
|
||||
controller: idController,
|
||||
decoration: InputDecoration(
|
||||
labelText: translate('ID Server'),
|
||||
),
|
||||
validator: validate,
|
||||
onSaved: (String? value) {
|
||||
if (value != null) id = value.trim();
|
||||
},
|
||||
labelText: translate('ID Server'),
|
||||
errorText: idServerMsg),
|
||||
)
|
||||
] +
|
||||
(isAndroid
|
||||
? [
|
||||
TextFormField(
|
||||
initialValue: relay,
|
||||
controller: relayController,
|
||||
decoration: InputDecoration(
|
||||
labelText: translate('Relay Server'),
|
||||
),
|
||||
validator: validate,
|
||||
onSaved: (String? value) {
|
||||
if (value != null) relay = value.trim();
|
||||
},
|
||||
labelText: translate('Relay Server'),
|
||||
errorText: relayServerMsg),
|
||||
)
|
||||
]
|
||||
: []) +
|
||||
[
|
||||
TextFormField(
|
||||
initialValue: api,
|
||||
controller: apiController,
|
||||
decoration: InputDecoration(
|
||||
labelText: translate('API Server'),
|
||||
),
|
||||
validator: validate,
|
||||
onSaved: (String? value) {
|
||||
if (value != null) api = value.trim();
|
||||
autovalidateMode: AutovalidateMode.onUserInteraction,
|
||||
validator: (v) {
|
||||
if (v != null && v.length > 0) {
|
||||
if (!(v.startsWith('http://') ||
|
||||
v.startsWith("https://"))) {
|
||||
return translate("invalid_http");
|
||||
}
|
||||
}
|
||||
return apiServerMsg;
|
||||
},
|
||||
),
|
||||
TextFormField(
|
||||
@ -208,11 +234,13 @@ void showServerSettingsWithValue(
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Key',
|
||||
),
|
||||
validator: null,
|
||||
onSaved: (String? value) {
|
||||
onChanged: (String? value) {
|
||||
if (value != null) key = value.trim();
|
||||
},
|
||||
),
|
||||
Offstage(
|
||||
offstage: !isInProgress,
|
||||
child: LinearProgressIndicator())
|
||||
])),
|
||||
actions: [
|
||||
TextButton(
|
||||
@ -224,24 +252,28 @@ void showServerSettingsWithValue(
|
||||
),
|
||||
TextButton(
|
||||
style: flatButtonStyle,
|
||||
onPressed: () {
|
||||
if (formKey.currentState != null &&
|
||||
formKey.currentState!.validate()) {
|
||||
formKey.currentState!.save();
|
||||
if (id != id0)
|
||||
gFFI.setByName('option',
|
||||
'{"name": "custom-rendezvous-server", "value": "$id"}');
|
||||
onPressed: () async {
|
||||
setState(() {
|
||||
idServerMsg = null;
|
||||
relayServerMsg = null;
|
||||
apiServerMsg = null;
|
||||
isInProgress = true;
|
||||
});
|
||||
if (await validate()) {
|
||||
if (id != id0) {
|
||||
bind.mainSetOption(key: "custom-rendezvous-server", value: id);
|
||||
}
|
||||
if (relay != relay0)
|
||||
gFFI.setByName(
|
||||
'option', '{"name": "relay-server", "value": "$relay"}');
|
||||
if (key != key0)
|
||||
gFFI.setByName('option', '{"name": "key", "value": "$key"}');
|
||||
bind.mainSetOption(key: "relay-server", value: relay);
|
||||
if (key != key0) bind.mainSetOption(key: "key", value: key);
|
||||
if (api != api0)
|
||||
gFFI.setByName(
|
||||
'option', '{"name": "api-server", "value": "$api"}');
|
||||
bind.mainSetOption(key: "api-server", value: api);
|
||||
gFFI.ffiModel.updateUser();
|
||||
close();
|
||||
}
|
||||
setState(() {
|
||||
isInProgress = false;
|
||||
});
|
||||
},
|
||||
child: Text(translate('OK')),
|
||||
),
|
||||
@ -250,11 +282,11 @@ void showServerSettingsWithValue(
|
||||
});
|
||||
}
|
||||
|
||||
String? validate(value) {
|
||||
Future<String?> validateAsync(String value) async {
|
||||
value = value.trim();
|
||||
if (value.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
final res = gFFI.getByName('test_if_valid_server', value);
|
||||
final res = await bind.mainTestIfValidServer(server: value);
|
||||
return res.isEmpty ? null : res;
|
||||
}
|
||||
|
@ -185,11 +185,12 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
|
||||
}
|
||||
}
|
||||
|
||||
void showServerSettings() {
|
||||
final id = gFFI.getByName('option', 'custom-rendezvous-server');
|
||||
final relay = gFFI.getByName('option', 'relay-server');
|
||||
final api = gFFI.getByName('option', 'api-server');
|
||||
final key = gFFI.getByName('option', 'key');
|
||||
void showServerSettings() async {
|
||||
Map<String, dynamic> options = jsonDecode(await bind.mainGetOptions());
|
||||
String id = options['custom-rendezvous-server'] ?? "";
|
||||
String relay = options['relay-server'] ?? "";
|
||||
String api = options['api-server'] ?? "";
|
||||
String key = options['key'] ?? "";
|
||||
showServerSettingsWithValue(id, relay, key, api);
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ import 'dart:convert';
|
||||
|
||||
import 'package:dash_chat_2/dash_chat_2.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hbb/models/platform_model.dart';
|
||||
|
||||
import '../../mobile/widgets/overlay.dart';
|
||||
import 'model.dart';
|
||||
@ -72,7 +73,7 @@ class ChatModel with ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
receive(int id, String text) {
|
||||
receive(int id, String text) async {
|
||||
if (text.isEmpty) return;
|
||||
// first message show overlay icon
|
||||
if (chatIconOverlayEntry == null) {
|
||||
@ -82,7 +83,7 @@ class ChatModel with ChangeNotifier {
|
||||
if (id == clientModeID) {
|
||||
chatUser = ChatUser(
|
||||
firstName: _ffi.target?.ffiModel.pi.username,
|
||||
id: _ffi.target?.getId() ?? "",
|
||||
id: await bind.mainGetLastRemoteId(),
|
||||
);
|
||||
} else {
|
||||
final client = _ffi.target?.serverModel.clients[id];
|
||||
|
@ -444,7 +444,7 @@ class FileModel extends ChangeNotifier {
|
||||
items.items.forEach((from) async {
|
||||
_jobId++;
|
||||
await bind.sessionSendFiles(
|
||||
id: '${_ffi.target?.getId()}',
|
||||
id: await bind.mainGetLastRemoteId(),
|
||||
actId: _jobId,
|
||||
path: from.path,
|
||||
to: PathUtil.join(toPath, from.name, isWindows),
|
||||
|
@ -881,11 +881,6 @@ class FFI {
|
||||
this.qualityMonitorModel = QualityMonitorModel(WeakReference(this));
|
||||
}
|
||||
|
||||
/// Get the remote id for current client.
|
||||
String getId() {
|
||||
return getByName('remote_id'); // TODO
|
||||
}
|
||||
|
||||
/// Send a mouse tap event(down and up).
|
||||
void tap(MouseButtons button) {
|
||||
sendMouse('down', button);
|
||||
@ -963,9 +958,9 @@ class FFI {
|
||||
}
|
||||
|
||||
/// List the saved peers.
|
||||
List<Peer> peers() {
|
||||
Future<List<Peer>> peers() async {
|
||||
try {
|
||||
var str = getByName('peers'); // TODO
|
||||
var str = await bind.mainGetRecentPeers();
|
||||
if (str == "") return [];
|
||||
List<dynamic> peers = json.decode(str);
|
||||
return peers
|
||||
@ -1046,33 +1041,6 @@ class FFI {
|
||||
platformFFI.setByName(name, value);
|
||||
}
|
||||
|
||||
String getOption(String name) {
|
||||
return platformFFI.getByName("option", name);
|
||||
}
|
||||
|
||||
Future<String> getLocalOption(String name) {
|
||||
return bind.mainGetLocalOption(key: name);
|
||||
}
|
||||
|
||||
Future<void> setLocalOption(String key, String value) {
|
||||
return bind.mainSetLocalOption(key: key, value: value);
|
||||
}
|
||||
|
||||
Future<String> getPeerOption(String id, String key) {
|
||||
return bind.mainGetPeerOption(id: id, key: key);
|
||||
}
|
||||
|
||||
Future<void> setPeerOption(String id, String key, String value) {
|
||||
return bind.mainSetPeerOption(id: id, key: key, value: value);
|
||||
}
|
||||
|
||||
void setOption(String name, String value) {
|
||||
Map<String, String> res = Map()
|
||||
..["name"] = name
|
||||
..["value"] = value;
|
||||
return platformFFI.setByName('option', jsonEncode(res));
|
||||
}
|
||||
|
||||
handleMouse(Map<String, dynamic> evt, {double tabBarHeight = 0.0}) {
|
||||
var type = '';
|
||||
var isMove = false;
|
||||
@ -1148,8 +1116,8 @@ class FFI {
|
||||
return await bind.mainGetSoundInputs();
|
||||
}
|
||||
|
||||
String getDefaultAudioInput() {
|
||||
final input = getOption('audio-input');
|
||||
Future<String> getDefaultAudioInput() async {
|
||||
final input = await bind.mainGetOption(key: 'audio-input');
|
||||
if (input.isEmpty && Platform.isWindows) {
|
||||
return "System Sound";
|
||||
}
|
||||
@ -1157,11 +1125,14 @@ class FFI {
|
||||
}
|
||||
|
||||
void setDefaultAudioInput(String input) {
|
||||
setOption('audio-input', input);
|
||||
bind.mainSetOption(key: 'audio-input', value: input);
|
||||
}
|
||||
|
||||
Future<Map<String, String>> getHttpHeaders() async {
|
||||
return {"Authorization": "Bearer " + await getLocalOption("access_token")};
|
||||
return {
|
||||
"Authorization":
|
||||
"Bearer " + await bind.mainGetLocalOption(key: "access_token")
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -1233,11 +1204,12 @@ void initializeCursorAndCanvas(FFI ffi) async {
|
||||
/// Translate text based on the pre-defined dictionary.
|
||||
/// note: params [FFI?] can be used to replace global FFI implementation
|
||||
/// for example: during global initialization, gFFI not exists yet.
|
||||
String translate(String name, {FFI? ffi}) {
|
||||
if (name.startsWith('Failed to') && name.contains(': ')) {
|
||||
return name.split(': ').map((x) => translate(x)).join(': ');
|
||||
}
|
||||
var a = 'translate';
|
||||
var b = '{"locale": "$localeName", "text": "$name"}';
|
||||
return (ffi ?? gFFI).getByName(a, b);
|
||||
}
|
||||
// String translate(String name, {FFI? ffi}) {
|
||||
// if (name.startsWith('Failed to') && name.contains(': ')) {
|
||||
// return name.split(': ').map((x) => translate(x)).join(': ');
|
||||
// }
|
||||
// var a = 'translate';
|
||||
// var b = '{"locale": "$localeName", "text": "$name"}';
|
||||
//
|
||||
// return (ffi ?? gFFI).getByName(a, b);
|
||||
// }
|
||||
|
@ -29,6 +29,7 @@ typedef HandleEvent = void Function(Map<String, dynamic> evt);
|
||||
class PlatformFFI {
|
||||
String _dir = '';
|
||||
String _homeDir = '';
|
||||
F2? _translate;
|
||||
F2? _getByName;
|
||||
F3? _setByName;
|
||||
var _eventHandlers = Map<String, Map<String, HandleEvent>>();
|
||||
@ -75,6 +76,19 @@ class PlatformFFI {
|
||||
}
|
||||
}
|
||||
|
||||
String translate(String name, String locale) {
|
||||
if (_translate == null) return '';
|
||||
var a = name.toNativeUtf8();
|
||||
var b = locale.toNativeUtf8();
|
||||
var p = _translate!(a, b);
|
||||
assert(p != nullptr);
|
||||
final res = p.toDartString();
|
||||
calloc.free(p);
|
||||
calloc.free(a);
|
||||
calloc.free(b);
|
||||
return res;
|
||||
}
|
||||
|
||||
/// Send **get** command to the Rust core based on [name] and [arg].
|
||||
/// Return the result as a string.
|
||||
String getByName(String name, [String arg = '']) {
|
||||
@ -118,6 +132,7 @@ class PlatformFFI {
|
||||
: DynamicLibrary.process();
|
||||
debugPrint('initializing FFI ${_appType}');
|
||||
try {
|
||||
_translate = dylib.lookupFunction<F2, F2>('translate');
|
||||
_getByName = dylib.lookupFunction<F2, F2>('get_by_name');
|
||||
_setByName =
|
||||
dylib.lookupFunction<Void Function(Pointer<Utf8>, Pointer<Utf8>), F3>(
|
||||
|
@ -3,6 +3,7 @@ import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hbb/models/platform_model.dart';
|
||||
import 'package:wakelock/wakelock.dart';
|
||||
|
||||
import '../common.dart';
|
||||
@ -57,7 +58,7 @@ class ServerModel with ChangeNotifier {
|
||||
|
||||
set verificationMethod(String method) {
|
||||
_verificationMethod = method;
|
||||
gFFI.setOption("verification-method", method);
|
||||
bind.mainSetOption(key: "verification-method", value: method);
|
||||
}
|
||||
|
||||
String get temporaryPasswordLength {
|
||||
@ -70,7 +71,7 @@ class ServerModel with ChangeNotifier {
|
||||
|
||||
set temporaryPasswordLength(String length) {
|
||||
_temporaryPasswordLength = length;
|
||||
gFFI.setOption("temporary-password-length", length);
|
||||
bind.mainSetOption(key: "temporary-password-length", value: length);
|
||||
}
|
||||
|
||||
TextEditingController get serverId => _serverId;
|
||||
@ -85,7 +86,7 @@ class ServerModel with ChangeNotifier {
|
||||
|
||||
ServerModel(this.parent) {
|
||||
() async {
|
||||
_emptyIdShow = translate("Generating ...", ffi: this.parent.target);
|
||||
_emptyIdShow = translate("Generating ...");
|
||||
_serverId = TextEditingController(text: this._emptyIdShow);
|
||||
/**
|
||||
* 1. check android permission
|
||||
@ -153,11 +154,13 @@ class ServerModel with ChangeNotifier {
|
||||
});
|
||||
}
|
||||
|
||||
updatePasswordModel() {
|
||||
updatePasswordModel() async {
|
||||
var update = false;
|
||||
final temporaryPassword = gFFI.getByName("temporary_password");
|
||||
final verificationMethod = gFFI.getOption("verification-method");
|
||||
final temporaryPasswordLength = gFFI.getOption("temporary-password-length");
|
||||
final verificationMethod =
|
||||
await bind.mainGetOption(key: "verification-method");
|
||||
final temporaryPasswordLength =
|
||||
await bind.mainGetOption(key: "temporary-password-length");
|
||||
final oldPwdText = _serverPasswd.text;
|
||||
if (_serverPasswd.text != temporaryPassword) {
|
||||
_serverPasswd.text = temporaryPassword;
|
||||
@ -325,7 +328,7 @@ class ServerModel with ChangeNotifier {
|
||||
const maxCount = 10;
|
||||
while (count < maxCount) {
|
||||
await Future.delayed(Duration(seconds: 1));
|
||||
final id = parent.target?.getByName("server_id") ?? "";
|
||||
final id = await bind.mainGetMyId();
|
||||
if (id.isEmpty) {
|
||||
continue;
|
||||
} else {
|
||||
|
@ -1,8 +1,9 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter_hbb/models/model.dart';
|
||||
import 'package:tray_manager/tray_manager.dart';
|
||||
|
||||
import '../common.dart';
|
||||
|
||||
Future<void> initTray({List<MenuItem>? extra_item}) async {
|
||||
List<MenuItem> items = [
|
||||
MenuItem(key: "show", label: translate("show rustdesk")),
|
||||
|
@ -23,10 +23,10 @@ use crate::ui_interface;
|
||||
use crate::ui_interface::{change_id, check_connect_status, is_ok_change_id};
|
||||
use crate::ui_interface::{
|
||||
discover, forget_password, get_api_server, get_app_name, get_async_job_status,
|
||||
get_connect_status, get_fav, get_id, get_lan_peers, get_license, get_local_option, get_options,
|
||||
get_peer, get_peer_option, get_socks, get_sound_inputs, get_uuid, get_version,
|
||||
has_rendezvous_service, post_request, set_local_option, set_options, set_peer_option,
|
||||
set_socks, store_fav, test_if_valid_server, using_public_server,
|
||||
get_connect_status, get_fav, get_id, get_lan_peers, get_license, get_local_option, get_option,
|
||||
get_options, get_peer, get_peer_option, get_socks, get_sound_inputs, get_uuid, get_version,
|
||||
has_rendezvous_service, post_request, set_local_option, set_option, set_options,
|
||||
set_peer_option, set_socks, store_fav, test_if_valid_server, using_public_server,
|
||||
};
|
||||
|
||||
fn initialize(app_dir: &str) {
|
||||
@ -81,14 +81,24 @@ pub enum EventToUI {
|
||||
}
|
||||
|
||||
pub fn start_global_event_stream(s: StreamSink<String>, app_type: String) -> ResultType<()> {
|
||||
if let Some(_) = flutter::GLOBAL_EVENT_STREAM.write().unwrap().insert(app_type.clone(), s) {
|
||||
log::warn!("Global event stream of type {} is started before, but now removed", app_type);
|
||||
if let Some(_) = flutter::GLOBAL_EVENT_STREAM
|
||||
.write()
|
||||
.unwrap()
|
||||
.insert(app_type.clone(), s)
|
||||
{
|
||||
log::warn!(
|
||||
"Global event stream of type {} is started before, but now removed",
|
||||
app_type
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn stop_global_event_stream(app_type: String) {
|
||||
let _ = flutter::GLOBAL_EVENT_STREAM.write().unwrap().remove(&app_type);
|
||||
let _ = flutter::GLOBAL_EVENT_STREAM
|
||||
.write()
|
||||
.unwrap()
|
||||
.remove(&app_type);
|
||||
}
|
||||
|
||||
pub fn host_stop_system_key_propagate(stopped: bool) {
|
||||
@ -113,7 +123,6 @@ pub fn get_session_remember(id: String) -> Option<bool> {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO sync
|
||||
pub fn get_session_toggle_option(id: String, arg: String) -> Option<bool> {
|
||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
||||
Some(session.get_toggle_option(&arg))
|
||||
@ -143,7 +152,6 @@ pub fn get_session_option(id: String, arg: String) -> Option<String> {
|
||||
}
|
||||
}
|
||||
|
||||
// void
|
||||
pub fn session_login(id: String, password: String, remember: bool) {
|
||||
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
|
||||
session.login(&password, remember);
|
||||
@ -409,6 +417,26 @@ pub fn main_get_async_status() -> String {
|
||||
get_async_job_status()
|
||||
}
|
||||
|
||||
pub fn main_get_option(key: String) -> String {
|
||||
get_option(key)
|
||||
}
|
||||
|
||||
pub fn main_set_option(key: String, value: String) {
|
||||
if key.eq("custom-rendezvous-server") {
|
||||
set_option(key, value);
|
||||
#[cfg(target_os = "android")]
|
||||
crate::rendezvous_mediator::RendezvousMediator::restart();
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "ios",
|
||||
feature = "cli"
|
||||
))]
|
||||
crate::common::test_rendezvous_server();
|
||||
} else {
|
||||
set_option(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main_get_options() -> String {
|
||||
get_options()
|
||||
}
|
||||
@ -452,7 +480,7 @@ pub fn main_store_fav(favs: Vec<String>) {
|
||||
store_fav(favs)
|
||||
}
|
||||
|
||||
pub fn main_get_peers(id: String) -> String {
|
||||
pub fn main_get_peer(id: String) -> String {
|
||||
let conf = get_peer(id);
|
||||
serde_json::to_string(&conf).unwrap_or("".to_string())
|
||||
}
|
||||
@ -525,13 +553,30 @@ pub fn main_forget_password(id: String) {
|
||||
forget_password(id)
|
||||
}
|
||||
|
||||
// TODO APP_DIR & ui_interface
|
||||
pub fn main_get_recent_peers() -> String {
|
||||
if !config::APP_DIR.read().unwrap().is_empty() {
|
||||
let peers: Vec<(String, config::PeerInfoSerde)> = PeerConfig::peers()
|
||||
.drain(..)
|
||||
.map(|(id, _, p)| (id, p.info))
|
||||
.collect();
|
||||
serde_json::ser::to_string(&peers).unwrap_or("".to_owned())
|
||||
} else {
|
||||
String::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main_load_recent_peers() {
|
||||
if !config::APP_DIR.read().unwrap().is_empty() {
|
||||
let peers: Vec<(String, config::PeerInfoSerde)> = PeerConfig::peers()
|
||||
.drain(..)
|
||||
.map(|(id, _, p)| (id, p.info))
|
||||
.collect();
|
||||
if let Some(s) = flutter::GLOBAL_EVENT_STREAM.read().unwrap().get(flutter::APP_TYPE_MAIN) {
|
||||
if let Some(s) = flutter::GLOBAL_EVENT_STREAM
|
||||
.read()
|
||||
.unwrap()
|
||||
.get(flutter::APP_TYPE_MAIN)
|
||||
{
|
||||
let data = HashMap::from([
|
||||
("name", "load_recent_peers".to_owned()),
|
||||
(
|
||||
@ -557,7 +602,11 @@ pub fn main_load_fav_peers() {
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
if let Some(s) = flutter::GLOBAL_EVENT_STREAM.read().unwrap().get(flutter::APP_TYPE_MAIN) {
|
||||
if let Some(s) = flutter::GLOBAL_EVENT_STREAM
|
||||
.read()
|
||||
.unwrap()
|
||||
.get(flutter::APP_TYPE_MAIN)
|
||||
{
|
||||
let data = HashMap::from([
|
||||
("name", "load_fav_peers".to_owned()),
|
||||
(
|
||||
@ -571,7 +620,11 @@ pub fn main_load_fav_peers() {
|
||||
}
|
||||
|
||||
pub fn main_load_lan_peers() {
|
||||
if let Some(s) = flutter::GLOBAL_EVENT_STREAM.read().unwrap().get(flutter::APP_TYPE_MAIN) {
|
||||
if let Some(s) = flutter::GLOBAL_EVENT_STREAM
|
||||
.read()
|
||||
.unwrap()
|
||||
.get(flutter::APP_TYPE_MAIN)
|
||||
{
|
||||
let data = HashMap::from([
|
||||
("name", "load_lan_peers".to_owned()),
|
||||
("peers", get_lan_peers()),
|
||||
@ -580,6 +633,25 @@ pub fn main_load_lan_peers() {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn main_get_last_remote_id() -> String {
|
||||
// if !config::APP_DIR.read().unwrap().is_empty() {
|
||||
// res = LocalConfig::get_remote_id();
|
||||
// }
|
||||
LocalConfig::get_remote_id()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn translate(name: *const c_char, locale: *const c_char) -> *const c_char {
|
||||
let name = CStr::from_ptr(name);
|
||||
let locale = CStr::from_ptr(locale);
|
||||
let res = if let (Ok(name), Ok(locale)) = (name.to_str(), locale.to_str()) {
|
||||
crate::client::translate_locale(name.to_owned(), locale)
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
CString::from_vec_unchecked(res.into_bytes()).into_raw()
|
||||
}
|
||||
|
||||
/// FFI for **get** commands which are idempotent.
|
||||
/// Return result in c string.
|
||||
///
|
||||
@ -594,93 +666,41 @@ unsafe extern "C" fn get_by_name(name: *const c_char, arg: *const c_char) -> *co
|
||||
let name: &CStr = CStr::from_ptr(name);
|
||||
if let Ok(name) = name.to_str() {
|
||||
match name {
|
||||
"peers" => {
|
||||
if !config::APP_DIR.read().unwrap().is_empty() {
|
||||
let peers: Vec<(String, config::PeerInfoSerde)> = PeerConfig::peers()
|
||||
.drain(..)
|
||||
.map(|(id, _, p)| (id, p.info))
|
||||
.collect();
|
||||
res = serde_json::ser::to_string(&peers).unwrap_or("".to_owned());
|
||||
}
|
||||
}
|
||||
"remote_id" => {
|
||||
if !config::APP_DIR.read().unwrap().is_empty() {
|
||||
res = LocalConfig::get_remote_id();
|
||||
}
|
||||
}
|
||||
// "remember" => {
|
||||
// res = Session::get_remember().to_string();
|
||||
// }
|
||||
// "toggle_option" => {
|
||||
// if let Ok(arg) = arg.to_str() {
|
||||
// if let Some(v) = Session::get_toggle_option(arg) {
|
||||
// res = v.to_string();
|
||||
// }
|
||||
// "peers" => {
|
||||
// if !config::APP_DIR.read().unwrap().is_empty() {
|
||||
// let peers: Vec<(String, config::PeerInfoSerde)> = PeerConfig::peers()
|
||||
// .drain(..)
|
||||
// .map(|(id, _, p)| (id, p.info))
|
||||
// .collect();
|
||||
// res = serde_json::ser::to_string(&peers).unwrap_or("".to_owned());
|
||||
// }
|
||||
// }
|
||||
"test_if_valid_server" => {
|
||||
if let Ok(arg) = arg.to_str() {
|
||||
res = hbb_common::socket_client::test_if_valid_server(arg);
|
||||
}
|
||||
}
|
||||
"option" => {
|
||||
if let Ok(arg) = arg.to_str() {
|
||||
res = ui_interface::get_option(arg.to_owned());
|
||||
}
|
||||
}
|
||||
// "image_quality" => {
|
||||
// res = Session::get_image_quality();
|
||||
// "remote_id" => {
|
||||
// if !config::APP_DIR.read().unwrap().is_empty() {
|
||||
// res = LocalConfig::get_remote_id();
|
||||
// }
|
||||
// }
|
||||
// "test_if_valid_server" => {
|
||||
// if let Ok(arg) = arg.to_str() {
|
||||
// res = hbb_common::socket_client::test_if_valid_server(arg);
|
||||
// }
|
||||
// }
|
||||
// "option" => {
|
||||
// if let Ok(arg) = arg.to_str() {
|
||||
// res = ui_interface::get_option(arg.to_owned());
|
||||
// }
|
||||
// }
|
||||
"software_update_url" => {
|
||||
res = crate::common::SOFTWARE_UPDATE_URL.lock().unwrap().clone()
|
||||
}
|
||||
"translate" => {
|
||||
if let Ok(arg) = arg.to_str() {
|
||||
if let Ok(m) = serde_json::from_str::<HashMap<String, String>>(arg) {
|
||||
if let Some(locale) = m.get("locale") {
|
||||
if let Some(text) = m.get("text") {
|
||||
res = crate::client::translate_locale(text.to_owned(), locale);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// "peer_option" => {
|
||||
// if let Ok(arg) = arg.to_str() {
|
||||
// res = Session::get_option(arg);
|
||||
// }
|
||||
// }
|
||||
// File Action
|
||||
"get_home_dir" => {
|
||||
res = fs::get_home_as_string();
|
||||
}
|
||||
// "read_local_dir_sync" => {
|
||||
// if let Ok(value) = arg.to_str() {
|
||||
// if let Ok(m) = serde_json::from_str::<HashMap<String, String>>(value) {
|
||||
// if let (Some(path), Some(show_hidden)) =
|
||||
// (m.get("path"), m.get("show_hidden"))
|
||||
// {
|
||||
// if let Ok(fd) =
|
||||
// fs::read_dir(&fs::get_path(path), show_hidden.eq("true"))
|
||||
// {
|
||||
// res = make_fd_to_json(fd);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// Server Side
|
||||
"local_option" => {
|
||||
if let Ok(arg) = arg.to_str() {
|
||||
res = LocalConfig::get_option(arg);
|
||||
}
|
||||
}
|
||||
"langs" => {
|
||||
res = crate::lang::LANGS.to_string();
|
||||
}
|
||||
"server_id" => {
|
||||
res = ui_interface::get_id();
|
||||
}
|
||||
"temporary_password" => {
|
||||
res = ui_interface::temporary_password();
|
||||
}
|
||||
@ -709,9 +729,6 @@ unsafe extern "C" fn get_by_name(name: *const c_char, arg: *const c_char) -> *co
|
||||
}
|
||||
}
|
||||
}
|
||||
"uuid" => {
|
||||
res = base64::encode(get_uuid());
|
||||
}
|
||||
_ => {
|
||||
log::error!("Unknown name of get_by_name: {}", name);
|
||||
}
|
||||
@ -742,69 +759,9 @@ unsafe extern "C" fn set_by_name(name: *const c_char, value: *const c_char) {
|
||||
"info2" => {
|
||||
*crate::common::FLUTTER_INFO2.lock().unwrap() = value.to_owned();
|
||||
}
|
||||
// "connect" => {
|
||||
// Session::start(value, false);
|
||||
// }
|
||||
// "connect_file_transfer" => {
|
||||
// Session::start(value, true);
|
||||
// }
|
||||
// "login" => {
|
||||
// if let Ok(m) = serde_json::from_str::<HashMap<String, String>>(value) {
|
||||
// if let Some(password) = m.get("password") {
|
||||
// if let Some(remember) = m.get("remember") {
|
||||
// Session::login(password, remember == "true");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// "close" => {
|
||||
// Session::close();
|
||||
// }
|
||||
// "refresh" => {
|
||||
// Session::refresh();
|
||||
// }
|
||||
// "reconnect" => {
|
||||
// Session::reconnect();
|
||||
// }
|
||||
// "toggle_option" => {
|
||||
// Session::toggle_option(value);
|
||||
// }
|
||||
// "image_quality" => {
|
||||
// Session::set_image_quality(value);
|
||||
// }
|
||||
// "lock_screen" => {
|
||||
// Session::lock_screen();
|
||||
// }
|
||||
// "ctrl_alt_del" => {
|
||||
// Session::ctrl_alt_del();
|
||||
// }
|
||||
// "switch_display" => {
|
||||
// if let Ok(v) = value.parse::<i32>() {
|
||||
// Session::switch_display(v);
|
||||
// }
|
||||
// }
|
||||
"remove" => {
|
||||
PeerConfig::remove(value);
|
||||
}
|
||||
// "input_key" => {
|
||||
// if let Ok(m) = serde_json::from_str::<HashMap<String, String>>(value) {
|
||||
// let alt = m.get("alt").is_some();
|
||||
// let ctrl = m.get("ctrl").is_some();
|
||||
// let shift = m.get("shift").is_some();
|
||||
// let command = m.get("command").is_some();
|
||||
// let down = m.get("down").is_some();
|
||||
// let press = m.get("press").is_some();
|
||||
// if let Some(name) = m.get("name") {
|
||||
// Session::input_key(name, down, press, alt, ctrl, shift, command);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// "input_string" => {
|
||||
// Session::input_string(value);
|
||||
// }
|
||||
// "chat_client_mode" => {
|
||||
// Session::send_chat(value.to_owned());
|
||||
// }
|
||||
|
||||
// TODO
|
||||
"send_mouse" => {
|
||||
@ -848,203 +805,29 @@ unsafe extern "C" fn set_by_name(name: *const c_char, value: *const c_char) {
|
||||
}
|
||||
}
|
||||
}
|
||||
"option" => {
|
||||
if let Ok(m) = serde_json::from_str::<HashMap<String, String>>(value) {
|
||||
if let Some(name) = m.get("name") {
|
||||
if let Some(value) = m.get("value") {
|
||||
ui_interface::set_option(name.to_owned(), value.to_owned());
|
||||
if name == "custom-rendezvous-server" {
|
||||
#[cfg(target_os = "android")]
|
||||
crate::rendezvous_mediator::RendezvousMediator::restart();
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "ios",
|
||||
feature = "cli"
|
||||
))]
|
||||
crate::common::test_rendezvous_server();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// "peer_option" => {
|
||||
// "option" => {
|
||||
// if let Ok(m) = serde_json::from_str::<HashMap<String, String>>(value) {
|
||||
// if let Some(name) = m.get("name") {
|
||||
// if let Some(value) = m.get("value") {
|
||||
// Session::set_option(name.to_owned(), value.to_owned());
|
||||
// ui_interface::set_option(name.to_owned(), value.to_owned());
|
||||
// if name == "custom-rendezvous-server" {
|
||||
// #[cfg(target_os = "android")]
|
||||
// crate::rendezvous_mediator::RendezvousMediator::restart();
|
||||
// #[cfg(any(
|
||||
// target_os = "android",
|
||||
// target_os = "ios",
|
||||
// feature = "cli"
|
||||
// ))]
|
||||
// crate::common::test_rendezvous_server();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
"local_option" => {
|
||||
if let Ok(m) = serde_json::from_str::<HashMap<String, String>>(value) {
|
||||
if let Some(name) = m.get("name") {
|
||||
if let Some(value) = m.get("value") {
|
||||
LocalConfig::set_option(name.to_owned(), value.to_owned());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// "input_os_password" => {
|
||||
// Session::input_os_password(value.to_owned(), true);
|
||||
// }
|
||||
"restart_remote_device" => {
|
||||
// TODO
|
||||
// Session::restart_remote_device();
|
||||
}
|
||||
// // File Action
|
||||
// "read_remote_dir" => {
|
||||
// if let Ok(m) = serde_json::from_str::<HashMap<String, String>>(value) {
|
||||
// if let (Some(path), Some(show_hidden), Some(session)) = (
|
||||
// m.get("path"),
|
||||
// m.get("show_hidden"),
|
||||
// Session::get().read().unwrap().as_ref(),
|
||||
// ) {
|
||||
// session.read_remote_dir(path.to_owned(), show_hidden.eq("true"));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// "send_files" => {
|
||||
// if let Ok(m) = serde_json::from_str::<HashMap<String, String>>(value) {
|
||||
// if let (
|
||||
// Some(id),
|
||||
// Some(path),
|
||||
// Some(to),
|
||||
// Some(file_num),
|
||||
// Some(show_hidden),
|
||||
// Some(is_remote),
|
||||
// ) = (
|
||||
// m.get("id"),
|
||||
// m.get("path"),
|
||||
// m.get("to"),
|
||||
// m.get("file_num"),
|
||||
// m.get("show_hidden"),
|
||||
// m.get("is_remote"),
|
||||
// ) {
|
||||
// Session::send_files(
|
||||
// id.parse().unwrap_or(0),
|
||||
// path.to_owned(),
|
||||
// to.to_owned(),
|
||||
// file_num.parse().unwrap_or(0),
|
||||
// show_hidden.eq("true"),
|
||||
// is_remote.eq("true"),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// "set_confirm_override_file" => {
|
||||
// if let Ok(m) = serde_json::from_str::<HashMap<String, String>>(value) {
|
||||
// if let (
|
||||
// Some(id),
|
||||
// Some(file_num),
|
||||
// Some(need_override),
|
||||
// Some(remember),
|
||||
// Some(is_upload),
|
||||
// ) = (
|
||||
// m.get("id"),
|
||||
// m.get("file_num"),
|
||||
// m.get("need_override"),
|
||||
// m.get("remember"),
|
||||
// m.get("is_upload"),
|
||||
// ) {
|
||||
// Session::set_confirm_override_file(
|
||||
// id.parse().unwrap_or(0),
|
||||
// file_num.parse().unwrap_or(0),
|
||||
// need_override.eq("true"),
|
||||
// remember.eq("true"),
|
||||
// is_upload.eq("true"),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// ** TODO ** continue
|
||||
// "remove_file" => {
|
||||
// if let Ok(m) = serde_json::from_str::<HashMap<String, String>>(value) {
|
||||
// if let (
|
||||
// Some(id),
|
||||
// Some(path),
|
||||
// Some(file_num),
|
||||
// Some(is_remote),
|
||||
// Some(session),
|
||||
// ) = (
|
||||
// m.get("id"),
|
||||
// m.get("path"),
|
||||
// m.get("file_num"),
|
||||
// m.get("is_remote"),
|
||||
// Session::get().write().unwrap().as_mut(),
|
||||
// ) {
|
||||
// session.remove_file(
|
||||
// id.parse().unwrap_or(0),
|
||||
// path.to_owned(),
|
||||
// file_num.parse().unwrap_or(0),
|
||||
// is_remote.eq("true"),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// "read_dir_recursive" => {
|
||||
// if let Ok(m) = serde_json::from_str::<HashMap<String, String>>(value) {
|
||||
// if let (Some(id), Some(path), Some(is_remote), Some(session)) = (
|
||||
// m.get("id"),
|
||||
// m.get("path"),
|
||||
// m.get("is_remote"),
|
||||
// Session::get().write().unwrap().as_mut(),
|
||||
// ) {
|
||||
// session.remove_dir_all(
|
||||
// id.parse().unwrap_or(0),
|
||||
// path.to_owned(),
|
||||
// is_remote.eq("true"),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// "remove_all_empty_dirs" => {
|
||||
// if let Ok(m) = serde_json::from_str::<HashMap<String, String>>(value) {
|
||||
// if let (Some(id), Some(path), Some(is_remote), Some(session)) = (
|
||||
// m.get("id"),
|
||||
// m.get("path"),
|
||||
// m.get("is_remote"),
|
||||
// Session::get().write().unwrap().as_mut(),
|
||||
// ) {
|
||||
// session.remove_dir(
|
||||
// id.parse().unwrap_or(0),
|
||||
// path.to_owned(),
|
||||
// is_remote.eq("true"),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// "cancel_job" => {
|
||||
// if let (Ok(id), Some(session)) =
|
||||
// (value.parse(), Session::get().write().unwrap().as_mut())
|
||||
// {
|
||||
// session.cancel_job(id);
|
||||
// }
|
||||
// }
|
||||
// "create_dir" => {
|
||||
// if let Ok(m) = serde_json::from_str::<HashMap<String, String>>(value) {
|
||||
// if let (Some(id), Some(path), Some(is_remote), Some(session)) = (
|
||||
// m.get("id"),
|
||||
// m.get("path"),
|
||||
// m.get("is_remote"),
|
||||
// Session::get().write().unwrap().as_mut(),
|
||||
// ) {
|
||||
// session.create_dir(
|
||||
// id.parse().unwrap_or(0),
|
||||
// path.to_owned(),
|
||||
// is_remote.eq("true"),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// Server Side
|
||||
// "update_password" => {
|
||||
// if value.is_empty() {
|
||||
// Config::set_password(&Config::get_auto_password());
|
||||
// } else {
|
||||
// Config::set_password(value);
|
||||
// }
|
||||
// }
|
||||
#[cfg(target_os = "android")]
|
||||
"chat_server_mode" => {
|
||||
if let Ok(m) = serde_json::from_str::<HashMap<String, Value>>(value) {
|
||||
@ -1105,7 +888,11 @@ unsafe extern "C" fn set_by_name(name: *const c_char, value: *const c_char) {
|
||||
}
|
||||
|
||||
fn handle_query_onlines(onlines: Vec<String>, offlines: Vec<String>) {
|
||||
if let Some(s) = flutter::GLOBAL_EVENT_STREAM.read().unwrap().get(flutter::APP_TYPE_MAIN) {
|
||||
if let Some(s) = flutter::GLOBAL_EVENT_STREAM
|
||||
.read()
|
||||
.unwrap()
|
||||
.get(flutter::APP_TYPE_MAIN)
|
||||
{
|
||||
let data = HashMap::from([
|
||||
("name", "callback_query_onlines".to_owned()),
|
||||
("onlines", onlines.join(",")),
|
||||
|
@ -138,10 +138,11 @@ pub fn get_license() -> String {
|
||||
}
|
||||
|
||||
pub fn get_option(key: String) -> String {
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
return Config::get_option(&key);
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
return get_option_(&key);
|
||||
get_option_(&key)
|
||||
// #[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
// return Config::get_option(&key);
|
||||
// #[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
// return get_option_(&key);
|
||||
}
|
||||
|
||||
fn get_option_(key: &str) -> String {
|
||||
@ -250,33 +251,31 @@ pub fn get_sound_inputs() -> Vec<String> {
|
||||
}
|
||||
|
||||
pub fn set_options(m: HashMap<String, String>) {
|
||||
*OPTIONS.lock().unwrap() = m.clone();
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
{
|
||||
*OPTIONS.lock().unwrap() = m.clone();
|
||||
ipc::set_options(m).ok();
|
||||
}
|
||||
ipc::set_options(m).ok();
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
Config::set_options(m);
|
||||
}
|
||||
|
||||
pub fn set_option(key: String, value: String) {
|
||||
let mut options = OPTIONS.lock().unwrap();
|
||||
#[cfg(target_os = "macos")]
|
||||
if &key == "stop-service" {
|
||||
let is_stop = value == "Y";
|
||||
if is_stop && crate::platform::macos::uninstall() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if value.is_empty() {
|
||||
options.remove(&key);
|
||||
} else {
|
||||
options.insert(key.clone(), value.clone());
|
||||
}
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
ipc::set_options(options.clone()).ok();
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
Config::set_option(key, value);
|
||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||
{
|
||||
let mut options = OPTIONS.lock().unwrap();
|
||||
#[cfg(target_os = "macos")]
|
||||
if &key == "stop-service" {
|
||||
let is_stop = value == "Y";
|
||||
if is_stop && crate::platform::macos::uninstall() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if value.is_empty() {
|
||||
options.remove(&key);
|
||||
} else {
|
||||
options.insert(key.clone(), value.clone());
|
||||
}
|
||||
ipc::set_options(options.clone()).ok();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn install_path() -> String {
|
||||
|
Loading…
x
Reference in New Issue
Block a user