572 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			572 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
import 'package:flutter/material.dart';
 | 
						|
import 'package:flutter_hbb/mobile/widgets/dialog.dart';
 | 
						|
import 'package:provider/provider.dart';
 | 
						|
 | 
						|
import '../../common.dart';
 | 
						|
import '../../common/widgets/dialog.dart';
 | 
						|
import '../../models/platform_model.dart';
 | 
						|
import '../../models/server_model.dart';
 | 
						|
import 'home_page.dart';
 | 
						|
 | 
						|
class ServerPage extends StatefulWidget implements PageShape {
 | 
						|
  @override
 | 
						|
  final title = translate("Share Screen");
 | 
						|
 | 
						|
  @override
 | 
						|
  final icon = const Icon(Icons.mobile_screen_share);
 | 
						|
 | 
						|
  @override
 | 
						|
  final appBarActions = [
 | 
						|
    PopupMenuButton<String>(
 | 
						|
        icon: const Icon(Icons.more_vert),
 | 
						|
        itemBuilder: (context) {
 | 
						|
          return [
 | 
						|
            PopupMenuItem(
 | 
						|
              padding: const EdgeInsets.symmetric(horizontal: 16.0),
 | 
						|
              value: "changeID",
 | 
						|
              child: Text(translate("Change ID")),
 | 
						|
            ),
 | 
						|
            PopupMenuItem(
 | 
						|
              padding: const EdgeInsets.symmetric(horizontal: 16.0),
 | 
						|
              value: "setPermanentPassword",
 | 
						|
              enabled:
 | 
						|
                  gFFI.serverModel.verificationMethod != kUseTemporaryPassword,
 | 
						|
              child: Text(translate("Set permanent password")),
 | 
						|
            ),
 | 
						|
            PopupMenuItem(
 | 
						|
              padding: const EdgeInsets.symmetric(horizontal: 16.0),
 | 
						|
              value: "setTemporaryPasswordLength",
 | 
						|
              enabled:
 | 
						|
                  gFFI.serverModel.verificationMethod != kUsePermanentPassword,
 | 
						|
              child: Text(translate("Set temporary password length")),
 | 
						|
            ),
 | 
						|
            const PopupMenuDivider(),
 | 
						|
            PopupMenuItem(
 | 
						|
              padding: const EdgeInsets.symmetric(horizontal: 0.0),
 | 
						|
              value: kUseTemporaryPassword,
 | 
						|
              child: ListTile(
 | 
						|
                  title: Text(translate("Use temporary password")),
 | 
						|
                  trailing: Icon(
 | 
						|
                    Icons.check,
 | 
						|
                    color: gFFI.serverModel.verificationMethod ==
 | 
						|
                            kUseTemporaryPassword
 | 
						|
                        ? null
 | 
						|
                        : Colors.transparent,
 | 
						|
                  )),
 | 
						|
            ),
 | 
						|
            PopupMenuItem(
 | 
						|
              padding: const EdgeInsets.symmetric(horizontal: 0.0),
 | 
						|
              value: kUsePermanentPassword,
 | 
						|
              child: ListTile(
 | 
						|
                  title: Text(translate("Use permanent password")),
 | 
						|
                  trailing: Icon(
 | 
						|
                    Icons.check,
 | 
						|
                    color: gFFI.serverModel.verificationMethod ==
 | 
						|
                            kUsePermanentPassword
 | 
						|
                        ? null
 | 
						|
                        : Colors.transparent,
 | 
						|
                  )),
 | 
						|
            ),
 | 
						|
            PopupMenuItem(
 | 
						|
              padding: const EdgeInsets.symmetric(horizontal: 0.0),
 | 
						|
              value: kUseBothPasswords,
 | 
						|
              child: ListTile(
 | 
						|
                  title: Text(translate("Use both passwords")),
 | 
						|
                  trailing: Icon(
 | 
						|
                    Icons.check,
 | 
						|
                    color: gFFI.serverModel.verificationMethod !=
 | 
						|
                                kUseTemporaryPassword &&
 | 
						|
                            gFFI.serverModel.verificationMethod !=
 | 
						|
                                kUsePermanentPassword
 | 
						|
                        ? null
 | 
						|
                        : Colors.transparent,
 | 
						|
                  )),
 | 
						|
            ),
 | 
						|
          ];
 | 
						|
        },
 | 
						|
        onSelected: (value) {
 | 
						|
          if (value == "changeID") {
 | 
						|
            changeIdDialog();
 | 
						|
          } else if (value == "setPermanentPassword") {
 | 
						|
            setPermanentPasswordDialog(gFFI.dialogManager);
 | 
						|
          } else if (value == "setTemporaryPasswordLength") {
 | 
						|
            setTemporaryPasswordLengthDialog(gFFI.dialogManager);
 | 
						|
          } else if (value == kUsePermanentPassword ||
 | 
						|
              value == kUseTemporaryPassword ||
 | 
						|
              value == kUseBothPasswords) {
 | 
						|
            bind.mainSetOption(key: "verification-method", value: value);
 | 
						|
            gFFI.serverModel.updatePasswordModel();
 | 
						|
          }
 | 
						|
        })
 | 
						|
  ];
 | 
						|
 | 
						|
  ServerPage({Key? key}) : super(key: key);
 | 
						|
 | 
						|
  @override
 | 
						|
  State<StatefulWidget> createState() => _ServerPageState();
 | 
						|
}
 | 
						|
 | 
						|
