mirror of
https://codeberg.org/shroff/phylum.git
synced 2026-04-26 14:40:19 -05:00
[client] Basic profile dialog
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
import 'package:circular_profile_avatar/circular_profile_avatar.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:phylum/libphylum/phylum_account.dart';
|
||||
import 'package:phylum/ui/explorer/explorer_controller.dart';
|
||||
@@ -10,7 +9,8 @@ import 'package:phylum/ui/layout/search.dart';
|
||||
import 'package:phylum/ui/layout/sync_status_button.dart';
|
||||
import 'package:phylum/ui/menu/bottom_sheet.dart';
|
||||
import 'package:phylum/ui/menu/option_groups.dart';
|
||||
import 'package:phylum/util/avatar.dart';
|
||||
import 'package:phylum/ui/profile/profile_dialog.dart';
|
||||
import 'package:phylum/ui/profile/profile_view.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class ExplorerPageCollapsed extends StatelessWidget {
|
||||
@@ -79,30 +79,11 @@ class ExplorerPageCollapsed extends StatelessWidget {
|
||||
StreamBuilder(
|
||||
stream: account.userNotifier.stream,
|
||||
initialData: account.user,
|
||||
builder: (context, snapshot) {
|
||||
final data = snapshot.data!;
|
||||
String initials = data.name.split(' ').map((s) => s.isEmpty ? null : s.substring(0, 1)).join('');
|
||||
if (initials.isEmpty) {
|
||||
initials = data.email.substring(0, 2);
|
||||
}
|
||||
final colorScheme = getColorFromString(data.email);
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(6.0),
|
||||
child: CircularProfileAvatar(
|
||||
'',
|
||||
initialsText: Text(
|
||||
initials,
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
foregroundColor: colorScheme.onPrimaryContainer,
|
||||
backgroundColor: colorScheme.primaryContainer,
|
||||
borderWidth: 1,
|
||||
borderColor: colorScheme.onPrimaryContainer,
|
||||
radius: 18,
|
||||
),
|
||||
);
|
||||
}),
|
||||
builder: (context, snapshot) => ProfileView(
|
||||
name: snapshot.data!.name,
|
||||
email: snapshot.data!.email,
|
||||
onTap: () => ProfileDialog.show(context),
|
||||
)),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_state_notifier/flutter_state_notifier.dart';
|
||||
import 'package:offtheline/offtheline.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:phylum/libphylum/user_permission.dart';
|
||||
import 'package:phylum/ui/app/shortcuts.dart';
|
||||
import 'package:phylum/libphylum/db/db.dart';
|
||||
@@ -166,27 +165,6 @@ class NavList extends StatelessWidget {
|
||||
: SizedBox();
|
||||
}),
|
||||
if (!kIsWeb) const DownloadButton(),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.help),
|
||||
title: const Text('About'),
|
||||
onTap: () async {
|
||||
Scaffold.maybeOf(context)?.closeDrawer();
|
||||
final info = await PackageInfo.fromPlatform();
|
||||
if (!context.mounted) return;
|
||||
showAboutDialog(
|
||||
context: context,
|
||||
applicationVersion: '${info.packageName} - ${info.version} (${info.buildNumber})',
|
||||
);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.logout),
|
||||
title: const Text('Log Out'),
|
||||
onTap: () {
|
||||
Scaffold.maybeOf(context)?.closeDrawer();
|
||||
context.read<PhylumAccount>().close(clearData: true);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:phylum/libphylum/phylum_account.dart';
|
||||
import 'package:phylum/ui/profile/profile_view.dart';
|
||||
import 'package:phylum/util/dialogs.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class ProfileDialog extends StatelessWidget {
|
||||
const ProfileDialog._();
|
||||
|
||||
static void show(BuildContext context) {
|
||||
final account = context.read<PhylumAccount>();
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => MultiProvider(
|
||||
providers: [
|
||||
Provider.value(value: account),
|
||||
],
|
||||
child: AlertDialog(
|
||||
scrollable: true,
|
||||
content: SizedBox(width: 360, child: ProfileDialog._()),
|
||||
actions: [
|
||||
ElevatedButton(onPressed: Navigator.of(context).pop, child: Text('OK')),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final account = context.read<PhylumAccount>();
|
||||
return Column(
|
||||
children: [
|
||||
Card(
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
leading: ProfileView(name: account.user.name, email: account.user.email),
|
||||
title: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Flexible(
|
||||
fit: FlexFit.loose,
|
||||
child: Text(
|
||||
account.userRepository.getUserDisplayName(account.user.id),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.fade,
|
||||
softWrap: false,
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
icon: Icon(Icons.edit, size: 18),
|
||||
splashRadius: 6,
|
||||
padding: EdgeInsets.symmetric(vertical: 3, horizontal: 6),
|
||||
constraints: BoxConstraints(),
|
||||
onPressed: () async {
|
||||
final name = await showInputDialog(
|
||||
context,
|
||||
title: 'Change Name',
|
||||
labelText: 'Name',
|
||||
preset: account.user.name,
|
||||
);
|
||||
if (name == null) return;
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
subtitle: Text(context.read<PhylumAccount>().apiClient.serverUrl.host),
|
||||
),
|
||||
Divider(thickness: 2),
|
||||
const ListTile(
|
||||
visualDensity: VisualDensity.compact,
|
||||
leading: Icon(Icons.password),
|
||||
title: Text('Change Password'),
|
||||
),
|
||||
ListTile(
|
||||
visualDensity: VisualDensity.compact,
|
||||
leading: const Icon(Icons.logout),
|
||||
title: const Text('Log Out'),
|
||||
onTap: () {
|
||||
Navigator.of(context).pop();
|
||||
context.read<PhylumAccount>().close(clearData: true);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const ListTile(
|
||||
visualDensity: VisualDensity.compact,
|
||||
leading: Icon(Icons.settings),
|
||||
title: Text('Settings'),
|
||||
),
|
||||
ListTile(
|
||||
visualDensity: VisualDensity.compact,
|
||||
leading: const Icon(Icons.help),
|
||||
title: const Text('About'),
|
||||
onTap: () async {
|
||||
final info = await PackageInfo.fromPlatform();
|
||||
if (!context.mounted) return;
|
||||
showAboutDialog(
|
||||
context: context,
|
||||
applicationVersion: '${info.packageName} - ${info.version} (${info.buildNumber})',
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import 'package:circular_profile_avatar/circular_profile_avatar.dart';
|
||||
import 'package:flutter/material.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});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(6.0),
|
||||
child: onTap == null
|
||||
? _buildAvatar()
|
||||
: InkWell(
|
||||
onTap: onTap,
|
||||
child: _buildAvatar(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildAvatar() {
|
||||
String initials = name.split(' ').map((s) => s.isEmpty ? null : s.substring(0, 1)).join('');
|
||||
if (initials.isEmpty) {
|
||||
initials = email.substring(0, 2);
|
||||
}
|
||||
final colorScheme = getColorFromString(email);
|
||||
return CircularProfileAvatar(
|
||||
'',
|
||||
initialsText: Text(
|
||||
initials,
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
foregroundColor: colorScheme.onPrimaryContainer,
|
||||
backgroundColor: colorScheme.primaryContainer,
|
||||
borderWidth: 1,
|
||||
borderColor: colorScheme.onPrimaryContainer,
|
||||
radius: 18,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ColorScheme getColorFromString(String input) {
|
||||
return ColorScheme.fromSeed(
|
||||
seedColor: Colors.primaries[(input.hashCode) % Colors.primaries.length],
|
||||
);
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
ColorScheme getColorFromString(String input) {
|
||||
return ColorScheme.fromSeed(
|
||||
seedColor: Colors.primaries[(input.hashCode) % Colors.primaries.length],
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user