chore: improve home screen performance

This commit is contained in:
Kingkor Roy Tirtho 2025-02-23 09:55:46 +06:00
parent e8e2d78529
commit 47edb8bf96
5 changed files with 52 additions and 89 deletions

View File

@ -52,7 +52,11 @@ class PlaybuttonCard extends StatelessWidget {
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: context.theme.borderRadiusMd, borderRadius: context.theme.borderRadiusMd,
image: DecorationImage( image: DecorationImage(
image: UniversalImage.imageProvider(imageUrl!), image: UniversalImage.imageProvider(
imageUrl!,
height: 200 * scale,
width: 200 * scale,
),
fit: BoxFit.cover, fit: BoxFit.cover,
), ),
), ),

View File

@ -1,6 +1,5 @@
import 'dart:ui'; import 'dart:ui';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:shadcn_flutter/shadcn_flutter.dart'; import 'package:shadcn_flutter/shadcn_flutter.dart';
import 'package:shadcn_flutter/shadcn_flutter_extension.dart'; import 'package:shadcn_flutter/shadcn_flutter_extension.dart';
@ -8,8 +7,6 @@ import 'package:skeletonizer/skeletonizer.dart';
import 'package:spotube/collections/fake.dart'; import 'package:spotube/collections/fake.dart';
import 'package:spotube/modules/home/sections/friends/friend_item.dart'; import 'package:spotube/modules/home/sections/friends/friend_item.dart';
import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/context.dart';
import 'package:spotube/hooks/utils/use_breakpoint_value.dart';
import 'package:spotube/models/spotify_friends.dart';
import 'package:spotube/provider/authentication/authentication.dart'; import 'package:spotube/provider/authentication/authentication.dart';
import 'package:spotube/provider/spotify/spotify.dart'; import 'package:spotube/provider/spotify/spotify.dart';
@ -23,90 +20,46 @@ class HomePageFriendsSection extends HookConsumerWidget {
final friends = final friends =
friendsQuery.asData?.value.friends ?? FakeData.friends.friends; friendsQuery.asData?.value.friends ?? FakeData.friends.friends;
final groupCount = useBreakpointValue(
sm: 3,
xs: 2,
md: 4,
lg: 5,
xl: 6,
xxl: 7,
);
final friendGroup = useMemoized(
() => friends.fold<List<List<SpotifyFriendActivity>>>(
[],
(previousValue, element) {
if (previousValue.isEmpty) {
return [
[element]
];
}
final lastGroup = previousValue.last;
if (lastGroup.length < groupCount) {
return [
...previousValue.sublist(0, previousValue.length - 1),
[...lastGroup, element]
];
}
return [
...previousValue,
[element]
];
},
),
[friends, groupCount],
);
if (friendsQuery.isLoading || if (friendsQuery.isLoading ||
friendsQuery.asData?.value.friends.isEmpty == true || friendsQuery.asData?.value.friends.isEmpty == true ||
auth.asData?.value == null) { auth.asData?.value == null) {
return const SliverToBoxAdapter( return const SizedBox.shrink();
child: SizedBox.shrink(),
);
} }
return Skeletonizer.sliver( return Column(
enabled: friendsQuery.isLoading, crossAxisAlignment: CrossAxisAlignment.start,
child: SliverMainAxisGroup( mainAxisAlignment: MainAxisAlignment.start,
slivers: [ children: [
SliverToBoxAdapter( Padding(
child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Text( child: Text(
context.l10n.friends, context.l10n.friends,
style: context.theme.typography.h4, style: context.theme.typography.h4,
), ),
), ),
), SizedBox(
SliverToBoxAdapter( height: 80 * context.theme.scaling,
width: double.infinity,
child: ScrollConfiguration( child: ScrollConfiguration(
behavior: ScrollConfiguration.of(context).copyWith( behavior: ScrollConfiguration.of(context).copyWith(
dragDevices: PointerDeviceKind.values.toSet(), dragDevices: PointerDeviceKind.values.toSet(),
scrollbars: false,
), ),
child: SingleChildScrollView( child: Skeletonizer(
enabled: friendsQuery.isLoading,
child: ListView.separated(
padding: const EdgeInsets.symmetric(horizontal: 8),
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
child: Column( itemCount: friends.length,
crossAxisAlignment: CrossAxisAlignment.start, separatorBuilder: (context, index) => const Gap(8),
children: [ itemBuilder: (context, index) {
for (final group in friendGroup) return FriendItem(friend: friends[index]);
Row( },
children: [
for (final friend in group)
Padding(
padding: const EdgeInsets.all(8.0),
child: FriendItem(friend: friend),
),
],
),
],
), ),
), ),
), ),
), ),
], ],
),
); );
} }
} }

