Fix federation errors and rename all instanceUrl to instanceHost

This commit is contained in:
shilangyu 2020-12-31 13:58:23 +00:00
parent a9e5113890
commit 58f964ab66
26 changed files with 210 additions and 256 deletions

View File

@ -14,13 +14,13 @@ import 'stores.dart';
Function(
Function(Jwt token) action, [
String message,
]) useLoggedInAction(String instanceUrl, {bool any = false}) {
]) useLoggedInAction(String instanceHost, {bool any = false}) {
final context = useContext();
final store = useAccountsStore();
return (Function(Jwt token) action, [message]) {
if (any && store.hasNoAccount ||
!any && store.isAnonymousFor(instanceUrl)) {
!any && store.isAnonymousFor(instanceHost)) {
return () {
Scaffold.of(context).showSnackBar(SnackBar(
content: Text(message ?? 'you have to be logged in to do that'),
@ -30,7 +30,7 @@ Function(
));
};
}
final token = store.defaultTokenFor(instanceUrl);
final token = store.defaultTokenFor(instanceHost);
return () => action(token);
};
}

View File

@ -13,10 +13,10 @@ import 'add_instance.dart';
/// A modal where an account can be added for a given instance
class AddAccountPage extends HookWidget {
final String instanceUrl;
final String instanceHost;
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey();
AddAccountPage({@required this.instanceUrl}) : assert(instanceUrl != null);
AddAccountPage({@required this.instanceHost}) : assert(instanceHost != null);
@override
Widget build(BuildContext context) {
@ -29,7 +29,7 @@ class AddAccountPage extends HookWidget {
final accountsStore = useAccountsStore();
final loading = useDelayedLoading();
final selectedInstance = useState(instanceUrl);
final selectedInstance = useState(instanceHost);
final icon = useState<String>(null);
useEffect(() {
LemmyApi(selectedInstance.value)

View File

@ -2,7 +2,6 @@ import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:lemmy_api_client/lemmy_api_client.dart';
import '../util/extensions/api.dart';
import '../util/goto.dart';
import '../widgets/markdown_text.dart';
import '../widgets/sortable_infinite_list.dart';
@ -44,12 +43,12 @@ class CommunitiesListPage extends StatelessWidget {
opacity: 0.5,
child: MarkdownText(
community.description,
instanceUrl: community.instanceUrl,
instanceHost: community.instanceHost,
),
)
: null,
onTap: () => goToCommunity.byId(
context, community.instanceUrl, community.id),
context, community.instanceHost, community.id),
leading: community.icon != null
? CachedNetworkImage(
height: 50,

View File

@ -32,8 +32,8 @@ class CommunitiesTab extends HookWidget {
final instancesSnap = useMemoFuture(() {
final futures = accountsStore.loggedInInstances
.map(
(instanceUrl) =>
LemmyApi(instanceUrl).v1.getSite().then((e) => e.site),
(instanceHost) =>
LemmyApi(instanceHost).v1.getSite().then((e) => e.site),
)
.toList();
@ -42,12 +42,13 @@ class CommunitiesTab extends HookWidget {
final communitiesSnap = useMemoFuture(() {
final futures = accountsStore.loggedInInstances
.map(
(instanceUrl) => LemmyApi(instanceUrl)
(instanceHost) => LemmyApi(instanceHost)
.v1
.getUserDetails(
sort: SortType.active,
savedOnly: false,
userId: accountsStore.defaultTokenFor(instanceUrl).payload.id,
userId:
accountsStore.defaultTokenFor(instanceHost).payload.id,
)
.then((e) => e.follows),
)
@ -208,7 +209,7 @@ class CommunitiesTab extends HookWidget {
],
),
trailing: _CommunitySubscribeToggle(
instanceUrl: comm.communityActorId.split('/')[2],
instanceHost: comm.communityActorId.split('/')[2],
communityId: comm.communityId,
),
),
@ -223,11 +224,11 @@ class CommunitiesTab extends HookWidget {
class _CommunitySubscribeToggle extends HookWidget {
final int communityId;
final String instanceUrl;
final String instanceHost;
_CommunitySubscribeToggle(
{@required this.instanceUrl, @required this.communityId})
: assert(instanceUrl != null),
{@required this.instanceHost, @required this.communityId})
: assert(instanceHost != null),
assert(communityId != null);
@override
@ -241,10 +242,10 @@ class _CommunitySubscribeToggle extends HookWidget {
delayed.start();
try {
await LemmyApi(instanceUrl).v1.followCommunity(
await LemmyApi(instanceHost).v1.followCommunity(
communityId: communityId,
follow: !subbed.value,
auth: accountsStore.defaultTokenFor(instanceUrl).raw,
auth: accountsStore.defaultTokenFor(instanceHost).raw,
);
subbed.value = !subbed.value;
} on Exception catch (err) {

View File

@ -10,7 +10,6 @@ import '../hooks/delayed_loading.dart';
import '../hooks/logged_in_action.dart';
import '../hooks/memo_future.dart';
import '../hooks/stores.dart';
import '../util/extensions/api.dart';
import '../util/goto.dart';
import '../util/intl.dart';
import '../util/more_icon.dart';
@ -25,26 +24,26 @@ import '../widgets/sortable_infinite_list.dart';
/// Displays posts, comments, and general info about the given community
class CommunityPage extends HookWidget {
final CommunityView _community;
final String instanceUrl;
final String instanceHost;
final String communityName;
final int communityId;
CommunityPage.fromName({
@required this.communityName,
@required this.instanceUrl,
@required this.instanceHost,
}) : assert(communityName != null),
assert(instanceUrl != null),
assert(instanceHost != null),
communityId = null,
_community = null;
CommunityPage.fromId({
@required this.communityId,
@required this.instanceUrl,
@required this.instanceHost,
}) : assert(communityId != null),
assert(instanceUrl != null),
assert(instanceHost != null),
communityName = null,
_community = null;
CommunityPage.fromCommunityView(this._community)
: instanceUrl = _community.instanceUrl,
: instanceHost = _community.instanceHost,
communityId = _community.id,
communityName = _community.name;
@ -54,15 +53,15 @@ class CommunityPage extends HookWidget {
final accountsStore = useAccountsStore();
final fullCommunitySnap = useMemoFuture(() {
final token = accountsStore.defaultTokenFor(instanceUrl);
final token = accountsStore.defaultTokenFor(instanceHost);
if (communityId != null) {
return LemmyApi(instanceUrl).v1.getCommunity(
return LemmyApi(instanceHost).v1.getCommunity(
id: communityId,
auth: token?.raw,
);
} else {
return LemmyApi(instanceUrl).v1.getCommunity(
return LemmyApi(instanceHost).v1.getCommunity(
name: communityName,
auth: token?.raw,
);
@ -169,7 +168,7 @@ class CommunityPage extends HookWidget {
],
flexibleSpace: FlexibleSpaceBar(
background:
_CommunityOverview(community, instanceUrl: instanceUrl),
_CommunityOverview(community, instanceHost: instanceHost),
),
),
SliverPersistentHeader(
@ -191,7 +190,7 @@ class CommunityPage extends HookWidget {
children: [
InfinitePostList(
fetcher: (page, batchSize, sort) =>
LemmyApi(community.instanceUrl).v1.getPosts(
LemmyApi(community.instanceHost).v1.getPosts(
type: PostListingType.community,
sort: sort,
communityId: community.id,
@ -201,10 +200,10 @@ class CommunityPage extends HookWidget {
),
InfiniteCommentList(
fetcher: (page, batchSize, sortType) =>
LemmyApi(community.instanceUrl).v1.getComments(
LemmyApi(community.instanceHost).v1.getComments(
communityId: community.id,
auth: accountsStore
.defaultTokenFor(community.instanceUrl)
.defaultTokenFor(community.instanceHost)
?.raw,
type: CommentListingType.community,
sort: sortType,
@ -225,12 +224,12 @@ class CommunityPage extends HookWidget {
class _CommunityOverview extends StatelessWidget {
final CommunityView community;
final String instanceUrl;
final String instanceHost;
_CommunityOverview(
this.community, {
@required this.instanceUrl,
}) : assert(instanceUrl != null),
@required this.instanceHost,
}) : assert(instanceHost != null),
assert(goToInstance != null);
@override
@ -316,10 +315,10 @@ class _CommunityOverview extends StatelessWidget {
text: '@',
style: TextStyle(fontWeight: FontWeight.w200)),
TextSpan(
text: instanceUrl,
text: instanceHost,
style: TextStyle(fontWeight: FontWeight.w600),
recognizer: TapGestureRecognizer()
..onTap = () => goToInstance(context, instanceUrl)),
..onTap = () => goToInstance(context, instanceHost)),
],
),
),
@ -423,7 +422,7 @@ class _AboutTab extends StatelessWidget {
Padding(
padding: const EdgeInsets.symmetric(horizontal: 15),
child: MarkdownText(community.description,
instanceUrl: community.instanceUrl),
instanceHost: community.instanceHost),
),
_Divider(),
],
@ -480,7 +479,7 @@ class _AboutTab extends StatelessWidget {
for (final mod in moderators)
ListTile(
title: Text(mod.userPreferredUsername ?? '@${mod.userName}'),
onTap: () => goToUser.byId(context, mod.instanceUrl, mod.userId),
onTap: () => goToUser.byId(context, mod.instanceHost, mod.userId),
),
]
],
@ -530,14 +529,14 @@ class _FollowButton extends HookWidget {
final isSubbed = useState(community.subscribed ?? false);
final delayed = useDelayedLoading(const Duration(milliseconds: 500));
final loggedInAction = useLoggedInAction(community.instanceUrl);
final loggedInAction = useLoggedInAction(community.instanceHost);
final colorOnTopOfAccent = textColorBasedOnBackground(theme.accentColor);
subscribe(Jwt token) async {
delayed.start();
try {
await LemmyApi(community.instanceUrl).v1.followCommunity(
await LemmyApi(community.instanceHost).v1.followCommunity(
communityId: community.id,
follow: !isSubbed.value,
auth: token.raw);

View File

@ -9,7 +9,6 @@ import '../hooks/image_picker.dart';
import '../hooks/logged_in_action.dart';
import '../hooks/memo_future.dart';
import '../hooks/stores.dart';
import '../util/extensions/api.dart';
import '../util/extensions/spaced.dart';
import '../util/goto.dart';
import '../util/pictrs.dart';
@ -46,7 +45,7 @@ class CreatePost extends HookWidget {
final bodyController = useTextEditingController();
final accStore = useAccountsStore();
final selectedInstance =
useState(community?.instanceUrl ?? accStore.loggedInInstances.first);
useState(community?.instanceHost ?? accStore.loggedInInstances.first);
final selectedCommunity = useState(community);
final showFancy = useState(false);
final nsfw = useState(false);
@ -203,7 +202,7 @@ class CreatePost extends HookWidget {
padding: const EdgeInsets.all(16),
child: MarkdownText(
bodyController.text,
instanceUrl: selectedInstance.value,
instanceHost: selectedInstance.value,
),
),
],

View File

@ -7,7 +7,6 @@ import 'package:lemmy_api_client/lemmy_api_client.dart';
import '../hooks/logged_in_action.dart';
import '../hooks/memo_future.dart';
import '../hooks/stores.dart';
import '../util/extensions/api.dart';
import '../util/more_icon.dart';
import '../widgets/comment_section.dart';
import '../widgets/post.dart';
@ -17,24 +16,24 @@ import '../widgets/write_comment.dart';
/// Displays a post with its comment section
class FullPostPage extends HookWidget {
final int id;
final String instanceUrl;
final String instanceHost;
final PostView post;
FullPostPage({@required this.id, @required this.instanceUrl})
FullPostPage({@required this.id, @required this.instanceHost})
: assert(id != null),
assert(instanceUrl != null),
assert(instanceHost != null),
post = null;
FullPostPage.fromPostView(this.post)
: id = post.id,
instanceUrl = post.instanceUrl;
instanceHost = post.instanceHost;
@override
Widget build(BuildContext context) {
final accStore = useAccountsStore();
final fullPostSnap = useMemoFuture(() => LemmyApi(instanceUrl)
final fullPostSnap = useMemoFuture(() => LemmyApi(instanceHost)
.v1
.getPost(id: id, auth: accStore.defaultTokenFor(instanceUrl)?.raw));
final loggedInAction = useLoggedInAction(instanceUrl);
.getPost(id: id, auth: accStore.defaultTokenFor(instanceHost)?.raw));
final loggedInAction = useLoggedInAction(instanceHost);
final newComments = useState(const <CommentView>[]);
// FALLBACK VIEW

View File

@ -118,10 +118,10 @@ class HomeTab extends HookWidget {
? () => showCupertinoModalPopup(
context: context,
builder: (_) =>
AddAccountPage(instanceUrl: instance))
AddAccountPage(instanceHost: instance))
: () => pop(_SelectedList(
listingType: PostListingType.subscribed,
instanceUrl: instance,
instanceHost: instance,
)),
leading: SizedBox(width: 20),
),
@ -129,7 +129,7 @@ class HomeTab extends HookWidget {
title: Text('All'),
onTap: () => pop(_SelectedList(
listingType: PostListingType.all,
instanceUrl: instance,
instanceHost: instance,
)),
leading: SizedBox(width: 20),
),
@ -149,9 +149,9 @@ class HomeTab extends HookWidget {
final first = selectedList.value.listingType == PostListingType.subscribed
? 'Subscribed'
: 'All';
final last = selectedList.value.instanceUrl == null
final last = selectedList.value.instanceHost == null
? ''
: '@${selectedList.value.instanceUrl}';
: '@${selectedList.value.instanceHost}';
return '$first$last';
}();
@ -256,12 +256,12 @@ class InfiniteHomeList extends HookWidget {
}();
final futures =
instances.map((instanceUrl) => LemmyApi(instanceUrl).v1.getPosts(
instances.map((instanceHost) => LemmyApi(instanceHost).v1.getPosts(
type: listingType,
sort: sort,
page: page,
limit: limit,
auth: accStore.defaultTokenFor(instanceUrl)?.raw,
auth: accStore.defaultTokenFor(instanceHost)?.raw,
));
final posts = await Future.wait(futures);
final newPosts = <PostView>[];
@ -277,13 +277,13 @@ class InfiniteHomeList extends HookWidget {
}
Future<List<PostView>> Function(int, int) fetcherFromInstance(
String instanceUrl, PostListingType listingType, SortType sort) =>
(page, batchSize) => LemmyApi(instanceUrl).v1.getPosts(
String instanceHost, PostListingType listingType, SortType sort) =>
(page, batchSize) => LemmyApi(instanceHost).v1.getPosts(
type: listingType,
sort: sort,
page: page,
limit: batchSize,
auth: accStore.defaultTokenFor(instanceUrl)?.raw,
auth: accStore.defaultTokenFor(instanceHost)?.raw,
);
return InfiniteScroll<PostView>(
@ -303,11 +303,11 @@ class InfiniteHomeList extends HookWidget {
],
),
padding: EdgeInsets.zero,
fetchMore: selectedList.instanceUrl == null
fetchMore: selectedList.instanceHost == null
? (page, limit) =>
generalFetcher(page, limit, sort.value, selectedList.listingType)
: fetcherFromInstance(
selectedList.instanceUrl,
selectedList.instanceHost,
selectedList.listingType,
sort.value,
),
@ -318,13 +318,13 @@ class InfiniteHomeList extends HookWidget {
}
class _SelectedList {
final String instanceUrl;
final String instanceHost;
final PostListingType listingType;
_SelectedList({
@required this.listingType,
this.instanceUrl,
this.instanceHost,
});
String toString() =>
'SelectedList({instanceUrl: $instanceUrl, listingType: $listingType})';
'SelectedList({instanceHost: $instanceHost, listingType: $listingType})';
}

View File

@ -6,7 +6,6 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:lemmy_api_client/lemmy_api_client.dart';
import '../hooks/stores.dart';
import '../util/extensions/api.dart';
import '../util/goto.dart';
import '../util/more_icon.dart';
import '../util/text_color.dart';
@ -20,18 +19,18 @@ import 'users_list.dart';
/// Displays posts, comments, and general info about the given instance
class InstancePage extends HookWidget {
final String instanceUrl;
final String instanceHost;
final Future<FullSiteView> siteFuture;
final Future<List<CommunityView>> communitiesFuture;
void _share() =>
Share.text('Share instance', 'https://$instanceUrl', 'text/plain');
Share.text('Share instance', 'https://$instanceHost', 'text/plain');
InstancePage({@required this.instanceUrl})
: assert(instanceUrl != null),
siteFuture = LemmyApi(instanceUrl).v1.getSite(),
InstancePage({@required this.instanceHost})
: assert(instanceHost != null),
siteFuture = LemmyApi(instanceHost).v1.getSite(),
communitiesFuture =
LemmyApi(instanceUrl).v1.listCommunities(sort: SortType.hot);
LemmyApi(instanceHost).v1.listCommunities(sort: SortType.hot);
@override
Widget build(BuildContext context) {
@ -70,7 +69,7 @@ class InstancePage extends HookWidget {
void _openMoreMenu(BuildContext c) {
showInfoTablePopup(context, {
'url': instanceUrl,
'url': instanceHost,
'creator': '@${site.site.creatorName}',
'version': site.version,
'enableDownvotes': site.site.enableDownvotes,
@ -132,7 +131,7 @@ class InstancePage extends HookWidget {
),
Text(site.site.name,
style: theme.textTheme.headline6),
Text(instanceUrl, style: theme.textTheme.caption)
Text(instanceHost, style: theme.textTheme.caption)
],
),
),
@ -159,26 +158,26 @@ class InstancePage extends HookWidget {
children: [
InfinitePostList(
fetcher: (page, batchSize, sort) =>
LemmyApi(instanceUrl).v1.getPosts(
LemmyApi(instanceHost).v1.getPosts(
// TODO: switch between all and subscribed
type: PostListingType.all,
sort: sort,
limit: batchSize,
page: page,
auth: accStore.defaultTokenFor(instanceUrl)?.raw,
auth: accStore.defaultTokenFor(instanceHost)?.raw,
)),
InfiniteCommentList(
fetcher: (page, batchSize, sort) =>
LemmyApi(instanceUrl).v1.getComments(
LemmyApi(instanceHost).v1.getComments(
type: CommentListingType.all,
sort: sort,
limit: batchSize,
page: page,
auth: accStore.defaultTokenFor(instanceUrl)?.raw,
auth: accStore.defaultTokenFor(instanceHost)?.raw,
)),
_AboutTab(site,
communitiesFuture: communitiesFuture,
instanceUrl: instanceUrl),
instanceHost: instanceHost),
],
),
),
@ -211,12 +210,12 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
class _AboutTab extends HookWidget {
final FullSiteView site;
final Future<List<CommunityView>> communitiesFuture;
final String instanceUrl;
final String instanceHost;
const _AboutTab(this.site,
{@required this.communitiesFuture, @required this.instanceUrl})
{@required this.communitiesFuture, @required this.instanceHost})
: assert(communitiesFuture != null),
assert(instanceUrl != null);
assert(instanceHost != null);
void goToUser(int id) {
print('GO TO USER $id');
@ -245,11 +244,11 @@ class _AboutTab extends HookWidget {
context,
(_) => CommunitiesListPage(
fetcher: (page, batchSize, sortType) =>
LemmyApi(instanceUrl).v1.listCommunities(
LemmyApi(instanceHost).v1.listCommunities(
sort: sortType,
limit: batchSize,
page: page,
auth: accStore.defaultTokenFor(instanceUrl)?.raw,
auth: accStore.defaultTokenFor(instanceHost)?.raw,
),
title: 'Communities of ${site.site.name}',
),
@ -265,7 +264,7 @@ class _AboutTab extends HookWidget {
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15),
child: MarkdownText(
site.site.description,
instanceUrl: instanceUrl,
instanceHost: instanceHost,
),
),
_Divider(),
@ -296,7 +295,7 @@ class _AboutTab extends HookWidget {
if (commSnap.hasData)
...commSnap.data.take(6).map((e) => ListTile(
onTap: () =>
goToCommunity.byId(context, e.instanceUrl, e.id),
goToCommunity.byId(context, e.instanceHost, e.id),
title: Text(e.name),
leading: e.icon != null
? CachedNetworkImage(
@ -345,7 +344,7 @@ class _AboutTab extends HookWidget {
? '@${e.name}'
: e.preferredUsername),
subtitle: e.bio != null
? MarkdownText(e.bio, instanceUrl: instanceUrl)
? MarkdownText(e.bio, instanceHost: instanceHost)
: null,
onTap: () => goToUser(e.id),
leading: e.avatar != null

View File

@ -85,9 +85,9 @@ class UserProfileTab extends HookWidget {
builder: (ctx) {
final userTags = <String>[];
accountsStore.tokens.forEach((instanceUrl, value) {
accountsStore.tokens.forEach((instanceHost, value) {
value.forEach((username, _) {
userTags.add('$username@$instanceUrl');
userTags.add('$username@$instanceHost');
});
});
@ -100,7 +100,7 @@ class UserProfileTab extends HookWidget {
value: tag,
title: Text(tag),
groupValue: '${accountsStore.defaultUsername}'
'@${accountsStore.defaultInstanceUrl}',
'@${accountsStore.defaultInstanceHost}',
onChanged: (selected) {
final userTag = selected.split('@');
accountsStore.setDefaultAccount(
@ -119,7 +119,7 @@ class UserProfileTab extends HookWidget {
),
body: UserProfile(
userId: accountsStore.defaultToken.payload.id,
instanceUrl: accountsStore.defaultInstanceUrl,
instanceHost: accountsStore.defaultInstanceHost,
),
);
}

View File

@ -99,12 +99,12 @@ class AccountsConfigPage extends HookWidget {
final theme = Theme.of(context);
final accountsStore = useAccountsStore();
removeInstanceDialog(String instanceUrl) async {
removeInstanceDialog(String instanceHost) async {
if (await showDialog<bool>(
context: context,
builder: (context) => AlertDialog(
title: Text('Remove instance?'),
content: Text('Are you sure you want to remove $instanceUrl?'),
content: Text('Are you sure you want to remove $instanceHost?'),
actions: [
FlatButton(
child: Text('no'),
@ -118,17 +118,17 @@ class AccountsConfigPage extends HookWidget {
),
) ??
false) {
accountsStore.removeInstance(instanceUrl);
accountsStore.removeInstance(instanceHost);
}
}
Future<void> removeUserDialog(String instanceUrl, String username) async {
Future<void> removeUserDialog(String instanceHost, String username) async {
if (await showDialog<bool>(
context: context,
builder: (context) => AlertDialog(
title: Text('Remove user?'),
content: Text(
'Are you sure you want to remove $username@$instanceUrl?'),
'Are you sure you want to remove $username@$instanceHost?'),
actions: [
FlatButton(
child: Text('no'),
@ -142,7 +142,7 @@ class AccountsConfigPage extends HookWidget {
),
) ??
false) {
accountsStore.removeAccount(instanceUrl, username);
accountsStore.removeAccount(instanceHost, username);
}
}
@ -171,7 +171,7 @@ class AccountsConfigPage extends HookWidget {
onTap: () => showCupertinoModalPopup(
context: context,
builder: (_) =>
AddAccountPage(instanceUrl: accountsStore.instances.last)),
AddAccountPage(instanceHost: accountsStore.instances.last)),
),
SpeedDialChild(
child: Icon(Icons.dns),
@ -263,7 +263,7 @@ class AccountsConfigPage extends HookWidget {
onTap: () {
showCupertinoModalPopup(
context: context,
builder: (_) => AddAccountPage(instanceUrl: entry.key));
builder: (_) => AddAccountPage(instanceHost: entry.key));
},
),
]

View File

@ -8,20 +8,20 @@ import '../widgets/user_profile.dart';
/// Page showing posts, comments, and general info about a user.
class UserPage extends HookWidget {
final int userId;
final String instanceUrl;
final String instanceHost;
final Future<UserDetails> _userDetails;
UserPage({@required this.userId, @required this.instanceUrl})
UserPage({@required this.userId, @required this.instanceHost})
: assert(userId != null),
assert(instanceUrl != null),
_userDetails = LemmyApi(instanceUrl).v1.getUserDetails(
assert(instanceHost != null),
_userDetails = LemmyApi(instanceHost).v1.getUserDetails(
userId: userId, savedOnly: true, sort: SortType.active);
UserPage.fromName({@required this.instanceUrl, @required String username})
: assert(instanceUrl != null),
UserPage.fromName({@required this.instanceHost, @required String username})
: assert(instanceHost != null),
assert(username != null),
userId = null,
_userDetails = LemmyApi(instanceUrl).v1.getUserDetails(
_userDetails = LemmyApi(instanceHost).v1.getUserDetails(
username: username, savedOnly: true, sort: SortType.active);
@override

View File

@ -2,7 +2,6 @@ import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:lemmy_api_client/lemmy_api_client.dart';
import '../util/extensions/api.dart';
import '../widgets/markdown_text.dart';
/// Infinite list of Users fetched by the given fetcher
@ -42,7 +41,7 @@ class UsersListPage extends StatelessWidget {
opacity: 0.5,
child: MarkdownText(
users[i].bio,
instanceUrl: users[i].instanceUrl,
instanceHost: users[i].instanceHost,
),
)
: null,

View File

@ -12,16 +12,16 @@ class AccountsStore extends ChangeNotifier {
/// Map containing JWT tokens of specific users.
/// If a token is in this map, the user is considered logged in
/// for that account.
/// `tokens['instanceUrl']['username']`
/// `tokens['instanceHost']['username']`
HashMap<String, HashMap<String, Jwt>> get tokens => _tokens;
HashMap<String, HashMap<String, Jwt>> _tokens;
/// default account for a given instance
/// map where keys are instanceUrls and values are usernames
/// map where keys are instanceHosts and values are usernames
HashMap<String, String> _defaultAccounts;
/// default account for the app
/// It is in a form of `username@instanceUrl`
/// It is in a form of `username@instanceHost`
String _defaultAccount;
Future<void> load() async {
@ -87,12 +87,12 @@ class AccountsStore extends ChangeNotifier {
}
// set local defaults
for (final instanceUrl in instances) {
for (final instanceHost in instances) {
// if this instance is not in defaults
if (!_defaultAccounts.containsKey(instanceUrl)) {
if (!_defaultAccounts.containsKey(instanceHost)) {
// select first account in this instance, if any
if (!isAnonymousFor(instanceUrl)) {
setDefaultAccountFor(instanceUrl, tokens[instanceUrl].keys.first);
if (!isAnonymousFor(instanceHost)) {
setDefaultAccountFor(instanceHost, tokens[instanceHost].keys.first);
}
}
}
@ -100,10 +100,10 @@ class AccountsStore extends ChangeNotifier {
// set global default
if (_defaultAccount == null) {
// select first account of first instance
for (final instanceUrl in instances) {
for (final instanceHost in instances) {
// select first account in this instance, if any
if (!isAnonymousFor(instanceUrl)) {
setDefaultAccount(instanceUrl, tokens[instanceUrl].keys.first);
if (!isAnonymousFor(instanceHost)) {
setDefaultAccount(instanceHost, tokens[instanceHost].keys.first);
}
}
}
@ -117,7 +117,7 @@ class AccountsStore extends ChangeNotifier {
return _defaultAccount.split('@')[0];
}
String get defaultInstanceUrl {
String get defaultInstanceHost {
if (_defaultAccount == null) {
return null;
}
@ -125,12 +125,12 @@ class AccountsStore extends ChangeNotifier {
return _defaultAccount.split('@')[1];
}
String defaultUsernameFor(String instanceUrl) {
if (isAnonymousFor(instanceUrl)) {
String defaultUsernameFor(String instanceHost) {
if (isAnonymousFor(instanceHost)) {
return null;
}
return _defaultAccounts[instanceUrl];
return _defaultAccounts[instanceHost];
}
Jwt get defaultToken {
@ -142,25 +142,25 @@ class AccountsStore extends ChangeNotifier {
return tokens[userTag[1]][userTag[0]];
}
Jwt defaultTokenFor(String instanceUrl) {
if (isAnonymousFor(instanceUrl)) {
Jwt defaultTokenFor(String instanceHost) {
if (isAnonymousFor(instanceHost)) {
return null;
}
return tokens[instanceUrl][_defaultAccounts[instanceUrl]];
return tokens[instanceHost][_defaultAccounts[instanceHost]];
}
/// sets globally default account
void setDefaultAccount(String instanceUrl, String username) {
_defaultAccount = '$username@$instanceUrl';
void setDefaultAccount(String instanceHost, String username) {
_defaultAccount = '$username@$instanceHost';
notifyListeners();
save();
}
/// sets default account for given instance
void setDefaultAccountFor(String instanceUrl, String username) {
_defaultAccounts[instanceUrl] = username;
void setDefaultAccountFor(String instanceHost, String username) {
_defaultAccounts[instanceHost] = username;
notifyListeners();
save();
@ -168,12 +168,12 @@ class AccountsStore extends ChangeNotifier {
/// An instance is considered anonymous if it was not
/// added or there are no accounts assigned to it.
bool isAnonymousFor(String instanceUrl) {
if (!instances.contains(instanceUrl)) {
bool isAnonymousFor(String instanceHost) {
if (!instances.contains(instanceHost)) {
return true;
}
return tokens[instanceUrl].isEmpty;
return tokens[instanceHost].isEmpty;
}
/// `true` if no added instance has an account assigned to it
@ -190,15 +190,15 @@ class AccountsStore extends ChangeNotifier {
/// if it's the first account for an instance the account is
/// set as default for that instance
Future<void> addAccount(
String instanceUrl,
String instanceHost,
String usernameOrEmail,
String password,
) async {
if (!instances.contains(instanceUrl)) {
if (!instances.contains(instanceHost)) {
throw Exception('No such instance was added');
}
final lemmy = LemmyApi(instanceUrl).v1;
final lemmy = LemmyApi(instanceHost).v1;
final token = await lemmy.login(
usernameOrEmail: usernameOrEmail,
@ -207,7 +207,7 @@ class AccountsStore extends ChangeNotifier {
final userData =
await lemmy.getSite(auth: token.raw).then((value) => value.myUser);
tokens[instanceUrl][userData.name] = token;
tokens[instanceHost][userData.name] = token;
_assignDefaultAccounts();
notifyListeners();
@ -218,23 +218,23 @@ class AccountsStore extends ChangeNotifier {
/// Additionally makes a test `GET /site` request to check if the instance exists.
/// Check is skipped when [assumeValid] is `true`
Future<void> addInstance(
String instanceUrl, {
String instanceHost, {
bool assumeValid = false,
}) async {
if (instances.contains(instanceUrl)) {
if (instances.contains(instanceHost)) {
throw Exception('This instance has already been added');
}
if (!assumeValid) {
try {
await LemmyApi(instanceUrl).v1.getSite();
await LemmyApi(instanceHost).v1.getSite();
// ignore: avoid_catches_without_on_clauses
} catch (_) {
throw Exception('This instance seems to not exist');
}
}
tokens[instanceUrl] = HashMap();
tokens[instanceHost] = HashMap();
_assignDefaultAccounts();
notifyListeners();
@ -242,16 +242,16 @@ class AccountsStore extends ChangeNotifier {
}
/// This also removes all accounts assigned to this instance
void removeInstance(String instanceUrl) {
tokens.remove(instanceUrl);
void removeInstance(String instanceHost) {
tokens.remove(instanceHost);
_assignDefaultAccounts();
notifyListeners();
save();
}
void removeAccount(String instanceUrl, String username) {
tokens[instanceUrl].remove(username);
void removeAccount(String instanceHost, String username) {
tokens[instanceHost].remove(username);
_assignDefaultAccounts();
notifyListeners();

View File

@ -15,7 +15,7 @@ import 'util/goto.dart';
Future<void> linkLauncher({
@required BuildContext context,
@required String url,
@required String instanceUrl,
@required String instanceHost,
}) async {
push(Widget Function() builder) {
goTo(context, (c) => builder());
@ -28,14 +28,14 @@ Future<void> linkLauncher({
// CHECK IF LINK TO USER
if (url.startsWith('/u/')) {
return push(
() => UserPage.fromName(instanceUrl: instanceUrl, username: chonks[2]));
return push(() =>
UserPage.fromName(instanceHost: instanceHost, username: chonks[2]));
}
// CHECK IF LINK TO COMMUNITY
if (url.startsWith('/c/')) {
return push(() => CommunityPage.fromName(
communityName: chonks[2], instanceUrl: instanceUrl));
communityName: chonks[2], instanceHost: instanceHost));
}
// CHECK IF REDIRECTS TO A PAGE ON ONE OF ADDED INSTANCES
@ -48,7 +48,7 @@ Future<void> linkLauncher({
if (matchedInstance != null && instances.any((e) => e == match.group(1))) {
if (rest.isEmpty || rest == '/') {
return push(() => InstancePage(instanceUrl: matchedInstance));
return push(() => InstancePage(instanceHost: matchedInstance));
}
final split = rest.split('/');
switch (split[1]) {

View File

@ -1,35 +0,0 @@
import 'package:lemmy_api_client/lemmy_api_client.dart';
import '../cleanup_url.dart';
// Extensions to lemmy api objects which give a [.instanceUrl] getter
// allowing for a convenient way of knowing from which instance did this
// object come from
// TODO: change it to something more robust? regex?
extension GetInstanceCommunityView on CommunityView {
String get instanceUrl => _extract(actorId);
}
extension GetInstanceUserView on UserView {
String get instanceUrl => _extract(actorId);
}
extension GetInstanceCommunityModeratorView on CommunityModeratorView {
String get instanceUrl => _extract(userActorId);
}
extension GetInstancePostView on PostView {
String get instanceUrl => _extract(apId);
}
extension GetInstanceUser on User {
String get instanceUrl => _extract(actorId);
}
extension GetInstanceCommentView on CommentView {
String get instanceUrl => _extract(apId);
}
String _extract(String s) => cleanUpUrl(s.split('/')[2]);

View File

@ -25,41 +25,42 @@ Future<dynamic> goToReplace(
builder: builder,
));
void goToInstance(BuildContext context, String instanceUrl) =>
goTo(context, (context) => InstancePage(instanceUrl: instanceUrl));
void goToInstance(BuildContext context, String instanceHost) =>
goTo(context, (context) => InstancePage(instanceHost: instanceHost));
// ignore: camel_case_types
abstract class goToCommunity {
/// Navigates to `CommunityPage`
static void byId(BuildContext context, String instanceUrl, int communityId) =>
static void byId(
BuildContext context, String instanceHost, int communityId) =>
goTo(
context,
(context) => CommunityPage.fromId(
instanceUrl: instanceUrl, communityId: communityId),
instanceHost: instanceHost, communityId: communityId),
);
static void byName(
BuildContext context, String instanceUrl, String communityName) =>
BuildContext context, String instanceHost, String communityName) =>
goTo(
context,
(context) => CommunityPage.fromName(
instanceUrl: instanceUrl, communityName: communityName),
instanceHost: instanceHost, communityName: communityName),
);
}
// ignore: camel_case_types
abstract class goToUser {
static void byId(BuildContext context, String instanceUrl, int userId) =>
static void byId(BuildContext context, String instanceHost, int userId) =>
goTo(context,
(context) => UserPage(instanceUrl: instanceUrl, userId: userId));
(context) => UserPage(instanceHost: instanceHost, userId: userId));
static void byName(
BuildContext context, String instanceUrl, String userName) =>
BuildContext context, String instanceHost, String userName) =>
throw UnimplementedError('need to create UserProfile constructor first');
}
void goToPost(BuildContext context, String instanceUrl, int postId) => goTo(
context, (context) => FullPostPage(instanceUrl: instanceUrl, id: postId));
void goToPost(BuildContext context, String instanceHost, int postId) => goTo(
context, (context) => FullPostPage(instanceHost: instanceHost, id: postId));
void goToMedia(BuildContext context, String url) => Navigator.push(
context,

View File

@ -1,2 +1,2 @@
String pathToPictrs(String instanceUrl, String imgId) =>
'https://$instanceUrl/pictrs/image/$imgId';
String pathToPictrs(String instanceHost, String imgId) =>
'https://$instanceHost/pictrs/image/$imgId';

View File

@ -11,7 +11,6 @@ import 'package:url_launcher/url_launcher.dart' as ul;
import '../comment_tree.dart';
import '../hooks/delayed_loading.dart';
import '../hooks/logged_in_action.dart';
import '../util/extensions/api.dart';
import '../util/goto.dart';
import '../util/intl.dart';
import '../util/text_color.dart';
@ -75,7 +74,7 @@ class Comment extends HookWidget {
final isDeleted = useState(commentTree.comment.deleted);
final delayedVoting = useDelayedLoading();
final delayedDeletion = useDelayedLoading();
final loggedInAction = useLoggedInAction(commentTree.comment.instanceUrl);
final loggedInAction = useLoggedInAction(commentTree.comment.instanceHost);
final newReplies = useState(const <CommentTree>[]);
final comment = commentTree.comment;
@ -237,7 +236,7 @@ class Comment extends HookWidget {
: Text(commentTree.comment.content)
: MarkdownText(
commentTree.comment.content,
instanceUrl: commentTree.comment.instanceUrl,
instanceHost: commentTree.comment.instanceHost,
selectable: selectable.value,
));
}
@ -305,7 +304,7 @@ class Comment extends HookWidget {
padding: const EdgeInsets.only(right: 5),
child: InkWell(
onTap: () => goToUser.byId(
context, comment.instanceUrl, comment.creatorId),
context, comment.instanceHost, comment.creatorId),
child: CachedNetworkImage(
imageUrl: comment.creatorAvatar,
height: 20,
@ -329,7 +328,7 @@ class Comment extends HookWidget {
color: Theme.of(context).accentColor,
)),
onTap: () => goToUser.byId(
context, comment.instanceUrl, comment.creatorId),
context, comment.instanceHost, comment.creatorId),
),
if (isOP) _CommentTag('OP', Theme.of(context).accentColor),
if (comment.banned) _CommentTag('BANNED', Colors.red),
@ -394,12 +393,12 @@ class _SaveComment extends HookWidget {
@override
Widget build(BuildContext context) {
final loggedInAction = useLoggedInAction(comment.instanceUrl);
final loggedInAction = useLoggedInAction(comment.instanceHost);
final isSaved = useState(comment.saved ?? false);
final delayed = useDelayedLoading(const Duration(milliseconds: 500));
handleSave(Jwt token) async {
final api = LemmyApi(comment.instanceUrl).v1;
final api = LemmyApi(comment.instanceHost).v1;
delayed.start();
try {

View File

@ -8,12 +8,13 @@ import 'fullscreenable_image.dart';
/// A Markdown renderer with link/image handling
class MarkdownText extends StatelessWidget {
final String instanceUrl;
final String instanceHost;
final String text;
final bool selectable;
MarkdownText(this.text, {@required this.instanceUrl, this.selectable = false})
: assert(instanceUrl != null);
MarkdownText(this.text,
{@required this.instanceHost, this.selectable = false})
: assert(instanceHost != null);
@override
Widget build(BuildContext context) => MarkdownBody(
@ -21,7 +22,7 @@ class MarkdownText extends StatelessWidget {
data: text,
extensionSet: md.ExtensionSet.gitHubWeb,
onTapLink: (href) {
linkLauncher(context: context, url: href, instanceUrl: instanceUrl)
linkLauncher(context: context, url: href, instanceHost: instanceHost)
.catchError((e) => Scaffold.of(context).showSnackBar(SnackBar(
content: Row(
children: [

View File

@ -13,7 +13,6 @@ import '../hooks/delayed_loading.dart';
import '../hooks/logged_in_action.dart';
import '../pages/full_post.dart';
import '../url_launcher.dart';
import '../util/extensions/api.dart';
import '../util/goto.dart';
import '../util/more_icon.dart';
import 'bottom_modal.dart';
@ -49,10 +48,10 @@ MediaType whatType(String url) {
/// A post overview card
class Post extends HookWidget {
final PostView post;
final String instanceUrl;
final String instanceHost;
final bool fullPost;
Post(this.post, {this.fullPost = false}) : instanceUrl = post.instanceUrl;
Post(this.post, {this.fullPost = false}) : instanceHost = post.instanceHost;
// == ACTIONS ==
@ -103,8 +102,8 @@ class Post extends HookWidget {
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
void _openLink() =>
linkLauncher(context: context, url: post.url, instanceUrl: instanceUrl);
void _openLink() => linkLauncher(
context: context, url: post.url, instanceHost: instanceHost);
final urlDomain = () {
if (whatType(post.url) == MediaType.none) return null;
@ -127,7 +126,7 @@ class Post extends HookWidget {
padding: const EdgeInsets.only(right: 10),
child: InkWell(
onTap: () => goToCommunity.byId(
context, instanceUrl, post.communityId),
context, instanceHost, post.communityId),
child: SizedBox(
height: 40,
width: 40,
@ -168,16 +167,16 @@ class Post extends HookWidget {
style: TextStyle(fontWeight: FontWeight.w600),
recognizer: TapGestureRecognizer()
..onTap = () => goToCommunity.byId(
context, instanceUrl, post.communityId)),
context, instanceHost, post.communityId)),
TextSpan(
text: '@',
style: TextStyle(fontWeight: FontWeight.w300)),
TextSpan(
text: instanceUrl,
text: instanceHost,
style: TextStyle(fontWeight: FontWeight.w600),
recognizer: TapGestureRecognizer()
..onTap =
() => goToInstance(context, instanceUrl)),
() => goToInstance(context, instanceHost)),
],
),
)
@ -199,7 +198,7 @@ class Post extends HookWidget {
style: TextStyle(fontWeight: FontWeight.w600),
recognizer: TapGestureRecognizer()
..onTap = () => goToUser.byId(
context, post.instanceUrl, post.creatorId),
context, post.instanceHost, post.creatorId),
),
TextSpan(
text:
@ -377,10 +376,7 @@ class Post extends HookWidget {
child: InkWell(
onTap: fullPost
? null
: () => goTo(
context,
(context) =>
FullPostPage.fromPostView(post)), //, instanceUrl, post.id),
: () => goTo(context, (context) => FullPostPage.fromPostView(post)),
child: Column(
children: [
info(),
@ -394,7 +390,7 @@ class Post extends HookWidget {
// TODO: trim content
Padding(
padding: const EdgeInsets.all(10),
child: MarkdownText(post.body, instanceUrl: instanceUrl)),
child: MarkdownText(post.body, instanceHost: instanceHost)),
actions(),
],
),
@ -416,10 +412,10 @@ class _Voting extends HookWidget {
final theme = Theme.of(context);
final myVote = useState(post.myVote ?? VoteType.none);
final loading = useDelayedLoading(Duration(milliseconds: 500));
final loggedInAction = useLoggedInAction(post.instanceUrl);
final loggedInAction = useLoggedInAction(post.instanceHost);
vote(VoteType vote, Jwt token) async {
final api = LemmyApi(post.instanceUrl).v1;
final api = LemmyApi(post.instanceHost).v1;
loading.start();
try {

View File

@ -4,7 +4,6 @@ import 'package:lemmy_api_client/lemmy_api_client.dart';
import '../hooks/delayed_loading.dart';
import '../hooks/logged_in_action.dart';
import '../util/extensions/api.dart';
// TODO: sync this button between post and fullpost. the same with voting
@ -18,10 +17,10 @@ class SavePostButton extends HookWidget {
final isSaved = useState(post.saved ?? false);
final savedIcon = isSaved.value ? Icons.bookmark : Icons.bookmark_border;
final loading = useDelayedLoading(Duration(milliseconds: 500));
final loggedInAction = useLoggedInAction(post.instanceUrl);
final loggedInAction = useLoggedInAction(post.instanceHost);
savePost(Jwt token) async {
final api = LemmyApi(post.instanceUrl).v1;
final api = LemmyApi(post.instanceHost).v1;
loading.start();
try {

View File

@ -6,7 +6,6 @@ import 'package:lemmy_api_client/lemmy_api_client.dart';
import 'package:timeago/timeago.dart' as timeago;
import '../hooks/stores.dart';
import '../util/extensions/api.dart';
import '../util/goto.dart';
import '../util/intl.dart';
import '../util/text_color.dart';
@ -18,15 +17,15 @@ import 'sortable_infinite_list.dart';
/// Shared widget of UserPage and ProfileTab
class UserProfile extends HookWidget {
final Future<UserDetails> _userDetails;
final String instanceUrl;
final String instanceHost;
UserProfile({@required int userId, @required this.instanceUrl})
: _userDetails = LemmyApi(instanceUrl).v1.getUserDetails(
UserProfile({@required int userId, @required this.instanceHost})
: _userDetails = LemmyApi(instanceHost).v1.getUserDetails(
userId: userId, savedOnly: false, sort: SortType.active);
UserProfile.fromUserDetails(UserDetails userDetails)
: _userDetails = Future.value(userDetails),
instanceUrl = userDetails.user.instanceUrl;
instanceHost = userDetails.user.instanceHost;
@override
Widget build(BuildContext context) {
@ -78,7 +77,7 @@ class UserProfile extends HookWidget {
// TODO: first batch is already fetched on render
// TODO: comment and post come from the same endpoint, could be shared
InfinitePostList(
fetcher: (page, batchSize, sort) => LemmyApi(instanceUrl)
fetcher: (page, batchSize, sort) => LemmyApi(instanceHost)
.v1
.getUserDetails(
userId: userView.id,
@ -90,7 +89,7 @@ class UserProfile extends HookWidget {
.then((val) => val.posts),
),
InfiniteCommentList(
fetcher: (page, batchSize, sort) => LemmyApi(instanceUrl)
fetcher: (page, batchSize, sort) => LemmyApi(instanceHost)
.v1
.getUserDetails(
userId: userView.id,
@ -222,9 +221,9 @@ class _UserOverview extends HookWidget {
style: theme.textTheme.caption,
),
InkWell(
onTap: () => goToInstance(context, userView.instanceUrl),
onTap: () => goToInstance(context, userView.instanceHost),
child: Text(
'${userView.instanceUrl}',
'${userView.instanceHost}',
style: theme.textTheme.caption,
),
)
@ -324,12 +323,12 @@ class _AboutTab extends HookWidget {
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final instanceUrl = userDetails.user.instanceUrl;
final instanceHost = userDetails.user.instanceHost;
final accStore = useAccountsStore();
final isOwnedAccount = accStore.loggedInInstances.contains(instanceUrl) &&
accStore.tokens[instanceUrl].containsKey(userDetails.user.name);
final isOwnedAccount = accStore.loggedInInstances.contains(instanceHost) &&
accStore.tokens[instanceHost].containsKey(userDetails.user.name);
const wallPadding = EdgeInsets.symmetric(horizontal: 15);
@ -341,7 +340,7 @@ class _AboutTab extends HookWidget {
communityTile(String name, String icon, int id) => ListTile(
dense: true,
onTap: () => goToCommunity.byId(context, instanceUrl, id),
onTap: () => goToCommunity.byId(context, instanceHost, id),
title: Text('!$name'),
leading: icon != null
? CachedNetworkImage(
@ -379,8 +378,8 @@ class _AboutTab extends HookWidget {
if (userDetails.user.bio != null) ...[
Padding(
padding: wallPadding,
child:
MarkdownText(userDetails.user.bio, instanceUrl: instanceUrl)),
child: MarkdownText(userDetails.user.bio,
instanceHost: instanceHost)),
divider,
],
if (userDetails.moderates.isNotEmpty) ...[

View File

@ -4,7 +4,6 @@ import 'package:lemmy_api_client/lemmy_api_client.dart';
import '../hooks/delayed_loading.dart';
import '../hooks/stores.dart';
import '../util/extensions/api.dart';
import 'markdown_text.dart';
/// Modal for writing a comment to a given post/comment (aka reply)
@ -14,14 +13,14 @@ class WriteComment extends HookWidget {
final PostView post;
final CommentView comment;
final String instanceUrl;
final String instanceHost;
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey();
WriteComment.toPost(this.post)
: instanceUrl = post.instanceUrl,
: instanceHost = post.instanceHost,
comment = null;
WriteComment.toComment(this.comment)
: instanceUrl = comment.instanceUrl,
: instanceHost = comment.instanceHost,
post = null;
@override
@ -34,7 +33,7 @@ class WriteComment extends HookWidget {
final preview = () {
final body = MarkdownText(
comment?.content ?? post.body ?? '',
instanceUrl: instanceUrl,
instanceHost: instanceHost,
);
if (post != null) {
@ -54,9 +53,9 @@ class WriteComment extends HookWidget {
}();
handleSubmit() async {
final api = LemmyApi(instanceUrl).v1;
final api = LemmyApi(instanceHost).v1;
final token = accStore.defaultTokenFor(instanceUrl);
final token = accStore.defaultTokenFor(instanceHost);
delayed.start();
try {
@ -115,7 +114,7 @@ class WriteComment extends HookWidget {
padding: const EdgeInsets.all(16),
child: MarkdownText(
controller.text,
instanceUrl: instanceUrl,
instanceHost: instanceHost,
),
)
],

View File

@ -260,7 +260,7 @@ packages:
name: lemmy_api_client
url: "https://pub.dartlang.org"
source: hosted
version: "0.8.0"
version: "0.8.2"
markdown:
dependency: "direct main"
description:

View File

@ -43,7 +43,7 @@ dependencies:
# utils
timeago: ^2.0.27
fuzzy: <1.0.0
lemmy_api_client: ^0.8.0
lemmy_api_client: ^0.8.2
flutter:
sdk: flutter