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 +-
| 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!);
--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
next prev 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox