opt: optimize cm ui & timer & auto close

Signed-off-by: Kingtous <kingtous@qq.com>
This commit is contained in:
Kingtous 2022-08-18 00:34:04 +08:00
parent a580b98472
commit eed87808e5
5 changed files with 104 additions and 49 deletions

View File

@ -10,8 +10,8 @@ import 'desktop/pages/server_page.dart';
void main(List<String> args) async { void main(List<String> args) async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
await windowManager.ensureInitialized(); await windowManager.ensureInitialized();
await initEnv(kAppTypeConnectionManager);
runApp(GetMaterialApp(theme: getCurrentTheme(), home: DesktopServerPage()));
await windowManager.setSize(Size(400, 600)); await windowManager.setSize(Size(400, 600));
await windowManager.setAlignment(Alignment.topRight); await windowManager.setAlignment(Alignment.topRight);
await initEnv(kAppTypeConnectionManager);
runApp(GetMaterialApp(theme: getCurrentTheme(), home: DesktopServerPage()));
} }

View File

@ -79,6 +79,15 @@ final ButtonStyle flatButtonStyle = TextButton.styleFrom(
), ),
); );
String formatDurationToTime(Duration duration) {
var totalTime = duration.inSeconds;
final secs = totalTime % 60;
totalTime = (totalTime - secs) ~/ 60;
final mins = totalTime % 60;
totalTime = (totalTime - mins) ~/ 60;
return "${totalTime.toString().padLeft(2, "0")}:${mins.toString().padLeft(2, "0")}:${secs.toString().padLeft(2, "0")}";
}
closeConnection({String? id}) { closeConnection({String? id}) {
if (isAndroid || isIOS) { if (isAndroid || isIOS) {
Navigator.popUntil(globalKey.currentContext!, ModalRoute.withName("/")); Navigator.popUntil(globalKey.currentContext!, ModalRoute.withName("/"));
@ -440,12 +449,18 @@ class PermissionManager {
} }
static Future<bool> check(String type) { static Future<bool> check(String type) {
if (isDesktop) {
return Future.value(true);
}
if (!permissions.contains(type)) if (!permissions.contains(type))
return Future.error("Wrong permission!$type"); return Future.error("Wrong permission!$type");
return gFFI.invokeMethod("check_permission", type); return gFFI.invokeMethod("check_permission", type);
} }
static Future<bool> request(String type) { static Future<bool> request(String type) {
if (isDesktop) {
return Future.value(true);
}
if (!permissions.contains(type)) if (!permissions.contains(type))
return Future.error("Wrong permission!$type"); return Future.error("Wrong permission!$type");

View File

@ -1,5 +1,8 @@
import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
// import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; // import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -32,14 +35,14 @@ class DesktopServerPage extends StatefulWidget implements PageShape {
padding: EdgeInsets.symmetric(horizontal: 16.0), padding: EdgeInsets.symmetric(horizontal: 16.0),
value: "setPermanentPassword", value: "setPermanentPassword",
enabled: enabled:
gFFI.serverModel.verificationMethod != kUseTemporaryPassword, gFFI.serverModel.verificationMethod != kUseTemporaryPassword,
), ),
PopupMenuItem( PopupMenuItem(
child: Text(translate("Set temporary password length")), child: Text(translate("Set temporary password length")),
padding: EdgeInsets.symmetric(horizontal: 16.0), padding: EdgeInsets.symmetric(horizontal: 16.0),
value: "setTemporaryPasswordLength", value: "setTemporaryPasswordLength",
enabled: enabled:
gFFI.serverModel.verificationMethod != kUsePermanentPassword, gFFI.serverModel.verificationMethod != kUsePermanentPassword,
), ),
const PopupMenuDivider(), const PopupMenuDivider(),
PopupMenuItem( PopupMenuItem(
@ -51,7 +54,7 @@ class DesktopServerPage extends StatefulWidget implements PageShape {
trailing: Icon( trailing: Icon(
Icons.check, Icons.check,
color: gFFI.serverModel.verificationMethod == color: gFFI.serverModel.verificationMethod ==
kUseTemporaryPassword kUseTemporaryPassword
? null ? null
: Color(0xFFFFFFFF), : Color(0xFFFFFFFF),
))), ))),
@ -64,7 +67,7 @@ class DesktopServerPage extends StatefulWidget implements PageShape {
trailing: Icon( trailing: Icon(
Icons.check, Icons.check,
color: gFFI.serverModel.verificationMethod == color: gFFI.serverModel.verificationMethod ==
kUsePermanentPassword kUsePermanentPassword
? null ? null
: Color(0xFFFFFFFF), : Color(0xFFFFFFFF),
)), )),
@ -77,9 +80,9 @@ class DesktopServerPage extends StatefulWidget implements PageShape {
trailing: Icon( trailing: Icon(
Icons.check, Icons.check,
color: gFFI.serverModel.verificationMethod != color: gFFI.serverModel.verificationMethod !=
kUseTemporaryPassword && kUseTemporaryPassword &&
gFFI.serverModel.verificationMethod != gFFI.serverModel.verificationMethod !=
kUsePermanentPassword kUsePermanentPassword
? null ? null
: Color(0xFFFFFFFF), : Color(0xFFFFFFFF),
)), )),
@ -115,16 +118,16 @@ class _DesktopServerPageState extends State<DesktopServerPage>
value: gFFI.serverModel, value: gFFI.serverModel,
child: Consumer<ServerModel>( child: Consumer<ServerModel>(
builder: (context, serverModel, child) => Material( builder: (context, serverModel, child) => Material(
child: Center( child: Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: [ children: [
Expanded(child: ConnectionManager()), Expanded(child: ConnectionManager()),
SizedBox.fromSize(size: Size(0, 15.0)), SizedBox.fromSize(size: Size(0, 15.0)),
], ],
), ),
), ),
))); )));
} }
@override @override
@ -136,9 +139,9 @@ class ConnectionManager extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final serverModel = Provider.of<ServerModel>(context); final serverModel = Provider.of<ServerModel>(context);
// test case: // test case:
serverModel.clients.clear(); // serverModel.clients.clear();
serverModel.clients[0] = Client( // serverModel.clients[0] = Client(
false, false, "Readmi-M21sdfsdf", "123123123", true, false, false); // false, false, "Readmi-M21sdfsdf", "123123123", true, false, false);
return serverModel.clients.isEmpty return serverModel.clients.isEmpty
? Center( ? Center(
child: Text(translate("Waiting")), child: Text(translate("Waiting")),
@ -150,11 +153,11 @@ class ConnectionManager extends StatelessWidget {
children: [ children: [
SizedBox( SizedBox(
height: kTextTabBarHeight, height: kTextTabBarHeight,
child: TabBar( child: TabBar(
isScrollable: true, isScrollable: true,
tabs: serverModel.clients.entries tabs: serverModel.clients.entries
.map((entry) => buildTab(entry)) .map((entry) => buildTab(entry))
.toList(growable: false)), .toList(growable: false)),
), ),
Expanded( Expanded(
child: TabBarView( child: TabBarView(
@ -170,9 +173,10 @@ class ConnectionManager extends StatelessWidget {
Widget buildConnectionCard(MapEntry<int, Client> entry) { Widget buildConnectionCard(MapEntry<int, Client> entry) {
final client = entry.value; final client = entry.value;
return Column( return Column(
key: ValueKey(entry.key),
children: [ children: [
_CmHeader(client: client), _CmHeader(client: client),
_PrivilegeBoard(client: client), client.isFileTransfer ? Offstage() : _PrivilegeBoard(client: client),
Expanded( Expanded(
child: Align( child: Align(
alignment: Alignment.bottomCenter, alignment: Alignment.bottomCenter,
@ -200,13 +204,39 @@ class ConnectionManager extends StatelessWidget {
} }
} }
class _CmHeader extends StatelessWidget { class _CmHeader extends StatefulWidget {
final Client client; final Client client;
const _CmHeader({Key? key, required this.client}) : super(key: key); const _CmHeader({Key? key, required this.client}) : super(key: key);
@override
State<_CmHeader> createState() => _CmHeaderState();
}
class _CmHeaderState extends State<_CmHeader>
with AutomaticKeepAliveClientMixin {
Client get client => widget.client;
var _time = 0.obs;
Timer? _timer;
@override
void initState() {
super.initState();
_timer = Timer.periodic(Duration(seconds: 1), (_) {
_time.value = _time.value + 1;
});
}
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
super.build(context);
return Row( return Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -242,13 +272,13 @@ class _CmHeader extends StatelessWidget {
SizedBox( SizedBox(
height: 16.0, height: 16.0,
), ),
Offstage( Row(
offstage: !client.authorized, children: [
child: Row( Text("${translate("Connected")}").marginOnly(right: 8.0),
children: [ Obx(() => Text(
Text("${translate("Connected")}"), "${formatDurationToTime(Duration(seconds: _time.value))}"))
], ],
)) )
], ],
), ),
), ),
@ -264,6 +294,9 @@ class _CmHeader extends StatelessWidget {
} }
void handleSendMsg() {} void handleSendMsg() {}
@override
bool get wantKeepAlive => true;
} }
class _PrivilegeBoard extends StatelessWidget { class _PrivilegeBoard extends StatelessWidget {
@ -277,7 +310,7 @@ class _PrivilegeBoard extends StatelessWidget {
message: tooltip ?? "", message: tooltip ?? "",
child: Ink( child: Ink(
decoration: decoration:
BoxDecoration(color: enabled ? MyTheme.accent80 : Colors.grey), BoxDecoration(color: enabled ? MyTheme.accent80 : Colors.grey),
padding: EdgeInsets.all(4.0), padding: EdgeInsets.all(4.0),
child: InkWell( child: InkWell(
onTap: () => onTap?.call(!enabled), onTap: () => onTap?.call(!enabled),
@ -437,9 +470,9 @@ class PaddingCard extends StatelessWidget {
children: [ children: [
titleIcon != null titleIcon != null
? Padding( ? Padding(
padding: EdgeInsets.only(right: 10), padding: EdgeInsets.only(right: 10),
child: Icon(titleIcon, child: Icon(titleIcon,
color: MyTheme.accent80, size: 30)) color: MyTheme.accent80, size: 30))
: SizedBox.shrink(), : SizedBox.shrink(),
Text( Text(
title!, title!,
@ -486,12 +519,12 @@ Widget clientInfo(Client client) {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Text(client.name, Text(client.name,
style: TextStyle(color: MyTheme.idColor, fontSize: 18)), style: TextStyle(color: MyTheme.idColor, fontSize: 18)),
SizedBox(width: 8), SizedBox(width: 8),
Text(client.peerId, Text(client.peerId,
style: TextStyle(color: MyTheme.idColor, fontSize: 10)) style: TextStyle(color: MyTheme.idColor, fontSize: 10))
])) ]))
], ],
), ),
])); ]));

View File

@ -117,9 +117,12 @@ void runFileTransferScreen(Map<String, dynamic> argument) async {
} }
void runConnectionManagerScreen() async { void runConnectionManagerScreen() async {
await initEnv(kAppTypeConnectionManager); await Future.wait([
await windowManager.setSize(Size(400, 600)); initEnv(kAppTypeConnectionManager),
await windowManager.setAlignment(Alignment.topRight); windowManager
.setSize(Size(300, 400))
.then((value) => windowManager.setAlignment(Alignment.topRight))
]);
runApp(GetMaterialApp(theme: getCurrentTheme(), home: DesktopServerPage())); runApp(GetMaterialApp(theme: getCurrentTheme(), home: DesktopServerPage()));
} }

View File

@ -342,6 +342,10 @@ class ServerModel with ChangeNotifier {
var res = await bind.mainGetClientsState(); var res = await bind.mainGetClientsState();
try { try {
final List clientsJson = jsonDecode(res); final List clientsJson = jsonDecode(res);
if (isDesktop && clientsJson.isEmpty && _clients.isNotEmpty) {
// exit cm when >1 peers to no peers
exit(0);
}
_clients.clear(); _clients.clear();
for (var clientJson in clientsJson) { for (var clientJson in clientsJson) {
final client = Client.fromJson(clientJson); final client = Client.fromJson(clientJson);