fix(ui): resolve album titles and show Home explicit badges

Hide the profile setup hint once a name or photo is saved.
This commit is contained in:
zarzet
2026-09-21 19:02:13 +07:00
parent 5958fe2719
commit 4c5af08cdd
7 changed files with 145 additions and 13 deletions
+87
View File
@@ -8,11 +8,98 @@ import 'package:shared_preferences/shared_preferences.dart';
import 'package:spotiflac_android/l10n/app_localizations.dart';
import 'package:spotiflac_android/models/track.dart';
import 'package:spotiflac_android/screens/album_screen.dart';
import 'package:spotiflac_android/screens/home_tab.dart';
import 'package:spotiflac_android/services/platform_bridge.dart';
import 'package:spotiflac_android/theme/mornye_theme.dart';
import 'package:spotiflac_android/widgets/audio_quality_badges.dart';
import 'package:spotiflac_android/widgets/track_list_tile.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
const backendChannel = MethodChannel('com.zarz.spotiflac/backend');
final backendMessenger =
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger;
setUp(() async {
SharedPreferences.setMockInitialValues({});
backendMessenger.setMockMethodCallHandler(
backendChannel,
(_) async => null,
);
await PlatformBridge.clearTrackCache();
});
tearDown(() async {
backendMessenger.setMockMethodCallHandler(
backendChannel,
(_) async => null,
);
await PlatformBridge.clearTrackCache();
backendMessenger.setMockMethodCallHandler(backendChannel, null);
});
for (final nested in [true, false]) {
for (final fetchedName in ['Actual Album Title', ' ']) {
testWidgets(
'extension album resolves its title (nested: $nested, name: "$fetchedName")',
(tester) async {
SharedPreferences.setMockInitialValues({});
await tester.binding.setSurfaceSize(const Size(430, 1200));
addTearDown(() => tester.binding.setSurfaceSize(null));
const channel = MethodChannel('com.zarz.spotiflac/backend');
final messenger = tester.binding.defaultBinaryMessenger;
var requests = 0;
messenger.setMockMethodCallHandler(channel, (call) async {
if (call.method != 'getProviderMetadata') return null;
requests++;
final info = <String, dynamic>{
'name': fetchedName,
'artists': 'Example Artist',
'total_tracks': 1,
};
final tracks = [
{
'id': 'example-song',
'name': 'Example Song',
'artists': 'Example Artist',
'album_name': '',
'duration_ms': 180000,
},
];
return jsonEncode(
nested
? {'album_info': info, 'track_list': tracks}
: {...info, 'tracks': tracks},
);
});
addTearDown(() => messenger.setMockMethodCallHandler(channel, null));
await tester.pumpWidget(
ProviderScope(
child: MaterialApp(
theme: MornyeTheme.build(Brightness.light),
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: const ExtensionAlbumScreen(
extensionId: 'example-metadata',
albumId: 'example-album',
albumName: 'Album',
),
),
),
);
await tester.pumpAndSettle();
final expected = fetchedName.trim().isEmpty ? 'Album' : fetchedName;
final album = tester.widget<AlbumScreen>(find.byType(AlbumScreen));
expect(album.albumName, expected);
expect(album.tracks!.single.albumName, expected);
expect(find.text(expected), findsWidgets);
expect(requests, 1);
expect(tester.takeException(), isNull);
await tester.pumpWidget(const SizedBox());
await tester.pumpAndSettle();
},
);
}
}
testWidgets('album tracks retain the extended tags supplied in search', (
tester,
) async {
+22 -2
View File
@@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:spotiflac_android/providers/explore_provider.dart';
import 'package:spotiflac_android/widgets/explore_featured_section.dart';
import 'package:spotiflac_android/widgets/audio_quality_badges.dart';
import 'package:spotiflac_android/l10n/app_localizations.dart';
void main() {
test('featured layout and artwork survive cache serialization', () {
@@ -18,6 +20,7 @@ void main() {
'featured_cover_url': 'https://example.test/banner.jpg',
'heading': 'Updated playlist',
'provider_id': 'example-provider',
'explicit': true,
},
],
});
@@ -27,6 +30,9 @@ void main() {
expect(restored.items.single.featuredCoverUrl, endsWith('/banner.jpg'));
expect(restored.items.single.coverUrl, endsWith('/cover.jpg'));
expect(restored.items.single.providerId, 'example-provider');
expect(restored.items.single.explicit, isTrue);
expect(ExploreItem.fromJson({'explicit': false}).explicit, isFalse);
expect(ExploreItem.fromJson({}).explicit, isNull);
expect(ExploreSection.fromJson({'items': <Object?>[]}).isFeatured, isFalse);
});
@@ -51,11 +57,14 @@ void main() {
name: 'Featured $index',
artists: 'Example artist',
heading: 'New album',
explicit: index == 0,
description: 'An editorial description of the featured album.',
),
);
await tester.pumpWidget(
MaterialApp(
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: MediaQuery(
data: MediaQueryData(textScaler: TextScaler.linear(scale)),
child: Scaffold(
@@ -75,12 +84,23 @@ void main() {
),
);
expect(tester.takeException(), isNull);
expect(find.byType(ExplicitBadge), findsOneWidget);
expect(
tester
.widget<ExplicitTrackTitle>(find.byType(ExplicitTrackTitle).first)
.explicit,
isTrue,
);
final firstTitle = find.byWidgetPredicate(
(widget) =>
widget is ExplicitTrackTitle && widget.title == 'Featured 0',
);
final card = find.ancestor(
of: find.text('Featured 0'),
of: firstTitle,
matching: find.byType(GestureDetector),
);
expect(tester.getSize(card).width, greaterThan(250));
await tester.tap(find.text('Featured 0'));
await tester.tap(firstTitle);
expect(opened?.id, 'collection-0');
await tester.drag(find.byType(ListView), const Offset(-600, 0));
await tester.pumpAndSettle();