class _ServerPageState extends State<ServerPage> {
 | 
						|
  @override
 | 
						|
  void initState() {
 | 
						|
    super.initState();
 | 
						|
    gFFI.serverModel.checkAndroidPermission();
 | 
						|
  }
 | 
						|
 | 
						|
  @override
 | 
						|
  Widget build(BuildContext context) {
 | 
						|
    checkService();
 | 
						|
    return ChangeNotifierProvider.value(
 | 
						|
        value: gFFI.serverModel,
 | 
						|
        child: Consumer<ServerModel>(
 | 
						|
            builder: (context, serverModel, child) => SingleChildScrollView(
 | 
						|
                  controller: gFFI.serverModel.controller,
 | 
						|
                  child: Center(
 | 
						|
                    child: Column(
 | 
						|
                      mainAxisAlignment: MainAxisAlignment.start,
 | 
						|
                      children: [
 | 
						|
                        ServerInfo(),
 | 
						|
                        const PermissionChecker(),
 | 
						|
                        const ConnectionManager(),
 | 
						|
                        SizedBox.fromSize(size: const Size(0, 15.0)),
 | 
						|
                      ],
 | 
						|
                    ),
 | 
						|
                  ),
 | 
						|
                )));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void checkService() async {
 | 
						|
  gFFI.invokeMethod("check_service"); // jvm
 | 
						|
  // for Android 10/11,MANAGE_EXTERNAL_STORAGE permission from a system setting page
 | 
						|
  if (PermissionManager.isWaitingFile() && !gFFI.serverModel.fileOk) {
 | 
						|
    PermissionManager.complete("file", await PermissionManager.check("file"));
 | 
						|
    debugPrint("file permission finished");
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
class ServerInfo extends StatelessWidget {
 | 
						|
  final model = gFFI.serverModel;
 | 
						|
  final emptyController = TextEditingController(text: "-");
 | 
						|
 | 
						|
  ServerInfo({Key? key}) : super(key: key);
 | 
						|
 | 
						|
  @override
 | 
						|
  Widget build(BuildContext context) {
 | 
						|
    final isPermanent = model.verificationMethod == kUsePermanentPassword;
 | 
						|
    return model.isStart
 | 
						|
        ? PaddingCard(
 | 
						|
            child: Column(
 | 
						|
            mainAxisSize: MainAxisSize.min,
 | 
						|
            children: [
 | 
						|
              TextFormField(
 | 
						|
                readOnly: true,
 | 
						|
                style: const TextStyle(
 | 
						|
                    fontSize: 25.0,
 | 
						|
                    fontWeight: FontWeight.bold,
 | 
						|
                    color: MyTheme.accent),
 | 
						|
                controller: model.serverId,
 | 
						|
                decoration: InputDecoration(
 | 
						|
                  icon: const Icon(Icons.perm_identity),
 | 
						|
                  labelText: translate("ID"),
 | 
						|
                  labelStyle: const TextStyle(
 | 
						|
                      fontWeight: FontWeight.bold, color: MyTheme.accent80),
 | 
						|
                ),
 | 
						|
                onSaved: (String? value) {},
 | 
						|
              ),
 | 
						|
              TextFormField(
 | 
						|
                readOnly: true,
 | 
						|
                style: const TextStyle(
 | 
						|
                    fontSize: 25.0,
 | 
						|
                    fontWeight: FontWeight.bold,
 | 
						|
                    color: MyTheme.accent),
 | 
						|
                controller: isPermanent ? emptyController : model.serverPasswd,
 | 
						|
                decoration: InputDecoration(
 | 
						|
                    icon: const Icon(Icons.lock),
 | 
						|
                    labelText: translate("Password"),
 | 
						|
                    labelStyle: const TextStyle(
 | 
						|
                        fontWeight: FontWeight.bold, color: MyTheme.accent80),
 | 
						|
                    suffix: isPermanent
 | 
						|
                        ? null
 | 
						|
                        : IconButton(
 | 
						|
                            icon: const Icon(Icons.refresh),
 | 
						|
                            onPressed: () =>
 | 
						|
                                bind.mainUpdateTemporaryPassword())),
 | 
						|
                onSaved: (String? value) {},
 | 
						|
              ),
 | 
						|
            ],
 | 
						|
          ))
 | 
						|
        : PaddingCard(
 | 
						|
            child: Column(
 | 
						|
            crossAxisAlignment: CrossAxisAlignment.center,
 | 
						|
            children: [
 | 
						|
              Center(
 | 
						|
                  child: Row(
 | 
						|
                children: [
 | 
						|
                  const Icon(Icons.warning_amber_sharp,
 | 
						|
                      color: Colors.redAccent, size: 24),
 | 
						|
                  const SizedBox(width: 10),
 | 
						|
                  Expanded(
 | 
						|
                      child: Text(
 | 
						|
                    translate("Service is not running"),
 | 
						|
                    style: const TextStyle(
 | 
						|
                      fontFamily: 'WorkSans',
 | 
						|
                      fontWeight: FontWeight.bold,
 | 
						|
                      fontSize: 18,
 | 
						|
                      color: MyTheme.accent,
 | 
						|
                    ),
 | 
						|
                  ))
 | 
						|
                ],
 | 
						|
              )),
 | 
						|
              const SizedBox(height: 5),
 | 
						|
              Center(
 | 
						|
                  child: Text(
 | 
						|
                translate("android_start_service_tip"),
 | 
						|
                style: const TextStyle(fontSize: 12, color: MyTheme.darkGray),
 | 
						|
              ))
 | 
						|
            ],
 | 
						|
          ));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
class PermissionChecker extends StatefulWidget {
 | 
						|
  const PermissionChecker({Key? key}) : super(key: key);
 | 
						|
 | 
						|
  @override
 | 
						|
  State<PermissionChecker> createState() => _PermissionCheckerState();
 | 
						|
}
 | 
						|
 | 
						|
class _PermissionCheckerState extends State<PermissionChecker> {
 | 
						|
  @override
 | 
						|
  Widget build(BuildContext context) {
 | 
						|
    final serverModel = Provider.of<ServerModel>(context);
 | 
						|
    final hasAudioPermission = androidVersion >= 30;
 | 
						|
    final String status;
 | 
						|
    if (serverModel.connectStatus == -1) {
 | 
						|
      status = 'not_ready_status';
 | 
						|
    } else if (serverModel.connectStatus == 0) {
 | 
						|
      status = 'connecting_status';
 | 
						|
    } else {
 | 
						|
      status = 'Ready';
 | 
						|
    }
 | 
						|
    return PaddingCard(
 | 
						|
        title: translate("Permissions"),
 | 
						|
        child: Column(
 | 
						|
          crossAxisAlignment: CrossAxisAlignment.start,
 | 
						|
          children: [
 | 
						|
            PermissionRow(translate("Screen Capture"), serverModel.mediaOk,
 | 
						|
                serverModel.toggleService),
 | 
						|
            PermissionRow(translate("Input Control"), serverModel.inputOk,
 | 
						|
                serverModel.toggleInput),
 | 
						|
            PermissionRow(translate("Transfer File"), serverModel.fileOk,
 | 
						|
                serverModel.toggleFile),
 | 
						|
            hasAudioPermission
 | 
						|
                ? PermissionRow(translate("Audio Capture"), serverModel.audioOk,
 | 
						|
                    serverModel.toggleAudio)
 | 
						|
                : Text(
 | 
						|
                    "* ${translate("android_version_audio_tip")}",
 | 
						|
                    style: const TextStyle(color: MyTheme.darkGray),
 | 
						|
                  ),
 | 
						|
            const SizedBox(height: 8),
 | 
						|
            Row(
 | 
						|
              crossAxisAlignment: CrossAxisAlignment.center,
 | 
						|
              children: [
 | 
						|
                Expanded(
 | 
						|
                    flex: 0,
 | 
						|
                    child: serverModel.mediaOk
 | 
						|
                        ? ElevatedButton.icon(
 | 
						|
                            style: ButtonStyle(
 | 
						|
                                backgroundColor:
 | 
						|
                                    MaterialStateProperty.all(Colors.red)),
 | 
						|
                            icon: const Icon(Icons.stop),
 | 
						|
                            onPressed: serverModel.toggleService,
 | 
						|
                            label: Text(translate("Stop service")))
 | 
						|
                        : ElevatedButton.icon(
 | 
						|
                            icon: const Icon(Icons.play_arrow),
 | 
						|
                            onPressed: serverModel.toggleService,
 | 
						|
                            label: Text(translate("Start Service")))),
 | 
						|
                Expanded(
 | 
						|
                    child: serverModel.mediaOk
 | 
						|
                        ? Row(
 | 
						|
                            children: [
 | 
						|
                              Expanded(
 | 
						|
                                  flex: 0,
 | 
						|
                                  child: Padding(
 | 
						|
                                      padding: const EdgeInsets.only(
 | 
						|
                                          left: 20, right: 5),
 | 
						|
                                      child: Icon(Icons.circle,
 | 
						|
                                          color: serverModel.connectStatus > 0
 | 
						|
                                              ? Colors.greenAccent
 | 
						|
                                              : Colors.deepOrangeAccent,
 | 
						|
                                          size: 10))),
 | 
						|
                              Expanded(
 | 
						|
                                  child: Text(translate(status),
 | 
						|
                                      softWrap: true,
 | 
						|
                                      style: const TextStyle(
 | 
						|
                                          fontSize: 14.0,
 | 
						|
                                          fontWeight: FontWeight.w500,
 | 
						|
                                          color: MyTheme.accent80)))
 | 
						|
                            ],
 | 
						|
                          )
 | 
						|
                        : const SizedBox.shrink())
 | 
						|
              ],
 | 
						|
            ),
 | 
						|
          ],
 | 
						|
        ));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
class PermissionRow extends StatelessWidget {
 | 
						|
  const PermissionRow(this.name, this.isOk, this.onPressed, {Key? key})
 | 
						|
      : super(key: key);
 | 
						|
 | 
						|
  final String name;
 | 
						|
  final bool isOk;
 | 
						|
  final VoidCallback onPressed;
 | 
						|
 | 
						|
  @override
 | 
						|
  Widget build(BuildContext context) {
 | 
						|
    return Row(
 | 
						|
      children: [
 | 
						|
        Expanded(
 | 
						|
            flex: 5,
 | 
						|
            child: FittedBox(
 | 
						|
                fit: BoxFit.scaleDown,
 | 
						|
                alignment: Alignment.centerLeft,
 | 
						|
                child:
 | 
						|
                    Text(name, style: Theme.of(context).textTheme.labelLarge))),
 | 
						|
        Expanded(
 | 
						|
          flex: 2,
 | 
						|
          child: FittedBox(
 | 
						|
              fit: BoxFit.scaleDown,
 | 
						|
              child: Text(isOk ? translate("ON") : translate("OFF"),
 | 
						|
                  style: TextStyle(
 | 
						|
                      fontSize: 16.0,
 | 
						|
                      color: isOk ? Colors.green : Colors.grey))),
 | 
						|
        ),
 | 
						|
        Expanded(
 | 
						|
            flex: 3,
 | 
						|
            child: FittedBox(
 | 
						|
                fit: BoxFit.scaleDown,
 | 
						|
                alignment: Alignment.centerRight,
 | 
						|
                child: TextButton(
 | 
						|
                    onPressed: onPressed,
 | 
						|
                    child: Text(
 | 
						|
                      translate(isOk ? "CLOSE" : "OPEN"),
 | 
						|
                      style: const TextStyle(fontWeight: FontWeight.bold),
 | 
						|
                    )))),
 | 
						|
      ],
 | 
						|
    );
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
class ConnectionManager extends StatelessWidget {
 | 
						|
  const ConnectionManager({Key? key}) : super(key: key);
 | 
						|
 | 
						|
  @override
 | 
						|
  Widget build(BuildContext context) {
 | 
						|
    final serverModel = Provider.of<ServerModel>(context);
 | 
						|
    return Column(
 | 
						|
        children: serverModel.clients
 | 
						|
            .map((client) => PaddingCard(
 | 
						|
                title: translate(client.isFileTransfer
 | 
						|
                    ? "File Connection"
 | 
						|
                    : "Screen Connection"),
 | 
						|
                titleIcon: client.isFileTransfer
 | 
						|
                    ? Icons.folder_outlined
 | 
						|
                    : Icons.mobile_screen_share,
 | 
						|
                child: Column(
 | 
						|
                  crossAxisAlignment: CrossAxisAlignment.start,
 | 
						|
                  children: [
 | 
						|
                    Row(
 | 
						|
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
						|
                      children: [
 | 
						|
                        Expanded(child: ClientInfo(client)),
 | 
						|
                        Expanded(
 | 
						|
                            flex: -1,
 | 
						|
                            child: client.isFileTransfer || !client.authorized
 | 
						|
                                ? const SizedBox.shrink()
 | 
						|
                                : IconButton(
 | 
						|
                                    onPressed: () {
 | 
						|
                                      gFFI.chatModel.changeCurrentID(client.id);
 | 
						|
                                      final bar =
 | 
						|
                                          navigationBarKey.currentWidget;
 | 
						|
                                      if (bar != null) {
 | 
						|
                                        bar as BottomNavigationBar;
 | 
						|
                                        bar.onTap!(1);
 | 
						|
                                      }
 | 
						|
                                    },
 | 
						|
                                    icon: const Icon(
 | 
						|
                                      Icons.chat,
 | 
						|
                                      color: MyTheme.accent,
 | 
						|
                                    )))
 | 
						|
                      ],
 | 
						|
                    ),
 | 
						|
                    client.authorized
 | 
						|
                        ? const SizedBox.shrink()
 | 
						|
                        : Text(
 | 
						|
                            translate("android_new_connection_tip"),
 | 
						|
                            style: Theme.of(globalKey.currentContext!)
 | 
						|
                                .textTheme
 | 
						|
                                .bodyMedium,
 | 
						|
                          ),
 | 
						|
                    client.authorized
 | 
						|
                        ? ElevatedButton.icon(
 | 
						|
                            style: ButtonStyle(
 | 
						|
                                backgroundColor:
 | 
						|
                                    MaterialStateProperty.all(Colors.red)),
 | 
						|
                            icon: const Icon(Icons.close),
 | 
						|
                            onPressed: () {
 | 
						|
                              bind.cmCloseConnection(connId: client.id);
 | 
						|
                              gFFI.invokeMethod(
 | 
						|
                                  "cancel_notification", client.id);
 | 
						|
                            },
 | 
						|
                            label: Text(translate("Close")))
 | 
						|
                        : Row(children: [
 | 
						|
                            TextButton(
 | 
						|
                                child: Text(translate("Dismiss")),
 | 
						|
                                onPressed: () {
 | 
						|
                                  serverModel.sendLoginResponse(client, false);
 | 
						|
                                }),
 | 
						|
                            const SizedBox(width: 20),
 | 
						|
                            ElevatedButton(
 | 
						|
                                child: Text(translate("Accept")),
 | 
						|
                                onPressed: () {
 | 
						|
                                  serverModel.sendLoginResponse(client, true);
 | 
						|
                                }),
 | 
						|
                          ]),
 | 
						|
                  ],
 | 
						|
                )))
 | 
						|
            .toList());
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
class PaddingCard extends StatelessWidget {
 | 
						|
  const PaddingCard({Key? key, required this.child, this.title, this.titleIcon})
 | 
						|
      : super(key: key);
 | 
						|
 | 
						|
  final String? title;
 | 
						|
  final IconData? titleIcon;
 | 
						|
  final Widget child;
 | 
						|
 | 
						|
  @override
 | 
						|
  Widget build(BuildContext context) {
 | 
						|
    final children = [child];
 | 
						|
    if (title != null) {
 | 
						|
      children.insert(
 | 
						|
          0,
 | 
						|
          Padding(
 | 
						|
              padding: const EdgeInsets.symmetric(vertical: 5.0),
 | 
						|
              child: Row(
 | 
						|
                children: [
 | 
						|
                  titleIcon != null
 | 
						|
                      ? Padding(
 | 
						|
                          padding: const EdgeInsets.only(right: 10),
 | 
						|
                          child:
 | 
						|
                              Icon(titleIcon, color: MyTheme.accent, size: 30))
 | 
						|
                      : const SizedBox.shrink(),
 | 
						|
                  Text(
 | 
						|
                    title!,
 | 
						|
                    style: const TextStyle(
 | 
						|
                      fontFamily: 'WorkSans',
 | 
						|
                      fontWeight: FontWeight.bold,
 | 
						|
                      fontSize: 20,
 | 
						|
                      color: MyTheme.accent,
 | 
						|
                    ),
 | 
						|
                  )
 | 
						|
                ],
 | 
						|
              )));
 | 
						|
    }
 | 
						|
    return SizedBox(
 | 
						|
        width: double.maxFinite,
 | 
						|
        child: Card(
 | 
						|
          margin: const EdgeInsets.fromLTRB(15.0, 15.0, 15.0, 0),
 | 
						|
          child: Padding(
 | 
						|
            padding:
 | 
						|
                const EdgeInsets.symmetric(vertical: 15.0, horizontal: 30.0),
 | 
						|
            child: Column(
 | 
						|
              crossAxisAlignment: CrossAxisAlignment.start,
 | 
						|
              children: children,
 | 
						|
            ),
 | 
						|
          ),
 | 
						|
        ));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
class ClientInfo extends StatelessWidget {
 | 
						|
  final Client client;
 | 
						|
  ClientInfo(this.client);
 | 
						|
 | 
						|
  @override
 | 
						|
  Widget build(BuildContext context) {
 | 
						|
    return Padding(
 | 
						|
        padding: const EdgeInsets.symmetric(vertical: 8),
 | 
						|
        child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
 | 
						|
          Row(
 | 
						|
            children: [
 | 
						|
              Expanded(
 | 
						|
                  flex: -1,
 | 
						|
                  child: Padding(
 | 
						|
                      padding: const EdgeInsets.only(right: 12),
 | 
						|
                      child: CircleAvatar(
 | 
						|
                          backgroundColor:
 | 
						|
                              str2color(client.name).withOpacity(0.7),
 | 
						|
                          child: Text(client.name[0])))),
 | 
						|
              Expanded(
 | 
						|
                  child: Column(
 | 
						|
                      crossAxisAlignment: CrossAxisAlignment.start,
 | 
						|
                      mainAxisAlignment: MainAxisAlignment.center,
 | 
						|
                      children: [
 | 
						|
                    Text(client.name,
 | 
						|
                        style: const TextStyle(
 | 
						|
                            color: MyTheme.idColor, fontSize: 18)),
 | 
						|
                    const SizedBox(width: 8),
 | 
						|
                    Text(client.peerId,
 | 
						|
                        style: const TextStyle(
 | 
						|
                            color: MyTheme.idColor, fontSize: 10))
 | 
						|
                  ]))
 | 
						|
            ],
 | 
						|
          ),
 | 
						|
        ]));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void androidChannelInit() {
 | 
						|
  gFFI.setMethodCallHandler((method, arguments) {
 | 
						|
    debugPrint("flutter got android msg,$method,$arguments");
 | 
						|
    try {
 | 
						|
      switch (method) {
 | 
						|
        case "start_capture":
 | 
						|
          {
 | 
						|
            gFFI.dialogManager.dismissAll();
 | 
						|
            gFFI.serverModel.updateClientState();
 | 
						|
            break;
 | 
						|
          }
 | 
						|
        case "on_state_changed":
 | 
						|
          {
 | 
						|
            var name = arguments["name"] as String;
 | 
						|
            var value = arguments["value"] as String == "true";
 | 
						|
            debugPrint("from jvm:on_state_changed,$name:$value");
 | 
						|
            gFFI.serverModel.changeStatue(name, value);
 | 
						|
            break;
 | 
						|
          }
 | 
						|
        case "on_android_permission_result":
 | 
						|
          {
 | 
						|
            var type = arguments["type"] as String;
 | 
						|
            var result = arguments["result"] as bool;
 | 
						|
            PermissionManager.complete(type, result);
 | 
						|
            break;
 | 
						|
          }
 | 
						|
        case "on_media_projection_canceled":
 | 
						|
          {
 | 
						|
            gFFI.serverModel.stopService();
 | 
						|
            break;
 | 
						|
          }
 | 
						|
      }
 | 
						|
    } catch (e) {
 | 
						|
      debugPrint("MethodCallHandler err:$e");
 | 
						|
    }
 | 
						|
    return "";
 | 
						|
  });
 | 
						|
}
 |