From bd7baa8cb97ae9eae6b0ae0680ddeab73a6a190b Mon Sep 17 00:00:00 2001 From: Abhishek Shroff Date: Fri, 18 Jul 2025 20:37:56 +0530 Subject: [PATCH] [client] Show profile icon and sync status in top-right corner --- .../ui/layout/explorer_page_collapsed.dart | 14 ++---- .../lib/ui/layout/explorer_page_expanded.dart | 33 ++++++++------ client/lib/ui/profile/profile_dialog.dart | 2 +- client/lib/ui/profile/profile_view.dart | 44 +++++++++++++------ 4 files changed, 55 insertions(+), 38 deletions(-) diff --git a/client/lib/ui/layout/explorer_page_collapsed.dart b/client/lib/ui/layout/explorer_page_collapsed.dart index a185ed2e..cc78278c 100644 --- a/client/lib/ui/layout/explorer_page_collapsed.dart +++ b/client/lib/ui/layout/explorer_page_collapsed.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:phylum/libphylum/phylum_account.dart'; import 'package:phylum/ui/explorer/explorer_controller.dart'; import 'package:phylum/ui/explorer/explorer_view.dart'; import 'package:phylum/ui/explorer/selection_mode.dart'; @@ -64,8 +63,6 @@ class ExplorerPageCollapsed extends StatelessWidget { ); } - final account = context.read(); - return AppBar( title: const Text('Phylum'), actions: [ @@ -76,14 +73,9 @@ class ExplorerPageCollapsed extends StatelessWidget { context.read().active = true; }, ), - StreamBuilder( - stream: account.userNotifier.stream, - initialData: account.user, - builder: (context, snapshot) => ProfileView( - name: snapshot.data!.name, - email: snapshot.data!.email, - onTap: () => ProfileDialog.show(context), - )), + ProfileView( + onTap: () => ProfileDialog.show(context), + ), ], ); } diff --git a/client/lib/ui/layout/explorer_page_expanded.dart b/client/lib/ui/layout/explorer_page_expanded.dart index 5b2acd8c..4e454dff 100644 --- a/client/lib/ui/layout/explorer_page_expanded.dart +++ b/client/lib/ui/layout/explorer_page_expanded.dart @@ -5,6 +5,8 @@ import 'package:phylum/ui/explorer/resource_info_view.dart'; import 'package:phylum/ui/layout/nav_list.dart'; import 'package:phylum/ui/layout/search.dart'; import 'package:phylum/ui/layout/sync_status_button.dart'; +import 'package:phylum/ui/profile/profile_dialog.dart'; +import 'package:phylum/ui/profile/profile_view.dart'; class ExplorerPageExpanded extends StatelessWidget { final bool large; @@ -26,37 +28,42 @@ class ExplorerPageExpanded extends StatelessWidget { width: sidebarWidth, child: Padding( padding: const EdgeInsets.only(left: 16), - child: const Row( - spacing: 6.0, - children: [ - LogoRow(), - SyncStatusButton(), - ], - ), + child: const LogoRow(), ), ), - Expanded( + const Expanded( child: Card( elevation: 0, - margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + margin: EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 12), + padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 12), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ - const Padding( + Padding( padding: EdgeInsets.only(right: 16.0), child: Icon(Icons.search), ), Expanded( - child: const SearchField(), + child: SearchField(), ), ], ), ), ), ), - if (large) SizedBox(width: 360), + ConstrainedBox( + constraints: BoxConstraints(minWidth: large ? 360 : 0), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + const SyncStatusButton(), + ProfileView( + onTap: () => ProfileDialog.show(context), + ), + ], + ), + ) ], ), Expanded( diff --git a/client/lib/ui/profile/profile_dialog.dart b/client/lib/ui/profile/profile_dialog.dart index b4d472fa..23020903 100644 --- a/client/lib/ui/profile/profile_dialog.dart +++ b/client/lib/ui/profile/profile_dialog.dart @@ -39,7 +39,7 @@ class ProfileDialog extends StatelessWidget { child: Column( children: [ ListTile( - leading: ProfileView(name: account.user.name, email: account.user.email), + leading: ProfileView(), title: Row( mainAxisSize: MainAxisSize.min, children: [ diff --git a/client/lib/ui/profile/profile_view.dart b/client/lib/ui/profile/profile_view.dart index f350e2dd..aa2d7ffc 100644 --- a/client/lib/ui/profile/profile_view.dart +++ b/client/lib/ui/profile/profile_view.dart @@ -1,27 +1,45 @@ import 'package:circular_profile_avatar/circular_profile_avatar.dart'; import 'package:flutter/material.dart'; +import 'package:phylum/libphylum/phylum_account.dart'; +import 'package:provider/provider.dart'; class ProfileView extends StatelessWidget { - final String name; - final String email; final Function()? onTap; - const ProfileView({super.key, required this.name, required this.email, this.onTap}); + const ProfileView({super.key, this.onTap}); @override Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.all(6.0), - child: onTap == null - ? _buildAvatar() - : InkWell( - onTap: onTap, - child: _buildAvatar(), - ), - ); + final account = context.read(); + return StreamBuilder( + initialData: account.user, + stream: account.userNotifier.stream, + builder: (context, sanpshot) { + final user = sanpshot.data!; + return Padding( + padding: const EdgeInsets.all(6.0), + child: onTap == null + ? AvatarView(name: user.name, email: user.email) + : InkWell( + onTap: onTap, + child: AvatarView( + name: user.name, + email: user.email, + ), + ), + ); + }); } +} - Widget _buildAvatar() { +class AvatarView extends StatelessWidget { + final String name; + final String email; + + const AvatarView({super.key, required this.name, required this.email}); + + @override + Widget build(BuildContext context) { String initials = name.split(' ').map((s) => s.isEmpty ? null : s.substring(0, 1)).join(''); if (initials.isEmpty) { initials = email.substring(0, 2);