diff --git a/lib/pages/chat/chat_app_bar_title.dart b/lib/pages/chat/chat_app_bar_title.dart index f4a369d7..91a770f0 100644 --- a/lib/pages/chat/chat_app_bar_title.dart +++ b/lib/pages/chat/chat_app_bar_title.dart @@ -39,10 +39,13 @@ class ChatAppBarTitle extends StatelessWidget { : () => VRouter.of(context).toSegments(['rooms', room.id, 'details']), child: Row( children: [ - Avatar( - mxContent: room.avatar, - name: room.displayname, - size: 32, + Hero( + tag: 'content_banner', + child: Avatar( + mxContent: room.avatar, + name: room.displayname, + size: 32, + ), ), const SizedBox(width: 12), Expanded( diff --git a/lib/pages/chat_list/stories_header.dart b/lib/pages/chat_list/stories_header.dart index 3176625e..251bba08 100644 --- a/lib/pages/chat_list/stories_header.dart +++ b/lib/pages/chat_list/stories_header.dart @@ -119,7 +119,7 @@ class StoriesHeader extends StatelessWidget { ...client.storiesRooms..remove(ownStoryRoom), ]; return SizedBox( - height: 106, + height: 98, child: ListView.builder( padding: const EdgeInsets.symmetric(horizontal: 2), scrollDirection: Axis.horizontal, @@ -145,6 +145,7 @@ class StoriesHeader extends StatelessWidget { avatarUrl: avatarUrl, userId: userId ?? 'Unknown', ), + heroTag: 'stories_${room.id}', hasPosts: room.hasPosts || room == ownStoryRoom, showEditFab: userId == client.userID, unread: room.membership == Membership.invite || @@ -186,10 +187,12 @@ class _StoryButton extends StatelessWidget { final bool hasPosts; final void Function() onPressed; final void Function()? onLongPressed; + final String heroTag; const _StoryButton({ required this.profile, required this.onPressed, + required this.heroTag, this.showEditFab = false, this.hasPosts = true, this.unread = false, @@ -246,11 +249,14 @@ class _StoryButton extends StatelessWidget { Theme.of(context).colorScheme.surface, foregroundColor: Theme.of(context).textTheme.bodyText1?.color, - child: Avatar( - mxContent: profile.avatarUrl, - name: profile.displayName, - size: 100, - fontSize: 24, + child: Hero( + tag: heroTag, + child: Avatar( + mxContent: profile.avatarUrl, + name: profile.displayName, + size: 100, + fontSize: 24, + ), ), ), ), diff --git a/lib/pages/story/story_view.dart b/lib/pages/story/story_view.dart index f43b29f6..ea9cfd89 100644 --- a/lib/pages/story/story_view.dart +++ b/lib/pages/story/story_view.dart @@ -83,9 +83,12 @@ class StoryView extends StatelessWidget { ), ) : null, - leading: Avatar( - mxContent: controller.avatar, - name: controller.title, + leading: Hero( + tag: 'stories_${controller.roomId}', + child: Avatar( + mxContent: controller.avatar, + name: controller.title, + ), ), ), actions: currentEvent == null diff --git a/lib/widgets/avatar.dart b/lib/widgets/avatar.dart index 2fe01fb7..0d90f31d 100644 --- a/lib/widgets/avatar.dart +++ b/lib/widgets/avatar.dart @@ -54,39 +54,40 @@ class Avatar extends StatelessWidget { ), ); final borderRadius = BorderRadius.circular(size / 2); - return InkWell( - onTap: onTap, - borderRadius: borderRadius, - child: Container( - decoration: BoxDecoration( - border: Border.all(color: Theme.of(context).dividerColor), - borderRadius: borderRadius, - ), - child: ClipRRect( - borderRadius: borderRadius, - child: Container( - width: size, - height: size, - color: noPic - ? name?.lightColor - : Theme.of(context).secondaryHeaderColor, - child: noPic - ? textWidget - : CachedNetworkImage( - imageUrl: src.toString(), - fit: BoxFit.cover, - width: size, - height: size, - placeholder: (c, s) => textWidget, - errorWidget: (c, s, d) => Stack( - children: [ - textWidget, - ], - ), + final container = Container( + decoration: BoxDecoration( + border: Border.all(color: Theme.of(context).dividerColor), + borderRadius: borderRadius, + ), + child: ClipRRect( + borderRadius: borderRadius, + child: Container( + width: size, + height: size, + color: + noPic ? name?.lightColor : Theme.of(context).secondaryHeaderColor, + child: noPic + ? textWidget + : CachedNetworkImage( + imageUrl: src.toString(), + fit: BoxFit.cover, + width: size, + height: size, + placeholder: (c, s) => textWidget, + errorWidget: (c, s, d) => Stack( + children: [ + textWidget, + ], ), - ), + ), ), ), ); + if (onTap == null) return container; + return InkWell( + onTap: onTap, + borderRadius: borderRadius, + child: container, + ); } } diff --git a/lib/widgets/content_banner.dart b/lib/widgets/content_banner.dart index 2cdda586..d1a6b717 100644 --- a/lib/widgets/content_banner.dart +++ b/lib/widgets/content_banner.dart @@ -15,6 +15,7 @@ class ContentBanner extends StatelessWidget { final void Function()? onEdit; final Client? client; final double opacity; + final String heroTag; const ContentBanner( {this.mxContent, @@ -24,6 +25,7 @@ class ContentBanner extends StatelessWidget { this.onEdit, this.client, this.opacity = 0.75, + this.heroTag = 'content_banner', Key? key}) : super(key: key); @@ -62,16 +64,19 @@ class ContentBanner extends StatelessWidget { method: ThumbnailMethod.scale, animated: true, ); - return CachedNetworkImage( - imageUrl: src.toString(), - height: 300, - fit: BoxFit.cover, - errorWidget: (c, m, e) => Icon( - defaultIcon, - size: 200, - color: Theme.of(context) - .colorScheme - .onSecondaryContainer, + return Hero( + tag: heroTag, + child: CachedNetworkImage( + imageUrl: src.toString(), + height: 300, + fit: BoxFit.cover, + errorWidget: (c, m, e) => Icon( + defaultIcon, + size: 200, + color: Theme.of(context) + .colorScheme + .onSecondaryContainer, + ), ), ); })