commit
522c865096
@ -118,7 +118,9 @@ void window_on_top(int? id) {
|
|||||||
windowManager.show();
|
windowManager.show();
|
||||||
windowManager.focus();
|
windowManager.focus();
|
||||||
} else {
|
} else {
|
||||||
WindowController.fromWindowId(id)..focus()..show();
|
WindowController.fromWindowId(id)
|
||||||
|
..focus()
|
||||||
|
..show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,11 +8,9 @@ import 'package:flutter_hbb/desktop/widgets/peer_widget.dart';
|
|||||||
import 'package:flutter_hbb/utils/multi_window_manager.dart';
|
import 'package:flutter_hbb/utils/multi_window_manager.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
|
||||||
import 'package:url_launcher/url_launcher_string.dart';
|
import 'package:url_launcher/url_launcher_string.dart';
|
||||||
|
|
||||||
import '../../common.dart';
|
import '../../common.dart';
|
||||||
import '../../mobile/pages/home_page.dart';
|
|
||||||
import '../../mobile/pages/scan_page.dart';
|
import '../../mobile/pages/scan_page.dart';
|
||||||
import '../../mobile/pages/settings_page.dart';
|
import '../../mobile/pages/settings_page.dart';
|
||||||
import '../../models/model.dart';
|
import '../../models/model.dart';
|
||||||
@ -21,18 +19,9 @@ import '../../models/platform_model.dart';
|
|||||||
// enum RemoteType { recently, favorite, discovered, addressBook }
|
// enum RemoteType { recently, favorite, discovered, addressBook }
|
||||||
|
|
||||||
/// Connection page for connecting to a remote peer.
|
/// Connection page for connecting to a remote peer.
|
||||||
class ConnectionPage extends StatefulWidget implements PageShape {
|
class ConnectionPage extends StatefulWidget {
|
||||||
ConnectionPage({Key? key}) : super(key: key);
|
ConnectionPage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
|
||||||
final icon = Icon(Icons.connected_tv);
|
|
||||||
|
|
||||||
@override
|
|
||||||
final title = translate("Connection");
|
|
||||||
|
|
||||||
@override
|
|
||||||
final appBarActions = !isAndroid ? <Widget>[WebMenu()] : <Widget>[];
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_ConnectionPageState createState() => _ConnectionPageState();
|
_ConnectionPageState createState() => _ConnectionPageState();
|
||||||
}
|
}
|
||||||
@ -174,8 +163,8 @@ class _ConnectionPageState extends State<ConnectionPage> {
|
|||||||
: InkWell(
|
: InkWell(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
final url = _updateUrl + '.apk';
|
final url = _updateUrl + '.apk';
|
||||||
if (await canLaunch(url)) {
|
if (await canLaunchUrlString(url)) {
|
||||||
await launch(url);
|
await launchUrlString(url);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
@ -387,13 +376,20 @@ class _ConnectionPageState extends State<ConnectionPage> {
|
|||||||
width: 8,
|
width: 8,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
color: Colors.green,
|
color: svcStopped.value ? Colors.redAccent : Colors.green,
|
||||||
),
|
),
|
||||||
).paddingSymmetric(horizontal: 8.0);
|
).paddingSymmetric(horizontal: 10.0);
|
||||||
if (svcStopped.value) {
|
if (svcStopped.value) {
|
||||||
return Row(
|
return Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [light, Text(translate("Service is not running"))],
|
children: [
|
||||||
|
light,
|
||||||
|
Text(translate("Service is not running")),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () =>
|
||||||
|
bind.mainSetOption(key: "stop-service", value: ""),
|
||||||
|
child: Text(translate("Start Service")))
|
||||||
|
],
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if (svcStatusCode.value == 0) {
|
if (svcStatusCode.value == 0) {
|
||||||
@ -436,7 +432,7 @@ class _ConnectionPageState extends State<ConnectionPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateStatus() async {
|
updateStatus() async {
|
||||||
svcStopped.value = bind.mainGetOption(key: "stop-service") == "Y";
|
svcStopped.value = await bind.mainGetOption(key: "stop-service") == "Y";
|
||||||
final status =
|
final status =
|
||||||
jsonDecode(await bind.mainGetConnectStatus()) as Map<String, dynamic>;
|
jsonDecode(await bind.mainGetConnectStatus()) as Map<String, dynamic>;
|
||||||
svcStatusCode.value = status["status_num"];
|
svcStatusCode.value = status["status_num"];
|
||||||
|
@ -2,7 +2,6 @@ import 'dart:async';
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:desktop_multi_window/desktop_multi_window.dart';
|
|
||||||
import 'package:flutter/material.dart' hide MenuItem;
|
import 'package:flutter/material.dart' hide MenuItem;
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_hbb/common.dart';
|
import 'package:flutter_hbb/common.dart';
|
||||||
@ -27,8 +26,8 @@ class DesktopHomePage extends StatefulWidget {
|
|||||||
|
|
||||||
const borderColor = Color(0xFF2F65BA);
|
const borderColor = Color(0xFF2F65BA);
|
||||||
|
|
||||||
class _DesktopHomePageState extends State<DesktopHomePage> with TrayListener, WindowListener {
|
class _DesktopHomePageState extends State<DesktopHomePage>
|
||||||
|
with TrayListener, WindowListener {
|
||||||
@override
|
@override
|
||||||
void onWindowClose() async {
|
void onWindowClose() async {
|
||||||
super.onWindowClose();
|
super.onWindowClose();
|
||||||
@ -132,18 +131,7 @@ class _DesktopHomePageState extends State<DesktopHomePage> with TrayListener, Wi
|
|||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 18, fontWeight: FontWeight.w500),
|
fontSize: 18, fontWeight: FontWeight.w500),
|
||||||
),
|
),
|
||||||
FutureBuilder<Widget>(
|
buildPopupMenu(context)
|
||||||
future: buildPopupMenu(context),
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
if (snapshot.hasError) {
|
|
||||||
print("${snapshot.error}");
|
|
||||||
}
|
|
||||||
if (snapshot.hasData) {
|
|
||||||
return snapshot.data!;
|
|
||||||
} else {
|
|
||||||
return Offstage();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
@ -165,7 +153,7 @@ class _DesktopHomePageState extends State<DesktopHomePage> with TrayListener, Wi
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Widget> buildPopupMenu(BuildContext context) async {
|
Widget buildPopupMenu(BuildContext context) {
|
||||||
var position;
|
var position;
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTapDown: (detail) {
|
onTapDown: (detail) {
|
||||||
@ -178,19 +166,19 @@ class _DesktopHomePageState extends State<DesktopHomePage> with TrayListener, Wi
|
|||||||
final enabledInput = await bind.mainGetOption(key: 'enable-audio');
|
final enabledInput = await bind.mainGetOption(key: 'enable-audio');
|
||||||
final defaultInput = await gFFI.getDefaultAudioInput();
|
final defaultInput = await gFFI.getDefaultAudioInput();
|
||||||
var menu = <PopupMenuEntry>[
|
var menu = <PopupMenuEntry>[
|
||||||
genEnablePopupMenuItem(
|
await genEnablePopupMenuItem(
|
||||||
translate("Enable Keyboard/Mouse"),
|
translate("Enable Keyboard/Mouse"),
|
||||||
'enable-keyboard',
|
'enable-keyboard',
|
||||||
),
|
),
|
||||||
genEnablePopupMenuItem(
|
await genEnablePopupMenuItem(
|
||||||
translate("Enable Clipboard"),
|
translate("Enable Clipboard"),
|
||||||
'enable-clipboard',
|
'enable-clipboard',
|
||||||
),
|
),
|
||||||
genEnablePopupMenuItem(
|
await genEnablePopupMenuItem(
|
||||||
translate("Enable File Transfer"),
|
translate("Enable File Transfer"),
|
||||||
'enable-file-transfer',
|
'enable-file-transfer',
|
||||||
),
|
),
|
||||||
genEnablePopupMenuItem(
|
await genEnablePopupMenuItem(
|
||||||
translate("Enable TCP Tunneling"),
|
translate("Enable TCP Tunneling"),
|
||||||
'enable-tunnel',
|
'enable-tunnel',
|
||||||
),
|
),
|
||||||
@ -209,16 +197,16 @@ class _DesktopHomePageState extends State<DesktopHomePage> with TrayListener, Wi
|
|||||||
value: 'socks5-proxy',
|
value: 'socks5-proxy',
|
||||||
),
|
),
|
||||||
PopupMenuDivider(),
|
PopupMenuDivider(),
|
||||||
genEnablePopupMenuItem(
|
await genEnablePopupMenuItem(
|
||||||
translate("Enable Service"),
|
translate("Enable Service"),
|
||||||
'stop-service',
|
'stop-service',
|
||||||
),
|
),
|
||||||
// TODO: direct server
|
// TODO: direct server
|
||||||
genEnablePopupMenuItem(
|
await genEnablePopupMenuItem(
|
||||||
translate("Always connected via relay"),
|
translate("Always connected via relay"),
|
||||||
'allow-always-relay',
|
'allow-always-relay',
|
||||||
),
|
),
|
||||||
genEnablePopupMenuItem(
|
await genEnablePopupMenuItem(
|
||||||
translate("Start ID/relay service"),
|
translate("Start ID/relay service"),
|
||||||
'stop-rendezvous-service',
|
'stop-rendezvous-service',
|
||||||
),
|
),
|
||||||
@ -237,7 +225,7 @@ class _DesktopHomePageState extends State<DesktopHomePage> with TrayListener, Wi
|
|||||||
value: 'change-id',
|
value: 'change-id',
|
||||||
),
|
),
|
||||||
PopupMenuDivider(),
|
PopupMenuDivider(),
|
||||||
genEnablePopupMenuItem(
|
await genEnablePopupMenuItem(
|
||||||
translate("Dark Theme"),
|
translate("Dark Theme"),
|
||||||
'allow-darktheme',
|
'allow-darktheme',
|
||||||
),
|
),
|
||||||
@ -491,6 +479,7 @@ class _DesktopHomePageState extends State<DesktopHomePage> with TrayListener, Wi
|
|||||||
Get.changeTheme(MyTheme.lightTheme);
|
Get.changeTheme(MyTheme.lightTheme);
|
||||||
}
|
}
|
||||||
Get.find<SharedPreferences>().setString("darkTheme", choice);
|
Get.find<SharedPreferences>().setString("darkTheme", choice);
|
||||||
|
Get.forceAppUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void onSelectMenu(String key) async {
|
void onSelectMenu(String key) async {
|
||||||
@ -501,7 +490,7 @@ class _DesktopHomePageState extends State<DesktopHomePage> with TrayListener, Wi
|
|||||||
final option = await bind.mainGetOption(key: key);
|
final option = await bind.mainGetOption(key: key);
|
||||||
final choice = option == "Y" ? "" : "Y";
|
final choice = option == "Y" ? "" : "Y";
|
||||||
bind.mainSetOption(key: key, value: choice);
|
bind.mainSetOption(key: key, value: choice);
|
||||||
changeTheme(choice);
|
if (key == "allow-darktheme") changeTheme(choice);
|
||||||
} else if (key == "stop-service") {
|
} else if (key == "stop-service") {
|
||||||
final option = await bind.mainGetOption(key: key);
|
final option = await bind.mainGetOption(key: key);
|
||||||
bind.mainSetOption(key: key, value: option == "Y" ? "" : "Y");
|
bind.mainSetOption(key: key, value: option == "Y" ? "" : "Y");
|
||||||
@ -522,30 +511,29 @@ class _DesktopHomePageState extends State<DesktopHomePage> with TrayListener, Wi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PopupMenuItem<String> genEnablePopupMenuItem(String label, String key) {
|
Future<PopupMenuItem<String>> genEnablePopupMenuItem(
|
||||||
Future<bool> getOptionEnable(String key) async {
|
String label, String key) async {
|
||||||
final v = await bind.mainGetOption(key: key);
|
final v = await bind.mainGetOption(key: key);
|
||||||
return key.startsWith('enable-') ? v != "N" : v == "Y";
|
bool enable;
|
||||||
|
if (key == "stop-service") {
|
||||||
|
enable = v != "Y";
|
||||||
|
} else if (key.startsWith("allow-")) {
|
||||||
|
enable = v == "Y";
|
||||||
|
} else {
|
||||||
|
enable = v != "N";
|
||||||
}
|
}
|
||||||
|
|
||||||
return PopupMenuItem(
|
return PopupMenuItem(
|
||||||
child: FutureBuilder<bool>(
|
child: Row(
|
||||||
future: getOptionEnable(key),
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
var enable = false;
|
|
||||||
if (snapshot.hasData && snapshot.data!) {
|
|
||||||
enable = true;
|
|
||||||
}
|
|
||||||
return Row(
|
|
||||||
children: [
|
children: [
|
||||||
Offstage(offstage: !enable, child: Icon(Icons.check)),
|
Icon(Icons.check,
|
||||||
|
color: enable ? null : MyTheme.accent.withAlpha(00)),
|
||||||
Text(
|
Text(
|
||||||
label,
|
label,
|
||||||
style: genTextStyle(enable),
|
style: genTextStyle(enable),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
),
|
||||||
}),
|
|
||||||
value: key,
|
value: key,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -187,10 +187,9 @@ class _PeerCardState extends State<_PeerCard>
|
|||||||
elevation: 8,
|
elevation: 8,
|
||||||
);
|
);
|
||||||
if (value == 'remove') {
|
if (value == 'remove') {
|
||||||
setState(() => bind.mainRemovePeer(id: id));
|
await bind.mainRemovePeer(id: id);
|
||||||
() async {
|
|
||||||
removePreference(id);
|
removePreference(id);
|
||||||
}();
|
Get.forceAppUpdate(); // TODO use inner model / state
|
||||||
} else if (value == 'file') {
|
} else if (value == 'file') {
|
||||||
_connect(id, isFileTransfer: true);
|
_connect(id, isFileTransfer: true);
|
||||||
} else if (value == 'add-fav') {
|
} else if (value == 'add-fav') {
|
||||||
|
@ -8,7 +8,7 @@ import '../../models/platform_model.dart';
|
|||||||
import '../../models/server_model.dart';
|
import '../../models/server_model.dart';
|
||||||
import 'home_page.dart';
|
import 'home_page.dart';
|
||||||
|
|
||||||
class ServerPage extends StatelessWidget implements PageShape {
|
class ServerPage extends StatefulWidget implements PageShape {
|
||||||
@override
|
@override
|
||||||
final title = translate("Share Screen");
|
final title = translate("Share Screen");
|
||||||
|
|
||||||
@ -102,6 +102,17 @@ class ServerPage extends StatelessWidget implements PageShape {
|
|||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<StatefulWidget> createState() => _ServerPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ServerPageState extends State<ServerPage> {
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
gFFI.serverModel.checkAndroidPermission();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
checkService();
|
checkService();
|
||||||
|
@ -85,40 +85,8 @@ class ServerModel with ChangeNotifier {
|
|||||||
WeakReference<FFI> parent;
|
WeakReference<FFI> parent;
|
||||||
|
|
||||||
ServerModel(this.parent) {
|
ServerModel(this.parent) {
|
||||||
() async {
|
|
||||||
_emptyIdShow = translate("Generating ...");
|
_emptyIdShow = translate("Generating ...");
|
||||||
_serverId = TextEditingController(text: this._emptyIdShow);
|
_serverId = TextEditingController(text: this._emptyIdShow);
|
||||||
/**
|
|
||||||
* 1. check android permission
|
|
||||||
* 2. check config
|
|
||||||
* audio true by default (if permission on) (false default < Android 10)
|
|
||||||
* file true by default (if permission on)
|
|
||||||
*/
|
|
||||||
await Future.delayed(Duration(seconds: 1));
|
|
||||||
|
|
||||||
// audio
|
|
||||||
if (androidVersion < 30 || !await PermissionManager.check("audio")) {
|
|
||||||
_audioOk = false;
|
|
||||||
bind.mainSetOption(key: "enable-audio", value: "N");
|
|
||||||
} else {
|
|
||||||
final audioOption = await bind.mainGetOption(key: 'enable-audio');
|
|
||||||
_audioOk = audioOption.isEmpty;
|
|
||||||
}
|
|
||||||
|
|
||||||
// file
|
|
||||||
if (!await PermissionManager.check("file")) {
|
|
||||||
_fileOk = false;
|
|
||||||
bind.mainSetOption(key: "enable-file-transfer", value: "N");
|
|
||||||
} else {
|
|
||||||
final fileOption =
|
|
||||||
await bind.mainGetOption(key: 'enable-file-transfer');
|
|
||||||
_fileOk = fileOption.isEmpty;
|
|
||||||
}
|
|
||||||
|
|
||||||
// input (mouse control) false by default
|
|
||||||
bind.mainSetOption(key: "enable-keyboard", value: "N");
|
|
||||||
notifyListeners();
|
|
||||||
}();
|
|
||||||
|
|
||||||
Timer.periodic(Duration(seconds: 1), (timer) async {
|
Timer.periodic(Duration(seconds: 1), (timer) async {
|
||||||
var status = await bind.mainGetOnlineStatue();
|
var status = await bind.mainGetOnlineStatue();
|
||||||
@ -139,6 +107,34 @@ class ServerModel with ChangeNotifier {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 1. check android permission
|
||||||
|
/// 2. check config
|
||||||
|
/// audio true by default (if permission on) (false default < Android 10)
|
||||||
|
/// file true by default (if permission on)
|
||||||
|
checkAndroidPermission() async {
|
||||||
|
// audio
|
||||||
|
if (androidVersion < 30 || !await PermissionManager.check("audio")) {
|
||||||
|
_audioOk = false;
|
||||||
|
bind.mainSetOption(key: "enable-audio", value: "N");
|
||||||
|
} else {
|
||||||
|
final audioOption = await bind.mainGetOption(key: 'enable-audio');
|
||||||
|
_audioOk = audioOption.isEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
// file
|
||||||
|
if (!await PermissionManager.check("file")) {
|
||||||
|
_fileOk = false;
|
||||||
|
bind.mainSetOption(key: "enable-file-transfer", value: "N");
|
||||||
|
} else {
|
||||||
|
final fileOption = await bind.mainGetOption(key: 'enable-file-transfer');
|
||||||
|
_fileOk = fileOption.isEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
// input (mouse control) false by default
|
||||||
|
bind.mainSetOption(key: "enable-keyboard", value: "N");
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
updatePasswordModel() async {
|
updatePasswordModel() async {
|
||||||
var update = false;
|
var update = false;
|
||||||
final temporaryPassword = await bind.mainGetTemporaryPassword();
|
final temporaryPassword = await bind.mainGetTemporaryPassword();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user