update multi chat,fix provider
This commit is contained in:
parent
4d64fee76d
commit
2ea9d80be6
@ -21,23 +21,13 @@ class App extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final analytics = FirebaseAnalytics();
|
final analytics = FirebaseAnalytics();
|
||||||
final providers = [
|
|
||||||
ChangeNotifierProvider.value(value: FFI.ffiModel),
|
|
||||||
ChangeNotifierProvider.value(value: FFI.imageModel),
|
|
||||||
ChangeNotifierProvider.value(value: FFI.cursorModel),
|
|
||||||
ChangeNotifierProvider.value(value: FFI.canvasModel),
|
|
||||||
];
|
|
||||||
if (!isWeb) {
|
|
||||||
providers.addAll([
|
|
||||||
ChangeNotifierProvider.value(value: FFI.chatModel),
|
|
||||||
ChangeNotifierProvider.value(value: FFI.fileModel),
|
|
||||||
]);
|
|
||||||
if (isAndroid) {
|
|
||||||
providers.add(ChangeNotifierProvider.value(value: FFI.serverModel));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return MultiProvider(
|
return MultiProvider(
|
||||||
providers: providers,
|
providers: [
|
||||||
|
ChangeNotifierProvider.value(value: FFI.ffiModel),
|
||||||
|
ChangeNotifierProvider.value(value: FFI.imageModel),
|
||||||
|
ChangeNotifierProvider.value(value: FFI.cursorModel),
|
||||||
|
ChangeNotifierProvider.value(value: FFI.canvasModel),
|
||||||
|
],
|
||||||
child: MaterialApp(
|
child: MaterialApp(
|
||||||
navigatorKey: globalKey,
|
navigatorKey: globalKey,
|
||||||
debugShowCheckedModeBanner: false,
|
debugShowCheckedModeBanner: false,
|
||||||
|
@ -17,14 +17,24 @@ class ChatModel with ChangeNotifier {
|
|||||||
final ChatUser me = ChatUser(
|
final ChatUser me = ChatUser(
|
||||||
uid:"",
|
uid:"",
|
||||||
name: "me",
|
name: "me",
|
||||||
customProperties: Map()..["id"] = clientModeID
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final _scroller = ScrollController();
|
||||||
|
|
||||||
var _currentID = clientModeID;
|
var _currentID = clientModeID;
|
||||||
|
|
||||||
get messages => _messages;
|
ScrollController get scroller => _scroller;
|
||||||
|
|
||||||
get currentID => _currentID;
|
Map<int, List<ChatMessage>> get messages => _messages;
|
||||||
|
|
||||||
|
int get currentID => _currentID;
|
||||||
|
|
||||||
|
changeCurrentID(int id){
|
||||||
|
if(_messages.containsKey(id)){
|
||||||
|
_currentID = id;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
receive(int id, String text) {
|
receive(int id, String text) {
|
||||||
if (text.isEmpty) return;
|
if (text.isEmpty) return;
|
||||||
@ -32,18 +42,36 @@ class ChatModel with ChangeNotifier {
|
|||||||
if (iconOverlayEntry == null) {
|
if (iconOverlayEntry == null) {
|
||||||
showChatIconOverlay();
|
showChatIconOverlay();
|
||||||
}
|
}
|
||||||
|
late final chatUser;
|
||||||
|
if(id == clientModeID){
|
||||||
|
chatUser = ChatUser(
|
||||||
|
name: FFI.ffiModel.pi.username,
|
||||||
|
uid: FFI.getId(),
|
||||||
|
);
|
||||||
|
}else{
|
||||||
|
chatUser = FFI.serverModel.clients[id]?.chatUser;
|
||||||
|
}
|
||||||
|
if(chatUser == null){
|
||||||
|
return debugPrint("Failed to receive msg,user doesn't exist");
|
||||||
|
}
|
||||||
if(!_messages.containsKey(id)){
|
if(!_messages.containsKey(id)){
|
||||||
_messages[id] = [];
|
_messages[id] = [];
|
||||||
}
|
}
|
||||||
// TODO peer info
|
_messages[id]!.add(ChatMessage(
|
||||||
_messages[id]?.add(ChatMessage(
|
|
||||||
text: text,
|
text: text,
|
||||||
user: ChatUser(
|
user: chatUser));
|
||||||
name: FFI.ffiModel.pi.username,
|
|
||||||
uid: FFI.getId(),
|
|
||||||
)));
|
|
||||||
_currentID = id;
|
_currentID = id;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
scrollToBottom();
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollToBottom(){
|
||||||
|
Future.delayed(Duration(milliseconds: 500), () {
|
||||||
|
_scroller.animateTo(
|
||||||
|
_scroller.position.maxScrollExtent,
|
||||||
|
duration: Duration(milliseconds: 200),
|
||||||
|
curve: Curves.fastLinearToSlowEaseIn);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
send(ChatMessage message) {
|
send(ChatMessage message) {
|
||||||
@ -59,13 +87,12 @@ class ChatModel with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
scrollToBottom();
|
||||||
}
|
}
|
||||||
|
|
||||||
release() {
|
close() {
|
||||||
hideChatIconOverlay();
|
hideChatIconOverlay();
|
||||||
hideChatWindowOverlay();
|
hideChatWindowOverlay();
|
||||||
_messages.forEach((key, value) => value.clear());
|
|
||||||
_messages.clear();
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -722,7 +722,7 @@ class FFI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void close() {
|
static void close() {
|
||||||
chatModel.release();
|
chatModel.close();
|
||||||
if (FFI.imageModel.image != null && !isDesktop) {
|
if (FFI.imageModel.image != null && !isDesktop) {
|
||||||
savePreference(id, cursorModel.x, cursorModel.y, canvasModel.x,
|
savePreference(id, cursorModel.x, cursorModel.y, canvasModel.x,
|
||||||
canvasModel.y, canvasModel.scale, ffiModel.pi.currentDisplay);
|
canvasModel.y, canvasModel.scale, ffiModel.pi.currentDisplay);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'package:dash_chat/dash_chat.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import '../common.dart';
|
import '../common.dart';
|
||||||
import '../pages/server_page.dart';
|
import '../pages/server_page.dart';
|
||||||
@ -17,7 +18,7 @@ class ServerModel with ChangeNotifier {
|
|||||||
final _serverId = TextEditingController(text: _emptyIdShow);
|
final _serverId = TextEditingController(text: _emptyIdShow);
|
||||||
final _serverPasswd = TextEditingController(text: "");
|
final _serverPasswd = TextEditingController(text: "");
|
||||||
|
|
||||||
List<Client> _clients = [];
|
Map<int,Client> _clients = {};
|
||||||
|
|
||||||
bool get isStart => _isStart;
|
bool get isStart => _isStart;
|
||||||
|
|
||||||
@ -33,7 +34,7 @@ class ServerModel with ChangeNotifier {
|
|||||||
|
|
||||||
TextEditingController get serverPasswd => _serverPasswd;
|
TextEditingController get serverPasswd => _serverPasswd;
|
||||||
|
|
||||||
List<Client> get clients => _clients;
|
Map<int,Client> get clients => _clients;
|
||||||
|
|
||||||
ServerModel() {
|
ServerModel() {
|
||||||
()async{
|
()async{
|
||||||
@ -191,9 +192,11 @@ class ServerModel with ChangeNotifier {
|
|||||||
var res = FFI.getByName("clients_state");
|
var res = FFI.getByName("clients_state");
|
||||||
try {
|
try {
|
||||||
final List clientsJson = jsonDecode(res);
|
final List clientsJson = jsonDecode(res);
|
||||||
_clients = clientsJson
|
for (var clientJson in clientsJson){
|
||||||
.map((clientJson) => Client.fromJson(jsonDecode(res)))
|
final client = Client.fromJson(jsonDecode(clientJson));
|
||||||
.toList();
|
_clients[client.id] = client;
|
||||||
|
}
|
||||||
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
}
|
}
|
||||||
@ -204,7 +207,7 @@ class ServerModel with ChangeNotifier {
|
|||||||
final Map<String, dynamic> response = Map();
|
final Map<String, dynamic> response = Map();
|
||||||
response["id"] = client.id;
|
response["id"] = client.id;
|
||||||
DialogManager.show((setState, close) => CustomAlertDialog(
|
DialogManager.show((setState, close) => CustomAlertDialog(
|
||||||
title: Text(client.isFileTransfer?"File":"Screen" + "Control Request"),
|
title: Text(translate(client.isFileTransfer?"File Connection":"Screen Connection")),
|
||||||
content: Column(
|
content: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
@ -234,7 +237,7 @@ class ServerModel with ChangeNotifier {
|
|||||||
"start_capture"); // to Android service
|
"start_capture"); // to Android service
|
||||||
debugPrint("_toAndroidStartCapture:$res");
|
debugPrint("_toAndroidStartCapture:$res");
|
||||||
}
|
}
|
||||||
_clients.add(client);
|
_clients[client.id] = client;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
close();
|
close();
|
||||||
}),
|
}),
|
||||||
@ -246,7 +249,8 @@ class ServerModel with ChangeNotifier {
|
|||||||
|
|
||||||
void onClientAuthorized(Map<String, dynamic> evt) {
|
void onClientAuthorized(Map<String, dynamic> evt) {
|
||||||
try{
|
try{
|
||||||
_clients.add(Client.fromJson(jsonDecode(evt['client'])));
|
final client = Client.fromJson(jsonDecode(evt['client']));
|
||||||
|
_clients[client.id] = client;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}catch(e){
|
}catch(e){
|
||||||
|
|
||||||
@ -256,8 +260,7 @@ class ServerModel with ChangeNotifier {
|
|||||||
void onClientRemove(Map<String, dynamic> evt) {
|
void onClientRemove(Map<String, dynamic> evt) {
|
||||||
try {
|
try {
|
||||||
final id = int.parse(evt['id'] as String);
|
final id = int.parse(evt['id'] as String);
|
||||||
Client client = _clients.singleWhere((c) => c.id == id);
|
_clients.remove(id);
|
||||||
_clients.remove(client);
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// singleWhere fail ,reset the login dialog
|
// singleWhere fail ,reset the login dialog
|
||||||
@ -267,10 +270,10 @@ class ServerModel with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
closeAll() {
|
closeAll() {
|
||||||
_clients.forEach((client) {
|
_clients.forEach((id,client) {
|
||||||
FFI.setByName("close_conn", client.id.toString());
|
FFI.setByName("close_conn", id.toString());
|
||||||
});
|
});
|
||||||
_clients = [];
|
_clients.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,6 +286,7 @@ class Client {
|
|||||||
bool keyboard = false;
|
bool keyboard = false;
|
||||||
bool clipboard = false;
|
bool clipboard = false;
|
||||||
bool audio = false;
|
bool audio = false;
|
||||||
|
late ChatUser chatUser;
|
||||||
|
|
||||||
Client(this.authorized, this.isFileTransfer, this.name, this.peerId,this.keyboard,this.clipboard,this.audio);
|
Client(this.authorized, this.isFileTransfer, this.name, this.peerId,this.keyboard,this.clipboard,this.audio);
|
||||||
|
|
||||||
@ -295,6 +299,10 @@ class Client {
|
|||||||
keyboard= json['keyboard'];
|
keyboard= json['keyboard'];
|
||||||
clipboard= json['clipboard'];
|
clipboard= json['clipboard'];
|
||||||
audio= json['audio'];
|
audio= json['audio'];
|
||||||
|
chatUser = ChatUser(
|
||||||
|
uid:peerId,
|
||||||
|
name: name,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
|
@ -20,23 +20,47 @@ class ChatPage extends StatelessWidget implements PageShape {
|
|||||||
final icon = Icon(Icons.chat);
|
final icon = Icon(Icons.chat);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
final appBarActions = [];
|
final appBarActions = [
|
||||||
|
PopupMenuButton<int>(
|
||||||
|
icon: Icon(Icons.list_alt),
|
||||||
|
itemBuilder: (context) {
|
||||||
|
final chatModel = FFI.chatModel;
|
||||||
|
final serverModel = FFI.serverModel;
|
||||||
|
return chatModel.messages.entries.map((entry) {
|
||||||
|
final id = entry.key;
|
||||||
|
final user = serverModel.clients[id]?.chatUser ?? chatModel.me;
|
||||||
|
return PopupMenuItem<int>(
|
||||||
|
child: Text("${user.name} - ${user.uid}"),
|
||||||
|
value: id,
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
|
},
|
||||||
|
onSelected: (id) {
|
||||||
|
FFI.chatModel.changeCurrentID(id);
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return ChangeNotifierProvider.value(
|
||||||
color: MyTheme.grayBg,
|
value: FFI.chatModel,
|
||||||
child: Consumer<ChatModel>(builder: (context, chatModel, child) {
|
child: Container(
|
||||||
return DashChat(
|
color: MyTheme.grayBg,
|
||||||
inputContainerStyle: BoxDecoration(color: Colors.white70),
|
child: Consumer<ChatModel>(builder: (context, chatModel, child) {
|
||||||
sendOnEnter: false, // if true,reload keyboard everytime,need fix
|
return DashChat(
|
||||||
onSend: (chatMsg) {
|
inputContainerStyle: BoxDecoration(color: Colors.white70),
|
||||||
chatModel.send(chatMsg);
|
sendOnEnter: false,
|
||||||
},
|
// if true,reload keyboard everytime,need fix
|
||||||
user: chatModel.me,
|
onSend: (chatMsg) {
|
||||||
messages: chatModel.messages[chatModel.currentID] ?? [],
|
chatModel.send(chatMsg);
|
||||||
);
|
},
|
||||||
}));
|
user: chatModel.me,
|
||||||
|
messages: chatModel.messages[chatModel.currentID] ?? [],
|
||||||
|
// default scrollToBottom has bug https://github.com/fayeed/dash_chat/issues/53
|
||||||
|
scrollToBottom: false,
|
||||||
|
scrollController: chatModel.scroller,
|
||||||
|
);
|
||||||
|
})));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,24 +233,30 @@ class _ChatWindowOverlayState extends State<ChatWindowOverlay> {
|
|||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Padding(padding: EdgeInsets.symmetric(horizontal: 15),child: Text(
|
Padding(
|
||||||
translate("Chat"),
|
padding: EdgeInsets.symmetric(horizontal: 15),
|
||||||
style: TextStyle(
|
child: Text(
|
||||||
color: Colors.white,
|
translate("Chat"),
|
||||||
fontFamily: 'WorkSans',
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.bold,
|
color: Colors.white,
|
||||||
fontSize: 20),
|
fontFamily: 'WorkSans',
|
||||||
)),
|
fontWeight: FontWeight.bold,
|
||||||
|
fontSize: 20),
|
||||||
|
)),
|
||||||
Row(
|
Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
IconButton(onPressed: () {
|
IconButton(
|
||||||
hideChatWindowOverlay();
|
onPressed: () {
|
||||||
}, icon: Icon(Icons.keyboard_arrow_down)),
|
hideChatWindowOverlay();
|
||||||
IconButton(onPressed: () {
|
},
|
||||||
hideChatWindowOverlay();
|
icon: Icon(Icons.keyboard_arrow_down)),
|
||||||
hideChatIconOverlay();
|
IconButton(
|
||||||
}, icon: Icon(Icons.close))
|
onPressed: () {
|
||||||
|
hideChatWindowOverlay();
|
||||||
|
hideChatIconOverlay();
|
||||||
|
},
|
||||||
|
icon: Icon(Icons.close))
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
@ -45,8 +45,9 @@ class _FileManagerPageState extends State<FileManagerPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) =>
|
Widget build(BuildContext context) => ChangeNotifierProvider.value(
|
||||||
Consumer<FileModel>(builder: (_context, _model, _child) {
|
value: FFI.fileModel,
|
||||||
|
child: Consumer<FileModel>(builder: (_context, _model, _child) {
|
||||||
return WillPopScope(
|
return WillPopScope(
|
||||||
onWillPop: () async {
|
onWillPop: () async {
|
||||||
if (model.selectMode) {
|
if (model.selectMode) {
|
||||||
@ -76,7 +77,7 @@ class _FileManagerPageState extends State<FileManagerPage> {
|
|||||||
body: body(),
|
body: body(),
|
||||||
bottomSheet: bottomSheet(),
|
bottomSheet: bottomSheet(),
|
||||||
));
|
));
|
||||||
});
|
}));
|
||||||
|
|
||||||
bool needShowCheckBox() {
|
bool needShowCheckBox() {
|
||||||
if (!model.selectMode) {
|
if (!model.selectMode) {
|
||||||
@ -260,8 +261,8 @@ class _FileManagerPageState extends State<FileManagerPage> {
|
|||||||
itemBuilder: (context) {
|
itemBuilder: (context) {
|
||||||
return SortBy.values
|
return SortBy.values
|
||||||
.map((e) => PopupMenuItem(
|
.map((e) => PopupMenuItem(
|
||||||
child: Text(
|
child:
|
||||||
translate(e.toString().split(".").last)),
|
Text(translate(e.toString().split(".").last)),
|
||||||
value: e,
|
value: e,
|
||||||
))
|
))
|
||||||
.toList();
|
.toList();
|
||||||
@ -380,7 +381,6 @@ class _FileManagerPageState extends State<FileManagerPage> {
|
|||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.all(2),
|
padding: EdgeInsets.all(2),
|
||||||
// TODO
|
|
||||||
child: Text(
|
child: Text(
|
||||||
"${translate("Total")}: ${model.currentDir.entries.length}${translate("items")}",
|
"${translate("Total")}: ${model.currentDir.entries.length}${translate("items")}",
|
||||||
style: TextStyle(color: MyTheme.darkGray),
|
style: TextStyle(color: MyTheme.darkGray),
|
||||||
@ -394,7 +394,7 @@ class _FileManagerPageState extends State<FileManagerPage> {
|
|||||||
Widget? bottomSheet() {
|
Widget? bottomSheet() {
|
||||||
final state = model.jobState;
|
final state = model.jobState;
|
||||||
final isOtherPage = _selectedItems.isOtherPage(model.isLocal);
|
final isOtherPage = _selectedItems.isOtherPage(model.isLocal);
|
||||||
final selectedItemsLength = "${_selectedItems.length} ${translate("items")}"; // TODO t
|
final selectedItemsLen = "${_selectedItems.length} ${translate("items")}";
|
||||||
final local = _selectedItems.isLocal == null
|
final local = _selectedItems.isLocal == null
|
||||||
? ""
|
? ""
|
||||||
: " [${_selectedItems.isLocal! ? translate("Local") : translate("Remote")}]";
|
: " [${_selectedItems.isLocal! ? translate("Local") : translate("Remote")}]";
|
||||||
@ -405,7 +405,7 @@ class _FileManagerPageState extends State<FileManagerPage> {
|
|||||||
return BottomSheetBody(
|
return BottomSheetBody(
|
||||||
leading: Icon(Icons.check),
|
leading: Icon(Icons.check),
|
||||||
title: translate("Selected"),
|
title: translate("Selected"),
|
||||||
text: selectedItemsLength + local,
|
text: selectedItemsLen + local,
|
||||||
onCanceled: () => model.toggleSelectMode(),
|
onCanceled: () => model.toggleSelectMode(),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
@ -422,7 +422,7 @@ class _FileManagerPageState extends State<FileManagerPage> {
|
|||||||
return BottomSheetBody(
|
return BottomSheetBody(
|
||||||
leading: Icon(Icons.input),
|
leading: Icon(Icons.input),
|
||||||
title: translate("Paste here?"),
|
title: translate("Paste here?"),
|
||||||
text: selectedItemsLength + local,
|
text: selectedItemsLen + local,
|
||||||
onCanceled: () => model.toggleSelectMode(),
|
onCanceled: () => model.toggleSelectMode(),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
@ -441,7 +441,8 @@ class _FileManagerPageState extends State<FileManagerPage> {
|
|||||||
return BottomSheetBody(
|
return BottomSheetBody(
|
||||||
leading: CircularProgressIndicator(),
|
leading: CircularProgressIndicator(),
|
||||||
title: translate("Waiting"),
|
title: translate("Waiting"),
|
||||||
text: "${translate("Speed")}: ${readableFileSize(model.jobProgress.speed)}/s",
|
text:
|
||||||
|
"${translate("Speed")}: ${readableFileSize(model.jobProgress.speed)}/s",
|
||||||
onCanceled: null,
|
onCanceled: null,
|
||||||
);
|
);
|
||||||
case JobState.done:
|
case JobState.done:
|
||||||
|
@ -37,20 +37,22 @@ class ServerPage extends StatelessWidget implements PageShape {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
checkService();
|
checkService();
|
||||||
return Consumer<ServerModel>(
|
return ChangeNotifierProvider.value(
|
||||||
builder: (context, serverModel, child) => SingleChildScrollView(
|
value: FFI.serverModel,
|
||||||
child: Center(
|
child: Consumer<ServerModel>(
|
||||||
child: Column(
|
builder: (context, serverModel, child) => SingleChildScrollView(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
child: Center(
|
||||||
children: [
|
child: Column(
|
||||||
ServerInfo(),
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
PermissionChecker(),
|
children: [
|
||||||
ConnectionManager(),
|
ServerInfo(),
|
||||||
SizedBox.fromSize(size: Size(0, 15.0)), // Bottom padding
|
PermissionChecker(),
|
||||||
],
|
ConnectionManager(),
|
||||||
),
|
SizedBox.fromSize(size: Size(0, 15.0)),
|
||||||
),
|
],
|
||||||
));
|
),
|
||||||
|
),
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,7 +157,7 @@ class _PermissionCheckerState extends State<PermissionChecker> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final serverModel = Provider.of<ServerModel>(context);
|
final serverModel = Provider.of<ServerModel>(context);
|
||||||
final hasAudioPermission = androidVersion>=30;
|
final hasAudioPermission = androidVersion >= 30;
|
||||||
return PaddingCard(
|
return PaddingCard(
|
||||||
title: translate("Configuration Permissions"),
|
title: translate("Configuration Permissions"),
|
||||||
child: Column(
|
child: Column(
|
||||||
@ -167,8 +169,13 @@ class _PermissionCheckerState extends State<PermissionChecker> {
|
|||||||
serverModel.toggleInput),
|
serverModel.toggleInput),
|
||||||
PermissionRow(translate("File Transfer"), serverModel.fileOk,
|
PermissionRow(translate("File Transfer"), serverModel.fileOk,
|
||||||
serverModel.toggleFile),
|
serverModel.toggleFile),
|
||||||
hasAudioPermission?PermissionRow(translate("Audio Capture"), serverModel.audioOk,
|
hasAudioPermission
|
||||||
serverModel.toggleAudio):Text("* ${translate("android_version_audio_tip")}",style: TextStyle(color: MyTheme.darkGray),),
|
? PermissionRow(translate("Audio Capture"), serverModel.audioOk,
|
||||||
|
serverModel.toggleAudio)
|
||||||
|
: Text(
|
||||||
|
"* ${translate("android_version_audio_tip")}",
|
||||||
|
style: TextStyle(color: MyTheme.darkGray),
|
||||||
|
),
|
||||||
SizedBox(height: 8),
|
SizedBox(height: 8),
|
||||||
serverModel.mediaOk
|
serverModel.mediaOk
|
||||||
? ElevatedButton.icon(
|
? ElevatedButton.icon(
|
||||||
@ -216,7 +223,7 @@ class PermissionRow extends StatelessWidget {
|
|||||||
TextButton(
|
TextButton(
|
||||||
onPressed: onPressed,
|
onPressed: onPressed,
|
||||||
child: Text(
|
child: Text(
|
||||||
translate(isOk ?"CLOSE":"OPEN"),
|
translate(isOk ? "CLOSE" : "OPEN"),
|
||||||
style: TextStyle(fontWeight: FontWeight.bold),
|
style: TextStyle(fontWeight: FontWeight.bold),
|
||||||
)),
|
)),
|
||||||
const Divider(height: 0)
|
const Divider(height: 0)
|
||||||
@ -230,16 +237,20 @@ class ConnectionManager extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final serverModel = Provider.of<ServerModel>(context);
|
final serverModel = Provider.of<ServerModel>(context);
|
||||||
return Column(
|
return Column(
|
||||||
children: serverModel.clients
|
children: serverModel.clients.entries
|
||||||
.map((client) => PaddingCard(
|
.map((entry) => PaddingCard(
|
||||||
title: translate(client.isFileTransfer?"File Connection":"Screen Connection"),
|
title: translate(entry.value.isFileTransfer
|
||||||
titleIcon: client.isFileTransfer?Icons.folder_outlined:Icons.mobile_screen_share,
|
? "File Connection"
|
||||||
|
: "Screen Connection"),
|
||||||
|
titleIcon: entry.value.isFileTransfer
|
||||||
|
? Icons.folder_outlined
|
||||||
|
: Icons.mobile_screen_share,
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.symmetric(vertical: 5.0),
|
padding: EdgeInsets.symmetric(vertical: 5.0),
|
||||||
child: clientInfo(client),
|
child: clientInfo(entry.value),
|
||||||
),
|
),
|
||||||
ElevatedButton.icon(
|
ElevatedButton.icon(
|
||||||
style: ButtonStyle(
|
style: ButtonStyle(
|
||||||
@ -247,7 +258,7 @@ class ConnectionManager extends StatelessWidget {
|
|||||||
MaterialStateProperty.all(Colors.red)),
|
MaterialStateProperty.all(Colors.red)),
|
||||||
icon: Icon(Icons.close),
|
icon: Icon(Icons.close),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
FFI.setByName("close_conn", client.id.toString());
|
FFI.setByName("close_conn", entry.key.toString());
|
||||||
},
|
},
|
||||||
label: Text(translate("Close")))
|
label: Text(translate("Close")))
|
||||||
],
|
],
|
||||||
@ -257,7 +268,7 @@ class ConnectionManager extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class PaddingCard extends StatelessWidget {
|
class PaddingCard extends StatelessWidget {
|
||||||
PaddingCard({required this.child, this.title,this.titleIcon});
|
PaddingCard({required this.child, this.title, this.titleIcon});
|
||||||
|
|
||||||
final String? title;
|
final String? title;
|
||||||
final IconData? titleIcon;
|
final IconData? titleIcon;
|
||||||
@ -273,7 +284,12 @@ class PaddingCard extends StatelessWidget {
|
|||||||
padding: EdgeInsets.symmetric(vertical: 5.0),
|
padding: EdgeInsets.symmetric(vertical: 5.0),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
titleIcon !=null?Padding(padding: EdgeInsets.only(right: 10),child:Icon(titleIcon,color: MyTheme.accent80,size: 30)):SizedBox.shrink(),
|
titleIcon != null
|
||||||
|
? Padding(
|
||||||
|
padding: EdgeInsets.only(right: 10),
|
||||||
|
child: Icon(titleIcon,
|
||||||
|
color: MyTheme.accent80, size: 30))
|
||||||
|
: SizedBox.shrink(),
|
||||||
Text(
|
Text(
|
||||||
title!,
|
title!,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
@ -284,7 +300,7 @@ class PaddingCard extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
) ));
|
)));
|
||||||
}
|
}
|
||||||
return Container(
|
return Container(
|
||||||
width: double.maxFinite,
|
width: double.maxFinite,
|
||||||
@ -302,28 +318,27 @@ class PaddingCard extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget clientInfo(Client client) {
|
Widget clientInfo(Client client) {
|
||||||
return Column(
|
return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||||
crossAxisAlignment: CrossAxisAlignment.start
|
|
||||||
,children: [
|
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
CircleAvatar(
|
CircleAvatar(
|
||||||
child: Text(client.name[0]), backgroundColor: MyTheme.border),
|
child: Text(client.name[0]), backgroundColor: MyTheme.border),
|
||||||
SizedBox(width: 12),
|
SizedBox(width: 12),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisAlignment: MainAxisAlignment.center
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
,children: [
|
children: [
|
||||||
Text(client.name, style: TextStyle(color: MyTheme.idColor,fontSize: 20)),
|
Text(client.name,
|
||||||
SizedBox(width: 8),
|
style: TextStyle(color: MyTheme.idColor, fontSize: 20)),
|
||||||
Text(client.peerId, style: TextStyle(color: MyTheme.idColor,fontSize: 10))
|
SizedBox(width: 8),
|
||||||
])
|
Text(client.peerId,
|
||||||
|
style: TextStyle(color: MyTheme.idColor, fontSize: 10))
|
||||||
|
])
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void toAndroidChannelInit() {
|
void toAndroidChannelInit() {
|
||||||
FFI.setMethodCallHandler((method, arguments) {
|
FFI.setMethodCallHandler((method, arguments) {
|
||||||
debugPrint("flutter got android msg,$method,$arguments");
|
debugPrint("flutter got android msg,$method,$arguments");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user