style(app): 格式化并拆分长函数
This commit is contained in:
1 parent
2b2b7e9913
commit
7850dfc746
31 files changed
+388
-318
No files matched your search
+2
-1
@@ -146,7 +146,8 @@ class _LumaDramaAppState extends State<LumaDramaApp> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
late final CommerceRepository _commerceRepository =
|
late final CommerceRepository _commerceRepository =
|
||||||
widget.commerceRepository ?? HttpCommerceRepository(CommerceApi(_apiClient));
|
widget.commerceRepository ??
|
||||||
|
HttpCommerceRepository(CommerceApi(_apiClient));
|
||||||
|
|
||||||
late final WalletController _walletController = WalletController(
|
late final WalletController _walletController = WalletController(
|
||||||
_commerceRepository,
|
_commerceRepository,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Author: fruit.com.cn
|
// Author: fruit.com.cn
|
||||||
|
|
||||||
import 'json_numbers.dart';
|
import 'json_numbers.dart';
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Author: fruit.com.cn
|
// Author: fruit.com.cn
|
||||||
|
|
||||||
import 'json_numbers.dart';
|
import 'json_numbers.dart';
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Author: fruit.com.cn
|
// Author: fruit.com.cn
|
||||||
|
|
||||||
import 'drama.dart';
|
import 'drama.dart';
|
||||||
import 'json_numbers.dart';
|
import 'json_numbers.dart';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Author: fruit.com.cn
|
// Author: fruit.com.cn
|
||||||
|
|
||||||
import '../models/order.dart';
|
import '../models/order.dart';
|
||||||
import '../models/product.dart';
|
import '../models/product.dart';
|
||||||
|
|||||||
@@ -59,7 +59,8 @@ class _CachedTicket {
|
|||||||
final PlayTicket ticket;
|
final PlayTicket ticket;
|
||||||
final DateTime fetchedAt;
|
final DateTime fetchedAt;
|
||||||
|
|
||||||
bool isExpired(DateTime now, Duration ttl) => now.difference(fetchedAt) >= ttl;
|
bool isExpired(DateTime now, Duration ttl) =>
|
||||||
|
now.difference(fetchedAt) >= ttl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 测试与离线场景用:按集返回固定票据,并记录被请求过几次。
|
/// 测试与离线场景用:按集返回固定票据,并记录被请求过几次。
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Author: fruit.com.cn
|
// Author: fruit.com.cn
|
||||||
|
|
||||||
import '../models/search_result.dart';
|
import '../models/search_result.dart';
|
||||||
import '../remote/catalog_api.dart';
|
import '../remote/catalog_api.dart';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Author: fruit.com.cn
|
// Author: fruit.com.cn
|
||||||
|
|
||||||
import '../models/order.dart';
|
import '../models/order.dart';
|
||||||
import '../models/product.dart';
|
import '../models/product.dart';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Author: fruit.com.cn
|
// Author: fruit.com.cn
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Author: fruit.com.cn
|
// Author: fruit.com.cn
|
||||||
|
|
||||||
import '../../core/data/models/drama.dart';
|
import '../../core/data/models/drama.dart';
|
||||||
import '../../core/data/repositories/search_repository.dart';
|
import '../../core/data/repositories/search_repository.dart';
|
||||||
@@ -10,9 +10,5 @@ class DiscoverBinding {
|
|||||||
required Drama drama,
|
required Drama drama,
|
||||||
required WatchHistoryRepository history,
|
required WatchHistoryRepository history,
|
||||||
SearchRepository? search,
|
SearchRepository? search,
|
||||||
}) => DiscoverLogic(
|
}) => DiscoverLogic(drama: drama, history: history, searchRepository: search);
|
||||||
drama: drama,
|
|
||||||
history: history,
|
|
||||||
searchRepository: search,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
@@ -134,7 +134,8 @@ class DiscoverLogic extends ChangeNotifier {
|
|||||||
|
|
||||||
void _scheduleSearch(String query) {
|
void _scheduleSearch(String query) {
|
||||||
final alreadyRequested = query == _lastRequestedQuery;
|
final alreadyRequested = query == _lastRequestedQuery;
|
||||||
if (alreadyRequested && (searchLoading || searchResults.isNotEmpty || searchError != null)) {
|
if (alreadyRequested &&
|
||||||
|
(searchLoading || searchResults.isNotEmpty || searchError != null)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_lastRequestedQuery = query;
|
_lastRequestedQuery = query;
|
||||||
|
|||||||
@@ -181,7 +181,8 @@ class _DiscoverPageState extends State<DiscoverPage> {
|
|||||||
padding: const EdgeInsets.fromLTRB(0, 0, 0, 12),
|
padding: const EdgeInsets.fromLTRB(0, 0, 0, 12),
|
||||||
child: _languages(l10n, allDramas),
|
child: _languages(l10n, allDramas),
|
||||||
),
|
),
|
||||||
), if (logic.resumeRecord != null && logic.resumeDrama(allDramas) != null)
|
),
|
||||||
|
if (logic.resumeRecord != null && logic.resumeDrama(allDramas) != null)
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(16, 0, 16, 14),
|
padding: const EdgeInsets.fromLTRB(16, 0, 16, 14),
|
||||||
@@ -495,6 +496,7 @@ class _DiscoverPageState extends State<DiscoverPage> {
|
|||||||
if (code == 'en') return l10n.languageEnglish;
|
if (code == 'en') return l10n.languageEnglish;
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _continueCard(
|
Widget _continueCard(
|
||||||
AppLocalizations l10n,
|
AppLocalizations l10n,
|
||||||
Drama drama,
|
Drama drama,
|
||||||
|
|||||||
@@ -25,24 +25,40 @@ class _HomeDramaGrid extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final loading = _loadingState();
|
||||||
|
if (loading != null) return loading;
|
||||||
|
final search = _searchState();
|
||||||
|
if (search != null) return search;
|
||||||
|
if (dramas.isEmpty) return _emptyState();
|
||||||
|
return SliverMainAxisGroup(
|
||||||
|
slivers: [
|
||||||
|
SliverToBoxAdapter(child: _masonry(dramas)),
|
||||||
|
const SliverToBoxAdapter(child: SizedBox(height: 24)),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget? _loadingState() {
|
||||||
if (categories.loading && categories.feed.sections.isEmpty) {
|
if (categories.loading && categories.feed.sections.isEmpty) {
|
||||||
return const SliverFillRemaining(
|
return const SliverFillRemaining(
|
||||||
hasScrollBody: false,
|
hasScrollBody: false,
|
||||||
child: Center(child: CircularProgressIndicator(strokeWidth: 2)),
|
child: Center(child: CircularProgressIndicator(strokeWidth: 2)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (categories.error != null) {
|
if (categories.error == null) return null;
|
||||||
return _fill(
|
return _fill(
|
||||||
EmptyState(
|
EmptyState(
|
||||||
key: const Key('home-categories-error'),
|
key: const Key('home-categories-error'),
|
||||||
icon: Icons.cloud_off_rounded,
|
icon: Icons.cloud_off_rounded,
|
||||||
title: l10n.categoriesError,
|
title: l10n.categoriesError,
|
||||||
subtitle: l10n.emptyHint,
|
subtitle: l10n.emptyHint,
|
||||||
actionLabel: l10n.retry,
|
actionLabel: l10n.retry,
|
||||||
onAction: categories.load,
|
onAction: categories.load,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget? _searchState() {
|
||||||
if (searching && searchLoading) {
|
if (searching && searchLoading) {
|
||||||
return const SliverFillRemaining(
|
return const SliverFillRemaining(
|
||||||
hasScrollBody: false,
|
hasScrollBody: false,
|
||||||
@@ -54,39 +70,33 @@ class _HomeDramaGrid extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (searching && searchError != null) {
|
if (!searching || searchError == null) return null;
|
||||||
return _fill(
|
return _fill(
|
||||||
EmptyState(
|
EmptyState(
|
||||||
key: const Key('discover-search-error'),
|
key: const Key('discover-search-error'),
|
||||||
icon: Icons.cloud_off_rounded,
|
icon: Icons.cloud_off_rounded,
|
||||||
title: errorText(l10n, searchError, l10n.searchFailed),
|
title: errorText(l10n, searchError, l10n.searchFailed),
|
||||||
actionLabel: l10n.retry,
|
actionLabel: l10n.retry,
|
||||||
actionKey: const Key('discover-search-retry'),
|
actionKey: const Key('discover-search-retry'),
|
||||||
onAction: onRetrySearch,
|
onAction: onRetrySearch,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (dramas.isEmpty) {
|
|
||||||
return _fill(
|
Widget _emptyState() {
|
||||||
EmptyState(
|
return _fill(
|
||||||
key: const Key('home-all-dramas-empty'),
|
EmptyState(
|
||||||
icon: searching
|
key: const Key('home-all-dramas-empty'),
|
||||||
? Icons.search_off_rounded
|
icon: searching
|
||||||
: Icons.movie_filter_outlined,
|
? Icons.search_off_rounded
|
||||||
title: searching
|
: Icons.movie_filter_outlined,
|
||||||
? l10n.noSearchResults
|
title: searching
|
||||||
: categories.selectedSectionMissing
|
? l10n.noSearchResults
|
||||||
? l10n.noCategoryDramas
|
: categories.selectedSectionMissing
|
||||||
: l10n.noSearchResults,
|
? l10n.noCategoryDramas
|
||||||
subtitle: l10n.emptyHint,
|
: l10n.noSearchResults,
|
||||||
),
|
subtitle: l10n.emptyHint,
|
||||||
);
|
),
|
||||||
}
|
|
||||||
return SliverMainAxisGroup(
|
|
||||||
slivers: [
|
|
||||||
SliverToBoxAdapter(child: _masonry(dramas)),
|
|
||||||
const SliverToBoxAdapter(child: SizedBox(height: 24)),
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -283,10 +283,7 @@ class PlayerLogic extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
final ready = await ensureTicket(index, forceRefresh: true);
|
final ready = await ensureTicket(index, forceRefresh: true);
|
||||||
if (ready) {
|
if (ready) {
|
||||||
await session.select(
|
await session.select(index, preloadIndex: nextVisibleIndex(index));
|
||||||
index,
|
|
||||||
preloadIndex: nextVisibleIndex(index),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return ready;
|
return ready;
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -991,7 +991,8 @@ class _PlaybackOverlayState extends State<_PlaybackOverlay> {
|
|||||||
Navigator.pop(sheetContext);
|
Navigator.pop(sheetContext);
|
||||||
widget.onQualityTap();
|
widget.onQualityTap();
|
||||||
},
|
},
|
||||||
), ListTile(
|
),
|
||||||
|
ListTile(
|
||||||
key: const Key('player-more-download'),
|
key: const Key('player-more-download'),
|
||||||
leading: const Icon(
|
leading: const Icon(
|
||||||
Icons.download_outlined,
|
Icons.download_outlined,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Author: fruit.com.cn
|
// Author: fruit.com.cn
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
@@ -26,54 +26,60 @@ class QualitySheet extends StatelessWidget {
|
|||||||
key: const Key('player-quality-sheet'),
|
key: const Key('player-quality-sheet'),
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
_header(l10n),
|
||||||
padding: const EdgeInsets.fromLTRB(20, 2, 20, 8),
|
for (final quality in qualities) _qualityTile(l10n, quality),
|
||||||
child: Align(
|
_hint(l10n),
|
||||||
alignment: Alignment.centerLeft,
|
|
||||||
child: Text(
|
|
||||||
l10n.playbackQuality,
|
|
||||||
style: const TextStyle(
|
|
||||||
color: AppColors.onSurface,
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.w700,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
for (final quality in qualities)
|
|
||||||
ListTile(
|
|
||||||
key: Key('player-quality-$quality'),
|
|
||||||
dense: true,
|
|
||||||
title: Text(
|
|
||||||
_label(l10n, quality),
|
|
||||||
style: TextStyle(
|
|
||||||
color: quality == selected ? AppColors.blue : AppColors.cream,
|
|
||||||
fontSize: 13,
|
|
||||||
fontWeight: quality == selected
|
|
||||||
? FontWeight.w700
|
|
||||||
: FontWeight.w500,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
trailing: quality == selected
|
|
||||||
? const Icon(
|
|
||||||
Icons.check_rounded,
|
|
||||||
color: AppColors.blue,
|
|
||||||
size: 18,
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.fromLTRB(20, 6, 20, 14),
|
|
||||||
child: Text(
|
|
||||||
l10n.qualityAutoHint,
|
|
||||||
style: const TextStyle(color: AppColors.muted, fontSize: 11),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _header(AppLocalizations l10n) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(20, 2, 20, 8),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Text(
|
||||||
|
l10n.playbackQuality,
|
||||||
|
style: const TextStyle(
|
||||||
|
color: AppColors.onSurface,
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _qualityTile(AppLocalizations l10n, String quality) {
|
||||||
|
final active = quality == selected;
|
||||||
|
return ListTile(
|
||||||
|
key: Key('player-quality-$quality'),
|
||||||
|
dense: true,
|
||||||
|
title: Text(
|
||||||
|
_label(l10n, quality),
|
||||||
|
style: TextStyle(
|
||||||
|
color: active ? AppColors.blue : AppColors.cream,
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: active ? FontWeight.w700 : FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
trailing: active
|
||||||
|
? const Icon(Icons.check_rounded, color: AppColors.blue, size: 18)
|
||||||
|
: null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _hint(AppLocalizations l10n) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(20, 6, 20, 14),
|
||||||
|
child: Text(
|
||||||
|
l10n.qualityAutoHint,
|
||||||
|
style: const TextStyle(color: AppColors.muted, fontSize: 11),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
String _label(AppLocalizations l10n, String quality) =>
|
String _label(AppLocalizations l10n, String quality) =>
|
||||||
quality == autoQuality ? l10n.qualityAuto : quality;
|
quality == autoQuality ? l10n.qualityAuto : quality;
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// Author: fruit.com.cn
|
// Author: fruit.com.cn
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Author: fruit.com.cn
|
// Author: fruit.com.cn
|
||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
@@ -122,7 +122,9 @@ class _StorePageState extends State<StorePage> {
|
|||||||
controller.purchaseError,
|
controller.purchaseError,
|
||||||
l10n.orderCreateFailed,
|
l10n.orderCreateFailed,
|
||||||
);
|
);
|
||||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(message)));
|
ScaffoldMessenger.of(
|
||||||
|
context,
|
||||||
|
).showSnackBar(SnackBar(content: Text(message)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
widget.onPurchased?.call();
|
widget.onPurchased?.call();
|
||||||
@@ -162,80 +164,85 @@ class _ProductTile extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
_ProductBadge(vip: product.isVip),
|
_ProductBadge(vip: product.isVip),
|
||||||
const SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
Expanded(
|
Expanded(child: _info(l10n)),
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
product.name,
|
|
||||||
key: Key('store-product-name-${product.id}'),
|
|
||||||
maxLines: 1,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
style: const TextStyle(
|
|
||||||
color: AppColors.onSurface,
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.w800,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 4),
|
|
||||||
Text(
|
|
||||||
_detail(l10n),
|
|
||||||
style: const TextStyle(
|
|
||||||
color: AppColors.muted,
|
|
||||||
fontSize: 11,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Column(
|
_price(l10n),
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
product.displayPrice,
|
|
||||||
key: Key('store-product-price-${product.id}'),
|
|
||||||
style: const TextStyle(
|
|
||||||
color: AppColors.gold,
|
|
||||||
fontSize: 13,
|
|
||||||
fontWeight: FontWeight.w800,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
SizedBox(
|
|
||||||
width: 88,
|
|
||||||
height: 32,
|
|
||||||
child: FilledButton(
|
|
||||||
key: Key('store-buy-${product.id}'),
|
|
||||||
onPressed: purchasing ? null : onBuy,
|
|
||||||
style: FilledButton.styleFrom(
|
|
||||||
backgroundColor: AppColors.blue,
|
|
||||||
foregroundColor: AppColors.onPrimary,
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
textStyle: const TextStyle(
|
|
||||||
fontSize: 11,
|
|
||||||
fontWeight: FontWeight.w700,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: purchasing
|
|
||||||
? const SizedBox(
|
|
||||||
width: 14,
|
|
||||||
height: 14,
|
|
||||||
child: CircularProgressIndicator(
|
|
||||||
strokeWidth: 2,
|
|
||||||
color: AppColors.onPrimary,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: Text(l10n.buy),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _info(AppLocalizations l10n) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
product.name,
|
||||||
|
key: Key('store-product-name-${product.id}'),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: const TextStyle(
|
||||||
|
color: AppColors.onSurface,
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w800,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Text(
|
||||||
|
_detail(l10n),
|
||||||
|
style: const TextStyle(color: AppColors.muted, fontSize: 11),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _price(AppLocalizations l10n) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
product.displayPrice,
|
||||||
|
key: Key('store-product-price-${product.id}'),
|
||||||
|
style: const TextStyle(
|
||||||
|
color: AppColors.gold,
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: FontWeight.w800,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
SizedBox(
|
||||||
|
width: 88,
|
||||||
|
height: 32,
|
||||||
|
child: FilledButton(
|
||||||
|
key: Key('store-buy-${product.id}'),
|
||||||
|
onPressed: purchasing ? null : onBuy,
|
||||||
|
style: FilledButton.styleFrom(
|
||||||
|
backgroundColor: AppColors.blue,
|
||||||
|
foregroundColor: AppColors.onPrimary,
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
textStyle: const TextStyle(
|
||||||
|
fontSize: 11,
|
||||||
|
fontWeight: FontWeight.w700,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: purchasing ? _buyProgress() : Text(l10n.buy),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buyProgress() {
|
||||||
|
return const SizedBox(
|
||||||
|
width: 14,
|
||||||
|
height: 14,
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
strokeWidth: 2,
|
||||||
|
color: AppColors.onPrimary,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
String _detail(AppLocalizations l10n) {
|
String _detail(AppLocalizations l10n) {
|
||||||
if (product.isVip) return l10n.vipDuration(product.vipDays);
|
if (product.isVip) return l10n.vipDuration(product.vipDays);
|
||||||
final base = l10n.walletBalanceShort(product.coinAmount);
|
final base = l10n.walletBalanceShort(product.coinAmount);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Author: fruit.com.cn
|
// Author: fruit.com.cn
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
|||||||
@@ -90,9 +90,8 @@ class _WalletPageState extends State<WalletPage> {
|
|||||||
void _openRecharge(WalletController wallet) {
|
void _openRecharge(WalletController wallet) {
|
||||||
Navigator.of(context).push(
|
Navigator.of(context).push(
|
||||||
MaterialPageRoute<void>(
|
MaterialPageRoute<void>(
|
||||||
builder: (_) => RechargePage(
|
builder: (_) =>
|
||||||
onPurchased: () => unawaited(wallet.load()),
|
RechargePage(onPurchased: () => unawaited(wallet.load())),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -320,7 +319,9 @@ class _LedgerTile extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final positive = entry.changeAmount >= 0;
|
final positive = entry.changeAmount >= 0;
|
||||||
final color = positive ? AppColors.success : AppColors.accent;
|
final color = positive ? AppColors.success : AppColors.accent;
|
||||||
final amount = positive ? '+${entry.changeAmount}' : '${entry.changeAmount}';
|
final amount = positive
|
||||||
|
? '+${entry.changeAmount}'
|
||||||
|
: '${entry.changeAmount}';
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.all(12),
|
padding: const EdgeInsets.all(12),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Author: fruit.com.cn
|
// Author: fruit.com.cn
|
||||||
|
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
@@ -9,43 +9,46 @@ import 'package:fruitshorts/core/data/remote/catalog_api.dart';
|
|||||||
import '../support/fake_http_adapter.dart';
|
import '../support/fake_http_adapter.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
test('should_request_search_with_keyword_and_paging_when_searching', () async {
|
test(
|
||||||
final adapter = FakeHttpAdapter(
|
'should_request_search_with_keyword_and_paging_when_searching',
|
||||||
(options) async => FakeHttpResponse(
|
() async {
|
||||||
jsonEncode({
|
final adapter = FakeHttpAdapter(
|
||||||
'code': 0,
|
(options) async => FakeHttpResponse(
|
||||||
'message': 'ok',
|
jsonEncode({
|
||||||
'data': {
|
'code': 0,
|
||||||
'total': 1,
|
'message': 'ok',
|
||||||
'list': [
|
'data': {
|
||||||
{
|
'total': 1,
|
||||||
'id': '2111012753262120962',
|
'list': [
|
||||||
'title': 'Velvet Nights',
|
{
|
||||||
'synopsis': 'A city romance',
|
'id': '2111012753262120962',
|
||||||
'cover': '/files/velvet.png',
|
'title': 'Velvet Nights',
|
||||||
'genre': 'Romance',
|
'synopsis': 'A city romance',
|
||||||
'totalEpisodes': 12,
|
'cover': '/files/velvet.png',
|
||||||
'isHot': true,
|
'genre': 'Romance',
|
||||||
'language': 'id',
|
'totalEpisodes': 12,
|
||||||
},
|
'isHot': true,
|
||||||
],
|
'language': 'id',
|
||||||
},
|
},
|
||||||
}),
|
],
|
||||||
),
|
},
|
||||||
);
|
}),
|
||||||
final api = CatalogApi(
|
),
|
||||||
ApiClient(baseUrl: 'http://127.0.0.1:8081', adapter: adapter),
|
);
|
||||||
);
|
final api = CatalogApi(
|
||||||
|
ApiClient(baseUrl: 'http://127.0.0.1:8081', adapter: adapter),
|
||||||
|
);
|
||||||
|
|
||||||
final page = await api.search('velvet');
|
final page = await api.search('velvet');
|
||||||
|
|
||||||
final request = adapter.requests.single;
|
final request = adapter.requests.single;
|
||||||
expect(request.uri.path, '/app/search');
|
expect(request.uri.path, '/app/search');
|
||||||
expect(request.queryParameters['keyword'], 'velvet');
|
expect(request.queryParameters['keyword'], 'velvet');
|
||||||
expect(request.queryParameters['pageIndex'], '1');
|
expect(request.queryParameters['pageIndex'], '1');
|
||||||
expect(request.queryParameters['pageSize'], '20');
|
expect(request.queryParameters['pageSize'], '20');
|
||||||
expect(page.total, 1);
|
expect(page.total, 1);
|
||||||
expect(page.list.single.title, 'Velvet Nights');
|
expect(page.list.single.title, 'Velvet Nights');
|
||||||
expect(page.list.single.language, 'id');
|
expect(page.list.single.language, 'id');
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// Author: fruit.com.cn
|
// Author: fruit.com.cn
|
||||||
|
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Author: fruit.com.cn
|
// Author: fruit.com.cn
|
||||||
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:fruitshorts/core/data/models/order.dart';
|
import 'package:fruitshorts/core/data/models/order.dart';
|
||||||
@@ -81,11 +81,7 @@ AppProduct _product(String name, {int coinAmount = 550, int bonusCoin = 0}) =>
|
|||||||
);
|
);
|
||||||
|
|
||||||
class _FakeStoreRepository implements StoreRepository {
|
class _FakeStoreRepository implements StoreRepository {
|
||||||
_FakeStoreRepository({
|
_FakeStoreRepository({this.products = const [], this.order, this.orderError});
|
||||||
this.products = const [],
|
|
||||||
this.order,
|
|
||||||
this.orderError,
|
|
||||||
});
|
|
||||||
|
|
||||||
final List<AppProduct> products;
|
final List<AppProduct> products;
|
||||||
final AppOrder? order;
|
final AppOrder? order;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Author: fruit.com.cn
|
// Author: fruit.com.cn
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|||||||
@@ -8,7 +8,11 @@ import 'package:fruitshorts/pages/discover/discover_logic.dart';
|
|||||||
|
|
||||||
import '../support/fake_watch_history.dart';
|
import '../support/fake_watch_history.dart';
|
||||||
|
|
||||||
Drama _drama(String id, {List<int> numbers = const [1, 2, 3], String language = ''}) => Drama(
|
Drama _drama(
|
||||||
|
String id, {
|
||||||
|
List<int> numbers = const [1, 2, 3],
|
||||||
|
String language = '',
|
||||||
|
}) => Drama(
|
||||||
language: language,
|
language: language,
|
||||||
id: id,
|
id: id,
|
||||||
title: id,
|
title: id,
|
||||||
@@ -29,15 +33,18 @@ Drama _drama(String id, {List<int> numbers = const [1, 2, 3], String language =
|
|||||||
void main() {
|
void main() {
|
||||||
TestWidgetsFlutterBinding.ensureInitialized();
|
TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
test('should_resolve_resume_position_of_episode_one_when_constructed', () async {
|
test(
|
||||||
final history = FakeWatchHistory()..saved = const Duration(seconds: 4);
|
'should_resolve_resume_position_of_episode_one_when_constructed',
|
||||||
final logic = DiscoverLogic(history: history, drama: _drama('signal'));
|
() async {
|
||||||
|
final history = FakeWatchHistory()..saved = const Duration(seconds: 4);
|
||||||
|
final logic = DiscoverLogic(history: history, drama: _drama('signal'));
|
||||||
|
|
||||||
expect(await logic.position, const Duration(seconds: 4));
|
expect(await logic.position, const Duration(seconds: 4));
|
||||||
expect(history.reads, ['signal']);
|
expect(history.reads, ['signal']);
|
||||||
expect(logic.searchOpen, isFalse);
|
expect(logic.searchOpen, isFalse);
|
||||||
logic.dispose();
|
logic.dispose();
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
test('should_reread_resume_position_when_drama_is_swapped', () async {
|
test('should_reread_resume_position_when_drama_is_swapped', () async {
|
||||||
final history = FakeWatchHistory();
|
final history = FakeWatchHistory();
|
||||||
@@ -51,22 +58,28 @@ void main() {
|
|||||||
logic.dispose();
|
logic.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should_resume_from_last_watch_when_list_card_has_no_episodes', () async {
|
test(
|
||||||
final history = FakeWatchHistory()
|
'should_resume_from_last_watch_when_list_card_has_no_episodes',
|
||||||
..saved = const Duration(seconds: 9)
|
() async {
|
||||||
..lastEpisode = 'signal-2';
|
final history = FakeWatchHistory()
|
||||||
final logic = DiscoverLogic(
|
..saved = const Duration(seconds: 9)
|
||||||
history: history,
|
..lastEpisode = 'signal-2';
|
||||||
drama: _drama('signal', numbers: const []),
|
final logic = DiscoverLogic(
|
||||||
);
|
history: history,
|
||||||
|
drama: _drama('signal', numbers: const []),
|
||||||
|
);
|
||||||
|
|
||||||
expect(await logic.position, const Duration(seconds: 9));
|
expect(await logic.position, const Duration(seconds: 9));
|
||||||
expect(history.reads, ['signal']);
|
expect(history.reads, ['signal']);
|
||||||
logic.dispose();
|
logic.dispose();
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
test('should_filter_visible_dramas_when_language_is_selected', () {
|
test('should_filter_visible_dramas_when_language_is_selected', () {
|
||||||
final logic = DiscoverLogic(history: FakeWatchHistory(), drama: _drama('s'));
|
final logic = DiscoverLogic(
|
||||||
|
history: FakeWatchHistory(),
|
||||||
|
drama: _drama('s'),
|
||||||
|
);
|
||||||
final dramas = [
|
final dramas = [
|
||||||
_drama('zh', language: 'zh-CN'),
|
_drama('zh', language: 'zh-CN'),
|
||||||
_drama('id', language: 'id'),
|
_drama('id', language: 'id'),
|
||||||
@@ -84,7 +97,10 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should_list_distinct_languages_when_feed_has_cards', () {
|
test('should_list_distinct_languages_when_feed_has_cards', () {
|
||||||
final logic = DiscoverLogic(history: FakeWatchHistory(), drama: _drama('s'));
|
final logic = DiscoverLogic(
|
||||||
|
history: FakeWatchHistory(),
|
||||||
|
drama: _drama('s'),
|
||||||
|
);
|
||||||
final dramas = [
|
final dramas = [
|
||||||
_drama('zh', language: 'zh-CN'),
|
_drama('zh', language: 'zh-CN'),
|
||||||
_drama('id', language: 'id'),
|
_drama('id', language: 'id'),
|
||||||
@@ -109,7 +125,10 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should_show_search_when_flag_is_on_or_text_is_typed', () {
|
test('should_show_search_when_flag_is_on_or_text_is_typed', () {
|
||||||
final logic = DiscoverLogic(history: FakeWatchHistory(), drama: _drama('s'));
|
final logic = DiscoverLogic(
|
||||||
|
history: FakeWatchHistory(),
|
||||||
|
drama: _drama('s'),
|
||||||
|
);
|
||||||
|
|
||||||
expect(logic.showSearch, isFalse);
|
expect(logic.showSearch, isFalse);
|
||||||
|
|
||||||
@@ -126,7 +145,10 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should_match_by_id_and_tolerate_missing_id_when_looking_up_drama', () {
|
test('should_match_by_id_and_tolerate_missing_id_when_looking_up_drama', () {
|
||||||
final logic = DiscoverLogic(history: FakeWatchHistory(), drama: _drama('s'));
|
final logic = DiscoverLogic(
|
||||||
|
history: FakeWatchHistory(),
|
||||||
|
drama: _drama('s'),
|
||||||
|
);
|
||||||
final catalog = [_drama('signal'), _drama('city')];
|
final catalog = [_drama('signal'), _drama('city')];
|
||||||
|
|
||||||
expect(logic.dramaFor('city', catalog)?.id, 'city');
|
expect(logic.dramaFor('city', catalog)?.id, 'city');
|
||||||
@@ -167,7 +189,12 @@ void main() {
|
|||||||
|
|
||||||
// Staying active with a changed drama re-reads history.
|
// Staying active with a changed drama re-reads history.
|
||||||
history.reads.clear();
|
history.reads.clear();
|
||||||
sync(_drama('vengeance'), active: true, wasActive: true, dramaChanged: true);
|
sync(
|
||||||
|
_drama('vengeance'),
|
||||||
|
active: true,
|
||||||
|
wasActive: true,
|
||||||
|
dramaChanged: true,
|
||||||
|
);
|
||||||
expect(logic.drama.id, 'vengeance');
|
expect(logic.drama.id, 'vengeance');
|
||||||
expect(history.reads, ['vengeance']);
|
expect(history.reads, ['vengeance']);
|
||||||
|
|
||||||
@@ -179,43 +206,50 @@ void main() {
|
|||||||
logic.dispose();
|
logic.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('should_open_and_focus_field_when_search_is_requested_and_page_is_active', (
|
testWidgets(
|
||||||
tester,
|
'should_open_and_focus_field_when_search_is_requested_and_page_is_active',
|
||||||
) async {
|
(tester) async {
|
||||||
final logic = DiscoverLogic(history: FakeWatchHistory(), drama: _drama('s'));
|
final logic = DiscoverLogic(
|
||||||
await tester.pumpWidget(
|
history: FakeWatchHistory(),
|
||||||
MaterialApp(
|
drama: _drama('s'),
|
||||||
home: Scaffold(
|
);
|
||||||
body: TextField(
|
await tester.pumpWidget(
|
||||||
controller: logic.search,
|
MaterialApp(
|
||||||
focusNode: logic.searchFocus,
|
home: Scaffold(
|
||||||
|
body: TextField(
|
||||||
|
controller: logic.search,
|
||||||
|
focusNode: logic.searchFocus,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
|
||||||
|
|
||||||
logic.syncDrama(
|
logic.syncDrama(
|
||||||
active: true,
|
active: true,
|
||||||
wasActive: true,
|
wasActive: true,
|
||||||
nextDrama: logic.drama,
|
nextDrama: logic.drama,
|
||||||
dramaChanged: false,
|
dramaChanged: false,
|
||||||
searchRequest: 1,
|
searchRequest: 1,
|
||||||
previousSearchRequest: 0,
|
previousSearchRequest: 0,
|
||||||
isActive: () => true,
|
isActive: () => true,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(logic.searchOpen, isTrue);
|
expect(logic.searchOpen, isTrue);
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
expect(logic.searchFocus.hasFocus, isTrue);
|
expect(logic.searchFocus.hasFocus, isTrue);
|
||||||
|
|
||||||
await tester.pumpWidget(const SizedBox.shrink());
|
await tester.pumpWidget(const SizedBox.shrink());
|
||||||
logic.dispose();
|
logic.dispose();
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
testWidgets('should_keep_search_field_closed_when_page_is_hidden', (
|
testWidgets('should_keep_search_field_closed_when_page_is_hidden', (
|
||||||
tester,
|
tester,
|
||||||
) async {
|
) async {
|
||||||
final logic = DiscoverLogic(history: FakeWatchHistory(), drama: _drama('s'));
|
final logic = DiscoverLogic(
|
||||||
|
history: FakeWatchHistory(),
|
||||||
|
drama: _drama('s'),
|
||||||
|
);
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
MaterialApp(
|
MaterialApp(
|
||||||
home: Scaffold(
|
home: Scaffold(
|
||||||
@@ -250,7 +284,10 @@ void main() {
|
|||||||
testWidgets('should_return_choice_and_forward_it_when_act_runs_embedded', (
|
testWidgets('should_return_choice_and_forward_it_when_act_runs_embedded', (
|
||||||
tester,
|
tester,
|
||||||
) async {
|
) async {
|
||||||
final logic = DiscoverLogic(history: FakeWatchHistory(), drama: _drama('s'));
|
final logic = DiscoverLogic(
|
||||||
|
history: FakeWatchHistory(),
|
||||||
|
drama: _drama('s'),
|
||||||
|
);
|
||||||
final forwarded = <DiscoverPageAction>[];
|
final forwarded = <DiscoverPageAction>[];
|
||||||
final popped = Completer<DiscoverPageAction?>();
|
final popped = Completer<DiscoverPageAction?>();
|
||||||
late BuildContext pageContext;
|
late BuildContext pageContext;
|
||||||
@@ -297,7 +334,10 @@ void main() {
|
|||||||
testWidgets('should_show_artwork_notice_when_card_has_no_playable_media', (
|
testWidgets('should_show_artwork_notice_when_card_has_no_playable_media', (
|
||||||
tester,
|
tester,
|
||||||
) async {
|
) async {
|
||||||
final logic = DiscoverLogic(history: FakeWatchHistory(), drama: _drama('s'));
|
final logic = DiscoverLogic(
|
||||||
|
history: FakeWatchHistory(),
|
||||||
|
drama: _drama('s'),
|
||||||
|
);
|
||||||
late BuildContext context;
|
late BuildContext context;
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
@@ -322,8 +362,13 @@ void main() {
|
|||||||
logic.dispose();
|
logic.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('should_forward_chosen_drama_when_card_is_embedded', (tester) async {
|
testWidgets('should_forward_chosen_drama_when_card_is_embedded', (
|
||||||
final logic = DiscoverLogic(history: FakeWatchHistory(), drama: _drama('s'));
|
tester,
|
||||||
|
) async {
|
||||||
|
final logic = DiscoverLogic(
|
||||||
|
history: FakeWatchHistory(),
|
||||||
|
drama: _drama('s'),
|
||||||
|
);
|
||||||
late BuildContext context;
|
late BuildContext context;
|
||||||
Drama? selected;
|
Drama? selected;
|
||||||
|
|
||||||
@@ -350,7 +395,10 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should_do_nothing_when_notifying_after_dispose', () {
|
test('should_do_nothing_when_notifying_after_dispose', () {
|
||||||
final logic = DiscoverLogic(history: FakeWatchHistory(), drama: _drama('s'));
|
final logic = DiscoverLogic(
|
||||||
|
history: FakeWatchHistory(),
|
||||||
|
drama: _drama('s'),
|
||||||
|
);
|
||||||
var notifications = 0;
|
var notifications = 0;
|
||||||
logic.addListener(() => notifications++);
|
logic.addListener(() => notifications++);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Author: fruit.com.cn
|
// Author: fruit.com.cn
|
||||||
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:fruitshorts/core/data/models/drama.dart';
|
import 'package:fruitshorts/core/data/models/drama.dart';
|
||||||
@@ -21,23 +21,28 @@ Drama _drama(String id, {String language = 'id'}) => Drama(
|
|||||||
void main() {
|
void main() {
|
||||||
TestWidgetsFlutterBinding.ensureInitialized();
|
TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
test('should_query_backend_and_render_results_when_search_text_changes', () async {
|
test(
|
||||||
final repository = _FakeSearchRepository(results: [_drama('velvet')]);
|
'should_query_backend_and_render_results_when_search_text_changes',
|
||||||
final logic = DiscoverLogic(
|
() async {
|
||||||
history: FakeWatchHistory(),
|
final repository = _FakeSearchRepository(results: [_drama('velvet')]);
|
||||||
drama: _drama('signal'),
|
final logic = DiscoverLogic(
|
||||||
searchRepository: repository,
|
history: FakeWatchHistory(),
|
||||||
)..searchDebounce = Duration.zero;
|
drama: _drama('signal'),
|
||||||
|
searchRepository: repository,
|
||||||
|
)..searchDebounce = Duration.zero;
|
||||||
|
|
||||||
logic.search.text = 'velvet';
|
logic.search.text = 'velvet';
|
||||||
logic.onSearchChanged();
|
logic.onSearchChanged();
|
||||||
await pumpEventQueue();
|
await pumpEventQueue();
|
||||||
|
|
||||||
expect(repository.calls, [(keyword: 'velvet', pageIndex: 1, pageSize: 20)]);
|
expect(repository.calls, [
|
||||||
expect(logic.searchLoading, isFalse);
|
(keyword: 'velvet', pageIndex: 1, pageSize: 20),
|
||||||
expect(logic.visibleDramas(const []).single.id, 'velvet');
|
]);
|
||||||
logic.dispose();
|
expect(logic.searchLoading, isFalse);
|
||||||
});
|
expect(logic.visibleDramas(const []).single.id, 'velvet');
|
||||||
|
logic.dispose();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
test('should_keep_server_results_when_text_only_loses_whitespace', () async {
|
test('should_keep_server_results_when_text_only_loses_whitespace', () async {
|
||||||
final repository = _FakeSearchRepository(results: [_drama('velvet')]);
|
final repository = _FakeSearchRepository(results: [_drama('velvet')]);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Author: fruit.com.cn
|
// Author: fruit.com.cn
|
||||||
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:fruitshorts/core/data/models/play_ticket.dart';
|
import 'package:fruitshorts/core/data/models/play_ticket.dart';
|
||||||
|
|||||||
@@ -28,12 +28,7 @@ void main() {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
logic.sessionEpisodes = [
|
logic.sessionEpisodes = [
|
||||||
Episode(
|
Episode(id: '12', number: 1, title: 'Episode 1', isFree: true),
|
||||||
id: '12',
|
|
||||||
number: 1,
|
|
||||||
title: 'Episode 1',
|
|
||||||
isFree: true,
|
|
||||||
),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
final ready = await logic.ensureTicket(0);
|
final ready = await logic.ensureTicket(0);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Author: fruit.com.cn
|
// Author: fruit.com.cn
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Author: fruit.com.cn
|
// Author: fruit.com.cn
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import 'package:fruitshorts/core/data/models/drama.dart';
|
import 'package:fruitshorts/core/data/models/drama.dart';
|
||||||
import 'package:fruitshorts/core/data/models/home_feed.dart';
|
import 'package:fruitshorts/core/data/models/home_feed.dart';
|
||||||
import 'package:fruitshorts/core/data/models/search_result.dart';
|
import 'package:fruitshorts/core/data/models/search_result.dart';
|
||||||
import 'package:fruitshorts/core/data/repositories/catalog_repository.dart';
|
import 'package:fruitshorts/core/data/repositories/catalog_repository.dart';
|
||||||
|
|||||||
Reference in new issue
Block a user