diff --git a/lib/api/analytics.dart b/lib/api/analytics.dart index 4c9f028..e7a59ea 100644 --- a/lib/api/analytics.dart +++ b/lib/api/analytics.dart @@ -1,17 +1,19 @@ -import 'package:dio/dio.dart'; +import 'dart:convert'; + import 'package:flutter/foundation.dart'; import 'package:starcitizen_doctor/common/conf/url_conf.dart'; import 'package:starcitizen_doctor/common/utils/base_utils.dart'; +import 'package:starcitizen_doctor/common/rust/api/http_api.dart' as rust_http; class AnalyticsApi { - static final Dio _dio = Dio(); - static touch(String key) async { // debug 不统计 if (kDebugMode) return; dPrint("AnalyticsApi.touch === $key start"); try { - await _dio.post("${URLConf.xkeycApiHome}/analytics/$key"); + await rust_http.postJsonString( + url: "${URLConf.xkeycApiHome}/analytics/$key", + jsonData: json.encode({"test": "a"})); dPrint("AnalyticsApi.touch === $key over"); } catch (e) { dPrint("AnalyticsApi.touch === $key Error:$e"); diff --git a/lib/api/api.dart b/lib/api/api.dart index fc8d4fb..d6d8f30 100644 --- a/lib/api/api.dart +++ b/lib/api/api.dart @@ -1,16 +1,13 @@ import 'dart:convert'; -import 'package:dio/dio.dart'; import 'package:starcitizen_doctor/common/conf/url_conf.dart'; +import 'package:starcitizen_doctor/common/rust/api/http_api.dart' as rust_http; import 'package:starcitizen_doctor/data/app_placard_data.dart'; import 'package:starcitizen_doctor/data/app_version_data.dart'; import 'package:starcitizen_doctor/data/countdown_festival_item_data.dart'; import 'package:starcitizen_doctor/data/sc_localization_data.dart'; class Api { - static final dio = - Dio(BaseOptions(connectTimeout: const Duration(seconds: 10))); - static Future getAppVersion() async { return AppVersionData.fromJson( await getRepoJson("sc_doctor", "version.json")); @@ -36,9 +33,10 @@ class Api { static Future> getAppReleaseDataByVersionName( String version) async { - final r = await dio.get( - "${URLConf.gitlabApiPath}/repos/SCToolBox/Release/releases/tags/$version"); - return r.data; + final r = await rust_http.getString( + url: + "${URLConf.gitlabApiPath}/repos/SCToolBox/Release/releases/tags/$version"); + return json.decode(r); } static Future> getScLocalizationData( @@ -54,9 +52,10 @@ class Api { } static Future getScServerStatus() async { - final r = - await dio.get("https://status.robertsspaceindustries.com/index.json"); - return r.data["systems"]; + final r = await rust_http.getString( + url: "https://status.robertsspaceindustries.com/index.json"); + final map = json.decode(r); + return map["systems"]; } static Future> getRepoJson( @@ -65,8 +64,9 @@ class Api { return json.decode(data); } - static Future getRepoData(String dir, String name) async { - final r = await dio.get("${URLConf.apiRepoPath}/$dir/$name"); - return r.data; + static Future getRepoData(String dir, String name) async { + final r = + await rust_http.getString(url: "${URLConf.apiRepoPath}/$dir/$name"); + return r; } } diff --git a/lib/api/rss.dart b/lib/api/rss.dart index 04e20f1..8e06145 100644 --- a/lib/api/rss.dart +++ b/lib/api/rss.dart @@ -1,25 +1,21 @@ import 'dart:io'; import 'package:dart_rss/dart_rss.dart'; -import 'package:dio/dio.dart'; +import 'package:starcitizen_doctor/common/rust/api/http_api.dart' as rust_http; import 'package:starcitizen_doctor/common/conf/url_conf.dart'; class RSSApi { - static final _dio = Dio(BaseOptions( - connectTimeout: const Duration(seconds: 10), - responseType: ResponseType.plain)); - static Future> getRssVideo() async { - final r = await _dio.get(URLConf.rssVideoUrl); - final f = RssFeed.parse(r.data); + final r = await rust_http.getString(url: URLConf.rssVideoUrl); + final f = RssFeed.parse(r); return f.items.sublist(0, 8); } static Future> getRssText() async { - final r1 = await _dio.get(URLConf.rssTextUrl1); - final r1f = RssFeed.parse(r1.data); - final r2 = await _dio.get(URLConf.rssTextUrl2); - final r2f = RssFeed.parse(r2.data); + final r1 = await rust_http.getString(url: URLConf.rssTextUrl1); + final r1f = RssFeed.parse(r1); + final r2 = await rust_http.getString(url: URLConf.rssTextUrl2); + final r2f = RssFeed.parse(r2); final items = r1f.items..addAll(r2f.items); items.sort((a, b) { final aDate = HttpDate.parse(a.pubDate ?? "").millisecondsSinceEpoch; diff --git a/lib/common/rust/api/http_api.dart b/lib/common/rust/api/http_api.dart new file mode 100644 index 0000000..553808d --- /dev/null +++ b/lib/common/rust/api/http_api.dart @@ -0,0 +1,19 @@ +// This file is automatically generated, so please do not edit it. +// Generated by `flutter_rust_bridge`@ 2.0.0-dev.23. + +// ignore_for_file: invalid_use_of_internal_member, unused_import, unnecessary_import + +import '../frb_generated.dart'; +import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart'; + +Future getString( + {required String url, Map? headers, dynamic hint}) => + RustLib.instance.api.getString(url: url, headers: headers, hint: hint); + +Future postJsonString( + {required String url, + Map? headers, + String? jsonData, + dynamic hint}) => + RustLib.instance.api.postJsonString( + url: url, headers: headers, jsonData: jsonData, hint: hint); diff --git a/lib/common/rust/frb_generated.dart b/lib/common/rust/frb_generated.dart index 43d637f..d1536a6 100644 --- a/lib/common/rust/frb_generated.dart +++ b/lib/common/rust/frb_generated.dart @@ -4,6 +4,7 @@ // ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field import 'api/downloader_api.dart'; +import 'api/http_api.dart'; import 'dart:async'; import 'dart:convert'; import 'downloader.dart'; @@ -71,6 +72,15 @@ abstract class RustLibApi extends BaseApi { required String fileName, required int connectionCount, dynamic hint}); + + Future getString( + {required String url, Map? headers, dynamic hint}); + + Future postJsonString( + {required String url, + Map? headers, + String? jsonData, + dynamic hint}); } class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { @@ -139,6 +149,71 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { argNames: ["url", "savePath", "fileName", "connectionCount"], ); + @override + Future getString( + {required String url, Map? headers, dynamic hint}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(url, serializer); + sse_encode_opt_Map_String_String(headers, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 3, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: null, + ), + constMeta: kGetStringConstMeta, + argValues: [url, headers], + apiImpl: this, + hint: hint, + )); + } + + TaskConstMeta get kGetStringConstMeta => const TaskConstMeta( + debugName: "get_string", + argNames: ["url", "headers"], + ); + + @override + Future postJsonString( + {required String url, + Map? headers, + String? jsonData, + dynamic hint}) { + return handler.executeNormal(NormalTask( + callFfi: (port_) { + final serializer = SseSerializer(generalizedFrbRustBinding); + sse_encode_String(url, serializer); + sse_encode_opt_Map_String_String(headers, serializer); + sse_encode_opt_String(jsonData, serializer); + pdeCallFfi(generalizedFrbRustBinding, serializer, + funcId: 4, port: port_); + }, + codec: SseCodec( + decodeSuccessData: sse_decode_String, + decodeErrorData: null, + ), + constMeta: kPostJsonStringConstMeta, + argValues: [url, headers, jsonData], + apiImpl: this, + hint: hint, + )); + } + + TaskConstMeta get kPostJsonStringConstMeta => const TaskConstMeta( + debugName: "post_json_string", + argNames: ["url", "headers", "jsonData"], + ); + + @protected + Map dco_decode_Map_String_String(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return Map.fromEntries(dco_decode_list_record_string_string(raw) + .map((e) => MapEntry(e.$1, e.$2))); + } + @protected String dco_decode_String(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -172,6 +247,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return raw as Uint8List; } + @protected + List<(String, String)> dco_decode_list_record_string_string(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return (raw as List).map(dco_decode_record_string_string).toList(); + } + @protected MyDownloaderStatus dco_decode_my_downloader_status(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -202,6 +283,31 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return MyNetworkItemPendingType.values[raw as int]; } + @protected + Map? dco_decode_opt_Map_String_String(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw == null ? null : dco_decode_Map_String_String(raw); + } + + @protected + String? dco_decode_opt_String(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return raw == null ? null : dco_decode_String(raw); + } + + @protected + (String, String) dco_decode_record_string_string(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + final arr = raw as List; + if (arr.length != 2) { + throw Exception('Expected 2 elements, got ${arr.length}'); + } + return ( + dco_decode_String(arr[0]), + dco_decode_String(arr[1]), + ); + } + @protected int dco_decode_u_64(dynamic raw) { // Codec=Dco (DartCObject based), see doc to use other codecs @@ -220,6 +326,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return; } + @protected + Map sse_decode_Map_String_String( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var inner = sse_decode_list_record_string_string(deserializer); + return Map.fromEntries(inner.map((e) => MapEntry(e.$1, e.$2))); + } + @protected String sse_decode_String(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -257,6 +371,19 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return deserializer.buffer.getUint8List(len_); } + @protected + List<(String, String)> sse_decode_list_record_string_string( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + var len_ = sse_decode_i_32(deserializer); + var ans_ = <(String, String)>[]; + for (var idx_ = 0; idx_ < len_; ++idx_) { + ans_.add(sse_decode_record_string_string(deserializer)); + } + return ans_; + } + @protected MyDownloaderStatus sse_decode_my_downloader_status( SseDeserializer deserializer) { @@ -289,6 +416,38 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return MyNetworkItemPendingType.values[inner]; } + @protected + Map? sse_decode_opt_Map_String_String( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + if (sse_decode_bool(deserializer)) { + return (sse_decode_Map_String_String(deserializer)); + } else { + return null; + } + } + + @protected + String? sse_decode_opt_String(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + if (sse_decode_bool(deserializer)) { + return (sse_decode_String(deserializer)); + } else { + return null; + } + } + + @protected + (String, String) sse_decode_record_string_string( + SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + var var_field0 = sse_decode_String(deserializer); + var var_field1 = sse_decode_String(deserializer); + return (var_field0, var_field1); + } + @protected int sse_decode_u_64(SseDeserializer deserializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -312,6 +471,14 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return deserializer.buffer.getUint8() != 0; } + @protected + void sse_encode_Map_String_String( + Map self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_list_record_string_string( + self.entries.map((e) => (e.key, e.value)).toList(), serializer); + } + @protected void sse_encode_String(String self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs @@ -343,6 +510,16 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { serializer.buffer.putUint8List(self); } + @protected + void sse_encode_list_record_string_string( + List<(String, String)> self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + for (final item in self) { + sse_encode_record_string_string(item, serializer); + } + } + @protected void sse_encode_my_downloader_status( MyDownloaderStatus self, SseSerializer serializer) { @@ -370,6 +547,35 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_i_32(self.index, serializer); } + @protected + void sse_encode_opt_Map_String_String( + Map? self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + sse_encode_bool(self != null, serializer); + if (self != null) { + sse_encode_Map_String_String(self, serializer); + } + } + + @protected + void sse_encode_opt_String(String? self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + sse_encode_bool(self != null, serializer); + if (self != null) { + sse_encode_String(self, serializer); + } + } + + @protected + void sse_encode_record_string_string( + (String, String) self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_String(self.$1, serializer); + sse_encode_String(self.$2, serializer); + } + @protected void sse_encode_u_64(int self, SseSerializer serializer) { // Codec=Sse (Serialization based), see doc to use other codecs diff --git a/lib/common/rust/frb_generated.io.dart b/lib/common/rust/frb_generated.io.dart index 6b9a97c..c220334 100644 --- a/lib/common/rust/frb_generated.io.dart +++ b/lib/common/rust/frb_generated.io.dart @@ -4,6 +4,7 @@ // ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field import 'api/downloader_api.dart'; +import 'api/http_api.dart'; import 'dart:async'; import 'dart:convert'; import 'dart:ffi' as ffi; @@ -19,6 +20,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { required super.portManager, }); + @protected + Map dco_decode_Map_String_String(dynamic raw); + @protected String dco_decode_String(dynamic raw); @@ -31,12 +35,24 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected Uint8List dco_decode_list_prim_u_8_strict(dynamic raw); + @protected + List<(String, String)> dco_decode_list_record_string_string(dynamic raw); + @protected MyDownloaderStatus dco_decode_my_downloader_status(dynamic raw); @protected MyNetworkItemPendingType dco_decode_my_network_item_pending_type(dynamic raw); + @protected + Map? dco_decode_opt_Map_String_String(dynamic raw); + + @protected + String? dco_decode_opt_String(dynamic raw); + + @protected + (String, String) dco_decode_record_string_string(dynamic raw); + @protected int dco_decode_u_64(dynamic raw); @@ -46,6 +62,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void dco_decode_unit(dynamic raw); + @protected + Map sse_decode_Map_String_String( + SseDeserializer deserializer); + @protected String sse_decode_String(SseDeserializer deserializer); @@ -59,6 +79,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected Uint8List sse_decode_list_prim_u_8_strict(SseDeserializer deserializer); + @protected + List<(String, String)> sse_decode_list_record_string_string( + SseDeserializer deserializer); + @protected MyDownloaderStatus sse_decode_my_downloader_status( SseDeserializer deserializer); @@ -67,6 +91,17 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { MyNetworkItemPendingType sse_decode_my_network_item_pending_type( SseDeserializer deserializer); + @protected + Map? sse_decode_opt_Map_String_String( + SseDeserializer deserializer); + + @protected + String? sse_decode_opt_String(SseDeserializer deserializer); + + @protected + (String, String) sse_decode_record_string_string( + SseDeserializer deserializer); + @protected int sse_decode_u_64(SseDeserializer deserializer); @@ -79,6 +114,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected bool sse_decode_bool(SseDeserializer deserializer); + @protected + void sse_encode_Map_String_String( + Map self, SseSerializer serializer); + @protected void sse_encode_String(String self, SseSerializer serializer); @@ -93,6 +132,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_list_prim_u_8_strict( Uint8List self, SseSerializer serializer); + @protected + void sse_encode_list_record_string_string( + List<(String, String)> self, SseSerializer serializer); + @protected void sse_encode_my_downloader_status( MyDownloaderStatus self, SseSerializer serializer); @@ -101,6 +144,17 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_my_network_item_pending_type( MyNetworkItemPendingType self, SseSerializer serializer); + @protected + void sse_encode_opt_Map_String_String( + Map? self, SseSerializer serializer); + + @protected + void sse_encode_opt_String(String? self, SseSerializer serializer); + + @protected + void sse_encode_record_string_string( + (String, String) self, SseSerializer serializer); + @protected void sse_encode_u_64(int self, SseSerializer serializer); diff --git a/lib/common/rust/frb_generated.web.dart b/lib/common/rust/frb_generated.web.dart index 04cc46e..9f78068 100644 --- a/lib/common/rust/frb_generated.web.dart +++ b/lib/common/rust/frb_generated.web.dart @@ -4,6 +4,7 @@ // ignore_for_file: unused_import, unused_element, unnecessary_import, duplicate_ignore, invalid_use_of_internal_member, annotate_overrides, non_constant_identifier_names, curly_braces_in_flow_control_structures, prefer_const_literals_to_create_immutables, unused_field import 'api/downloader_api.dart'; +import 'api/http_api.dart'; import 'dart:async'; import 'dart:convert'; import 'downloader.dart'; @@ -18,6 +19,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { required super.portManager, }); + @protected + Map dco_decode_Map_String_String(dynamic raw); + @protected String dco_decode_String(dynamic raw); @@ -30,12 +34,24 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected Uint8List dco_decode_list_prim_u_8_strict(dynamic raw); + @protected + List<(String, String)> dco_decode_list_record_string_string(dynamic raw); + @protected MyDownloaderStatus dco_decode_my_downloader_status(dynamic raw); @protected MyNetworkItemPendingType dco_decode_my_network_item_pending_type(dynamic raw); + @protected + Map? dco_decode_opt_Map_String_String(dynamic raw); + + @protected + String? dco_decode_opt_String(dynamic raw); + + @protected + (String, String) dco_decode_record_string_string(dynamic raw); + @protected int dco_decode_u_64(dynamic raw); @@ -45,6 +61,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected void dco_decode_unit(dynamic raw); + @protected + Map sse_decode_Map_String_String( + SseDeserializer deserializer); + @protected String sse_decode_String(SseDeserializer deserializer); @@ -58,6 +78,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected Uint8List sse_decode_list_prim_u_8_strict(SseDeserializer deserializer); + @protected + List<(String, String)> sse_decode_list_record_string_string( + SseDeserializer deserializer); + @protected MyDownloaderStatus sse_decode_my_downloader_status( SseDeserializer deserializer); @@ -66,6 +90,17 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { MyNetworkItemPendingType sse_decode_my_network_item_pending_type( SseDeserializer deserializer); + @protected + Map? sse_decode_opt_Map_String_String( + SseDeserializer deserializer); + + @protected + String? sse_decode_opt_String(SseDeserializer deserializer); + + @protected + (String, String) sse_decode_record_string_string( + SseDeserializer deserializer); + @protected int sse_decode_u_64(SseDeserializer deserializer); @@ -78,6 +113,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { @protected bool sse_decode_bool(SseDeserializer deserializer); + @protected + void sse_encode_Map_String_String( + Map self, SseSerializer serializer); + @protected void sse_encode_String(String self, SseSerializer serializer); @@ -92,6 +131,10 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_list_prim_u_8_strict( Uint8List self, SseSerializer serializer); + @protected + void sse_encode_list_record_string_string( + List<(String, String)> self, SseSerializer serializer); + @protected void sse_encode_my_downloader_status( MyDownloaderStatus self, SseSerializer serializer); @@ -100,6 +143,17 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { void sse_encode_my_network_item_pending_type( MyNetworkItemPendingType self, SseSerializer serializer); + @protected + void sse_encode_opt_Map_String_String( + Map? self, SseSerializer serializer); + + @protected + void sse_encode_opt_String(String? self, SseSerializer serializer); + + @protected + void sse_encode_record_string_string( + (String, String) self, SseSerializer serializer); + @protected void sse_encode_u_64(int self, SseSerializer serializer); diff --git a/lib/ui/home/home_ui_model.dart b/lib/ui/home/home_ui_model.dart index c927d60..9647369 100644 --- a/lib/ui/home/home_ui_model.dart +++ b/lib/ui/home/home_ui_model.dart @@ -4,7 +4,7 @@ import 'dart:io'; import 'package:dart_rss/dart_rss.dart'; import 'package:desktop_webview_window/desktop_webview_window.dart'; -import 'package:dio/dio.dart'; +import 'package:starcitizen_doctor/common/rust/api/http_api.dart' as rust_http; import 'package:hive/hive.dart'; import 'package:starcitizen_doctor/api/analytics.dart'; import 'package:starcitizen_doctor/api/api.dart'; @@ -107,10 +107,8 @@ class HomeUIModel extends BaseUIModel { updateSCServerStatus(); notifyListeners(); appWebLocalizationVersionsData = AppWebLocalizationVersionsData.fromJson( - json.decode((await Api.dio.get( - "${URLConf.webTranslateHomeUrl}/versions.json", - options: Options(responseType: ResponseType.plain))) - .data)); + json.decode((await rust_http.getString( + url: "${URLConf.webTranslateHomeUrl}/versions.json")))); countdownFestivalListData = await Api.getFestivalCountdownList(); notifyListeners(); _loadRRS(); diff --git a/lib/ui/home/webview/webview.dart b/lib/ui/home/webview/webview.dart index d07af8a..22dc4da 100644 --- a/lib/ui/home/webview/webview.dart +++ b/lib/ui/home/webview/webview.dart @@ -5,7 +5,6 @@ import 'dart:convert'; import 'package:cryptography/cryptography.dart'; import 'package:desktop_webview_window/desktop_webview_window.dart'; -import 'package:dio/dio.dart'; import 'package:flutter/services.dart'; import 'package:hive/hive.dart'; import 'package:local_auth/local_auth.dart'; @@ -13,8 +12,8 @@ import 'package:starcitizen_doctor/common/conf/app_conf.dart'; import 'package:starcitizen_doctor/common/conf/url_conf.dart'; import 'package:starcitizen_doctor/common/win32/credentials.dart'; import 'package:starcitizen_doctor/data/app_web_localization_versions_data.dart'; +import 'package:starcitizen_doctor/common/rust/api/http_api.dart' as rust_http; -import '../../../api/api.dart'; import '../../../base/ui.dart'; typedef RsiLoginCallback = void Function(Map? data, bool success); @@ -257,10 +256,9 @@ class WebViewModel { } } final startTime = DateTime.now(); - final r = await Api.dio - .get(url, options: Options(responseType: ResponseType.plain)); + final r = await rust_http.getString(url: url); final endTime = DateTime.now(); - final data = json.decode(r.data); + final data = json.decode(r); if (cacheKey.isNotEmpty) { dPrint( "update $cacheKey v == $version time == ${(endTime.microsecondsSinceEpoch - startTime.microsecondsSinceEpoch) / 1000 / 1000}s"); diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 454a0d7..bd66a3c 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -9,7 +9,10 @@ crate-type = ["cdylib", "staticlib"] [dependencies] flutter_rust_bridge = "=2.0.0-dev.23" http-downloader = { version = "0.3.2", features = ["status-tracker", "speed-tracker", "breakpoint-resume", "bson-file-archiver"] } -tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] } +tokio = { version = "1", features = ["full"] } url = "2.5.0" uuid = { version = "1.7.0", features = ["v4", "fast-rng", "macro-diagnostics"] } async-std = "1.12.0" +once_cell = "1.19.0" +reqwest = { version = "0.11", features = ["rustls-tls-native-roots", "cookies", "gzip", "brotli", "deflate", "multipart", "trust-dns", "json"] } +serde_json = { version = "1.0.1", features = [] } \ No newline at end of file diff --git a/rust/src/api/http.rs b/rust/src/api/http.rs deleted file mode 100644 index e69de29..0000000 diff --git a/rust/src/api/http_api.rs b/rust/src/api/http_api.rs new file mode 100644 index 0000000..fecfbab --- /dev/null +++ b/rust/src/api/http_api.rs @@ -0,0 +1,40 @@ +use std::collections::HashMap; +use std::time::Duration; +use once_cell::sync::Lazy; +use reqwest; +use reqwest::header::{HeaderMap, HeaderValue}; +use reqwest::RequestBuilder; + +static HTTP_CLIENT: Lazy = Lazy::new(|| { + let mut header_map = HeaderMap::new(); + header_map.insert("User-Agent", HeaderValue::from_static("SCToolBox/2.10.x lib_rust_http")); + reqwest::Client::builder() + .use_rustls_tls() + .connect_timeout(Duration::from_secs(10)) + .timeout(Duration::from_secs(10)) + .default_headers(header_map).build().unwrap() +}); + + +#[tokio::main] +pub async fn get_string(url: String, headers: Option>) -> String { + let mut req = _append_header(HTTP_CLIENT.get(url), headers); + req.send().await.unwrap().text().await.unwrap() +} + +pub async fn post_json_string(url: String, headers: Option>, json_data: Option) -> String { + let mut req = _append_header(HTTP_CLIENT.post(url), headers); + if json_data.is_some() { + req = req.body(json_data.unwrap()).header(reqwest::header::CONTENT_TYPE, "application/json"); + } + req.send().await.unwrap().text().await.unwrap() +} + +fn _append_header(mut req: RequestBuilder, headers: Option>) -> RequestBuilder { + if headers.is_some() { + for x in headers.unwrap() { + req = req.header(x.0, x.1); + } + } + req +} \ No newline at end of file diff --git a/rust/src/api/mod.rs b/rust/src/api/mod.rs index 6e27e2a..279e7fb 100644 --- a/rust/src/api/mod.rs +++ b/rust/src/api/mod.rs @@ -3,4 +3,4 @@ // pub mod downloader_api; -mod http; +pub mod http_api; diff --git a/rust/src/frb_generated.rs b/rust/src/frb_generated.rs index 0a5da19..d1e90ae 100644 --- a/rust/src/frb_generated.rs +++ b/rust/src/frb_generated.rs @@ -120,9 +120,96 @@ fn wire_start_download_impl( }, ) } +fn wire_get_string_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_normal::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "get_string", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_url = ::sse_decode(&mut deserializer); + let api_headers = + >>::sse_decode(&mut deserializer); + deserializer.end(); + move |context| { + transform_result_sse((move || { + Result::<_, ()>::Ok(crate::api::http_api::get_string(api_url, api_headers)) + })()) + } + }, + ) +} +fn wire_post_json_string_impl( + port_: flutter_rust_bridge::for_generated::MessagePort, + ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr, + rust_vec_len_: i32, + data_len_: i32, +) { + FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::( + flutter_rust_bridge::for_generated::TaskInfo { + debug_name: "post_json_string", + port: Some(port_), + mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal, + }, + move || { + let message = unsafe { + flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire( + ptr_, + rust_vec_len_, + data_len_, + ) + }; + let mut deserializer = + flutter_rust_bridge::for_generated::SseDeserializer::new(message); + let api_url = ::sse_decode(&mut deserializer); + let api_headers = + >>::sse_decode(&mut deserializer); + let api_json_data = >::sse_decode(&mut deserializer); + deserializer.end(); + move |context| async move { + transform_result_sse( + (move || async move { + Result::<_, ()>::Ok( + crate::api::http_api::post_json_string( + api_url, + api_headers, + api_json_data, + ) + .await, + ) + })() + .await, + ) + } + }, + ) +} // Section: dart2rust +impl SseDecode for std::collections::HashMap { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut inner = >::sse_decode(deserializer); + return inner.into_iter().collect(); + } +} + impl SseDecode for String { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -168,6 +255,18 @@ impl SseDecode for Vec { } } +impl SseDecode for Vec<(String, String)> { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut len_ = ::sse_decode(deserializer); + let mut ans_ = vec![]; + for idx_ in 0..len_ { + ans_.push(<(String, String)>::sse_decode(deserializer)); + } + return ans_; + } +} + impl SseDecode for crate::downloader::MyDownloaderStatus { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -212,6 +311,39 @@ impl SseDecode for crate::downloader::MyNetworkItemPendingType { } } +impl SseDecode for Option> { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + if (::sse_decode(deserializer)) { + return Some(>::sse_decode( + deserializer, + )); + } else { + return None; + } + } +} + +impl SseDecode for Option { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + if (::sse_decode(deserializer)) { + return Some(::sse_decode(deserializer)); + } else { + return None; + } + } +} + +impl SseDecode for (String, String) { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut var_field0 = ::sse_decode(deserializer); + let mut var_field1 = ::sse_decode(deserializer); + return (var_field0, var_field1); + } +} + impl SseDecode for u64 { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -249,6 +381,8 @@ fn pde_ffi_dispatcher_primary_impl( match func_id { 2 => wire_cancel_download_impl(port, ptr, rust_vec_len, data_len), 1 => wire_start_download_impl(port, ptr, rust_vec_len, data_len), + 3 => wire_get_string_impl(port, ptr, rust_vec_len, data_len), + 4 => wire_post_json_string_impl(port, ptr, rust_vec_len, data_len), _ => unreachable!(), } } @@ -341,6 +475,13 @@ impl flutter_rust_bridge::IntoIntoDart { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + >::sse_encode(self.into_iter().collect(), serializer); + } +} + impl SseEncode for String { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -376,6 +517,16 @@ impl SseEncode for Vec { } } +impl SseEncode for Vec<(String, String)> { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.len() as _, serializer); + for item in self { + <(String, String)>::sse_encode(item, serializer); + } + } +} + impl SseEncode for crate::downloader::MyDownloaderStatus { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { @@ -419,6 +570,34 @@ impl SseEncode for crate::downloader::MyNetworkItemPendingType { } } +impl SseEncode for Option> { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.is_some(), serializer); + if let Some(value) = self { + >::sse_encode(value, serializer); + } + } +} + +impl SseEncode for Option { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.is_some(), serializer); + if let Some(value) = self { + ::sse_encode(value, serializer); + } + } +} + +impl SseEncode for (String, String) { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.0, serializer); + ::sse_encode(self.1, serializer); + } +} + impl SseEncode for u64 { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {