feat(flutter): 重构播放页并增加语言切换

This commit is contained in:
Zhou Weidong committed 2026-10-20 11:01:38 +08:00
1 parent f1efbc5be8
commit 8c43e9e385
34 files changed
+1331 -879

No files matched your search

+1 -1
View File
@@ -68,7 +68,7 @@ void main() {
await tester.pumpAndSettle();
expect(find.text('Second page'), findsOneWidget);
expect(find.text('Comments (2)'), findsOneWidget);
expect(find.text('2 comments'), findsOneWidget);
expect(repository.pageCalls.last.cursor, '10');
});
+39
View File
@@ -0,0 +1,39 @@
// Author: fruit.com.cn
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:fruitshorts/core/data/services/locale_controller.dart';
import 'package:shared_preferences_platform_interface/in_memory_shared_preferences_async.dart';
import 'package:shared_preferences_platform_interface/shared_preferences_async_platform_interface.dart';
void main() {
setUp(() {
SharedPreferencesAsyncPlatform.instance =
InMemorySharedPreferencesAsync.empty();
});
test('should_restore_saved_locale_when_controller_loads', () async {
SharedPreferencesAsyncPlatform.instance =
InMemorySharedPreferencesAsync.withData({
LocaleController.preferenceKey: 'zh',
});
final controller = LocaleController();
await controller.load();
expect(controller.locale?.languageCode, 'zh');
controller.dispose();
});
test('should_persist_selected_locale_for_next_launch', () async {
final controller = LocaleController();
await controller.select(const Locale('id'));
final restored = LocaleController();
await restored.load();
expect(restored.locale?.languageCode, 'id');
controller.dispose();
restored.dispose();
});
}
+1 -1
View File
@@ -32,7 +32,7 @@ void main() {
expect(find.text('Continue Watching'), findsNothing);
expect(find.byKey(const Key('discover-search')), findsOneWidget);
expect(find.byKey(const Key('theater-category-chips')), findsOneWidget);
expect(find.byKey(const Key('theater-language-chips')), findsOneWidget);
expect(find.byKey(const Key('theater-language-chips')), findsNothing);
expect(find.byKey(const Key('home-all-dramas-grid')), findsOneWidget);
expect(tester.takeException(), isNull);
});
+6 -11
View File
@@ -86,20 +86,15 @@ void main() {
expect(field.focusNode?.hasFocus, isTrue);
});
testWidgets('should_select_theater_language_without_filtering_catalog', (
tester,
) async {
testWidgets('should_not_render_theater_language_filters', (tester) async {
await _pumpApp(tester);
await tester.tap(find.byKey(const Key('tab-theater')));
await tester.pumpAndSettle();
expect(_chip(tester, 'theater-language-all').selected, isTrue);
expect(_chip(tester, 'theater-language-id').selected, isFalse);
await tester.tap(find.byKey(const Key('theater-language-id')));
await tester.pumpAndSettle();
expect(_chip(tester, 'theater-language-all').selected, isFalse);
expect(_chip(tester, 'theater-language-id').selected, isTrue);
expect(find.byKey(const Key('theater-language-chips')), findsNothing);
expect(find.byKey(const Key('theater-category-chips')), findsOneWidget);
expect(find.byKey(const Key('discover-search')), findsOneWidget);
expect(find.byKey(const Key('discover-refresh')), findsOneWidget);
expect(
find.byKey(const Key('home-drama-card-the-signal-demo')),
findsOneWidget,
@@ -202,7 +197,7 @@ void main() {
await tester.tap(find.byKey(const Key('tab-theater')));
await tester.pumpAndSettle();
expect(find.byKey(const Key('theater-category-chips')), findsOneWidget);
expect(find.byKey(const Key('theater-language-chips')), findsOneWidget);
expect(find.byKey(const Key('theater-language-chips')), findsNothing);
expect(tester.takeException(), isNull);
});
}
+2 -1
View File
@@ -60,11 +60,12 @@ void main() {
Key('mine-creator-center'),
Key('mine-notices'),
Key('mine-settings'),
Key('mine-language'),
Key('mine-help'),
]) {
expect(find.byKey(key), findsOneWidget);
}
expect(find.byKey(const Key('mine-language')), findsNothing);
expect(find.byKey(const Key('mine-language')), findsOneWidget);
expect(find.byKey(const Key('mine-library-tab-0')), findsNothing);
expect(find.byKey(const Key('mine-library-tab-1')), findsNothing);
expect(find.byKey(const Key('mine-library-tab-2')), findsNothing);
+75 -52
View File
@@ -40,14 +40,9 @@ void main() {
expect(find.byType(PageView), findsOneWidget);
await tester.tap(find.byKey(const Key('player-more')));
await tester.pumpAndSettle();
expect(find.byKey(const Key('player-more-quality')), findsOneWidget);
expect(find.byKey(const Key('player-more-download')), findsOneWidget);
expect(find.byKey(const Key('player-more-pip')), findsOneWidget);
await tester.tap(find.byKey(const Key('player-more-quality')));
await tester.pumpAndSettle();
expect(find.byKey(const Key('player-quality-sheet')), findsOneWidget);
expect(find.text('720P'), findsOneWidget);
await tester.binding.handlePopRoute();
expect(find.byKey(const Key('player-more-quality-AUTO')), findsOneWidget);
expect(find.byKey(const Key('player-more-offline')), findsOneWidget);
await tester.tap(find.byKey(const Key('player-more-close')));
await tester.pumpAndSettle();
expect(tester.takeException(), isNull);
});
@@ -111,7 +106,7 @@ void main() {
expect(find.byKey(const Key('player-controls-bottom')), findsOneWidget);
expect(find.byType(PlayerCenterToggle), findsOneWidget);
await tester.tap(find.byKey(const Key('player-clear-screen')));
await tester.tap(find.byKey(const Key('player-fullscreen-toggle')));
await tester.pump();
expect(find.byKey(const Key('player-controls-top')), findsNothing);
@@ -184,7 +179,7 @@ void main() {
await _pumpApp(tester);
await _openSeriesPlayer(tester);
await tester.tap(find.byKey(const Key('player-clear-screen')));
await tester.tap(find.byKey(const Key('player-fullscreen-toggle')));
await tester.pump();
expect(find.byKey(const Key('player-controls-top')), findsNothing);
@@ -208,14 +203,11 @@ void main() {
await _pumpApp(tester);
await _openSeriesPlayer(tester);
await tester.tap(find.byKey(const Key('player-more')));
await tester.pumpAndSettle();
expect(find.byKey(const Key('player-more-speed')), findsOneWidget);
await tester.tap(find.byKey(const Key('player-more-speed')));
await tester.tap(find.byKey(const Key('player-speed-entry')));
await tester.pumpAndSettle();
expect(find.byKey(const Key('player-speed-sheet')), findsOneWidget);
for (final value in ['0.5', '0.75', '1.0', '1.25', '1.5', '2.0']) {
for (final value in ['0.75', '1.0', '1.25', '1.5', '2.0', '3.0']) {
expect(find.byKey(Key('player-speed-$value')), findsOneWidget);
}
@@ -223,11 +215,11 @@ void main() {
await tester.pumpAndSettle();
expect(find.byKey(const Key('player-speed-sheet')), findsNothing);
await tester.tap(find.byKey(const Key('player-more')));
await tester.tap(find.byKey(const Key('player-speed-entry')));
await tester.pumpAndSettle();
expect(
find.descendant(
of: find.byKey(const Key('player-more-speed')),
of: find.byKey(const Key('player-speed-entry')),
matching: find.text('1.5x'),
),
findsOneWidget,
@@ -240,38 +232,22 @@ void main() {
await _pumpApp(tester);
await _openSeriesPlayer(tester);
await tester.tap(find.byKey(const Key('player-more')));
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key('player-more-speed')));
await tester.tap(find.byKey(const Key('player-speed-entry')));
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key('player-speed-1.5')));
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key('player-clear-screen')));
await tester.tap(find.byKey(const Key('player-fullscreen-toggle')));
await tester.pump();
expect(find.byKey(const Key('player-more')), findsNothing);
await tester.tap(find.byKey(const Key('player-exit-clear-screen')));
await tester.pump();
await tester.tap(find.byKey(const Key('player-more')));
await tester.pumpAndSettle();
expect(
find.descendant(
of: find.byKey(const Key('player-more-speed')),
matching: find.text('1.5x'),
),
findsOneWidget,
);
await tester.binding.handlePopRoute();
await tester.pumpAndSettle();
await tester.drag(find.byType(PageView), const Offset(0, -550));
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key('player-more')));
await tester.pumpAndSettle();
expect(
find.descendant(
of: find.byKey(const Key('player-more-speed')),
of: find.byKey(const Key('player-speed-entry')),
matching: find.text('1.5x'),
),
findsOneWidget,
@@ -341,25 +317,70 @@ void main() {
expect(find.byKey(const Key('player-more-sheet')), findsOneWidget);
expect(find.byKey(const Key('player-more-speed')), findsOneWidget);
expect(find.byKey(const Key('player-more-quality')), findsOneWidget);
expect(find.byKey(const Key('player-more-download')), findsOneWidget);
expect(find.byKey(const Key('player-more-quality-AUTO')), findsOneWidget);
expect(find.byKey(const Key('player-more-offline')), findsOneWidget);
expect(find.byKey(const Key('player-more-clear')), findsOneWidget);
expect(find.byKey(const Key('player-more-danmaku')), findsOneWidget);
expect(
find.byKey(const Key('player-more-danmaku-settings')),
findsOneWidget,
);
expect(find.byKey(const Key('player-more-cast')), findsOneWidget);
expect(find.byKey(const Key('player-more-timer')), findsOneWidget);
expect(find.byKey(const Key('player-more-text-size')), findsOneWidget);
expect(find.byKey(const Key('player-more-report')), findsOneWidget);
await tester.tap(find.byKey(const Key('player-more-text-size')));
await tester.tap(find.byTooltip('Text size'));
await tester.pumpAndSettle();
expect(find.byKey(const Key('player-text-size-sheet')), findsOneWidget);
expect(find.byKey(const Key('player-text-size-large')), findsOneWidget);
await tester.tap(find.byKey(const Key('player-text-size-large')));
await tester.pumpAndSettle();
expect(find.text('Large'), findsOneWidget);
});
testWidgets('should_disable_quality_not_supplied_by_ticket', (tester) async {
await _pumpApp(
tester,
playback: FakePlaybackRepository(
ticket: const PlayTicket(
episodeId: 'city-lights-demo-1',
accessible: true,
accessType: PlayTicket.free,
playUrl: '/files/city-lights-demo-1.mp4',
qualities: ['AUTO'],
),
),
);
await _openSeriesPlayer(tester);
await tester.tap(find.byKey(const Key('player-more')));
await tester.pumpAndSettle();
expect(
find.descendant(
of: find.byKey(const Key('player-more-text-size')),
matching: find.text('Large'),
),
findsOneWidget,
tester
.widget<ChoiceChip>(find.byKey(const Key('player-more-quality-AUTO')))
.onSelected,
isNotNull,
);
expect(
tester
.widget<ChoiceChip>(find.byKey(const Key('player-more-quality-720P')))
.onSelected,
isNull,
);
expect(find.text('720P · Unavailable'), findsOneWidget);
});
testWidgets('should_enter_clear_screen_from_more_panel', (tester) async {
await _pumpApp(tester);
await _openSeriesPlayer(tester);
await tester.tap(find.byKey(const Key('player-more')));
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key('player-more-clear')));
await tester.pumpAndSettle();
expect(find.byKey(const Key('player-controls-top')), findsNothing);
expect(find.byKey(const Key('player-controls-bottom')), findsNothing);
expect(find.byKey(const Key('player-exit-clear-screen')), findsOneWidget);
});
testWidgets('should_open_unlock_panel_with_honest_method_states', (
@@ -395,14 +416,10 @@ void main() {
void _expectFullscreenOverlay(WidgetTester tester) {
expect(find.byKey(const Key('player-back')), findsOneWidget);
expect(find.byKey(const Key('player-title')), findsOneWidget);
expect(find.byKey(const Key('player-title-dot')), findsOneWidget);
expect(find.byKey(const Key('player-subtitle')), findsOneWidget);
expect(find.byKey(const Key('player-genre-chip')), findsOneWidget);
expect(find.byKey(const Key('player-page-dots')), findsOneWidget);
expect(find.byKey(const Key('player-episode-heading')), findsOneWidget);
expect(find.byKey(const Key('player-speed-entry')), findsOneWidget);
expect(find.byKey(const Key('player-drama-title')), findsOneWidget);
expect(find.byKey(const Key('player-episode-label')), findsOneWidget);
expect(find.byKey(const Key('player-follow')), findsOneWidget);
expect(find.byKey(const Key('player-synopsis')), findsOneWidget);
expect(find.byKey(const Key('player-time-label')), findsOneWidget);
expect(find.byKey(const Key('player-more')), findsOneWidget);
@@ -412,8 +429,14 @@ void _expectFullscreenOverlay(WidgetTester tester) {
expect(find.byKey(const Key('player-play-toggle')), findsNothing);
expect(find.byKey(const Key('player-episodes')), findsOneWidget);
expect(find.byKey(const Key('player-rail-comments')), findsOneWidget);
expect(find.byKey(const Key('player-next')), findsOneWidget);
expect(find.byKey(const Key('player-fullscreen-toggle')), findsOneWidget);
expect(find.byType(Slider), findsOneWidget);
expect(find.byKey(const Key('player-title')), findsNothing);
expect(find.byKey(const Key('player-subtitle')), findsNothing);
expect(find.byKey(const Key('player-genre-chip')), findsNothing);
expect(find.byKey(const Key('player-page-dots')), findsNothing);
expect(find.byKey(const Key('player-clear-screen')), findsNothing);
expect(find.byKey(const Key('player-next')), findsNothing);
expect(find.byKey(const Key('player-interaction-rail')), findsOneWidget);
expect(find.byKey(const Key('player-rail-like')), findsOneWidget);
-32
View File
@@ -1,32 +0,0 @@
// Author: fruit.com.cn
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:fruitshorts/l10n/app_localizations.dart';
import 'package:fruitshorts/pages/player/widgets/quality_sheet.dart';
void main() {
testWidgets('should_list_every_returned_quality_when_sheet_opens', (
tester,
) async {
await tester.pumpWidget(
MaterialApp(
locale: const Locale('en'),
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: const Scaffold(
body: QualitySheet(qualities: ['AUTO', '720P', '1080P']),
),
),
);
expect(find.text('Auto'), findsOneWidget);
expect(find.text('720P'), findsOneWidget);
expect(find.text('1080P'), findsOneWidget);
expect(find.byIcon(Icons.check_rounded), findsOneWidget);
expect(
find.text('HLS adjusts the bitrate automatically for your connection.'),
findsOneWidget,
);
});
}
+1 -3
View File
@@ -42,9 +42,7 @@ void main() {
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key('tab-mine')));
await tester.pumpAndSettle();
await tester.drag(find.byType(ListView), const Offset(0, -520));
await tester.pumpAndSettle();
await tester.tap(find.text('Watch History'));
await tester.tap(find.byKey(const Key('mine-history')));
await tester.pumpAndSettle();
expect(tester.takeException(), isNull);
+29 -7
View File
@@ -72,7 +72,7 @@ void main() {
await tester.pumpAndSettle();
expect(
tester.widget<Text>(find.byKey(const Key('player-title'))).data,
tester.widget<Text>(find.byKey(const Key('player-episode-heading'))).data,
contains('Episode 2'),
);
expect(created, hasLength(3));
@@ -135,9 +135,7 @@ void main() {
);
});
testWidgets('should_follow_system_locale_without_language_switch', (
tester,
) async {
testWidgets('should_show_language_entry_on_mine_page', (tester) async {
await tester.pumpWidget(appUnderTest());
await tester.pumpAndSettle();
expect(find.byTooltip('Captions'), findsNothing);
@@ -146,7 +144,7 @@ void main() {
await tester.pumpAndSettle();
expect(find.text('Vicky sheng'), findsOneWidget);
expect(find.text('Coins'), findsOneWidget);
expect(find.text('App Language'), findsNothing);
expect(find.byKey(const Key('mine-language')), findsOneWidget);
expect(find.byKey(const Key('mine-wallet')), findsOneWidget);
await tester.tap(find.byKey(const Key('tab-theater')));
@@ -154,6 +152,30 @@ void main() {
expect(find.text('Theater'), findsWidgets);
});
testWidgets('should_switch_app_language_from_mine_menu', (tester) async {
await tester.pumpWidget(appUnderTest());
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key('tab-mine')));
await tester.pumpAndSettle();
await tester.drag(
find.byKey(const Key('mine-page-scroll')),
const Offset(0, -320),
);
await tester.pumpAndSettle();
await tester.tap(find.byKey(const Key('mine-language')));
await tester.pumpAndSettle();
expect(find.byKey(const Key('mine-language-sheet')), findsOneWidget);
await tester.tap(find.byKey(const Key('mine-language-zh')));
await tester.pumpAndSettle();
expect(find.text('我的'), findsWidgets);
expect(find.text('语言'), findsOneWidget);
await tester.tap(find.byKey(const Key('tab-theater')));
await tester.pumpAndSettle();
expect(find.text('剧场'), findsWidgets);
});
testWidgets('should_fit_compact_viewport_when_player_is_opened', (
tester,
) async {
@@ -170,7 +192,7 @@ void main() {
await tester.drag(find.byType(PageView), const Offset(0, -500));
await tester.pumpAndSettle();
expect(
tester.widget<Text>(find.byKey(const Key('player-title'))).data,
tester.widget<Text>(find.byKey(const Key('player-episode-heading'))).data,
contains('Episode 2'),
);
expect(tester.takeException(), isNull);
@@ -191,7 +213,7 @@ void main() {
expect(find.byKey(const Key('discover-search')), findsOneWidget);
expect(find.byKey(const Key('theater-category-chips')), findsOneWidget);
expect(find.byKey(const Key('theater-language-chips')), findsOneWidget);
expect(find.byKey(const Key('theater-language-chips')), findsNothing);
expect(find.byKey(const Key('home-all-dramas-grid')), findsOneWidget);
expect(find.byKey(const Key('discover-profile')), findsOneWidget);
expect(tester.takeException(), isNull);