From c2f528750a19f12ba9e72cb7e0ee265dd6898d1b Mon Sep 17 00:00:00 2001 From: krawieck Date: Sun, 24 Jan 2021 20:01:55 +0100 Subject: [PATCH 01/17] transition all api v1 calls to api v2 --- lib/comment_tree.dart | 18 ++-- lib/hooks/logged_in_action.dart | 2 +- lib/pages/add_account.dart | 10 +- lib/pages/add_instance.dart | 6 +- lib/pages/communities_list.dart | 16 ++-- lib/pages/communities_tab.dart | 44 ++++----- lib/pages/community.dart | 121 +++++++++++------------ lib/pages/create_post.dart | 59 ++++++------ lib/pages/full_post.dart | 22 +++-- lib/pages/home_tab.dart | 17 ++-- lib/pages/instance.dart | 122 ++++++++++++------------ lib/pages/manage_account.dart | 91 +++++++++--------- lib/pages/search_results.dart | 24 ++--- lib/pages/user.dart | 14 +-- lib/pages/users_list.dart | 24 ++--- lib/stores/accounts_store.dart | 17 ++-- lib/util/extensions/api.dart | 24 ++--- lib/util/hot_rank.dart | 5 +- lib/widgets/comment_section.dart | 9 +- lib/widgets/post.dart | 120 ++++++++++++----------- lib/widgets/post_list_options.dart | 2 +- lib/widgets/save_post_button.dart | 8 +- lib/widgets/sortable_infinite_list.dart | 6 +- lib/widgets/user_profile.dart | 89 ++++++++--------- lib/widgets/write_comment.dart | 26 +++-- 25 files changed, 462 insertions(+), 434 deletions(-) diff --git a/lib/comment_tree.dart b/lib/comment_tree.dart index fab9827..153bb22 100644 --- a/lib/comment_tree.dart +++ b/lib/comment_tree.dart @@ -1,4 +1,4 @@ -import 'package:lemmy_api_client/lemmy_api_client.dart'; +import 'package:lemmy_api_client/v2.dart'; import 'util/hot_rank.dart'; @@ -25,13 +25,16 @@ extension on CommentSortType { a.comment.computedHotRank.compareTo(b.comment.computedHotRank); case CommentSortType.new_: - return (b, a) => a.comment.published.compareTo(b.comment.published); + return (b, a) => + a.comment.comment.published.compareTo(b.comment.comment.published); case CommentSortType.old: - return (b, a) => b.comment.published.compareTo(a.comment.published); + return (b, a) => + b.comment.comment.published.compareTo(a.comment.comment.published); case CommentSortType.top: - return (b, a) => a.comment.score.compareTo(b.comment.score); + return (b, a) => + a.comment.counts.score.compareTo(b.comment.counts.score); } throw Exception('unreachable'); @@ -50,15 +53,16 @@ class CommentTree { static List fromList(List comments) { CommentTree gatherChildren(CommentTree parent) { for (final el in comments) { - if (el.parentId == parent.comment.id) { + if (el.comment.parentId == parent.comment.comment.id) { parent.children.add(gatherChildren(CommentTree(el))); } } return parent; } - final topLevelParents = - comments.where((e) => e.parentId == null).map((e) => CommentTree(e)); + final topLevelParents = comments + .where((e) => e.comment.parentId == null) + .map((e) => CommentTree(e)); final result = topLevelParents.map(gatherChildren).toList(); return result; diff --git a/lib/hooks/logged_in_action.dart b/lib/hooks/logged_in_action.dart index a48d0af..cc5258a 100644 --- a/lib/hooks/logged_in_action.dart +++ b/lib/hooks/logged_in_action.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:lemmy_api_client/lemmy_api_client.dart'; +import 'package:lemmy_api_client/v2.dart'; import '../pages/settings.dart'; import '../util/goto.dart'; diff --git a/lib/pages/add_account.dart b/lib/pages/add_account.dart index c4290a9..6dba4fc 100644 --- a/lib/pages/add_account.dart +++ b/lib/pages/add_account.dart @@ -2,7 +2,7 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:lemmy_api_client/lemmy_api_client.dart'; +import 'package:lemmy_api_client/v2.dart'; import 'package:url_launcher/url_launcher.dart' as ul; import '../hooks/delayed_loading.dart'; @@ -32,10 +32,10 @@ class AddAccountPage extends HookWidget { final selectedInstance = useState(instanceHost); final icon = useState(null); useEffect(() { - LemmyApi(selectedInstance.value) - .v1 - .getSite() - .then((site) => icon.value = site.site.icon); + // LemmyApi(selectedInstance.value).v2.run(GetPost(id: )); + LemmyApiV2(selectedInstance.value) + .run(GetSite()) + .then((site) => icon.value = site.siteView.site.icon); return null; }, [selectedInstance.value]); diff --git a/lib/pages/add_instance.dart b/lib/pages/add_instance.dart index 4aef4e8..dbaf5d4 100644 --- a/lib/pages/add_instance.dart +++ b/lib/pages/add_instance.dart @@ -1,7 +1,7 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:lemmy_api_client/lemmy_api_client.dart'; +import 'package:lemmy_api_client/v2.dart'; import '../hooks/debounce.dart'; import '../hooks/stores.dart'; @@ -33,7 +33,7 @@ class AddInstancePage extends HookWidget { return; } try { - icon.value = (await LemmyApi(inst).v1.getSite()).site.icon; + icon.value = (await LemmyApiV2(inst).run(GetSite())).siteView.site.icon; isSite.value = true; // ignore: avoid_catches_without_on_clauses } catch (e) { @@ -75,7 +75,7 @@ class AddInstancePage extends HookWidget { ), body: ListView( children: [ - if (isSite.value == true) + if (isSite.value == true && icon.value != null) SizedBox( height: 150, child: FullscreenableImage( diff --git a/lib/pages/communities_list.dart b/lib/pages/communities_list.dart index ad410ef..336f8ea 100644 --- a/lib/pages/communities_list.dart +++ b/lib/pages/communities_list.dart @@ -1,6 +1,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 'package:lemmy_api_client/v2.dart'; import '../util/goto.dart'; import '../widgets/markdown_text.dart'; @@ -55,23 +55,23 @@ class CommunitiesListItem extends StatelessWidget { @override Widget build(BuildContext context) => ListTile( - title: Text(community.name), - subtitle: community.description != null + title: Text(community.community.name), + subtitle: community.community.description != null ? Opacity( opacity: 0.7, child: MarkdownText( - community.description, + community.community.description, instanceHost: community.instanceHost, ), ) : null, - onTap: () => - goToCommunity.byId(context, community.instanceHost, community.id), - leading: community.icon != null + onTap: () => goToCommunity.byId( + context, community.instanceHost, community.community.id), + leading: community.community.icon != null ? CachedNetworkImage( height: 50, width: 50, - imageUrl: community.icon, + imageUrl: community.community.icon, imageBuilder: (context, imageProvider) => Container( decoration: BoxDecoration( shape: BoxShape.circle, diff --git a/lib/pages/communities_tab.dart b/lib/pages/communities_tab.dart index 7915fbf..a48f915 100644 --- a/lib/pages/communities_tab.dart +++ b/lib/pages/communities_tab.dart @@ -5,7 +5,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:fuzzy/fuzzy.dart'; -import 'package:lemmy_api_client/lemmy_api_client.dart'; +import 'package:lemmy_api_client/v2.dart'; import '../hooks/delayed_loading.dart'; import '../hooks/refreshable.dart'; @@ -33,8 +33,9 @@ class CommunitiesTab extends HookWidget { getInstances() { final futures = accountsStore.loggedInInstances .map( - (instanceHost) => - LemmyApi(instanceHost).v1.getSite().then((e) => e.site), + (instanceHost) => LemmyApiV2(instanceHost) + .run(GetSite()) + .then((e) => e.siteView.site), ) .toList(); @@ -44,14 +45,13 @@ class CommunitiesTab extends HookWidget { getCommunities() { final futures = accountsStore.loggedInInstances .map( - (instanceHost) => LemmyApi(instanceHost) - .v1 - .getUserDetails( + (instanceHost) => LemmyApiV2(instanceHost) + .run(GetUserDetails( sort: SortType.active, savedOnly: false, userId: accountsStore.defaultTokenFor(instanceHost).payload.id, - ) + )) .then((e) => e.follows), ) .toList(); @@ -108,8 +108,8 @@ class CommunitiesTab extends HookWidget { final instances = instancesRefreshable.snapshot.data; final communities = communitiesRefreshable.snapshot.data - ..forEach( - (e) => e.sort((a, b) => a.communityName.compareTo(b.communityName))); + ..forEach((e) => + e.sort((a, b) => a.community.name.compareTo(b.community.name))); final filterIcon = () { if (filterController.text.isEmpty) { @@ -127,12 +127,12 @@ class CommunitiesTab extends HookWidget { filterCommunities(List comm) { final matches = Fuzzy( - comm.map((e) => e.communityName).toList(), + comm.map((e) => e.community.name).toList(), options: FuzzyOptions(threshold: 0.5), ).search(filterController.text).map((e) => e.item); return matches - .map((match) => comm.firstWhere((e) => e.communityName == match)); + .map((match) => comm.firstWhere((e) => e.community.name == match)); } toggleCollapse(int i) => isCollapsed.value = @@ -203,18 +203,18 @@ class CommunitiesTab extends HookWidget { onTap: () => goToCommunity.byId( context, accountsStore.loggedInInstances.elementAt(i), - comm.communityId), + comm.community.id), dense: true, leading: VerticalDivider( color: theme.hintColor, ), title: Row( children: [ - if (comm.communityIcon != null) + if (comm.community.icon != null) CachedNetworkImage( height: 30, width: 30, - imageUrl: comm.communityIcon, + imageUrl: comm.community.icon, imageBuilder: (context, imageProvider) => Container( decoration: BoxDecoration( @@ -231,14 +231,14 @@ class CommunitiesTab extends HookWidget { const SizedBox(width: 30), const SizedBox(width: 10), Text( - '''!${comm.communityName}${comm.isLocal ? '' : '@${comm.originInstanceHost}'}''', + '''!${comm.community.name}${comm.community.local ? '' : '@${comm.originInstanceHost}'}''', ), ], ), trailing: _CommunitySubscribeToggle( - key: ValueKey(comm.communityId), + key: ValueKey(comm.community.id), instanceHost: comm.instanceHost, - communityId: comm.communityId, + communityId: comm.community.id, ), ), ) @@ -272,11 +272,11 @@ class _CommunitySubscribeToggle extends HookWidget { delayed.start(); try { - await LemmyApi(instanceHost).v1.followCommunity( - communityId: communityId, - follow: !subbed.value, - auth: accountsStore.defaultTokenFor(instanceHost).raw, - ); + await LemmyApiV2(instanceHost).run(FollowCommunity( + communityId: communityId, + follow: !subbed.value, + auth: accountsStore.defaultTokenFor(instanceHost).raw, + )); subbed.value = !subbed.value; } on Exception catch (err) { Scaffold.of(context).showSnackBar(SnackBar( diff --git a/lib/pages/community.dart b/lib/pages/community.dart index 038197a..ef84cff 100644 --- a/lib/pages/community.dart +++ b/lib/pages/community.dart @@ -3,7 +3,7 @@ import 'package:esys_flutter_share/esys_flutter_share.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:lemmy_api_client/lemmy_api_client.dart'; +import 'package:lemmy_api_client/v2.dart'; import 'package:url_launcher/url_launcher.dart' as ul; import '../hooks/delayed_loading.dart'; @@ -45,8 +45,8 @@ class CommunityPage extends HookWidget { _community = null; CommunityPage.fromCommunityView(this._community) : instanceHost = _community.instanceHost, - communityId = _community.id, - communityName = _community.name; + communityId = _community.community.id, + communityName = _community.community.name; @override Widget build(BuildContext context) { @@ -57,15 +57,15 @@ class CommunityPage extends HookWidget { final token = accountsStore.defaultTokenFor(instanceHost); if (communityId != null) { - return LemmyApi(instanceHost).v1.getCommunity( - id: communityId, - auth: token?.raw, - ); + return LemmyApiV2(instanceHost).run(GetCommunity( + id: communityId, + auth: token?.raw, + )); } else { - return LemmyApi(instanceHost).v1.getCommunity( - name: communityName, - auth: token?.raw, - ); + return LemmyApiV2(instanceHost).run(GetCommunity( + name: communityName, + auth: token?.raw, + )); } }); @@ -73,7 +73,7 @@ class CommunityPage extends HookWidget { final community = () { if (fullCommunitySnap.hasData) { - return fullCommunitySnap.data.community; + return fullCommunitySnap.data.communityView; } else if (_community != null) { return _community; } else { @@ -111,7 +111,7 @@ class CommunityPage extends HookWidget { // FUNCTIONS void _share() => - Share.text('Share instance', community.actorId, 'text/plain'); + Share.text('Share instance', community.community.actorId, 'text/plain'); void _openMoreMenu() { showModalBottomSheet( @@ -123,8 +123,9 @@ class CommunityPage extends HookWidget { ListTile( leading: const Icon(Icons.open_in_browser), title: const Text('Open in browser'), - onTap: () async => await ul.canLaunch(community.actorId) - ? ul.launch(community.actorId) + onTap: () async => await ul + .canLaunch(community.community.actorId) + ? ul.launch(community.community.actorId) : Scaffold.of(context).showSnackBar( const SnackBar(content: Text("can't open in browser"))), ), @@ -133,11 +134,10 @@ class CommunityPage extends HookWidget { title: const Text('Nerd stuff'), onTap: () { showInfoTablePopup(context, { - 'id': community.id, - 'actorId': community.actorId, - 'created by': '@${community.creatorName}', - 'hot rank': community.hotRank, - 'published': community.published, + 'id': community.community.id, + 'actorId': community.community.actorId, + 'created by': '@${community.creator.name}', + 'published': community.community.published, }); }, ), @@ -160,7 +160,7 @@ class CommunityPage extends HookWidget { backgroundColor: theme.cardColor, brightness: theme.brightness, iconTheme: theme.iconTheme, - title: Text('!${community.name}', + title: Text('!${community.community.name}', style: TextStyle(color: colorOnCard)), actions: [ IconButton(icon: const Icon(Icons.share), onPressed: _share), @@ -190,26 +190,26 @@ class CommunityPage extends HookWidget { children: [ InfinitePostList( fetcher: (page, batchSize, sort) => - LemmyApi(community.instanceHost).v1.getPosts( - type: PostListingType.community, - sort: sort, - communityId: community.id, - page: page, - limit: batchSize, - ), + LemmyApiV2(community.instanceHost).run(GetPosts( + type: PostListingType.community, + sort: sort, + communityId: community.community.id, + page: page, + limit: batchSize, + )), ), InfiniteCommentList( fetcher: (page, batchSize, sortType) => - LemmyApi(community.instanceHost).v1.getComments( - communityId: community.id, - auth: accountsStore - .defaultTokenFor(community.instanceHost) - ?.raw, - type: CommentListingType.community, - sort: sortType, - limit: batchSize, - page: page, - )), + LemmyApiV2(community.instanceHost).run(GetComments( + communityId: community.community.id, + auth: accountsStore + .defaultTokenFor(community.instanceHost) + ?.raw, + type: CommentListingType.community, + sort: sortType, + limit: batchSize, + page: page, + ))), _AboutTab( community: community, moderators: fullCommunitySnap.data?.moderators, @@ -237,7 +237,7 @@ class _CommunityOverview extends StatelessWidget { final theme = Theme.of(context); final shadow = BoxShadow(color: theme.canvasColor, blurRadius: 5); - final icon = community.icon != null + final icon = community.community.icon != null ? Stack( alignment: Alignment.center, children: [ @@ -256,9 +256,9 @@ class _CommunityOverview extends StatelessWidget { width: 83, height: 83, child: FullscreenableImage( - url: community.icon, + url: community.community.icon, child: CachedNetworkImage( - imageUrl: community.icon, + imageUrl: community.community.icon, imageBuilder: (context, imageProvider) => Container( decoration: BoxDecoration( shape: BoxShape.circle, @@ -277,11 +277,11 @@ class _CommunityOverview extends StatelessWidget { : null; return Stack(children: [ - if (community.banner != null) + if (community.community.banner != null) FullscreenableImage( - url: community.banner, + url: community.community.banner, child: CachedNetworkImage( - imageUrl: community.banner, + imageUrl: community.community.banner, errorWidget: (_, __, ___) => const SizedBox.shrink(), ), ), @@ -289,7 +289,7 @@ class _CommunityOverview extends StatelessWidget { child: Padding( padding: const EdgeInsets.only(top: 45), child: Column(children: [ - if (community.icon != null) icon, + if (community.community.icon != null) icon, // NAME Center( child: Padding( @@ -304,7 +304,7 @@ class _CommunityOverview extends StatelessWidget { text: '!', style: TextStyle(fontWeight: FontWeight.w200)), TextSpan( - text: community.name, + text: community.community.name, style: const TextStyle(fontWeight: FontWeight.w600)), const TextSpan( text: '@', @@ -326,7 +326,7 @@ class _CommunityOverview extends StatelessWidget { child: Padding( padding: const EdgeInsets.only(top: 8, left: 20, right: 20), child: Text( - community.title, + community.community.title, textAlign: TextAlign.center, style: TextStyle(fontWeight: FontWeight.w300, shadows: [shadow]), @@ -346,7 +346,7 @@ class _CommunityOverview extends StatelessWidget { padding: EdgeInsets.only(right: 3), child: Icon(Icons.people, size: 20), ), - Text(compactNumber(community.numberOfSubscribers)), + Text(compactNumber(community.counts.subscribers)), const Spacer( flex: 4, ), @@ -416,10 +416,10 @@ class _AboutTab extends StatelessWidget { return ListView( padding: const EdgeInsets.only(top: 20), children: [ - if (community.description != null) ...[ + if (community.community.description != null) ...[ Padding( padding: const EdgeInsets.symmetric(horizontal: 15), - child: MarkdownText(community.description, + child: MarkdownText(community.community.description, instanceHost: community.instanceHost), ), const _Divider(), @@ -435,13 +435,13 @@ class _AboutTab extends StatelessWidget { child: _Badge('X users online'), ), _Badge( - '''${community.numberOfSubscribers} subscriber${pluralS(community.numberOfSubscribers)}'''), + '''${community.counts.subscribers} subscriber${pluralS(community.counts.subscribers)}'''), _Badge( - '''${community.numberOfPosts} post${pluralS(community.numberOfPosts)}'''), + '''${community.counts.posts} post${pluralS(community.counts.posts)}'''), Padding( padding: const EdgeInsets.only(right: 15), child: _Badge( - '''${community.numberOfComments} comment${pluralS(community.numberOfComments)}'''), + '''${community.counts.comments} comment${pluralS(community.counts.comments)}'''), ), ], ), @@ -454,7 +454,7 @@ class _AboutTab extends StatelessWidget { borderRadius: BorderRadius.circular(10), ), onPressed: goToCategories, - child: Text(community.categoryName), + child: Text(community.category.name), ), ), const _Divider(), @@ -475,9 +475,12 @@ class _AboutTab extends StatelessWidget { child: Text('Mods:', style: theme.textTheme.subtitle2), ), for (final mod in moderators) + // TODO: add user picture, maybe make it into reusable component ListTile( - title: Text(mod.userPreferredUsername ?? '@${mod.userName}'), - onTap: () => goToUser.byId(context, mod.instanceHost, mod.userId), + title: Text( + mod.moderator.preferredUsername ?? '@${mod.moderator.name}'), + onTap: () => + goToUser.byId(context, mod.instanceHost, mod.moderator.id), ), ] ], @@ -536,10 +539,10 @@ class _FollowButton extends HookWidget { subscribe(Jwt token) async { delayed.start(); try { - await LemmyApi(community.instanceHost).v1.followCommunity( - communityId: community.id, + await LemmyApiV2(community.instanceHost).run(FollowCommunity( + communityId: community.community.id, follow: !isSubbed.value, - auth: token.raw); + auth: token.raw)); isSubbed.value = !isSubbed.value; // ignore: avoid_catches_without_on_clauses } catch (e) { diff --git a/lib/pages/create_post.dart b/lib/pages/create_post.dart index 0ffa4ce..abb340b 100644 --- a/lib/pages/create_post.dart +++ b/lib/pages/create_post.dart @@ -2,7 +2,8 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:image_picker/image_picker.dart'; -import 'package:lemmy_api_client/lemmy_api_client.dart'; +import 'package:lemmy_api_client/pictrs.dart'; +import 'package:lemmy_api_client/v2.dart'; import '../hooks/delayed_loading.dart'; import '../hooks/image_picker.dart'; @@ -26,20 +27,20 @@ class CreatePostFab extends HookWidget { return FloatingActionButton( onPressed: loggedInAction((_) => showCupertinoModalPopup( - context: context, builder: (_) => CreatePost())), + context: context, builder: (_) => CreatePostPage())), child: const Icon(Icons.add), ); } } /// Modal for creating a post to some community in some instance -class CreatePost extends HookWidget { +class CreatePostPage extends HookWidget { final CommunityView community; final GlobalKey scaffoldKey = GlobalKey(); - CreatePost() : community = null; - CreatePost.toCommunity(this.community); + CreatePostPage() : community = null; + CreatePostPage.toCommunity(this.community); @override Widget build(BuildContext context) { @@ -58,16 +59,15 @@ class CreatePost extends HookWidget { final pictrsDeleteToken = useState(null); final allCommunitiesSnap = useMemoFuture( - () => LemmyApi(selectedInstance.value) - .v1 - .listCommunities( - sort: SortType.hot, - limit: 9999, - auth: accStore.defaultTokenFor(selectedInstance.value).raw, - ) + () => LemmyApiV2(selectedInstance.value) + .run(ListCommunities( + sort: SortType.hot, + limit: 9999, + auth: accStore.defaultTokenFor(selectedInstance.value).raw, + )) .then( (value) { - value.sort((a, b) => a.name.compareTo(b.name)); + value.sort((a, b) => a.community.name.compareTo(b.community.name)); return value; }, ), @@ -82,7 +82,7 @@ class CreatePost extends HookWidget { imageUploadLoading.value = true; final token = accStore.defaultTokenFor(selectedInstance.value); - final pictrs = LemmyApi(selectedInstance.value).pictrs; + final pictrs = PictrsApi(selectedInstance.value); final upload = await pictrs.upload(filePath: pic.path, auth: token.raw); pictrsDeleteToken.value = upload.files[0]; @@ -100,8 +100,7 @@ class CreatePost extends HookWidget { } removePicture() { - LemmyApi(selectedInstance.value) - .pictrs + PictrsApi(selectedInstance.value) .delete(pictrsDeleteToken.value) .catchError((_) {}); @@ -135,15 +134,16 @@ class CreatePost extends HookWidget { border: OutlineInputBorder()), child: DropdownButtonHideUnderline( child: DropdownButton( - value: selectedCommunity.value?.name, + value: selectedCommunity.value?.community?.name, hint: const Text('Community'), - onChanged: (val) => selectedCommunity.value = - allCommunitiesSnap.data.firstWhere((e) => e.name == val), + onChanged: (val) => selectedCommunity.value = allCommunitiesSnap.data + .firstWhere((e) => e.community.name == val), items: allCommunitiesSnap.hasData ? allCommunitiesSnap.data + // FIXME: use id instead of name cuz it breaks with federation .map((e) => DropdownMenuItem( - value: e.name, - child: Text(e.name), + value: e.community.name, + child: Text(e.community.name), )) .toList() : const [ @@ -219,19 +219,20 @@ class CreatePost extends HookWidget { return; } - final api = LemmyApi(selectedInstance.value).v1; + final api = LemmyApiV2(selectedInstance.value); final token = accStore.defaultTokenFor(selectedInstance.value); delayed.start(); try { - final res = await api.createPost( - url: urlController.text.isEmpty ? null : urlController.text, - body: bodyController.text.isEmpty ? null : bodyController.text, - nsfw: nsfw.value, - name: titleController.text, - communityId: selectedCommunity.value.id, - auth: token.raw); + final res = await api.run(CreatePost( + url: urlController.text.isEmpty ? null : urlController.text, + body: bodyController.text.isEmpty ? null : bodyController.text, + nsfw: nsfw.value, + name: titleController.text, + communityId: selectedCommunity.value.community.id, + auth: token.raw, + )); unawaited(goToReplace(context, (_) => FullPostPage.fromPostView(res))); return; // ignore: avoid_catches_without_on_clauses diff --git a/lib/pages/full_post.dart b/lib/pages/full_post.dart index 4478421..ed86941 100644 --- a/lib/pages/full_post.dart +++ b/lib/pages/full_post.dart @@ -3,7 +3,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:lemmy_api_client/lemmy_api_client.dart'; +import 'package:lemmy_api_client/v2.dart'; import '../hooks/logged_in_action.dart'; import '../hooks/refreshable.dart'; @@ -25,15 +25,17 @@ class FullPostPage extends HookWidget { assert(instanceHost != null), post = null; FullPostPage.fromPostView(this.post) - : id = post.id, + : id = post.post.id, instanceHost = post.instanceHost; @override Widget build(BuildContext context) { final accStore = useAccountsStore(); - final fullPostRefreshable = useRefreshable(() => LemmyApi(instanceHost) - .v1 - .getPost(id: id, auth: accStore.defaultTokenFor(instanceHost)?.raw)); + final fullPostRefreshable = + useRefreshable(() => LemmyApiV2(instanceHost).run(GetPost( + id: id, + auth: accStore.defaultTokenFor(instanceHost)?.raw, + ))); final loggedInAction = useLoggedInAction(instanceHost); final newComments = useState(const []); @@ -58,7 +60,7 @@ class FullPostPage extends HookWidget { // VARIABLES final post = fullPostRefreshable.snapshot.hasData - ? fullPostRefreshable.snapshot.data.post + ? fullPostRefreshable.snapshot.data.postView : this.post; final fullPost = fullPostRefreshable.snapshot.data; @@ -78,7 +80,7 @@ class FullPostPage extends HookWidget { } } - sharePost() => Share.text('Share post', post.apId, 'text/plain'); + sharePost() => Share.text('Share post', post.post.apId, 'text/plain'); comment() async { final newComment = await showCupertinoModalPopup( @@ -98,7 +100,7 @@ class FullPostPage extends HookWidget { SavePostButton(post), IconButton( icon: Icon(moreIcon), - onPressed: () => Post.showMoreMenu(context, post)), + onPressed: () => PostWidget.showMoreMenu(context, post)), ], ), floatingActionButton: FloatingActionButton( @@ -109,11 +111,11 @@ class FullPostPage extends HookWidget { child: ListView( physics: const AlwaysScrollableScrollPhysics(), children: [ - Post(post, fullPost: true), + PostWidget(post, fullPost: true), if (fullPostRefreshable.snapshot.hasData) CommentSection( newComments.value.followedBy(fullPost.comments).toList(), - postCreatorId: fullPost.post.creatorId) + postCreatorId: fullPost.postView.creator.id) else if (fullPostRefreshable.snapshot.hasError) Padding( padding: diff --git a/lib/pages/home_tab.dart b/lib/pages/home_tab.dart index 1e3f936..7276fc2 100644 --- a/lib/pages/home_tab.dart +++ b/lib/pages/home_tab.dart @@ -4,7 +4,7 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:lemmy_api_client/lemmy_api_client.dart'; +import 'package:lemmy_api_client/v2.dart'; import '../hooks/infinite_scroll.dart'; import '../hooks/memo_future.dart'; @@ -35,10 +35,11 @@ class HomeTab extends HookWidget { final instancesIcons = useMemoFuture(() async { final instances = accStore.instances.toList(growable: false); final sites = await Future.wait(instances - .map((e) => LemmyApi(e).v1.getSite().catchError((e) => null))); + .map((e) => LemmyApiV2(e).run(GetSite()).catchError((e) => null))); return { - for (var i = 0; i < sites.length; i++) instances[i]: sites[i].site.icon + for (var i = 0; i < sites.length; i++) + instances[i]: sites[i].siteView.site.icon }; }); @@ -262,13 +263,13 @@ class InfiniteHomeList extends HookWidget { }(); final futures = - instances.map((instanceHost) => LemmyApi(instanceHost).v1.getPosts( + instances.map((instanceHost) => LemmyApiV2(instanceHost).run(GetPosts( type: listingType, sort: sort, page: page, limit: limit, auth: accStore.defaultTokenFor(instanceHost)?.raw, - )); + ))); final posts = await Future.wait(futures); final newPosts = []; final longest = posts.map((e) => e.length).reduce(max); @@ -286,13 +287,13 @@ class InfiniteHomeList extends HookWidget { Future> Function(int, int) fetcherFromInstance( String instanceHost, PostListingType listingType, SortType sort) => - (page, batchSize) => LemmyApi(instanceHost).v1.getPosts( + (page, batchSize) => LemmyApiV2(instanceHost).run(GetPosts( type: listingType, sort: sort, page: page, limit: batchSize, auth: accStore.defaultTokenFor(instanceHost)?.raw, - ); + )); return InfiniteScroll( prepend: Column( @@ -305,7 +306,7 @@ class InfiniteHomeList extends HookWidget { ), builder: (post) => Column( children: [ - Post(post), + PostWidget(post), const SizedBox(height: 20), ], ), diff --git a/lib/pages/instance.dart b/lib/pages/instance.dart index 8ebef98..34e025d 100644 --- a/lib/pages/instance.dart +++ b/lib/pages/instance.dart @@ -3,7 +3,7 @@ import 'package:esys_flutter_share/esys_flutter_share.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:lemmy_api_client/lemmy_api_client.dart'; +import 'package:lemmy_api_client/v2.dart'; import 'package:url_launcher/url_launcher.dart' as ul; import '../hooks/stores.dart'; @@ -30,9 +30,9 @@ class InstancePage extends HookWidget { InstancePage({@required this.instanceHost}) : assert(instanceHost != null), - siteFuture = LemmyApi(instanceHost).v1.getSite(), + siteFuture = LemmyApiV2(instanceHost).run(GetSite()), communitiesFuture = - LemmyApi(instanceHost).v1.listCommunities(sort: SortType.hot); + LemmyApiV2(instanceHost).run(ListCommunities(sort: SortType.hot)); @override Widget build(BuildContext context) { @@ -80,8 +80,8 @@ class InstancePage extends HookWidget { leading: const Icon(Icons.open_in_browser), title: const Text('Open in browser'), onTap: () async => await ul - .canLaunch('https://${site.site.instanceHost}') - ? ul.launch('https://${site.site.instanceHost}') + .canLaunch('https://${site.instanceHost}') + ? ul.launch('https://${site.instanceHost}') : Scaffold.of(context).showSnackBar( const SnackBar(content: Text("can't open in browser"))), ), @@ -91,12 +91,12 @@ class InstancePage extends HookWidget { onTap: () { showInfoTablePopup(context, { 'url': instanceHost, - 'creator': '@${site.site.creatorName}', + 'creator': '@${site.siteView.creator.name}', 'version': site.version, - 'enableDownvotes': site.site.enableDownvotes, - 'enableNsfw': site.site.enableNsfw, - 'published': site.site.published, - 'updated': site.site.updated, + 'enableDownvotes': site.siteView.site.enableDownvotes, + 'enableNsfw': site.siteView.site.enableNsfw, + 'published': site.siteView.site.published, + 'updated': site.siteView.site.updated, }); }, ), @@ -119,7 +119,7 @@ class InstancePage extends HookWidget { backgroundColor: theme.cardColor, iconTheme: theme.iconTheme, title: Text( - site.site.name, + site.siteView.site.name, style: TextStyle(color: colorOnCard), ), actions: [ @@ -130,11 +130,11 @@ class InstancePage extends HookWidget { ], flexibleSpace: FlexibleSpaceBar( background: Stack(children: [ - if (site.site.banner != null) + if (site.siteView.site.banner != null) FullscreenableImage( - url: site.site.banner, + url: site.siteView.site.banner, child: CachedNetworkImage( - imageUrl: site.site.banner, + imageUrl: site.siteView.site.banner, errorWidget: (_, __, ___) => const SizedBox.shrink(), ), ), @@ -144,20 +144,20 @@ class InstancePage extends HookWidget { children: [ Padding( padding: const EdgeInsets.only(top: 40), - child: site.site.icon == null + child: site.siteView.site.icon == null ? const SizedBox(height: 100, width: 100) : FullscreenableImage( - url: site.site.icon, + url: site.siteView.site.icon, child: CachedNetworkImage( width: 100, height: 100, - imageUrl: site.site.icon, + imageUrl: site.siteView.site.icon, errorWidget: (_, __, ___) => const Icon(Icons.warning), ), ), ), - Text(site.site.name, + Text(site.siteView.site.name, style: theme.textTheme.headline6), Text(instanceHost, style: theme.textTheme.caption) ], @@ -186,23 +186,23 @@ class InstancePage extends HookWidget { children: [ InfinitePostList( fetcher: (page, batchSize, sort) => - LemmyApi(instanceHost).v1.getPosts( - // TODO: switch between all and subscribed - type: PostListingType.all, - sort: sort, - limit: batchSize, - page: page, - auth: accStore.defaultTokenFor(instanceHost)?.raw, - )), + LemmyApiV2(instanceHost).run(GetPosts( + // TODO: switch between all and subscribed + type: PostListingType.all, + sort: sort, + limit: batchSize, + page: page, + auth: accStore.defaultTokenFor(instanceHost)?.raw, + ))), InfiniteCommentList( fetcher: (page, batchSize, sort) => - LemmyApi(instanceHost).v1.getComments( - type: CommentListingType.all, - sort: sort, - limit: batchSize, - page: page, - auth: accStore.defaultTokenFor(instanceHost)?.raw, - )), + LemmyApiV2(instanceHost).run(GetComments( + type: CommentListingType.all, + sort: sort, + limit: batchSize, + page: page, + auth: accStore.defaultTokenFor(instanceHost)?.raw, + ))), _AboutTab(site, communitiesFuture: communitiesFuture, instanceHost: instanceHost), @@ -268,13 +268,13 @@ class _AboutTab extends HookWidget { context, (_) => CommunitiesListPage( fetcher: (page, batchSize, sortType) => - LemmyApi(instanceHost).v1.listCommunities( - sort: sortType, - limit: batchSize, - page: page, - auth: accStore.defaultTokenFor(instanceHost)?.raw, - ), - title: 'Communities of ${site.site.name}', + LemmyApiV2(instanceHost).run(ListCommunities( + sort: sortType, + limit: batchSize, + page: page, + auth: accStore.defaultTokenFor(instanceHost)?.raw, + )), + title: 'Communities of ${site.siteView.site.name}', ), ); } @@ -287,7 +287,7 @@ class _AboutTab extends HookWidget { Padding( padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15), child: MarkdownText( - site.site.description, + site.siteView.site.description, instanceHost: instanceHost, ), ), @@ -299,10 +299,10 @@ class _AboutTab extends HookWidget { children: [ const SizedBox(width: 7), const _Badge('X users online'), - _Badge('${site.site.numberOfUsers} users'), - _Badge('${site.site.numberOfCommunities} communities'), - _Badge('${site.site.numberOfPosts} posts'), - _Badge('${site.site.numberOfComments} comments'), + _Badge('${site.siteView.counts.users} users'), + _Badge('${site.siteView.counts.communities} communities'), + _Badge('${site.siteView.counts.posts} posts'), + _Badge('${site.siteView.counts.comments} comments'), const SizedBox(width: 15), ], ), @@ -317,15 +317,15 @@ class _AboutTab extends HookWidget { ), ), if (commSnap.hasData) - ...commSnap.data.take(6).map((e) => ListTile( - onTap: () => - goToCommunity.byId(context, e.instanceHost, e.id), - title: Text(e.name), - leading: e.icon != null + ...commSnap.data.take(6).map((c) => ListTile( + onTap: () => goToCommunity.byId( + context, c.instanceHost, c.community.id), + title: Text(c.community.name), + leading: c.community.icon != null ? CachedNetworkImage( height: 50, width: 50, - imageUrl: e.icon, + imageUrl: c.community.icon, errorWidget: (_, __, ___) => const SizedBox(width: 50, height: 50), imageBuilder: (context, imageProvider) => Container( @@ -362,20 +362,20 @@ class _AboutTab extends HookWidget { ), ), ), - ...site.admins.map((e) => ListTile( - title: Text((e.preferredUsername == null || - e.preferredUsername.isEmpty) - ? '@${e.name}' - : e.preferredUsername), - subtitle: e.bio != null - ? MarkdownText(e.bio, instanceHost: instanceHost) + ...site.admins.map((u) => ListTile( + title: Text((u.user.preferredUsername == null || + u.user.preferredUsername.isEmpty) + ? '@${u.user.name}' + : u.user.preferredUsername), + subtitle: u.user.bio != null + ? MarkdownText(u.user.bio, instanceHost: instanceHost) : null, - onTap: () => goToUser.byId(context, instanceHost, e.id), - leading: e.avatar != null + onTap: () => goToUser.byId(context, instanceHost, u.user.id), + leading: u.user.avatar != null ? CachedNetworkImage( height: 50, width: 50, - imageUrl: e.avatar, + imageUrl: u.user.avatar, errorWidget: (_, __, ___) => const SizedBox(width: 50, height: 50), imageBuilder: (context, imageProvider) => Container( diff --git a/lib/pages/manage_account.dart b/lib/pages/manage_account.dart index 61d6eb6..f31e43b 100644 --- a/lib/pages/manage_account.dart +++ b/lib/pages/manage_account.dart @@ -2,7 +2,8 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:image_picker/image_picker.dart'; -import 'package:lemmy_api_client/lemmy_api_client.dart'; +import 'package:lemmy_api_client/pictrs.dart'; +import 'package:lemmy_api_client/v2.dart'; import '../hooks/delayed_loading.dart'; import '../hooks/image_picker.dart'; @@ -28,9 +29,8 @@ class ManageAccountPage extends HookWidget { final theme = Theme.of(context); final userFuture = useMemoized(() async { - final site = await LemmyApi(instanceHost) - .v1 - .getSite(auth: accountStore.tokenFor(instanceHost, username).raw); + final site = await LemmyApiV2(instanceHost).run( + GetSite(auth: accountStore.tokenFor(instanceHost, username).raw)); return site.myUser; }); @@ -45,7 +45,7 @@ class ManageAccountPage extends HookWidget { Text('@$instanceHost@$username', style: theme.textTheme.headline6), centerTitle: true, ), - body: FutureBuilder( + body: FutureBuilder( future: userFuture, builder: (_, userSnap) { if (userSnap.hasError) { @@ -67,7 +67,7 @@ class _ManageAccount extends HookWidget { : assert(user != null), super(key: key); - final User user; + final UserSafeSettings user; @override Widget build(BuildContext context) { @@ -104,35 +104,35 @@ class _ManageAccount extends HookWidget { saveDelayedLoading.start(); try { - await LemmyApi(user.instanceHost).v1.saveUserSettings( - showNsfw: showNsfw.value, - theme: user.theme, - defaultSortType: defaultSortType.value, - defaultListingType: defaultListingType.value, - lang: user.lang, - showAvatars: showAvatars.value, - sendNotificationsToEmail: sendNotificationsToEmail.value, - auth: token.raw, - avatar: avatar.current, - banner: banner.current, - newPassword: newPasswordController.text.isEmpty - ? null - : newPasswordController.text, - newPasswordVerify: newPasswordVerifyController.text.isEmpty - ? null - : newPasswordVerifyController.text, - oldPassword: oldPasswordController.text.isEmpty - ? null - : oldPasswordController.text, - matrixUserId: matrixUserController.text.isEmpty - ? null - : matrixUserController.text, - preferredUsername: displayNameController.text.isEmpty - ? null - : displayNameController.text, - bio: bioController.text.isEmpty ? null : bioController.text, - email: emailController.text.isEmpty ? null : emailController.text, - ); + await LemmyApiV2(user.instanceHost).run(SaveUserSettings( + showNsfw: showNsfw.value, + theme: user.theme, + defaultSortType: defaultSortType.value, + defaultListingType: defaultListingType.value, + lang: user.lang, + showAvatars: showAvatars.value, + sendNotificationsToEmail: sendNotificationsToEmail.value, + auth: token.raw, + avatar: avatar.current, + banner: banner.current, + newPassword: newPasswordController.text.isEmpty + ? null + : newPasswordController.text, + newPasswordVerify: newPasswordVerifyController.text.isEmpty + ? null + : newPasswordVerifyController.text, + oldPassword: oldPasswordController.text.isEmpty + ? null + : oldPasswordController.text, + matrixUserId: matrixUserController.text.isEmpty + ? null + : matrixUserController.text, + preferredUsername: displayNameController.text.isEmpty + ? null + : displayNameController.text, + bio: bioController.text.isEmpty ? null : bioController.text, + email: emailController.text.isEmpty ? null : emailController.text, + )); informAcceptedAvatarRef.current(); informAcceptedBannerRef.current(); @@ -186,10 +186,10 @@ class _ManageAccount extends HookWidget { deleteDelayedLoading.start(); try { - await LemmyApi(user.instanceHost).v1.deleteAccount( - password: deleteAccountPasswordController.text, - auth: token.raw, - ); + await LemmyApiV2(user.instanceHost).run(DeleteAccount( + password: deleteAccountPasswordController.text, + auth: token.raw, + )); accountsStore.removeAccount(user.instanceHost, user.name); Navigator.of(context).pop(); @@ -439,7 +439,7 @@ class _ManageAccount extends HookWidget { class _ImagePicker extends HookWidget { final String name; final String initialUrl; - final User user; + final UserSafeSettings user; final ValueChanged onChange; /// _ImagePicker will set the ref to a callback that can inform _ImagePicker @@ -478,10 +478,10 @@ class _ImagePicker extends HookWidget { if (pic != null) { delayedLoading.start(); - final upload = await LemmyApi(user.instanceHost).pictrs.upload( - filePath: pic.path, - auth: accountsStore.tokenFor(user.instanceHost, user.name).raw, - ); + final upload = await PictrsApi(user.instanceHost).upload( + filePath: pic.path, + auth: accountsStore.tokenFor(user.instanceHost, user.name).raw, + ); pictrsDeleteToken.value = upload.files[0]; url.value = pathToPictrs(user.instanceHost, pictrsDeleteToken.value.file); @@ -497,8 +497,7 @@ class _ImagePicker extends HookWidget { } removePicture({bool updateState = true}) { - LemmyApi(user.instanceHost) - .pictrs + PictrsApi(user.instanceHost) .delete(pictrsDeleteToken.value) .catchError((_) {}); diff --git a/lib/pages/search_results.dart b/lib/pages/search_results.dart index ec43e96..ab8819f 100644 --- a/lib/pages/search_results.dart +++ b/lib/pages/search_results.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:lemmy_api_client/lemmy_api_client.dart'; +import 'package:lemmy_api_client/v2.dart'; import '../comment_tree.dart'; import '../hooks/stores.dart'; @@ -82,14 +82,14 @@ class _SearchResultsList extends HookWidget { return SortableInfiniteList( fetcher: (page, batchSize, sort) async { - final s = await LemmyApi(instanceHost).v1.search( - q: query, - sort: sort, - type: type, - auth: accStore.defaultTokenFor(instanceHost)?.raw, - page: page, - limit: batchSize, - ); + final s = await LemmyApiV2(instanceHost).run(Search( + q: query, + sort: sort, + type: type, + auth: accStore.defaultTokenFor(instanceHost)?.raw, + page: page, + limit: batchSize, + )); switch (s.type) { case SearchType.comments: @@ -107,7 +107,7 @@ class _SearchResultsList extends HookWidget { builder: (data) { switch (type) { case SearchType.comments: - return Comment( + return CommentWidget( CommentTree(data as CommentView), postCreatorId: null, ); @@ -116,10 +116,10 @@ class _SearchResultsList extends HookWidget { case SearchType.posts: return Padding( padding: const EdgeInsets.only(bottom: 20), - child: Post(data as PostView), + child: PostWidget(data as PostView), ); case SearchType.users: - return UsersListItem(user: data as UserView); + return UsersListItem(user: data as UserViewSafe); default: throw UnimplementedError(); } diff --git a/lib/pages/user.dart b/lib/pages/user.dart index 4e14e99..0ac2304 100644 --- a/lib/pages/user.dart +++ b/lib/pages/user.dart @@ -1,7 +1,7 @@ import 'package:esys_flutter_share/esys_flutter_share.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:lemmy_api_client/lemmy_api_client.dart'; +import 'package:lemmy_api_client/v2.dart'; import '../widgets/user_profile.dart'; @@ -9,20 +9,20 @@ import '../widgets/user_profile.dart'; class UserPage extends HookWidget { final int userId; final String instanceHost; - final Future _userDetails; + final Future _userDetails; UserPage({@required this.userId, @required this.instanceHost}) : assert(userId != null), assert(instanceHost != null), - _userDetails = LemmyApi(instanceHost).v1.getUserDetails( - userId: userId, savedOnly: true, sort: SortType.active); + _userDetails = LemmyApiV2(instanceHost).run(GetUserDetails( + userId: userId, savedOnly: true, sort: SortType.active)); UserPage.fromName({@required this.instanceHost, @required String username}) : assert(instanceHost != null), assert(username != null), userId = null, - _userDetails = LemmyApi(instanceHost).v1.getUserDetails( - username: username, savedOnly: true, sort: SortType.active); + _userDetails = LemmyApiV2(instanceHost).run(GetUserDetails( + username: username, savedOnly: true, sort: SortType.active)); @override Widget build(BuildContext context) { @@ -52,7 +52,7 @@ class UserPage extends HookWidget { IconButton( icon: const Icon(Icons.share), onPressed: () => Share.text('Share user', - userDetailsSnap.data.user.actorId, 'text/plain'), + userDetailsSnap.data.userView.user.actorId, 'text/plain'), ) ] ], diff --git a/lib/pages/users_list.dart b/lib/pages/users_list.dart index b01af53..43e26a4 100644 --- a/lib/pages/users_list.dart +++ b/lib/pages/users_list.dart @@ -1,6 +1,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 'package:lemmy_api_client/v2.dart'; import '../util/goto.dart'; import '../widgets/markdown_text.dart'; @@ -8,7 +8,7 @@ import '../widgets/markdown_text.dart'; /// Infinite list of Users fetched by the given fetcher class UsersListPage extends StatelessWidget { final String title; - final List users; + final List users; const UsersListPage({Key key, @required this.users, this.title}) : assert(users != null), @@ -34,7 +34,7 @@ class UsersListPage extends StatelessWidget { } class UsersListItem extends StatelessWidget { - final UserView user; + final UserViewSafe user; const UsersListItem({Key key, @required this.user}) : assert(user != null), @@ -42,25 +42,25 @@ class UsersListItem extends StatelessWidget { @override Widget build(BuildContext context) => ListTile( - title: Text( - (user.preferredUsername == null || user.preferredUsername.isEmpty) - ? '@${user.name}' - : user.preferredUsername), - subtitle: user.bio != null + title: Text((user.user.preferredUsername == null || + user.user.preferredUsername.isEmpty) + ? '@${user.user.name}' + : user.user.preferredUsername), + subtitle: user.user.bio != null ? Opacity( opacity: 0.5, child: MarkdownText( - user.bio, + user.user.bio, instanceHost: user.instanceHost, ), ) : null, - onTap: () => goToUser.byId(context, user.instanceHost, user.id), - leading: user.avatar != null + onTap: () => goToUser.byId(context, user.instanceHost, user.user.id), + leading: user.user.avatar != null ? CachedNetworkImage( height: 50, width: 50, - imageUrl: user.avatar, + imageUrl: user.user.avatar, errorWidget: (_, __, ___) => const SizedBox(height: 50, width: 50), imageBuilder: (context, imageProvider) => Container( diff --git a/lib/stores/accounts_store.dart b/lib/stores/accounts_store.dart index b82e525..d2a9415 100644 --- a/lib/stores/accounts_store.dart +++ b/lib/stores/accounts_store.dart @@ -2,7 +2,7 @@ import 'dart:collection'; import 'dart:convert'; import 'package:flutter/foundation.dart'; -import 'package:lemmy_api_client/lemmy_api_client.dart'; +import 'package:lemmy_api_client/v2.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../util/unawaited.dart'; @@ -215,14 +215,15 @@ class AccountsStore extends ChangeNotifier { throw Exception('No such instance was added'); } - final lemmy = LemmyApi(instanceHost).v1; - - final token = await lemmy.login( + final lemmy = LemmyApiV2(instanceHost); + final token = await lemmy.run(Login( usernameOrEmail: usernameOrEmail, password: password, - ); - final userData = - await lemmy.getSite(auth: token.raw).then((value) => value.myUser); + )); + // lemmy.login(); + final userData = await lemmy + .run(GetSite(auth: token.raw)) + .then((value) => value.myUser); // TODO: change Mser to User _tokens[instanceHost][userData.name] = token; @@ -244,7 +245,7 @@ class AccountsStore extends ChangeNotifier { if (!assumeValid) { try { - await LemmyApi(instanceHost).v1.getSite(); + await LemmyApiV2(instanceHost).run(GetSite()); // ignore: avoid_catches_without_on_clauses } catch (_) { throw Exception('This instance seems to not exist'); diff --git a/lib/util/extensions/api.dart b/lib/util/extensions/api.dart index 19a428c..4990757 100644 --- a/lib/util/extensions/api.dart +++ b/lib/util/extensions/api.dart @@ -1,4 +1,4 @@ -import 'package:lemmy_api_client/lemmy_api_client.dart'; +import 'package:lemmy_api_client/v2.dart'; import '../cleanup_url.dart'; @@ -11,28 +11,28 @@ import '../cleanup_url.dart'; // [.isLocal] is true iff `.originInstanceHost == .instanceHost` extension GetInstanceCommunityView on CommunityView { - String get originInstanceHost => _extract(actorId); - bool get isLocal => originInstanceHost == instanceHost; + String get originInstanceHost => _extract(community.actorId); + // bool get isLocal => originInstanceHost == instanceHost; } -extension GetInstanceUserView on UserView { - String get originInstanceHost => _extract(actorId); - bool get isLocal => originInstanceHost == instanceHost; +extension GetInstanceUserView on UserViewSafe { + String get originInstanceHost => _extract(user.actorId); + // bool get isLocal => originInstanceHost == instanceHost; } extension GetInstanceCommunityFollowerView on CommunityFollowerView { - String get originInstanceHost => _extract(communityActorId); - bool get isLocal => originInstanceHost == instanceHost; + String get originInstanceHost => _extract(community.actorId); + // bool get isLocal => originInstanceHost == instanceHost; } extension GetInstancePostView on PostView { - String get originInstanceHost => _extract(apId); - bool get isLocal => originInstanceHost == instanceHost; + String get originInstanceHost => _extract(post.apId); + // bool get isLocal => originInstanceHost == instanceHost; } extension GetInstanceCommentView on CommentView { - String get originInstanceHost => _extract(apId); - bool get isLocal => originInstanceHost == instanceHost; + String get originInstanceHost => _extract(comment.apId); + // bool get isLocal => originInstanceHost == instanceHost; } // TODO: change it to something more robust? regex? diff --git a/lib/util/hot_rank.dart b/lib/util/hot_rank.dart index 6d56f4b..a8c6236 100644 --- a/lib/util/hot_rank.dart +++ b/lib/util/hot_rank.dart @@ -1,6 +1,6 @@ import 'dart:math' show log, max, pow, ln10; -import 'package:lemmy_api_client/lemmy_api_client.dart'; +import 'package:lemmy_api_client/v2.dart'; /// Calculates hot rank /// because API always claims it's `0` @@ -17,5 +17,6 @@ double _calculateHotRank(int score, DateTime time) { } extension CommentHotRank on CommentView { - double get computedHotRank => _calculateHotRank(score, published); + double get computedHotRank => + _calculateHotRank(counts.score, comment.published); } diff --git a/lib/widgets/comment_section.dart b/lib/widgets/comment_section.dart index 20e4e31..8ec9c29 100644 --- a/lib/widgets/comment_section.dart +++ b/lib/widgets/comment_section.dart @@ -1,7 +1,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:lemmy_api_client/lemmy_api_client.dart'; +import 'package:lemmy_api_client/v2.dart'; import '../comment_tree.dart'; import 'bottom_modal.dart'; @@ -29,7 +29,7 @@ class CommentSection extends HookWidget { }) : comments = CommentTree.sortList(sortType, CommentTree.fromList(rawComments)), rawComments = rawComments - ..sort((b, a) => a.published.compareTo(b.published)), + ..sort((b, a) => a.comment.published.compareTo(b.comment.published)), assert(postCreatorId != null); @override @@ -99,12 +99,13 @@ class CommentSection extends HookWidget { ) else if (sorting.value == CommentSortType.chat) for (final com in rawComments) - Comment( + CommentWidget( CommentTree(com), postCreatorId: postCreatorId, ) else - for (final com in comments) Comment(com, postCreatorId: postCreatorId), + for (final com in comments) + CommentWidget(com, postCreatorId: postCreatorId), const SizedBox(height: 50), ]); } diff --git a/lib/widgets/post.dart b/lib/widgets/post.dart index fcdc8ab..b0b39c7 100644 --- a/lib/widgets/post.dart +++ b/lib/widgets/post.dart @@ -5,7 +5,7 @@ import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:intl/intl.dart'; -import 'package:lemmy_api_client/lemmy_api_client.dart'; +import 'package:lemmy_api_client/v2.dart'; import 'package:timeago/timeago.dart' as timeago; import 'package:url_launcher/url_launcher.dart' as ul; @@ -47,12 +47,13 @@ MediaType whatType(String url) { } /// A post overview card -class Post extends HookWidget { +class PostWidget extends HookWidget { final PostView post; final String instanceHost; final bool fullPost; - Post(this.post, {this.fullPost = false}) : instanceHost = post.instanceHost; + PostWidget(this.post, {this.fullPost = false}) + : instanceHost = post.instanceHost; // == ACTIONS == @@ -66,8 +67,8 @@ class Post extends HookWidget { ListTile( leading: const Icon(Icons.open_in_browser), title: const Text('Open in browser'), - onTap: () async => await ul.canLaunch(post.apId) - ? ul.launch(post.apId) + onTap: () async => await ul.canLaunch(post.post.apId) + ? ul.launch(post.post.apId) : Scaffold.of(context).showSnackBar( const SnackBar(content: Text("can't open in browser"))), ), @@ -76,19 +77,16 @@ class Post extends HookWidget { title: const Text('Nerd stuff'), onTap: () { showInfoTablePopup(context, { - 'id': post.id, - 'apId': post.apId, - 'upvotes': post.upvotes, - 'downvotes': post.downvotes, - 'score': post.score, + 'id': post.post.id, + 'apId': post.post.apId, + 'upvotes': post.counts.upvotes, + 'downvotes': post.counts.downvotes, + 'score': post.counts.score, '% of upvotes': - '''${(100 * (post.upvotes / (post.upvotes + post.downvotes))).toInt()}%''', - 'hotRank': post.hotRank, - 'hotRank active': post.hotRankActive, - 'local': post.local, - 'published': post.published, - 'updated': post.updated ?? 'never', - 'newestActivityTime': post.newestActivityTime, + '''${(100 * (post.counts.upvotes / (post.counts.upvotes + post.counts.downvotes))).toInt()}%''', + 'local': post.post.local, + 'published': post.post.published, + 'updated': post.post.updated ?? 'never', }); }, ), @@ -104,12 +102,12 @@ class Post extends HookWidget { Widget build(BuildContext context) { final theme = Theme.of(context); void _openLink() => linkLauncher( - context: context, url: post.url, instanceHost: instanceHost); + context: context, url: post.post.url, instanceHost: instanceHost); final urlDomain = () { - if (whatType(post.url) == MediaType.none) return null; + if (whatType(post.post.url) == MediaType.none) return null; - final url = post.url.split('/')[2]; + final url = post.post.url.split('/')[2]; // TODO: change to Url(str).host if (url.startsWith('www.')) return url.substring(4); return url; }(); @@ -122,12 +120,12 @@ class Post extends HookWidget { Column( mainAxisSize: MainAxisSize.min, children: [ - if (post.communityIcon != null) + if (post.community.icon != null) Padding( padding: const EdgeInsets.only(right: 10), child: InkWell( onTap: () => goToCommunity.byId( - context, instanceHost, post.communityId), + context, instanceHost, post.community.id), child: SizedBox( height: 40, width: 40, @@ -141,7 +139,7 @@ class Post extends HookWidget { ), ), ), - imageUrl: post.communityIcon, + imageUrl: post.community.icon, errorWidget: (context, url, error) => Text(error.toString()), ), @@ -165,12 +163,12 @@ class Post extends HookWidget { text: '!', style: TextStyle(fontWeight: FontWeight.w300)), TextSpan( - text: post.communityName, + text: post.community.name, style: const TextStyle(fontWeight: FontWeight.w600), recognizer: TapGestureRecognizer() ..onTap = () => goToCommunity.byId( - context, instanceHost, post.communityId)), + context, instanceHost, post.community.id)), const TextSpan( text: '@', style: TextStyle(fontWeight: FontWeight.w300)), @@ -198,28 +196,32 @@ class Post extends HookWidget { style: TextStyle(fontWeight: FontWeight.w300)), TextSpan( text: - ''' ${post.creatorPreferredUsername ?? post.creatorName}''', + ''' ${post.creator.preferredUsername ?? post.creator.name}''', style: const TextStyle(fontWeight: FontWeight.w600), recognizer: TapGestureRecognizer() ..onTap = () => goToUser.byId( - context, post.instanceHost, post.creatorId), + context, + post.instanceHost, + post.creator.id, + ), ), TextSpan( text: - ''' ยท ${timeago.format(post.published, locale: 'en_short')}'''), - if (post.locked) const TextSpan(text: ' ยท ๐Ÿ”’'), - if (post.stickied) const TextSpan(text: ' ยท ๐Ÿ“Œ'), - if (post.nsfw) const TextSpan(text: ' ยท '), - if (post.nsfw) + ''' ยท ${timeago.format(post.post.published, locale: 'en_short')}'''), + if (post.post.locked) const TextSpan(text: ' ยท ๐Ÿ”’'), + if (post.post.stickied) + const TextSpan(text: ' ยท ๐Ÿ“Œ'), + if (post.post.nsfw) const TextSpan(text: ' ยท '), + if (post.post.nsfw) const TextSpan( text: 'NSFW', style: TextStyle(color: Colors.red)), if (urlDomain != null) TextSpan(text: ' ยท $urlDomain'), - if (post.removed) + if (post.post.removed) const TextSpan(text: ' ยท REMOVED'), - if (post.deleted) + if (post.post.deleted) const TextSpan(text: ' ยท DELETED'), ], )) @@ -250,15 +252,15 @@ class Post extends HookWidget { Expanded( flex: 100, child: Text( - post.name, + post.post.name, textAlign: TextAlign.left, softWrap: true, style: const TextStyle( fontSize: 18, fontWeight: FontWeight.w600), ), ), - if (whatType(post.url) == MediaType.other && - post.thumbnailUrl != null) ...[ + if (whatType(post.post.url) == MediaType.other && + post.post.thumbnailUrl != null) ...[ const Spacer(), InkWell( onTap: _openLink, @@ -266,7 +268,7 @@ class Post extends HookWidget { ClipRRect( borderRadius: BorderRadius.circular(20), child: CachedNetworkImage( - imageUrl: post.thumbnailUrl, + imageUrl: post.post.thumbnailUrl, width: 70, height: 70, fit: BoxFit.cover, @@ -291,7 +293,7 @@ class Post extends HookWidget { /// assemble link preview Widget linkPreview() { - assert(post.url != null); + assert(post.post.url != null); return Padding( padding: const EdgeInsets.all(10), @@ -315,14 +317,14 @@ class Post extends HookWidget { ]), Row(children: [ Flexible( - child: Text(post.embedTitle ?? '', + child: Text(post.post.embedTitle ?? '', style: theme.textTheme.subtitle1 .apply(fontWeightDelta: 2))) ]), - if (post.embedDescription != null && - post.embedDescription.isNotEmpty) + if (post.post.embedDescription != null && + post.post.embedDescription.isNotEmpty) Row(children: [ - Flexible(child: Text(post.embedDescription)) + Flexible(child: Text(post.post.embedDescription)) ]), ], ), @@ -334,12 +336,12 @@ class Post extends HookWidget { /// assemble image Widget postImage() { - assert(post.url != null); + assert(post.post.url != null); return FullscreenableImage( - url: post.url, + url: post.post.url, child: CachedNetworkImage( - imageUrl: post.url, + imageUrl: post.post.url, errorWidget: (_, __, ___) => const Icon(Icons.warning), progressIndicatorBuilder: (context, url, progress) => CircularProgressIndicator(value: progress.progress), @@ -356,7 +358,8 @@ class Post extends HookWidget { Expanded( flex: 999, child: Text( - ''' ${NumberFormat.compact().format(post.numberOfComments)} comment${post.numberOfComments == 1 ? '' : 's'}''', + ' ${NumberFormat.compact().format(post.counts.comments)}' + ' comment${post.counts.comments == 1 ? '' : 's'}', overflow: TextOverflow.fade, softWrap: false, ), @@ -365,7 +368,9 @@ class Post extends HookWidget { if (!fullPost) IconButton( icon: const Icon(Icons.share), - onPressed: () => Share.text('Share post url', post.apId, + onPressed: () => Share.text( + 'Share post url', + post.post.apId, 'text/plain')), // TODO: find a way to mark it as url if (!fullPost) SavePostButton(post), _Voting(post), @@ -387,16 +392,17 @@ class Post extends HookWidget { children: [ info(), title(), - if (whatType(post.url) != MediaType.other && - whatType(post.url) != MediaType.none) + if (whatType(post.post.url) != MediaType.other && + whatType(post.post.url) != MediaType.none) postImage() - else if (post.url != null && post.url.isNotEmpty) + else if (post.post.url != null && post.post.url.isNotEmpty) linkPreview(), - if (post.body != null) + if (post.post.body != null) // TODO: trim content Padding( padding: const EdgeInsets.all(10), - child: MarkdownText(post.body, instanceHost: instanceHost)), + child: + MarkdownText(post.post.body, instanceHost: instanceHost)), actions(), ], ), @@ -421,12 +427,12 @@ class _Voting extends HookWidget { final loggedInAction = useLoggedInAction(post.instanceHost); vote(VoteType vote, Jwt token) async { - final api = LemmyApi(post.instanceHost).v1; + final api = LemmyApiV2(post.instanceHost); loading.start(); try { - final res = await api.createPostLike( - postId: post.id, score: vote, auth: token.raw); + final res = await api.run( + CreatePostLike(postId: post.post.id, score: vote, auth: token.raw)); myVote.value = res.myVote; // ignore: avoid_catches_without_on_clauses } catch (e) { @@ -455,7 +461,7 @@ class _Voting extends HookWidget { width: 20, height: 20, child: CircularProgressIndicator()) else Text(NumberFormat.compact() - .format(post.score + (wasVoted ? 0 : myVote.value.value))), + .format(post.counts.score + (wasVoted ? 0 : myVote.value.value))), IconButton( icon: Icon( Icons.arrow_downward, diff --git a/lib/widgets/post_list_options.dart b/lib/widgets/post_list_options.dart index b467df6..3862ac6 100644 --- a/lib/widgets/post_list_options.dart +++ b/lib/widgets/post_list_options.dart @@ -1,7 +1,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:lemmy_api_client/lemmy_api_client.dart'; +import 'package:lemmy_api_client/v2.dart'; import 'bottom_modal.dart'; diff --git a/lib/widgets/save_post_button.dart b/lib/widgets/save_post_button.dart index 5675de8..564e73c 100644 --- a/lib/widgets/save_post_button.dart +++ b/lib/widgets/save_post_button.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:lemmy_api_client/lemmy_api_client.dart'; +import 'package:lemmy_api_client/v2.dart'; import '../hooks/delayed_loading.dart'; import '../hooks/logged_in_action.dart'; @@ -20,12 +20,12 @@ class SavePostButton extends HookWidget { final loggedInAction = useLoggedInAction(post.instanceHost); savePost(Jwt token) async { - final api = LemmyApi(post.instanceHost).v1; + final api = LemmyApiV2(post.instanceHost); loading.start(); try { - final res = await api.savePost( - postId: post.id, save: !isSaved.value, auth: token.raw); + final res = await api.run(SavePost( + postId: post.post.id, save: !isSaved.value, auth: token.raw)); isSaved.value = res.saved; // ignore: avoid_catches_without_on_clauses } catch (e) { diff --git a/lib/widgets/sortable_infinite_list.dart b/lib/widgets/sortable_infinite_list.dart index e313f51..946bbe2 100644 --- a/lib/widgets/sortable_infinite_list.dart +++ b/lib/widgets/sortable_infinite_list.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:lemmy_api_client/lemmy_api_client.dart'; +import 'package:lemmy_api_client/v2.dart'; import '../comment_tree.dart'; import '../hooks/infinite_scroll.dart'; @@ -57,7 +57,7 @@ class InfinitePostList extends StatelessWidget { onStyleChange: () {}, builder: (post) => Column( children: [ - Post(post), + PostWidget(post), const SizedBox(height: 20), ], ), @@ -72,7 +72,7 @@ class InfiniteCommentList extends StatelessWidget { const InfiniteCommentList({@required this.fetcher}) : assert(fetcher != null); Widget build(BuildContext context) => SortableInfiniteList( - builder: (comment) => Comment( + builder: (comment) => CommentWidget( CommentTree(comment), postCreatorId: null, detached: true, diff --git a/lib/widgets/user_profile.dart b/lib/widgets/user_profile.dart index ee9cfb7..7447dc1 100644 --- a/lib/widgets/user_profile.dart +++ b/lib/widgets/user_profile.dart @@ -2,7 +2,7 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:intl/intl.dart'; -import 'package:lemmy_api_client/lemmy_api_client.dart'; +import 'package:lemmy_api_client/v2.dart'; import 'package:timeago/timeago.dart' as timeago; import '../hooks/stores.dart'; @@ -17,16 +17,16 @@ import 'sortable_infinite_list.dart'; /// Shared widget of UserPage and ProfileTab class UserProfile extends HookWidget { - final Future _userDetails; + final Future _userDetails; final String instanceHost; UserProfile({@required int userId, @required this.instanceHost}) - : _userDetails = LemmyApi(instanceHost).v1.getUserDetails( - userId: userId, savedOnly: false, sort: SortType.active); + : _userDetails = LemmyApiV2(instanceHost).run(GetUserDetails( + userId: userId, savedOnly: false, sort: SortType.active)); - UserProfile.fromUserDetails(UserDetails userDetails) + UserProfile.fromUserDetails(FullUserView userDetails) : _userDetails = Future.value(userDetails), - instanceHost = userDetails.user.instanceHost; + instanceHost = userDetails.instanceHost; @override Widget build(BuildContext context) { @@ -47,7 +47,7 @@ class UserProfile extends HookWidget { ); } - final userView = userDetailsSnap.data.user; + final userView = userDetailsSnap.data.userView; return DefaultTabController( length: 3, @@ -78,27 +78,25 @@ 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(instanceHost) - .v1 - .getUserDetails( - userId: userView.id, + fetcher: (page, batchSize, sort) => LemmyApiV2(instanceHost) + .run(GetUserDetails( + userId: userView.user.id, savedOnly: false, sort: SortType.active, page: page, limit: batchSize, - ) + )) .then((val) => val.posts), ), InfiniteCommentList( - fetcher: (page, batchSize, sort) => LemmyApi(instanceHost) - .v1 - .getUserDetails( - userId: userView.id, + fetcher: (page, batchSize, sort) => LemmyApiV2(instanceHost) + .run(GetUserDetails( + userId: userView.user.id, savedOnly: false, sort: SortType.active, page: page, limit: batchSize, - ) + )) .then((val) => val.comments), ), _AboutTab(userDetailsSnap.data), @@ -113,7 +111,7 @@ class UserProfile extends HookWidget { /// Such as his nickname, no. of posts, no. of posts, /// banner, avatar etc. class _UserOverview extends HookWidget { - final UserView userView; + final UserViewSafe userView; const _UserOverview(this.userView); @@ -125,12 +123,12 @@ class _UserOverview extends HookWidget { return Stack( children: [ - if (userView.banner != null) + if (userView.user.banner != null) // TODO: for some reason doesnt react to presses FullscreenableImage( - url: userView.banner, + url: userView.user.banner, child: CachedNetworkImage( - imageUrl: userView.banner, + imageUrl: userView.user.banner, errorWidget: (_, __, ___) => const SizedBox.shrink(), ), ) @@ -174,7 +172,7 @@ class _UserOverview extends HookWidget { SafeArea( child: Column( children: [ - if (userView.avatar != null) + if (userView.user.avatar != null) SizedBox( width: 80, height: 80, @@ -190,9 +188,9 @@ class _UserOverview extends HookWidget { child: ClipRRect( borderRadius: const BorderRadius.all(Radius.circular(12)), child: FullscreenableImage( - url: userView.avatar, + url: userView.user.avatar, child: CachedNetworkImage( - imageUrl: userView.avatar, + imageUrl: userView.user.avatar, errorWidget: (_, __, ___) => const SizedBox.shrink(), ), ), @@ -200,14 +198,14 @@ class _UserOverview extends HookWidget { ), ), Padding( - padding: userView.avatar != null + padding: userView.user.avatar != null ? const EdgeInsets.only(top: 8) : const EdgeInsets.only(top: 70), child: Padding( - padding: - EdgeInsets.only(top: userView.avatar == null ? 10 : 0), + padding: EdgeInsets.only( + top: userView.user.avatar == null ? 10 : 0), child: Text( - userView.preferredUsername ?? userView.name, + userView.user.preferredUsername ?? userView.user.name, style: theme.textTheme.headline6, ), ), @@ -218,7 +216,7 @@ class _UserOverview extends HookWidget { mainAxisAlignment: MainAxisAlignment.center, children: [ Text( - '@${userView.name}@', + '@${userView.user.name}@', style: theme.textTheme.caption, ), InkWell( @@ -248,8 +246,8 @@ class _UserOverview extends HookWidget { Padding( padding: const EdgeInsets.only(left: 4), child: Text( - '${compactNumber(userView.numberOfPosts)}' - ' Post${pluralS(userView.numberOfPosts)}', + '${compactNumber(userView.counts.postCount)}' + ' Post${pluralS(userView.counts.postCount)}', style: TextStyle(color: colorOnTopOfAccentColor), ), ), @@ -269,8 +267,8 @@ class _UserOverview extends HookWidget { Padding( padding: const EdgeInsets.only(left: 4), child: Text( - '${compactNumber(userView.numberOfComments)}' - ' Comment${pluralS(userView.numberOfComments)}', + '${compactNumber(userView.counts.commentCount)}' + ' Comment${pluralS(userView.counts.commentCount)}', style: TextStyle(color: colorOnTopOfAccentColor), ), @@ -285,7 +283,7 @@ class _UserOverview extends HookWidget { Padding( padding: const EdgeInsets.only(top: 15), child: Text( - 'Joined ${timeago.format(userView.published)}', + 'Joined ${timeago.format(userView.user.published)}', style: theme.textTheme.bodyText1, ), ), @@ -301,7 +299,8 @@ class _UserOverview extends HookWidget { Padding( padding: const EdgeInsets.only(left: 4), child: Text( - DateFormat('MMM dd, yyyy').format(userView.published), + DateFormat('MMM dd, yyyy') + .format(userView.user.published), style: theme.textTheme.bodyText1, ), ), @@ -318,19 +317,21 @@ class _UserOverview extends HookWidget { } class _AboutTab extends HookWidget { - final UserDetails userDetails; + final FullUserView userDetails; const _AboutTab(this.userDetails); @override Widget build(BuildContext context) { final theme = Theme.of(context); - final instanceHost = userDetails.user.instanceHost; + final instanceHost = userDetails.userView.user.instanceHost; final accStore = useAccountsStore(); final isOwnedAccount = accStore.loggedInInstances.contains(instanceHost) && - accStore.usernamesFor(instanceHost).contains(userDetails.user.name); + accStore + .usernamesFor(instanceHost) + .contains(userDetails.userView.user.name); const wallPadding = EdgeInsets.symmetric(horizontal: 15); @@ -378,10 +379,10 @@ class _AboutTab extends HookWidget { ), onTap: () {}, // TODO: go to account editing ), - if (userDetails.user.bio != null) ...[ + if (userDetails.userView.user.bio != null) ...[ Padding( padding: wallPadding, - child: MarkdownText(userDetails.user.bio, + child: MarkdownText(userDetails.userView.user.bio, instanceHost: instanceHost)), divider, ], @@ -396,9 +397,9 @@ class _AboutTab extends HookWidget { ), for (final comm in userDetails.moderates - ..sort((a, b) => a.communityName.compareTo(b.communityName))) + ..sort((a, b) => a.community.name.compareTo(b.community.name))) communityTile( - comm.communityName, comm.communityIcon, comm.communityId), + comm.community.name, comm.community.icon, comm.community.id), divider ], ListTile( @@ -412,9 +413,9 @@ class _AboutTab extends HookWidget { if (userDetails.follows.isNotEmpty) for (final comm in userDetails.follows - ..sort((a, b) => a.communityName.compareTo(b.communityName))) + ..sort((a, b) => a.community.name.compareTo(b.community.name))) communityTile( - comm.communityName, comm.communityIcon, comm.communityId) + comm.community.name, comm.community.icon, comm.community.id) else const Padding( padding: EdgeInsets.only(top: 8), diff --git a/lib/widgets/write_comment.dart b/lib/widgets/write_comment.dart index 9bffc6c..12aae80 100644 --- a/lib/widgets/write_comment.dart +++ b/lib/widgets/write_comment.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:lemmy_api_client/lemmy_api_client.dart'; +import 'package:lemmy_api_client/v2.dart'; import '../hooks/delayed_loading.dart'; import '../hooks/stores.dart'; @@ -32,7 +32,7 @@ class WriteComment extends HookWidget { final preview = () { final body = MarkdownText( - comment?.content ?? post.body ?? '', + comment?.comment?.content ?? post.post.body ?? '', instanceHost: instanceHost, ); @@ -40,7 +40,7 @@ class WriteComment extends HookWidget { return Column( children: [ Text( - post.name, + post.post.name, style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w600), ), const SizedBox(height: 4), @@ -53,17 +53,25 @@ class WriteComment extends HookWidget { }(); handleSubmit() async { - final api = LemmyApi(instanceHost).v1; + final api = LemmyApiV2(instanceHost); final token = accStore.defaultTokenFor(instanceHost); delayed.start(); try { - final res = await api.createComment( - content: controller.text, - postId: post?.id ?? comment.postId, - parentId: comment?.id, - auth: token.raw); + print(''' +CreateComment( + content: ${controller.text}, + postId: ${post?.post?.id ?? comment.post.id}, + parentId: ${comment?.comment?.id}, + auth: ${token.raw}, +)'''); + final res = await api.run(CreateComment( + content: controller.text, + postId: post?.post?.id ?? comment.post.id, + parentId: comment?.comment?.id, + auth: token.raw, + )); Navigator.of(context).pop(res); // ignore: avoid_catches_without_on_clauses } catch (e) { From 6555b8c6141f8f06f3f7733e32e3892efdf9cda7 Mon Sep 17 00:00:00 2001 From: krawieck Date: Sun, 24 Jan 2021 21:50:49 +0100 Subject: [PATCH 02/17] transition comment to v2 --- lib/widgets/comment.dart | 172 ++++++++++++++++++++++----------------- 1 file changed, 96 insertions(+), 76 deletions(-) diff --git a/lib/widgets/comment.dart b/lib/widgets/comment.dart index ec45e3f..7255140 100644 --- a/lib/widgets/comment.dart +++ b/lib/widgets/comment.dart @@ -4,13 +4,14 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:lemmy_api_client/lemmy_api_client.dart'; +import 'package:lemmy_api_client/v2.dart'; import 'package:timeago/timeago.dart' as timeago; 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 '../hooks/stores.dart'; import '../util/extensions/api.dart'; import '../util/goto.dart'; import '../util/intl.dart'; @@ -21,7 +22,7 @@ import 'markdown_text.dart'; import 'write_comment.dart'; /// A single comment that renders its replies -class Comment extends HookWidget { +class CommentWidget extends HookWidget { final int indent; final int postCreatorId; final CommentTree commentTree; @@ -37,7 +38,7 @@ class Comment extends HookWidget { Colors.indigo, ]; - Comment( + CommentWidget( this.commentTree, { this.indent = 0, @required this.postCreatorId, @@ -48,48 +49,58 @@ class Comment extends HookWidget { _showCommentInfo(BuildContext context) { final com = commentTree.comment; showInfoTablePopup(context, { - 'id': com.id, - 'creatorId': com.creatorId, - 'postId': com.postId, - 'postName': com.postName, - 'parentId': com.parentId, - 'removed': com.removed, - 'read': com.read, - 'published': com.published, - 'updated': com.updated, - 'deleted': com.deleted, - 'apId': com.apId, - 'local': com.local, - 'communityId': com.communityId, - 'communityActorId': com.communityActorId, - 'communityLocal': com.communityLocal, - 'communityName': com.communityName, - 'communityIcon': com.communityIcon, - 'banned': com.banned, - 'bannedFromCommunity': com.bannedFromCommunity, - 'creatorActirId': com.creatorActorId, - 'userId': com.userId, - 'upvotes': com.upvotes, - 'downvotes': com.downvotes, - 'score': com.score, - '% of upvotes': '${100 * (com.upvotes / (com.upvotes + com.downvotes))}%', - 'hotRank': com.hotRank, - 'hotRankActive': com.hotRankActive, + 'id': com.comment.id, + 'creatorId': com.comment.creatorId, + 'postId': com.comment.postId, + 'postName': com.post.name, + 'parentId': com.comment.parentId, + 'removed': com.comment.removed, + 'read': com.comment.read, + 'published': com.comment.published, + 'updated': com.comment.updated, + 'deleted': com.comment.deleted, + 'apId': com.comment.apId, + 'local': com.comment.local, + 'communityId': com.community.id, + 'communityActorId': com.community.actorId, + 'communityLocal': com.community.local, + 'communityName': com.community.name, + 'communityIcon': com.community.icon, + 'banned': com.creator.banned, + 'bannedFromCommunity': com.creatorBannedFromCommunity, + 'creatorActirId': com.creator.actorId, + 'userId': com.creator.id, + 'upvotes': com.counts.upvotes, + 'downvotes': com.counts.downvotes, + 'score': com.counts.score, + '% of upvotes': + '${100 * (com.counts.upvotes / (com.counts.upvotes + com.counts.downvotes))}%', }); } - bool get isOP => commentTree.comment.creatorId == postCreatorId; - bool get isMine => - commentTree.comment.creatorId == commentTree.comment.userId; + bool get isOP => + commentTree.comment.comment.creatorId == + commentTree.comment.post.creatorId; + + // bool get isMine => commentTree.comment.comment.creatorId == ; + + // commentTree.comment.comment.creatorId == commentTree.comment. + // commentTree.comment.userId; // FIXME: WHAT SHOULD REPLACE USER ID???? @override Widget build(BuildContext context) { + print(commentTree.comment.comment.id); final theme = Theme.of(context); + + final accStore = useAccountsStore(); + + final isMine = commentTree.comment.comment.creatorId == + accStore.defaultTokenFor(commentTree.comment.instanceHost).payload.id; final selectable = useState(false); final showRaw = useState(false); final collapsed = useState(false); final myVote = useState(commentTree.comment.myVote ?? VoteType.none); - final isDeleted = useState(commentTree.comment.deleted); + final isDeleted = useState(commentTree.comment.comment.deleted); final delayedVoting = useDelayedLoading(); final delayedDeletion = useDelayedLoading(); final loggedInAction = useLoggedInAction(commentTree.comment.instanceHost); @@ -98,14 +109,17 @@ class Comment extends HookWidget { final comment = commentTree.comment; handleDelete(Jwt token) async { - final api = LemmyApi(token.payload.iss).v1; + final api = LemmyApiV2(token.payload.iss); delayedDeletion.start(); Navigator.of(context).pop(); try { - final res = await api.deleteComment( - editId: comment.id, deleted: !isDeleted.value, auth: token.raw); - isDeleted.value = res.deleted; + final res = await api.run(DeleteComment( + commentId: comment.comment.id, + deleted: !isDeleted.value, + auth: token.raw, + )); + isDeleted.value = res.commentView.comment.deleted; // ignore: avoid_catches_without_on_clauses } catch (e) { Scaffold.of(context).showSnackBar( @@ -128,22 +142,22 @@ class Comment extends HookWidget { ListTile( leading: const Icon(Icons.open_in_browser), title: const Text('Open in browser'), - onTap: () async => await ul.canLaunch(com.apId) - ? ul.launch(com.apId) + onTap: () async => await ul.canLaunch(com.comment.apId) + ? ul.launch(com.comment.apId) : Scaffold.of(context).showSnackBar( const SnackBar(content: Text("can't open in browser"))), ), ListTile( leading: const Icon(Icons.share), title: const Text('Share url'), - onTap: () => - Share.text('Share comment url', com.apId, 'text/plain'), + onTap: () => Share.text( + 'Share comment url', com.comment.apId, 'text/plain'), ), ListTile( leading: const Icon(Icons.share), title: const Text('Share text'), - onTap: () => - Share.text('Share comment text', com.content, 'text/plain'), + onTap: () => Share.text( + 'Share comment text', com.comment.content, 'text/plain'), ), ListTile( leading: Icon( @@ -191,13 +205,13 @@ class Comment extends HookWidget { } vote(VoteType vote, Jwt token) async { - final api = LemmyApi(token.payload.iss).v1; + final api = LemmyApiV2(token.payload.iss); delayedVoting.start(); try { - final res = await api.createCommentLike( - commentId: comment.id, score: vote, auth: token.raw); - myVote.value = res.myVote; + final res = await api.run(CreateCommentLike( + commentId: comment.comment.id, score: vote, auth: token.raw)); + myVote.value = res.commentView.myVote; // ignore: avoid_catches_without_on_clauses } catch (e) { Scaffold.of(context) @@ -210,15 +224,15 @@ class Comment extends HookWidget { // decide which username to use final username = () { final name = () { - if (comment.creatorPreferredUsername != null && - comment.creatorPreferredUsername != '') { - return comment.creatorPreferredUsername; + if (comment.creator.preferredUsername != null && + comment.creator.preferredUsername != '') { + return comment.creator.preferredUsername; } else { - return '@${comment.creatorName}'; + return '@${comment.creator.name}'; } }(); - if (!comment.isLocal) return '$name@${comment.originInstanceHost}'; + if (!comment.comment.local) return '$name@${comment.originInstanceHost}'; return name; }(); @@ -231,7 +245,7 @@ class Comment extends HookWidget { style: TextStyle(fontStyle: FontStyle.italic), ), ); - } else if (comment.removed) { + } else if (comment.comment.removed) { return const Flexible( child: Text( 'comment deleted by moderator', @@ -243,7 +257,7 @@ class Comment extends HookWidget { child: Opacity( opacity: 0.3, child: Text( - commentTree.comment.content, + commentTree.comment.comment.content, maxLines: 1, overflow: TextOverflow.ellipsis, ), @@ -256,10 +270,10 @@ class Comment extends HookWidget { return Flexible( child: showRaw.value ? selectable.value - ? SelectableText(commentTree.comment.content) - : Text(commentTree.comment.content) + ? SelectableText(commentTree.comment.comment.content) + : Text(commentTree.comment.comment.content) : MarkdownText( - commentTree.comment.content, + commentTree.comment.comment.content, instanceHost: commentTree.comment.instanceHost, selectable: selectable.value, )); @@ -269,13 +283,15 @@ class Comment extends HookWidget { final actions = collapsed.value ? const SizedBox.shrink() : Row(children: [ - if (selectable.value && !isDeleted.value && !comment.removed) + if (selectable.value && + !isDeleted.value && + !comment.comment.removed) _CommentAction( icon: Icons.content_copy, tooltip: 'copy', onPressed: () { - Clipboard.setData( - ClipboardData(text: commentTree.comment.content)) + Clipboard.setData(ClipboardData( + text: commentTree.comment.comment.content)) .then((_) => Scaffold.of(context).showSnackBar( const SnackBar( content: Text('comment copied to clipboard')))); @@ -285,7 +301,7 @@ class Comment extends HookWidget { _CommentAction( icon: Icons.link, onPressed: () => - goToPost(context, comment.instanceHost, comment.postId), + goToPost(context, comment.instanceHost, comment.post.id), tooltip: 'go to post', ), _CommentAction( @@ -295,7 +311,7 @@ class Comment extends HookWidget { tooltip: 'more', ), _SaveComment(commentTree.comment), - if (!isDeleted.value && !comment.removed) + if (!isDeleted.value && !comment.comment.removed) _CommentAction( icon: Icons.reply, onPressed: loggedInAction((_) => reply()), @@ -340,14 +356,14 @@ class Comment extends HookWidget { child: Column( children: [ Row(children: [ - if (comment.creatorAvatar != null) + if (comment.creator.avatar != null) Padding( padding: const EdgeInsets.only(right: 5), child: InkWell( onTap: () => goToUser.byId( - context, comment.instanceHost, comment.creatorId), + context, comment.instanceHost, comment.creator.id), child: CachedNetworkImage( - imageUrl: comment.creatorAvatar, + imageUrl: comment.creator.avatar, height: 20, width: 20, imageBuilder: (context, imageProvider) => Container( @@ -365,15 +381,16 @@ class Comment extends HookWidget { ), InkWell( onTap: () => goToUser.byId( - context, comment.instanceHost, comment.creatorId), + context, comment.instanceHost, comment.creator.id), child: Text(username, style: TextStyle( color: Theme.of(context).accentColor, )), ), if (isOP) _CommentTag('OP', Theme.of(context).accentColor), - if (comment.banned) const _CommentTag('BANNED', Colors.red), - if (comment.bannedFromCommunity) + if (comment.creator.banned) + const _CommentTag('BANNED', Colors.red), + if (comment.creatorBannedFromCommunity) const _CommentTag('BANNED FROM COMMUNITY', Colors.red), const Spacer(), if (collapsed.value && commentTree.children.length > 0) ...[ @@ -390,10 +407,10 @@ class Comment extends HookWidget { size: const Size.square(16), child: const CircularProgressIndicator()) else - Text(compactNumber(comment.score + + Text(compactNumber(comment.counts.score + (wasVoted ? 0 : myVote.value.value))), const Text(' ยท '), - Text(timeago.format(comment.published)), + Text(timeago.format(comment.comment.published)), ], ), ) @@ -407,7 +424,7 @@ class Comment extends HookWidget { ), if (!collapsed.value) for (final c in newReplies.value.followedBy(commentTree.children)) - Comment( + CommentWidget( c, indent: indent + 1, postCreatorId: postCreatorId, @@ -430,13 +447,16 @@ class _SaveComment extends HookWidget { final delayed = useDelayedLoading(); handleSave(Jwt token) async { - final api = LemmyApi(comment.instanceHost).v1; + final api = LemmyApiV2(comment.instanceHost); delayed.start(); try { - final res = await api.saveComment( - commentId: comment.id, save: !isSaved.value, auth: token.raw); - isSaved.value = res.saved; + final res = await api.run(SaveComment( + commentId: comment.comment.id, + save: !isSaved.value, + auth: token.raw, + )); + isSaved.value = res.commentView.saved; // ignore: avoid_catches_without_on_clauses } catch (e) { Scaffold.of(context) From 208a4ac1ae4376f4ec715264cd139aef15702377 Mon Sep 17 00:00:00 2001 From: krawieck Date: Sun, 24 Jan 2021 21:51:07 +0100 Subject: [PATCH 03/17] fix bugs with commenting --- lib/widgets/write_comment.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/widgets/write_comment.dart b/lib/widgets/write_comment.dart index 12aae80..cff9837 100644 --- a/lib/widgets/write_comment.dart +++ b/lib/widgets/write_comment.dart @@ -69,10 +69,10 @@ CreateComment( final res = await api.run(CreateComment( content: controller.text, postId: post?.post?.id ?? comment.post.id, - parentId: comment?.comment?.id, + parentId: comment?.recipient?.id, auth: token.raw, )); - Navigator.of(context).pop(res); + Navigator.of(context).pop(res.commentView); // ignore: avoid_catches_without_on_clauses } catch (e) { print(e); From 6c1049b5ee915adb453bd804f4cf25348f3475b0 Mon Sep 17 00:00:00 2001 From: krawieck Date: Sun, 24 Jan 2021 22:59:20 +0100 Subject: [PATCH 04/17] add safearea in useful places --- lib/pages/instance.dart | 2 +- lib/pages/manage_account.dart | 1 + lib/widgets/infinite_scroll.dart | 6 ++++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/pages/instance.dart b/lib/pages/instance.dart index 34e025d..f79e124 100644 --- a/lib/pages/instance.dart +++ b/lib/pages/instance.dart @@ -396,7 +396,7 @@ class _AboutTab extends HookWidget { title: const Center(child: Text('Modlog')), onTap: goToModLog, ), - const SizedBox(height: 20), + const SafeArea(child: SizedBox.shrink()), ], ), ), diff --git a/lib/pages/manage_account.dart b/lib/pages/manage_account.dart index f31e43b..7b63879 100644 --- a/lib/pages/manage_account.dart +++ b/lib/pages/manage_account.dart @@ -430,6 +430,7 @@ class _ManageAccount extends HookWidget { ), child: const Text('DELETE ACCOUNT'), ), + const SafeArea(child: SizedBox.shrink()), ], ); } diff --git a/lib/widgets/infinite_scroll.dart b/lib/widgets/infinite_scroll.dart index a9a03d2..0a285b3 100644 --- a/lib/widgets/infinite_scroll.dart +++ b/lib/widgets/infinite_scroll.dart @@ -82,7 +82,7 @@ class InfiniteScroll extends HookWidget { if (i == data.value.length) { // if there are no more, skip if (!hasMore.current) { - return const SizedBox.shrink(); + return const SafeArea(child: SizedBox.shrink()); } // if it's already fetching more, skip @@ -98,7 +98,9 @@ class InfiniteScroll extends HookWidget { }).whenComplete(() => isFetching.current = false); } - return loadingWidget; + return SafeArea( + child: loadingWidget, + ); } // not last element, render list item From 190ae1b3ae40e2713c3c5da978013a59f697c9a5 Mon Sep 17 00:00:00 2001 From: krawieck Date: Sun, 24 Jan 2021 23:06:54 +0100 Subject: [PATCH 05/17] revise api extensions * change originInstanceHost extensions to extract from deeper structures * add extension for getting proper user name that includes originInstanceHost if needed --- lib/pages/communities_tab.dart | 2 +- lib/pages/community.dart | 4 ++-- lib/util/extensions/api.dart | 37 ++++++++++++++++++++++------------ lib/widgets/comment.dart | 15 +------------- lib/widgets/post.dart | 7 +++---- lib/widgets/user_profile.dart | 6 +++--- 6 files changed, 34 insertions(+), 37 deletions(-) diff --git a/lib/pages/communities_tab.dart b/lib/pages/communities_tab.dart index a48f915..6b1d1fc 100644 --- a/lib/pages/communities_tab.dart +++ b/lib/pages/communities_tab.dart @@ -231,7 +231,7 @@ class CommunitiesTab extends HookWidget { const SizedBox(width: 30), const SizedBox(width: 10), Text( - '''!${comm.community.name}${comm.community.local ? '' : '@${comm.originInstanceHost}'}''', + '''!${comm.community.name}${comm.community.local ? '' : '@${comm.community.originInstanceHost}'}''', ), ], ), diff --git a/lib/pages/community.dart b/lib/pages/community.dart index ef84cff..8bbd105 100644 --- a/lib/pages/community.dart +++ b/lib/pages/community.dart @@ -310,11 +310,11 @@ class _CommunityOverview extends StatelessWidget { text: '@', style: TextStyle(fontWeight: FontWeight.w200)), TextSpan( - text: community.originInstanceHost, + text: community.community.originInstanceHost, style: const TextStyle(fontWeight: FontWeight.w600), recognizer: TapGestureRecognizer() ..onTap = () => goToInstance( - context, community.originInstanceHost), + context, community.community.originInstanceHost), ), ], ), diff --git a/lib/util/extensions/api.dart b/lib/util/extensions/api.dart index 4990757..c47ad1c 100644 --- a/lib/util/extensions/api.dart +++ b/lib/util/extensions/api.dart @@ -10,30 +10,41 @@ import '../cleanup_url.dart'; // [.isLocal] is true iff `.originInstanceHost == .instanceHost` -extension GetInstanceCommunityView on CommunityView { - String get originInstanceHost => _extract(community.actorId); +extension GetInstanceCommunitySafe on CommunitySafe { + String get originInstanceHost => _extract(actorId); // bool get isLocal => originInstanceHost == instanceHost; } -extension GetInstanceUserView on UserViewSafe { - String get originInstanceHost => _extract(user.actorId); +extension GetInstanceUserSafe on UserSafe { + String get originInstanceHost => _extract(actorId); // bool get isLocal => originInstanceHost == instanceHost; } -extension GetInstanceCommunityFollowerView on CommunityFollowerView { - String get originInstanceHost => _extract(community.actorId); +extension GetInstancePostView on Post { + String get originInstanceHost => _extract(apId); // bool get isLocal => originInstanceHost == instanceHost; } -extension GetInstancePostView on PostView { - String get originInstanceHost => _extract(post.apId); - // bool get isLocal => originInstanceHost == instanceHost; -} - -extension GetInstanceCommentView on CommentView { - String get originInstanceHost => _extract(comment.apId); +extension GetInstanceCommentView on Comment { + String get originInstanceHost => _extract(apId); // bool get isLocal => originInstanceHost == instanceHost; } // TODO: change it to something more robust? regex? String _extract(String s) => cleanUpUrl(s.split('/')[2]); + +extension ProperName on UserSafe { + String get properName { + final name = () { + if (preferredUsername != null && preferredUsername != '') { + return preferredUsername; + } else { + return '@${this.name}'; + } + }(); + + if (!local) return '$name@$originInstanceHost'; + + return name; + } +} diff --git a/lib/widgets/comment.dart b/lib/widgets/comment.dart index 7255140..b827e5c 100644 --- a/lib/widgets/comment.dart +++ b/lib/widgets/comment.dart @@ -222,20 +222,7 @@ class CommentWidget extends HookWidget { } // decide which username to use - final username = () { - final name = () { - if (comment.creator.preferredUsername != null && - comment.creator.preferredUsername != '') { - return comment.creator.preferredUsername; - } else { - return '@${comment.creator.name}'; - } - }(); - - if (!comment.comment.local) return '$name@${comment.originInstanceHost}'; - - return name; - }(); + final username = comment.creator.properName; final body = () { if (isDeleted.value) { diff --git a/lib/widgets/post.dart b/lib/widgets/post.dart index b0b39c7..dda07e4 100644 --- a/lib/widgets/post.dart +++ b/lib/widgets/post.dart @@ -173,12 +173,12 @@ class PostWidget extends HookWidget { text: '@', style: TextStyle(fontWeight: FontWeight.w300)), TextSpan( - text: post.originInstanceHost, + text: post.post.originInstanceHost, style: const TextStyle(fontWeight: FontWeight.w600), recognizer: TapGestureRecognizer() ..onTap = () => goToInstance( - context, post.originInstanceHost)), + context, post.post.originInstanceHost)), ], ), ) @@ -195,8 +195,7 @@ class PostWidget extends HookWidget { text: 'by', style: TextStyle(fontWeight: FontWeight.w300)), TextSpan( - text: - ''' ${post.creator.preferredUsername ?? post.creator.name}''', + text: ' ${post.creator.properName}', style: const TextStyle(fontWeight: FontWeight.w600), recognizer: TapGestureRecognizer() diff --git a/lib/widgets/user_profile.dart b/lib/widgets/user_profile.dart index 7447dc1..b2a1b65 100644 --- a/lib/widgets/user_profile.dart +++ b/lib/widgets/user_profile.dart @@ -220,10 +220,10 @@ class _UserOverview extends HookWidget { style: theme.textTheme.caption, ), InkWell( - onTap: () => - goToInstance(context, userView.originInstanceHost), + onTap: () => goToInstance( + context, userView.user.originInstanceHost), child: Text( - userView.originInstanceHost, + userView.user.originInstanceHost, style: theme.textTheme.caption, ), ) From dec2147b383ecf6b51d509b715c815de45e9afa6 Mon Sep 17 00:00:00 2001 From: krawieck Date: Tue, 26 Jan 2021 21:55:57 +0100 Subject: [PATCH 06/17] remove debugging debris --- lib/pages/add_account.dart | 1 - lib/stores/accounts_store.dart | 6 ++---- lib/widgets/comment.dart | 6 ------ lib/widgets/write_comment.dart | 7 ------- 4 files changed, 2 insertions(+), 18 deletions(-) diff --git a/lib/pages/add_account.dart b/lib/pages/add_account.dart index 6dba4fc..a67d26f 100644 --- a/lib/pages/add_account.dart +++ b/lib/pages/add_account.dart @@ -32,7 +32,6 @@ class AddAccountPage extends HookWidget { final selectedInstance = useState(instanceHost); final icon = useState(null); useEffect(() { - // LemmyApi(selectedInstance.value).v2.run(GetPost(id: )); LemmyApiV2(selectedInstance.value) .run(GetSite()) .then((site) => icon.value = site.siteView.site.icon); diff --git a/lib/stores/accounts_store.dart b/lib/stores/accounts_store.dart index d2a9415..86fbf2b 100644 --- a/lib/stores/accounts_store.dart +++ b/lib/stores/accounts_store.dart @@ -220,10 +220,8 @@ class AccountsStore extends ChangeNotifier { usernameOrEmail: usernameOrEmail, password: password, )); - // lemmy.login(); - final userData = await lemmy - .run(GetSite(auth: token.raw)) - .then((value) => value.myUser); // TODO: change Mser to User + final userData = + await lemmy.run(GetSite(auth: token.raw)).then((value) => value.myUser); _tokens[instanceHost][userData.name] = token; diff --git a/lib/widgets/comment.dart b/lib/widgets/comment.dart index b827e5c..d592260 100644 --- a/lib/widgets/comment.dart +++ b/lib/widgets/comment.dart @@ -82,14 +82,8 @@ class CommentWidget extends HookWidget { commentTree.comment.comment.creatorId == commentTree.comment.post.creatorId; - // bool get isMine => commentTree.comment.comment.creatorId == ; - - // commentTree.comment.comment.creatorId == commentTree.comment. - // commentTree.comment.userId; // FIXME: WHAT SHOULD REPLACE USER ID???? - @override Widget build(BuildContext context) { - print(commentTree.comment.comment.id); final theme = Theme.of(context); final accStore = useAccountsStore(); diff --git a/lib/widgets/write_comment.dart b/lib/widgets/write_comment.dart index cff9837..74861ce 100644 --- a/lib/widgets/write_comment.dart +++ b/lib/widgets/write_comment.dart @@ -59,13 +59,6 @@ class WriteComment extends HookWidget { delayed.start(); try { - print(''' -CreateComment( - content: ${controller.text}, - postId: ${post?.post?.id ?? comment.post.id}, - parentId: ${comment?.comment?.id}, - auth: ${token.raw}, -)'''); final res = await api.run(CreateComment( content: controller.text, postId: post?.post?.id ?? comment.post.id, From 347ba7aae571968389cf54312d569e874b8fdb94 Mon Sep 17 00:00:00 2001 From: krawieck Date: Tue, 26 Jan 2021 22:18:53 +0100 Subject: [PATCH 07/17] rename a widget contructor --- lib/pages/user.dart | 2 +- lib/widgets/user_profile.dart | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/pages/user.dart b/lib/pages/user.dart index 0ac2304..30d0a9a 100644 --- a/lib/pages/user.dart +++ b/lib/pages/user.dart @@ -30,7 +30,7 @@ class UserPage extends HookWidget { final body = () { if (userDetailsSnap.hasData) { - return UserProfile.fromUserDetails(userDetailsSnap.data); + return UserProfile.fromFullUserView(userDetailsSnap.data); } else if (userDetailsSnap.hasError) { return const Center(child: Text('Could not find that user.')); } else { diff --git a/lib/widgets/user_profile.dart b/lib/widgets/user_profile.dart index b2a1b65..bcf5c20 100644 --- a/lib/widgets/user_profile.dart +++ b/lib/widgets/user_profile.dart @@ -24,9 +24,9 @@ class UserProfile extends HookWidget { : _userDetails = LemmyApiV2(instanceHost).run(GetUserDetails( userId: userId, savedOnly: false, sort: SortType.active)); - UserProfile.fromUserDetails(FullUserView userDetails) - : _userDetails = Future.value(userDetails), - instanceHost = userDetails.instanceHost; + UserProfile.fromFullUserView(FullUserView fullUserView) + : _userDetails = Future.value(fullUserView), + instanceHost = fullUserView.instanceHost; @override Widget build(BuildContext context) { From 1f26bf70aee1d7225e88a6bab3bde9632ae8ba03 Mon Sep 17 00:00:00 2001 From: krawieck Date: Tue, 26 Jan 2021 22:19:26 +0100 Subject: [PATCH 08/17] add arg to safearea specifying what kind of padding should it use --- lib/pages/manage_account.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pages/manage_account.dart b/lib/pages/manage_account.dart index 7b63879..282efb5 100644 --- a/lib/pages/manage_account.dart +++ b/lib/pages/manage_account.dart @@ -430,7 +430,7 @@ class _ManageAccount extends HookWidget { ), child: const Text('DELETE ACCOUNT'), ), - const SafeArea(child: SizedBox.shrink()), + const SafeArea(top: false, child: SizedBox.shrink()), ], ); } From 618b8c93e15f2d49a9f00ace764dc0ce099cd57b Mon Sep 17 00:00:00 2001 From: krawieck Date: Tue, 26 Jan 2021 22:20:43 +0100 Subject: [PATCH 09/17] remove unnecesary safearea --- lib/pages/instance.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/pages/instance.dart b/lib/pages/instance.dart index f79e124..666a4a5 100644 --- a/lib/pages/instance.dart +++ b/lib/pages/instance.dart @@ -396,7 +396,6 @@ class _AboutTab extends HookWidget { title: const Center(child: Text('Modlog')), onTap: goToModLog, ), - const SafeArea(child: SizedBox.shrink()), ], ), ), From 5a449eb0bec34e89dca1de2a61af55b9b2cd95b5 Mon Sep 17 00:00:00 2001 From: krawieck Date: Tue, 26 Jan 2021 22:28:06 +0100 Subject: [PATCH 10/17] rename getter properName -> displayName --- lib/util/extensions/api.dart | 4 ++-- lib/widgets/comment.dart | 2 +- lib/widgets/post.dart | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/util/extensions/api.dart b/lib/util/extensions/api.dart index c47ad1c..1b851fc 100644 --- a/lib/util/extensions/api.dart +++ b/lib/util/extensions/api.dart @@ -33,8 +33,8 @@ extension GetInstanceCommentView on Comment { // TODO: change it to something more robust? regex? String _extract(String s) => cleanUpUrl(s.split('/')[2]); -extension ProperName on UserSafe { - String get properName { +extension DisplayName on UserSafe { + String get displayName { final name = () { if (preferredUsername != null && preferredUsername != '') { return preferredUsername; diff --git a/lib/widgets/comment.dart b/lib/widgets/comment.dart index d592260..e1e8562 100644 --- a/lib/widgets/comment.dart +++ b/lib/widgets/comment.dart @@ -216,7 +216,7 @@ class CommentWidget extends HookWidget { } // decide which username to use - final username = comment.creator.properName; + final username = comment.creator.displayName; final body = () { if (isDeleted.value) { diff --git a/lib/widgets/post.dart b/lib/widgets/post.dart index dda07e4..4a816a3 100644 --- a/lib/widgets/post.dart +++ b/lib/widgets/post.dart @@ -195,7 +195,7 @@ class PostWidget extends HookWidget { text: 'by', style: TextStyle(fontWeight: FontWeight.w300)), TextSpan( - text: ' ${post.creator.properName}', + text: ' ${post.creator.displayName}', style: const TextStyle(fontWeight: FontWeight.w600), recognizer: TapGestureRecognizer() From 8d0f85ceae4214267dafc379e17c85243dcdcce1 Mon Sep 17 00:00:00 2001 From: krawieck Date: Tue, 26 Jan 2021 23:16:47 +0100 Subject: [PATCH 11/17] add reusable widget BottomSafe --- lib/pages/home_tab.dart | 8 +++++--- lib/pages/manage_account.dart | 3 ++- lib/widgets/bottom_safe.dart | 10 ++++++++++ lib/widgets/comment_section.dart | 3 ++- lib/widgets/infinite_scroll.dart | 4 +++- 5 files changed, 22 insertions(+), 6 deletions(-) create mode 100644 lib/widgets/bottom_safe.dart diff --git a/lib/pages/home_tab.dart b/lib/pages/home_tab.dart index 7276fc2..599bb6c 100644 --- a/lib/pages/home_tab.dart +++ b/lib/pages/home_tab.dart @@ -210,9 +210,11 @@ class HomeTab extends HookWidget { ), ), ), - body: InfiniteHomeList( - controller: isc, - selectedList: selectedList.value, + body: SafeArea( + child: InfiniteHomeList( + controller: isc, + selectedList: selectedList.value, + ), ), ); } diff --git a/lib/pages/manage_account.dart b/lib/pages/manage_account.dart index 282efb5..3f2890d 100644 --- a/lib/pages/manage_account.dart +++ b/lib/pages/manage_account.dart @@ -2,6 +2,7 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:image_picker/image_picker.dart'; +import 'package:lemmur/widgets/bottom_safe.dart'; import 'package:lemmy_api_client/pictrs.dart'; import 'package:lemmy_api_client/v2.dart'; @@ -430,7 +431,7 @@ class _ManageAccount extends HookWidget { ), child: const Text('DELETE ACCOUNT'), ), - const SafeArea(top: false, child: SizedBox.shrink()), + const BottomSafe(), ], ); } diff --git a/lib/widgets/bottom_safe.dart b/lib/widgets/bottom_safe.dart new file mode 100644 index 0000000..f4eead8 --- /dev/null +++ b/lib/widgets/bottom_safe.dart @@ -0,0 +1,10 @@ +import 'package:flutter/material.dart'; + +class BottomSafe extends StatelessWidget { + final double additionalPadding; + const BottomSafe([this.additionalPadding = 0]); + + @override + Widget build(BuildContext context) => SizedBox( + height: MediaQuery.of(context).padding.bottom + additionalPadding); +} diff --git a/lib/widgets/comment_section.dart b/lib/widgets/comment_section.dart index 8ec9c29..a224623 100644 --- a/lib/widgets/comment_section.dart +++ b/lib/widgets/comment_section.dart @@ -5,6 +5,7 @@ import 'package:lemmy_api_client/v2.dart'; import '../comment_tree.dart'; import 'bottom_modal.dart'; +import 'bottom_safe.dart'; import 'comment.dart'; /// Manages comments section, sorts them @@ -106,7 +107,7 @@ class CommentSection extends HookWidget { else for (final com in comments) CommentWidget(com, postCreatorId: postCreatorId), - const SizedBox(height: 50), + const BottomSafe(50), ]); } } diff --git a/lib/widgets/infinite_scroll.dart b/lib/widgets/infinite_scroll.dart index 0a285b3..7e4b7c4 100644 --- a/lib/widgets/infinite_scroll.dart +++ b/lib/widgets/infinite_scroll.dart @@ -3,6 +3,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import '../hooks/ref.dart'; +import 'bottom_safe.dart'; class InfiniteScrollController { VoidCallback clear; @@ -82,7 +83,7 @@ class InfiniteScroll extends HookWidget { if (i == data.value.length) { // if there are no more, skip if (!hasMore.current) { - return const SafeArea(child: SizedBox.shrink()); + return const BottomSafe(); } // if it's already fetching more, skip @@ -99,6 +100,7 @@ class InfiniteScroll extends HookWidget { } return SafeArea( + top: false, child: loadingWidget, ); } From cb44c6b7080fa7cb0ff3e768107f8177fcbfd8bb Mon Sep 17 00:00:00 2001 From: krawieck Date: Tue, 26 Jan 2021 23:16:56 +0100 Subject: [PATCH 12/17] upgrade to api v2 --- pubspec.lock | 67 +++++++++++++++++++++++++++++----------------------- pubspec.yaml | 15 ++++++++---- 2 files changed, 47 insertions(+), 35 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index bb4a5b4..e79c585 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -35,7 +35,7 @@ packages: name: cached_network_image url: "https://pub.dartlang.org" source: hosted - version: "2.3.3" + version: "2.5.0" characters: dependency: transitive description: @@ -91,7 +91,7 @@ packages: name: effective_dart url: "https://pub.dartlang.org" source: hosted - version: "1.2.4" + version: "1.3.0" esys_flutter_share: dependency: "direct main" description: @@ -138,7 +138,7 @@ packages: name: flutter_cache_manager url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.1" flutter_hooks: dependency: "direct main" description: @@ -191,13 +191,20 @@ packages: description: flutter source: sdk version: "0.0.0" + freezed_annotation: + dependency: transitive + description: + name: freezed_annotation + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.0" fuzzy: dependency: "direct main" description: name: fuzzy url: "https://pub.dartlang.org" source: hosted - version: "0.2.3" + version: "0.3.0" http: dependency: transitive description: @@ -225,7 +232,7 @@ packages: name: image_picker url: "https://pub.dartlang.org" source: hosted - version: "0.6.7+12" + version: "0.6.7+21" image_picker_platform_interface: dependency: transitive description: @@ -246,7 +253,7 @@ packages: name: json_annotation url: "https://pub.dartlang.org" source: hosted - version: "3.1.0" + version: "3.1.1" latinize: dependency: transitive description: @@ -260,7 +267,7 @@ packages: name: lemmy_api_client url: "https://pub.dartlang.org" source: hosted - version: "0.9.0" + version: "0.10.0" markdown: dependency: "direct main" description: @@ -302,7 +309,7 @@ packages: name: package_info url: "https://pub.dartlang.org" source: hosted - version: "0.4.3" + version: "0.4.3+2" path: dependency: transitive description: @@ -316,7 +323,7 @@ packages: name: path_provider url: "https://pub.dartlang.org" source: hosted - version: "1.6.22" + version: "1.6.27" path_provider_linux: dependency: transitive description: @@ -330,21 +337,21 @@ packages: name: path_provider_macos url: "https://pub.dartlang.org" source: hosted - version: "0.0.4+4" + version: "0.0.4+8" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "1.0.3" + version: "1.0.4" path_provider_windows: dependency: transitive description: name: path_provider_windows url: "https://pub.dartlang.org" source: hosted - version: "0.0.4+1" + version: "0.0.4+3" pedantic: dependency: transitive description: @@ -365,7 +372,7 @@ packages: name: photo_view url: "https://pub.dartlang.org" source: hosted - version: "0.10.2" + version: "0.10.3" platform: dependency: transitive description: @@ -393,35 +400,35 @@ packages: name: provider url: "https://pub.dartlang.org" source: hosted - version: "4.3.2+2" + version: "4.3.3" rxdart: dependency: transitive description: name: rxdart url: "https://pub.dartlang.org" source: hosted - version: "0.24.1" + version: "0.25.0" shared_preferences: dependency: "direct main" description: name: shared_preferences url: "https://pub.dartlang.org" source: hosted - version: "0.5.12+2" + version: "0.5.12+4" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux url: "https://pub.dartlang.org" source: hosted - version: "0.0.2+2" + version: "0.0.2+4" shared_preferences_macos: dependency: transitive description: name: shared_preferences_macos url: "https://pub.dartlang.org" source: hosted - version: "0.0.1+10" + version: "0.0.1+11" shared_preferences_platform_interface: dependency: transitive description: @@ -442,7 +449,7 @@ packages: name: shared_preferences_windows url: "https://pub.dartlang.org" source: hosted - version: "0.0.1+1" + version: "0.0.2+2" sky_engine: dependency: transitive description: flutter @@ -461,14 +468,14 @@ packages: name: sqflite url: "https://pub.dartlang.org" source: hosted - version: "1.3.1+2" + version: "1.3.2+2" sqflite_common: dependency: transitive description: name: sqflite_common url: "https://pub.dartlang.org" source: hosted - version: "1.0.2+1" + version: "1.0.3+1" stack_trace: dependency: transitive description: @@ -517,7 +524,7 @@ packages: name: timeago url: "https://pub.dartlang.org" source: hosted - version: "2.0.28" + version: "2.0.29" typed_data: dependency: transitive description: @@ -531,21 +538,21 @@ packages: name: url_launcher url: "https://pub.dartlang.org" source: hosted - version: "5.7.8" + version: "5.7.10" url_launcher_linux: dependency: transitive description: name: url_launcher_linux url: "https://pub.dartlang.org" source: hosted - version: "0.0.1+3" + version: "0.0.1+4" url_launcher_macos: dependency: transitive description: name: url_launcher_macos url: "https://pub.dartlang.org" source: hosted - version: "0.0.1+8" + version: "0.0.1+9" url_launcher_platform_interface: dependency: transitive description: @@ -559,14 +566,14 @@ packages: name: url_launcher_web url: "https://pub.dartlang.org" source: hosted - version: "0.1.5" + version: "0.1.5+1" url_launcher_windows: dependency: transitive description: name: url_launcher_windows url: "https://pub.dartlang.org" source: hosted - version: "0.0.1+1" + version: "0.0.1+3" uuid: dependency: transitive description: @@ -587,7 +594,7 @@ packages: name: win32 url: "https://pub.dartlang.org" source: hosted - version: "1.7.3" + version: "1.7.4" xdg_directories: dependency: transitive description: @@ -610,5 +617,5 @@ packages: source: hosted version: "2.2.1" sdks: - dart: ">=2.10.0 <2.11.0" - flutter: ">=1.22.0 <2.0.0" + dart: ">=2.10.2 <2.11.0" + flutter: ">=1.22.2 <2.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index fd1b109..24ba2aa 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: A new Flutter project. # The following line prevents the package from being accidentally published to # pub.dev using `pub publish`. This is preferred for private packages. -publish_to: "none" # Remove this line if you wish to publish to pub.dev +publish_to: 'none' # Remove this line if you wish to publish to pub.dev # The following defines the version and build number for your application. # A version number is three numbers separated by dots, like 1.2.43 @@ -18,7 +18,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev version: 0.1.0 environment: - sdk: ">=2.7.0 <3.0.0" + sdk: '>=2.7.0 <3.0.0' dependencies: # widgets @@ -32,7 +32,7 @@ dependencies: # native esys_flutter_share: ^1.0.2 url_launcher: ^5.5.1 - shared_preferences: ">=0.5.0 <2.0.0" + shared_preferences: '>=0.5.0 <2.0.0' package_info: ^0.4.3 image_picker: ^0.6.7 @@ -43,7 +43,12 @@ dependencies: # utils timeago: ^2.0.27 fuzzy: <1.0.0 - lemmy_api_client: ^0.9.0 + lemmy_api_client: ^0.10.0 + # TEMPORARY IMPORT remove before pull request! + # lemmy_api_client: + # git: + # url: git://github.com/krawieck/lemmy_api_client.git + # ref: v2 flutter: sdk: flutter @@ -62,7 +67,7 @@ flutter_icons: android: true ios: true image_path: assets/app_icon.png - adaptive_icon_background: "#ffffff" + adaptive_icon_background: '#ffffff' adaptive_icon_foreground: assets/adaptive_icon_fg.png # For information on the generic Dart part of this file, see the From b5714a1b34c34f4e7fb58cde11181981205a0ca0 Mon Sep 17 00:00:00 2001 From: krawieck Date: Tue, 26 Jan 2021 23:28:46 +0100 Subject: [PATCH 13/17] revert to proper ciapkas --- pubspec.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pubspec.yaml b/pubspec.yaml index 24ba2aa..130ef98 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: A new Flutter project. # The following line prevents the package from being accidentally published to # pub.dev using `pub publish`. This is preferred for private packages. -publish_to: 'none' # Remove this line if you wish to publish to pub.dev +publish_to: "none" # Remove this line if you wish to publish to pub.dev # The following defines the version and build number for your application. # A version number is three numbers separated by dots, like 1.2.43 @@ -18,7 +18,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 0.1.0 environment: - sdk: '>=2.7.0 <3.0.0' + sdk: ">=2.7.0 <3.0.0" dependencies: # widgets @@ -32,7 +32,7 @@ dependencies: # native esys_flutter_share: ^1.0.2 url_launcher: ^5.5.1 - shared_preferences: '>=0.5.0 <2.0.0' + shared_preferences: ">=0.5.0 <2.0.0" package_info: ^0.4.3 image_picker: ^0.6.7 @@ -67,7 +67,7 @@ flutter_icons: android: true ios: true image_path: assets/app_icon.png - adaptive_icon_background: '#ffffff' + adaptive_icon_background: "#ffffff" adaptive_icon_foreground: assets/adaptive_icon_fg.png # For information on the generic Dart part of this file, see the From 1e161c19668c53b396c8703f29ed031c7ee63e8d Mon Sep 17 00:00:00 2001 From: krawieck Date: Tue, 26 Jan 2021 23:29:59 +0100 Subject: [PATCH 14/17] remove useless comment --- pubspec.yaml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pubspec.yaml b/pubspec.yaml index 130ef98..49a78f2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -44,11 +44,6 @@ dependencies: timeago: ^2.0.27 fuzzy: <1.0.0 lemmy_api_client: ^0.10.0 - # TEMPORARY IMPORT remove before pull request! - # lemmy_api_client: - # git: - # url: git://github.com/krawieck/lemmy_api_client.git - # ref: v2 flutter: sdk: flutter From 1812d70546827c426fddbb3ea9243d173fe98a74 Mon Sep 17 00:00:00 2001 From: krawieck Date: Tue, 26 Jan 2021 23:38:23 +0100 Subject: [PATCH 15/17] remove widget that was mistakenly commited --- lib/pages/home_tab.dart | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/pages/home_tab.dart b/lib/pages/home_tab.dart index 599bb6c..7276fc2 100644 --- a/lib/pages/home_tab.dart +++ b/lib/pages/home_tab.dart @@ -210,11 +210,9 @@ class HomeTab extends HookWidget { ), ), ), - body: SafeArea( - child: InfiniteHomeList( - controller: isc, - selectedList: selectedList.value, - ), + body: InfiniteHomeList( + controller: isc, + selectedList: selectedList.value, ), ); } From 735bd52be24c464a98e83d02c21b92632211f581 Mon Sep 17 00:00:00 2001 From: krawieck Date: Tue, 26 Jan 2021 23:51:02 +0100 Subject: [PATCH 16/17] fix lint errors --- lib/pages/manage_account.dart | 2 +- lib/widgets/comment.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pages/manage_account.dart b/lib/pages/manage_account.dart index 3f2890d..5829d91 100644 --- a/lib/pages/manage_account.dart +++ b/lib/pages/manage_account.dart @@ -2,7 +2,6 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:image_picker/image_picker.dart'; -import 'package:lemmur/widgets/bottom_safe.dart'; import 'package:lemmy_api_client/pictrs.dart'; import 'package:lemmy_api_client/v2.dart'; @@ -11,6 +10,7 @@ import '../hooks/image_picker.dart'; import '../hooks/ref.dart'; import '../hooks/stores.dart'; import '../util/pictrs.dart'; +import '../widgets/bottom_safe.dart'; /// Page for managing things like username, email, avatar etc /// This page will assume the manage account is logged in and diff --git a/lib/widgets/comment.dart b/lib/widgets/comment.dart index e1e8562..9a6af85 100644 --- a/lib/widgets/comment.dart +++ b/lib/widgets/comment.dart @@ -374,7 +374,7 @@ class CommentWidget extends HookWidget { if (comment.creatorBannedFromCommunity) const _CommentTag('BANNED FROM COMMUNITY', Colors.red), const Spacer(), - if (collapsed.value && commentTree.children.length > 0) ...[ + if (collapsed.value && commentTree.children.isNotEmpty) ...[ _CommentTag('+${commentTree.children.length}', Theme.of(context).accentColor), const SizedBox(width: 7), From 41d44537e9fa5cc2074f5ce991e25525478579c9 Mon Sep 17 00:00:00 2001 From: krawieck Date: Tue, 26 Jan 2021 23:53:40 +0100 Subject: [PATCH 17/17] fix lint error --- lib/widgets/comment.dart | 2 +- lib/widgets/user_profile.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/widgets/comment.dart b/lib/widgets/comment.dart index 9a6af85..12ab386 100644 --- a/lib/widgets/comment.dart +++ b/lib/widgets/comment.dart @@ -74,7 +74,7 @@ class CommentWidget extends HookWidget { 'downvotes': com.counts.downvotes, 'score': com.counts.score, '% of upvotes': - '${100 * (com.counts.upvotes / (com.counts.upvotes + com.counts.downvotes))}%', + '''${100 * (com.counts.upvotes / (com.counts.upvotes + com.counts.downvotes))}%''', }); } diff --git a/lib/widgets/user_profile.dart b/lib/widgets/user_profile.dart index bcf5c20..5570815 100644 --- a/lib/widgets/user_profile.dart +++ b/lib/widgets/user_profile.dart @@ -268,7 +268,7 @@ class _UserOverview extends HookWidget { padding: const EdgeInsets.only(left: 4), child: Text( '${compactNumber(userView.counts.commentCount)}' - ' Comment${pluralS(userView.counts.commentCount)}', + ''' Comment${pluralS(userView.counts.commentCount)}''', style: TextStyle(color: colorOnTopOfAccentColor), ),