Fix federation errors and rename all instanceUrl to instanceHost
This commit is contained in:
parent
a9e5113890
commit
58f964ab66
|
@ -14,13 +14,13 @@ import 'stores.dart';
|
||||||
Function(
|
Function(
|
||||||
Function(Jwt token) action, [
|
Function(Jwt token) action, [
|
||||||
String message,
|
String message,
|
||||||
]) useLoggedInAction(String instanceUrl, {bool any = false}) {
|
]) useLoggedInAction(String instanceHost, {bool any = false}) {
|
||||||
final context = useContext();
|
final context = useContext();
|
||||||
final store = useAccountsStore();
|
final store = useAccountsStore();
|
||||||
|
|
||||||
return (Function(Jwt token) action, [message]) {
|
return (Function(Jwt token) action, [message]) {
|
||||||
if (any && store.hasNoAccount ||
|
if (any && store.hasNoAccount ||
|
||||||
!any && store.isAnonymousFor(instanceUrl)) {
|
!any && store.isAnonymousFor(instanceHost)) {
|
||||||
return () {
|
return () {
|
||||||
Scaffold.of(context).showSnackBar(SnackBar(
|
Scaffold.of(context).showSnackBar(SnackBar(
|
||||||
content: Text(message ?? 'you have to be logged in to do that'),
|
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);
|
return () => action(token);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,10 +13,10 @@ import 'add_instance.dart';
|
||||||
|
|
||||||
/// A modal where an account can be added for a given instance
|
/// A modal where an account can be added for a given instance
|
||||||
class AddAccountPage extends HookWidget {
|
class AddAccountPage extends HookWidget {
|
||||||
final String instanceUrl;
|
final String instanceHost;
|
||||||
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey();
|
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey();
|
||||||
|
|
||||||
AddAccountPage({@required this.instanceUrl}) : assert(instanceUrl != null);
|
AddAccountPage({@required this.instanceHost}) : assert(instanceHost != null);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -29,7 +29,7 @@ class AddAccountPage extends HookWidget {
|
||||||
final accountsStore = useAccountsStore();
|
final accountsStore = useAccountsStore();
|
||||||
|
|
||||||
final loading = useDelayedLoading();
|
final loading = useDelayedLoading();
|
||||||
final selectedInstance = useState(instanceUrl);
|
final selectedInstance = useState(instanceHost);
|
||||||
final icon = useState<String>(null);
|
final icon = useState<String>(null);
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
LemmyApi(selectedInstance.value)
|
LemmyApi(selectedInstance.value)
|
||||||
|
|
|
@ -2,7 +2,6 @@ import 'package:cached_network_image/cached_network_image.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:lemmy_api_client/lemmy_api_client.dart';
|
import 'package:lemmy_api_client/lemmy_api_client.dart';
|
||||||
|
|
||||||
import '../util/extensions/api.dart';
|
|
||||||
import '../util/goto.dart';
|
import '../util/goto.dart';
|
||||||
import '../widgets/markdown_text.dart';
|
import '../widgets/markdown_text.dart';
|
||||||
import '../widgets/sortable_infinite_list.dart';
|
import '../widgets/sortable_infinite_list.dart';
|
||||||
|
@ -44,12 +43,12 @@ class CommunitiesListPage extends StatelessWidget {
|
||||||
opacity: 0.5,
|
opacity: 0.5,
|
||||||
child: MarkdownText(
|
child: MarkdownText(
|
||||||
community.description,
|
community.description,
|
||||||
instanceUrl: community.instanceUrl,
|
instanceHost: community.instanceHost,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
onTap: () => goToCommunity.byId(
|
onTap: () => goToCommunity.byId(
|
||||||
context, community.instanceUrl, community.id),
|
context, community.instanceHost, community.id),
|
||||||
leading: community.icon != null
|
leading: community.icon != null
|
||||||
? CachedNetworkImage(
|
? CachedNetworkImage(
|
||||||
height: 50,
|
height: 50,
|
||||||
|
|
|
@ -32,8 +32,8 @@ class CommunitiesTab extends HookWidget {
|
||||||
final instancesSnap = useMemoFuture(() {
|
final instancesSnap = useMemoFuture(() {
|
||||||
final futures = accountsStore.loggedInInstances
|
final futures = accountsStore.loggedInInstances
|
||||||
.map(
|
.map(
|
||||||
(instanceUrl) =>
|
(instanceHost) =>
|
||||||
LemmyApi(instanceUrl).v1.getSite().then((e) => e.site),
|
LemmyApi(instanceHost).v1.getSite().then((e) => e.site),
|
||||||
)
|
)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
|
@ -42,12 +42,13 @@ class CommunitiesTab extends HookWidget {
|
||||||
final communitiesSnap = useMemoFuture(() {
|
final communitiesSnap = useMemoFuture(() {
|
||||||
final futures = accountsStore.loggedInInstances
|
final futures = accountsStore.loggedInInstances
|
||||||
.map(
|
.map(
|
||||||
(instanceUrl) => LemmyApi(instanceUrl)
|
(instanceHost) => LemmyApi(instanceHost)
|
||||||
.v1
|
.v1
|
||||||
.getUserDetails(
|
.getUserDetails(
|
||||||
sort: SortType.active,
|
sort: SortType.active,
|
||||||
savedOnly: false,
|
savedOnly: false,
|
||||||
userId: accountsStore.defaultTokenFor(instanceUrl).payload.id,
|
userId:
|
||||||
|
accountsStore.defaultTokenFor(instanceHost).payload.id,
|
||||||
)
|
)
|
||||||
.then((e) => e.follows),
|
.then((e) => e.follows),
|
||||||
)
|
)
|
||||||
|
@ -208,7 +209,7 @@ class CommunitiesTab extends HookWidget {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
trailing: _CommunitySubscribeToggle(
|
trailing: _CommunitySubscribeToggle(
|
||||||
instanceUrl: comm.communityActorId.split('/')[2],
|
instanceHost: comm.communityActorId.split('/')[2],
|
||||||
communityId: comm.communityId,
|
communityId: comm.communityId,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -223,11 +224,11 @@ class CommunitiesTab extends HookWidget {
|
||||||
|
|
||||||
class _CommunitySubscribeToggle extends HookWidget {
|
class _CommunitySubscribeToggle extends HookWidget {
|
||||||
final int communityId;
|
final int communityId;
|
||||||
final String instanceUrl;
|
final String instanceHost;
|
||||||
|
|
||||||
_CommunitySubscribeToggle(
|
_CommunitySubscribeToggle(
|
||||||
{@required this.instanceUrl, @required this.communityId})
|
{@required this.instanceHost, @required this.communityId})
|
||||||
: assert(instanceUrl != null),
|
: assert(instanceHost != null),
|
||||||
assert(communityId != null);
|
assert(communityId != null);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -241,10 +242,10 @@ class _CommunitySubscribeToggle extends HookWidget {
|
||||||
delayed.start();
|
delayed.start();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await LemmyApi(instanceUrl).v1.followCommunity(
|
await LemmyApi(instanceHost).v1.followCommunity(
|
||||||
communityId: communityId,
|
communityId: communityId,
|
||||||
follow: !subbed.value,
|
follow: !subbed.value,
|
||||||
auth: accountsStore.defaultTokenFor(instanceUrl).raw,
|
auth: accountsStore.defaultTokenFor(instanceHost).raw,
|
||||||
);
|
);
|
||||||
subbed.value = !subbed.value;
|
subbed.value = !subbed.value;
|
||||||
} on Exception catch (err) {
|
} on Exception catch (err) {
|
||||||
|
|
|
@ -10,7 +10,6 @@ import '../hooks/delayed_loading.dart';
|
||||||
import '../hooks/logged_in_action.dart';
|
import '../hooks/logged_in_action.dart';
|
||||||
import '../hooks/memo_future.dart';
|
import '../hooks/memo_future.dart';
|
||||||
import '../hooks/stores.dart';
|
import '../hooks/stores.dart';
|
||||||
import '../util/extensions/api.dart';
|
|
||||||
import '../util/goto.dart';
|
import '../util/goto.dart';
|
||||||
import '../util/intl.dart';
|
import '../util/intl.dart';
|
||||||
import '../util/more_icon.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
|
/// Displays posts, comments, and general info about the given community
|
||||||
class CommunityPage extends HookWidget {
|
class CommunityPage extends HookWidget {
|
||||||
final CommunityView _community;
|
final CommunityView _community;
|
||||||
final String instanceUrl;
|
final String instanceHost;
|
||||||
final String communityName;
|
final String communityName;
|
||||||
final int communityId;
|
final int communityId;
|
||||||
|
|
||||||
CommunityPage.fromName({
|
CommunityPage.fromName({
|
||||||
@required this.communityName,
|
@required this.communityName,
|
||||||
@required this.instanceUrl,
|
@required this.instanceHost,
|
||||||
}) : assert(communityName != null),
|
}) : assert(communityName != null),
|
||||||
assert(instanceUrl != null),
|
assert(instanceHost != null),
|
||||||
communityId = null,
|
communityId = null,
|
||||||
_community = null;
|
_community = null;
|
||||||
CommunityPage.fromId({
|
CommunityPage.fromId({
|
||||||
@required this.communityId,
|
@required this.communityId,
|
||||||
@required this.instanceUrl,
|
@required this.instanceHost,
|
||||||
}) : assert(communityId != null),
|
}) : assert(communityId != null),
|
||||||
assert(instanceUrl != null),
|
assert(instanceHost != null),
|
||||||
communityName = null,
|
communityName = null,
|
||||||
_community = null;
|
_community = null;
|
||||||
CommunityPage.fromCommunityView(this._community)
|
CommunityPage.fromCommunityView(this._community)
|
||||||
: instanceUrl = _community.instanceUrl,
|
: instanceHost = _community.instanceHost,
|
||||||
communityId = _community.id,
|
communityId = _community.id,
|
||||||
communityName = _community.name;
|
communityName = _community.name;
|
||||||
|
|
||||||
|
@ -54,15 +53,15 @@ class CommunityPage extends HookWidget {
|
||||||
final accountsStore = useAccountsStore();
|
final accountsStore = useAccountsStore();
|
||||||
|
|
||||||
final fullCommunitySnap = useMemoFuture(() {
|
final fullCommunitySnap = useMemoFuture(() {
|
||||||
final token = accountsStore.defaultTokenFor(instanceUrl);
|
final token = accountsStore.defaultTokenFor(instanceHost);
|
||||||
|
|
||||||
if (communityId != null) {
|
if (communityId != null) {
|
||||||
return LemmyApi(instanceUrl).v1.getCommunity(
|
return LemmyApi(instanceHost).v1.getCommunity(
|
||||||
id: communityId,
|
id: communityId,
|
||||||
auth: token?.raw,
|
auth: token?.raw,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return LemmyApi(instanceUrl).v1.getCommunity(
|
return LemmyApi(instanceHost).v1.getCommunity(
|
||||||
name: communityName,
|
name: communityName,
|
||||||
auth: token?.raw,
|
auth: token?.raw,
|
||||||
);
|
);
|
||||||
|
@ -169,7 +168,7 @@ class CommunityPage extends HookWidget {
|
||||||
],
|
],
|
||||||
flexibleSpace: FlexibleSpaceBar(
|
flexibleSpace: FlexibleSpaceBar(
|
||||||
background:
|
background:
|
||||||
_CommunityOverview(community, instanceUrl: instanceUrl),
|
_CommunityOverview(community, instanceHost: instanceHost),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SliverPersistentHeader(
|
SliverPersistentHeader(
|
||||||
|
@ -191,7 +190,7 @@ class CommunityPage extends HookWidget {
|
||||||
children: [
|
children: [
|
||||||
InfinitePostList(
|
InfinitePostList(
|
||||||
fetcher: (page, batchSize, sort) =>
|
fetcher: (page, batchSize, sort) =>
|
||||||
LemmyApi(community.instanceUrl).v1.getPosts(
|
LemmyApi(community.instanceHost).v1.getPosts(
|
||||||
type: PostListingType.community,
|
type: PostListingType.community,
|
||||||
sort: sort,
|
sort: sort,
|
||||||
communityId: community.id,
|
communityId: community.id,
|
||||||
|
@ -201,10 +200,10 @@ class CommunityPage extends HookWidget {
|
||||||
),
|
),
|
||||||
InfiniteCommentList(
|
InfiniteCommentList(
|
||||||
fetcher: (page, batchSize, sortType) =>
|
fetcher: (page, batchSize, sortType) =>
|
||||||
LemmyApi(community.instanceUrl).v1.getComments(
|
LemmyApi(community.instanceHost).v1.getComments(
|
||||||
communityId: community.id,
|
communityId: community.id,
|
||||||
auth: accountsStore
|
auth: accountsStore
|
||||||
.defaultTokenFor(community.instanceUrl)
|
.defaultTokenFor(community.instanceHost)
|
||||||
?.raw,
|
?.raw,
|
||||||
type: CommentListingType.community,
|
type: CommentListingType.community,
|
||||||
sort: sortType,
|
sort: sortType,
|
||||||
|
@ -225,12 +224,12 @@ class CommunityPage extends HookWidget {
|
||||||
|
|
||||||
class _CommunityOverview extends StatelessWidget {
|
class _CommunityOverview extends StatelessWidget {
|
||||||
final CommunityView community;
|
final CommunityView community;
|
||||||
final String instanceUrl;
|
final String instanceHost;
|
||||||
|
|
||||||
_CommunityOverview(
|
_CommunityOverview(
|
||||||
this.community, {
|
this.community, {
|
||||||
@required this.instanceUrl,
|
@required this.instanceHost,
|
||||||
}) : assert(instanceUrl != null),
|
}) : assert(instanceHost != null),
|
||||||
assert(goToInstance != null);
|
assert(goToInstance != null);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -316,10 +315,10 @@ class _CommunityOverview extends StatelessWidget {
|
||||||
text: '@',
|
text: '@',
|
||||||
style: TextStyle(fontWeight: FontWeight.w200)),
|
style: TextStyle(fontWeight: FontWeight.w200)),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: instanceUrl,
|
text: instanceHost,
|
||||||
style: TextStyle(fontWeight: FontWeight.w600),
|
style: TextStyle(fontWeight: FontWeight.w600),
|
||||||
recognizer: TapGestureRecognizer()
|
recognizer: TapGestureRecognizer()
|
||||||
..onTap = () => goToInstance(context, instanceUrl)),
|
..onTap = () => goToInstance(context, instanceHost)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -423,7 +422,7 @@ class _AboutTab extends StatelessWidget {
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 15),
|
padding: const EdgeInsets.symmetric(horizontal: 15),
|
||||||
child: MarkdownText(community.description,
|
child: MarkdownText(community.description,
|
||||||
instanceUrl: community.instanceUrl),
|
instanceHost: community.instanceHost),
|
||||||
),
|
),
|
||||||
_Divider(),
|
_Divider(),
|
||||||
],
|
],
|
||||||
|
@ -480,7 +479,7 @@ class _AboutTab extends StatelessWidget {
|
||||||
for (final mod in moderators)
|
for (final mod in moderators)
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(mod.userPreferredUsername ?? '@${mod.userName}'),
|
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 isSubbed = useState(community.subscribed ?? false);
|
||||||
final delayed = useDelayedLoading(const Duration(milliseconds: 500));
|
final delayed = useDelayedLoading(const Duration(milliseconds: 500));
|
||||||
final loggedInAction = useLoggedInAction(community.instanceUrl);
|
final loggedInAction = useLoggedInAction(community.instanceHost);
|
||||||
|
|
||||||
final colorOnTopOfAccent = textColorBasedOnBackground(theme.accentColor);
|
final colorOnTopOfAccent = textColorBasedOnBackground(theme.accentColor);
|
||||||
|
|
||||||
subscribe(Jwt token) async {
|
subscribe(Jwt token) async {
|
||||||
delayed.start();
|
delayed.start();
|
||||||
try {
|
try {
|
||||||
await LemmyApi(community.instanceUrl).v1.followCommunity(
|
await LemmyApi(community.instanceHost).v1.followCommunity(
|
||||||
communityId: community.id,
|
communityId: community.id,
|
||||||
follow: !isSubbed.value,
|
follow: !isSubbed.value,
|
||||||
auth: token.raw);
|
auth: token.raw);
|
||||||
|
|
|
@ -9,7 +9,6 @@ import '../hooks/image_picker.dart';
|
||||||
import '../hooks/logged_in_action.dart';
|
import '../hooks/logged_in_action.dart';
|
||||||
import '../hooks/memo_future.dart';
|
import '../hooks/memo_future.dart';
|
||||||
import '../hooks/stores.dart';
|
import '../hooks/stores.dart';
|
||||||
import '../util/extensions/api.dart';
|
|
||||||
import '../util/extensions/spaced.dart';
|
import '../util/extensions/spaced.dart';
|
||||||
import '../util/goto.dart';
|
import '../util/goto.dart';
|
||||||
import '../util/pictrs.dart';
|
import '../util/pictrs.dart';
|
||||||
|
@ -46,7 +45,7 @@ class CreatePost extends HookWidget {
|
||||||
final bodyController = useTextEditingController();
|
final bodyController = useTextEditingController();
|
||||||
final accStore = useAccountsStore();
|
final accStore = useAccountsStore();
|
||||||
final selectedInstance =
|
final selectedInstance =
|
||||||
useState(community?.instanceUrl ?? accStore.loggedInInstances.first);
|
useState(community?.instanceHost ?? accStore.loggedInInstances.first);
|
||||||
final selectedCommunity = useState(community);
|
final selectedCommunity = useState(community);
|
||||||
final showFancy = useState(false);
|
final showFancy = useState(false);
|
||||||
final nsfw = useState(false);
|
final nsfw = useState(false);
|
||||||
|
@ -203,7 +202,7 @@ class CreatePost extends HookWidget {
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
child: MarkdownText(
|
child: MarkdownText(
|
||||||
bodyController.text,
|
bodyController.text,
|
||||||
instanceUrl: selectedInstance.value,
|
instanceHost: selectedInstance.value,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -7,7 +7,6 @@ import 'package:lemmy_api_client/lemmy_api_client.dart';
|
||||||
import '../hooks/logged_in_action.dart';
|
import '../hooks/logged_in_action.dart';
|
||||||
import '../hooks/memo_future.dart';
|
import '../hooks/memo_future.dart';
|
||||||
import '../hooks/stores.dart';
|
import '../hooks/stores.dart';
|
||||||
import '../util/extensions/api.dart';
|
|
||||||
import '../util/more_icon.dart';
|
import '../util/more_icon.dart';
|
||||||
import '../widgets/comment_section.dart';
|
import '../widgets/comment_section.dart';
|
||||||
import '../widgets/post.dart';
|
import '../widgets/post.dart';
|
||||||
|
@ -17,24 +16,24 @@ import '../widgets/write_comment.dart';
|
||||||
/// Displays a post with its comment section
|
/// Displays a post with its comment section
|
||||||
class FullPostPage extends HookWidget {
|
class FullPostPage extends HookWidget {
|
||||||
final int id;
|
final int id;
|
||||||
final String instanceUrl;
|
final String instanceHost;
|
||||||
final PostView post;
|
final PostView post;
|
||||||
|
|
||||||
FullPostPage({@required this.id, @required this.instanceUrl})
|
FullPostPage({@required this.id, @required this.instanceHost})
|
||||||
: assert(id != null),
|
: assert(id != null),
|
||||||
assert(instanceUrl != null),
|
assert(instanceHost != null),
|
||||||
post = null;
|
post = null;
|
||||||
FullPostPage.fromPostView(this.post)
|
FullPostPage.fromPostView(this.post)
|
||||||
: id = post.id,
|
: id = post.id,
|
||||||
instanceUrl = post.instanceUrl;
|
instanceHost = post.instanceHost;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final accStore = useAccountsStore();
|
final accStore = useAccountsStore();
|
||||||
final fullPostSnap = useMemoFuture(() => LemmyApi(instanceUrl)
|
final fullPostSnap = useMemoFuture(() => LemmyApi(instanceHost)
|
||||||
.v1
|
.v1
|
||||||
.getPost(id: id, auth: accStore.defaultTokenFor(instanceUrl)?.raw));
|
.getPost(id: id, auth: accStore.defaultTokenFor(instanceHost)?.raw));
|
||||||
final loggedInAction = useLoggedInAction(instanceUrl);
|
final loggedInAction = useLoggedInAction(instanceHost);
|
||||||
final newComments = useState(const <CommentView>[]);
|
final newComments = useState(const <CommentView>[]);
|
||||||
|
|
||||||
// FALLBACK VIEW
|
// FALLBACK VIEW
|
||||||
|
|
|
@ -118,10 +118,10 @@ class HomeTab extends HookWidget {
|
||||||
? () => showCupertinoModalPopup(
|
? () => showCupertinoModalPopup(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (_) =>
|
builder: (_) =>
|
||||||
AddAccountPage(instanceUrl: instance))
|
AddAccountPage(instanceHost: instance))
|
||||||
: () => pop(_SelectedList(
|
: () => pop(_SelectedList(
|
||||||
listingType: PostListingType.subscribed,
|
listingType: PostListingType.subscribed,
|
||||||
instanceUrl: instance,
|
instanceHost: instance,
|
||||||
)),
|
)),
|
||||||
leading: SizedBox(width: 20),
|
leading: SizedBox(width: 20),
|
||||||
),
|
),
|
||||||
|
@ -129,7 +129,7 @@ class HomeTab extends HookWidget {
|
||||||
title: Text('All'),
|
title: Text('All'),
|
||||||
onTap: () => pop(_SelectedList(
|
onTap: () => pop(_SelectedList(
|
||||||
listingType: PostListingType.all,
|
listingType: PostListingType.all,
|
||||||
instanceUrl: instance,
|
instanceHost: instance,
|
||||||
)),
|
)),
|
||||||
leading: SizedBox(width: 20),
|
leading: SizedBox(width: 20),
|
||||||
),
|
),
|
||||||
|
@ -149,9 +149,9 @@ class HomeTab extends HookWidget {
|
||||||
final first = selectedList.value.listingType == PostListingType.subscribed
|
final first = selectedList.value.listingType == PostListingType.subscribed
|
||||||
? 'Subscribed'
|
? 'Subscribed'
|
||||||
: 'All';
|
: 'All';
|
||||||
final last = selectedList.value.instanceUrl == null
|
final last = selectedList.value.instanceHost == null
|
||||||
? ''
|
? ''
|
||||||
: '@${selectedList.value.instanceUrl}';
|
: '@${selectedList.value.instanceHost}';
|
||||||
return '$first$last';
|
return '$first$last';
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
@ -256,12 +256,12 @@ class InfiniteHomeList extends HookWidget {
|
||||||
}();
|
}();
|
||||||
|
|
||||||
final futures =
|
final futures =
|
||||||
instances.map((instanceUrl) => LemmyApi(instanceUrl).v1.getPosts(
|
instances.map((instanceHost) => LemmyApi(instanceHost).v1.getPosts(
|
||||||
type: listingType,
|
type: listingType,
|
||||||
sort: sort,
|
sort: sort,
|
||||||
page: page,
|
page: page,
|
||||||
limit: limit,
|
limit: limit,
|
||||||
auth: accStore.defaultTokenFor(instanceUrl)?.raw,
|
auth: accStore.defaultTokenFor(instanceHost)?.raw,
|
||||||
));
|
));
|
||||||
final posts = await Future.wait(futures);
|
final posts = await Future.wait(futures);
|
||||||
final newPosts = <PostView>[];
|
final newPosts = <PostView>[];
|
||||||
|
@ -277,13 +277,13 @@ class InfiniteHomeList extends HookWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<PostView>> Function(int, int) fetcherFromInstance(
|
Future<List<PostView>> Function(int, int) fetcherFromInstance(
|
||||||
String instanceUrl, PostListingType listingType, SortType sort) =>
|
String instanceHost, PostListingType listingType, SortType sort) =>
|
||||||
(page, batchSize) => LemmyApi(instanceUrl).v1.getPosts(
|
(page, batchSize) => LemmyApi(instanceHost).v1.getPosts(
|
||||||
type: listingType,
|
type: listingType,
|
||||||
sort: sort,
|
sort: sort,
|
||||||
page: page,
|
page: page,
|
||||||
limit: batchSize,
|
limit: batchSize,
|
||||||
auth: accStore.defaultTokenFor(instanceUrl)?.raw,
|
auth: accStore.defaultTokenFor(instanceHost)?.raw,
|
||||||
);
|
);
|
||||||
|
|
||||||
return InfiniteScroll<PostView>(
|
return InfiniteScroll<PostView>(
|
||||||
|
@ -303,11 +303,11 @@ class InfiniteHomeList extends HookWidget {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
fetchMore: selectedList.instanceUrl == null
|
fetchMore: selectedList.instanceHost == null
|
||||||
? (page, limit) =>
|
? (page, limit) =>
|
||||||
generalFetcher(page, limit, sort.value, selectedList.listingType)
|
generalFetcher(page, limit, sort.value, selectedList.listingType)
|
||||||
: fetcherFromInstance(
|
: fetcherFromInstance(
|
||||||
selectedList.instanceUrl,
|
selectedList.instanceHost,
|
||||||
selectedList.listingType,
|
selectedList.listingType,
|
||||||
sort.value,
|
sort.value,
|
||||||
),
|
),
|
||||||
|
@ -318,13 +318,13 @@ class InfiniteHomeList extends HookWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _SelectedList {
|
class _SelectedList {
|
||||||
final String instanceUrl;
|
final String instanceHost;
|
||||||
final PostListingType listingType;
|
final PostListingType listingType;
|
||||||
_SelectedList({
|
_SelectedList({
|
||||||
@required this.listingType,
|
@required this.listingType,
|
||||||
this.instanceUrl,
|
this.instanceHost,
|
||||||
});
|
});
|
||||||
|
|
||||||
String toString() =>
|
String toString() =>
|
||||||
'SelectedList({instanceUrl: $instanceUrl, listingType: $listingType})';
|
'SelectedList({instanceHost: $instanceHost, listingType: $listingType})';
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:lemmy_api_client/lemmy_api_client.dart';
|
import 'package:lemmy_api_client/lemmy_api_client.dart';
|
||||||
|
|
||||||
import '../hooks/stores.dart';
|
import '../hooks/stores.dart';
|
||||||
import '../util/extensions/api.dart';
|
|
||||||
import '../util/goto.dart';
|
import '../util/goto.dart';
|
||||||
import '../util/more_icon.dart';
|
import '../util/more_icon.dart';
|
||||||
import '../util/text_color.dart';
|
import '../util/text_color.dart';
|
||||||
|
@ -20,18 +19,18 @@ import 'users_list.dart';
|
||||||
|
|
||||||
/// Displays posts, comments, and general info about the given instance
|
/// Displays posts, comments, and general info about the given instance
|
||||||
class InstancePage extends HookWidget {
|
class InstancePage extends HookWidget {
|
||||||
final String instanceUrl;
|
final String instanceHost;
|
||||||
final Future<FullSiteView> siteFuture;
|
final Future<FullSiteView> siteFuture;
|
||||||
final Future<List<CommunityView>> communitiesFuture;
|
final Future<List<CommunityView>> communitiesFuture;
|
||||||
|
|
||||||
void _share() =>
|
void _share() =>
|
||||||
Share.text('Share instance', 'https://$instanceUrl', 'text/plain');
|
Share.text('Share instance', 'https://$instanceHost', 'text/plain');
|
||||||
|
|
||||||
InstancePage({@required this.instanceUrl})
|
InstancePage({@required this.instanceHost})
|
||||||
: assert(instanceUrl != null),
|
: assert(instanceHost != null),
|
||||||
siteFuture = LemmyApi(instanceUrl).v1.getSite(),
|
siteFuture = LemmyApi(instanceHost).v1.getSite(),
|
||||||
communitiesFuture =
|
communitiesFuture =
|
||||||
LemmyApi(instanceUrl).v1.listCommunities(sort: SortType.hot);
|
LemmyApi(instanceHost).v1.listCommunities(sort: SortType.hot);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -70,7 +69,7 @@ class InstancePage extends HookWidget {
|
||||||
|
|
||||||
void _openMoreMenu(BuildContext c) {
|
void _openMoreMenu(BuildContext c) {
|
||||||
showInfoTablePopup(context, {
|
showInfoTablePopup(context, {
|
||||||
'url': instanceUrl,
|
'url': instanceHost,
|
||||||
'creator': '@${site.site.creatorName}',
|
'creator': '@${site.site.creatorName}',
|
||||||
'version': site.version,
|
'version': site.version,
|
||||||
'enableDownvotes': site.site.enableDownvotes,
|
'enableDownvotes': site.site.enableDownvotes,
|
||||||
|
@ -132,7 +131,7 @@ class InstancePage extends HookWidget {
|
||||||
),
|
),
|
||||||
Text(site.site.name,
|
Text(site.site.name,
|
||||||
style: theme.textTheme.headline6),
|
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: [
|
children: [
|
||||||
InfinitePostList(
|
InfinitePostList(
|
||||||
fetcher: (page, batchSize, sort) =>
|
fetcher: (page, batchSize, sort) =>
|
||||||
LemmyApi(instanceUrl).v1.getPosts(
|
LemmyApi(instanceHost).v1.getPosts(
|
||||||
// TODO: switch between all and subscribed
|
// TODO: switch between all and subscribed
|
||||||
type: PostListingType.all,
|
type: PostListingType.all,
|
||||||
sort: sort,
|
sort: sort,
|
||||||
limit: batchSize,
|
limit: batchSize,
|
||||||
page: page,
|
page: page,
|
||||||
auth: accStore.defaultTokenFor(instanceUrl)?.raw,
|
auth: accStore.defaultTokenFor(instanceHost)?.raw,
|
||||||
)),
|
)),
|
||||||
InfiniteCommentList(
|
InfiniteCommentList(
|
||||||
fetcher: (page, batchSize, sort) =>
|
fetcher: (page, batchSize, sort) =>
|
||||||
LemmyApi(instanceUrl).v1.getComments(
|
LemmyApi(instanceHost).v1.getComments(
|
||||||
type: CommentListingType.all,
|
type: CommentListingType.all,
|
||||||
sort: sort,
|
sort: sort,
|
||||||
limit: batchSize,
|
limit: batchSize,
|
||||||
page: page,
|
page: page,
|
||||||
auth: accStore.defaultTokenFor(instanceUrl)?.raw,
|
auth: accStore.defaultTokenFor(instanceHost)?.raw,
|
||||||
)),
|
)),
|
||||||
_AboutTab(site,
|
_AboutTab(site,
|
||||||
communitiesFuture: communitiesFuture,
|
communitiesFuture: communitiesFuture,
|
||||||
instanceUrl: instanceUrl),
|
instanceHost: instanceHost),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -211,12 +210,12 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
|
||||||
class _AboutTab extends HookWidget {
|
class _AboutTab extends HookWidget {
|
||||||
final FullSiteView site;
|
final FullSiteView site;
|
||||||
final Future<List<CommunityView>> communitiesFuture;
|
final Future<List<CommunityView>> communitiesFuture;
|
||||||
final String instanceUrl;
|
final String instanceHost;
|
||||||
|
|
||||||
const _AboutTab(this.site,
|
const _AboutTab(this.site,
|
||||||
{@required this.communitiesFuture, @required this.instanceUrl})
|
{@required this.communitiesFuture, @required this.instanceHost})
|
||||||
: assert(communitiesFuture != null),
|
: assert(communitiesFuture != null),
|
||||||
assert(instanceUrl != null);
|
assert(instanceHost != null);
|
||||||
|
|
||||||
void goToUser(int id) {
|
void goToUser(int id) {
|
||||||
print('GO TO USER $id');
|
print('GO TO USER $id');
|
||||||
|
@ -245,11 +244,11 @@ class _AboutTab extends HookWidget {
|
||||||
context,
|
context,
|
||||||
(_) => CommunitiesListPage(
|
(_) => CommunitiesListPage(
|
||||||
fetcher: (page, batchSize, sortType) =>
|
fetcher: (page, batchSize, sortType) =>
|
||||||
LemmyApi(instanceUrl).v1.listCommunities(
|
LemmyApi(instanceHost).v1.listCommunities(
|
||||||
sort: sortType,
|
sort: sortType,
|
||||||
limit: batchSize,
|
limit: batchSize,
|
||||||
page: page,
|
page: page,
|
||||||
auth: accStore.defaultTokenFor(instanceUrl)?.raw,
|
auth: accStore.defaultTokenFor(instanceHost)?.raw,
|
||||||
),
|
),
|
||||||
title: 'Communities of ${site.site.name}',
|
title: 'Communities of ${site.site.name}',
|
||||||
),
|
),
|
||||||
|
@ -265,7 +264,7 @@ class _AboutTab extends HookWidget {
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15),
|
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15),
|
||||||
child: MarkdownText(
|
child: MarkdownText(
|
||||||
site.site.description,
|
site.site.description,
|
||||||
instanceUrl: instanceUrl,
|
instanceHost: instanceHost,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
_Divider(),
|
_Divider(),
|
||||||
|
@ -296,7 +295,7 @@ class _AboutTab extends HookWidget {
|
||||||
if (commSnap.hasData)
|
if (commSnap.hasData)
|
||||||
...commSnap.data.take(6).map((e) => ListTile(
|
...commSnap.data.take(6).map((e) => ListTile(
|
||||||
onTap: () =>
|
onTap: () =>
|
||||||
goToCommunity.byId(context, e.instanceUrl, e.id),
|
goToCommunity.byId(context, e.instanceHost, e.id),
|
||||||
title: Text(e.name),
|
title: Text(e.name),
|
||||||
leading: e.icon != null
|
leading: e.icon != null
|
||||||
? CachedNetworkImage(
|
? CachedNetworkImage(
|
||||||
|
@ -345,7 +344,7 @@ class _AboutTab extends HookWidget {
|
||||||
? '@${e.name}'
|
? '@${e.name}'
|
||||||
: e.preferredUsername),
|
: e.preferredUsername),
|
||||||
subtitle: e.bio != null
|
subtitle: e.bio != null
|
||||||
? MarkdownText(e.bio, instanceUrl: instanceUrl)
|
? MarkdownText(e.bio, instanceHost: instanceHost)
|
||||||
: null,
|
: null,
|
||||||
onTap: () => goToUser(e.id),
|
onTap: () => goToUser(e.id),
|
||||||
leading: e.avatar != null
|
leading: e.avatar != null
|
||||||
|
|
|
@ -85,9 +85,9 @@ class UserProfileTab extends HookWidget {
|
||||||
builder: (ctx) {
|
builder: (ctx) {
|
||||||
final userTags = <String>[];
|
final userTags = <String>[];
|
||||||
|
|
||||||
accountsStore.tokens.forEach((instanceUrl, value) {
|
accountsStore.tokens.forEach((instanceHost, value) {
|
||||||
value.forEach((username, _) {
|
value.forEach((username, _) {
|
||||||
userTags.add('$username@$instanceUrl');
|
userTags.add('$username@$instanceHost');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ class UserProfileTab extends HookWidget {
|
||||||
value: tag,
|
value: tag,
|
||||||
title: Text(tag),
|
title: Text(tag),
|
||||||
groupValue: '${accountsStore.defaultUsername}'
|
groupValue: '${accountsStore.defaultUsername}'
|
||||||
'@${accountsStore.defaultInstanceUrl}',
|
'@${accountsStore.defaultInstanceHost}',
|
||||||
onChanged: (selected) {
|
onChanged: (selected) {
|
||||||
final userTag = selected.split('@');
|
final userTag = selected.split('@');
|
||||||
accountsStore.setDefaultAccount(
|
accountsStore.setDefaultAccount(
|
||||||
|
@ -119,7 +119,7 @@ class UserProfileTab extends HookWidget {
|
||||||
),
|
),
|
||||||
body: UserProfile(
|
body: UserProfile(
|
||||||
userId: accountsStore.defaultToken.payload.id,
|
userId: accountsStore.defaultToken.payload.id,
|
||||||
instanceUrl: accountsStore.defaultInstanceUrl,
|
instanceHost: accountsStore.defaultInstanceHost,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,12 +99,12 @@ class AccountsConfigPage extends HookWidget {
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
final accountsStore = useAccountsStore();
|
final accountsStore = useAccountsStore();
|
||||||
|
|
||||||
removeInstanceDialog(String instanceUrl) async {
|
removeInstanceDialog(String instanceHost) async {
|
||||||
if (await showDialog<bool>(
|
if (await showDialog<bool>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => AlertDialog(
|
builder: (context) => AlertDialog(
|
||||||
title: Text('Remove instance?'),
|
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: [
|
actions: [
|
||||||
FlatButton(
|
FlatButton(
|
||||||
child: Text('no'),
|
child: Text('no'),
|
||||||
|
@ -118,17 +118,17 @@ class AccountsConfigPage extends HookWidget {
|
||||||
),
|
),
|
||||||
) ??
|
) ??
|
||||||
false) {
|
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>(
|
if (await showDialog<bool>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => AlertDialog(
|
builder: (context) => AlertDialog(
|
||||||
title: Text('Remove user?'),
|
title: Text('Remove user?'),
|
||||||
content: Text(
|
content: Text(
|
||||||
'Are you sure you want to remove $username@$instanceUrl?'),
|
'Are you sure you want to remove $username@$instanceHost?'),
|
||||||
actions: [
|
actions: [
|
||||||
FlatButton(
|
FlatButton(
|
||||||
child: Text('no'),
|
child: Text('no'),
|
||||||
|
@ -142,7 +142,7 @@ class AccountsConfigPage extends HookWidget {
|
||||||
),
|
),
|
||||||
) ??
|
) ??
|
||||||
false) {
|
false) {
|
||||||
accountsStore.removeAccount(instanceUrl, username);
|
accountsStore.removeAccount(instanceHost, username);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ class AccountsConfigPage extends HookWidget {
|
||||||
onTap: () => showCupertinoModalPopup(
|
onTap: () => showCupertinoModalPopup(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (_) =>
|
builder: (_) =>
|
||||||
AddAccountPage(instanceUrl: accountsStore.instances.last)),
|
AddAccountPage(instanceHost: accountsStore.instances.last)),
|
||||||
),
|
),
|
||||||
SpeedDialChild(
|
SpeedDialChild(
|
||||||
child: Icon(Icons.dns),
|
child: Icon(Icons.dns),
|
||||||
|
@ -263,7 +263,7 @@ class AccountsConfigPage extends HookWidget {
|
||||||
onTap: () {
|
onTap: () {
|
||||||
showCupertinoModalPopup(
|
showCupertinoModalPopup(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (_) => AddAccountPage(instanceUrl: entry.key));
|
builder: (_) => AddAccountPage(instanceHost: entry.key));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -8,20 +8,20 @@ import '../widgets/user_profile.dart';
|
||||||
/// Page showing posts, comments, and general info about a user.
|
/// Page showing posts, comments, and general info about a user.
|
||||||
class UserPage extends HookWidget {
|
class UserPage extends HookWidget {
|
||||||
final int userId;
|
final int userId;
|
||||||
final String instanceUrl;
|
final String instanceHost;
|
||||||
final Future<UserDetails> _userDetails;
|
final Future<UserDetails> _userDetails;
|
||||||
|
|
||||||
UserPage({@required this.userId, @required this.instanceUrl})
|
UserPage({@required this.userId, @required this.instanceHost})
|
||||||
: assert(userId != null),
|
: assert(userId != null),
|
||||||
assert(instanceUrl != null),
|
assert(instanceHost != null),
|
||||||
_userDetails = LemmyApi(instanceUrl).v1.getUserDetails(
|
_userDetails = LemmyApi(instanceHost).v1.getUserDetails(
|
||||||
userId: userId, savedOnly: true, sort: SortType.active);
|
userId: userId, savedOnly: true, sort: SortType.active);
|
||||||
|
|
||||||
UserPage.fromName({@required this.instanceUrl, @required String username})
|
UserPage.fromName({@required this.instanceHost, @required String username})
|
||||||
: assert(instanceUrl != null),
|
: assert(instanceHost != null),
|
||||||
assert(username != null),
|
assert(username != null),
|
||||||
userId = null,
|
userId = null,
|
||||||
_userDetails = LemmyApi(instanceUrl).v1.getUserDetails(
|
_userDetails = LemmyApi(instanceHost).v1.getUserDetails(
|
||||||
username: username, savedOnly: true, sort: SortType.active);
|
username: username, savedOnly: true, sort: SortType.active);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -2,7 +2,6 @@ import 'package:cached_network_image/cached_network_image.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:lemmy_api_client/lemmy_api_client.dart';
|
import 'package:lemmy_api_client/lemmy_api_client.dart';
|
||||||
|
|
||||||
import '../util/extensions/api.dart';
|
|
||||||
import '../widgets/markdown_text.dart';
|
import '../widgets/markdown_text.dart';
|
||||||
|
|
||||||
/// Infinite list of Users fetched by the given fetcher
|
/// Infinite list of Users fetched by the given fetcher
|
||||||
|
@ -42,7 +41,7 @@ class UsersListPage extends StatelessWidget {
|
||||||
opacity: 0.5,
|
opacity: 0.5,
|
||||||
child: MarkdownText(
|
child: MarkdownText(
|
||||||
users[i].bio,
|
users[i].bio,
|
||||||
instanceUrl: users[i].instanceUrl,
|
instanceHost: users[i].instanceHost,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
|
|
|
@ -12,16 +12,16 @@ class AccountsStore extends ChangeNotifier {
|
||||||
/// Map containing JWT tokens of specific users.
|
/// Map containing JWT tokens of specific users.
|
||||||
/// If a token is in this map, the user is considered logged in
|
/// If a token is in this map, the user is considered logged in
|
||||||
/// for that account.
|
/// for that account.
|
||||||
/// `tokens['instanceUrl']['username']`
|
/// `tokens['instanceHost']['username']`
|
||||||
HashMap<String, HashMap<String, Jwt>> get tokens => _tokens;
|
HashMap<String, HashMap<String, Jwt>> get tokens => _tokens;
|
||||||
HashMap<String, HashMap<String, Jwt>> _tokens;
|
HashMap<String, HashMap<String, Jwt>> _tokens;
|
||||||
|
|
||||||
/// default account for a given instance
|
/// 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;
|
HashMap<String, String> _defaultAccounts;
|
||||||
|
|
||||||
/// default account for the app
|
/// default account for the app
|
||||||
/// It is in a form of `username@instanceUrl`
|
/// It is in a form of `username@instanceHost`
|
||||||
String _defaultAccount;
|
String _defaultAccount;
|
||||||
|
|
||||||
Future<void> load() async {
|
Future<void> load() async {
|
||||||
|
@ -87,12 +87,12 @@ class AccountsStore extends ChangeNotifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
// set local defaults
|
// set local defaults
|
||||||
for (final instanceUrl in instances) {
|
for (final instanceHost in instances) {
|
||||||
// if this instance is not in defaults
|
// if this instance is not in defaults
|
||||||
if (!_defaultAccounts.containsKey(instanceUrl)) {
|
if (!_defaultAccounts.containsKey(instanceHost)) {
|
||||||
// select first account in this instance, if any
|
// select first account in this instance, if any
|
||||||
if (!isAnonymousFor(instanceUrl)) {
|
if (!isAnonymousFor(instanceHost)) {
|
||||||
setDefaultAccountFor(instanceUrl, tokens[instanceUrl].keys.first);
|
setDefaultAccountFor(instanceHost, tokens[instanceHost].keys.first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,10 +100,10 @@ class AccountsStore extends ChangeNotifier {
|
||||||
// set global default
|
// set global default
|
||||||
if (_defaultAccount == null) {
|
if (_defaultAccount == null) {
|
||||||
// select first account of first instance
|
// select first account of first instance
|
||||||
for (final instanceUrl in instances) {
|
for (final instanceHost in instances) {
|
||||||
// select first account in this instance, if any
|
// select first account in this instance, if any
|
||||||
if (!isAnonymousFor(instanceUrl)) {
|
if (!isAnonymousFor(instanceHost)) {
|
||||||
setDefaultAccount(instanceUrl, tokens[instanceUrl].keys.first);
|
setDefaultAccount(instanceHost, tokens[instanceHost].keys.first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ class AccountsStore extends ChangeNotifier {
|
||||||
return _defaultAccount.split('@')[0];
|
return _defaultAccount.split('@')[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
String get defaultInstanceUrl {
|
String get defaultInstanceHost {
|
||||||
if (_defaultAccount == null) {
|
if (_defaultAccount == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -125,12 +125,12 @@ class AccountsStore extends ChangeNotifier {
|
||||||
return _defaultAccount.split('@')[1];
|
return _defaultAccount.split('@')[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
String defaultUsernameFor(String instanceUrl) {
|
String defaultUsernameFor(String instanceHost) {
|
||||||
if (isAnonymousFor(instanceUrl)) {
|
if (isAnonymousFor(instanceHost)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _defaultAccounts[instanceUrl];
|
return _defaultAccounts[instanceHost];
|
||||||
}
|
}
|
||||||
|
|
||||||
Jwt get defaultToken {
|
Jwt get defaultToken {
|
||||||
|
@ -142,25 +142,25 @@ class AccountsStore extends ChangeNotifier {
|
||||||
return tokens[userTag[1]][userTag[0]];
|
return tokens[userTag[1]][userTag[0]];
|
||||||
}
|
}
|
||||||
|
|
||||||
Jwt defaultTokenFor(String instanceUrl) {
|
Jwt defaultTokenFor(String instanceHost) {
|
||||||
if (isAnonymousFor(instanceUrl)) {
|
if (isAnonymousFor(instanceHost)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return tokens[instanceUrl][_defaultAccounts[instanceUrl]];
|
return tokens[instanceHost][_defaultAccounts[instanceHost]];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// sets globally default account
|
/// sets globally default account
|
||||||
void setDefaultAccount(String instanceUrl, String username) {
|
void setDefaultAccount(String instanceHost, String username) {
|
||||||
_defaultAccount = '$username@$instanceUrl';
|
_defaultAccount = '$username@$instanceHost';
|
||||||
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
save();
|
save();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// sets default account for given instance
|
/// sets default account for given instance
|
||||||
void setDefaultAccountFor(String instanceUrl, String username) {
|
void setDefaultAccountFor(String instanceHost, String username) {
|
||||||
_defaultAccounts[instanceUrl] = username;
|
_defaultAccounts[instanceHost] = username;
|
||||||
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
save();
|
save();
|
||||||
|
@ -168,12 +168,12 @@ class AccountsStore extends ChangeNotifier {
|
||||||
|
|
||||||
/// An instance is considered anonymous if it was not
|
/// An instance is considered anonymous if it was not
|
||||||
/// added or there are no accounts assigned to it.
|
/// added or there are no accounts assigned to it.
|
||||||
bool isAnonymousFor(String instanceUrl) {
|
bool isAnonymousFor(String instanceHost) {
|
||||||
if (!instances.contains(instanceUrl)) {
|
if (!instances.contains(instanceHost)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return tokens[instanceUrl].isEmpty;
|
return tokens[instanceHost].isEmpty;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `true` if no added instance has an account assigned to it
|
/// `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
|
/// if it's the first account for an instance the account is
|
||||||
/// set as default for that instance
|
/// set as default for that instance
|
||||||
Future<void> addAccount(
|
Future<void> addAccount(
|
||||||
String instanceUrl,
|
String instanceHost,
|
||||||
String usernameOrEmail,
|
String usernameOrEmail,
|
||||||
String password,
|
String password,
|
||||||
) async {
|
) async {
|
||||||
if (!instances.contains(instanceUrl)) {
|
if (!instances.contains(instanceHost)) {
|
||||||
throw Exception('No such instance was added');
|
throw Exception('No such instance was added');
|
||||||
}
|
}
|
||||||
|
|
||||||
final lemmy = LemmyApi(instanceUrl).v1;
|
final lemmy = LemmyApi(instanceHost).v1;
|
||||||
|
|
||||||
final token = await lemmy.login(
|
final token = await lemmy.login(
|
||||||
usernameOrEmail: usernameOrEmail,
|
usernameOrEmail: usernameOrEmail,
|
||||||
|
@ -207,7 +207,7 @@ class AccountsStore extends ChangeNotifier {
|
||||||
final userData =
|
final userData =
|
||||||
await lemmy.getSite(auth: token.raw).then((value) => value.myUser);
|
await lemmy.getSite(auth: token.raw).then((value) => value.myUser);
|
||||||
|
|
||||||
tokens[instanceUrl][userData.name] = token;
|
tokens[instanceHost][userData.name] = token;
|
||||||
|
|
||||||
_assignDefaultAccounts();
|
_assignDefaultAccounts();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
@ -218,23 +218,23 @@ class AccountsStore extends ChangeNotifier {
|
||||||
/// Additionally makes a test `GET /site` request to check if the instance exists.
|
/// Additionally makes a test `GET /site` request to check if the instance exists.
|
||||||
/// Check is skipped when [assumeValid] is `true`
|
/// Check is skipped when [assumeValid] is `true`
|
||||||
Future<void> addInstance(
|
Future<void> addInstance(
|
||||||
String instanceUrl, {
|
String instanceHost, {
|
||||||
bool assumeValid = false,
|
bool assumeValid = false,
|
||||||
}) async {
|
}) async {
|
||||||
if (instances.contains(instanceUrl)) {
|
if (instances.contains(instanceHost)) {
|
||||||
throw Exception('This instance has already been added');
|
throw Exception('This instance has already been added');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!assumeValid) {
|
if (!assumeValid) {
|
||||||
try {
|
try {
|
||||||
await LemmyApi(instanceUrl).v1.getSite();
|
await LemmyApi(instanceHost).v1.getSite();
|
||||||
// ignore: avoid_catches_without_on_clauses
|
// ignore: avoid_catches_without_on_clauses
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
throw Exception('This instance seems to not exist');
|
throw Exception('This instance seems to not exist');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tokens[instanceUrl] = HashMap();
|
tokens[instanceHost] = HashMap();
|
||||||
|
|
||||||
_assignDefaultAccounts();
|
_assignDefaultAccounts();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
@ -242,16 +242,16 @@ class AccountsStore extends ChangeNotifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This also removes all accounts assigned to this instance
|
/// This also removes all accounts assigned to this instance
|
||||||
void removeInstance(String instanceUrl) {
|
void removeInstance(String instanceHost) {
|
||||||
tokens.remove(instanceUrl);
|
tokens.remove(instanceHost);
|
||||||
|
|
||||||
_assignDefaultAccounts();
|
_assignDefaultAccounts();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
save();
|
save();
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeAccount(String instanceUrl, String username) {
|
void removeAccount(String instanceHost, String username) {
|
||||||
tokens[instanceUrl].remove(username);
|
tokens[instanceHost].remove(username);
|
||||||
|
|
||||||
_assignDefaultAccounts();
|
_assignDefaultAccounts();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
|
|
@ -15,7 +15,7 @@ import 'util/goto.dart';
|
||||||
Future<void> linkLauncher({
|
Future<void> linkLauncher({
|
||||||
@required BuildContext context,
|
@required BuildContext context,
|
||||||
@required String url,
|
@required String url,
|
||||||
@required String instanceUrl,
|
@required String instanceHost,
|
||||||
}) async {
|
}) async {
|
||||||
push(Widget Function() builder) {
|
push(Widget Function() builder) {
|
||||||
goTo(context, (c) => builder());
|
goTo(context, (c) => builder());
|
||||||
|
@ -28,14 +28,14 @@ Future<void> linkLauncher({
|
||||||
|
|
||||||
// CHECK IF LINK TO USER
|
// CHECK IF LINK TO USER
|
||||||
if (url.startsWith('/u/')) {
|
if (url.startsWith('/u/')) {
|
||||||
return push(
|
return push(() =>
|
||||||
() => UserPage.fromName(instanceUrl: instanceUrl, username: chonks[2]));
|
UserPage.fromName(instanceHost: instanceHost, username: chonks[2]));
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK IF LINK TO COMMUNITY
|
// CHECK IF LINK TO COMMUNITY
|
||||||
if (url.startsWith('/c/')) {
|
if (url.startsWith('/c/')) {
|
||||||
return push(() => CommunityPage.fromName(
|
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
|
// 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 (matchedInstance != null && instances.any((e) => e == match.group(1))) {
|
||||||
if (rest.isEmpty || rest == '/') {
|
if (rest.isEmpty || rest == '/') {
|
||||||
return push(() => InstancePage(instanceUrl: matchedInstance));
|
return push(() => InstancePage(instanceHost: matchedInstance));
|
||||||
}
|
}
|
||||||
final split = rest.split('/');
|
final split = rest.split('/');
|
||||||
switch (split[1]) {
|
switch (split[1]) {
|
||||||
|
|
|
@ -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]);
|
|
|
@ -25,41 +25,42 @@ Future<dynamic> goToReplace(
|
||||||
builder: builder,
|
builder: builder,
|
||||||
));
|
));
|
||||||
|
|
||||||
void goToInstance(BuildContext context, String instanceUrl) =>
|
void goToInstance(BuildContext context, String instanceHost) =>
|
||||||
goTo(context, (context) => InstancePage(instanceUrl: instanceUrl));
|
goTo(context, (context) => InstancePage(instanceHost: instanceHost));
|
||||||
|
|
||||||
// ignore: camel_case_types
|
// ignore: camel_case_types
|
||||||
abstract class goToCommunity {
|
abstract class goToCommunity {
|
||||||
/// Navigates to `CommunityPage`
|
/// Navigates to `CommunityPage`
|
||||||
static void byId(BuildContext context, String instanceUrl, int communityId) =>
|
static void byId(
|
||||||
|
BuildContext context, String instanceHost, int communityId) =>
|
||||||
goTo(
|
goTo(
|
||||||
context,
|
context,
|
||||||
(context) => CommunityPage.fromId(
|
(context) => CommunityPage.fromId(
|
||||||
instanceUrl: instanceUrl, communityId: communityId),
|
instanceHost: instanceHost, communityId: communityId),
|
||||||
);
|
);
|
||||||
|
|
||||||
static void byName(
|
static void byName(
|
||||||
BuildContext context, String instanceUrl, String communityName) =>
|
BuildContext context, String instanceHost, String communityName) =>
|
||||||
goTo(
|
goTo(
|
||||||
context,
|
context,
|
||||||
(context) => CommunityPage.fromName(
|
(context) => CommunityPage.fromName(
|
||||||
instanceUrl: instanceUrl, communityName: communityName),
|
instanceHost: instanceHost, communityName: communityName),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore: camel_case_types
|
// ignore: camel_case_types
|
||||||
abstract class goToUser {
|
abstract class goToUser {
|
||||||
static void byId(BuildContext context, String instanceUrl, int userId) =>
|
static void byId(BuildContext context, String instanceHost, int userId) =>
|
||||||
goTo(context,
|
goTo(context,
|
||||||
(context) => UserPage(instanceUrl: instanceUrl, userId: userId));
|
(context) => UserPage(instanceHost: instanceHost, userId: userId));
|
||||||
|
|
||||||
static void byName(
|
static void byName(
|
||||||
BuildContext context, String instanceUrl, String userName) =>
|
BuildContext context, String instanceHost, String userName) =>
|
||||||
throw UnimplementedError('need to create UserProfile constructor first');
|
throw UnimplementedError('need to create UserProfile constructor first');
|
||||||
}
|
}
|
||||||
|
|
||||||
void goToPost(BuildContext context, String instanceUrl, int postId) => goTo(
|
void goToPost(BuildContext context, String instanceHost, int postId) => goTo(
|
||||||
context, (context) => FullPostPage(instanceUrl: instanceUrl, id: postId));
|
context, (context) => FullPostPage(instanceHost: instanceHost, id: postId));
|
||||||
|
|
||||||
void goToMedia(BuildContext context, String url) => Navigator.push(
|
void goToMedia(BuildContext context, String url) => Navigator.push(
|
||||||
context,
|
context,
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
String pathToPictrs(String instanceUrl, String imgId) =>
|
String pathToPictrs(String instanceHost, String imgId) =>
|
||||||
'https://$instanceUrl/pictrs/image/$imgId';
|
'https://$instanceHost/pictrs/image/$imgId';
|
||||||
|
|
|
@ -11,7 +11,6 @@ import 'package:url_launcher/url_launcher.dart' as ul;
|
||||||
import '../comment_tree.dart';
|
import '../comment_tree.dart';
|
||||||
import '../hooks/delayed_loading.dart';
|
import '../hooks/delayed_loading.dart';
|
||||||
import '../hooks/logged_in_action.dart';
|
import '../hooks/logged_in_action.dart';
|
||||||
import '../util/extensions/api.dart';
|
|
||||||
import '../util/goto.dart';
|
import '../util/goto.dart';
|
||||||
import '../util/intl.dart';
|
import '../util/intl.dart';
|
||||||
import '../util/text_color.dart';
|
import '../util/text_color.dart';
|
||||||
|
@ -75,7 +74,7 @@ class Comment extends HookWidget {
|
||||||
final isDeleted = useState(commentTree.comment.deleted);
|
final isDeleted = useState(commentTree.comment.deleted);
|
||||||
final delayedVoting = useDelayedLoading();
|
final delayedVoting = useDelayedLoading();
|
||||||
final delayedDeletion = useDelayedLoading();
|
final delayedDeletion = useDelayedLoading();
|
||||||
final loggedInAction = useLoggedInAction(commentTree.comment.instanceUrl);
|
final loggedInAction = useLoggedInAction(commentTree.comment.instanceHost);
|
||||||
final newReplies = useState(const <CommentTree>[]);
|
final newReplies = useState(const <CommentTree>[]);
|
||||||
|
|
||||||
final comment = commentTree.comment;
|
final comment = commentTree.comment;
|
||||||
|
@ -237,7 +236,7 @@ class Comment extends HookWidget {
|
||||||
: Text(commentTree.comment.content)
|
: Text(commentTree.comment.content)
|
||||||
: MarkdownText(
|
: MarkdownText(
|
||||||
commentTree.comment.content,
|
commentTree.comment.content,
|
||||||
instanceUrl: commentTree.comment.instanceUrl,
|
instanceHost: commentTree.comment.instanceHost,
|
||||||
selectable: selectable.value,
|
selectable: selectable.value,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -305,7 +304,7 @@ class Comment extends HookWidget {
|
||||||
padding: const EdgeInsets.only(right: 5),
|
padding: const EdgeInsets.only(right: 5),
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () => goToUser.byId(
|
onTap: () => goToUser.byId(
|
||||||
context, comment.instanceUrl, comment.creatorId),
|
context, comment.instanceHost, comment.creatorId),
|
||||||
child: CachedNetworkImage(
|
child: CachedNetworkImage(
|
||||||
imageUrl: comment.creatorAvatar,
|
imageUrl: comment.creatorAvatar,
|
||||||
height: 20,
|
height: 20,
|
||||||
|
@ -329,7 +328,7 @@ class Comment extends HookWidget {
|
||||||
color: Theme.of(context).accentColor,
|
color: Theme.of(context).accentColor,
|
||||||
)),
|
)),
|
||||||
onTap: () => goToUser.byId(
|
onTap: () => goToUser.byId(
|
||||||
context, comment.instanceUrl, comment.creatorId),
|
context, comment.instanceHost, comment.creatorId),
|
||||||
),
|
),
|
||||||
if (isOP) _CommentTag('OP', Theme.of(context).accentColor),
|
if (isOP) _CommentTag('OP', Theme.of(context).accentColor),
|
||||||
if (comment.banned) _CommentTag('BANNED', Colors.red),
|
if (comment.banned) _CommentTag('BANNED', Colors.red),
|
||||||
|
@ -394,12 +393,12 @@ class _SaveComment extends HookWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final loggedInAction = useLoggedInAction(comment.instanceUrl);
|
final loggedInAction = useLoggedInAction(comment.instanceHost);
|
||||||
final isSaved = useState(comment.saved ?? false);
|
final isSaved = useState(comment.saved ?? false);
|
||||||
final delayed = useDelayedLoading(const Duration(milliseconds: 500));
|
final delayed = useDelayedLoading(const Duration(milliseconds: 500));
|
||||||
|
|
||||||
handleSave(Jwt token) async {
|
handleSave(Jwt token) async {
|
||||||
final api = LemmyApi(comment.instanceUrl).v1;
|
final api = LemmyApi(comment.instanceHost).v1;
|
||||||
|
|
||||||
delayed.start();
|
delayed.start();
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -8,12 +8,13 @@ import 'fullscreenable_image.dart';
|
||||||
|
|
||||||
/// A Markdown renderer with link/image handling
|
/// A Markdown renderer with link/image handling
|
||||||
class MarkdownText extends StatelessWidget {
|
class MarkdownText extends StatelessWidget {
|
||||||
final String instanceUrl;
|
final String instanceHost;
|
||||||
final String text;
|
final String text;
|
||||||
final bool selectable;
|
final bool selectable;
|
||||||
|
|
||||||
MarkdownText(this.text, {@required this.instanceUrl, this.selectable = false})
|
MarkdownText(this.text,
|
||||||
: assert(instanceUrl != null);
|
{@required this.instanceHost, this.selectable = false})
|
||||||
|
: assert(instanceHost != null);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) => MarkdownBody(
|
Widget build(BuildContext context) => MarkdownBody(
|
||||||
|
@ -21,7 +22,7 @@ class MarkdownText extends StatelessWidget {
|
||||||
data: text,
|
data: text,
|
||||||
extensionSet: md.ExtensionSet.gitHubWeb,
|
extensionSet: md.ExtensionSet.gitHubWeb,
|
||||||
onTapLink: (href) {
|
onTapLink: (href) {
|
||||||
linkLauncher(context: context, url: href, instanceUrl: instanceUrl)
|
linkLauncher(context: context, url: href, instanceHost: instanceHost)
|
||||||
.catchError((e) => Scaffold.of(context).showSnackBar(SnackBar(
|
.catchError((e) => Scaffold.of(context).showSnackBar(SnackBar(
|
||||||
content: Row(
|
content: Row(
|
||||||
children: [
|
children: [
|
||||||
|
|
|
@ -13,7 +13,6 @@ import '../hooks/delayed_loading.dart';
|
||||||
import '../hooks/logged_in_action.dart';
|
import '../hooks/logged_in_action.dart';
|
||||||
import '../pages/full_post.dart';
|
import '../pages/full_post.dart';
|
||||||
import '../url_launcher.dart';
|
import '../url_launcher.dart';
|
||||||
import '../util/extensions/api.dart';
|
|
||||||
import '../util/goto.dart';
|
import '../util/goto.dart';
|
||||||
import '../util/more_icon.dart';
|
import '../util/more_icon.dart';
|
||||||
import 'bottom_modal.dart';
|
import 'bottom_modal.dart';
|
||||||
|
@ -49,10 +48,10 @@ MediaType whatType(String url) {
|
||||||
/// A post overview card
|
/// A post overview card
|
||||||
class Post extends HookWidget {
|
class Post extends HookWidget {
|
||||||
final PostView post;
|
final PostView post;
|
||||||
final String instanceUrl;
|
final String instanceHost;
|
||||||
final bool fullPost;
|
final bool fullPost;
|
||||||
|
|
||||||
Post(this.post, {this.fullPost = false}) : instanceUrl = post.instanceUrl;
|
Post(this.post, {this.fullPost = false}) : instanceHost = post.instanceHost;
|
||||||
|
|
||||||
// == ACTIONS ==
|
// == ACTIONS ==
|
||||||
|
|
||||||
|
@ -103,8 +102,8 @@ class Post extends HookWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
void _openLink() =>
|
void _openLink() => linkLauncher(
|
||||||
linkLauncher(context: context, url: post.url, instanceUrl: instanceUrl);
|
context: context, url: post.url, instanceHost: instanceHost);
|
||||||
|
|
||||||
final urlDomain = () {
|
final urlDomain = () {
|
||||||
if (whatType(post.url) == MediaType.none) return null;
|
if (whatType(post.url) == MediaType.none) return null;
|
||||||
|
@ -127,7 +126,7 @@ class Post extends HookWidget {
|
||||||
padding: const EdgeInsets.only(right: 10),
|
padding: const EdgeInsets.only(right: 10),
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () => goToCommunity.byId(
|
onTap: () => goToCommunity.byId(
|
||||||
context, instanceUrl, post.communityId),
|
context, instanceHost, post.communityId),
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
width: 40,
|
width: 40,
|
||||||
|
@ -168,16 +167,16 @@ class Post extends HookWidget {
|
||||||
style: TextStyle(fontWeight: FontWeight.w600),
|
style: TextStyle(fontWeight: FontWeight.w600),
|
||||||
recognizer: TapGestureRecognizer()
|
recognizer: TapGestureRecognizer()
|
||||||
..onTap = () => goToCommunity.byId(
|
..onTap = () => goToCommunity.byId(
|
||||||
context, instanceUrl, post.communityId)),
|
context, instanceHost, post.communityId)),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: '@',
|
text: '@',
|
||||||
style: TextStyle(fontWeight: FontWeight.w300)),
|
style: TextStyle(fontWeight: FontWeight.w300)),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: instanceUrl,
|
text: instanceHost,
|
||||||
style: TextStyle(fontWeight: FontWeight.w600),
|
style: TextStyle(fontWeight: FontWeight.w600),
|
||||||
recognizer: TapGestureRecognizer()
|
recognizer: TapGestureRecognizer()
|
||||||
..onTap =
|
..onTap =
|
||||||
() => goToInstance(context, instanceUrl)),
|
() => goToInstance(context, instanceHost)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -199,7 +198,7 @@ class Post extends HookWidget {
|
||||||
style: TextStyle(fontWeight: FontWeight.w600),
|
style: TextStyle(fontWeight: FontWeight.w600),
|
||||||
recognizer: TapGestureRecognizer()
|
recognizer: TapGestureRecognizer()
|
||||||
..onTap = () => goToUser.byId(
|
..onTap = () => goToUser.byId(
|
||||||
context, post.instanceUrl, post.creatorId),
|
context, post.instanceHost, post.creatorId),
|
||||||
),
|
),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text:
|
text:
|
||||||
|
@ -377,10 +376,7 @@ class Post extends HookWidget {
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: fullPost
|
onTap: fullPost
|
||||||
? null
|
? null
|
||||||
: () => goTo(
|
: () => goTo(context, (context) => FullPostPage.fromPostView(post)),
|
||||||
context,
|
|
||||||
(context) =>
|
|
||||||
FullPostPage.fromPostView(post)), //, instanceUrl, post.id),
|
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
info(),
|
info(),
|
||||||
|
@ -394,7 +390,7 @@ class Post extends HookWidget {
|
||||||
// TODO: trim content
|
// TODO: trim content
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(10),
|
padding: const EdgeInsets.all(10),
|
||||||
child: MarkdownText(post.body, instanceUrl: instanceUrl)),
|
child: MarkdownText(post.body, instanceHost: instanceHost)),
|
||||||
actions(),
|
actions(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -416,10 +412,10 @@ class _Voting extends HookWidget {
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
final myVote = useState(post.myVote ?? VoteType.none);
|
final myVote = useState(post.myVote ?? VoteType.none);
|
||||||
final loading = useDelayedLoading(Duration(milliseconds: 500));
|
final loading = useDelayedLoading(Duration(milliseconds: 500));
|
||||||
final loggedInAction = useLoggedInAction(post.instanceUrl);
|
final loggedInAction = useLoggedInAction(post.instanceHost);
|
||||||
|
|
||||||
vote(VoteType vote, Jwt token) async {
|
vote(VoteType vote, Jwt token) async {
|
||||||
final api = LemmyApi(post.instanceUrl).v1;
|
final api = LemmyApi(post.instanceHost).v1;
|
||||||
|
|
||||||
loading.start();
|
loading.start();
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -4,7 +4,6 @@ import 'package:lemmy_api_client/lemmy_api_client.dart';
|
||||||
|
|
||||||
import '../hooks/delayed_loading.dart';
|
import '../hooks/delayed_loading.dart';
|
||||||
import '../hooks/logged_in_action.dart';
|
import '../hooks/logged_in_action.dart';
|
||||||
import '../util/extensions/api.dart';
|
|
||||||
|
|
||||||
// TODO: sync this button between post and fullpost. the same with voting
|
// 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 isSaved = useState(post.saved ?? false);
|
||||||
final savedIcon = isSaved.value ? Icons.bookmark : Icons.bookmark_border;
|
final savedIcon = isSaved.value ? Icons.bookmark : Icons.bookmark_border;
|
||||||
final loading = useDelayedLoading(Duration(milliseconds: 500));
|
final loading = useDelayedLoading(Duration(milliseconds: 500));
|
||||||
final loggedInAction = useLoggedInAction(post.instanceUrl);
|
final loggedInAction = useLoggedInAction(post.instanceHost);
|
||||||
|
|
||||||
savePost(Jwt token) async {
|
savePost(Jwt token) async {
|
||||||
final api = LemmyApi(post.instanceUrl).v1;
|
final api = LemmyApi(post.instanceHost).v1;
|
||||||
|
|
||||||
loading.start();
|
loading.start();
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -6,7 +6,6 @@ import 'package:lemmy_api_client/lemmy_api_client.dart';
|
||||||
import 'package:timeago/timeago.dart' as timeago;
|
import 'package:timeago/timeago.dart' as timeago;
|
||||||
|
|
||||||
import '../hooks/stores.dart';
|
import '../hooks/stores.dart';
|
||||||
import '../util/extensions/api.dart';
|
|
||||||
import '../util/goto.dart';
|
import '../util/goto.dart';
|
||||||
import '../util/intl.dart';
|
import '../util/intl.dart';
|
||||||
import '../util/text_color.dart';
|
import '../util/text_color.dart';
|
||||||
|
@ -18,15 +17,15 @@ import 'sortable_infinite_list.dart';
|
||||||
/// Shared widget of UserPage and ProfileTab
|
/// Shared widget of UserPage and ProfileTab
|
||||||
class UserProfile extends HookWidget {
|
class UserProfile extends HookWidget {
|
||||||
final Future<UserDetails> _userDetails;
|
final Future<UserDetails> _userDetails;
|
||||||
final String instanceUrl;
|
final String instanceHost;
|
||||||
|
|
||||||
UserProfile({@required int userId, @required this.instanceUrl})
|
UserProfile({@required int userId, @required this.instanceHost})
|
||||||
: _userDetails = LemmyApi(instanceUrl).v1.getUserDetails(
|
: _userDetails = LemmyApi(instanceHost).v1.getUserDetails(
|
||||||
userId: userId, savedOnly: false, sort: SortType.active);
|
userId: userId, savedOnly: false, sort: SortType.active);
|
||||||
|
|
||||||
UserProfile.fromUserDetails(UserDetails userDetails)
|
UserProfile.fromUserDetails(UserDetails userDetails)
|
||||||
: _userDetails = Future.value(userDetails),
|
: _userDetails = Future.value(userDetails),
|
||||||
instanceUrl = userDetails.user.instanceUrl;
|
instanceHost = userDetails.user.instanceHost;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -78,7 +77,7 @@ class UserProfile extends HookWidget {
|
||||||
// TODO: first batch is already fetched on render
|
// TODO: first batch is already fetched on render
|
||||||
// TODO: comment and post come from the same endpoint, could be shared
|
// TODO: comment and post come from the same endpoint, could be shared
|
||||||
InfinitePostList(
|
InfinitePostList(
|
||||||
fetcher: (page, batchSize, sort) => LemmyApi(instanceUrl)
|
fetcher: (page, batchSize, sort) => LemmyApi(instanceHost)
|
||||||
.v1
|
.v1
|
||||||
.getUserDetails(
|
.getUserDetails(
|
||||||
userId: userView.id,
|
userId: userView.id,
|
||||||
|
@ -90,7 +89,7 @@ class UserProfile extends HookWidget {
|
||||||
.then((val) => val.posts),
|
.then((val) => val.posts),
|
||||||
),
|
),
|
||||||
InfiniteCommentList(
|
InfiniteCommentList(
|
||||||
fetcher: (page, batchSize, sort) => LemmyApi(instanceUrl)
|
fetcher: (page, batchSize, sort) => LemmyApi(instanceHost)
|
||||||
.v1
|
.v1
|
||||||
.getUserDetails(
|
.getUserDetails(
|
||||||
userId: userView.id,
|
userId: userView.id,
|
||||||
|
@ -222,9 +221,9 @@ class _UserOverview extends HookWidget {
|
||||||
style: theme.textTheme.caption,
|
style: theme.textTheme.caption,
|
||||||
),
|
),
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap: () => goToInstance(context, userView.instanceUrl),
|
onTap: () => goToInstance(context, userView.instanceHost),
|
||||||
child: Text(
|
child: Text(
|
||||||
'${userView.instanceUrl}',
|
'${userView.instanceHost}',
|
||||||
style: theme.textTheme.caption,
|
style: theme.textTheme.caption,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -324,12 +323,12 @@ class _AboutTab extends HookWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
final instanceUrl = userDetails.user.instanceUrl;
|
final instanceHost = userDetails.user.instanceHost;
|
||||||
|
|
||||||
final accStore = useAccountsStore();
|
final accStore = useAccountsStore();
|
||||||
|
|
||||||
final isOwnedAccount = accStore.loggedInInstances.contains(instanceUrl) &&
|
final isOwnedAccount = accStore.loggedInInstances.contains(instanceHost) &&
|
||||||
accStore.tokens[instanceUrl].containsKey(userDetails.user.name);
|
accStore.tokens[instanceHost].containsKey(userDetails.user.name);
|
||||||
|
|
||||||
const wallPadding = EdgeInsets.symmetric(horizontal: 15);
|
const wallPadding = EdgeInsets.symmetric(horizontal: 15);
|
||||||
|
|
||||||
|
@ -341,7 +340,7 @@ class _AboutTab extends HookWidget {
|
||||||
|
|
||||||
communityTile(String name, String icon, int id) => ListTile(
|
communityTile(String name, String icon, int id) => ListTile(
|
||||||
dense: true,
|
dense: true,
|
||||||
onTap: () => goToCommunity.byId(context, instanceUrl, id),
|
onTap: () => goToCommunity.byId(context, instanceHost, id),
|
||||||
title: Text('!$name'),
|
title: Text('!$name'),
|
||||||
leading: icon != null
|
leading: icon != null
|
||||||
? CachedNetworkImage(
|
? CachedNetworkImage(
|
||||||
|
@ -379,8 +378,8 @@ class _AboutTab extends HookWidget {
|
||||||
if (userDetails.user.bio != null) ...[
|
if (userDetails.user.bio != null) ...[
|
||||||
Padding(
|
Padding(
|
||||||
padding: wallPadding,
|
padding: wallPadding,
|
||||||
child:
|
child: MarkdownText(userDetails.user.bio,
|
||||||
MarkdownText(userDetails.user.bio, instanceUrl: instanceUrl)),
|
instanceHost: instanceHost)),
|
||||||
divider,
|
divider,
|
||||||
],
|
],
|
||||||
if (userDetails.moderates.isNotEmpty) ...[
|
if (userDetails.moderates.isNotEmpty) ...[
|
||||||
|
|
|
@ -4,7 +4,6 @@ import 'package:lemmy_api_client/lemmy_api_client.dart';
|
||||||
|
|
||||||
import '../hooks/delayed_loading.dart';
|
import '../hooks/delayed_loading.dart';
|
||||||
import '../hooks/stores.dart';
|
import '../hooks/stores.dart';
|
||||||
import '../util/extensions/api.dart';
|
|
||||||
import 'markdown_text.dart';
|
import 'markdown_text.dart';
|
||||||
|
|
||||||
/// Modal for writing a comment to a given post/comment (aka reply)
|
/// Modal for writing a comment to a given post/comment (aka reply)
|
||||||
|
@ -14,14 +13,14 @@ class WriteComment extends HookWidget {
|
||||||
final PostView post;
|
final PostView post;
|
||||||
final CommentView comment;
|
final CommentView comment;
|
||||||
|
|
||||||
final String instanceUrl;
|
final String instanceHost;
|
||||||
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey();
|
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey();
|
||||||
|
|
||||||
WriteComment.toPost(this.post)
|
WriteComment.toPost(this.post)
|
||||||
: instanceUrl = post.instanceUrl,
|
: instanceHost = post.instanceHost,
|
||||||
comment = null;
|
comment = null;
|
||||||
WriteComment.toComment(this.comment)
|
WriteComment.toComment(this.comment)
|
||||||
: instanceUrl = comment.instanceUrl,
|
: instanceHost = comment.instanceHost,
|
||||||
post = null;
|
post = null;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -34,7 +33,7 @@ class WriteComment extends HookWidget {
|
||||||
final preview = () {
|
final preview = () {
|
||||||
final body = MarkdownText(
|
final body = MarkdownText(
|
||||||
comment?.content ?? post.body ?? '',
|
comment?.content ?? post.body ?? '',
|
||||||
instanceUrl: instanceUrl,
|
instanceHost: instanceHost,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (post != null) {
|
if (post != null) {
|
||||||
|
@ -54,9 +53,9 @@ class WriteComment extends HookWidget {
|
||||||
}();
|
}();
|
||||||
|
|
||||||
handleSubmit() async {
|
handleSubmit() async {
|
||||||
final api = LemmyApi(instanceUrl).v1;
|
final api = LemmyApi(instanceHost).v1;
|
||||||
|
|
||||||
final token = accStore.defaultTokenFor(instanceUrl);
|
final token = accStore.defaultTokenFor(instanceHost);
|
||||||
|
|
||||||
delayed.start();
|
delayed.start();
|
||||||
try {
|
try {
|
||||||
|
@ -115,7 +114,7 @@ class WriteComment extends HookWidget {
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
child: MarkdownText(
|
child: MarkdownText(
|
||||||
controller.text,
|
controller.text,
|
||||||
instanceUrl: instanceUrl,
|
instanceHost: instanceHost,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
|
|
@ -260,7 +260,7 @@ packages:
|
||||||
name: lemmy_api_client
|
name: lemmy_api_client
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.8.0"
|
version: "0.8.2"
|
||||||
markdown:
|
markdown:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -43,7 +43,7 @@ dependencies:
|
||||||
# utils
|
# utils
|
||||||
timeago: ^2.0.27
|
timeago: ^2.0.27
|
||||||
fuzzy: <1.0.0
|
fuzzy: <1.0.0
|
||||||
lemmy_api_client: ^0.8.0
|
lemmy_api_client: ^0.8.2
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|
Loading…
Reference in New Issue