The noVNC console was disabled in iOS and was only available in
android.

To fix the issue enabled the noVNC console view on iOS devices. The
changes also includes a refactor of the function responsible for
displaying the webview. Additionally, an `AppBar` has been added
to the console view to allow users to easily close the view.

The `dart format` command was also ran in the file to fix the file
formatting.

Signed-off-by: Shan Shaji <s.sh...@proxmox.com>
---
 
 changes since v1: 
 - Udpated the commit message. 
 - Rebased with master. 

 lib/widgets/pve_console_menu_widget.dart | 175 +++++++++++------------
 1 file changed, 83 insertions(+), 92 deletions(-)

diff --git a/lib/widgets/pve_console_menu_widget.dart 
b/lib/widgets/pve_console_menu_widget.dart
index 473595d..281cad1 100644
--- a/lib/widgets/pve_console_menu_widget.dart
+++ b/lib/widgets/pve_console_menu_widget.dart
@@ -97,45 +97,19 @@ class PveConsoleMenu extends StatelessWidget {
                   }
                 },
               ),
-            if (Platform.isAndroid) // web_view is only available for mobile :(
+
+            // web_view is only available for mobile :(
+            // xterm.js doesn't work that well on mobile
+            if (Platform.isAndroid || Platform.isIOS)
               ListTile(
                 title: const Text(
-                  //type == "qemu" ? "noVNC Console" : "xterm.js Console",
-                  "noVNC Console", // xterm.js doesn't work that well on mobile
+                  "noVNC Console",
                   style: TextStyle(fontWeight: FontWeight.bold),
                 ),
                 subtitle: const Text("Open console view"),
-                onTap: () async {
-                  if (Platform.isAndroid) {
-                    if (['qemu', 'lxc'].contains(type)) {
-                      SystemChrome.setEnabledSystemUIMode(
-                          SystemUiMode.immersive);
-                      Navigator.of(context)
-                          .push(_createHTMLConsoleRoute())
-                          .then((completion) {
-                        SystemChrome.setEnabledSystemUIMode(
-                            SystemUiMode.edgeToEdge,
-                            overlays: [
-                              SystemUiOverlay.top,
-                              SystemUiOverlay.bottom
-                            ]);
-                      });
-                    } else if (type == 'node') {
-                      SystemChrome.setEnabledSystemUIMode(
-                          SystemUiMode.immersive);
-                      Navigator.of(context)
-                          .push(_createHTMLConsoleRoute())
-                          .then((completion) {
-                        SystemChrome.setEnabledSystemUIMode(
-                            SystemUiMode.edgeToEdge,
-                            overlays: [
-                              SystemUiOverlay.top,
-                              SystemUiOverlay.bottom
-                            ]);
-                      });
-                    }
-                  } else {
-                    print('not implemented for current platform');
+                onTap: () {
+                  if (['qemu', 'lxc'].contains(type) || type == 'node') {
+                    _openNoVncConsole(context);
                   }
                 },
               ),
@@ -145,6 +119,18 @@ class PveConsoleMenu extends StatelessWidget {
     );
   }
 
+  Future<void> _openNoVncConsole(BuildContext context) async {
+    SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive);
+    await Navigator.push(context, _createHTMLConsoleRoute());
+    SystemChrome.setEnabledSystemUIMode(
+      SystemUiMode.edgeToEdge,
+      overlays: [
+        SystemUiOverlay.top,
+        SystemUiOverlay.bottom,
+      ],
+    );
+  }
+
   void showTextDialog(BuildContext context, String title, String content) {
     showDialog(
       context: context,
@@ -226,74 +212,79 @@ class PVEWebConsoleState extends State<PVEWebConsole> {
     WidgetsFlutterBinding.ensureInitialized();
 
     return FutureBuilder(
-        future: CookieManager.instance().setCookie(
-          url: WebUri(consoleUrl),
-          name: 'PVEAuthCookie',
-          value: ticket,
-        ),
-        builder: (context, snapshot) {
-          return SafeArea(
-            child: InAppWebView(
-              onReceivedServerTrustAuthRequest: (controller, challenge) async {
-                final cert = challenge.protectionSpace.sslCertificate;
-                final certBytes = cert?.x509Certificate?.encoded;
-                final sslError = challenge.protectionSpace.sslError?.message;
+      future: CookieManager.instance().setCookie(
+        url: WebUri(consoleUrl),
+        name: 'PVEAuthCookie',
+        value: ticket,
+      ),
+      builder: (context, snapshot) {
+        return Scaffold(
+          appBar: AppBar(),
+          body: InAppWebView(
+            onReceivedServerTrustAuthRequest: (controller, challenge) async {
+              final cert = challenge.protectionSpace.sslCertificate;
+              final certBytes = cert?.x509Certificate?.encoded;
+              final sslError = challenge.protectionSpace.sslError?.message;
 
-                String? issuedTo = cert?.issuedTo?.CName.toString();
-                String? hash = certBytes != null
-                    ? sha256.convert(certBytes).toString()
-                    : null;
+              String? issuedTo = cert?.issuedTo?.CName.toString();
+              String? hash = certBytes != null
+                  ? sha256.convert(certBytes).toString()
+                  : null;
 
-                final settings =
-                    await ProxmoxGeneralSettingsModel.fromLocalStorage();
+              final settings =
+                  await ProxmoxGeneralSettingsModel.fromLocalStorage();
 
-                bool trust = false;
-                if (hash != null && settings.trustedFingerprints != null) {
-                  trust = settings.trustedFingerprints!.contains(hash);
-                }
+              bool trust = false;
+              if (hash != null && settings.trustedFingerprints != null) {
+                trust = settings.trustedFingerprints!.contains(hash);
+              }
 
-                if (!trust) {
-                  // format hash to '01:23:...' format
-                  String? formattedHash = hash?.toUpperCase().replaceAllMapped(
-                      RegExp(r"[a-zA-Z0-9]{2}"),
-                      (match) => "${match.group(0)}:");
-                  formattedHash = formattedHash?.substring(
-                      0, formattedHash.length - 1); // remove last ':'
+              if (!trust) {
+                // format hash to '01:23:...' format
+                String? formattedHash = hash?.toUpperCase().replaceAllMapped(
+                    RegExp(r"[a-zA-Z0-9]{2}"), (match) => 
"${match.group(0)}:");
+                formattedHash = formattedHash?.substring(
+                    0, formattedHash.length - 1); // remove last ':'
 
-                  if (context.mounted) {
-                    trust = await showTLSWarning(
-                        context,
-                        sslError ?? 'An unknown TLS error has occurred',
-                        issuedTo ?? 'unknown',
-                        formattedHash ?? 'unknown');
-                  }
+                if (context.mounted) {
+                  trust = await showTLSWarning(
+                      context,
+                      sslError ?? 'An unknown TLS error has occurred',
+                      issuedTo ?? 'unknown',
+                      formattedHash ?? 'unknown');
                 }
+              }
 
-                // save Fingerprint
-                if (trust && hash != null) {
-                  await settings
-                      .rebuild((b) => b..trustedFingerprints.add(hash))
-                      .toLocalStorage();
-                  print(settings.toJson());
-                }
+              // save Fingerprint
+              if (trust && hash != null) {
+                await settings
+                    .rebuild((b) => b..trustedFingerprints.add(hash))
+                    .toLocalStorage();
+                print(settings.toJson());
+              }
 
-                final action = trust
-                    ? ServerTrustAuthResponseAction.PROCEED
-                    : ServerTrustAuthResponseAction.CANCEL;
-                return ServerTrustAuthResponse(action: action);
-              },
-              onWebViewCreated: (controller) {
-                webViewController = controller;
-                controller.loadUrl(
-                    urlRequest: URLRequest(url: WebUri(consoleUrl)));
-              },
-            ),
-          );
-        });
+              final action = trust
+                  ? ServerTrustAuthResponseAction.PROCEED
+                  : ServerTrustAuthResponseAction.CANCEL;
+              return ServerTrustAuthResponse(action: action);
+            },
+            onWebViewCreated: (controller) {
+              webViewController = controller;
+              controller.loadUrl(
+                  urlRequest: URLRequest(url: WebUri(consoleUrl)));
+            },
+          ),
+        );
+      },
+    );
   }
 
-  Future<bool> showTLSWarning(BuildContext context, String sslError,
-      String issuedTo, String hash) async {
+  Future<bool> showTLSWarning(
+    BuildContext context,
+    String sslError,
+    String issuedTo,
+    String hash,
+  ) async {
     return await showDialog(
         context: context,
         barrierDismissible: false,
-- 
2.50.1



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

Reply via email to