[pve-devel] [PATCH proxmox_login_manager] fix: ui: remove `SafeArea` to avoid black background in status bar
Shan Shaji
s.shaji at proxmox.com
Thu May 15 15:34:01 CEST 2025
Since the `SafeArea` widget was wrapping the `Scaffold` widget, the
background color of the status bar was black rather than influenced by
the `AppBar` color.
This patch fixes it by removing the `SafeArea` widget. According to
flutter docs [0] when using `AppBar` with `Scaffold` the
appropriate spacing will be calculated at the top of the screen
without the needing to wrap the `Scaffold` in a `SafeArea` and the
status bar color will be influenced by the app bar color.
This patch also fixes the app name title alignment issue in iOS.
[0] - https://api.flutter.dev/flutter/material/AppBar-class.html?utm_source
Signed-off-by: Shan Shaji <s.shaji at proxmox.com>
---
lib/proxmox_login_selector.dart | 264 ++++++++++++++++----------------
1 file changed, 130 insertions(+), 134 deletions(-)
diff --git a/lib/proxmox_login_selector.dart b/lib/proxmox_login_selector.dart
index f063699..fb1218b 100644
--- a/lib/proxmox_login_selector.dart
+++ b/lib/proxmox_login_selector.dart
@@ -29,152 +29,87 @@ class _ProxmoxLoginSelectorState extends State<ProxmoxLoginSelector> {
@override
Widget build(BuildContext context) {
- return SafeArea(
- child: Scaffold(
- backgroundColor: Theme.of(context).colorScheme.background,
- appBar: AppBar(
- title: const Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- 'Proxmox',
- style: TextStyle(
- fontSize: 14,
- ),
+ return Scaffold(
+ backgroundColor: Theme.of(context).colorScheme.background,
+ appBar: AppBar(
+ centerTitle: false,
+ title: const Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ 'Proxmox',
+ style: TextStyle(
+ fontSize: 14,
),
- Text(
- 'Virtual Environment',
- style: TextStyle(
- fontSize: 14,
- ),
- )
- ],
- ),
- actions: [
- IconButton(
- icon: const Icon(Icons.settings),
- onPressed: () {
- Navigator.of(context).push(MaterialPageRoute(
- builder: (context) => const ProxmoxGeneralSettingsForm(),
- ));
- })
+ ),
+ Text(
+ 'Virtual Environment',
+ style: TextStyle(
+ fontSize: 14,
+ ),
+ )
],
),
- body: FutureBuilder<ProxmoxLoginStorage?>(
- future: loginStorage,
- builder: (context, snapshot) {
- if (!snapshot.hasData) {
- return const Center(
- child: CircularProgressIndicator(),
- );
- }
- if (snapshot.hasData &&
- (snapshot.data!.logins?.isEmpty ?? true)) {
- return const Center(
- child: Text('Add an account'),
- );
- }
- var items = <Widget>[];
- final BuiltList<ProxmoxLoginModel> logins =
- snapshot.data?.logins ?? BuiltList<ProxmoxLoginModel>();
+ actions: [
+ IconButton(
+ icon: const Icon(Icons.settings),
+ onPressed: () {
+ Navigator.of(context).push(MaterialPageRoute(
+ builder: (context) => const ProxmoxGeneralSettingsForm(),
+ ));
+ })
+ ],
+ ),
+ body: FutureBuilder<ProxmoxLoginStorage?>(
+ future: loginStorage,
+ builder: (context, snapshot) {
+ if (!snapshot.hasData) {
+ return const Center(
+ child: CircularProgressIndicator(),
+ );
+ }
+ if (snapshot.hasData && (snapshot.data!.logins?.isEmpty ?? true)) {
+ return const Center(
+ child: Text('Add an account'),
+ );
+ }
+ var items = <Widget>[];
+ final BuiltList<ProxmoxLoginModel> logins =
+ snapshot.data?.logins ?? BuiltList<ProxmoxLoginModel>();
- final activeSessions =
- logins.rebuild((b) => b.where((b) => b.activeSession));
+ final activeSessions =
+ logins.rebuild((b) => b.where((b) => b.activeSession));
- if (activeSessions.isNotEmpty) {
- items.addAll([
- const Padding(
- padding: EdgeInsets.all(12.0),
- child: Text(
- 'Active Sessions',
- style: TextStyle(
- fontSize: 18,
- fontWeight: FontWeight.bold,
- ),
- ),
- ),
- ...activeSessions.map((s) => ListTile(
- title: Text(s.fullHostname),
- subtitle: Text(s.fullUsername),
- trailing: const Icon(Icons.navigate_next),
- leading: PopupMenuButton(
- icon: const Icon(Icons.more_vert,
- color: Colors.green),
- itemBuilder: (context) => [
- PopupMenuItem(
- child: ListTile(
- dense: true,
- leading: const Icon(Icons.logout),
- title: const Text('Logout'),
- onTap: () async {
- await snapshot.data!
- .rebuild((b) => b.logins
- .rebuildWhere((m) => s == m,
- (b) => b..ticket = ''))
- .saveToDisk();
- refreshFromStorage();
- if (context.mounted) {
- Navigator.of(context).pop();
- }
- },
- ),
- ),
- ]),
- onTap: () => _login(user: s),
- )),
- ]);
- }
+ if (activeSessions.isNotEmpty) {
items.addAll([
const Padding(
padding: EdgeInsets.all(12.0),
child: Text(
- 'Available Sites',
+ 'Active Sessions',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
),
- ...logins.where((b) => !b.activeSession).map((login) =>
- ListTile(
- title: Text(login.fullHostname),
- subtitle: Text(login.fullUsername),
+ ...activeSessions.map((s) => ListTile(
+ title: Text(s.fullHostname),
+ subtitle: Text(s.fullUsername),
trailing: const Icon(Icons.navigate_next),
leading: PopupMenuButton(
+ icon:
+ const Icon(Icons.more_vert, color: Colors.green),
itemBuilder: (context) => [
- if (login.passwordSaved ?? false)
- PopupMenuItem(
- child: ListTile(
- dense: true,
- leading: const Icon(Icons.key_off),
- title: const Text('Delete Password'),
- onTap: () async {
- await deletePassword(login.identifier!);
-
- await snapshot.data!
- .rebuild((b) => b
- ..logins.rebuildWhere(
- (m) => m == login,
- (b) =>
- b..passwordSaved = false))
- .saveToDisk();
- refreshFromStorage();
- if (context.mounted) {
- Navigator.of(context).pop();
- }
- },
- ),
- ),
PopupMenuItem(
child: ListTile(
dense: true,
- leading: const Icon(Icons.delete),
- title: const Text('Delete'),
+ leading: const Icon(Icons.logout),
+ title: const Text('Logout'),
onTap: () async {
- await deletePassword(login.identifier!);
await snapshot.data!
- .rebuild(
- (b) => b.logins.remove(login))
+ .rebuild((b) => b.logins.rebuildWhere(
+ (m) => s == m,
+ (b) => b..ticket = ''))
.saveToDisk();
refreshFromStorage();
if (context.mounted) {
@@ -184,18 +119,79 @@ class _ProxmoxLoginSelectorState extends State<ProxmoxLoginSelector> {
),
),
]),
- onTap: () => _login(user: login),
- ))
+ onTap: () => _login(user: s),
+ )),
]);
- return ListView(
- children: items,
- );
- }),
- floatingActionButton: FloatingActionButton.extended(
- onPressed: () => _login(isCreate: true),
- label: const Text('Add'),
- icon: const Icon(Icons.account_circle),
- ),
+ }
+ items.addAll([
+ const Padding(
+ padding: EdgeInsets.all(12.0),
+ child: Text(
+ 'Available Sites',
+ style: TextStyle(
+ fontSize: 18,
+ fontWeight: FontWeight.bold,
+ ),
+ ),
+ ),
+ ...logins.where((b) => !b.activeSession).map((login) => ListTile(
+ title: Text(login.fullHostname),
+ subtitle: Text(login.fullUsername),
+ trailing: const Icon(Icons.navigate_next),
+ leading: PopupMenuButton(
+ itemBuilder: (context) => [
+ if (login.passwordSaved ?? false)
+ PopupMenuItem(
+ child: ListTile(
+ dense: true,
+ leading: const Icon(Icons.key_off),
+ title: const Text('Delete Password'),
+ onTap: () async {
+ await deletePassword(login.identifier!);
+
+ await snapshot.data!
+ .rebuild((b) => b
+ ..logins.rebuildWhere(
+ (m) => m == login,
+ (b) =>
+ b..passwordSaved = false))
+ .saveToDisk();
+ refreshFromStorage();
+ if (context.mounted) {
+ Navigator.of(context).pop();
+ }
+ },
+ ),
+ ),
+ PopupMenuItem(
+ child: ListTile(
+ dense: true,
+ leading: const Icon(Icons.delete),
+ title: const Text('Delete'),
+ onTap: () async {
+ await deletePassword(login.identifier!);
+ await snapshot.data!
+ .rebuild((b) => b.logins.remove(login))
+ .saveToDisk();
+ refreshFromStorage();
+ if (context.mounted) {
+ Navigator.of(context).pop();
+ }
+ },
+ ),
+ ),
+ ]),
+ onTap: () => _login(user: login),
+ ))
+ ]);
+ return ListView(
+ children: items,
+ );
+ }),
+ floatingActionButton: FloatingActionButton.extended(
+ onPressed: () => _login(isCreate: true),
+ label: const Text('Add'),
+ icon: const Icon(Icons.account_circle),
),
);
}
--
2.39.5 (Apple Git-154)
More information about the pve-devel
mailing list