Popup comments

This commit is contained in:
LittleSheep 2024-04-16 20:36:47 +08:00
parent 0814c17407
commit bb5a10c4c4
5 changed files with 122 additions and 37 deletions

View File

@ -12,14 +12,14 @@ import 'package:solian/widgets/indent_wrapper.dart';
import 'package:solian/widgets/posts/attachment_editor.dart'; import 'package:solian/widgets/posts/attachment_editor.dart';
class CommentPostArguments { class CommentPostArguments {
final Post related; final Post? related;
final Post? editing; final Post? editing;
CommentPostArguments({required this.related, this.editing}); CommentPostArguments({this.related, this.editing});
} }
class CommentEditorScreen extends StatefulWidget { class CommentEditorScreen extends StatefulWidget {
final Post related; final Post? related;
final Post? editing; final Post? editing;
const CommentEditorScreen({super.key, required this.related, this.editing}); const CommentEditorScreen({super.key, required this.related, this.editing});
@ -50,9 +50,10 @@ class _CommentEditorScreenState extends State<CommentEditorScreen> {
final auth = context.read<AuthProvider>(); final auth = context.read<AuthProvider>();
if (!await auth.isAuthorized()) return; if (!await auth.isAuthorized()) return;
final relatedDataset = '${widget.related.modelType}s'; final alias = widget.related?.alias ?? 'not-found';
final relatedDataset = '${widget.related?.modelType ?? 'comment'}s';
final uri = widget.editing == null final uri = widget.editing == null
? getRequestUri('interactive', '/api/p/$relatedDataset/${widget.related.alias}/comments') ? getRequestUri('interactive', '/api/p/$relatedDataset/$alias/comments')
: getRequestUri('interactive', '/api/p/comments/${widget.editing!.id}'); : getRequestUri('interactive', '/api/p/comments/${widget.editing!.id}');
final req = Request(widget.editing == null ? "POST" : "PUT", uri); final req = Request(widget.editing == null ? "POST" : "PUT", uri);

View File

@ -3,18 +3,29 @@ import 'package:solian/widgets/navigation_drawer.dart';
class LayoutWrapper extends StatelessWidget { class LayoutWrapper extends StatelessWidget {
final Widget? child; final Widget? child;
final Widget? floatingActionButton;
final List<Widget>? appBarActions;
final bool? noSafeArea;
final String title; final String title;
const LayoutWrapper({super.key, this.child, required this.title}); const LayoutWrapper({
super.key,
this.child,
required this.title,
this.floatingActionButton,
this.appBarActions,
this.noSafeArea,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final content = child ?? Container();
return Scaffold( return Scaffold(
appBar: AppBar(title: Text(title), actions: appBarActions),
floatingActionButton: floatingActionButton,
drawer: const SolianNavigationDrawer(), drawer: const SolianNavigationDrawer(),
appBar: AppBar(title: Text(title)), body: (noSafeArea ?? false) ? content : SafeArea(child: content),
body: SafeArea(
child: child ?? Container(),
),
); );
} }
} }

View File

@ -1,15 +1,19 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:solian/widgets/common_wrapper.dart';
import 'package:solian/widgets/navigation_drawer.dart'; import 'package:solian/widgets/navigation_drawer.dart';
class IndentWrapper extends StatelessWidget { class IndentWrapper extends LayoutWrapper {
final Widget? child;
final Widget? floatingActionButton;
final List<Widget>? appBarActions;
final bool? hideDrawer; final bool? hideDrawer;
final bool? noSafeArea;
final String title;
const IndentWrapper({super.key, this.child, required this.title, this.floatingActionButton, this.appBarActions, this.hideDrawer, this.noSafeArea}); const IndentWrapper({
super.key,
super.child,
required super.title,
super.floatingActionButton,
super.appBarActions,
this.hideDrawer,
super.noSafeArea,
}) : super();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View File

@ -1,5 +1,10 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';
import 'package:flutter/widgets.dart';
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
import 'package:solian/models/post.dart'; import 'package:solian/models/post.dart';
import 'package:solian/widgets/posts/comment_list.dart';
import 'package:solian/widgets/posts/content/article.dart'; import 'package:solian/widgets/posts/content/article.dart';
import 'package:solian/widgets/posts/content/attachment.dart'; import 'package:solian/widgets/posts/content/attachment.dart';
import 'package:solian/widgets/posts/content/moment.dart'; import 'package:solian/widgets/posts/content/moment.dart';
@ -38,6 +43,36 @@ class _PostItemState extends State<PostItem> {
); );
} }
void viewComments(BuildContext context) {
final PagingController<int, Post> commentPaging =
PagingController(firstPageKey: 0);
showModalBottomSheet(
context: context,
builder: (context) {
return Column(
children: [
CommentListHeader(
related: widget.item,
paging: commentPaging,
),
Expanded(
child: CustomScrollView(
slivers: [
CommentList(
related: widget.item,
dataset: '${widget.item.modelType}s',
paging: commentPaging,
),
],
),
),
],
);
},
);
}
Widget renderContent() { Widget renderContent() {
switch (widget.item.modelType) { switch (widget.item.modelType) {
case 'article': case 'article':
@ -62,20 +97,36 @@ class _PostItemState extends State<PostItem> {
} }
Widget renderReactions() { Widget renderReactions() {
const density = VisualDensity(horizontal: -4, vertical: -2);
return Container( return Container(
height: 48, height: 48,
padding: const EdgeInsets.only(top: 8, left: 4, right: 4), padding: const EdgeInsets.only(top: 8, left: 4, right: 4),
child: ReactionList( child: Row(
item: widget.item, mainAxisAlignment: MainAxisAlignment.center,
reactionList: reactionList, children: [
onReact: (symbol, changes) { ActionChip(
setState(() { avatar: const Icon(Icons.comment),
if (!reactionList!.containsKey(symbol)) { label: Text(widget.item.commentCount.toString()),
reactionList![symbol] = 0; tooltip: 'Comment',
} onPressed: () => viewComments(context),
reactionList![symbol] += changes; ),
}); const VerticalDivider(thickness: 0.3, indent: 8, endIndent: 8),
}, Expanded(
child: ReactionList(
item: widget.item,
reactionList: reactionList,
onReact: (symbol, changes) {
setState(() {
if (!reactionList!.containsKey(symbol)) {
reactionList![symbol] = 0;
}
reactionList![symbol] += changes;
});
},
),
),
],
), ),
); );
} }

View File

@ -4,6 +4,7 @@ import 'package:solian/models/post.dart';
import 'package:solian/providers/auth.dart'; import 'package:solian/providers/auth.dart';
import 'package:solian/router.dart'; import 'package:solian/router.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:solian/screens/posts/comment_editor.dart';
import 'package:solian/widgets/posts/item_deletion.dart'; import 'package:solian/widgets/posts/item_deletion.dart';
class PostItemAction extends StatelessWidget { class PostItemAction extends StatelessWidget {
@ -18,6 +19,31 @@ class PostItemAction extends StatelessWidget {
this.onDelete, this.onDelete,
}); });
void viewEditor() async {
bool ok = false;
switch (item.modelType) {
case 'article':
ok = await router.pushNamed(
'posts.articles.editor',
extra: item,
) as bool;
case 'moment':
ok = await router.pushNamed(
'posts.moments.editor',
extra: item,
) as bool;
case 'comment':
ok = await router.pushNamed(
'posts.comments.editor',
extra: CommentPostArguments(editing: item),
) as bool;
}
if (ok == true && onUpdate != null) {
onUpdate!();
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final auth = context.read<AuthProvider>(); final auth = context.read<AuthProvider>();
@ -43,15 +69,7 @@ class PostItemAction extends StatelessWidget {
ListTile( ListTile(
leading: const Icon(Icons.edit), leading: const Icon(Icons.edit),
title: Text(AppLocalizations.of(context)!.edit), title: Text(AppLocalizations.of(context)!.edit),
onTap: () { onTap: () => viewEditor(),
router
.pushNamed('posts.moments.editor', extra: item)
.then((did) {
if (did == true && onUpdate != null) {
onUpdate!();
}
});
},
), ),
ListTile( ListTile(
leading: const Icon(Icons.delete), leading: const Icon(Icons.delete),