Post headline, and read est

This commit is contained in:
LittleSheep 2024-11-25 00:51:34 +08:00
parent a59de65130
commit 731ab97209
4 changed files with 125 additions and 29 deletions

View File

@ -55,6 +55,13 @@
"untitled": "Untitled",
"postDetail": "Post detail",
"postNoun": "Post",
"postReadMore": "Read more",
"postReadEstimate": "Est read time {}",
"postTotalLength": {
"zero": "No character",
"one": "{} character",
"other": "{} characters"
},
"fieldUsername": "Username",
"fieldNickname": "Nickname",
"fieldEmail": "Email address",

View File

@ -55,6 +55,13 @@
"untitled": "无题",
"postDetail": "帖子详情",
"postNoun": "帖子",
"postReadMore": "阅读更多",
"postReadEstimate": "预计花费 {} 阅读",
"postTotalLength": {
"zero": "没有内容",
"one": "总计 {} 字",
"other": "总计 {} 字"
},
"fieldUsername": "用户名",
"fieldNickname": "显示名",
"fieldEmail": "电子邮箱地址",

View File

@ -109,35 +109,38 @@ class _AttachmentItemSensitiveBlurState
child: Container(
color: Colors.black.withOpacity(0.5),
alignment: Alignment.center,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(
Symbols.visibility_off,
color: Colors.white,
size: 32,
),
const Gap(8),
Text('sensitiveContent')
.tr()
.fontSize(20)
.textColor(Colors.white)
.bold(),
Text('sensitiveContentDescription')
.tr()
.fontSize(14)
.textColor(Colors.white.withOpacity(0.8)),
const Gap(16),
InkWell(
child: Text('sensitiveContentReveal')
child: Container(
constraints: const BoxConstraints(maxWidth: 280),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(
Symbols.visibility_off,
color: Colors.white,
size: 32,
),
const Gap(8),
Text('sensitiveContent')
.tr()
.textColor(Colors.white),
onTap: () {
setState(() => _doesShow = !_doesShow);
},
),
],
),
.fontSize(20)
.textColor(Colors.white)
.bold(),
Text('sensitiveContentDescription')
.tr()
.fontSize(14)
.textColor(Colors.white.withOpacity(0.8)),
const Gap(16),
InkWell(
child: Text('sensitiveContentReveal')
.tr()
.textColor(Colors.white),
onTap: () {
setState(() => _doesShow = !_doesShow);
},
),
],
),
).center(),
),
),
)

View File

@ -41,15 +41,24 @@ class PostItem extends StatelessWidget {
Container(
constraints: BoxConstraints(maxWidth: maxWidth ?? double.infinity),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_PostContentHeader(data: data)
.padding(horizontal: 12, vertical: 8),
if (data.body['title'] != null ||
data.body['description'] != null)
_PostHeadline(data: data).padding(horizontal: 16, bottom: 8),
_PostContentBody(data: data.body)
.padding(horizontal: 16, bottom: 6),
if (data.repostTo != null)
_PostQuoteContent(child: data.repostTo!).padding(
horizontal: 12,
),
if (data.body['content_truncated'] == true)
_PostTruncatedHint(data: data).padding(
horizontal: 16,
vertical: 4,
),
],
),
),
@ -69,7 +78,7 @@ class PostItem extends StatelessWidget {
showComments: showComments,
showReactions: showReactions,
onChanged: _onChanged,
).padding(left: 12, right: 18),
).padding(left: 8, right: 14),
],
),
),
@ -175,6 +184,30 @@ class _PostBottomAction extends StatelessWidget {
}
}
class _PostHeadline extends StatelessWidget {
final SnPost data;
const _PostHeadline({super.key, required this.data});
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (data.body['title'] != null)
Text(
data.body['title'],
style: Theme.of(context).textTheme.titleMedium,
),
if (data.body['description'] != null)
Text(
data.body['description'],
style: Theme.of(context).textTheme.bodyMedium,
),
],
);
}
}
class _PostContentHeader extends StatelessWidget {
final SnPost data;
final bool isCompact;
@ -351,3 +384,49 @@ class _PostQuoteContent extends StatelessWidget {
);
}
}
class _PostTruncatedHint extends StatelessWidget {
final SnPost data;
const _PostTruncatedHint({super.key, required this.data});
static const int kHumanReadSpeed = 238;
@override
Widget build(BuildContext context) {
return Row(
children: [
if (data.body['content_length'] != null)
Row(
children: [
const Icon(Symbols.timer, size: 20),
const Gap(4),
Text('postReadEstimate').tr(args: [
'${Duration(
seconds: ((data.body['content_length'] as num).toDouble() /
kHumanReadSpeed)
.round(),
).inSeconds}s',
]),
],
).padding(right: 12),
if (data.body['content_length'] != null)
Row(
children: [
const Icon(Symbols.height, size: 20),
const Gap(4),
Text(
'postTotalLength'.plural(data.body['content_length']),
).padding(right: 12)
],
),
Row(
children: [
const Icon(Symbols.unfold_more, size: 20),
const Gap(4),
Text('postReadMore').tr(),
],
)
],
).opacity(0.75);
}
}