diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index 17caebf6..fed37078 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -2544,6 +2544,7 @@ } }, "searchChatsRooms": "Search for #chats, @users...", + "nothingFound": "Nothing found...", "groupName": "Group name", "createGroupAndInviteUsers": "Create a group and invite users", "groupCanBeFoundViaSearch": "Group can be found via search", diff --git a/lib/config/app_config.dart b/lib/config/app_config.dart index 6cac22ed..296c8e90 100644 --- a/lib/config/app_config.dart +++ b/lib/config/app_config.dart @@ -67,6 +67,11 @@ abstract class AppConfig { 'https://github.com/googlefonts/noto-emoji/'; static const double borderRadius = 16.0; static const double columnWidth = 360.0; + static final Uri homeserverList = Uri( + scheme: 'https', + host: 'servers.joinmatrix.org', + path: 'servers.json', + ); static void loadFromJson(Map json) { if (json['chat_color'] != null) { diff --git a/lib/pages/homeserver_picker/homeserver_app_bar.dart b/lib/pages/homeserver_picker/homeserver_app_bar.dart index 3b7611ed..165d76ea 100644 --- a/lib/pages/homeserver_picker/homeserver_app_bar.dart +++ b/lib/pages/homeserver_picker/homeserver_app_bar.dart @@ -2,9 +2,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_typeahead/flutter_typeahead.dart'; -import 'package:matrix_homeserver_recommendations/matrix_homeserver_recommendations.dart'; import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/pages/homeserver_picker/public_homeserver.dart'; import 'homeserver_bottom_sheet.dart'; import 'homeserver_picker.dart'; @@ -15,16 +15,26 @@ class HomeserverAppBar extends StatelessWidget { @override Widget build(BuildContext context) { - return TypeAheadField( + return TypeAheadField( suggestionsBoxDecoration: SuggestionsBoxDecoration( borderRadius: BorderRadius.circular(AppConfig.borderRadius), elevation: Theme.of(context).appBarTheme.scrolledUnderElevation ?? 4, shadowColor: Theme.of(context).appBarTheme.shadowColor ?? Colors.black, constraints: const BoxConstraints(maxHeight: 256), ), + noItemsFoundBuilder: (context) => ListTile( + leading: const Icon(Icons.search_outlined), + title: Text(L10n.of(context)!.nothingFound), + ), + loadingBuilder: (context) => ListTile( + leading: const CircularProgressIndicator.adaptive(strokeWidth: 2), + title: Text(L10n.of(context)!.loadingPleaseWait), + ), itemBuilder: (context, homeserver) => ListTile( - title: Text(homeserver.homeserver.baseUrl.toString()), - subtitle: Text(homeserver.homeserver.description ?? ''), + title: Text(homeserver.name), + subtitle: homeserver.description == null + ? null + : Text(homeserver.description ?? ''), trailing: IconButton( icon: const Icon(Icons.info_outlined), onPressed: () => showModalBottomSheet( @@ -36,17 +46,25 @@ class HomeserverAppBar extends StatelessWidget { ), ), suggestionsCallback: (pattern) async { - final homeserverList = - await const JoinmatrixOrgParser().fetchHomeservers(); - final benchmark = await HomeserverListProvider.benchmarkHomeserver( - homeserverList, - timeout: const Duration(seconds: 3), - ); - return benchmark; + pattern = pattern.toLowerCase().trim(); + final homeservers = await controller.loadHomeserverList(); + final matches = homeservers + .where( + (homeserver) => + homeserver.name.toLowerCase().contains(pattern) || + (homeserver.description?.toLowerCase().contains(pattern) ?? + false), + ) + .toList(); + if (pattern.contains('.') && + pattern.split('.').any((part) => part.isNotEmpty) && + !matches.any((homeserver) => homeserver.name == pattern)) { + matches.add(PublicHomeserver(name: pattern)); + } + return matches; }, onSuggestionSelected: (suggestion) { - controller.homeserverController.text = - suggestion.homeserver.baseUrl.host; + controller.homeserverController.text = suggestion.name; controller.checkHomeserverAction(); }, textFieldConfiguration: TextFieldConfiguration( diff --git a/lib/pages/homeserver_picker/homeserver_bottom_sheet.dart b/lib/pages/homeserver_picker/homeserver_bottom_sheet.dart index 0fc6d011..18256d6f 100644 --- a/lib/pages/homeserver_picker/homeserver_bottom_sheet.dart +++ b/lib/pages/homeserver_picker/homeserver_bottom_sheet.dart @@ -1,24 +1,22 @@ import 'package:flutter/material.dart'; -import 'package:matrix_homeserver_recommendations/matrix_homeserver_recommendations.dart'; import 'package:url_launcher/url_launcher_string.dart'; +import 'package:fluffychat/pages/homeserver_picker/public_homeserver.dart'; + class HomeserverBottomSheet extends StatelessWidget { - final HomeserverBenchmarkResult homeserver; + final PublicHomeserver homeserver; const HomeserverBottomSheet({required this.homeserver, super.key}); @override Widget build(BuildContext context) { - final responseTime = homeserver.responseTime; - final description = homeserver.homeserver.description; - final rules = homeserver.homeserver.rules; - final privacy = homeserver.homeserver.privacyPolicy; - final registration = homeserver.homeserver.registration; - final jurisdiction = homeserver.homeserver.jurisdiction; - final homeserverSoftware = homeserver.homeserver.homeserverSoftware; + final description = homeserver.description; + final registration = homeserver.regLink; + final jurisdiction = homeserver.staffJur; + final homeserverSoftware = homeserver.software; return Scaffold( appBar: AppBar( - title: Text(homeserver.homeserver.baseUrl.host), + title: Text(homeserver.name), ), body: ListView( children: [ @@ -38,33 +36,15 @@ class HomeserverBottomSheet extends StatelessWidget { title: Text(homeserverSoftware), ), ListTile( - onTap: () => - launchUrlString(homeserver.homeserver.baseUrl.toString()), + onTap: () => launchUrlString(homeserver.name), leading: const Icon(Icons.link_outlined), - title: Text(homeserver.homeserver.baseUrl.toString()), + title: Text(homeserver.name), ), if (registration != null) ListTile( - onTap: () => launchUrlString(registration.toString()), + onTap: () => launchUrlString(registration), leading: const Icon(Icons.person_add_outlined), - title: Text(registration.toString()), - ), - if (rules != null) - ListTile( - onTap: () => launchUrlString(rules.toString()), - leading: const Icon(Icons.visibility_outlined), - title: Text(rules.toString()), - ), - if (privacy != null) - ListTile( - onTap: () => launchUrlString(privacy.toString()), - leading: const Icon(Icons.shield_outlined), - title: Text(privacy.toString()), - ), - if (responseTime != null) - ListTile( - leading: const Icon(Icons.timer_outlined), - title: Text('${responseTime.inMilliseconds}ms'), + title: Text(registration), ), ], ), diff --git a/lib/pages/homeserver_picker/homeserver_picker.dart b/lib/pages/homeserver_picker/homeserver_picker.dart index c711fd0c..5f42c325 100644 --- a/lib/pages/homeserver_picker/homeserver_picker.dart +++ b/lib/pages/homeserver_picker/homeserver_picker.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -15,6 +16,7 @@ import 'package:universal_html/html.dart' as html; import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pages/homeserver_picker/homeserver_picker_view.dart'; +import 'package:fluffychat/pages/homeserver_picker/public_homeserver.dart'; import 'package:fluffychat/utils/platform_infos.dart'; import 'package:fluffychat/widgets/app_lock.dart'; import 'package:fluffychat/widgets/matrix.dart'; @@ -176,6 +178,20 @@ class HomeserverPickerController extends State { return list; } + List? cachedHomeservers; + + Future> loadHomeserverList() async { + if (cachedHomeservers != null) return cachedHomeservers!; + final result = await Matrix.of(context) + .getLoginClient() + .httpClient + .get(AppConfig.homeserverList); + final resultJson = jsonDecode(result.body)['public_servers'] as List; + final homeserverList = + resultJson.map((json) => PublicHomeserver.fromJson(json)).toList(); + return cachedHomeservers = homeserverList; + } + void login() => context.go('${GoRouterState.of(context).fullPath}/login'); @override diff --git a/lib/pages/homeserver_picker/public_homeserver.dart b/lib/pages/homeserver_picker/public_homeserver.dart new file mode 100644 index 00000000..4eef2aa5 --- /dev/null +++ b/lib/pages/homeserver_picker/public_homeserver.dart @@ -0,0 +1,73 @@ +class PublicHomeserver { + final String name; + final String? clientDomain; + final String? isp; + final String? staffJur; + final bool? usingVanillaReg; + final String? description; + final String? regMethod; + final String? regLink; + final String? software; + final String? version; + final bool? captcha; + final bool? email; + final List? languages; + final List? features; + final int? onlineStatus; + final String? serverDomain; + final int? verStatus; + final int? roomDirectory; + final bool? slidingSync; + final bool? ipv6; + + const PublicHomeserver({ + required this.name, + this.clientDomain, + this.isp, + this.staffJur, + this.usingVanillaReg, + this.description, + this.regMethod, + this.regLink, + this.software, + this.version, + this.captcha, + this.email, + this.languages, + this.features, + this.onlineStatus, + this.serverDomain, + this.verStatus, + this.roomDirectory, + this.slidingSync, + this.ipv6, + }); + + factory PublicHomeserver.fromJson(Map json) => + PublicHomeserver( + name: json['name'], + clientDomain: json['client_domain'], + isp: json['isp'], + staffJur: json['staff_jur'], + usingVanillaReg: json['using_vanilla_reg'], + description: json['description'], + regMethod: json['reg_method'], + regLink: json['reg_link'], + software: json['software'], + version: json['version'], + captcha: json['captcha'], + email: json['email'], + languages: json['languages'] == null + ? null + : List.from(json['languages']), + features: json['features'] == null + ? null + : List.from(json['features']), + onlineStatus: json['online_status'], + serverDomain: json['server_domain'], + verStatus: json['ver_status'], + roomDirectory: json['room_directory'], + slidingSync: json['sliding_sync'], + ipv6: json['ipv6'], + ); +} diff --git a/pubspec.lock b/pubspec.lock index e0e16f33..23a0b7b2 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1165,14 +1165,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.7.2" - matrix_homeserver_recommendations: - dependency: "direct main" - description: - name: matrix_homeserver_recommendations - sha256: d372a7357676106897134dac67beb3ac2bb8753922fd0d808f18cf7e0574001a - url: "https://pub.dev" - source: hosted - version: "0.3.0" meta: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 93dfc368..00bde27d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -62,7 +62,6 @@ dependencies: latlong2: ^0.8.1 linkify: ^5.0.0 matrix: ^0.25.0 - matrix_homeserver_recommendations: ^0.3.0 native_imaging: ^0.1.0 package_info_plus: ^4.0.0 pasteboard: ^0.2.0