all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Shan Shaji <s.shaji@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [PATCH pve_flutter_frontend 2/4] fix: breaking changes due to the upgrade of font_awesome_flutter to v11
Date: Fri, 10 Apr 2026 17:09:30 +0200	[thread overview]
Message-ID: <20260410150935.25870-3-s.shaji@proxmox.com> (raw)
In-Reply-To: <20260410150935.25870-1-s.shaji@proxmox.com>

Previously, `FaIconData` extended `IconData`, but starting from
`v11.0.0`, `FaIconData` no longer implements `IconData` to prevent
rendering issues and to anticipate `IconData` being marked `final`
in an upcoming Flutter release, which will prevent subtyping outside
of its library.

Due to this change, the `Icon` widget can no longer directly accept
`FontAwesomeIcons`. To fix this, replace the `Icon` widget with
`FaIcon` wherever `FontAwesomeIcons` is used.

Signed-off-by: Shan Shaji <s.shaji@proxmox.com>
---
 lib/pages/main_layout_slim.dart               |  4 +-
 lib/utils/renderers.dart                      |  5 +--
 lib/widgets/pve_action_card_widget.dart       | 17 +++++++++
 lib/widgets/pve_file_selector_widget.dart     |  6 +--
 lib/widgets/pve_guest_backup_widget.dart      |  2 +-
 lib/widgets/pve_guest_migrate_widget.dart     |  4 +-
 lib/widgets/pve_guest_os_selector_widget.dart |  4 +-
 lib/widgets/pve_guest_overview_header.dart    |  4 +-
 lib/widgets/pve_lxc_overview.dart             | 32 +++++-----------
 lib/widgets/pve_node_overview.dart            |  6 +--
 lib/widgets/pve_qemu_overview.dart            | 38 +++++++------------
 .../pve_qemu_power_settings_widget.dart       |  4 +-
 pubspec.lock                                  |  4 +-
 pubspec.yaml                                  |  2 +-
 14 files changed, 63 insertions(+), 69 deletions(-)

