Skip to content

Commit

Permalink
feat: increased image performance
Browse files Browse the repository at this point in the history
Added resizing to images which dramatically increased efficiency.

Drastically decreased
memory usages.

Imporved cached images loading time.

Fixed PostMedia carousel rebuilding. Previously, PostView always used InViewNotifier. That caused widget inside of the InViewNotifier widget to constantly rebuild. However, we need to track whether the widget is in view only if it is video. We shouldn't have wrapped images with InViewNotifierWidget.

Fixed send duplicated attachments issue.
  • Loading branch information
Gambley1 committed Aug 5, 2024
1 parent e2d9f3d commit a312011
Show file tree
Hide file tree
Showing 33 changed files with 384 additions and 162 deletions.
28 changes: 23 additions & 5 deletions lib/auth/login/view/login_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,29 @@ class LoginView extends StatelessWidget {
),
),
const Align(child: SignInButton()),
const Padding(
padding: EdgeInsets.symmetric(
vertical: AppSpacing.md,
),
child: AppDivider(withText: true),
Row(
children: <Widget>[
const Expanded(
child: AppDivider(
endIndent: AppSpacing.sm,
indent: AppSpacing.md,
color: AppColors.white,
height: 36,
),
),
Text(
'OR',
style: context.titleMedium,
),
const Expanded(
child: AppDivider(
color: AppColors.white,
indent: AppSpacing.sm,
endIndent: AppSpacing.md,
height: 36,
),
),
],
),
Align(
child: AuthProviderSignInButton(
Expand Down
3 changes: 2 additions & 1 deletion lib/chats/chat/view/chat_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -456,10 +456,11 @@ class ChatAppBar extends StatelessWidget implements PreferredSizeWidget {
title: Text(participant.displayUsername),
subtitle: Text(context.l10n.onlineText),
leading: UserStoriesAvatar(
resizeHeight: 156,
author: participant,
enableInactiveBorder: false,
withAdaptiveBorder: false,
radius: 26,
radius: 22,
),
),
bottom: const PreferredSize(
Expand Down
33 changes: 26 additions & 7 deletions lib/chats/chat/widgets/message_content.dart
Original file line number Diff line number Diff line change
Expand Up @@ -236,13 +236,7 @@ class MessageSharedPost extends StatelessWidget {
),
Stack(
children: [
AspectRatio(
aspectRatio: 1,
child: ImageAttachmentThumbnail(
image: Attachment(imageUrl: sharedPost.firstMediaUrl),
fit: BoxFit.cover,
),
),
MessageSharedPostImage(sharedPost: sharedPost),
Positioned(
top: AppSpacing.sm,
right: AppSpacing.sm,
Expand Down Expand Up @@ -329,6 +323,31 @@ class MessageSharedPost extends StatelessWidget {
}
}

class MessageSharedPostImage extends StatelessWidget {
const MessageSharedPostImage({
required this.sharedPost,
super.key,
});

final PostBlock sharedPost;

@override
Widget build(BuildContext context) {
final screenWidth = (context.screenWidth * .85) - AppSpacing.md * 2;
final pixelRatio = context.devicePixelRatio;

final thumbnailWidth = (screenWidth * pixelRatio) ~/ 1;
return AspectRatio(
aspectRatio: 1,
child: ImageAttachmentThumbnail(
resizeHeight: thumbnailWidth,
image: Attachment(imageUrl: sharedPost.firstMediaUrl),
fit: BoxFit.cover,
),
);
}
}

class MessageSharedReel extends StatelessWidget {
const MessageSharedReel({
required this.sharedPost,
Expand Down
30 changes: 5 additions & 25 deletions lib/chats/chat/widgets/message_input_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -144,26 +144,11 @@ class MessageInputController extends ValueNotifier<Message> {
attachments = [...attachments, attachment];
}

/// Adds a new attachment at the specified [index].
void addAttachmentAt(int index, Attachment attachment) {
attachments = [...attachments]..insert(index, attachment);
}

/// Removes the specified [attachment] from the message.
void removeAttachment(Attachment attachment) {
attachments = [...attachments]..remove(attachment);
}

/// Remove the attachment with the given [attachmentId].
void removeAttachmentById(String attachmentId) {
attachments = [...attachments]..removeWhere((it) => it.id == attachmentId);
}

/// Removes the attachment at the given [index].
void removeAttachmentAt(int index) {
attachments = [...attachments]..removeAt(index);
}

/// Clears the message attachments.
void clearAttachments() {
attachments = [];
Expand Down Expand Up @@ -242,17 +227,12 @@ class MessageInputController extends ValueNotifier<Message> {
if (attachments
.map((e) => e.type.toAttachmentType)
.contains(AttachmentType.urlPreview)) {
attachments.retainWhere(
(e) => e.type.toAttachmentType == AttachmentType.urlPreview,
);
attachments = [...attachments]
..remove(attachment)
..insert(0, attachment);
} else {
attachments = [...attachments]
..remove(attachment)
..insert(0, attachment);
attachments = attachments
..removeWhere(
(e) => e.type.toAttachmentType == AttachmentType.urlPreview,
);
}
addAttachment(attachment);
_ogAttachment = attachment;
}

Expand Down
1 change: 1 addition & 0 deletions lib/chats/chat/widgets/replied_message_bubble.dart
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class RepliedMessageBubble extends StatelessWidget {
children: [
if (!repliedMessageSharedPostDeleted) ...[
ImageAttachmentThumbnail(
resizeHeight: 138,
image: Attachment(imageUrl: replyMessageAttachmentUrl),
fit: BoxFit.cover,
borderRadius: 4,
Expand Down
1 change: 1 addition & 0 deletions lib/chats/widgets/chat_inbox_tile.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class ChatInboxTile extends StatelessWidget {
.add(ChatsDeleteChatRequested(chatId: chat.id, userId: user.id)),
),
leading: UserStoriesAvatar(
resizeHeight: 156,
author: participant,
enableInactiveBorder: false,
withAdaptiveBorder: false,
Expand Down
1 change: 1 addition & 0 deletions lib/comments/comment/view/comment_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ class CommentGroup extends StatelessWidget {
),
avatarBuilder: (context, author, onAvatarTap, radius) =>
UserStoriesAvatar(
resizeHeight: 108,
author: author,
onAvatarTap: onAvatarTap,
radius: radius,
Expand Down
1 change: 1 addition & 0 deletions lib/feed/post/view/post_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ class PostLargeView extends StatelessWidget {
likersInFollowings: likersInFollowings,
postAuthorAvatarBuilder: (context, author, onAvatarTap) {
return UserStoriesAvatar(
resizeHeight: 108,
author: author.toUser,
onAvatarTap: onAvatarTap,
enableInactiveBorder: false,
Expand Down
35 changes: 28 additions & 7 deletions lib/feed/post/widgets/post_popup_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ class PopupDialogHeader extends StatelessWidget {
),
horizontalTitleGap: AppSpacing.sm,
leading: UserProfileAvatar(
resizeHeight: 108,
avatarUrl: block.author.avatarUrl,
isLarge: false,
enableBorder: false,
Expand Down Expand Up @@ -134,13 +135,7 @@ class PopupDialogBody extends StatelessWidget {
alignment: Alignment.center,
children: [
if (block.firstMedia is ImageMedia)
AspectRatio(
aspectRatio: 1,
child: ImageAttachmentThumbnail(
image: Attachment(imageUrl: block.firstMediaUrl),
fit: BoxFit.cover,
),
)
PostPopupImage(block: block)
else
InlineVideo(
videoSettings: VideoSettings.build(
Expand Down Expand Up @@ -172,6 +167,32 @@ class PopupDialogBody extends StatelessWidget {
}
}

class PostPopupImage extends StatelessWidget {
const PostPopupImage({
required this.block,
super.key,
});

final PostBlock block;

@override
Widget build(BuildContext context) {
final screenWidth = (context.screenWidth) - AppSpacing.md * 2;
final pixelRatio = context.devicePixelRatio;

final thumbnailWidth = (screenWidth * pixelRatio) ~/ 1;

return AspectRatio(
aspectRatio: 1,
child: ImageAttachmentThumbnail(
resizeWidth: thumbnailWidth,
image: Attachment(imageUrl: block.firstMediaUrl),
fit: BoxFit.cover,
),
);
}
}

class PopupDialogFooter extends StatelessWidget {
const PopupDialogFooter({
required this.likeButtonKey,
Expand Down
1 change: 1 addition & 0 deletions lib/feed/post/widgets/share_post.dart
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,7 @@ class UsersListView extends StatelessWidget {
Stack(
children: [
UserProfileAvatar(
resizeHeight: 252,
avatarUrl: user.avatarUrl,
enableBorder: false,
),
Expand Down
7 changes: 6 additions & 1 deletion lib/feed/view/feed_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,12 @@ class FeedBody extends StatelessWidget {
}
}
if (block is PostBlock) {
return PostView(key: ValueKey(block.id), block: block, postIndex: index);
return PostView(
key: ValueKey(block.id),
block: block,
postIndex: index,
withInViewNotifier: block.isReel,
);
}

return Text('Unknown block type: ${block.type}');
Expand Down
1 change: 1 addition & 0 deletions lib/reels/reel/view/reel_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,7 @@ class ReelAuthorListTile extends StatelessWidget {
return Row(
children: <Widget>[
UserStoriesAvatar(
resizeHeight: 108,
author: author.toUser,
withAdaptiveBorder: false,
enableInactiveBorder: false,
Expand Down
1 change: 1 addition & 0 deletions lib/search/view/search_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class UserListTile extends StatelessWidget {
Widget build(BuildContext context) {
return ListTile(
leading: UserStoriesAvatar(
resizeHeight: 156,
author: user,
withAdaptiveBorder: false,
enableInactiveBorder: false,
Expand Down
1 change: 1 addition & 0 deletions lib/stories/widgets/stories_carousel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ class StoriesListView extends StatelessWidget {
onLongPress,
) {
return UserStoriesAvatar(
resizeHeight: 252,
isLarge: true,
stories: stories,
author: author,
Expand Down
1 change: 1 addition & 0 deletions lib/stories/widgets/story_avatar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ class AvatarView extends StatelessWidget {
onLongPress,
) ??
UserProfileAvatar(
resizeHeight: 252,
withAddButton: isMine,
stories: state.stories,
onTap: onTap,
Expand Down
12 changes: 12 additions & 0 deletions lib/stories/widgets/user_stories_avatar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ class UserStoriesAvatar extends StatelessWidget {
this.showStories,
this.showWhenSeen,
this.isLarge = false,
this.resizeHeight,
this.resizeWidth,
this.isImagePicker = false,
this.enableInactiveBorder = true,
this.withShimmerPlaceholder = false,
Expand All @@ -42,6 +44,8 @@ class UserStoriesAvatar extends StatelessWidget {
final bool? showStories;
final bool? showWhenSeen;
final bool isLarge;
final int? resizeHeight;
final int? resizeWidth;
final bool isImagePicker;
final bool enableInactiveBorder;
final bool withShimmerPlaceholder;
Expand All @@ -64,6 +68,8 @@ class UserStoriesAvatar extends StatelessWidget {
showStories: showStories,
showWhenSeen: showWhenSeen,
isLarge: isLarge,
resizeHeight: resizeHeight,
resizeWidth: resizeWidth,
onImagePick: onImagePick,
enableInactiveBorder: enableInactiveBorder,
withShimmerPlaceholder: withShimmerPlaceholder,
Expand Down Expand Up @@ -104,6 +110,8 @@ class ProfileAvatar extends StatelessWidget {
required this.onImagePick,
required this.onAddButtonTap,
required this.withAdaptiveBorder,
required this.resizeHeight,
required this.resizeWidth,
super.key,
});

Expand All @@ -116,6 +124,8 @@ class ProfileAvatar extends StatelessWidget {
final bool? showStories;
final bool? showWhenSeen;
final bool isLarge;
final int? resizeHeight;
final int? resizeWidth;
final bool enableInactiveBorder;
final bool withShimmerPlaceholder;
final bool withAdaptiveBorder;
Expand All @@ -142,6 +152,8 @@ class ProfileAvatar extends StatelessWidget {
showStories: this.showStories ?? showStories,
avatarUrl: author.avatarUrl,
isLarge: isLarge,
resizeHeight: resizeHeight,
resizeWidth: resizeWidth,
onImagePick: onImagePick,
withAddButton: withAddButton,
onLongPress: onLongPress,
Expand Down
28 changes: 24 additions & 4 deletions lib/timeline/view/timeline_page.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:math';

import 'package:app_ui/app_ui.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
Expand Down Expand Up @@ -215,17 +217,35 @@ class _TimelineGridViewState extends State<TimelineGridView> {
);
},
)
: ImageAttachmentThumbnail(
image: Attachment(imageUrl: url),
fit: BoxFit.cover,
),
: TimelinePostImage(url: url),
),
);
},
);
}
}

class TimelinePostImage extends StatelessWidget {
const TimelinePostImage({required this.url, super.key});

final String url;

@override
Widget build(BuildContext context) {
/// AppSpacing.xxs is the padding of the image.
final screenWidth = (context.screenWidth - AppSpacing.xxs) / 3;
final pixelRatio = context.devicePixelRatio;

final size = min((screenWidth * pixelRatio) ~/ 1, 1920);

return ImageAttachmentThumbnail(
resizeHeight: size,
image: Attachment(imageUrl: url),
fit: BoxFit.cover,
);
}
}

class TimelineLoading extends StatelessWidget {
const TimelineLoading({super.key});

Expand Down
Loading

0 comments on commit a312011

Please sign in to comment.