novyronst/lib/pages/collect/pages/history_page.dart

180 lines
4.7 KiB
Dart

import 'package:flutter/material.dart';
import 'package:novyronst/common/api/video_request.dart';
import 'package:novyronst/common/model/ny_drama_model.dart';
import 'package:novyronst/pages/collect/pages/collect_page_helpers.dart';
class HistoryPage extends StatefulWidget {
const HistoryPage({super.key, required this.isEditing, this.fetchHistory});
final bool isEditing;
final Future<List<NyDramaModel>> Function({int page, int pageSize})?
fetchHistory;
@override
State<HistoryPage> createState() => _HistoryPageState();
}
class _HistoryPageState extends State<HistoryPage> {
final List<NyDramaModel> _items = [];
bool _isLoading = false;
@override
void initState() {
super.initState();
_loadHistory();
}
Future<void> _loadHistory() async {
setState(() {
_isLoading = true;
});
final fetch = widget.fetchHistory ?? VideoRequest.getHistory;
final items = await fetch(page: 1, pageSize: 20);
if (!mounted) return;
setState(() {
_items
..clear()
..addAll(items);
_isLoading = false;
});
}
void _deleteHistory(int index) {
if (index < 0 || index >= _items.length) return;
setState(() {
_items.removeAt(index);
});
}
@override
Widget build(BuildContext context) {
if (_isLoading && _items.isEmpty) {
return const Center(
child: CircularProgressIndicator(color: Colors.white),
);
}
if (_items.isEmpty) {
return const Center(
child: Text('No history', style: TextStyle(color: Colors.white70)),
);
}
return ListView.separated(
padding: const EdgeInsets.fromLTRB(30, 8, 20, 96),
itemCount: _items.length,
separatorBuilder: (context, index) => const SizedBox(height: 13),
itemBuilder: (context, index) {
return Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(
width: 30,
child: _HistoryLeadingButton(
isEditing: widget.isEditing,
onDelete: () => _deleteHistory(index),
),
),
const SizedBox(width: 18),
Expanded(child: _HistoryItem(item: _items[index])),
],
);
},
);
}
}
class _HistoryLeadingButton extends StatelessWidget {
const _HistoryLeadingButton({
required this.isEditing,
required this.onDelete,
});
final bool isEditing;
final VoidCallback onDelete;
@override
Widget build(BuildContext context) {
if (isEditing) {
return IconButton(
padding: EdgeInsets.zero,
constraints: const BoxConstraints.tightFor(width: 30, height: 40),
onPressed: onDelete,
icon: const Icon(Icons.delete_outline, color: Colors.redAccent, size: 28),
);
}
return Icon(
Icons.bookmark_border,
color: Colors.white.withValues(alpha: 0.28),
size: 32,
);
}
}
class _HistoryItem extends StatelessWidget {
const _HistoryItem({required this.item});
final NyDramaModel item;
@override
Widget build(BuildContext context) {
return SizedBox(
height: 68,
child: Row(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(2),
child: Image.network(
item.imageUrl,
width: 51,
height: 68,
fit: BoxFit.cover,
errorBuilder: (context, error, stackTrace) {
return Container(
width: 51,
height: 68,
color: Colors.white.withValues(alpha: 0.12),
);
},
),
),
const SizedBox(width: 15),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
item.name,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
color: Colors.white,
fontSize: 14,
height: 1.22,
fontFamily: 'Montserrat-Bold',
fontWeight: FontWeight.w700,
),
),
const SizedBox(height: 8),
Text(
dramaEpisodeText(item),
style: TextStyle(
color: Colors.white.withValues(alpha: 0.45),
fontSize: 12,
fontFamily: 'Montserrat-Medium',
fontWeight: FontWeight.w500,
),
),
],
),
),
],
),
);
}
}