feat: cm ui

Signed-off-by: Kingtous <kingtous@qq.com>
This commit is contained in:
Kingtous
2022-08-17 21:28:36 +08:00
parent 444b48436d
commit dcab45d8ab
5 changed files with 308 additions and 81 deletions

View File

@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
// import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:provider/provider.dart';
@@ -111,13 +112,12 @@ class _DesktopServerPageState extends State<DesktopServerPage> {
return ChangeNotifierProvider.value(
value: gFFI.serverModel,
child: Consumer<ServerModel>(
builder: (context, serverModel, child) => SingleChildScrollView(
controller: gFFI.serverModel.controller,
builder: (context, serverModel, child) => Material(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
ConnectionManager(),
Expanded(child: ConnectionManager()),
SizedBox.fromSize(size: Size(0, 15.0)),
],
),
@@ -130,81 +130,277 @@ class ConnectionManager extends StatelessWidget {
@override
Widget build(BuildContext context) {
final serverModel = Provider.of<ServerModel>(context);
return Column(
children: serverModel.clients.entries
.map((entry) => PaddingCard(
title: translate(entry.value.isFileTransfer
? "File Connection"
: "Screen Connection"),
titleIcon: entry.value.isFileTransfer
? Icons.folder_outlined
: Icons.mobile_screen_share,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(child: clientInfo(entry.value)),
Expanded(
flex: -1,
child: entry.value.isFileTransfer ||
!entry.value.authorized
? SizedBox.shrink()
: IconButton(
onPressed: () {
gFFI.chatModel
.changeCurrentID(entry.value.id);
final bar =
navigationBarKey.currentWidget;
if (bar != null) {
bar as BottomNavigationBar;
bar.onTap!(1);
}
},
icon: Icon(
Icons.chat,
color: MyTheme.accent80,
)))
],
),
entry.value.authorized
? SizedBox.shrink()
: Text(
translate("android_new_connection_tip"),
style: TextStyle(color: Colors.black54),
),
entry.value.authorized
? ElevatedButton.icon(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Colors.red)),
icon: Icon(Icons.close),
onPressed: () {
bind.cmCloseConnection(connId: entry.key);
gFFI.invokeMethod(
"cancel_notification", entry.key);
},
label: Text(translate("Close")))
: Row(children: [
TextButton(
child: Text(translate("Dismiss")),
onPressed: () {
serverModel.sendLoginResponse(
entry.value, false);
}),
SizedBox(width: 20),
ElevatedButton(
child: Text(translate("Accept")),
onPressed: () {
serverModel.sendLoginResponse(
entry.value, true);
}),
]),
],
)))
.toList());
// test case:
// serverModel.clients.clear();
// serverModel.clients[0] = Client(false, false, "Readmi-M21sdfsdf", "123123123", true, false, false);
return DefaultTabController(
length: serverModel.clients.length,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: kTextTabBarHeight,
child: TabBar(
isScrollable: true,
tabs: serverModel.clients.entries
.map((entry) => buildTab(entry))
.toList(growable: false)),
),
Expanded(
child: TabBarView(
children: serverModel.clients.entries
.map((entry) => buildConnectionCard(entry))
.toList(growable: false)),
)
],
),
);
}
Widget buildConnectionCard(MapEntry<int, Client> entry) {
final client = entry.value;
return Column(
children: [
_CmHeader(client: client),
_PrivilegeBoard(client: client),
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: _CmControlPanel(client: client),
))
],
).paddingSymmetric(vertical: 8.0, horizontal: 8.0);
}
Widget buildTab(MapEntry<int, Client> entry) {
return Tab(
child: Row(
children: [
SizedBox(
width: 80,
child: Text(
"${entry.value.name}",
maxLines: 1,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
)),
],
),
);
}
}
class _CmHeader extends StatelessWidget {
final Client client;
const _CmHeader({Key? key, required this.client}) : super(key: key);
@override
Widget build(BuildContext context) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// icon
Container(
width: 100,
height: 100,
alignment: Alignment.center,
decoration: BoxDecoration(color: str2color(client.name)),
child: Text(
"${client.name[0]}",
style: TextStyle(
fontWeight: FontWeight.bold, color: Colors.white, fontSize: 75),
),
).marginOnly(left: 4.0, right: 8.0),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"${client.name}",
style: TextStyle(
color: MyTheme.cmIdColor,
fontWeight: FontWeight.bold,
fontSize: 20,
overflow: TextOverflow.ellipsis,
),
maxLines: 1,
),
Text("(${client.peerId})",
style: TextStyle(color: MyTheme.cmIdColor, fontSize: 14)),
SizedBox(
height: 16.0,
),
Offstage(
offstage: !client.authorized,
child: Row(
children: [
Text("${translate("Connected")}"),
],
))
],
),
),
Offstage(
offstage: client.isFileTransfer,
child: IconButton(
onPressed: handleSendMsg,
icon: Icon(Icons.message_outlined),
),
)
],
);
}
void handleSendMsg() {}
}
class _PrivilegeBoard extends StatelessWidget {
final Client client;
const _PrivilegeBoard({Key? key, required this.client}) : super(key: key);
Widget buildPermissionIcon(bool enabled, ImageProvider icon,
Function(bool)? onTap, String? tooltip) {
return Tooltip(
message: tooltip ?? "",
child: Ink(
decoration:
BoxDecoration(color: enabled ? MyTheme.accent80 : Colors.grey),
padding: EdgeInsets.all(4.0),
child: InkWell(
onTap: () => onTap?.call(!enabled),
child: Image(
image: icon,
width: 50,
height: 50,
fit: BoxFit.scaleDown,
),
),
).marginSymmetric(horizontal: 4.0),
);
}
@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(top: 16.0, bottom: 8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
translate("Permissions"),
style: TextStyle(fontSize: 16),
).marginOnly(left: 4.0),
SizedBox(
height: 8.0,
),
Row(
children: [
buildPermissionIcon(
client.keyboard, iconKeyboard, (enable) => null, null),
buildPermissionIcon(
client.clipboard, iconClipboard, (enable) => null, null),
buildPermissionIcon(
client.audio, iconAudio, (enable) => null, null),
// TODO: file transfer
buildPermissionIcon(false, iconFile, (enable) => null, null),
],
),
],
),
);
}
}
class _CmControlPanel extends StatelessWidget {
final Client client;
const _CmControlPanel({Key? key, required this.client}) : super(key: key);
@override
Widget build(BuildContext context) {
return client.authorized ? buildAuthorized() : buildUnAuthorized();
}
buildAuthorized() {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Ink(
width: 200,
height: 40,
decoration: BoxDecoration(
color: Colors.redAccent, borderRadius: BorderRadius.circular(10)),
child: InkWell(
onTap: handleDisconnect,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
translate("Disconnect"),
style: TextStyle(color: Colors.white),
),
],
)),
)
],
);
}
buildUnAuthorized() {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Ink(
width: 100,
height: 40,
decoration: BoxDecoration(
color: MyTheme.accent, borderRadius: BorderRadius.circular(10)),
child: InkWell(
onTap: handleAccept,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
translate("Accept"),
style: TextStyle(color: Colors.white),
),
],
)),
),
SizedBox(
width: 30,
),
Ink(
width: 100,
height: 40,
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.grey)),
child: InkWell(
onTap: handleCancel,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
translate("Cancel"),
style: TextStyle(),
),
],
)),
)
],
);
}
void handleDisconnect() {}
void handleCancel() {}
void handleAccept() {}
}
class PaddingCard extends StatelessWidget {