mirror of
https://gitlab.com/famedly/fluffychat.git
synced 2025-01-08 08:12:37 +01:00
feat: propose homeserver based on response time
- use `package:matrix_homeserver_recommendations` to benchmark homeservers - propose fastest server without anti-features as homeserver - display small button with server information - use Matrix.org / the default configuration as fallback Signed-off-by: TheOneWithTheBraid <the-one@with-the-braid.cf>
This commit is contained in:
parent
95182a623e
commit
a81e732617
@ -2709,5 +2709,15 @@
|
|||||||
"@iUnderstand": {},
|
"@iUnderstand": {},
|
||||||
"openChat": "Open Chat",
|
"openChat": "Open Chat",
|
||||||
"markAsRead": "Mark as read",
|
"markAsRead": "Mark as read",
|
||||||
"reportUser": "Report user"
|
"reportUser": "Report user",
|
||||||
|
"showAvailableHomeservers": "Show available homeservers (Advanced users)",
|
||||||
|
"antiFeatures": "Anti-features",
|
||||||
|
"noAntiFeaturesRecorded": "No anti features recorded",
|
||||||
|
"serverRules": "Server rules",
|
||||||
|
"jurisdiction": "Jurisdiction",
|
||||||
|
"selectServer": "Select server",
|
||||||
|
"responseTime": "Response time",
|
||||||
|
"openServerList": "Visit",
|
||||||
|
"reportServerListProblem": "Report list issue",
|
||||||
|
"serverListJoinMatrix": "Server list by joinMatrix.org"
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,12 @@ import 'dart:async';
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:animations/animations.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
|
import 'package:matrix_homeserver_recommendations/matrix_homeserver_recommendations.dart';
|
||||||
import 'package:uni_links/uni_links.dart';
|
import 'package:uni_links/uni_links.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
import 'package:vrouter/vrouter.dart';
|
import 'package:vrouter/vrouter.dart';
|
||||||
@ -19,6 +21,7 @@ import 'package:fluffychat/utils/platform_infos.dart';
|
|||||||
import 'package:fluffychat/widgets/matrix.dart';
|
import 'package:fluffychat/widgets/matrix.dart';
|
||||||
import '../../main.dart';
|
import '../../main.dart';
|
||||||
import '../../utils/localized_exception_extension.dart';
|
import '../../utils/localized_exception_extension.dart';
|
||||||
|
import 'homeserver_tile.dart';
|
||||||
|
|
||||||
class HomeserverPicker extends StatefulWidget {
|
class HomeserverPicker extends StatefulWidget {
|
||||||
const HomeserverPicker({Key? key}) : super(key: key);
|
const HomeserverPicker({Key? key}) : super(key: key);
|
||||||
@ -28,14 +31,19 @@ class HomeserverPicker extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class HomeserverPickerController extends State<HomeserverPicker> {
|
class HomeserverPickerController extends State<HomeserverPicker> {
|
||||||
bool isLoading = false;
|
bool isLoading = true;
|
||||||
String domain = AppConfig.defaultHomeserver;
|
|
||||||
final TextEditingController homeserverController =
|
String? domain;
|
||||||
TextEditingController(text: AppConfig.defaultHomeserver);
|
List<HomeserverBenchmarkResult>? benchmarkResults;
|
||||||
|
|
||||||
|
TextEditingController? homeserverController;
|
||||||
|
|
||||||
StreamSubscription? _intentDataStreamSubscription;
|
StreamSubscription? _intentDataStreamSubscription;
|
||||||
String? error;
|
String? error;
|
||||||
Timer? _coolDown;
|
Timer? _coolDown;
|
||||||
|
|
||||||
|
late HomeserverListProvider parser;
|
||||||
|
|
||||||
void setDomain(String domain) {
|
void setDomain(String domain) {
|
||||||
this.domain = domain;
|
this.domain = domain;
|
||||||
_coolDown?.cancel();
|
_coolDown?.cancel();
|
||||||
@ -94,7 +102,7 @@ class HomeserverPickerController extends State<HomeserverPicker> {
|
|||||||
if (token != null) _loginWithToken(token);
|
if (token != null) _loginWithToken(token);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
checkHomeserverAction();
|
benchmarkHomeServers();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -112,10 +120,12 @@ class HomeserverPickerController extends State<HomeserverPicker> {
|
|||||||
Future<void> checkHomeserverAction() async {
|
Future<void> checkHomeserverAction() async {
|
||||||
_coolDown?.cancel();
|
_coolDown?.cancel();
|
||||||
if (_lastCheckedHomeserver == domain) return;
|
if (_lastCheckedHomeserver == domain) return;
|
||||||
if (domain.isEmpty) throw L10n.of(context)!.changeTheHomeserver;
|
if (domain == null || domain!.isEmpty) {
|
||||||
|
throw L10n.of(context)!.changeTheHomeserver;
|
||||||
|
}
|
||||||
var homeserver = domain;
|
var homeserver = domain;
|
||||||
|
|
||||||
if (!homeserver.startsWith('https://')) {
|
if (!homeserver!.startsWith('https://')) {
|
||||||
homeserver = 'https://$homeserver';
|
homeserver = 'https://$homeserver';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,7 +233,7 @@ class HomeserverPickerController extends State<HomeserverPicker> {
|
|||||||
|
|
||||||
void signUpAction() => VRouter.of(context).to(
|
void signUpAction() => VRouter.of(context).to(
|
||||||
'signup',
|
'signup',
|
||||||
queryParameters: {'domain': domain},
|
queryParameters: {'domain': domain!},
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -231,6 +241,75 @@ class HomeserverPickerController extends State<HomeserverPicker> {
|
|||||||
Matrix.of(context).navigatorContext = context;
|
Matrix.of(context).navigatorContext = context;
|
||||||
return HomeserverPickerView(this);
|
return HomeserverPickerView(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> benchmarkHomeServers() async {
|
||||||
|
try {
|
||||||
|
parser = JoinmatrixOrgParser();
|
||||||
|
final homeserverList = await parser.fetchHomeservers();
|
||||||
|
final benchmark = await HomeserverListProvider.benchmarkHomeserver(
|
||||||
|
homeserverList,
|
||||||
|
timeout: const Duration(seconds: 10),
|
||||||
|
// TODO: do not rely on the homeserver list information telling the server supports registration
|
||||||
|
);
|
||||||
|
|
||||||
|
if (benchmark.isEmpty) {
|
||||||
|
throw NullThrownError();
|
||||||
|
}
|
||||||
|
|
||||||
|
// trying to use server without anti-features
|
||||||
|
final goodServers = <HomeserverBenchmarkResult>[];
|
||||||
|
final badServers = <HomeserverBenchmarkResult>[];
|
||||||
|
for (final result in benchmark) {
|
||||||
|
if (result.homeserver.antiFeatures == null) {
|
||||||
|
goodServers.add(result);
|
||||||
|
} else {
|
||||||
|
badServers.add(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
goodServers.sort();
|
||||||
|
badServers.sort();
|
||||||
|
|
||||||
|
benchmarkResults = List.from([...goodServers, ...badServers]);
|
||||||
|
|
||||||
|
domain = benchmarkResults!.first.homeserver.baseUrl.host;
|
||||||
|
} on Exception catch (e, s) {
|
||||||
|
Logs().e('Homeserver benchmark failed', e, s);
|
||||||
|
domain = AppConfig.defaultHomeserver;
|
||||||
|
} finally {
|
||||||
|
homeserverController = TextEditingController(text: domain);
|
||||||
|
checkHomeserverAction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> showServerPicker() async {
|
||||||
|
final selection = await showModal(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => SimpleDialog(
|
||||||
|
title: Text(L10n.of(context)!.changeTheHomeserver),
|
||||||
|
children: [
|
||||||
|
...benchmarkResults!.map<Widget>(
|
||||||
|
(e) => HomeserverTile(
|
||||||
|
benchmark: e,
|
||||||
|
onSelect: () {
|
||||||
|
Navigator.of(context).pop(e.homeserver);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(),
|
||||||
|
JoinMatrixAttributionTile(),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
if (selection is Homeserver) {
|
||||||
|
if (domain != selection.baseUrl.host) {
|
||||||
|
setState(() {
|
||||||
|
domain = selection.baseUrl.host;
|
||||||
|
homeserverController!.text = domain!;
|
||||||
|
});
|
||||||
|
checkHomeserverAction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class IdentityProvider {
|
class IdentityProvider {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:animations/animations.dart';
|
||||||
import 'package:cached_network_image/cached_network_image.dart';
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
@ -25,18 +26,44 @@ class HomeserverPickerView extends StatelessWidget {
|
|||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
titleSpacing: 8,
|
titleSpacing: 8,
|
||||||
title: DefaultAppBarSearchField(
|
title: PageTransitionSwitcher(
|
||||||
prefixText: 'https://',
|
transitionBuilder: (
|
||||||
hintText: L10n.of(context)!.enterYourHomeserver,
|
Widget child,
|
||||||
searchController: controller.homeserverController,
|
Animation<double> primaryAnimation,
|
||||||
suffix: const Icon(Icons.edit_outlined),
|
Animation<double> secondaryAnimation,
|
||||||
padding: EdgeInsets.zero,
|
) {
|
||||||
onChanged: controller.setDomain,
|
return SharedAxisTransition(
|
||||||
readOnly: !AppConfig.allowOtherHomeservers,
|
animation: primaryAnimation,
|
||||||
onSubmit: (_) => controller.checkHomeserverAction(),
|
secondaryAnimation: secondaryAnimation,
|
||||||
unfocusOnClear: false,
|
transitionType: SharedAxisTransitionType.vertical,
|
||||||
autocorrect: false,
|
fillColor: Colors.transparent,
|
||||||
labelText: L10n.of(context)!.homeserver,
|
child: child,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: controller.homeserverController == null
|
||||||
|
? Center(
|
||||||
|
key: ValueKey(controller.homeserverController),
|
||||||
|
child: const CircularProgressIndicator(),
|
||||||
|
)
|
||||||
|
: DefaultAppBarSearchField(
|
||||||
|
key: ValueKey(controller.homeserverController),
|
||||||
|
prefixIcon: IconButton(
|
||||||
|
icon: const Icon(Icons.format_list_numbered),
|
||||||
|
onPressed: controller.showServerPicker,
|
||||||
|
tooltip: L10n.of(context)!.showAvailableHomeservers,
|
||||||
|
),
|
||||||
|
prefixText: 'https://',
|
||||||
|
hintText: L10n.of(context)!.enterYourHomeserver,
|
||||||
|
searchController: controller.homeserverController,
|
||||||
|
suffix: const Icon(Icons.edit_outlined),
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
onChanged: controller.setDomain,
|
||||||
|
readOnly: !AppConfig.allowOtherHomeservers,
|
||||||
|
onSubmit: (_) => controller.checkHomeserverAction(),
|
||||||
|
unfocusOnClear: false,
|
||||||
|
autocorrect: false,
|
||||||
|
labelText: L10n.of(context)!.homeserver,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
),
|
),
|
||||||
|
108
lib/pages/homeserver_picker/homeserver_tile.dart
Normal file
108
lib/pages/homeserver_picker/homeserver_tile.dart
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
|
import 'package:matrix_homeserver_recommendations/matrix_homeserver_recommendations.dart';
|
||||||
|
import 'package:url_launcher/link.dart';
|
||||||
|
|
||||||
|
class HomeserverTile extends StatelessWidget {
|
||||||
|
final HomeserverBenchmarkResult benchmark;
|
||||||
|
final VoidCallback onSelect;
|
||||||
|
|
||||||
|
const HomeserverTile(
|
||||||
|
{Key? key, required this.benchmark, required this.onSelect})
|
||||||
|
: super(key: key);
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ExpansionTile(
|
||||||
|
title: Text(benchmark.homeserver.baseUrl.host),
|
||||||
|
subtitle: benchmark.homeserver.description != null
|
||||||
|
? Text(benchmark.homeserver.description!)
|
||||||
|
: null,
|
||||||
|
children: [
|
||||||
|
benchmark.homeserver.antiFeatures != null &&
|
||||||
|
benchmark.homeserver.antiFeatures!.isNotEmpty
|
||||||
|
? ListTile(
|
||||||
|
leading: const Icon(Icons.thumb_down),
|
||||||
|
title: Text(benchmark.homeserver.antiFeatures!),
|
||||||
|
subtitle: Text(L10n.of(context)!.antiFeatures),
|
||||||
|
)
|
||||||
|
: ListTile(
|
||||||
|
leading: const Icon(Icons.recommend),
|
||||||
|
title: Text(L10n.of(context)!.noAntiFeaturesRecorded),
|
||||||
|
),
|
||||||
|
if (benchmark.homeserver.jurisdiction != null)
|
||||||
|
ListTile(
|
||||||
|
leading: const Icon(Icons.public),
|
||||||
|
title: Text(benchmark.homeserver.jurisdiction!),
|
||||||
|
subtitle: Text(L10n.of(context)!.jurisdiction),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: const Icon(Icons.speed),
|
||||||
|
title: Text("${benchmark.responseTime!.inMilliseconds} ms"),
|
||||||
|
subtitle: Text(L10n.of(context)!.responseTime),
|
||||||
|
),
|
||||||
|
ButtonBar(
|
||||||
|
/* spacing: 8,
|
||||||
|
runSpacing: 8,
|
||||||
|
alignment: WrapAlignment.end,
|
||||||
|
runAlignment: WrapAlignment.center,
|
||||||
|
crossAxisAlignment: WrapCrossAlignment.center, */
|
||||||
|
children: [
|
||||||
|
if (benchmark.homeserver.privacyPolicy != null)
|
||||||
|
Link(
|
||||||
|
uri: benchmark.homeserver.privacyPolicy!,
|
||||||
|
target: LinkTarget.blank,
|
||||||
|
builder: (context, callback) => TextButton(
|
||||||
|
onPressed: callback,
|
||||||
|
child: Text(L10n.of(context)!.privacy),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (benchmark.homeserver.rules != null)
|
||||||
|
Link(
|
||||||
|
uri: benchmark.homeserver.rules!,
|
||||||
|
target: LinkTarget.blank,
|
||||||
|
builder: (context, callback) => TextButton(
|
||||||
|
onPressed: callback,
|
||||||
|
child: Text(L10n.of(context)!.serverRules),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
OutlinedButton(
|
||||||
|
onPressed: onSelect.call,
|
||||||
|
child: Text(L10n.of(context)!.selectServer),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class JoinMatrixAttributionTile extends StatelessWidget {
|
||||||
|
final parser = JoinmatrixOrgParser();
|
||||||
|
|
||||||
|
JoinMatrixAttributionTile({Key? key}) : super(key: key);
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ListTile(
|
||||||
|
title: Text(L10n.of(context)!.serverListJoinMatrix),
|
||||||
|
subtitle: ButtonBar(children: [
|
||||||
|
Link(
|
||||||
|
uri: parser.externalUri,
|
||||||
|
target: LinkTarget.blank,
|
||||||
|
builder: (context, callback) => TextButton(
|
||||||
|
onPressed: callback,
|
||||||
|
child: Text(L10n.of(context)!.openServerList),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Link(
|
||||||
|
uri: parser.errorReportUrl,
|
||||||
|
target: LinkTarget.blank,
|
||||||
|
builder: (context, callback) => TextButton(
|
||||||
|
onPressed: callback,
|
||||||
|
child: Text(L10n.of(context)!.reportServerListProblem),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -17,6 +17,7 @@ import path_provider_macos
|
|||||||
import shared_preferences_macos
|
import shared_preferences_macos
|
||||||
import sqflite
|
import sqflite
|
||||||
import url_launcher_macos
|
import url_launcher_macos
|
||||||
|
import video_compress
|
||||||
import wakelock_macos
|
import wakelock_macos
|
||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||||
@ -32,5 +33,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|||||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||||
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
||||||
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||||
|
VideoCompressPlugin.register(with: registry.registrar(forPlugin: "VideoCompressPlugin"))
|
||||||
WakelockMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockMacosPlugin"))
|
WakelockMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockMacosPlugin"))
|
||||||
}
|
}
|
||||||
|
27
pubspec.lock
27
pubspec.lock
@ -211,6 +211,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.17.1"
|
version: "0.17.1"
|
||||||
|
csv:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: csv
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "5.0.1"
|
||||||
cupertino_icons:
|
cupertino_icons:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -812,6 +819,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.11"
|
version: "0.12.11"
|
||||||
|
material_color_utilities:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: material_color_utilities
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.3"
|
||||||
matrix:
|
matrix:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -826,6 +840,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.3"
|
version: "0.5.3"
|
||||||
|
matrix_homeserver_recommendations:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: matrix_homeserver_recommendations
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.4"
|
||||||
matrix_link_text:
|
matrix_link_text:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -1411,21 +1432,21 @@ packages:
|
|||||||
name: test
|
name: test
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.17.12"
|
version: "1.19.5"
|
||||||
test_api:
|
test_api:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.3"
|
version: "0.4.8"
|
||||||
test_core:
|
test_core:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_core
|
name: test_core
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.2"
|
version: "0.4.9"
|
||||||
timezone:
|
timezone:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -51,6 +51,7 @@ dependencies:
|
|||||||
localstorage: ^4.0.0+1
|
localstorage: ^4.0.0+1
|
||||||
lottie: ^1.2.1
|
lottie: ^1.2.1
|
||||||
matrix: ^0.8.2
|
matrix: ^0.8.2
|
||||||
|
matrix_homeserver_recommendations: ^0.1.4
|
||||||
matrix_link_text: ^1.0.2
|
matrix_link_text: ^1.0.2
|
||||||
open_noti_settings: ^0.4.0
|
open_noti_settings: ^0.4.0
|
||||||
package_info_plus: ^1.2.1
|
package_info_plus: ^1.2.1
|
||||||
|
@ -2,14 +2,22 @@
|
|||||||
// Generated file. Do not edit.
|
// Generated file. Do not edit.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
#include "generated_plugin_registrant.h"
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
#include <file_chooser/file_chooser_plugin.h>
|
#include <desktop_drop/desktop_drop_plugin.h>
|
||||||
#include <url_launcher_windows/url_launcher_plugin.h>
|
#include <file_selector_windows/file_selector_plugin.h>
|
||||||
|
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
|
||||||
|
#include <url_launcher_windows/url_launcher_windows.h>
|
||||||
|
|
||||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||||
FileChooserPluginRegisterWithRegistrar(
|
DesktopDropPluginRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("FileChooserPlugin"));
|
registry->GetRegistrarForPlugin("DesktopDropPlugin"));
|
||||||
UrlLauncherPluginRegisterWithRegistrar(
|
FileSelectorPluginRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("UrlLauncherPlugin"));
|
registry->GetRegistrarForPlugin("FileSelectorPlugin"));
|
||||||
|
FlutterSecureStorageWindowsPluginRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin"));
|
||||||
|
UrlLauncherWindowsRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
// Generated file. Do not edit.
|
// Generated file. Do not edit.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
#ifndef GENERATED_PLUGIN_REGISTRANT_
|
#ifndef GENERATED_PLUGIN_REGISTRANT_
|
||||||
#define GENERATED_PLUGIN_REGISTRANT_
|
#define GENERATED_PLUGIN_REGISTRANT_
|
||||||
|
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
file_chooser
|
desktop_drop
|
||||||
|
file_selector_windows
|
||||||
|
flutter_secure_storage_windows
|
||||||
url_launcher_windows
|
url_launcher_windows
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user