Files
ReelShort/lib/pages/discover/widgets/discover_search_results.dart

82 lines
2.3 KiB
Dart

// Author: fruit.com.cn
import 'package:flutter/material.dart';
import '../../../core/data/models/drama.dart';
import '../../../core/formatting/error_text.dart';
import '../../../core/theme/app_colors.dart';
import '../../../core/widgets/empty_state.dart';
import '../../../l10n/app_localizations.dart';
import 'drama_grid.dart';
/// 剧场搜索结果:加载、失败与空结果都留在同一页内。
///
/// 自身是 sliver,好让结果网格跟着剧场页一起懒加载。
class DiscoverSearchResults extends StatelessWidget {
const DiscoverSearchResults({
super.key,
required this.loading,
required this.error,
required this.results,
required this.onRetry,
required this.onOpen,
});
final bool loading;
final String? error;
final List<Drama> results;
final VoidCallback onRetry;
final ValueChanged<Drama> onOpen;
static const EdgeInsets _topPadding = EdgeInsets.only(top: 12);
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
if (!loading && error == null && results.isNotEmpty) {
return SliverPadding(
padding: _topPadding,
sliver: SliverDramaGrid(l10n: l10n, dramas: results, onOpen: onOpen),
);
}
return SliverPadding(
padding: _topPadding,
sliver: SliverToBoxAdapter(child: _state(l10n)),
);
}
Widget _state(AppLocalizations l10n) {
if (loading) {
return const Padding(
padding: EdgeInsets.symmetric(vertical: 80),
child: Center(
child: SizedBox.square(
dimension: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
color: AppColors.textPrimary,
),
),
),
);
}
final message = error;
if (message != null) {
return EmptyState(
key: const Key('discover-search-error'),
icon: Icons.cloud_off_rounded,
title: errorText(l10n, message, l10n.searchFailed),
actionLabel: l10n.retry,
actionKey: const Key('discover-search-retry'),
onAction: onRetry,
);
}
return EmptyState(
key: const Key('discover-search-empty'),
icon: Icons.search_off_rounded,
title: l10n.noSearchResults,
subtitle: l10n.emptyHint,
);
}
}