Post overview w/ content length limit indicator

This commit is contained in:
2024-07-30 14:49:26 +08:00
parent 6ace977bf6
commit 6590062dcb
10 changed files with 412 additions and 177 deletions

View File

@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:flutter_markdown_selectionarea/flutter_markdown.dart';
import 'package:markdown/markdown.dart' as markdown;
import 'package:url_launcher/url_launcher_string.dart';
@ -13,8 +13,7 @@ class MarkdownTextContent extends StatelessWidget {
this.isSelectable = false,
});
@override
Widget build(BuildContext context) {
Widget _buildContent(BuildContext context) {
return Markdown(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
@ -48,4 +47,12 @@ class MarkdownTextContent extends StatelessWidget {
},
);
}
@override
Widget build(BuildContext context) {
if (isSelectable) {
return SelectionArea(child: _buildContent(context));
}
return _buildContent(context);
}
}

View File

@ -0,0 +1,51 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:solian/controllers/post_editor_controller.dart';
class PostEditorOverviewDialog extends StatelessWidget {
final PostEditorController controller;
const PostEditorOverviewDialog({super.key, required this.controller});
@override
Widget build(BuildContext context) {
return AlertDialog(
title: Text('postOverview'.tr),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
autofocus: true,
autocorrect: true,
controller: controller.titleController,
decoration: InputDecoration(
border: const UnderlineInputBorder(),
hintText: 'title'.tr,
),
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
),
const SizedBox(height: 16),
TextField(
enabled: controller.mode.value == 1,
maxLines: null,
autofocus: true,
autocorrect: true,
keyboardType: TextInputType.multiline,
controller: controller.descriptionController,
decoration: InputDecoration(
border: const UnderlineInputBorder(),
hintText: 'description'.tr,
),
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
),
],
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text('confirm'.tr),
),
],
);
}
}

View File

@ -55,7 +55,7 @@ class _PostItemState extends State<PostItem> {
Widget _buildDate() {
if (widget.isFullDate) {
return Text(DateFormat('y/M/d H:m')
return Text(DateFormat('y/M/d HH:mm')
.format(item.publishedAt?.toLocal() ?? DateTime.now()));
} else {
return Text(
@ -75,20 +75,49 @@ class _PostItemState extends State<PostItem> {
content: item.author.avatar.toString(),
radius: 10,
).paddingOnly(left: 2),
Text(
item.author.nick,
style: const TextStyle(fontWeight: FontWeight.bold),
).paddingOnly(left: widget.isCompact ? 6 : 12),
_buildDate().paddingOnly(left: 4),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text(
item.author.nick,
style: const TextStyle(fontWeight: FontWeight.bold),
),
_buildDate().paddingOnly(left: 4),
],
),
if (item.body['title'] != null)
Text(
item.body['title'],
style: Theme.of(context)
.textTheme
.bodyMedium!
.copyWith(fontSize: 15),
),
if (item.body['description'] != null)
Text(
item.body['description'],
style: Theme.of(context).textTheme.bodySmall,
),
if (item.body['description'] != null ||
item.body['title'] != null)
const Divider(thickness: 0.3, height: 1).paddingSymmetric(
vertical: 8,
),
],
).paddingOnly(left: widget.isCompact ? 6 : 12),
),
],
);
}
Widget _buildFooter() {
List<String> labels = List.empty(growable: true);
if (widget.item.createdAt != widget.item.updatedAt) {
if (widget.item.editedAt != null) {
labels.add('postEdited'.trParams({
'date': DateFormat('yy/M/d H:m').format(item.updatedAt.toLocal()),
'date': DateFormat('yy/M/d HH:mm').format(item.editedAt!.toLocal()),
}));
}
if (widget.item.realm != null) {