Batch of changes addressing CR comments
post_info_section.dart * Hook -> Stateless * remove mysterious Rows & Columns post_body.dart * extract into variable instead of !-ing post_media.dart * extract url into variable, give reason for unwrapping * make spinner adaptive post_link_preview.dart * extract url into a variable * use ?? operator full_post.dart * fix bug from previous commit :^) post_more_menu.dart * remove useless column post_title.dart * rework variables to make it more safe save_post_button.dart * remove TODO comment that has been resolved post_voting.dart * spinner -> adaprive post_voting.dart * spinner -> adaptive * stop manually adding myVote
This commit is contained in:
parent
1a1d001052
commit
cff87e0682
|
@ -58,19 +58,15 @@ class FullPostPage extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
|
||||
static Jwt? _tryGetJwt(BuildContext context) {
|
||||
final store = context.read<FullPostStore>();
|
||||
return context
|
||||
.read<AccountsStore>()
|
||||
.defaultUserDataFor(store.instanceHost)
|
||||
?.jwt;
|
||||
static Jwt? _tryGetJwt(BuildContext context, String instanceHost) {
|
||||
return context.read<AccountsStore>().defaultUserDataFor(instanceHost)?.jwt;
|
||||
}
|
||||
|
||||
static Route route(int id, String instanceHost) => MaterialPageRoute(
|
||||
builder: (context) => Provider(
|
||||
create: (context) =>
|
||||
FullPostStore(instanceHost: instanceHost, postId: id)
|
||||
..refresh(_tryGetJwt(context)),
|
||||
..refresh(_tryGetJwt(context, instanceHost)),
|
||||
child: FullPostPage(
|
||||
id: id,
|
||||
instanceHost: instanceHost,
|
||||
|
@ -81,14 +77,14 @@ class FullPostPage extends StatelessWidget {
|
|||
static Route fromPostViewRoute(PostView postView) => MaterialPageRoute(
|
||||
builder: (context) => Provider(
|
||||
create: (context) => FullPostStore.fromPostView(postView)
|
||||
..refresh(_tryGetJwt(context)),
|
||||
..refresh(_tryGetJwt(context, postView.instanceHost)),
|
||||
child: FullPostPage.fromPostView(postView),
|
||||
),
|
||||
);
|
||||
static Route fromPostStoreRoute(PostStore postStore) => MaterialPageRoute(
|
||||
builder: (context) => Provider(
|
||||
create: (context) => FullPostStore.fromPostStore(postStore)
|
||||
..refresh(_tryGetJwt(context)),
|
||||
..refresh(_tryGetJwt(context, postStore.postView.instanceHost)),
|
||||
child: FullPostPage.fromPostStore(postStore)),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -16,13 +16,14 @@ class PostBody extends StatelessWidget {
|
|||
final fullPost = context.read<IsFullPost>();
|
||||
|
||||
return ObserverBuilder<PostStore>(builder: (context, store) {
|
||||
if (store.postView.post.body == null) return const SizedBox();
|
||||
final body = store.postView.post.body;
|
||||
if (body == null) return const SizedBox();
|
||||
|
||||
if (fullPost) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: MarkdownText(
|
||||
store.postView.post.body!,
|
||||
body,
|
||||
instanceHost: store.postView.instanceHost,
|
||||
selectable: true,
|
||||
),
|
||||
|
@ -31,7 +32,7 @@ class PostBody extends StatelessWidget {
|
|||
return LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final span = TextSpan(
|
||||
text: store.postView.post.body,
|
||||
text: body,
|
||||
);
|
||||
final tp = TextPainter(
|
||||
text: span,
|
||||
|
@ -50,9 +51,10 @@ class PostBody extends StatelessWidget {
|
|||
alignment: Alignment.topCenter,
|
||||
heightFactor: 0.8,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: MarkdownText(store.postView.post.body!,
|
||||
instanceHost: store.postView.instanceHost)),
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: MarkdownText(body,
|
||||
instanceHost: store.postView.instanceHost),
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
|
@ -74,7 +76,7 @@ class PostBody extends StatelessWidget {
|
|||
} else {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: MarkdownText(store.postView.post.body!,
|
||||
child: MarkdownText(body,
|
||||
instanceHost: store.postView.instanceHost));
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../../l10n/l10n.dart';
|
||||
|
@ -14,7 +13,7 @@ import 'post_more_menu.dart';
|
|||
import 'post_status.dart';
|
||||
import 'post_store.dart';
|
||||
|
||||
class PostInfoSection extends HookWidget {
|
||||
class PostInfoSection extends StatelessWidget {
|
||||
const PostInfoSection();
|
||||
|
||||
@override
|
||||
|
@ -31,111 +30,91 @@ class PostInfoSection extends HookWidget {
|
|||
padding: const EdgeInsets.all(10),
|
||||
child: Row(
|
||||
children: [
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (post.community.icon != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 10),
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
onTap: () => goToCommunity.byId(
|
||||
context, instanceHost, post.community.id),
|
||||
child: Avatar(
|
||||
url: post.community.icon,
|
||||
noBlank: true,
|
||||
radius: 20,
|
||||
),
|
||||
),
|
||||
if (post.community.icon != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 10),
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
onTap: () => goToCommunity.byId(
|
||||
context, instanceHost, post.community.id),
|
||||
child: Avatar(
|
||||
url: post.community.icon,
|
||||
noBlank: true,
|
||||
radius: 20,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
RichText(
|
||||
overflow:
|
||||
TextOverflow.ellipsis, // TODO: fix overflowing
|
||||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
color: theme.textTheme.bodyText1?.color),
|
||||
children: [
|
||||
const TextSpan(
|
||||
text: '!',
|
||||
style:
|
||||
TextStyle(fontWeight: FontWeight.w300)),
|
||||
TextSpan(
|
||||
text: post.community.name,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.w600),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () => goToCommunity.byId(context,
|
||||
instanceHost, post.community.id)),
|
||||
const TextSpan(
|
||||
text: '@',
|
||||
style:
|
||||
TextStyle(fontWeight: FontWeight.w300)),
|
||||
TextSpan(
|
||||
text: post.post.originInstanceHost,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.w600),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () => goToInstance(
|
||||
context, post.post.originInstanceHost)),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
RichText(
|
||||
overflow: TextOverflow.ellipsis, // TODO: fix overflowing
|
||||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
color: theme.textTheme.bodyText1?.color),
|
||||
children: [
|
||||
const TextSpan(
|
||||
text: '!',
|
||||
style: TextStyle(fontWeight: FontWeight.w300)),
|
||||
TextSpan(
|
||||
text: post.community.name,
|
||||
style:
|
||||
const TextStyle(fontWeight: FontWeight.w600),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () => goToCommunity.byId(
|
||||
context, instanceHost, post.community.id)),
|
||||
const TextSpan(
|
||||
text: '@',
|
||||
style: TextStyle(fontWeight: FontWeight.w300)),
|
||||
TextSpan(
|
||||
text: post.post.originInstanceHost,
|
||||
style:
|
||||
const TextStyle(fontWeight: FontWeight.w600),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () => goToInstance(
|
||||
context, post.post.originInstanceHost)),
|
||||
],
|
||||
),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
RichText(
|
||||
overflow: TextOverflow.ellipsis,
|
||||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: theme.textTheme.bodyText1?.color),
|
||||
children: [
|
||||
TextSpan(
|
||||
text: L10n.of(context)!.by,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.w300),
|
||||
),
|
||||
TextSpan(
|
||||
text: ' ${post.creator.originPreferredName}',
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.w600),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () => goToUser.fromPersonSafe(
|
||||
context,
|
||||
post.creator,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: ' · ${post.post.published.fancyShort}'),
|
||||
if (post.post.locked)
|
||||
const TextSpan(text: ' · 🔒'),
|
||||
if (post.post.stickied)
|
||||
const TextSpan(text: ' · 📌'),
|
||||
if (post.post.nsfw) const TextSpan(text: ' · '),
|
||||
if (post.post.nsfw)
|
||||
TextSpan(
|
||||
text: L10n.of(context)!.nsfw,
|
||||
style: const TextStyle(color: Colors.red)),
|
||||
if (store.urlDomain != null)
|
||||
TextSpan(text: ' · ${store.urlDomain}'),
|
||||
if (post.post.removed)
|
||||
const TextSpan(text: ' · REMOVED'),
|
||||
if (post.post.deleted)
|
||||
const TextSpan(text: ' · DELETED'),
|
||||
],
|
||||
RichText(
|
||||
overflow: TextOverflow.ellipsis,
|
||||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: theme.textTheme.bodyText1?.color),
|
||||
children: [
|
||||
TextSpan(
|
||||
text: L10n.of(context)!.by,
|
||||
style: const TextStyle(fontWeight: FontWeight.w300),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
TextSpan(
|
||||
text: ' ${post.creator.originPreferredName}',
|
||||
style: const TextStyle(fontWeight: FontWeight.w600),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () => goToUser.fromPersonSafe(
|
||||
context,
|
||||
post.creator,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: ' · ${post.post.published.fancyShort}'),
|
||||
if (post.post.locked) const TextSpan(text: ' · 🔒'),
|
||||
if (post.post.stickied) const TextSpan(text: ' · 📌'),
|
||||
if (post.post.nsfw) const TextSpan(text: ' · '),
|
||||
if (post.post.nsfw)
|
||||
TextSpan(
|
||||
text: L10n.of(context)!.nsfw,
|
||||
style: const TextStyle(color: Colors.red)),
|
||||
if (store.urlDomain != null)
|
||||
TextSpan(text: ' · ${store.urlDomain}'),
|
||||
if (post.post.removed)
|
||||
const TextSpan(text: ' · REMOVED'),
|
||||
if (post.post.deleted)
|
||||
const TextSpan(text: ' · DELETED'),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
const Spacer(),
|
||||
|
|
|
@ -11,9 +11,9 @@ class PostLinkPreview extends StatelessWidget {
|
|||
Widget build(BuildContext context) {
|
||||
return ObserverBuilder<PostStore>(
|
||||
builder: (context, store) {
|
||||
if (store.hasMedia ||
|
||||
store.postView.post.url == null ||
|
||||
store.postView.post.url!.isEmpty) {
|
||||
final url = store.postView.post.url;
|
||||
|
||||
if (store.hasMedia || url == null || url.isEmpty) {
|
||||
return const SizedBox();
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ class PostLinkPreview extends StatelessWidget {
|
|||
child: InkWell(
|
||||
onTap: () => linkLauncher(
|
||||
context: context,
|
||||
url: store.postView.post.url!,
|
||||
url: url,
|
||||
instanceHost: store.postView.instanceHost,
|
||||
),
|
||||
child: Container(
|
||||
|
@ -58,8 +58,8 @@ class PostLinkPreview extends StatelessWidget {
|
|||
)
|
||||
],
|
||||
),
|
||||
if (store.postView.post.embedDescription != null &&
|
||||
store.postView.post.embedDescription!.isNotEmpty)
|
||||
if (store.postView.post.embedDescription?.isNotEmpty ??
|
||||
false)
|
||||
Row(
|
||||
children: [
|
||||
Flexible(
|
||||
|
|
|
@ -11,19 +11,23 @@ class PostMedia extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ObserverBuilder<PostStore>(builder: (context, store) {
|
||||
final post = store.postView.post;
|
||||
if (!store.hasMedia) return const SizedBox();
|
||||
return ObserverBuilder<PostStore>(
|
||||
builder: (context, store) {
|
||||
final post = store.postView.post;
|
||||
if (!store.hasMedia) return const SizedBox();
|
||||
|
||||
return FullscreenableImage(
|
||||
url: post.url!,
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: post.url!,
|
||||
errorWidget: (_, __, ___) => const Icon(Icons.warning),
|
||||
progressIndicatorBuilder: (context, url, progress) =>
|
||||
CircularProgressIndicator(value: progress.progress),
|
||||
),
|
||||
);
|
||||
});
|
||||
final url = post.url!; // hasMedia returns false if url is null
|
||||
|
||||
return FullscreenableImage(
|
||||
url: url,
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: url,
|
||||
errorWidget: (_, __, ___) => const Icon(Icons.warning),
|
||||
progressIndicatorBuilder: (context, url, progress) =>
|
||||
CircularProgressIndicator.adaptive(value: progress.progress),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,19 +32,15 @@ class PostMoreMenuButton extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () => show(
|
||||
context: context,
|
||||
postStore: context.read<PostStore>(),
|
||||
fullPostStore: null,
|
||||
),
|
||||
icon: Icon(moreIcon),
|
||||
padding: EdgeInsets.zero,
|
||||
visualDensity: VisualDensity.compact,
|
||||
)
|
||||
],
|
||||
return IconButton(
|
||||
onPressed: () => show(
|
||||
context: context,
|
||||
postStore: context.read<PostStore>(),
|
||||
fullPostStore: null,
|
||||
),
|
||||
icon: Icon(moreIcon),
|
||||
padding: EdgeInsets.zero,
|
||||
visualDensity: VisualDensity.compact,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -108,7 +104,7 @@ class PostMoreMenu extends HookWidget {
|
|||
loggedInAction(store.blockUser)();
|
||||
},
|
||||
),
|
||||
if (fullPostStore != null && fullPostStore!.fullPostView != null)
|
||||
if (fullPostStore?.fullPostView != null)
|
||||
ObserverBuilder<FullPostStore>(
|
||||
store: fullPostStore,
|
||||
builder: (context, store) {
|
||||
|
|
|
@ -13,9 +13,11 @@ class PostTitle extends StatelessWidget {
|
|||
return ObserverBuilder<PostStore>(
|
||||
builder: (context, store) {
|
||||
final post = store.postView.post;
|
||||
final thumbnailUrl = post.thumbnailUrl;
|
||||
final url = post.url;
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(left: 10, right: 10, bottom: 10),
|
||||
padding: const EdgeInsets.all(10).copyWith(top: 0),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
|
@ -28,20 +30,20 @@ class PostTitle extends StatelessWidget {
|
|||
fontSize: 18, fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
if (!store.hasMedia && post.thumbnailUrl != null) ...[
|
||||
if (!store.hasMedia && thumbnailUrl != null && url != null) ...[
|
||||
const Spacer(),
|
||||
InkWell(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
onTap: () => linkLauncher(
|
||||
context: context,
|
||||
url: post.url!,
|
||||
url: url,
|
||||
instanceHost: store.postView.instanceHost),
|
||||
child: Stack(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: post.thumbnailUrl!,
|
||||
imageUrl: thumbnailUrl,
|
||||
width: 70,
|
||||
height: 70,
|
||||
fit: BoxFit.cover,
|
||||
|
|
|
@ -34,10 +34,12 @@ class PostVoting extends HookWidget {
|
|||
),
|
||||
if (store.votingState.isLoading)
|
||||
const SizedBox(
|
||||
width: 20, height: 20, child: CircularProgressIndicator())
|
||||
width: 20,
|
||||
height: 20,
|
||||
child: CircularProgressIndicator.adaptive(),
|
||||
)
|
||||
else if (showScores)
|
||||
Text(compactNumber(store.postView.counts.score +
|
||||
(store.postView.myVote?.value ?? 0))),
|
||||
Text(compactNumber(store.postView.counts.score)),
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
Icons.arrow_downward,
|
||||
|
|
|
@ -6,8 +6,6 @@ import '../../hooks/logged_in_action.dart';
|
|||
import '../../util/observer_consumers.dart';
|
||||
import 'post_store.dart';
|
||||
|
||||
// TODO: sync this button between post and fullpost. the same with voting
|
||||
|
||||
class SavePostButton extends HookWidget {
|
||||
const SavePostButton();
|
||||
|
||||
|
|
Loading…
Reference in New Issue