diff --git a/lib/pages/main_layout_slim.dart b/lib/pages/main_layout_slim.dart
index 4229ef4..c8ab607 100644
--- a/lib/pages/main_layout_slim.dart
+++ b/lib/pages/main_layout_slim.dart
@@ -861,11 +861,11 @@ class AppBarFilterIconButton extends StatelessWidget {
         builder: (context, state) {
           return IconButton(
             icon: rBloc.isFiltered
-                ? const Icon(
+                ? const FaIcon(
                     FontAwesomeIcons.filter,
                     color: Colors.black,
                   )
-                : const Icon(
+                : const FaIcon(
                     FontAwesomeIcons.filter,
                     color: Colors.grey,
                   ),
diff --git a/lib/utils/renderers.dart b/lib/utils/renderers.dart
index b139a87..5c73539 100644
--- a/lib/utils/renderers.dart
+++ b/lib/utils/renderers.dart
@@ -35,13 +35,12 @@ class Renderers {
         return Icons.storage;
       case "qemu":
         return Icons.desktop_windows;
-
       case "lxc":
-        return FontAwesomeIcons.cube;
+        return FontAwesomeIcons.cube.data;
       case "storage":
         return (shared ?? false)
             ? Icons.folder_shared
-            : FontAwesomeIcons.database;
+            : FontAwesomeIcons.database.data;
       case "pool":
         return Icons.label;
       default:
diff --git a/lib/widgets/pve_action_card_widget.dart b/lib/widgets/pve_action_card_widget.dart
index 019a584..9fca232 100644
--- a/lib/widgets/pve_action_card_widget.dart
+++ b/lib/widgets/pve_action_card_widget.dart
@@ -1,4 +1,5 @@
 import 'package:flutter/material.dart';
+import 'package:font_awesome_flutter/font_awesome_flutter.dart';
 
 class ActionCard extends StatelessWidget {
   final Function? onTap;
@@ -14,6 +15,22 @@ class ActionCard extends StatelessWidget {
     this.color,
   });
 
+  factory ActionCard.withIcon(String title, IconData icon, Function onTap) {
+    return ActionCard(
+      title: title,
+      icon: Icon(icon, size: 55, color: Colors.white24),
+      onTap: onTap,
+    );
+  }
+
+  factory ActionCard.withFaIcon(String title, FaIconData icon, Function onTap) {
+    return ActionCard(
+      title: title,
+      icon: FaIcon(icon, size: 55, color: Colors.white24),
+      onTap: onTap,
+    );
+  }
+
   @override
   Widget build(BuildContext context) {
     return Card(
diff --git a/lib/widgets/pve_file_selector_widget.dart b/lib/widgets/pve_file_selector_widget.dart
index 59964dd..1722e50 100644
--- a/lib/widgets/pve_file_selector_widget.dart
+++ b/lib/widgets/pve_file_selector_widget.dart
@@ -373,7 +373,7 @@ class FileSelectorContentView extends StatelessWidget {
                 child: Column(
                   mainAxisAlignment: MainAxisAlignment.center,
                   children: <Widget>[
-                    Icon(
+                    FaIcon(
                       getContentIcon(content![index].content),
                       color: Theme.of(context).colorScheme.secondary,
                     ),
@@ -401,7 +401,7 @@ class FileSelectorContentView extends StatelessWidget {
       itemCount: content!.length,
       itemBuilder: (context, index) => Card(
         child: ListTile(
-          leading: Icon(
+          leading: FaIcon(
             getContentIcon(content![index].content),
             color: Theme.of(context).colorScheme.secondary,
           ),
@@ -418,7 +418,7 @@ class FileSelectorContentView extends StatelessWidget {
     );
   }
 
-  IconData getContentIcon(PveStorageContentType? content) {
+  FaIconData getContentIcon(PveStorageContentType? content) {
     switch (content) {
       case PveStorageContentType.iso:
         return FontAwesomeIcons.compactDisc;
diff --git a/lib/widgets/pve_guest_backup_widget.dart b/lib/widgets/pve_guest_backup_widget.dart
index 4966e9d..119348b 100644
--- a/lib/widgets/pve_guest_backup_widget.dart
+++ b/lib/widgets/pve_guest_backup_widget.dart
@@ -205,7 +205,7 @@ class PveGuestBackupContent extends StatelessWidget {
       itemCount: content!.length,
       itemBuilder: (context, index) => Card(
         child: ListTile(
-          leading: Icon(
+          leading: FaIcon(
             FontAwesomeIcons.floppyDisk,
             color: Theme.of(context).colorScheme.onSurface,
           ),
diff --git a/lib/widgets/pve_guest_migrate_widget.dart b/lib/widgets/pve_guest_migrate_widget.dart
index cb6cd38..c65f6fe 100644
--- a/lib/widgets/pve_guest_migrate_widget.dart
+++ b/lib/widgets/pve_guest_migrate_widget.dart
@@ -55,7 +55,7 @@ class PveGuestMigrate extends StatelessWidget {
                       crossAxisAlignment: CrossAxisAlignment.start,
                       children: [
                         ListTile(
-                          leading: const Icon(FontAwesomeIcons.globe),
+                          leading: const FaIcon(FontAwesomeIcons.globe),
                           title: Text(
                             'Mode',
                             style: TextStyle(color: colorScheme.onPrimary),
@@ -68,7 +68,7 @@ class PveGuestMigrate extends StatelessWidget {
                           ),
                         ),
                         ListTile(
-                          leading: const Icon(FontAwesomeIcons.mapPin),
+                          leading: const FaIcon(FontAwesomeIcons.mapPin),
                           title: Text(
                             'Source',
                             style: TextStyle(color: colorScheme.onPrimary),
diff --git a/lib/widgets/pve_guest_os_selector_widget.dart b/lib/widgets/pve_guest_os_selector_widget.dart
index 2b3bd82..3a89143 100644
--- a/lib/widgets/pve_guest_os_selector_widget.dart
+++ b/lib/widgets/pve_guest_os_selector_widget.dart
@@ -40,11 +40,11 @@ class PveGuestOsSelector extends StatelessWidget {
 
   Widget getIcon(String? osGroup) {
     if (osGroup == "Microsoft Windows") {
-      return const Icon(FontAwesomeIcons.windows);
+      return const FaIcon(FontAwesomeIcons.windows);
     }
 
     if (osGroup == "Linux") {
-      return const Icon(FontAwesomeIcons.linux);
+      return const FaIcon(FontAwesomeIcons.linux);
     }
 
     return Text(osGroup!);
diff --git a/lib/widgets/pve_guest_overview_header.dart b/lib/widgets/pve_guest_overview_header.dart
index e4b5756..addb888 100644
--- a/lib/widgets/pve_guest_overview_header.dart
+++ b/lib/widgets/pve_guest_overview_header.dart
@@ -122,7 +122,7 @@ class PveGuestOverviewHeader extends StatelessWidget {
                     padding: const EdgeInsets.symmetric(horizontal: 20.0),
                     child: Row(
                       children: <Widget>[
-                        Icon(
+                        FaIcon(
                           FontAwesomeIcons.heartPulse,
                           color: haError ? Colors.red : Colors.green[400],
                         ),
@@ -219,7 +219,7 @@ class _PveGuestHeaderRRDPageViewState extends State<PveGuestHeaderRRDPageView> {
                     subtitle: Renderers.formatSize(rrdData.last.mem ?? 0),
                     data: rrdData.where((e) => e.mem != null).map(
                         (e) => Point(e.time!.millisecondsSinceEpoch, e.mem!)),
-                    icon: Icon(FontAwesomeIcons.memory, color: fgColor),
+                    icon: FaIcon(FontAwesomeIcons.memory, color: fgColor),
                     bottomRight: pageIndicator,
                     dataRenderer: (data) => Renderers.formatSize(data),
                   ),
diff --git a/lib/widgets/pve_lxc_overview.dart b/lib/widgets/pve_lxc_overview.dart
index 78ad853..7caa5cf 100644
--- a/lib/widgets/pve_lxc_overview.dart
+++ b/lib/widgets/pve_lxc_overview.dart
@@ -38,18 +38,6 @@ class PveLxcOverview extends StatelessWidget {
   static final routeName = RegExp(r"\/nodes\/(\S+)\/lxc\/(\d+)");
   final String guestID;
 
-  ActionCard createActionCard(String title, IconData icon, Function onTap) {
-    return ActionCard(
-      icon: Icon(
-        icon,
-        size: 55,
-        color: Colors.white24,
-      ),
-      title: title,
-      onTap: onTap,
-    );
-  }
-
   const PveLxcOverview({super.key, required this.guestID});
   @override
   Widget build(BuildContext context) {
@@ -139,13 +127,13 @@ class PveLxcOverview extends StatelessWidget {
                             mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                             children: <Widget>[
                               if (!(status?.template ?? false))
-                                createActionCard(
+                                ActionCard.withIcon(
                                     'Power Settings',
                                     Icons.power_settings_new,
                                     () => showPowerMenuBottomSheet(
                                         context, lxcBloc)),
                               if (!(status?.template ?? false))
-                                createActionCard(
+                                ActionCard.withIcon(
                                     'Console',
                                     Icons.queue_play_next,
                                     () => showConsoleMenuBottomSheet(
@@ -154,7 +142,7 @@ class PveLxcOverview extends StatelessWidget {
                                         guestID,
                                         state.nodeID,
                                         'lxc')),
-                              createActionCard(
+                              ActionCard.withIcon(
                                   'Options',
                                   Icons.settings,
                                   () => Navigator.of(context)
@@ -164,7 +152,7 @@ class PveLxcOverview extends StatelessWidget {
                                               ),
                                           fullscreenDialog: true))),
                               if (!resourceBloc.latestState.isStandalone)
-                                createActionCard(
+                                ActionCard.withFaIcon(
                                     'Migrate',
                                     FontAwesomeIcons.paperPlane,
                                     () => Navigator.of(context).push(
@@ -172,7 +160,7 @@ class PveLxcOverview extends StatelessWidget {
                                             guestID,
                                             state.nodeID,
                                             resourceBloc.apiClient!))),
-                              createActionCard(
+                              ActionCard.withFaIcon(
                                   'Backup',
                                   FontAwesomeIcons.floppyDisk,
                                   () => Navigator.of(context).push(
@@ -193,7 +181,7 @@ class PveLxcOverview extends StatelessWidget {
                           ),
                           children: <Widget>[
                             ListTile(
-                              leading: const Icon(FontAwesomeIcons.memory),
+                              leading: const FaIcon(FontAwesomeIcons.memory),
                               title: Text('${config.memory}'),
                               subtitle: const Text('Memory'),
                               dense: true,
@@ -211,7 +199,7 @@ class PveLxcOverview extends StatelessWidget {
                               dense: true,
                             ),
                             ListTile(
-                              leading: const Icon(FontAwesomeIcons.hardDrive),
+                              leading: const FaIcon(FontAwesomeIcons.hardDrive),
                               dense: true,
                               title: Text('${config.rootfs}'),
                             ),
@@ -229,7 +217,7 @@ class PveLxcOverview extends StatelessWidget {
                               for (var net in config.net!)
                                 ListTile(
                                   leading:
-                                      const Icon(FontAwesomeIcons.ethernet),
+                                      const FaIcon(FontAwesomeIcons.ethernet),
                                   dense: true,
                                   title: Text(net),
                                 ),
@@ -244,14 +232,14 @@ class PveLxcOverview extends StatelessWidget {
                             ),
                             children: <Widget>[
                               ListTile(
-                                leading: const Icon(FontAwesomeIcons.globe),
+                                leading: const FaIcon(FontAwesomeIcons.globe),
                                 dense: true,
                                 title: Text(
                                     config.searchdomain ?? 'Use host settings'),
                                 subtitle: const Text('DNS Domain'),
                               ),
                               ListTile(
-                                leading: const Icon(
+                                leading: const FaIcon(
                                     FontAwesomeIcons.magnifyingGlass),
                                 dense: true,
                                 title: Text(
diff --git a/lib/widgets/pve_node_overview.dart b/lib/widgets/pve_node_overview.dart
index 7236cf4..092bb54 100644
--- a/lib/widgets/pve_node_overview.dart
+++ b/lib/widgets/pve_node_overview.dart
@@ -115,7 +115,7 @@ class PveNodeOverview extends StatelessWidget {
                                       data: rrd.map((e) => Point(
                                           e.time!.millisecondsSinceEpoch,
                                           e.memused ?? 0)),
-                                      icon: Icon(FontAwesomeIcons.memory,
+                                      icon: FaIcon(FontAwesomeIcons.memory,
                                           color: fgColor),
                                       bottomRight: pageIndicator,
                                       dataRenderer: (data) =>
@@ -259,7 +259,7 @@ class PveNodeOverview extends StatelessWidget {
                           child: ListTile(
                             title: const Text('HD space (root)'),
                             subtitle: ProxmoxCapacityIndicator(
-                              icon: Icon(
+                              icon: FaIcon(
                                 FontAwesomeIcons.solidHardDrive,
                                 color: Colors.blueGrey[300],
                               ),
@@ -385,7 +385,7 @@ class PveNodeOverview extends StatelessWidget {
                         .map(
                           (d) => ListTile(
                             dense: true,
-                            leading: Icon(FontAwesomeIcons.solidHardDrive,
+                            leading: FaIcon(FontAwesomeIcons.solidHardDrive,
                                 color: state.isDiskHealthy(d)
                                     ? Colors.grey
                                     : Colors.red),
diff --git a/lib/widgets/pve_qemu_overview.dart b/lib/widgets/pve_qemu_overview.dart
index 3fb25ba..12e3b30 100644
--- a/lib/widgets/pve_qemu_overview.dart
+++ b/lib/widgets/pve_qemu_overview.dart
@@ -40,18 +40,6 @@ class PveQemuOverview extends StatelessWidget {
 
   const PveQemuOverview({super.key, required this.guestID});
 
-  ActionCard createActionCard(String title, IconData icon, Function onTap) {
-    return ActionCard(
-      icon: Icon(
-        icon,
-        size: 55,
-        color: Colors.white24,
-      ),
-      title: title,
-      onTap: onTap,
-    );
-  }
-
   @override
   Widget build(BuildContext context) {
     final bloc = Provider.of<PveQemuOverviewBloc>(context);
@@ -140,13 +128,13 @@ class PveQemuOverview extends StatelessWidget {
                           mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                           children: <Widget>[
                             if (!(status?.template ?? false))
-                              createActionCard(
+                              ActionCard.withIcon(
                                   'Power Settings',
                                   Icons.power_settings_new,
                                   () =>
                                       showPowerMenuBottomSheet(context, bloc)),
                             if (!(status?.template ?? false))
-                              createActionCard(
+                              ActionCard.withIcon(
                                   'Console',
                                   Icons.queue_play_next,
                                   () => showConsoleMenuBottomSheet(
@@ -157,19 +145,19 @@ class PveQemuOverview extends StatelessWidget {
                                         'qemu',
                                         allowSpice: status?.spice ?? false,
                                       )),
-                            createActionCard(
+                            ActionCard.withIcon(
                                 'Options',
                                 Icons.settings,
                                 () => Navigator.of(context)
                                     .push(_createOptionsRoute(bloc))),
                             if (!rBloc.latestState.isStandalone)
-                              createActionCard(
+                              ActionCard.withFaIcon(
                                   'Migrate',
                                   FontAwesomeIcons.paperPlane,
                                   () => Navigator.of(context).push(
                                       _createMigrationRoute(guestID,
                                           state.nodeID, bloc.apiClient))),
-                            createActionCard(
+                            ActionCard.withFaIcon(
                                 'Backup',
                                 FontAwesomeIcons.floppyDisk,
                                 () => Navigator.of(context).push(
@@ -191,7 +179,7 @@ class PveQemuOverview extends StatelessWidget {
                           ),
                           children: [
                             ListTile(
-                              leading: const Icon(FontAwesomeIcons.memory),
+                              leading: const FaIcon(FontAwesomeIcons.memory),
                               title: Text('${config.memory}'),
                               subtitle: const Text('Memory'),
                               dense: true,
@@ -204,20 +192,20 @@ class PveQemuOverview extends StatelessWidget {
                               dense: true,
                             ),
                             ListTile(
-                              leading: const Icon(FontAwesomeIcons.microchip),
+                              leading: const FaIcon(FontAwesomeIcons.microchip),
                               title: Text(
                                   config.bios?.name ?? 'Default (SeaBIOS)'),
                               subtitle: const Text('BIOS'),
                               dense: true,
                             ),
                             ListTile(
-                              leading: const Icon(FontAwesomeIcons.gears),
+                              leading: const FaIcon(FontAwesomeIcons.gears),
                               dense: true,
                               title: Text(config.machine ?? 'Default (i440fx)'),
                               subtitle: const Text('Machine Type'),
                             ),
                             ListTile(
-                              leading: const Icon(FontAwesomeIcons.database),
+                              leading: const FaIcon(FontAwesomeIcons.database),
                               title: Text(
                                   config.scsihw?.name ?? 'Default (i440fx)'),
                               subtitle: const Text('SCSI Controller'),
@@ -226,21 +214,23 @@ class PveQemuOverview extends StatelessWidget {
                             for (var ide in config.ide!)
                               ListTile(
                                 leading:
-                                    const Icon(FontAwesomeIcons.compactDisc),
+                                    const FaIcon(FontAwesomeIcons.compactDisc),
                                 title: Text(ide),
                                 subtitle: const Text('CD/DVD Drive'),
                                 dense: true,
                               ),
                             for (var scsi in config.scsi!)
                               ListTile(
-                                leading: const Icon(FontAwesomeIcons.hardDrive),
+                                leading:
+                                    const FaIcon(FontAwesomeIcons.hardDrive),
                                 title: Text(scsi),
                                 subtitle: const Text('Hard Disk'),
                                 dense: true,
                               ),
                             for (var net in config.net!)
                               ListTile(
-                                leading: const Icon(FontAwesomeIcons.ethernet),
+                                leading:
+                                    const FaIcon(FontAwesomeIcons.ethernet),
                                 dense: true,
                                 subtitle: const Text('Network Device'),
                                 title: Text(net),
diff --git a/lib/widgets/pve_qemu_power_settings_widget.dart b/lib/widgets/pve_qemu_power_settings_widget.dart
index b4c3c0a..84c3b83 100644
--- a/lib/widgets/pve_qemu_power_settings_widget.dart
+++ b/lib/widgets/pve_qemu_power_settings_widget.dart
@@ -86,7 +86,7 @@ class PveQemuPowerSettings extends StatelessWidget {
                             context, PveClusterResourceAction.suspend, bloc),
                       ),
                       ListTile(
-                        leading: const Icon(FontAwesomeIcons.download),
+                        leading: const FaIcon(FontAwesomeIcons.download),
                         title: const Text(
                           "Hibernate",
                           style: TextStyle(fontWeight: FontWeight.bold),
@@ -106,7 +106,7 @@ class PveQemuPowerSettings extends StatelessWidget {
                             context, PveClusterResourceAction.stop, bloc),
                       ),
                       ListTile(
-                        leading: const Icon(FontAwesomeIcons.bolt),
+                        leading: const FaIcon(FontAwesomeIcons.bolt),
                         title: const Text(
                           "Reset",
                           style: TextStyle(fontWeight: FontWeight.bold),
diff --git a/pubspec.lock b/pubspec.lock
index ecaab97..def499d 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -324,10 +324,10 @@ packages:
     dependency: "direct main"
     description:
       name: font_awesome_flutter
-      sha256: b9011df3a1fa02993630b8fb83526368cf2206a711259830325bab2f1d2a4eb0
+      sha256: "09dcde8ab90ffae1a7d65ff2ef96fc62a17ad9d0ce7c127b317ded676b0d5935"
       url: "https://pub.dev"
     source: hosted
-    version: "10.12.0"
+    version: "11.0.0"
   glob:
     dependency: transitive
     description:
diff --git a/pubspec.yaml b/pubspec.yaml
index e15d57b..04c56a4 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -30,7 +30,7 @@ dependencies:
   path: ^1.8.0
   provider: ^6.0.1
   meta: ^1.1.7
-  font_awesome_flutter: ^10.0.0
+  font_awesome_flutter: ^11.0.0
   url_launcher: ^6.0.17
   intl: ^0.20.1
   path_provider: ^2.0.8
-- 
2.50.1





  parent reply	other threads:[~2026-04-10 15:09 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-10 15:09 [PATCH proxmox{_login_manager,_dart_api_client}/pve_flutter_frontend 0/7] upgrade dependencies based on flutter v3.41 and migrate deprecated members Shan Shaji
2026-04-10 15:09 ` [PATCH pve_flutter_frontend 1/4] chore: upgrade dependencies based on flutter v3.41 Shan Shaji
2026-04-10 15:09 ` Shan Shaji [this message]
2026-04-10 15:09 ` [PATCH pve_flutter_frontend 3/4] fix: migrate to UIScene lifecycle for iOS 26+ compatibility Shan Shaji
2026-04-10 15:09 ` [PATCH pve_flutter_frontend 4/4] chore: use latest ndkVersion from flutter Shan Shaji
2026-04-10 15:09 ` [PATCH proxmox_login_manager 1/1] chore: upgrade dependencies Shan Shaji
2026-04-10 15:09 ` [PATCH proxmox_dart_api_client 1/2] " Shan Shaji
2026-04-10 15:09 ` [PATCH proxmox_dart_api_client 2/2] deps: add objective_c dependency to access NSError's code property Shan Shaji

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260410150935.25870-3-s.shaji@proxmox.com \
    --to=s.shaji@proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal