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) {
|
static Jwt? _tryGetJwt(BuildContext context, String instanceHost) {
|
||||||
final store = context.read<FullPostStore>();
|
return context.read<AccountsStore>().defaultUserDataFor(instanceHost)?.jwt;
|
||||||
return context
|
|
||||||
.read<AccountsStore>()
|
|
||||||
.defaultUserDataFor(store.instanceHost)
|
|
||||||
?.jwt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Route route(int id, String instanceHost) => MaterialPageRoute(
|
static Route route(int id, String instanceHost) => MaterialPageRoute(
|
||||||
builder: (context) => Provider(
|
builder: (context) => Provider(
|
||||||
create: (context) =>
|
create: (context) =>
|
||||||
FullPostStore(instanceHost: instanceHost, postId: id)
|
FullPostStore(instanceHost: instanceHost, postId: id)
|
||||||
..refresh(_tryGetJwt(context)),
|
..refresh(_tryGetJwt(context, instanceHost)),
|
||||||
child: FullPostPage(
|
child: FullPostPage(
|
||||||
id: id,
|
id: id,
|
||||||
instanceHost: instanceHost,
|
instanceHost: instanceHost,
|
||||||
|
@ -81,14 +77,14 @@ class FullPostPage extends StatelessWidget {
|
||||||
static Route fromPostViewRoute(PostView postView) => MaterialPageRoute(
|
static Route fromPostViewRoute(PostView postView) => MaterialPageRoute(
|
||||||
builder: (context) => Provider(
|
builder: (context) => Provider(
|
||||||
create: (context) => FullPostStore.fromPostView(postView)
|
create: (context) => FullPostStore.fromPostView(postView)
|
||||||
..refresh(_tryGetJwt(context)),
|
..refresh(_tryGetJwt(context, postView.instanceHost)),
|
||||||
child: FullPostPage.fromPostView(postView),
|
child: FullPostPage.fromPostView(postView),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
static Route fromPostStoreRoute(PostStore postStore) => MaterialPageRoute(
|
static Route fromPostStoreRoute(PostStore postStore) => MaterialPageRoute(
|
||||||
builder: (context) => Provider(
|
builder: (context) => Provider(
|
||||||
create: (context) => FullPostStore.fromPostStore(postStore)
|
create: (context) => FullPostStore.fromPostStore(postStore)
|
||||||
..refresh(_tryGetJwt(context)),
|
..refresh(_tryGetJwt(context, postStore.postView.instanceHost)),
|
||||||
child: FullPostPage.fromPostStore(postStore)),
|
child: FullPostPage.fromPostStore(postStore)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,13 +16,14 @@ class PostBody extends StatelessWidget {
|
||||||
final fullPost = context.read<IsFullPost>();
|
final fullPost = context.read<IsFullPost>();
|
||||||
|
|
||||||
return ObserverBuilder<PostStore>(builder: (context, store) {
|
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) {
|
if (fullPost) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(10),
|
padding: const EdgeInsets.all(10),
|
||||||
child: MarkdownText(
|
child: MarkdownText(
|
||||||
store.postView.post.body!,
|
body,
|
||||||
instanceHost: store.postView.instanceHost,
|
instanceHost: store.postView.instanceHost,
|
||||||
selectable: true,
|
selectable: true,
|
||||||
),
|
),
|
||||||
|
@ -31,7 +32,7 @@ class PostBody extends StatelessWidget {
|
||||||
return LayoutBuilder(
|
return LayoutBuilder(
|
||||||
builder: (context, constraints) {
|
builder: (context, constraints) {
|
||||||
final span = TextSpan(
|
final span = TextSpan(
|
||||||
text: store.postView.post.body,
|
text: body,
|
||||||
);
|
);
|
||||||
final tp = TextPainter(
|
final tp = TextPainter(
|
||||||
text: span,
|
text: span,
|
||||||
|
@ -50,9 +51,10 @@ class PostBody extends StatelessWidget {
|
||||||
alignment: Alignment.topCenter,
|
alignment: Alignment.topCenter,
|
||||||
heightFactor: 0.8,
|
heightFactor: 0.8,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(10),
|
padding: const EdgeInsets.all(10),
|
||||||
child: MarkdownText(store.postView.post.body!,
|
child: MarkdownText(body,
|
||||||
instanceHost: store.postView.instanceHost)),
|
instanceHost: store.postView.instanceHost),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
|
@ -74,7 +76,7 @@ class PostBody extends StatelessWidget {
|
||||||
} else {
|
} else {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(10),
|
padding: const EdgeInsets.all(10),
|
||||||
child: MarkdownText(store.postView.post.body!,
|
child: MarkdownText(body,
|
||||||
instanceHost: store.postView.instanceHost));
|
instanceHost: store.postView.instanceHost));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
import '../../l10n/l10n.dart';
|
import '../../l10n/l10n.dart';
|
||||||
|
@ -14,7 +13,7 @@ import 'post_more_menu.dart';
|
||||||
import 'post_status.dart';
|
import 'post_status.dart';
|
||||||
import 'post_store.dart';
|
import 'post_store.dart';
|
||||||
|
|
||||||
class PostInfoSection extends HookWidget {
|
class PostInfoSection extends StatelessWidget {
|
||||||
const PostInfoSection();
|
const PostInfoSection();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -31,111 +30,91 @@ class PostInfoSection extends HookWidget {
|
||||||
padding: const EdgeInsets.all(10),
|
padding: const EdgeInsets.all(10),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Column(
|
if (post.community.icon != null)
|
||||||
mainAxisSize: MainAxisSize.min,
|
Padding(
|
||||||
children: [
|
padding: const EdgeInsets.only(right: 10),
|
||||||
if (post.community.icon != null)
|
child: InkWell(
|
||||||
Padding(
|
borderRadius: BorderRadius.circular(20),
|
||||||
padding: const EdgeInsets.only(right: 10),
|
onTap: () => goToCommunity.byId(
|
||||||
child: InkWell(
|
context, instanceHost, post.community.id),
|
||||||
borderRadius: BorderRadius.circular(20),
|
child: Avatar(
|
||||||
onTap: () => goToCommunity.byId(
|
url: post.community.icon,
|
||||||
context, instanceHost, post.community.id),
|
noBlank: true,
|
||||||
child: Avatar(
|
radius: 20,
|
||||||
url: post.community.icon,
|
|
||||||
noBlank: true,
|
|
||||||
radius: 20,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Row(
|
RichText(
|
||||||
children: [
|
overflow: TextOverflow.ellipsis, // TODO: fix overflowing
|
||||||
RichText(
|
text: TextSpan(
|
||||||
overflow:
|
style: TextStyle(
|
||||||
TextOverflow.ellipsis, // TODO: fix overflowing
|
fontSize: 15,
|
||||||
text: TextSpan(
|
color: theme.textTheme.bodyText1?.color),
|
||||||
style: TextStyle(
|
children: [
|
||||||
fontSize: 15,
|
const TextSpan(
|
||||||
color: theme.textTheme.bodyText1?.color),
|
text: '!',
|
||||||
children: [
|
style: TextStyle(fontWeight: FontWeight.w300)),
|
||||||
const TextSpan(
|
TextSpan(
|
||||||
text: '!',
|
text: post.community.name,
|
||||||
style:
|
style:
|
||||||
TextStyle(fontWeight: FontWeight.w300)),
|
const TextStyle(fontWeight: FontWeight.w600),
|
||||||
TextSpan(
|
recognizer: TapGestureRecognizer()
|
||||||
text: post.community.name,
|
..onTap = () => goToCommunity.byId(
|
||||||
style: const TextStyle(
|
context, instanceHost, post.community.id)),
|
||||||
fontWeight: FontWeight.w600),
|
const TextSpan(
|
||||||
recognizer: TapGestureRecognizer()
|
text: '@',
|
||||||
..onTap = () => goToCommunity.byId(context,
|
style: TextStyle(fontWeight: FontWeight.w300)),
|
||||||
instanceHost, post.community.id)),
|
TextSpan(
|
||||||
const TextSpan(
|
text: post.post.originInstanceHost,
|
||||||
text: '@',
|
style:
|
||||||
style:
|
const TextStyle(fontWeight: FontWeight.w600),
|
||||||
TextStyle(fontWeight: FontWeight.w300)),
|
recognizer: TapGestureRecognizer()
|
||||||
TextSpan(
|
..onTap = () => goToInstance(
|
||||||
text: post.post.originInstanceHost,
|
context, post.post.originInstanceHost)),
|
||||||
style: const TextStyle(
|
],
|
||||||
fontWeight: FontWeight.w600),
|
),
|
||||||
recognizer: TapGestureRecognizer()
|
|
||||||
..onTap = () => goToInstance(
|
|
||||||
context, post.post.originInstanceHost)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
Row(
|
RichText(
|
||||||
children: [
|
overflow: TextOverflow.ellipsis,
|
||||||
RichText(
|
text: TextSpan(
|
||||||
overflow: TextOverflow.ellipsis,
|
style: TextStyle(
|
||||||
text: TextSpan(
|
fontSize: 13,
|
||||||
style: TextStyle(
|
color: theme.textTheme.bodyText1?.color),
|
||||||
fontSize: 13,
|
children: [
|
||||||
color: theme.textTheme.bodyText1?.color),
|
TextSpan(
|
||||||
children: [
|
text: L10n.of(context)!.by,
|
||||||
TextSpan(
|
style: const TextStyle(fontWeight: FontWeight.w300),
|
||||||
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'),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
)
|
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(),
|
const Spacer(),
|
||||||
|
|
|
@ -11,9 +11,9 @@ class PostLinkPreview extends StatelessWidget {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ObserverBuilder<PostStore>(
|
return ObserverBuilder<PostStore>(
|
||||||
builder: (context, store) {
|
builder: (context, store) {
|
||||||
if (store.hasMedia ||
|
final url = store.postView.post.url;
|
||||||
store.postView.post.url == null ||
|
|
||||||
store.postView.post.url!.isEmpty) {
|
if (store.hasMedia || url == null || url.isEmpty) {
|
||||||
return const SizedBox();
|
return const SizedBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ class PostLinkPreview extends StatelessWidget {
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () => linkLauncher(
|
onTap: () => linkLauncher(
|
||||||
context: context,
|
context: context,
|
||||||
url: store.postView.post.url!,
|
url: url,
|
||||||
instanceHost: store.postView.instanceHost,
|
instanceHost: store.postView.instanceHost,
|
||||||
),
|
),
|
||||||
child: Container(
|
child: Container(
|
||||||
|
@ -58,8 +58,8 @@ class PostLinkPreview extends StatelessWidget {
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (store.postView.post.embedDescription != null &&
|
if (store.postView.post.embedDescription?.isNotEmpty ??
|
||||||
store.postView.post.embedDescription!.isNotEmpty)
|
false)
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Flexible(
|
Flexible(
|
||||||
|
|
|
@ -11,19 +11,23 @@ class PostMedia extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ObserverBuilder<PostStore>(builder: (context, store) {
|
return ObserverBuilder<PostStore>(
|
||||||
final post = store.postView.post;
|
builder: (context, store) {
|
||||||
if (!store.hasMedia) return const SizedBox();
|
final post = store.postView.post;
|
||||||
|
if (!store.hasMedia) return const SizedBox();
|
||||||
|
|
||||||
return FullscreenableImage(
|
final url = post.url!; // hasMedia returns false if url is null
|
||||||
url: post.url!,
|
|
||||||
child: CachedNetworkImage(
|
return FullscreenableImage(
|
||||||
imageUrl: post.url!,
|
url: url,
|
||||||
errorWidget: (_, __, ___) => const Icon(Icons.warning),
|
child: CachedNetworkImage(
|
||||||
progressIndicatorBuilder: (context, url, progress) =>
|
imageUrl: url,
|
||||||
CircularProgressIndicator(value: progress.progress),
|
errorWidget: (_, __, ___) => const Icon(Icons.warning),
|
||||||
),
|
progressIndicatorBuilder: (context, url, progress) =>
|
||||||
);
|
CircularProgressIndicator.adaptive(value: progress.progress),
|
||||||
});
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,19 +32,15 @@ class PostMoreMenuButton extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Column(
|
return IconButton(
|
||||||
children: [
|
onPressed: () => show(
|
||||||
IconButton(
|
context: context,
|
||||||
onPressed: () => show(
|
postStore: context.read<PostStore>(),
|
||||||
context: context,
|
fullPostStore: null,
|
||||||
postStore: context.read<PostStore>(),
|
),
|
||||||
fullPostStore: null,
|
icon: Icon(moreIcon),
|
||||||
),
|
padding: EdgeInsets.zero,
|
||||||
icon: Icon(moreIcon),
|
visualDensity: VisualDensity.compact,
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
visualDensity: VisualDensity.compact,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,7 +104,7 @@ class PostMoreMenu extends HookWidget {
|
||||||
loggedInAction(store.blockUser)();
|
loggedInAction(store.blockUser)();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
if (fullPostStore != null && fullPostStore!.fullPostView != null)
|
if (fullPostStore?.fullPostView != null)
|
||||||
ObserverBuilder<FullPostStore>(
|
ObserverBuilder<FullPostStore>(
|
||||||
store: fullPostStore,
|
store: fullPostStore,
|
||||||
builder: (context, store) {
|
builder: (context, store) {
|
||||||
|
|
|
@ -13,9 +13,11 @@ class PostTitle extends StatelessWidget {
|
||||||
return ObserverBuilder<PostStore>(
|
return ObserverBuilder<PostStore>(
|
||||||
builder: (context, store) {
|
builder: (context, store) {
|
||||||
final post = store.postView.post;
|
final post = store.postView.post;
|
||||||
|
final thumbnailUrl = post.thumbnailUrl;
|
||||||
|
final url = post.url;
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(left: 10, right: 10, bottom: 10),
|
padding: const EdgeInsets.all(10).copyWith(top: 0),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
|
@ -28,20 +30,20 @@ class PostTitle extends StatelessWidget {
|
||||||
fontSize: 18, fontWeight: FontWeight.w600),
|
fontSize: 18, fontWeight: FontWeight.w600),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (!store.hasMedia && post.thumbnailUrl != null) ...[
|
if (!store.hasMedia && thumbnailUrl != null && url != null) ...[
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
InkWell(
|
InkWell(
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
onTap: () => linkLauncher(
|
onTap: () => linkLauncher(
|
||||||
context: context,
|
context: context,
|
||||||
url: post.url!,
|
url: url,
|
||||||
instanceHost: store.postView.instanceHost),
|
instanceHost: store.postView.instanceHost),
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
ClipRRect(
|
ClipRRect(
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
child: CachedNetworkImage(
|
child: CachedNetworkImage(
|
||||||
imageUrl: post.thumbnailUrl!,
|
imageUrl: thumbnailUrl,
|
||||||
width: 70,
|
width: 70,
|
||||||
height: 70,
|
height: 70,
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
|
|
|
@ -34,10 +34,12 @@ class PostVoting extends HookWidget {
|
||||||
),
|
),
|
||||||
if (store.votingState.isLoading)
|
if (store.votingState.isLoading)
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
width: 20, height: 20, child: CircularProgressIndicator())
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
child: CircularProgressIndicator.adaptive(),
|
||||||
|
)
|
||||||
else if (showScores)
|
else if (showScores)
|
||||||
Text(compactNumber(store.postView.counts.score +
|
Text(compactNumber(store.postView.counts.score)),
|
||||||
(store.postView.myVote?.value ?? 0))),
|
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
Icons.arrow_downward,
|
Icons.arrow_downward,
|
||||||
|
|
|
@ -6,8 +6,6 @@ import '../../hooks/logged_in_action.dart';
|
||||||
import '../../util/observer_consumers.dart';
|
import '../../util/observer_consumers.dart';
|
||||||
import 'post_store.dart';
|
import 'post_store.dart';
|
||||||
|
|
||||||
// TODO: sync this button between post and fullpost. the same with voting
|
|
||||||
|
|
||||||
class SavePostButton extends HookWidget {
|
class SavePostButton extends HookWidget {
|
||||||
const SavePostButton();
|
const SavePostButton();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue