Redesign comment views to make it cleaner and easier to follow

This commit is contained in:
John Wesley 2024-01-11 11:29:40 -05:00
parent 134a89e193
commit 89b35d7852
12 changed files with 388 additions and 331 deletions

View File

@ -16,7 +16,7 @@ Future<PostCommentListModel> fetchComments(
final response = await client.get(Uri.https( final response = await client.get(Uri.https(
instanceHost, instanceHost,
'/api/posts/$postId/comments', '/api/posts/$postId/comments',
removeNulls({'p': page?.toString(), 'sortBy': sort?.name}))); removeNulls({'p': page?.toString(), 'sort': sort?.name})));
httpErrorHandler(response, message: 'Failed to load comments'); httpErrorHandler(response, message: 'Failed to load comments');

View File

@ -75,7 +75,7 @@ class _EntriesListViewState extends State<EntriesListView> {
), ),
SliverToBoxAdapter( SliverToBoxAdapter(
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(12),
child: Row( child: Row(
children: [ children: [
DropdownButton<ContentSort>( DropdownButton<ContentSort>(
@ -122,35 +122,33 @@ class _EntriesListViewState extends State<EntriesListView> {
PagedSliverList<int, EntryModel>( PagedSliverList<int, EntryModel>(
pagingController: _pagingController, pagingController: _pagingController,
builderDelegate: PagedChildBuilderDelegate<EntryModel>( builderDelegate: PagedChildBuilderDelegate<EntryModel>(
itemBuilder: (context, item, index) => Padding( itemBuilder: (context, item, index) => Card(
padding: const EdgeInsets.all(8.0), margin: const EdgeInsets.all(12),
child: Card( clipBehavior: Clip.antiAlias,
clipBehavior: Clip.antiAlias, child: InkWell(
child: InkWell( onTap: () {
onTap: () { Navigator.of(context).push(
Navigator.of(context).push( MaterialPageRoute(
MaterialPageRoute( builder: (context) => EntryPage(item, (newValue) {
builder: (context) => EntryPage(item, (newValue) { var newList = _pagingController.itemList;
var newList = _pagingController.itemList; newList![index] = newValue;
newList![index] = newValue; setState(() {
setState(() { _pagingController.itemList = newList;
_pagingController.itemList = newList; });
}); }),
}), ),
), );
); },
child: EntryItem(
item,
(newValue) {
var newList = _pagingController.itemList;
newList![index] = newValue;
setState(() {
_pagingController.itemList = newList;
});
}, },
child: EntryItem( isPreview: true,
item,
(newValue) {
var newList = _pagingController.itemList;
newList![index] = newValue;
setState(() {
_pagingController.itemList = newList;
});
},
isPreview: true,
),
), ),
), ),
), ),

View File

@ -17,119 +17,142 @@ class EntryComment extends StatefulWidget {
} }
class _EntryCommentState extends State<EntryComment> { class _EntryCommentState extends State<EntryComment> {
bool _isCollapsed = false;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Card( return Column(
child: ContentItem( children: [
body: widget.comment.body ?? '_comment deleted_', Card(
createdAt: widget.comment.createdAt, margin: const EdgeInsets.only(top: 8),
user: widget.comment.user.username, child: ContentItem(
userIcon: widget.comment.user.avatar?.storageUrl, body: widget.comment.body ?? '_comment deleted_',
userIdOnClick: widget.comment.user.userId, createdAt: widget.comment.createdAt,
boosts: widget.comment.uv, user: widget.comment.user.username,
isBoosted: widget.comment.userVote == 1, userIcon: widget.comment.user.avatar?.storageUrl,
onBoost: whenLoggedIn(context, () async { userIdOnClick: widget.comment.user.userId,
var newValue = await api_comments.putVote( boosts: widget.comment.uv,
context.read<SettingsController>().httpClient, isBoosted: widget.comment.userVote == 1,
context.read<SettingsController>().instanceHost, onBoost: whenLoggedIn(context, () async {
widget.comment.commentId, var newValue = await api_comments.putVote(
1, context.read<SettingsController>().httpClient,
); context.read<SettingsController>().instanceHost,
widget.onUpdate(newValue.copyWith( widget.comment.commentId,
childCount: widget.comment.childCount, 1,
children: widget.comment.children, );
)); widget.onUpdate(newValue.copyWith(
}), childCount: widget.comment.childCount,
upVotes: widget.comment.favourites, children: widget.comment.children,
isUpVoted: widget.comment.isFavourited == true, ));
onUpVote: whenLoggedIn(context, () async { }),
var newValue = await api_comments.putFavorite( upVotes: widget.comment.favourites,
context.read<SettingsController>().httpClient, isUpVoted: widget.comment.isFavourited == true,
context.read<SettingsController>().instanceHost, onUpVote: whenLoggedIn(context, () async {
widget.comment.commentId, var newValue = await api_comments.putFavorite(
); context.read<SettingsController>().httpClient,
widget.onUpdate(newValue.copyWith( context.read<SettingsController>().instanceHost,
childCount: widget.comment.childCount, widget.comment.commentId,
children: widget.comment.children, );
)); widget.onUpdate(newValue.copyWith(
}), childCount: widget.comment.childCount,
downVotes: widget.comment.dv, children: widget.comment.children,
isDownVoted: widget.comment.userVote == -1, ));
onDownVote: whenLoggedIn(context, () async { }),
var newValue = await api_comments.putVote( downVotes: widget.comment.dv,
context.read<SettingsController>().httpClient, isDownVoted: widget.comment.userVote == -1,
context.read<SettingsController>().instanceHost, onDownVote: whenLoggedIn(context, () async {
widget.comment.commentId, var newValue = await api_comments.putVote(
-1, context.read<SettingsController>().httpClient,
); context.read<SettingsController>().instanceHost,
widget.onUpdate(newValue.copyWith( widget.comment.commentId,
childCount: widget.comment.childCount, -1,
children: widget.comment.children, );
)); widget.onUpdate(newValue.copyWith(
}), childCount: widget.comment.childCount,
showCollapse: true, children: widget.comment.children,
onReply: (body) async { ));
var newSubComment = await api_comments.postComment( }),
context.read<SettingsController>().httpClient, onReply: (body) async {
context.read<SettingsController>().instanceHost, var newSubComment = await api_comments.postComment(
body, context.read<SettingsController>().httpClient,
widget.comment.entryId, context.read<SettingsController>().instanceHost,
parentCommentId: widget.comment.commentId, body,
); widget.comment.entryId,
parentCommentId: widget.comment.commentId,
);
widget.onUpdate(widget.comment.copyWith( widget.onUpdate(widget.comment.copyWith(
childCount: widget.comment.childCount + 1, childCount: widget.comment.childCount + 1,
children: [newSubComment, ...widget.comment.children!], children: [newSubComment, ...widget.comment.children!],
)); ));
}, },
onEdit: widget.comment.visibility != 'soft_deleted' onEdit: widget.comment.visibility != 'soft_deleted'
? whenLoggedIn(context, (body) async { ? whenLoggedIn(context, (body) async {
var newValue = await api_comments.editComment( var newValue = await api_comments.editComment(
context.read<SettingsController>().httpClient, context.read<SettingsController>().httpClient,
context.read<SettingsController>().instanceHost, context.read<SettingsController>().instanceHost,
widget.comment.commentId, widget.comment.commentId,
body, body,
widget.comment.lang, widget.comment.lang,
widget.comment.isAdult); widget.comment.isAdult);
widget.onUpdate(newValue.copyWith( widget.onUpdate(newValue.copyWith(
childCount: widget.comment.childCount, childCount: widget.comment.childCount,
children: widget.comment.children, children: widget.comment.children,
)); ));
}, matchesUsername: widget.comment.user.username) }, matchesUsername: widget.comment.user.username)
: null, : null,
onDelete: widget.comment.visibility != 'soft_deleted' onDelete: widget.comment.visibility != 'soft_deleted'
? whenLoggedIn(context, () async { ? whenLoggedIn(context, () async {
await api_comments.deleteComment( await api_comments.deleteComment(
context.read<SettingsController>().httpClient, context.read<SettingsController>().httpClient,
context.read<SettingsController>().instanceHost, context.read<SettingsController>().instanceHost,
widget.comment.commentId, widget.comment.commentId,
); );
widget.onUpdate(widget.comment.copyWith( widget.onUpdate(widget.comment.copyWith(
body: '_comment deleted_', body: '_comment deleted_',
uv: null, uv: null,
dv: null, dv: null,
favourites: null, favourites: null,
visibility: 'soft_deleted', visibility: 'soft_deleted',
)); ));
}, matchesUsername: widget.comment.user.username) }, matchesUsername: widget.comment.user.username)
: null, : null,
child: widget.comment.childCount > 0 isCollapsed: _isCollapsed,
? Column( onCollapse: widget.comment.childCount > 0
children: widget.comment.children! ? () => setState(() {
.asMap() _isCollapsed = !_isCollapsed;
.entries })
.map((item) => EntryComment(item.value, (newValue) { : null,
var newChildren = [...widget.comment.children!]; ),
newChildren[item.key] = newValue; ),
widget.onUpdate(widget.comment.copyWith( if (widget.comment.childCount > 0 && !_isCollapsed)
childCount: widget.comment.childCount + 1, Container(
children: newChildren, margin: const EdgeInsets.only(left: 1),
)); padding: const EdgeInsets.only(left: 10),
})) decoration: BoxDecoration(
.toList(), border: Border(
) left: BorderSide(
: null, color: Theme.of(context).colorScheme.outlineVariant,
), width: 1,
),
),
),
child: Column(
children: widget.comment.children!
.asMap()
.entries
.map((item) => EntryComment(item.value, (newValue) {
var newChildren = [...widget.comment.children!];
newChildren[item.key] = newValue;
widget.onUpdate(widget.comment.copyWith(
childCount: widget.comment.childCount + 1,
children: newChildren,
));
}))
.toList(),
),
),
],
); );
} }
} }

View File

@ -148,7 +148,7 @@ class _EntryPageState extends State<EntryPage> {
), ),
SliverToBoxAdapter( SliverToBoxAdapter(
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(12),
child: Row( child: Row(
children: [ children: [
DropdownButton<api_comments.CommentsSort>( DropdownButton<api_comments.CommentsSort>(
@ -192,7 +192,10 @@ class _EntryPageState extends State<EntryPage> {
pagingController: _pagingController, pagingController: _pagingController,
builderDelegate: PagedChildBuilderDelegate<EntryCommentModel>( builderDelegate: PagedChildBuilderDelegate<EntryCommentModel>(
itemBuilder: (context, item, index) => Padding( itemBuilder: (context, item, index) => Padding(
padding: const EdgeInsets.all(8), padding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 4,
),
child: EntryComment(item, (newValue) { child: EntryComment(item, (newValue) {
var newList = _pagingController.itemList; var newList = _pagingController.itemList;
newList![index] = newValue; newList![index] = newValue;

View File

@ -63,7 +63,7 @@ class _DomainsScreenState extends State<DomainsScreen> {
slivers: [ slivers: [
SliverToBoxAdapter( SliverToBoxAdapter(
child: Padding( child: Padding(
padding: const EdgeInsets.all(12.0), padding: const EdgeInsets.all(12),
child: Row( child: Row(
children: [ children: [
SizedBox( SizedBox(
@ -106,7 +106,7 @@ class _DomainsScreenState extends State<DomainsScreen> {
); );
}, },
child: Padding( child: Padding(
padding: const EdgeInsets.all(12.0), padding: const EdgeInsets.all(12),
child: Row(children: [ child: Row(children: [
Expanded( Expanded(
child: child:

View File

@ -66,7 +66,7 @@ class _MagazinesScreenState extends State<MagazinesScreen> {
slivers: [ slivers: [
SliverToBoxAdapter( SliverToBoxAdapter(
child: Padding( child: Padding(
padding: const EdgeInsets.all(12.0), padding: const EdgeInsets.all(12),
child: Row( child: Row(
children: [ children: [
DropdownButton<api_magazines.MagazinesSort>( DropdownButton<api_magazines.MagazinesSort>(
@ -135,7 +135,7 @@ class _MagazinesScreenState extends State<MagazinesScreen> {
); );
}, },
child: Padding( child: Padding(
padding: const EdgeInsets.all(12.0), padding: const EdgeInsets.all(12),
child: Row(children: [ child: Row(children: [
if (item.icon?.storageUrl != null) if (item.icon?.storageUrl != null)
Avatar(item.icon!.storageUrl, radius: 16), Avatar(item.icon!.storageUrl, radius: 16),

View File

@ -82,7 +82,7 @@ class _UsersScreenState extends State<UsersScreen> {
); );
}, },
child: Padding( child: Padding(
padding: const EdgeInsets.all(12.0), padding: const EdgeInsets.all(12),
child: Row(children: [ child: Row(children: [
if (item.avatar?.storageUrl != null) if (item.avatar?.storageUrl != null)
Avatar( Avatar(

View File

@ -17,119 +17,142 @@ class PostComment extends StatefulWidget {
} }
class _EntryCommentState extends State<PostComment> { class _EntryCommentState extends State<PostComment> {
bool _isCollapsed = false;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Card( return Column(
child: ContentItem( children: [
body: widget.comment.body ?? '_comment deleted_', Card(
createdAt: widget.comment.createdAt, margin: const EdgeInsets.only(top: 8),
user: widget.comment.user.username, child: ContentItem(
userIcon: widget.comment.user.avatar?.storageUrl, body: widget.comment.body ?? '_comment deleted_',
userIdOnClick: widget.comment.user.userId, createdAt: widget.comment.createdAt,
boosts: widget.comment.uv, user: widget.comment.user.username,
isBoosted: widget.comment.userVote == 1, userIcon: widget.comment.user.avatar?.storageUrl,
onBoost: whenLoggedIn(context, () async { userIdOnClick: widget.comment.user.userId,
var newValue = await api_comments.putVote( boosts: widget.comment.uv,
context.read<SettingsController>().httpClient, isBoosted: widget.comment.userVote == 1,
context.read<SettingsController>().instanceHost, onBoost: whenLoggedIn(context, () async {
widget.comment.commentId, var newValue = await api_comments.putVote(
1, context.read<SettingsController>().httpClient,
); context.read<SettingsController>().instanceHost,
widget.onUpdate(newValue.copyWith( widget.comment.commentId,
childCount: widget.comment.childCount, 1,
children: widget.comment.children, );
)); widget.onUpdate(newValue.copyWith(
}), childCount: widget.comment.childCount,
upVotes: widget.comment.favourites, children: widget.comment.children,
onUpVote: whenLoggedIn(context, () async { ));
var newValue = await api_comments.putFavorite( }),
context.read<SettingsController>().httpClient, upVotes: widget.comment.favourites,
context.read<SettingsController>().instanceHost, onUpVote: whenLoggedIn(context, () async {
widget.comment.commentId, var newValue = await api_comments.putFavorite(
); context.read<SettingsController>().httpClient,
widget.onUpdate(newValue.copyWith( context.read<SettingsController>().instanceHost,
childCount: widget.comment.childCount, widget.comment.commentId,
children: widget.comment.children, );
)); widget.onUpdate(newValue.copyWith(
}), childCount: widget.comment.childCount,
isUpVoted: widget.comment.isFavourited == true, children: widget.comment.children,
downVotes: widget.comment.dv, ));
isDownVoted: widget.comment.userVote == -1, }),
onDownVote: whenLoggedIn(context, () async { isUpVoted: widget.comment.isFavourited == true,
var newValue = await api_comments.putVote( downVotes: widget.comment.dv,
context.read<SettingsController>().httpClient, isDownVoted: widget.comment.userVote == -1,
context.read<SettingsController>().instanceHost, onDownVote: whenLoggedIn(context, () async {
widget.comment.commentId, var newValue = await api_comments.putVote(
-1, context.read<SettingsController>().httpClient,
); context.read<SettingsController>().instanceHost,
widget.onUpdate(newValue.copyWith( widget.comment.commentId,
childCount: widget.comment.childCount, -1,
children: widget.comment.children, );
)); widget.onUpdate(newValue.copyWith(
}), childCount: widget.comment.childCount,
showCollapse: true, children: widget.comment.children,
onReply: (body) async { ));
var newSubComment = await api_comments.postComment( }),
context.read<SettingsController>().httpClient, onReply: (body) async {
context.read<SettingsController>().instanceHost, var newSubComment = await api_comments.postComment(
body, context.read<SettingsController>().httpClient,
widget.comment.postId, context.read<SettingsController>().instanceHost,
parentCommentId: widget.comment.commentId, body,
); widget.comment.postId,
parentCommentId: widget.comment.commentId,
);
widget.onUpdate(widget.comment.copyWith( widget.onUpdate(widget.comment.copyWith(
childCount: widget.comment.childCount + 1, childCount: widget.comment.childCount + 1,
children: [newSubComment, ...widget.comment.children!], children: [newSubComment, ...widget.comment.children!],
)); ));
}, },
onEdit: widget.comment.visibility != 'soft_deleted' onEdit: widget.comment.visibility != 'soft_deleted'
? whenLoggedIn(context, (body) async { ? whenLoggedIn(context, (body) async {
var newValue = await api_comments.editComment( var newValue = await api_comments.editComment(
context.read<SettingsController>().httpClient, context.read<SettingsController>().httpClient,
context.read<SettingsController>().instanceHost, context.read<SettingsController>().instanceHost,
widget.comment.commentId, widget.comment.commentId,
body, body,
widget.comment.lang, widget.comment.lang,
widget.comment.isAdult); widget.comment.isAdult);
widget.onUpdate(newValue.copyWith( widget.onUpdate(newValue.copyWith(
childCount: widget.comment.childCount, childCount: widget.comment.childCount,
children: widget.comment.children, children: widget.comment.children,
)); ));
}) })
: null, : null,
onDelete: widget.comment.visibility != 'soft_deleted' onDelete: widget.comment.visibility != 'soft_deleted'
? whenLoggedIn(context, () async { ? whenLoggedIn(context, () async {
await api_comments.deleteComment( await api_comments.deleteComment(
context.read<SettingsController>().httpClient, context.read<SettingsController>().httpClient,
context.read<SettingsController>().instanceHost, context.read<SettingsController>().instanceHost,
widget.comment.commentId, widget.comment.commentId,
); );
widget.onUpdate(widget.comment.copyWith( widget.onUpdate(widget.comment.copyWith(
body: '_comment deleted_', body: '_comment deleted_',
uv: null, uv: null,
dv: null, dv: null,
favourites: null, favourites: null,
visibility: 'soft_deleted', visibility: 'soft_deleted',
)); ));
}) })
: null, : null,
child: widget.comment.childCount > 0 isCollapsed: _isCollapsed,
? Column( onCollapse: widget.comment.childCount > 0
children: widget.comment.children! ? () => setState(() {
.asMap() _isCollapsed = !_isCollapsed;
.entries })
.map((item) => PostComment(item.value, (newValue) { : null,
var newChildren = [...widget.comment.children!]; ),
newChildren[item.key] = newValue; ),
widget.onUpdate(widget.comment.copyWith( if (widget.comment.childCount > 0 && !_isCollapsed)
childCount: widget.comment.childCount + 1, Container(
children: newChildren, margin: const EdgeInsets.only(left: 1),
)); padding: const EdgeInsets.only(left: 10),
})) decoration: BoxDecoration(
.toList(), border: Border(
) left: BorderSide(
: null, color: Theme.of(context).colorScheme.outlineVariant,
), width: 1,
),
),
),
child: Column(
children: widget.comment.children!
.asMap()
.entries
.map((item) => PostComment(item.value, (newValue) {
var newChildren = [...widget.comment.children!];
newChildren[item.key] = newValue;
widget.onUpdate(widget.comment.copyWith(
childCount: widget.comment.childCount + 1,
children: newChildren,
));
}))
.toList(),
),
),
],
); );
} }
} }

View File

@ -144,7 +144,7 @@ class _PostPageState extends State<PostPage> {
), ),
SliverToBoxAdapter( SliverToBoxAdapter(
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(12),
child: Row( child: Row(
children: [ children: [
DropdownButton<api_comments.CommentsSort>( DropdownButton<api_comments.CommentsSort>(
@ -188,7 +188,10 @@ class _PostPageState extends State<PostPage> {
pagingController: _pagingController, pagingController: _pagingController,
builderDelegate: PagedChildBuilderDelegate<PostCommentModel>( builderDelegate: PagedChildBuilderDelegate<PostCommentModel>(
itemBuilder: (context, item, index) => Padding( itemBuilder: (context, item, index) => Padding(
padding: const EdgeInsets.all(8), padding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 4,
),
child: PostComment(item, (newValue) { child: PostComment(item, (newValue) {
var newList = _pagingController.itemList; var newList = _pagingController.itemList;
newList![index] = newValue; newList![index] = newValue;

View File

@ -75,7 +75,7 @@ class _PostsListViewState extends State<PostsListView> {
), ),
SliverToBoxAdapter( SliverToBoxAdapter(
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(12),
child: Row( child: Row(
children: [ children: [
DropdownButton<ContentSort>( DropdownButton<ContentSort>(
@ -122,35 +122,33 @@ class _PostsListViewState extends State<PostsListView> {
PagedSliverList<int, PostModel>( PagedSliverList<int, PostModel>(
pagingController: _pagingController, pagingController: _pagingController,
builderDelegate: PagedChildBuilderDelegate<PostModel>( builderDelegate: PagedChildBuilderDelegate<PostModel>(
itemBuilder: (context, item, index) => Padding( itemBuilder: (context, item, index) => Card(
padding: const EdgeInsets.all(8.0), margin: const EdgeInsets.all(12),
child: Card( clipBehavior: Clip.antiAlias,
clipBehavior: Clip.antiAlias, child: InkWell(
child: InkWell( onTap: () {
onTap: () { Navigator.of(context).push(
Navigator.of(context).push( MaterialPageRoute(
MaterialPageRoute( builder: (context) => PostPage(item, (newValue) {
builder: (context) => PostPage(item, (newValue) { var newList = _pagingController.itemList;
var newList = _pagingController.itemList; newList![index] = newValue;
newList![index] = newValue; setState(() {
setState(() { _pagingController.itemList = newList;
_pagingController.itemList = newList; });
}); }),
}), ),
), );
); },
child: PostItem(
item,
(newValue) {
var newList = _pagingController.itemList;
newList![index] = newValue;
setState(() {
_pagingController.itemList = newList;
});
}, },
child: PostItem( isPreview: true,
item,
(newValue) {
var newList = _pagingController.itemList;
newList![index] = newValue;
setState(() {
_pagingController.itemList = newList;
});
},
isPreview: true,
),
), ),
), ),
), ),

View File

@ -8,6 +8,7 @@ import 'package:interstellar/src/widgets/markdown.dart';
import 'package:interstellar/src/widgets/markdown_editor.dart'; import 'package:interstellar/src/widgets/markdown_editor.dart';
import 'package:interstellar/src/widgets/open_webpage.dart'; import 'package:interstellar/src/widgets/open_webpage.dart';
import 'package:interstellar/src/widgets/video.dart'; import 'package:interstellar/src/widgets/video.dart';
import 'package:interstellar/src/widgets/wrapper.dart';
class ContentItem extends StatefulWidget { class ContentItem extends StatefulWidget {
final String? title; final String? title;
@ -18,7 +19,6 @@ class ContentItem extends StatefulWidget {
final DateTime? createdAt; final DateTime? createdAt;
final bool isPreview; final bool isPreview;
final bool showCollapse;
final bool showMagazineFirst; final bool showMagazineFirst;
final String? user; final String? user;
@ -49,7 +49,8 @@ class ContentItem extends StatefulWidget {
final Future<void> Function(String)? onEdit; final Future<void> Function(String)? onEdit;
final Future<void> Function()? onDelete; final Future<void> Function()? onDelete;
final Widget? child; final bool isCollapsed;
final void Function()? onCollapse;
const ContentItem( const ContentItem(
{this.title, {this.title,
@ -59,7 +60,6 @@ class ContentItem extends StatefulWidget {
this.body, this.body,
this.createdAt, this.createdAt,
this.isPreview = false, this.isPreview = false,
this.showCollapse = false,
this.showMagazineFirst = false, this.showMagazineFirst = false,
this.user, this.user,
this.userIcon, this.userIcon,
@ -82,7 +82,8 @@ class ContentItem extends StatefulWidget {
this.onReply, this.onReply,
this.onEdit, this.onEdit,
this.onDelete, this.onDelete,
this.child, this.isCollapsed = false,
this.onCollapse,
super.key}); super.key});
@override @override
@ -90,7 +91,6 @@ class ContentItem extends StatefulWidget {
} }
class _ContentItemState extends State<ContentItem> { class _ContentItemState extends State<ContentItem> {
bool _isCollapsed = false;
TextEditingController? _replyTextController; TextEditingController? _replyTextController;
TextEditingController? _editTextController; TextEditingController? _editTextController;
final MenuController _menuController = MenuController(); final MenuController _menuController = MenuController();
@ -161,35 +161,32 @@ class _ContentItemState extends State<ContentItem> {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[ children: <Widget>[
if (!widget.isPreview && widget.video != null) if (widget.image != null || (!widget.isPreview && widget.video != null))
VideoPlayer(widget.video!), Wrapper(
if (widget.image != null && shouldWrap: !widget.isPreview,
!(!widget.isPreview && widget.video != null)) parentBuilder: (child) => Container(
widget.isPreview constraints: BoxConstraints(
? (widget.video != null maxHeight: MediaQuery.of(context).size.height / 2,
? Image.network( ),
widget.image!, child: child),
height: 160, child: (!widget.isPreview && widget.video != null)
width: double.infinity, ? VideoPlayer(widget.video!)
fit: BoxFit.cover, : Wrapper(
) shouldWrap: widget.video == null,
: InkWell( parentBuilder: (child) => InkWell(
onTap: () => _onImageClick(context), onTap: () => _onImageClick(context),
child: Image.network( child: child,
widget.image!, ),
height: 160, child: widget.isPreview
width: double.infinity, ? Image.network(
fit: BoxFit.cover, widget.image!,
), height: 160,
)) width: double.infinity,
: Container( fit: BoxFit.cover,
constraints: BoxConstraints( )
maxHeight: MediaQuery.of(context).size.height / 2, : Image.network(widget.image!),
), ),
child: InkWell( ),
onTap: () => _onImageClick(context),
child: Image.network(widget.image!),
)),
Container( Container(
padding: const EdgeInsets.all(12), padding: const EdgeInsets.all(12),
child: Column( child: Column(
@ -290,13 +287,11 @@ class _ContentItemState extends State<ContentItem> {
}), }),
), ),
), ),
if (widget.showCollapse && widget.child != null) if (widget.onCollapse != null)
IconButton( IconButton(
tooltip: _isCollapsed ? 'Expand' : 'Collapse', tooltip: widget.isCollapsed ? 'Expand' : 'Collapse',
onPressed: () => setState(() { onPressed: widget.onCollapse,
_isCollapsed = !_isCollapsed; icon: widget.isCollapsed
}),
icon: _isCollapsed
? const Icon(Icons.expand_more) ? const Icon(Icons.expand_more)
: const Icon(Icons.expand_less)), : const Icon(Icons.expand_less)),
const Spacer(), const Spacer(),
@ -450,11 +445,6 @@ class _ContentItemState extends State<ContentItem> {
], ],
), ),
), ),
if (widget.child != null && !_isCollapsed)
Padding(
padding: const EdgeInsets.only(top: 10),
child: widget.child,
)
], ],
), ),
), ),

View File

@ -0,0 +1,19 @@
import 'package:flutter/material.dart';
class Wrapper extends StatelessWidget {
final bool shouldWrap;
final Widget Function(Widget child) parentBuilder;
final Widget child;
const Wrapper({
super.key,
required this.shouldWrap,
required this.parentBuilder,
required this.child,
});
@override
Widget build(BuildContext context) {
return shouldWrap ? parentBuilder(child) : child;
}
}