View File

@ -35,7 +35,8 @@ class HomeGenresSection extends HookConsumerWidget {
); );
final controller = useMemoized(() => CarouselController(), []); final controller = useMemoized(() => CarouselController(), []);
return SliverList.list( return Column(
mainAxisSize: MainAxisSize.min,
children: [ children: [
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: 8), padding: const EdgeInsets.symmetric(horizontal: 8),

View File

@ -6,7 +6,6 @@ import 'package:spotify/spotify.dart' hide Offset, Image;
import 'package:spotube/collections/env.dart'; import 'package:spotube/collections/env.dart';
import 'package:spotube/collections/routes.gr.dart'; import 'package:spotube/collections/routes.gr.dart';
import 'package:spotube/components/dialogs/select_device_dialog.dart'; import 'package:spotube/components/dialogs/select_device_dialog.dart';
import 'package:spotube/components/image/universal_image.dart';
import 'package:spotube/components/playbutton_view/playbutton_card.dart'; import 'package:spotube/components/playbutton_view/playbutton_card.dart';
import 'package:spotube/components/playbutton_view/playbutton_tile.dart'; import 'package:spotube/components/playbutton_view/playbutton_tile.dart';
import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/context.dart';
@ -200,16 +199,14 @@ class PlaylistCard extends HookConsumerWidget {
); );
}, },
) )
: UniversalImage( : null;
path: imageUrl,
fit: BoxFit.cover,
);
if (_isTile) { if (_isTile) {
return PlaybuttonTile( return PlaybuttonTile(
title: playlist.name!, title: playlist.name!,
description: playlist.description, description: playlist.description,
image: image, image: image,
imageUrl: image == null ? imageUrl : null,
isPlaying: isPlaylistPlaying, isPlaying: isPlaylistPlaying,
isLoading: isLoading, isLoading: isLoading,
isOwner: isOwner, isOwner: isOwner,
@ -223,6 +220,7 @@ class PlaylistCard extends HookConsumerWidget {
title: playlist.name!, title: playlist.name!,
description: playlist.description, description: playlist.description,
image: image, image: image,
imageUrl: image == null ? imageUrl : null,
isPlaying: isPlaylistPlaying, isPlaying: isPlaylistPlaying,
isLoading: isLoading, isLoading: isLoading,
isOwner: isOwner, isOwner: isOwner,

View File

@ -62,12 +62,19 @@ class HomePage extends HookConsumerWidget {
) )
else if (kIsMacOS) else if (kIsMacOS)
const SliverGap(10), const SliverGap(10),
const HomeGenresSection(),
const SliverGap(10), const SliverGap(10),
const SliverToBoxAdapter(child: HomeRecentlyPlayedSection()), SliverList.builder(
const SliverToBoxAdapter(child: HomeFeaturedSection()), itemCount: 5,
const HomePageFriendsSection(), itemBuilder: (context, index) {
const SliverToBoxAdapter(child: HomeNewReleasesSection()), return switch (index) {
0 => const HomeGenresSection(),
1 => const HomeRecentlyPlayedSection(),
2 => const HomeFeaturedSection(),
3 => const HomePageFriendsSection(),
_ => const HomeNewReleasesSection()
};
},
),
const HomePageFeedSection(), const HomePageFeedSection(),
const SliverSafeArea(sliver: HomeMadeForUserSection()), const SliverSafeArea(sliver: HomeMadeForUserSection()),
], ],