Skip to content

Commit

Permalink
style: round image for group
Browse files Browse the repository at this point in the history
  • Loading branch information
borgoat committed Jan 3, 2025
1 parent c23553e commit 645a7d4
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 64 deletions.
85 changes: 31 additions & 54 deletions lib/presentation/screens/group_details.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,71 +25,48 @@ class GroupDetailsScreen extends StatelessWidget {
final groupId = group?.id;
final groupIdStr = groupId?.toString();
final groupImage = group?.picture;
final groupName = group?.displayName ?? groupIdStr ?? '';
final groupName = group?.displayName ?? l10n.loading;
final groupDescription = group?.description;

final imageOrDescriptionToShow =
groupImage != null || groupDescription != null;

return Scaffold(
body: NestedScrollView(
headerSliverBuilder: (context, innerBoxIsScrolled) => [
SliverAppBar(
pinned: true,
expandedHeight: groupImage != null ? 256 : 0,
flexibleSpace: FlexibleSpaceBar(
background: groupImage != null
? Hero(
tag: groupImage,
child: ClipRRect(
borderRadius: BorderRadius.vertical(
bottom: Radius.circular(24)),
child: AspectRatio(
aspectRatio: 1,
child: Stack(
fit: StackFit.expand,
children: [
Image.network(groupImage,
fit: BoxFit.cover),
DecoratedBox(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
colorScheme.surface
.withValues(alpha: 0.1),
colorScheme.secondaryContainer
.withValues(alpha: 0.8),
],
),
),
),
],
),
title: Text(groupName),
bottom: PreferredSize(
preferredSize: Size.fromHeight(60),
child: const DateDropdownContainer(),
),
),
if (imageOrDescriptionToShow)
SliverToBoxAdapter(
child: Column(
children: [
if (groupImage != null)
Padding(
padding: EdgeInsets.all(16),
child: Hero(
tag: groupImage,
child: ProfilePicture(
image: NetworkImage(groupImage),
icon: Icons.group,
radius: 128,
color: colorScheme.secondary,
),
),
),
if (groupDescription != null)
Padding(
padding: EdgeInsets.all(16),
child: Text(groupDescription),
)
: null,
collapseMode: CollapseMode.pin,
title: group != null
? Hero(
tag: group!,
child: Text(groupName,
style: textTheme.headlineMedium))
: null,
],
),
),
),
SliverToBoxAdapter(
child: Column(
children: [
if (groupDescription != null)
Padding(
padding:
EdgeInsets.only(top: 32, left: 16, right: 16),
child: Text(groupDescription),
),
const DateDropdownContainer(),
],
),
),
],
body: SchedulesListContainer(groupId: groupIdStr)),
floatingActionButton: isAdmin && groupIdStr != null
Expand Down
2 changes: 2 additions & 0 deletions lib/presentation/widgets/group_form.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class _GroupFormState extends State<GroupForm> {
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
final colorScheme = Theme.of(context).colorScheme;

return Form(
key: _formKey,
Expand All @@ -63,6 +64,7 @@ class _GroupFormState extends State<GroupForm> {
builder: (context, child) => ImageFormField(
radius: 64,
icon: Icons.group,
color: colorScheme.secondary,
controller: _imageController,
initialImage: widget.group?.picture != null
? NetworkImage(widget.group!.picture!)
Expand Down
14 changes: 6 additions & 8 deletions lib/presentation/widgets/groups_list.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:parousia/go_router_builder.dart';
import 'package:parousia/models/models.dart';
import 'package:parousia/presentation/presentation.dart';

/// A widget to display a list of groups and route to their details.
class GroupsList extends StatelessWidget {
Expand All @@ -22,14 +23,11 @@ class GroupsList extends StatelessWidget {
return ListTile(
leading: Hero(
tag: picture ?? group.hashCode,
child: CircleAvatar(
radius: 32,
foregroundImage: picture != null ? NetworkImage(picture) : null,
child: Icon(
Icons.group,
size: 32,
color: Colors.white,
),
child: ProfilePicture(
image: picture != null ? NetworkImage(picture) : null,
icon: Icons.group,
radius: 24,
color: theme.colorScheme.secondary,
),
),
title: Hero(
Expand Down
5 changes: 5 additions & 0 deletions lib/presentation/widgets/image_form_field.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class ImageFormField extends FormField<XFile> {
this.initialImage,
this.icon,
this.radius,
this.color,
}) : super(builder: (state) => (state as _ImageFormFieldState).builder());

/// Controls the state of the image.
Expand All @@ -38,6 +39,9 @@ class ImageFormField extends FormField<XFile> {
/// The radius of the image.
final double? radius;

/// The color of the icon.
final Color? color;

@override
FormFieldState<XFile> createState() => _ImageFormFieldState();
}
Expand Down Expand Up @@ -102,6 +106,7 @@ class _ImageFormFieldState extends FormFieldState<XFile> {
image: image,
radius: widget.radius,
icon: widget.icon,
color: widget.color,
// loadingValue: // TODO This should show a loading indicator when the image is being uploaded.
),
Positioned.directional(
Expand Down
10 changes: 8 additions & 2 deletions lib/presentation/widgets/profile_picture.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class ProfilePicture extends StatelessWidget {
this.radius,
this.loadingValue = 1,
this.icon,
this.color,
});

final VoidCallback? onPressed;
Expand All @@ -18,12 +19,16 @@ class ProfilePicture extends StatelessWidget {
final double? radius;
final double? loadingValue;
final IconData? icon;
final Color? color;

@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final nameInitials = getNameInitials(name);
final padding = radius != null ? radius! / 12.0 : 1.0;
final color = this.color ?? theme.colorScheme.primary;
final backgroundColor =
HSLColor.fromColor(color).withLightness(0.9).toColor();

return ElevatedButton(
onPressed: onPressed,
Expand All @@ -33,16 +38,17 @@ class ProfilePicture extends StatelessWidget {
children: [
CircleAvatar(
radius: radius,
backgroundColor: theme.colorScheme.primary.withValues(alpha: 0.3),
backgroundColor: backgroundColor,
foregroundImage: image,
child: nameInitials != null && nameInitials.isNotEmpty
? Text(nameInitials)
: Icon(icon, size: radius, color: theme.colorScheme.primary),
: Icon(icon, size: radius, color: color),
),
Positioned.fill(
child: CircularProgressIndicator(
strokeWidth: padding,
value: loadingValue,
color: color,
),
),
],
Expand Down

0 comments on commit 645a7d4

Please sign in to comment.