[client] Show profile icon and sync status in top-right corner

This commit is contained in:
Abhishek Shroff
2025-07-18 20:37:56 +05:30
parent 9b1a49368b
commit bd7baa8cb9
4 changed files with 55 additions and 38 deletions

View File

@@ -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<PhylumAccount>();
return AppBar(
title: const Text('Phylum'),
actions: [
@@ -76,14 +73,9 @@ class ExplorerPageCollapsed extends StatelessWidget {
context.read<PhylumSearchController>().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),
),
],
);
}

View File

@@ -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(

View File

@@ -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: [

View File

@@ -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<PhylumAccount>();
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);