Redesign comment views to make it cleaner and easier to follow
This commit is contained in:
parent
134a89e193
commit
89b35d7852
|
@ -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');
|
||||||
|
|
||||||
|
|
|
@ -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,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -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(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -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,
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue