mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 07:55:18 +00:00
feat: optimize image load + genre page and reduce page size of loaded categories
This commit is contained in:
parent
862c4b8faf
commit
7131efa07f
18
.vscode/launch.json
vendored
18
.vscode/launch.json
vendored
@ -2,11 +2,25 @@
|
|||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "Flutter",
|
"name": "spotube",
|
||||||
"type": "dart",
|
"type": "dart",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${workspaceFolder}/lib/main.dart"
|
"program": "lib/main.dart"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "spotube (profile)",
|
||||||
|
"type": "dart",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "lib/main.dart",
|
||||||
|
"flutterMode": "profile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "spotube (release)",
|
||||||
|
"type": "dart",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "lib/main.dart",
|
||||||
|
"flutterMode": "release"
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"compounds": []
|
"compounds": []
|
||||||
}
|
}
|
@ -33,12 +33,7 @@ class PlayerTrackDetails extends HookConsumerWidget {
|
|||||||
borderRadius: BorderRadius.circular(4),
|
borderRadius: BorderRadius.circular(4),
|
||||||
child: UniversalImage(
|
child: UniversalImage(
|
||||||
path: albumArt ?? "",
|
path: albumArt ?? "",
|
||||||
placeholder: (context, url) {
|
placeholder: Assets.albumPlaceholder.path,
|
||||||
return Assets.albumPlaceholder.image(
|
|
||||||
height: 50,
|
|
||||||
width: 50,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -11,7 +11,7 @@ class UniversalImage extends HookWidget {
|
|||||||
final double? height;
|
final double? height;
|
||||||
final double? width;
|
final double? width;
|
||||||
final double scale;
|
final double scale;
|
||||||
final PlaceholderWidgetBuilder? placeholder;
|
final String? placeholder;
|
||||||
const UniversalImage({
|
const UniversalImage({
|
||||||
required this.path,
|
required this.path,
|
||||||
this.height,
|
this.height,
|
||||||
@ -46,16 +46,17 @@ class UniversalImage extends HookWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (path.startsWith("http")) {
|
if (path.startsWith("http")) {
|
||||||
return CachedNetworkImage(
|
return FadeInImage(
|
||||||
imageUrl: path,
|
image: CachedNetworkImageProvider(
|
||||||
|
path,
|
||||||
|
maxHeight: height?.toInt(),
|
||||||
|
maxWidth: width?.toInt(),
|
||||||
|
cacheKey: path,
|
||||||
|
scale: scale,
|
||||||
|
),
|
||||||
height: height,
|
height: height,
|
||||||
width: width,
|
width: width,
|
||||||
maxWidthDiskCache: width?.toInt(),
|
placeholder: AssetImage(placeholder ?? Assets.placeholder.path),
|
||||||
maxHeightDiskCache: height?.toInt(),
|
|
||||||
memCacheHeight: height?.toInt(),
|
|
||||||
memCacheWidth: width?.toInt(),
|
|
||||||
placeholder: placeholder,
|
|
||||||
cacheKey: path,
|
|
||||||
);
|
);
|
||||||
} else if (Uri.tryParse(path) != null && !path.startsWith("assets")) {
|
} else if (Uri.tryParse(path) != null && !path.startsWith("assets")) {
|
||||||
return Image.file(
|
return Image.file(
|
||||||
@ -66,14 +67,14 @@ class UniversalImage extends HookWidget {
|
|||||||
cacheWidth: width?.toInt(),
|
cacheWidth: width?.toInt(),
|
||||||
scale: scale,
|
scale: scale,
|
||||||
errorBuilder: (context, error, stackTrace) {
|
errorBuilder: (context, error, stackTrace) {
|
||||||
return placeholder?.call(context, error.toString()) ??
|
return Image.asset(
|
||||||
Assets.placeholder.image(
|
placeholder ?? Assets.placeholder.path,
|
||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
cacheHeight: height?.toInt(),
|
cacheHeight: height?.toInt(),
|
||||||
cacheWidth: width?.toInt(),
|
cacheWidth: width?.toInt(),
|
||||||
scale: scale,
|
scale: scale,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} else if (path.startsWith("assets")) {
|
} else if (path.startsWith("assets")) {
|
||||||
@ -85,14 +86,14 @@ class UniversalImage extends HookWidget {
|
|||||||
cacheWidth: width?.toInt(),
|
cacheWidth: width?.toInt(),
|
||||||
scale: scale,
|
scale: scale,
|
||||||
errorBuilder: (context, error, stackTrace) {
|
errorBuilder: (context, error, stackTrace) {
|
||||||
return placeholder?.call(context, error.toString()) ??
|
return Image.asset(
|
||||||
Assets.placeholder.image(
|
placeholder ?? Assets.placeholder.path,
|
||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
cacheHeight: height?.toInt(),
|
cacheHeight: height?.toInt(),
|
||||||
cacheWidth: width?.toInt(),
|
cacheWidth: width?.toInt(),
|
||||||
scale: scale,
|
scale: scale,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -105,14 +106,14 @@ class UniversalImage extends HookWidget {
|
|||||||
cacheWidth: width?.toInt(),
|
cacheWidth: width?.toInt(),
|
||||||
scale: scale,
|
scale: scale,
|
||||||
errorBuilder: (context, error, stackTrace) {
|
errorBuilder: (context, error, stackTrace) {
|
||||||
return placeholder?.call(context, error.toString()) ??
|
return Image.asset(
|
||||||
Assets.placeholder.image(
|
placeholder ?? Assets.placeholder.path,
|
||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
cacheHeight: height?.toInt(),
|
cacheHeight: height?.toInt(),
|
||||||
cacheWidth: width?.toInt(),
|
cacheWidth: width?.toInt(),
|
||||||
scale: scale,
|
scale: scale,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -84,10 +84,7 @@ class PlaybuttonCard extends HookWidget {
|
|||||||
borderRadius: radius,
|
borderRadius: radius,
|
||||||
child: UniversalImage(
|
child: UniversalImage(
|
||||||
path: imageUrl,
|
path: imageUrl,
|
||||||
placeholder: (context, url) {
|
placeholder: Assets.albumPlaceholder.path,
|
||||||
return Assets.albumPlaceholder
|
|
||||||
.image(fit: BoxFit.cover);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -174,6 +174,7 @@ class TrackCollectionView<T> extends HookConsumerWidget {
|
|||||||
color: color?.titleTextColor ?? Colors.white,
|
color: color?.titleTextColor ?? Colors.white,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
isDense: true,
|
||||||
prefixIconColor: color?.titleTextColor,
|
prefixIconColor: color?.titleTextColor,
|
||||||
prefixIcon: const Icon(SpotubeIcons.search),
|
prefixIcon: const Icon(SpotubeIcons.search),
|
||||||
),
|
),
|
||||||
@ -269,9 +270,7 @@ class TrackCollectionView<T> extends HookConsumerWidget {
|
|||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
child: UniversalImage(
|
child: UniversalImage(
|
||||||
path: titleImage,
|
path: titleImage,
|
||||||
placeholder: (context, url) {
|
placeholder: Assets.albumPlaceholder.path,
|
||||||
return Assets.albumPlaceholder.image();
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -216,12 +216,7 @@ class TrackTile extends HookConsumerWidget {
|
|||||||
path: thumbnailUrl,
|
path: thumbnailUrl,
|
||||||
height: 40,
|
height: 40,
|
||||||
width: 40,
|
width: 40,
|
||||||
placeholder: (context, url) {
|
placeholder: Assets.albumPlaceholder.path,
|
||||||
return Assets.albumPlaceholder.image(
|
|
||||||
height: 40,
|
|
||||||
width: 40,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -14,6 +14,7 @@ import 'package:package_info_plus/package_info_plus.dart';
|
|||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:spotube/collections/cache_keys.dart';
|
import 'package:spotube/collections/cache_keys.dart';
|
||||||
import 'package:spotube/collections/env.dart';
|
import 'package:spotube/collections/env.dart';
|
||||||
|
import 'package:spotube/components/settings/color_scheme_picker_dialog.dart';
|
||||||
import 'package:spotube/components/shared/dialogs/replace_downloaded_dialog.dart';
|
import 'package:spotube/components/shared/dialogs/replace_downloaded_dialog.dart';
|
||||||
import 'package:spotube/entities/cache_track.dart';
|
import 'package:spotube/entities/cache_track.dart';
|
||||||
import 'package:spotube/collections/routes.dart';
|
import 'package:spotube/collections/routes.dart';
|
||||||
@ -69,6 +70,7 @@ void main(List<String> rawArgs) async {
|
|||||||
|
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
await SystemTheme.accentColor.load();
|
await SystemTheme.accentColor.load();
|
||||||
|
colorsMap["System"] = SystemTheme.accentColor.accent;
|
||||||
await QueryClient.initialize(cachePrefix: "oss.krtirtho.spotube");
|
await QueryClient.initialize(cachePrefix: "oss.krtirtho.spotube");
|
||||||
Hive.registerAdapter(CacheTrackAdapter());
|
Hive.registerAdapter(CacheTrackAdapter());
|
||||||
Hive.registerAdapter(CacheTrackEngagementAdapter());
|
Hive.registerAdapter(CacheTrackEngagementAdapter());
|
||||||
|
@ -68,20 +68,17 @@ class GenrePage extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
controller: scrollController,
|
controller: scrollController,
|
||||||
child: SingleChildScrollView(
|
child: SafeArea(
|
||||||
child: SafeArea(
|
child: ListView.builder(
|
||||||
child: Column(
|
controller: scrollController,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
itemCount: categories.length,
|
||||||
children: [
|
shrinkWrap: true,
|
||||||
...categories.mapIndexed((index, category) {
|
itemBuilder: (context, index) {
|
||||||
if (searchText.value.isEmpty &&
|
if (searchText.value.isEmpty && index == categories.length - 1) {
|
||||||
index == categories.length - 1) {
|
return const ShimmerCategories();
|
||||||
return const ShimmerCategories();
|
}
|
||||||
}
|
return CategoryCard(categories[index]);
|
||||||
return CategoryCard(category);
|
},
|
||||||
})
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -110,26 +110,23 @@ class PersonalizedPage extends HookConsumerWidget {
|
|||||||
|
|
||||||
final newReleases = useQueries.album.newReleases(ref);
|
final newReleases = useQueries.album.newReleases(ref);
|
||||||
|
|
||||||
return SingleChildScrollView(
|
return SafeArea(
|
||||||
child: SafeArea(
|
child: ListView(
|
||||||
child: Column(
|
children: [
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
PersonalizedItemCard(
|
||||||
children: [
|
playlists:
|
||||||
PersonalizedItemCard(
|
featuredPlaylistsQuery.pages.whereType<Page<PlaylistSimple>>(),
|
||||||
playlists: featuredPlaylistsQuery.pages
|
title: 'Featured',
|
||||||
.whereType<Page<PlaylistSimple>>(),
|
hasNextPage: featuredPlaylistsQuery.hasNextPage,
|
||||||
title: 'Featured',
|
onFetchMore: featuredPlaylistsQuery.fetchNext,
|
||||||
hasNextPage: featuredPlaylistsQuery.hasNextPage,
|
),
|
||||||
onFetchMore: featuredPlaylistsQuery.fetchNext,
|
PersonalizedItemCard(
|
||||||
),
|
albums: newReleases.pages.whereType<Page<AlbumSimple>>(),
|
||||||
PersonalizedItemCard(
|
title: 'New Releases',
|
||||||
albums: newReleases.pages.whereType<Page<AlbumSimple>>(),
|
hasNextPage: newReleases.hasNextPage,
|
||||||
title: 'New Releases',
|
onFetchMore: newReleases.fetchNext,
|
||||||
hasNextPage: newReleases.hasNextPage,
|
),
|
||||||
onFetchMore: newReleases.fetchNext,
|
],
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -16,13 +16,13 @@ class CategoryQueries {
|
|||||||
country: recommendationMarket,
|
country: recommendationMarket,
|
||||||
locale: 'en_US',
|
locale: 'en_US',
|
||||||
)
|
)
|
||||||
.getPage(15, pageParam);
|
.getPage(8, pageParam);
|
||||||
|
|
||||||
return categories;
|
return categories;
|
||||||
},
|
},
|
||||||
initialPage: 0,
|
initialPage: 0,
|
||||||
nextPage: (lastPage, lastPageData) {
|
nextPage: (lastPage, lastPageData) {
|
||||||
if (lastPageData.isLast || (lastPageData.items ?? []).length < 15) {
|
if (lastPageData.isLast || (lastPageData.items ?? []).length < 8) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return lastPageData.nextOffset;
|
return lastPageData.nextOffset;
|
||||||
|
31
pubspec.lock
31
pubspec.lock
@ -554,14 +554,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0-alpha.2"
|
version: "1.0.0-alpha.2"
|
||||||
fluent_ui:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: fluent_ui
|
|
||||||
sha256: "29d85b74ee8d051bed9b5234afd50af4a693fef91f4e79657644051c23d789fb"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "4.4.1"
|
|
||||||
fluentui_system_icons:
|
fluentui_system_icons:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -679,11 +671,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.1"
|
version: "2.0.1"
|
||||||
flutter_localizations:
|
|
||||||
dependency: transitive
|
|
||||||
description: flutter
|
|
||||||
source: sdk
|
|
||||||
version: "0.0.0"
|
|
||||||
flutter_mailer:
|
flutter_mailer:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1286,14 +1273,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.2.1"
|
version: "3.2.1"
|
||||||
recase:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: recase
|
|
||||||
sha256: e4eb4ec2dcdee52dcf99cb4ceabaffc631d7424ee55e56f280bc039737f89213
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "4.1.0"
|
|
||||||
riverpod:
|
riverpod:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1318,14 +1297,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.6"
|
version: "0.1.6"
|
||||||
scroll_pos:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: scroll_pos
|
|
||||||
sha256: cfca311b6b8d51538ff90e206fbe6ce3b36e7125ea6da4a40eb626c7f9f083b1
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.3.0"
|
|
||||||
scroll_to_index:
|
scroll_to_index:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -1807,4 +1778,4 @@ packages:
|
|||||||
version: "1.12.3"
|
version: "1.12.3"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=2.19.0 <3.0.0"
|
dart: ">=2.19.0 <3.0.0"
|
||||||
flutter: ">=3.7.0"
|
flutter: ">=3.3.0"
|
||||||
|
Loading…
Reference in New Issue
Block a user