commit
1a3dcbd275
@ -205,6 +205,9 @@ class MyTheme {
|
|||||||
splashColor: Colors.transparent,
|
splashColor: Colors.transparent,
|
||||||
highlightColor: Colors.transparent,
|
highlightColor: Colors.transparent,
|
||||||
splashFactory: isDesktop ? NoSplash.splashFactory : null,
|
splashFactory: isDesktop ? NoSplash.splashFactory : null,
|
||||||
|
outlinedButtonTheme: OutlinedButtonThemeData(
|
||||||
|
style:
|
||||||
|
OutlinedButton.styleFrom(side: BorderSide(color: Colors.white38))),
|
||||||
textButtonTheme: isDesktop
|
textButtonTheme: isDesktop
|
||||||
? TextButtonThemeData(
|
? TextButtonThemeData(
|
||||||
style: ButtonStyle(splashFactory: NoSplash.splashFactory),
|
style: ButtonStyle(splashFactory: NoSplash.splashFactory),
|
||||||
@ -613,6 +616,7 @@ class CustomAlertDialog extends StatelessWidget {
|
|||||||
Future.delayed(Duration.zero, () {
|
Future.delayed(Duration.zero, () {
|
||||||
if (!scopeNode.hasFocus) scopeNode.requestFocus();
|
if (!scopeNode.hasFocus) scopeNode.requestFocus();
|
||||||
});
|
});
|
||||||
|
const double padding = 16;
|
||||||
return FocusScope(
|
return FocusScope(
|
||||||
node: scopeNode,
|
node: scopeNode,
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
@ -637,17 +641,18 @@ class CustomAlertDialog extends StatelessWidget {
|
|||||||
child: AlertDialog(
|
child: AlertDialog(
|
||||||
scrollable: true,
|
scrollable: true,
|
||||||
title: title,
|
title: title,
|
||||||
contentPadding: EdgeInsets.symmetric(
|
contentPadding: EdgeInsets.fromLTRB(
|
||||||
horizontal: contentPadding ?? 25, vertical: 10),
|
contentPadding ?? padding, 25, contentPadding ?? padding, 10),
|
||||||
content: ConstrainedBox(
|
content: ConstrainedBox(
|
||||||
constraints: contentBoxConstraints,
|
constraints: contentBoxConstraints,
|
||||||
child: Theme(
|
child: Theme(
|
||||||
data: ThemeData(
|
data: Theme.of(context).copyWith(
|
||||||
inputDecorationTheme: InputDecorationTheme(
|
inputDecorationTheme: InputDecorationTheme(
|
||||||
isDense: true, contentPadding: EdgeInsets.all(15)),
|
isDense: true, contentPadding: EdgeInsets.all(15))),
|
||||||
|
child: content),
|
||||||
),
|
),
|
||||||
child: content)),
|
|
||||||
actions: actions,
|
actions: actions,
|
||||||
|
actionsPadding: EdgeInsets.fromLTRB(0, 0, padding, padding),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -701,9 +706,8 @@ void msgBox(String id, String type, String title, String text, String link,
|
|||||||
}
|
}
|
||||||
dialogManager.show(
|
dialogManager.show(
|
||||||
(setState, close) => CustomAlertDialog(
|
(setState, close) => CustomAlertDialog(
|
||||||
title: _msgBoxTitle(title),
|
title: null,
|
||||||
content:
|
content: msgboxContent(type, title, text),
|
||||||
SelectableText(translate(text), style: const TextStyle(fontSize: 15)),
|
|
||||||
actions: buttons,
|
actions: buttons,
|
||||||
onSubmit: hasOk ? submit : null,
|
onSubmit: hasOk ? submit : null,
|
||||||
onCancel: hasCancel == true ? cancel : null,
|
onCancel: hasCancel == true ? cancel : null,
|
||||||
@ -712,30 +716,74 @@ void msgBox(String id, String type, String title, String text, String link,
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget msgBoxButton(String text, void Function() onPressed) {
|
Color? _msgboxColor(String type) {
|
||||||
return ButtonTheme(
|
if (type == "input-password" || type == "custom-os-password") {
|
||||||
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
return Color(0xFFAD448E);
|
||||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
}
|
||||||
//limits the touch area to the button area
|
if (type.contains("success")) {
|
||||||
minWidth: 0,
|
return Color(0xFF32bea6);
|
||||||
//wraps child's width
|
}
|
||||||
height: 0,
|
if (type.contains("error") || type == "re-input-password") {
|
||||||
child: TextButton(
|
return Color(0xFFE04F5F);
|
||||||
style: flatButtonStyle,
|
}
|
||||||
onPressed: onPressed,
|
return Color(0xFF2C8CFF);
|
||||||
child:
|
|
||||||
Text(translate(text), style: TextStyle(color: MyTheme.accent))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _msgBoxTitle(String title) =>
|
Widget msgboxIcon(String type) {
|
||||||
Text(translate(title), style: TextStyle(fontSize: 21));
|
IconData? iconData;
|
||||||
|
if (type.contains("error") || type == "re-input-password") {
|
||||||
|
iconData = Icons.cancel;
|
||||||
|
}
|
||||||
|
if (type.contains("success")) {
|
||||||
|
iconData = Icons.check_circle;
|
||||||
|
}
|
||||||
|
if (type == "wait-uac" || type == "wait-remote-accept-nook") {
|
||||||
|
iconData = Icons.hourglass_top;
|
||||||
|
}
|
||||||
|
if (type == 'on-uac' || type == 'on-foreground-elevated') {
|
||||||
|
iconData = Icons.admin_panel_settings;
|
||||||
|
}
|
||||||
|
if (type == "info") {
|
||||||
|
iconData = Icons.info;
|
||||||
|
}
|
||||||
|
if (iconData != null) {
|
||||||
|
return Icon(iconData, size: 50, color: _msgboxColor(type))
|
||||||
|
.marginOnly(right: 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Offstage();
|
||||||
|
}
|
||||||
|
|
||||||
|
// title should be null
|
||||||
|
Widget msgboxContent(String type, String title, String text) {
|
||||||
|
return Row(
|
||||||
|
children: [
|
||||||
|
msgboxIcon(type),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
translate(title),
|
||||||
|
style: TextStyle(fontSize: 21),
|
||||||
|
).marginOnly(bottom: 10),
|
||||||
|
Text(translate(text), style: const TextStyle(fontSize: 15)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void msgBoxCommon(OverlayDialogManager dialogManager, String title,
|
void msgBoxCommon(OverlayDialogManager dialogManager, String title,
|
||||||
Widget content, List<Widget> buttons,
|
Widget content, List<Widget> buttons,
|
||||||
{bool hasCancel = true}) {
|
{bool hasCancel = true}) {
|
||||||
dialogManager.dismissAll();
|
dialogManager.dismissAll();
|
||||||
dialogManager.show((setState, close) => CustomAlertDialog(
|
dialogManager.show((setState, close) => CustomAlertDialog(
|
||||||
title: _msgBoxTitle(title),
|
title: Text(
|
||||||
|
translate(title),
|
||||||
|
style: TextStyle(fontSize: 21),
|
||||||
|
),
|
||||||
content: content,
|
content: content,
|
||||||
actions: buttons,
|
actions: buttons,
|
||||||
onCancel: hasCancel ? close : null,
|
onCancel: hasCancel ? close : null,
|
||||||
@ -1589,7 +1637,8 @@ class ServerConfig {
|
|||||||
Widget dialogButton(String text,
|
Widget dialogButton(String text,
|
||||||
{required VoidCallback? onPressed,
|
{required VoidCallback? onPressed,
|
||||||
bool isOutline = false,
|
bool isOutline = false,
|
||||||
TextStyle? style}) {
|
TextStyle? style,
|
||||||
|
ButtonStyle? buttonStyle}) {
|
||||||
if (isDesktop) {
|
if (isDesktop) {
|
||||||
if (isOutline) {
|
if (isOutline) {
|
||||||
return OutlinedButton(
|
return OutlinedButton(
|
||||||
@ -1598,7 +1647,7 @@ Widget dialogButton(String text,
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return ElevatedButton(
|
return ElevatedButton(
|
||||||
style: ElevatedButton.styleFrom(elevation: 0),
|
style: ElevatedButton.styleFrom(elevation: 0).merge(buttonStyle),
|
||||||
onPressed: onPressed,
|
onPressed: onPressed,
|
||||||
child: Text(translate(text), style: style),
|
child: Text(translate(text), style: style),
|
||||||
);
|
);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:auto_size_text/auto_size_text.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hbb/common.dart';
|
import 'package:flutter_hbb/common.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
@ -316,42 +317,47 @@ class _DraggableState extends State<Draggable> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class QualityMonitor extends StatelessWidget {
|
class QualityMonitor extends StatelessWidget {
|
||||||
static const textStyle = TextStyle(color: MyTheme.grayBg);
|
|
||||||
final QualityMonitorModel qualityMonitorModel;
|
final QualityMonitorModel qualityMonitorModel;
|
||||||
QualityMonitor(this.qualityMonitorModel);
|
QualityMonitor(this.qualityMonitorModel);
|
||||||
|
|
||||||
|
Widget _row(String info, String? value) {
|
||||||
|
return Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
flex: 8,
|
||||||
|
child: AutoSizeText(info,
|
||||||
|
style: TextStyle(color: MyTheme.grayBg),
|
||||||
|
textAlign: TextAlign.right,
|
||||||
|
maxLines: 1)),
|
||||||
|
Spacer(flex: 1),
|
||||||
|
Expanded(
|
||||||
|
flex: 8,
|
||||||
|
child: AutoSizeText(value ?? '',
|
||||||
|
style: TextStyle(color: MyTheme.grayBg), maxLines: 1)),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) => ChangeNotifierProvider.value(
|
Widget build(BuildContext context) => ChangeNotifierProvider.value(
|
||||||
value: qualityMonitorModel,
|
value: qualityMonitorModel,
|
||||||
child: Consumer<QualityMonitorModel>(
|
child: Consumer<QualityMonitorModel>(
|
||||||
builder: (context, qualityMonitorModel, child) =>
|
builder: (context, qualityMonitorModel, child) => qualityMonitorModel
|
||||||
qualityMonitorModel.show
|
.show
|
||||||
? Container(
|
? Container(
|
||||||
|
constraints: BoxConstraints(maxWidth: 200),
|
||||||
padding: const EdgeInsets.all(8),
|
padding: const EdgeInsets.all(8),
|
||||||
color: MyTheme.canvasColor.withAlpha(120),
|
color: MyTheme.canvasColor.withAlpha(120),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
_row("Speed", qualityMonitorModel.data.speed ?? ''),
|
||||||
"Speed: ${qualityMonitorModel.data.speed ?? ''}",
|
_row("FPS", qualityMonitorModel.data.fps ?? ''),
|
||||||
style: textStyle,
|
_row(
|
||||||
),
|
"Delay", "${qualityMonitorModel.data.delay ?? ''}ms"),
|
||||||
Text(
|
_row("Target Bitrate",
|
||||||
"FPS: ${qualityMonitorModel.data.fps ?? ''}",
|
"${qualityMonitorModel.data.targetBitrate ?? ''}kb"),
|
||||||
style: textStyle,
|
_row("Codec", qualityMonitorModel.data.codecFormat ?? ''),
|
||||||
),
|
|
||||||
Text(
|
|
||||||
"Delay: ${qualityMonitorModel.data.delay ?? ''} ms",
|
|
||||||
style: textStyle,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
"Target Bitrate: ${qualityMonitorModel.data.targetBitrate ?? ''}kb",
|
|
||||||
style: textStyle,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
"Codec: ${qualityMonitorModel.data.codecFormat ?? ''}",
|
|
||||||
style: textStyle,
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -1432,12 +1432,8 @@ void showConfirmSwitchSidesDialog(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return CustomAlertDialog(
|
return CustomAlertDialog(
|
||||||
title: Text(translate('Switch Sides')),
|
content: msgboxContent('info', 'Switch Sides',
|
||||||
content: Column(
|
'Please confirm if you want to share your desktop?'),
|
||||||
children: [
|
|
||||||
Text(translate('Please confirm if you want to share your desktop?')),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
actions: [
|
actions: [
|
||||||
dialogButton('Cancel', onPressed: close, isOutline: true),
|
dialogButton('Cancel', onPressed: close, isOutline: true),
|
||||||
dialogButton('OK', onPressed: submit),
|
dialogButton('OK', onPressed: submit),
|
||||||
|
@ -9,7 +9,7 @@ import '../../models/model.dart';
|
|||||||
import '../../models/platform_model.dart';
|
import '../../models/platform_model.dart';
|
||||||
|
|
||||||
void clientClose(String id, OverlayDialogManager dialogManager) {
|
void clientClose(String id, OverlayDialogManager dialogManager) {
|
||||||
msgBox(id, '', 'Close', 'Are you sure to close the connection?', '',
|
msgBox(id, 'info', 'Close', 'Are you sure to close the connection?', '',
|
||||||
dialogManager);
|
dialogManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,8 +33,10 @@ void showRestartRemoteDevice(
|
|||||||
]),
|
]),
|
||||||
content: Text(
|
content: Text(
|
||||||
"${translate('Are you sure you want to restart')} \n${pi.username}@${pi.hostname}($id) ?"),
|
"${translate('Are you sure you want to restart')} \n${pi.username}@${pi.hostname}($id) ?"),
|
||||||
|
onCancel: close,
|
||||||
|
onSubmit: () => close(true),
|
||||||
actions: [
|
actions: [
|
||||||
dialogButton("Cancel", onPressed: () => close(), isOutline: true),
|
dialogButton("Cancel", onPressed: close, isOutline: true),
|
||||||
dialogButton("OK", onPressed: () => close(true)),
|
dialogButton("OK", onPressed: () => close(true)),
|
||||||
],
|
],
|
||||||
));
|
));
|
||||||
@ -48,6 +50,18 @@ void setPermanentPasswordDialog(OverlayDialogManager dialogManager) async {
|
|||||||
var validateLength = false;
|
var validateLength = false;
|
||||||
var validateSame = false;
|
var validateSame = false;
|
||||||
dialogManager.show((setState, close) {
|
dialogManager.show((setState, close) {
|
||||||
|
submit() async {
|
||||||
|
close();
|
||||||
|
dialogManager.showLoading(translate("Waiting"));
|
||||||
|
if (await gFFI.serverModel.setPermanentPassword(p0.text)) {
|
||||||
|
dialogManager.dismissAll();
|
||||||
|
showSuccess();
|
||||||
|
} else {
|
||||||
|
dialogManager.dismissAll();
|
||||||
|
showError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return CustomAlertDialog(
|
return CustomAlertDialog(
|
||||||
title: Text(translate('Set your own password')),
|
title: Text(translate('Set your own password')),
|
||||||
content: Form(
|
content: Form(
|
||||||
@ -94,29 +108,17 @@ void setPermanentPasswordDialog(OverlayDialogManager dialogManager) async {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
])),
|
])),
|
||||||
|
onCancel: close,
|
||||||
|
onSubmit: (validateLength && validateSame) ? submit : null,
|
||||||
actions: [
|
actions: [
|
||||||
dialogButton(
|
dialogButton(
|
||||||
'Cancel',
|
'Cancel',
|
||||||
onPressed: () {
|
onPressed: close,
|
||||||
close();
|
|
||||||
},
|
|
||||||
isOutline: true,
|
isOutline: true,
|
||||||
),
|
),
|
||||||
dialogButton(
|
dialogButton(
|
||||||
'OK',
|
'OK',
|
||||||
onPressed: (validateLength && validateSame)
|
onPressed: (validateLength && validateSame) ? submit : null,
|
||||||
? () async {
|
|
||||||
close();
|
|
||||||
dialogManager.showLoading(translate("Waiting"));
|
|
||||||
if (await gFFI.serverModel.setPermanentPassword(p0.text)) {
|
|
||||||
dialogManager.dismissAll();
|
|
||||||
showSuccess();
|
|
||||||
} else {
|
|
||||||
dialogManager.dismissAll();
|
|
||||||
showError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
: null,
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@ -205,26 +207,36 @@ void enterPasswordDialog(String id, OverlayDialogManager dialogManager) async {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void wrongPasswordDialog(String id, OverlayDialogManager dialogManager) {
|
void wrongPasswordDialog(
|
||||||
dialogManager.show((setState, close) => CustomAlertDialog(
|
String id, OverlayDialogManager dialogManager, type, title, text) {
|
||||||
title: Text(translate('Wrong Password')),
|
dialogManager.dismissAll();
|
||||||
content: Text(translate('Do you want to enter again?')),
|
dialogManager.show((setState, close) {
|
||||||
|
cancel() {
|
||||||
|
close();
|
||||||
|
closeConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
submit() {
|
||||||
|
enterPasswordDialog(id, dialogManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CustomAlertDialog(
|
||||||
|
title: null,
|
||||||
|
content: msgboxContent(type, title, text),
|
||||||
|
onSubmit: submit,
|
||||||
|
onCancel: cancel,
|
||||||
actions: [
|
actions: [
|
||||||
dialogButton(
|
dialogButton(
|
||||||
'Cancel',
|
'Cancel',
|
||||||
onPressed: () {
|
onPressed: cancel,
|
||||||
close();
|
|
||||||
closeConnection();
|
|
||||||
},
|
|
||||||
isOutline: true,
|
isOutline: true,
|
||||||
),
|
),
|
||||||
dialogButton(
|
dialogButton(
|
||||||
'Retry',
|
'Retry',
|
||||||
onPressed: () {
|
onPressed: submit,
|
||||||
enterPasswordDialog(id, dialogManager);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
]));
|
]);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void showServerSettingsWithValue(
|
void showServerSettingsWithValue(
|
||||||
@ -352,13 +364,15 @@ void showServerSettingsWithValue(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void showWaitUacDialog(String id, OverlayDialogManager dialogManager) {
|
void showWaitUacDialog(
|
||||||
|
String id, OverlayDialogManager dialogManager, String type) {
|
||||||
dialogManager.dismissAll();
|
dialogManager.dismissAll();
|
||||||
dialogManager.show(
|
dialogManager.show(
|
||||||
tag: '$id-wait-uac',
|
tag: '$id-wait-uac',
|
||||||
(setState, close) => CustomAlertDialog(
|
(setState, close) => CustomAlertDialog(
|
||||||
title: Text(translate('Wait')),
|
title: null,
|
||||||
content: Text(translate('wait_accept_uac_tip')).marginAll(10),
|
content: msgboxContent(type, 'Wait', 'wait_accept_uac_tip')
|
||||||
|
.marginOnly(bottom: 10),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -516,16 +530,6 @@ void showOnBlockDialog(
|
|||||||
dialogManager.existing('$id-request-elevation')) {
|
dialogManager.existing('$id-request-elevation')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var content = Column(children: [
|
|
||||||
Align(
|
|
||||||
alignment: Alignment.centerLeft,
|
|
||||||
child: Text(
|
|
||||||
"${translate(text)}${type.contains('uac') ? '\n' : '\n\n'}${translate('request_elevation_tip')}",
|
|
||||||
textAlign: TextAlign.left,
|
|
||||||
style: TextStyle(fontWeight: FontWeight.w400),
|
|
||||||
).marginSymmetric(vertical: 15),
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
dialogManager.show(tag: '$id-$type', (setState, close) {
|
dialogManager.show(tag: '$id-$type', (setState, close) {
|
||||||
void submit() {
|
void submit() {
|
||||||
close();
|
close();
|
||||||
@ -533,12 +537,11 @@ void showOnBlockDialog(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return CustomAlertDialog(
|
return CustomAlertDialog(
|
||||||
title: Text(translate(title)),
|
title: null,
|
||||||
content: content,
|
content: msgboxContent(type, title,
|
||||||
|
"${translate(text)}${type.contains('uac') ? '\n' : '\n\n'}${translate('request_elevation_tip')}"),
|
||||||
actions: [
|
actions: [
|
||||||
dialogButton('Wait', onPressed: () {
|
dialogButton('Wait', onPressed: close, isOutline: true),
|
||||||
close();
|
|
||||||
}, isOutline: true),
|
|
||||||
dialogButton('Request Elevation', onPressed: submit),
|
dialogButton('Request Elevation', onPressed: submit),
|
||||||
],
|
],
|
||||||
onSubmit: submit,
|
onSubmit: submit,
|
||||||
@ -556,8 +559,8 @@ void showElevationError(String id, String type, String title, String text,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return CustomAlertDialog(
|
return CustomAlertDialog(
|
||||||
title: Text(translate(title)),
|
title: null,
|
||||||
content: Text(translate(text)),
|
content: msgboxContent(type, title, text),
|
||||||
actions: [
|
actions: [
|
||||||
dialogButton('Cancel', onPressed: () {
|
dialogButton('Cancel', onPressed: () {
|
||||||
close();
|
close();
|
||||||
@ -570,6 +573,25 @@ void showElevationError(String id, String type, String title, String text,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void showWaitAcceptDialog(String id, String type, String title, String text,
|
||||||
|
OverlayDialogManager dialogManager) {
|
||||||
|
dialogManager.dismissAll();
|
||||||
|
dialogManager.show((setState, close) {
|
||||||
|
onCancel() {
|
||||||
|
closeConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
return CustomAlertDialog(
|
||||||
|
title: null,
|
||||||
|
content: msgboxContent(type, title, text),
|
||||||
|
actions: [
|
||||||
|
dialogButton('Cancel', onPressed: onCancel, isOutline: true),
|
||||||
|
],
|
||||||
|
onCancel: onCancel,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
Future<String?> validateAsync(String value) async {
|
Future<String?> validateAsync(String value) async {
|
||||||
value = value.trim();
|
value = value.trim();
|
||||||
if (value.isEmpty) {
|
if (value.isEmpty) {
|
||||||
|
@ -264,19 +264,18 @@ class FfiModel with ChangeNotifier {
|
|||||||
final text = evt['text'];
|
final text = evt['text'];
|
||||||
final link = evt['link'];
|
final link = evt['link'];
|
||||||
if (type == 're-input-password') {
|
if (type == 're-input-password') {
|
||||||
wrongPasswordDialog(id, dialogManager);
|
wrongPasswordDialog(id, dialogManager, type, title, text);
|
||||||
} else if (type == 'input-password') {
|
} else if (type == 'input-password') {
|
||||||
enterPasswordDialog(id, dialogManager);
|
enterPasswordDialog(id, dialogManager);
|
||||||
} else if (type == 'restarting') {
|
} else if (type == 'restarting') {
|
||||||
showMsgBox(id, type, title, text, link, false, dialogManager,
|
showMsgBox(id, type, title, text, link, false, dialogManager,
|
||||||
hasCancel: false);
|
hasCancel: false);
|
||||||
} else if (type == 'wait-remote-accept-nook') {
|
} else if (type == 'wait-remote-accept-nook') {
|
||||||
msgBoxCommon(dialogManager, title, Text(translate(text)),
|
showWaitAcceptDialog(id, type, title, text, dialogManager);
|
||||||
[dialogButton("Cancel", onPressed: closeConnection)]);
|
|
||||||
} else if (type == 'on-uac' || type == 'on-foreground-elevated') {
|
} else if (type == 'on-uac' || type == 'on-foreground-elevated') {
|
||||||
showOnBlockDialog(id, type, title, text, dialogManager);
|
showOnBlockDialog(id, type, title, text, dialogManager);
|
||||||
} else if (type == 'wait-uac') {
|
} else if (type == 'wait-uac') {
|
||||||
showWaitUacDialog(id, dialogManager);
|
showWaitUacDialog(id, dialogManager, type);
|
||||||
} else if (type == 'elevation-error') {
|
} else if (type == 'elevation-error') {
|
||||||
showElevationError(id, type, title, text, dialogManager);
|
showElevationError(id, type, title, text, dialogManager);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1104,7 +1104,7 @@ impl<T: InvokeUiSession> Remote<T> {
|
|||||||
Some(misc::Union::PortableServiceRunning(b)) => {
|
Some(misc::Union::PortableServiceRunning(b)) => {
|
||||||
if b {
|
if b {
|
||||||
self.handler.msgbox(
|
self.handler.msgbox(
|
||||||
"custom-nocancel",
|
"custom-nocancel-success",
|
||||||
"Successful",
|
"Successful",
|
||||||
"Elevate successfully",
|
"Elevate successfully",
|
||||||
"",
|
"",
|
||||||
|
@ -1745,3 +1745,13 @@ pub fn create_process_with_logon(user: &str, pwd: &str, exe: &str, arg: &str) ->
|
|||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_path_permission(dir: &PathBuf, permission: &str) -> ResultType<()> {
|
||||||
|
std::process::Command::new("icacls")
|
||||||
|
.arg(dir.as_os_str())
|
||||||
|
.arg("/grant")
|
||||||
|
.arg(format!("Everyone:(OI)(CI){}", permission))
|
||||||
|
.arg("/T")
|
||||||
|
.spawn()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
@ -2,9 +2,7 @@ use core::slice;
|
|||||||
use hbb_common::{
|
use hbb_common::{
|
||||||
allow_err,
|
allow_err,
|
||||||
anyhow::anyhow,
|
anyhow::anyhow,
|
||||||
bail,
|
bail, log,
|
||||||
config::Config,
|
|
||||||
log,
|
|
||||||
message_proto::{KeyEvent, MouseEvent},
|
message_proto::{KeyEvent, MouseEvent},
|
||||||
protobuf::Message,
|
protobuf::Message,
|
||||||
tokio::{self, sync::mpsc},
|
tokio::{self, sync::mpsc},
|
||||||
@ -15,6 +13,7 @@ use shared_memory::*;
|
|||||||
use std::{
|
use std::{
|
||||||
mem::size_of,
|
mem::size_of,
|
||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
|
path::PathBuf,
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
@ -25,6 +24,7 @@ use winapi::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ipc::{self, new_listener, Connection, Data, DataPortableService},
|
ipc::{self, new_listener, Connection, Data, DataPortableService},
|
||||||
|
platform::set_path_permission,
|
||||||
video_service::get_current_display,
|
video_service::get_current_display,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ impl DerefMut for SharedMemory {
|
|||||||
|
|
||||||
impl SharedMemory {
|
impl SharedMemory {
|
||||||
pub fn create(name: &str, size: usize) -> ResultType<Self> {
|
pub fn create(name: &str, size: usize) -> ResultType<Self> {
|
||||||
let flink = Self::flink(name.to_string());
|
let flink = Self::flink(name.to_string())?;
|
||||||
let shmem = match ShmemConf::new()
|
let shmem = match ShmemConf::new()
|
||||||
.size(size)
|
.size(size)
|
||||||
.flink(&flink)
|
.flink(&flink)
|
||||||
@ -91,12 +91,12 @@ impl SharedMemory {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
log::info!("Create shared memory, size:{}, flink:{}", size, flink);
|
log::info!("Create shared memory, size:{}, flink:{}", size, flink);
|
||||||
Self::set_all_perm(&flink);
|
set_path_permission(&PathBuf::from(flink), "F").ok();
|
||||||
Ok(SharedMemory { inner: shmem })
|
Ok(SharedMemory { inner: shmem })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_existing(name: &str) -> ResultType<Self> {
|
pub fn open_existing(name: &str) -> ResultType<Self> {
|
||||||
let flink = Self::flink(name.to_string());
|
let flink = Self::flink(name.to_string())?;
|
||||||
let shmem = match ShmemConf::new().flink(&flink).allow_raw(true).open() {
|
let shmem = match ShmemConf::new().flink(&flink).allow_raw(true).open() {
|
||||||
Ok(m) => m,
|
Ok(m) => m,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@ -116,30 +116,29 @@ impl SharedMemory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flink(name: String) -> String {
|
fn flink(name: String) -> ResultType<String> {
|
||||||
let mut shmem_flink = format!("shared_memory{}", name);
|
let disk = std::env::var("SystemDrive").unwrap_or("C:".to_string());
|
||||||
if cfg!(windows) {
|
let mut dir = PathBuf::from(disk);
|
||||||
let df = "C:\\ProgramData";
|
let dir1 = dir.join("ProgramData");
|
||||||
let df = if std::path::Path::new(df).exists() {
|
let dir2 = std::env::var("TEMP")
|
||||||
df.to_owned()
|
.map(|d| PathBuf::from(d))
|
||||||
|
.unwrap_or(dir.join("Windows").join("Temp"));
|
||||||
|
if dir1.exists() {
|
||||||
|
dir = dir1;
|
||||||
|
} else if dir2.exists() {
|
||||||
|
dir = dir2;
|
||||||
} else {
|
} else {
|
||||||
std::env::var("TEMP").unwrap_or("C:\\Windows\\TEMP".to_owned())
|
bail!("no vaild flink directory");
|
||||||
};
|
|
||||||
let df = format!("{}\\{}", df, *hbb_common::config::APP_NAME.read().unwrap());
|
|
||||||
std::fs::create_dir(&df).ok();
|
|
||||||
shmem_flink = format!("{}\\{}", df, shmem_flink);
|
|
||||||
} else {
|
|
||||||
shmem_flink = Config::ipc_path("").replace("ipc", "") + &shmem_flink;
|
|
||||||
}
|
}
|
||||||
return shmem_flink;
|
dir = dir.join(hbb_common::config::APP_NAME.read().unwrap().clone());
|
||||||
}
|
if !dir.exists() {
|
||||||
|
std::fs::create_dir(&dir)?;
|
||||||
fn set_all_perm(_p: &str) {
|
set_path_permission(&dir, "F").ok();
|
||||||
#[cfg(not(windows))]
|
|
||||||
{
|
|
||||||
use std::os::unix::fs::PermissionsExt;
|
|
||||||
std::fs::set_permissions(_p, std::fs::Permissions::from_mode(0o0777)).ok();
|
|
||||||
}
|
}
|
||||||
|
Ok(dir
|
||||||
|
.join(format!("shared_memory{}", name))
|
||||||
|
.to_string_lossy()
|
||||||
|
.to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -451,7 +450,6 @@ pub mod server {
|
|||||||
// functions called in main process.
|
// functions called in main process.
|
||||||
pub mod client {
|
pub mod client {
|
||||||
use hbb_common::anyhow::Context;
|
use hbb_common::anyhow::Context;
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
@ -515,7 +513,7 @@ pub mod client {
|
|||||||
#[cfg(feature = "flutter")]
|
#[cfg(feature = "flutter")]
|
||||||
{
|
{
|
||||||
if let Some(dir) = PathBuf::from(&exe).parent() {
|
if let Some(dir) = PathBuf::from(&exe).parent() {
|
||||||
if !set_dir_permission(&PathBuf::from(dir)) {
|
if set_path_permission(&PathBuf::from(dir), "RX").is_err() {
|
||||||
*SHMEM.lock().unwrap() = None;
|
*SHMEM.lock().unwrap() = None;
|
||||||
bail!("Failed to set permission of {:?}", dir);
|
bail!("Failed to set permission of {:?}", dir);
|
||||||
}
|
}
|
||||||
@ -533,7 +531,7 @@ pub mod client {
|
|||||||
let dst = dir.join("rustdesk.exe");
|
let dst = dir.join("rustdesk.exe");
|
||||||
if std::fs::copy(&exe, &dst).is_ok() {
|
if std::fs::copy(&exe, &dst).is_ok() {
|
||||||
if dst.exists() {
|
if dst.exists() {
|
||||||
if set_dir_permission(&dir) {
|
if set_path_permission(&dir, "RX").is_ok() {
|
||||||
exe = dst.to_string_lossy().to_string();
|
exe = dst.to_string_lossy().to_string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -566,16 +564,6 @@ pub mod client {
|
|||||||
*QUICK_SUPPORT.lock().unwrap() = v;
|
*QUICK_SUPPORT.lock().unwrap() = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_dir_permission(dir: &PathBuf) -> bool {
|
|
||||||
// // give Everyone RX permission
|
|
||||||
std::process::Command::new("icacls")
|
|
||||||
.arg(dir.as_os_str())
|
|
||||||
.arg("/grant")
|
|
||||||
.arg("Everyone:(OI)(CI)RX")
|
|
||||||
.arg("/T")
|
|
||||||
.spawn()
|
|
||||||
.is_ok()
|
|
||||||
}
|
|
||||||
pub struct CapturerPortable;
|
pub struct CapturerPortable;
|
||||||
|
|
||||||
impl CapturerPortable {
|
impl CapturerPortable {
|
||||||
|
@ -16,7 +16,7 @@ div#quality-monitor {
|
|||||||
padding: 5px;
|
padding: 5px;
|
||||||
min-width: 150px;
|
min-width: 150px;
|
||||||
color: azure;
|
color: azure;
|
||||||
border: solid azure;
|
border: 0.5px solid azure;
|
||||||
}
|
}
|
||||||
|
|
||||||
video#handler {
|
video#handler {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user