136 lines
4.9 KiB
Dart
136 lines
4.9 KiB
Dart
import 'dart:convert';
|
|
|
|
import 'package:feet/pages/article.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart';
|
|
import '../api/api.dart';
|
|
|
|
// TODO use some localization library
|
|
String formatDate(DateTime date) {
|
|
return '${date.day}.${date.month}.${date.year}, ${date.hour}:${date.minute < 10 ? '0${date.minute}' : date.minute}';
|
|
}
|
|
|
|
class HomepagePost extends StatefulWidget {
|
|
final Item post;
|
|
const HomepagePost({super.key, required this.post});
|
|
|
|
@override
|
|
State<StatefulWidget> createState() => _HomepagePostState();
|
|
}
|
|
|
|
class _HomepagePostState extends State<HomepagePost> {
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
var post = widget.post;
|
|
var favicon = post.api.cache.favicons.get(post.feedId);
|
|
|
|
return Container(
|
|
margin: const EdgeInsets.symmetric(vertical: 6.0, horizontal: 8.0),
|
|
decoration: BoxDecoration(
|
|
border: Border.all(
|
|
color: Theme.of(context).colorScheme.secondaryContainer,
|
|
),
|
|
borderRadius: const BorderRadius.all(Radius.circular(15)),
|
|
color: post.isRead
|
|
? null
|
|
: Theme.of(context).colorScheme.secondaryContainer.withAlpha(150),
|
|
),
|
|
child: InkWell(
|
|
onTap: () async {
|
|
Navigator.of(context).push(
|
|
MaterialPageRoute(
|
|
builder: (context) => ArticlePage(article: post)),
|
|
);
|
|
if (!post.isRead) {
|
|
await post.api
|
|
.request()
|
|
.markItem(post, ItemMarkType.read)
|
|
.execute();
|
|
setState(() {});
|
|
}
|
|
},
|
|
onLongPress: () async {
|
|
var theme = Theme.of(context);
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(
|
|
content: Text(
|
|
'Marking post as ${post.isRead ? 'Unread' : 'Read'}',
|
|
style: TextStyle(color: theme.colorScheme.onBackground)),
|
|
duration: const Duration(seconds: 2),
|
|
backgroundColor: theme.colorScheme.secondaryContainer,
|
|
),
|
|
);
|
|
await post.api
|
|
.request()
|
|
.markItem(
|
|
post, post.isRead ? ItemMarkType.unread : ItemMarkType.read)
|
|
.execute();
|
|
setState(() {});
|
|
},
|
|
borderRadius: const BorderRadius.all(Radius.circular(15)),
|
|
child: Container(
|
|
margin: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 12.0),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
favicon?.data != null
|
|
? Container(
|
|
margin: const EdgeInsets.fromLTRB(0, 0, 6, 4),
|
|
child: Image.memory(
|
|
base64Decode(favicon!.data.split(',')[1]),
|
|
width: 20,
|
|
height: 20,
|
|
),
|
|
)
|
|
: Container(),
|
|
Expanded(
|
|
child: Text(post.title,
|
|
style: Theme.of(context).textTheme.titleMedium,
|
|
overflow: TextOverflow.ellipsis),
|
|
),
|
|
],
|
|
),
|
|
ClipRRect(
|
|
clipBehavior: Clip.antiAlias,
|
|
child: Row(
|
|
children: [
|
|
GestureDetector(
|
|
onTap: () async {
|
|
HapticFeedback.lightImpact();
|
|
await post.api
|
|
.request()
|
|
.markItem(
|
|
post,
|
|
post.isSaved
|
|
? ItemMarkType.unsaved
|
|
: ItemMarkType.saved)
|
|
.execute();
|
|
setState(() {});
|
|
},
|
|
child: Icon(
|
|
post.isSaved
|
|
? Icons.bookmark
|
|
: Icons.bookmark_add_outlined,
|
|
color:
|
|
post.isSaved ? const Color(0xFFF3A13E) : null),
|
|
),
|
|
Text('${post.api.cache.feeds.get(post.feedId)?.title}'),
|
|
const Text(' \u2022 '),
|
|
post.author.isNotEmpty
|
|
? Text(post.author)
|
|
: const Text('Unknown author',
|
|
style: TextStyle(fontStyle: FontStyle.italic)),
|
|
const Text(' \u2022 '),
|
|
Text(formatDate(post.createdOnTime)),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
)),
|
|
);
|
|
}
|
|
}
|