diff --git a/lib/main.dart b/lib/main.dart index 02094d5..93282fd 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -28,6 +28,6 @@ void main() async { // Load user settings final settingsController = SettingsController(); await settingsController.loadSettings(); - + print(settingsController.api); runApp(MyApp(settingsController: settingsController)); } diff --git a/lib/src/api/api.dart b/lib/src/api/api.dart index 4236543..df17887 100644 --- a/lib/src/api/api.dart +++ b/lib/src/api/api.dart @@ -7,7 +7,6 @@ import 'package:interstellar/src/api/entries.dart'; import 'package:interstellar/src/api/magazines.dart'; import 'package:interstellar/src/api/messages.dart'; import 'package:interstellar/src/api/notifications.dart'; -import 'package:interstellar/src/api/oauth.dart'; import 'package:interstellar/src/api/posts.dart'; import 'package:interstellar/src/api/search.dart'; import 'package:interstellar/src/api/users.dart'; @@ -19,7 +18,6 @@ class API { final http.Client httpClient; final String server; - final KbinAPIOAuth oauth; final KbinAPIComments comments; final KbinAPIDomains domains; final APIThreads entries; @@ -34,8 +32,7 @@ class API { this.software, this.httpClient, this.server, - ) : oauth = KbinAPIOAuth(software, httpClient, server), - comments = KbinAPIComments(software, httpClient, server), + ) : comments = KbinAPIComments(software, httpClient, server), domains = KbinAPIDomains(software, httpClient, server), entries = APIThreads(software, httpClient, server), magazines = APIMagazines(software, httpClient, server), diff --git a/lib/src/api/entries.dart b/lib/src/api/entries.dart index 5b9f440..bf665ad 100644 --- a/lib/src/api/entries.dart +++ b/lib/src/api/entries.dart @@ -23,6 +23,7 @@ class APIThreads { Future list( FeedSource source, { + int? sourceId, String? page, FeedSort? sort, List? langs, @@ -31,7 +32,15 @@ class APIThreads { switch (software) { case ServerSoftware.kbin: case ServerSoftware.mbin: - final path = source.getEntriesPath(); + final path = switch (source) { + FeedSource.all => '/api/entries', + FeedSource.subscribed => '/api/entries/subscribed', + FeedSource.moderated => '/api/entries/moderated', + FeedSource.favorited => '/api/entries/favourited', + FeedSource.magazine => '/api/magazine/${sourceId!}/entries', + FeedSource.user => '/api/users/${sourceId!}/entries', + FeedSource.domain => '/api/users/${sourceId!}/entries', + }; final query = queryParams({ 'p': page, 'sort': sort?.name, @@ -50,7 +59,17 @@ class APIThreads { const path = '/api/v3/post/list'; final query = queryParams({ 'page_cursor': page, - }); + }..addAll(switch (source) { + FeedSource.all => {'type_': 'All'}, + FeedSource.subscribed => {'type_': 'Subscribed'}, + FeedSource.moderated => {'type_': 'ModeratorView'}, + FeedSource.favorited => {'liked_only': 'true'}, + FeedSource.magazine => {'community_id': sourceId!.toString()}, + FeedSource.user => + throw Exception('User source not allowed for lemmy'), + FeedSource.domain => + throw Exception('Domain source not allowed for lemmy'), + })); final response = await httpClient.get(Uri.https(server, path, query)); diff --git a/lib/src/api/feed_source.dart b/lib/src/api/feed_source.dart index 8939a91..94f80d3 100644 --- a/lib/src/api/feed_source.dart +++ b/lib/src/api/feed_source.dart @@ -1,75 +1,18 @@ -enum FeedSort { active, hot, newest, oldest, top, commented } - -abstract class FeedSource { - String getEntriesPath(); - String? getPostsPath(); +enum FeedSource { + all, + subscribed, + moderated, + favorited, + magazine, + user, + domain, } -class FeedSourceAll implements FeedSource { - const FeedSourceAll(); - - @override - String getEntriesPath() => '/api/entries'; - @override - String getPostsPath() => '/api/posts'; -} - -class FeedSourceSub implements FeedSource { - const FeedSourceSub(); - - @override - String getEntriesPath() => '/api/entries/subscribed'; - @override - String getPostsPath() => '/api/posts/subscribed'; -} - -class FeedSourceMod implements FeedSource { - const FeedSourceMod(); - - @override - String getEntriesPath() => '/api/entries/moderated'; - @override - String getPostsPath() => '/api/posts/moderated'; -} - -class FeedSourceFav implements FeedSource { - const FeedSourceFav(); - - @override - String getEntriesPath() => '/api/entries/favourited'; - @override - String getPostsPath() => '/api/posts/favourited'; -} - -class FeedSourceMagazine implements FeedSource { - final int id; - - const FeedSourceMagazine(this.id); - - @override - String getEntriesPath() => '/api/magazine/$id/entries'; - @override - String getPostsPath() => '/api/magazine/$id/posts'; -} - -class FeedSourceUser implements FeedSource { - final int id; - - const FeedSourceUser(this.id); - - @override - String getEntriesPath() => '/api/users/$id/entries'; - @override - String getPostsPath() => '/api/users/$id/posts'; -} - -class FeedSourceDomain implements FeedSource { - final int id; - - const FeedSourceDomain(this.id); - - @override - String getEntriesPath() => '/api/domain/$id/entries'; - @override - String? getPostsPath() => null; +enum FeedSort { + active, + hot, + newest, + oldest, + top, + commented, } diff --git a/lib/src/api/magazines.dart b/lib/src/api/magazines.dart index 62161db..ec8ab97 100644 --- a/lib/src/api/magazines.dart +++ b/lib/src/api/magazines.dart @@ -47,8 +47,14 @@ class APIMagazines { case ServerSoftware.lemmy: const path = '/api/v3/community/list'; + final query = queryParams({ + 'limit': '50', + 'listingType': 'All', + 'sort': 'TopAll', + 'page': page?.toString(), + }); - final response = await httpClient.get(Uri.https(server, path)); + final response = await httpClient.get(Uri.https(server, path, query)); httpErrorHandler(response, message: 'Failed to load magazines'); diff --git a/lib/src/api/oauth.dart b/lib/src/api/oauth.dart index 92d684c..830d780 100644 --- a/lib/src/api/oauth.dart +++ b/lib/src/api/oauth.dart @@ -1,7 +1,6 @@ import 'dart:convert'; import 'package:http/http.dart' as http; -import 'package:interstellar/src/screens/settings/settings_controller.dart'; import 'package:interstellar/src/utils/utils.dart'; import 'package:interstellar/src/widgets/redirect_listen.dart'; @@ -20,37 +19,25 @@ const oauthScopes = [ 'moderate' ]; -class KbinAPIOAuth { - final ServerSoftware software; - final http.Client httpClient; - final String server; +Future registerOauthApp(String instanceHost) async { + const path = '/api/client'; - KbinAPIOAuth( - this.software, - this.httpClient, - this.server, + final response = await http.post( + Uri.https(instanceHost, path), + headers: { + 'Content-Type': 'application/json; charset=UTF-8', + }, + body: jsonEncode({ + 'name': oauthName, + 'contactEmail': oauthContact, + 'public': true, + 'redirectUris': [redirectUri], + 'grants': oauthGrants, + 'scopes': oauthScopes + }), ); - Future registerApp(String instanceHost) async { - const path = '/api/client'; + httpErrorHandler(response, message: 'Failed to register client'); - final response = await httpClient.post( - Uri.https(instanceHost, path), - headers: { - 'Content-Type': 'application/json; charset=UTF-8', - }, - body: jsonEncode({ - 'name': oauthName, - 'contactEmail': oauthContact, - 'public': true, - 'redirectUris': [redirectUri], - 'grants': oauthGrants, - 'scopes': oauthScopes - }), - ); - - httpErrorHandler(response, message: 'Failed to register client'); - - return (jsonDecode(response.body) as Map)['identifier']; - } + return (jsonDecode(response.body) as Map)['identifier']; } diff --git a/lib/src/api/posts.dart b/lib/src/api/posts.dart index 50ab8b0..4fdf058 100644 --- a/lib/src/api/posts.dart +++ b/lib/src/api/posts.dart @@ -23,16 +23,23 @@ class APIPosts { Future list( FeedSource source, { + int? sourceId, String? page, FeedSort? sort, List? langs, bool? usePreferredLangs, }) async { - if (source.getPostsPath() == null) { - throw Exception('Failed to load posts'); - } + final path = switch (source) { + FeedSource.all => '/api/posts', + FeedSource.subscribed => '/api/posts/subscribed', + FeedSource.moderated => '/api/posts/moderated', + FeedSource.favorited => '/api/posts/favourited', + FeedSource.magazine => '/api/magazine/${sourceId!}/posts', + FeedSource.user => '/api/users/${sourceId!}/posts', + FeedSource.domain => + throw Exception('Domain source not allowed for microblog'), + }; - final path = source.getPostsPath()!; final query = queryParams({ 'p': page, 'sort': sort?.name, diff --git a/lib/src/models/magazine.dart b/lib/src/models/magazine.dart index cb0eca6..a48cfc9 100644 --- a/lib/src/models/magazine.dart +++ b/lib/src/models/magazine.dart @@ -1,7 +1,6 @@ import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:interstellar/src/models/user.dart'; import 'package:interstellar/src/utils/models.dart'; -import 'package:interstellar/src/widgets/markdown_mention.dart'; part 'magazine.freezed.dart'; @@ -52,31 +51,26 @@ class DetailedMagazineModel with _$DetailedMagazineModel { required bool? isBlockedByUser, }) = _DetailedMagazineModel; - factory DetailedMagazineModel.fromKbin(Map json) { - final magazine = DetailedMagazineModel( - id: json['magazineId'] as int, - name: json['name'] as String, - title: json['title'] as String, - icon: kbinGetImageUrl(json['icon'] as Map?), - description: json['description'] as String?, - rules: json['rules'] as String?, - moderators: ((json['moderators'] ?? []) as List) - .map((user) => UserModel.fromKbin(user as Map)) - .toList(), - subscriptionsCount: json['subscriptionsCount'] as int, - threadCount: json['entryCount'] as int, - threadCommentCount: json['entryCommentCount'] as int, - microblogCount: json['postCount'] as int, - microblogCommentCount: json['postCommentCount'] as int, - isAdult: json['isAdult'] as bool, - isUserSubscribed: json['isUserSubscribed'] as bool?, - isBlockedByUser: json['isBlockedByUser'] as bool?, - ); - - magazineMentionCache[magazine.name] = magazine; - - return magazine; - } + factory DetailedMagazineModel.fromKbin(Map json) => + DetailedMagazineModel( + id: json['magazineId'] as int, + name: json['name'] as String, + title: json['title'] as String, + icon: kbinGetImageUrl(json['icon'] as Map?), + description: json['description'] as String?, + rules: json['rules'] as String?, + moderators: ((json['moderators'] ?? []) as List) + .map((user) => UserModel.fromKbin(user as Map)) + .toList(), + subscriptionsCount: json['subscriptionsCount'] as int, + threadCount: json['entryCount'] as int, + threadCommentCount: json['entryCommentCount'] as int, + microblogCount: json['postCount'] as int, + microblogCommentCount: json['postCommentCount'] as int, + isAdult: json['isAdult'] as bool, + isUserSubscribed: json['isUserSubscribed'] as bool?, + isBlockedByUser: json['isBlockedByUser'] as bool?, + ); factory DetailedMagazineModel.fromLemmy(Map json) { final lemmyCommunity = json['community'] as Map; @@ -100,8 +94,6 @@ class DetailedMagazineModel with _$DetailedMagazineModel { isBlockedByUser: json['blocked'] as bool?, ); - magazineMentionCache[magazine.name] = magazine; - return magazine; } } diff --git a/lib/src/models/user.dart b/lib/src/models/user.dart index ae0f1c2..e67a3cc 100644 --- a/lib/src/models/user.dart +++ b/lib/src/models/user.dart @@ -1,6 +1,5 @@ import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:interstellar/src/utils/models.dart'; -import 'package:interstellar/src/widgets/markdown_mention.dart'; part 'user.freezed.dart'; @@ -38,26 +37,20 @@ class DetailedUserModel with _$DetailedUserModel { required bool? isBlockedByUser, }) = _DetailedUserModel; - factory DetailedUserModel.fromKbin(Map json) { - final user = DetailedUserModel( - id: json['userId'] as int, - name: json['username'] as String, - avatar: kbinGetImageUrl(json['avatar'] as Map?), - cover: kbinGetImageUrl(json['cover'] as Map?), - createdAt: DateTime.parse(json['createdAt'] as String), - isBot: json['isBot'] as bool, - about: json['about'] as String?, - followersCount: json['followersCount'] as int, - isFollowedByUser: json['isFollowedByUser'] as bool?, - isFollowerOfUser: json['isFollowerOfUser'] as bool?, - isBlockedByUser: json['isBlockedByUser'] as bool?, - ); - - userMentionCache[ - user.name.startsWith('@') ? user.name.substring(1) : user.name] = user; - - return user; - } + factory DetailedUserModel.fromKbin(Map json) => + DetailedUserModel( + id: json['userId'] as int, + name: json['username'] as String, + avatar: kbinGetImageUrl(json['avatar'] as Map?), + cover: kbinGetImageUrl(json['cover'] as Map?), + createdAt: DateTime.parse(json['createdAt'] as String), + isBot: json['isBot'] as bool, + about: json['about'] as String?, + followersCount: json['followersCount'] as int, + isFollowedByUser: json['isFollowedByUser'] as bool?, + isFollowerOfUser: json['isFollowerOfUser'] as bool?, + isBlockedByUser: json['isBlockedByUser'] as bool?, + ); } @freezed diff --git a/lib/src/screens/explore/domain_screen.dart b/lib/src/screens/explore/domain_screen.dart index 284dcb1..670d277 100644 --- a/lib/src/screens/explore/domain_screen.dart +++ b/lib/src/screens/explore/domain_screen.dart @@ -41,7 +41,8 @@ class _DomainScreenState extends State { @override Widget build(BuildContext context) { return FeedScreen( - source: FeedSourceDomain(widget.domainId), + source: FeedSource.domain, + sourceId: widget.domainId, title: _data?.name ?? '', details: _data != null ? Padding( diff --git a/lib/src/screens/explore/explore_screen.dart b/lib/src/screens/explore/explore_screen.dart index e050757..dc6e294 100644 --- a/lib/src/screens/explore/explore_screen.dart +++ b/lib/src/screens/explore/explore_screen.dart @@ -12,42 +12,47 @@ class ExploreScreen extends StatelessWidget { @override Widget build(BuildContext context) { return DefaultTabController( - length: 3, + length: context.watch().serverSoftware == + ServerSoftware.lemmy + ? 2 + : 4, child: Scaffold( appBar: AppBar( title: Text( 'Explore ${context.watch().instanceHost}'), - actions: [ - IconButton( - onPressed: () { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => const SearchScreen(), - ), - ); - }, - icon: const Icon(Icons.search)) - ], - bottom: const TabBar(tabs: [ - Tab( + bottom: TabBar(tabs: [ + const Tab( text: 'Magazines', icon: Icon(Icons.article), ), - Tab( - text: 'People', - icon: Icon(Icons.account_circle), - ), - Tab( - text: 'Domains', - icon: Icon(Icons.public), + if (context.watch().serverSoftware != + ServerSoftware.lemmy) + const Tab( + text: 'People', + icon: Icon(Icons.account_circle), + ), + if (context.watch().serverSoftware != + ServerSoftware.lemmy) + const Tab( + text: 'Domains', + icon: Icon(Icons.public), + ), + const Tab( + text: 'Search', + icon: Icon(Icons.search), ), ]), ), - body: const TabBarView( + body: TabBarView( children: [ - MagazinesScreen(), - UsersScreen(), - DomainsScreen(), + const MagazinesScreen(), + if (context.watch().serverSoftware != + ServerSoftware.lemmy) + const UsersScreen(), + if (context.watch().serverSoftware != + ServerSoftware.lemmy) + const DomainsScreen(), + const SearchScreen(), ], ), ), diff --git a/lib/src/screens/explore/magazine_screen.dart b/lib/src/screens/explore/magazine_screen.dart index a56d2c3..88a2b06 100644 --- a/lib/src/screens/explore/magazine_screen.dart +++ b/lib/src/screens/explore/magazine_screen.dart @@ -45,7 +45,8 @@ class _MagazineScreenState extends State { @override Widget build(BuildContext context) { return FeedScreen( - source: FeedSourceMagazine(widget.magazineId), + source: FeedSource.magazine, + sourceId: widget.magazineId, title: _data?.name ?? '', details: _data != null ? Padding( diff --git a/lib/src/screens/explore/magazines_screen.dart b/lib/src/screens/explore/magazines_screen.dart index d733f86..2cee80c 100644 --- a/lib/src/screens/explore/magazines_screen.dart +++ b/lib/src/screens/explore/magazines_screen.dart @@ -22,8 +22,8 @@ class _MagazinesScreenState extends State { KbinAPIMagazinesSort sort = KbinAPIMagazinesSort.hot; String search = ""; - final PagingController _pagingController = - PagingController(firstPageKey: '1'); + final PagingController _pagingController = + PagingController(firstPageKey: 1); @override void initState() { @@ -32,11 +32,11 @@ class _MagazinesScreenState extends State { _pagingController.addPageRequestListener(_fetchPage); } - Future _fetchPage(String pageKey) async { + Future _fetchPage(int pageKey) async { try { final newPage = await context.read().api.magazines.list( - page: int.parse(pageKey), + page: pageKey, filter: filter, sort: sort, search: search.isEmpty ? null : search, @@ -50,7 +50,14 @@ class _MagazinesScreenState extends State { final newItems = newPage.items.where((e) => !currentItemIds.contains(e.id)).toList(); - _pagingController.appendPage(newItems, newPage.nextPage); + _pagingController.appendPage( + newItems, + context.read().serverSoftware == + ServerSoftware.lemmy + ? (newPage.items.isEmpty ? null : pageKey + 1) + : (newPage.nextPage == null + ? null + : int.parse(newPage.nextPage!))); } catch (error, st) { print(error); print(st); diff --git a/lib/src/screens/explore/user_screen.dart b/lib/src/screens/explore/user_screen.dart index 0fabfdb..c495643 100644 --- a/lib/src/screens/explore/user_screen.dart +++ b/lib/src/screens/explore/user_screen.dart @@ -54,7 +54,8 @@ class _UserScreenState extends State { @override Widget build(BuildContext context) { return FeedScreen( - source: FeedSourceUser(widget.userId), + source: FeedSource.user, + sourceId: widget.userId, title: _data?.name ?? '', details: _data != null ? Column( diff --git a/lib/src/screens/feed/feed_screen.dart b/lib/src/screens/feed/feed_screen.dart index f10bad6..3082f67 100644 --- a/lib/src/screens/feed/feed_screen.dart +++ b/lib/src/screens/feed/feed_screen.dart @@ -13,6 +13,7 @@ import 'package:provider/provider.dart'; class FeedScreen extends StatefulWidget { final FeedSource? source; + final int? sourceId; final String? title; final Widget? details; final Widget? floatingActionButton; @@ -20,6 +21,7 @@ class FeedScreen extends StatefulWidget { const FeedScreen({ super.key, this.source, + this.sourceId, this.title, this.details, this.floatingActionButton, @@ -37,7 +39,8 @@ class _FeedScreenState extends State { void initState() { super.initState(); - _mode = (widget.source ?? const FeedSourceAll()).getPostsPath() != null + _mode = context.read().serverSoftware != + ServerSoftware.lemmy ? context.read().defaultFeedType : PostType.thread; _sort = widget.source == null @@ -82,7 +85,10 @@ class _FeedScreenState extends State { ), ), actions: [ - if ((widget.source ?? const FeedSourceAll()).getPostsPath() != null) + // Domain FeedSource is not available for microblogs + if (widget.source != FeedSource.domain && + context.read().serverSoftware != + ServerSoftware.lemmy) Padding( padding: const EdgeInsets.only(right: 8), child: IconButton( @@ -156,6 +162,7 @@ class _FeedScreenState extends State { body: widget.source != null ? FeedScreenBody( source: widget.source!, + sourceId: widget.sourceId, sort: _sort, mode: _mode, details: widget.details, @@ -165,25 +172,25 @@ class _FeedScreenState extends State { TabBarView( children: [ FeedScreenBody( - source: const FeedSourceSub(), + source: FeedSource.subscribed, sort: _sort, mode: _mode, details: widget.details, ), FeedScreenBody( - source: const FeedSourceMod(), + source: FeedSource.moderated, sort: _sort, mode: _mode, details: widget.details, ), FeedScreenBody( - source: const FeedSourceFav(), + source: FeedSource.favorited, sort: _sort, mode: _mode, details: widget.details, ), FeedScreenBody( - source: const FeedSourceAll(), + source: FeedSource.all, sort: _sort, mode: _mode, details: widget.details, @@ -191,7 +198,7 @@ class _FeedScreenState extends State { ], ), otherwise: FeedScreenBody( - source: const FeedSourceAll(), + source: FeedSource.all, sort: _sort, mode: _mode, details: widget.details, @@ -260,6 +267,7 @@ const SelectionMenu feedSortSelect = SelectionMenu( class FeedScreenBody extends StatefulWidget { final FeedSource source; + final int? sourceId; final FeedSort sort; final PostType mode; final Widget? details; @@ -267,6 +275,7 @@ class FeedScreenBody extends StatefulWidget { const FeedScreenBody({ super.key, required this.source, + this.sourceId, required this.sort, required this.mode, this.details, @@ -292,6 +301,7 @@ class _FeedScreenBodyState extends State { PostListModel newPage = await (switch (widget.mode) { PostType.thread => context.read().api.entries.list( widget.source, + sourceId: widget.sourceId, page: pageKey.isEmpty ? null : pageKey, sort: widget.sort, usePreferredLangs: whenLoggedIn(context, @@ -300,6 +310,7 @@ class _FeedScreenBodyState extends State { ), PostType.microblog => context.read().api.posts.list( widget.source, + sourceId: widget.sourceId, page: pageKey.isEmpty ? null : pageKey, sort: widget.sort, usePreferredLangs: whenLoggedIn(context, diff --git a/lib/src/screens/settings/login_select.dart b/lib/src/screens/settings/login_select.dart index ba55732..1360061 100644 --- a/lib/src/screens/settings/login_select.dart +++ b/lib/src/screens/settings/login_select.dart @@ -54,7 +54,7 @@ class _LoginSelectScreenState extends State { await context .read() - .setServer(software, _instanceHostController.text); + .saveServer(software, _instanceHostController.text); // Check BuildContext if (!mounted) return; diff --git a/lib/src/screens/settings/settings_controller.dart b/lib/src/screens/settings/settings_controller.dart index 1744c19..4298121 100644 --- a/lib/src/screens/settings/settings_controller.dart +++ b/lib/src/screens/settings/settings_controller.dart @@ -5,6 +5,7 @@ import 'package:http/http.dart' as http; import 'package:interstellar/src/api/api.dart'; import 'package:interstellar/src/api/comments.dart'; import 'package:interstellar/src/api/feed_source.dart'; +import 'package:interstellar/src/api/oauth.dart'; import 'package:interstellar/src/models/post.dart'; import 'package:interstellar/src/utils/jwt_http_client.dart'; import 'package:interstellar/src/utils/themes.dart'; @@ -137,7 +138,7 @@ class SettingsController with ChangeNotifier { as Map) .map((key, value) => MapEntry(key, Account.fromJson(value))); _selectedAccount = prefs.getString('selectedAccount') ?? '@kbin.earth'; - updateAPI(); + await updateAPI(); notifyListeners(); } @@ -300,7 +301,9 @@ class SettingsController with ChangeNotifier { await prefs.setString('defaultCreateLang', newDefaultCreateLang); } - Future setServer(ServerSoftware software, String server) async { + Future saveServer(ServerSoftware software, String server) async { + if (_servers.containsKey(server)) return; + _servers[server] = Server(software); final SharedPreferences prefs = await SharedPreferences.getInstance(); @@ -318,7 +321,7 @@ class SettingsController with ChangeNotifier { throw Exception('Tried to register oauth for lemmy'); } - String oauthIdentifier = await _api.oauth.registerApp(server); + String oauthIdentifier = await registerOauthApp(server); _servers[server] = Server(software, oauthIdentifier: oauthIdentifier); final SharedPreferences prefs = await SharedPreferences.getInstance(); diff --git a/lib/src/screens/settings/settings_screen.dart b/lib/src/screens/settings/settings_screen.dart index a128201..3b5c5c7 100644 --- a/lib/src/screens/settings/settings_screen.dart +++ b/lib/src/screens/settings/settings_screen.dart @@ -99,6 +99,7 @@ class SettingsScreen extends StatelessWidget { ListTile( title: const Text('Default Feed Type'), leading: const Icon(Icons.tab), + enabled: controller.serverSoftware != ServerSoftware.lemmy, onTap: () async { controller.updateDefaultFeedType( await feedTypeSelect.inquireSelection( diff --git a/lib/src/widgets/markdown_mention.dart b/lib/src/widgets/markdown_mention.dart index f3d5d49..94cb54d 100644 --- a/lib/src/widgets/markdown_mention.dart +++ b/lib/src/widgets/markdown_mention.dart @@ -150,9 +150,7 @@ class MentionWidgetState extends State { final modifier = widget.name[0]; final split = widget.name.substring(1).split('@'); final name = split[0]; - final host = (split.length > 1) - ? split[1] - : widget.originInstance; + final host = (split.length > 1) ? split[1] : widget.originInstance; final cacheKey = '$name@$host'; setState(() { @@ -164,7 +162,9 @@ class MentionWidgetState extends State { if (!userMentionCache.containsKey(cacheKey)) { userMentionCache[cacheKey] = await context.read().api.users.getByName( - '@$name@$host', + host == context.read().instanceHost + ? name + : '@$name@$host', ); } final user = userMentionCache[cacheKey]!; @@ -183,7 +183,9 @@ class MentionWidgetState extends State { if (!magazineMentionCache.containsKey(cacheKey)) { magazineMentionCache[cacheKey] = await context.read().api.magazines.getByName( - '$name@$host', + host == context.read().instanceHost + ? name + : '$name@$host', ); } final magazine = magazineMentionCache[cacheKey]!;