60 lines
1.6 KiB
Dart
60 lines
1.6 KiB
Dart
class FeedItem {
|
|
final int? id;
|
|
final String title;
|
|
final String description;
|
|
|
|
// the extracted article body — may be empty for older rows or sources
|
|
// that havent been backfilled yet.
|
|
final String content;
|
|
|
|
final String link;
|
|
final String? source;
|
|
final DateTime? pubDate;
|
|
|
|
FeedItem({
|
|
this.id,
|
|
required this.title,
|
|
required this.description,
|
|
this.content = "",
|
|
required this.link,
|
|
this.source,
|
|
this.pubDate,
|
|
});
|
|
|
|
@override
|
|
String toString() => 'FeedItem(title: $title, link: $link)';
|
|
|
|
FeedItem.fromJson(Map<String, dynamic> json)
|
|
: id = json['id'] is int ? json['id'] as int : int.tryParse('${json['id']}'),
|
|
title = json['title'] ?? '',
|
|
description = json['description'] ?? '',
|
|
content = (json['content'] ?? '').toString(),
|
|
link = json['link'] ?? '',
|
|
source = json['source'],
|
|
pubDate = json['pub_date'] != null ? DateTime.tryParse(json['pub_date']) : null;
|
|
|
|
Map<String, dynamic> toJson() {
|
|
return {
|
|
if (id != null) 'id': id,
|
|
'title': title,
|
|
'description': description,
|
|
if (content.isNotEmpty) 'content': content,
|
|
'link': link,
|
|
if (source != null) 'source': source,
|
|
if (pubDate != null) 'pub_date': pubDate!.toIso8601String(),
|
|
};
|
|
}
|
|
}
|
|
|
|
|
|
// median pub date of a cluster — falls back to now if none have dates
|
|
DateTime medianPubDate(List<FeedItem> articles) {
|
|
final dates = articles
|
|
.where((a) => a.pubDate != null)
|
|
.map((a) => a.pubDate!)
|
|
.toList()
|
|
..sort();
|
|
|
|
if (dates.isEmpty) return DateTime.now();
|
|
return dates[dates.length ~/ 2];
|
|
}
|