Change way of parsing urls

This commit is contained in:
shilangyu 2021-01-27 19:53:09 +00:00
parent 651e059fbd
commit fa1243f9d9
3 changed files with 206 additions and 177 deletions

View File

@ -14,3 +14,14 @@ String cleanUpUrl(String url) {
return newUrl;
}
// Returns host of a url without a leading 'www.' if present
String urlHost(String url) {
final host = Uri.parse(url).host;
if (host.startsWith('www.')) {
return host.substring(4);
}
return host;
}

View File

@ -8,30 +8,23 @@ import '../cleanup_url.dart';
// `post.instanceHost == 'lemmy.ml'
// && post.originInstanceHost == 'lemmygrad.ml``
// [.isLocal] is true iff `.originInstanceHost == .instanceHost`
extension GetInstanceCommunitySafe on CommunitySafe {
extension GetOriginInstanceCommunitySafe on CommunitySafe {
String get originInstanceHost => _extract(actorId);
// bool get isLocal => originInstanceHost == instanceHost;
}
extension GetInstanceUserSafe on UserSafe {
extension GetOriginInstanceUserSafe on UserSafe {
String get originInstanceHost => _extract(actorId);
// bool get isLocal => originInstanceHost == instanceHost;
}
extension GetInstancePostView on Post {
extension GetOriginInstancePostView on Post {
String get originInstanceHost => _extract(apId);
// bool get isLocal => originInstanceHost == instanceHost;
}
extension GetInstanceCommentView on Comment {
extension GetOriginInstanceCommentView on Comment {
String get originInstanceHost => _extract(apId);
// bool get isLocal => originInstanceHost == instanceHost;
}
// TODO: change it to something more robust? regex?
String _extract(String s) => cleanUpUrl(s.split('/')[2]);
String _extract(String url) => urlHost(url);
extension DisplayName on UserSafe {
String get displayName {

View File

@ -13,6 +13,7 @@ import '../hooks/delayed_loading.dart';
import '../hooks/logged_in_action.dart';
import '../pages/full_post.dart';
import '../url_launcher.dart';
import '../util/cleanup_url.dart';
import '../util/extensions/api.dart';
import '../util/goto.dart';
import '../util/more_icon.dart';
@ -107,141 +108,156 @@ class PostWidget extends HookWidget {
final urlDomain = () {
if (whatType(post.post.url) == MediaType.none) return null;
final url = post.post.url.split('/')[2]; // TODO: change to Url(str).host
if (url.startsWith('www.')) return url.substring(4);
return url;
return urlHost(post.post.url);
}();
/// assemble info section
Widget info() => Column(children: [
Padding(
padding: const EdgeInsets.all(10),
child: Row(children: [
Column(
mainAxisSize: MainAxisSize.min,
Widget info() => Column(
children: [
Padding(
padding: const EdgeInsets.all(10),
child: Row(
children: [
if (post.community.icon != null)
Padding(
padding: const EdgeInsets.only(right: 10),
child: InkWell(
onTap: () => goToCommunity.byId(
context, instanceHost, post.community.id),
child: SizedBox(
height: 40,
width: 40,
child: CachedNetworkImage(
imageBuilder: (context, imageProvider) => Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
image: DecorationImage(
fit: BoxFit.cover,
image: imageProvider,
Column(
mainAxisSize: MainAxisSize.min,
children: [
if (post.community.icon != null)
Padding(
padding: const EdgeInsets.only(right: 10),
child: InkWell(
onTap: () => goToCommunity.byId(
context, instanceHost, post.community.id),
child: SizedBox(
height: 40,
width: 40,
child: CachedNetworkImage(
imageBuilder: (context, imageProvider) =>
Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
image: DecorationImage(
fit: BoxFit.cover,
image: imageProvider,
),
),
),
imageUrl: post.community.icon,
errorWidget: (context, url, error) =>
Text(error.toString()),
),
),
imageUrl: post.community.icon,
errorWidget: (context, url, error) =>
Text(error.toString()),
),
),
),
),
],
),
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),
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
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: [
const TextSpan(
text: 'by',
style: TextStyle(fontWeight: FontWeight.w300)),
TextSpan(
text: ' ${post.creator.displayName}',
style:
const TextStyle(fontWeight: FontWeight.w600),
recognizer: TapGestureRecognizer()
..onTap = () => goToUser.byId(
context,
post.instanceHost,
post.creator.id,
),
Row(
children: [
RichText(
overflow: TextOverflow.ellipsis,
text: TextSpan(
style: TextStyle(
fontSize: 13,
color: theme.textTheme.bodyText1.color),
children: [
const TextSpan(
text: 'by',
style:
TextStyle(fontWeight: FontWeight.w300)),
TextSpan(
text: ' ${post.creator.displayName}',
style: const TextStyle(
fontWeight: FontWeight.w600),
recognizer: TapGestureRecognizer()
..onTap = () => goToUser.byId(
context,
post.instanceHost,
post.creator.id,
),
),
TextSpan(
text:
''' · ${timeago.format(post.post.published, locale: 'en_short')}'''),
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)
const TextSpan(
text: 'NSFW',
style: TextStyle(color: Colors.red)),
if (urlDomain != null)
TextSpan(text: ' · $urlDomain'),
if (post.post.removed)
const TextSpan(text: ' · REMOVED'),
if (post.post.deleted)
const TextSpan(text: ' · DELETED'),
],
),
TextSpan(
text:
''' · ${timeago.format(post.post.published, locale: 'en_short')}'''),
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)
const TextSpan(
text: 'NSFW',
style: TextStyle(color: Colors.red)),
if (urlDomain != null)
TextSpan(text: ' · $urlDomain'),
if (post.post.removed)
const TextSpan(text: ' · REMOVED'),
if (post.post.deleted)
const TextSpan(text: ' · DELETED'),
],
))
]),
)
],
),
],
),
const Spacer(),
if (!fullPost)
Column(
children: [
IconButton(
onPressed: () => showMoreMenu(context, post),
icon: Icon(moreIcon),
padding: const EdgeInsets.all(0),
visualDensity: VisualDensity.compact,
)
],
)
],
),
const Spacer(),
if (!fullPost)
Column(
children: [
IconButton(
onPressed: () => showMoreMenu(context, post),
icon: Icon(moreIcon),
padding: const EdgeInsets.all(0),
visualDensity: VisualDensity.compact,
)
],
)
]),
),
]);
),
],
);
/// assemble title section
Widget title() => Padding(
@ -263,27 +279,29 @@ class PostWidget extends HookWidget {
const Spacer(),
InkWell(
onTap: _openLink,
child: Stack(children: [
ClipRRect(
borderRadius: BorderRadius.circular(20),
child: CachedNetworkImage(
imageUrl: post.post.thumbnailUrl,
width: 70,
height: 70,
fit: BoxFit.cover,
errorWidget: (context, url, error) =>
Text(error.toString()),
child: Stack(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(20),
child: CachedNetworkImage(
imageUrl: post.post.thumbnailUrl,
width: 70,
height: 70,
fit: BoxFit.cover,
errorWidget: (context, url, error) =>
Text(error.toString()),
),
),
),
const Positioned(
top: 8,
right: 8,
child: Icon(
Icons.launch,
size: 20,
),
)
]),
const Positioned(
top: 8,
right: 8,
child: Icon(
Icons.launch,
size: 20,
),
)
],
),
)
]
],
@ -307,24 +325,30 @@ class PostWidget extends HookWidget {
padding: const EdgeInsets.all(10),
child: Column(
children: [
Row(children: [
const Spacer(),
Text('$urlDomain ',
style: theme.textTheme.caption
.apply(fontStyle: FontStyle.italic)),
const Icon(Icons.launch, size: 12),
]),
Row(children: [
Flexible(
child: Text(post.post.embedTitle ?? '',
style: theme.textTheme.subtitle1
.apply(fontWeightDelta: 2)))
]),
Row(
children: [
const Spacer(),
Text('$urlDomain ',
style: theme.textTheme.caption
.apply(fontStyle: FontStyle.italic)),
const Icon(Icons.launch, size: 12),
],
),
Row(
children: [
Flexible(
child: Text(post.post.embedTitle ?? '',
style: theme.textTheme.subtitle1
.apply(fontWeightDelta: 2)))
],
),
if (post.post.embedDescription != null &&
post.post.embedDescription.isNotEmpty)
Row(children: [
Flexible(child: Text(post.post.embedDescription))
]),
Row(
children: [
Flexible(child: Text(post.post.embedDescription))
],
),
],
),
),
@ -462,16 +486,17 @@ class _Voting extends HookWidget {
Text(NumberFormat.compact()
.format(post.counts.score + (wasVoted ? 0 : myVote.value.value))),
IconButton(
icon: Icon(
Icons.arrow_downward,
color: myVote.value == VoteType.down ? Colors.red : null,
icon: Icon(
Icons.arrow_downward,
color: myVote.value == VoteType.down ? Colors.red : null,
),
onPressed: loggedInAction(
(token) => vote(
myVote.value == VoteType.down ? VoteType.none : VoteType.down,
token,
),
onPressed: loggedInAction(
(token) => vote(
myVote.value == VoteType.down ? VoteType.none : VoteType.down,
token,
),
)),
),
),
],
);
}