diff --git a/lib/models/course_table.dart b/lib/models/course_table.dart index e2e4807..f41f326 100644 --- a/lib/models/course_table.dart +++ b/lib/models/course_table.dart @@ -201,6 +201,20 @@ class SemesterInfo { return null; } + SemesterTerm? findSemesterTerm(String semesterId) { + for (final yearEntry in semesters.entries) { + for (final semEntry in yearEntry.value.entries) { + if (semEntry.value != semesterId) continue; + + final year = yearEntry.key.split('-').first; + final semester = _semesterNumberForTermName(semEntry.key); + if (semester == null) return null; + return SemesterTerm(year: year, semester: semester); + } + } + return null; + } + List> get allSemesters { final result = >[]; for (final yearEntry in semesters.entries) { @@ -212,6 +226,45 @@ class SemesterInfo { } return result; } + + static String? _semesterNumberForTermName(String termName) { + final normalized = termName.trim().toLowerCase(); + if (normalized.isEmpty) return null; + + if (normalized == '1' || + normalized.contains('春') || + normalized.contains('下') || + normalized.contains('第二') || + normalized.contains('spring')) { + return '1'; + } + + if (normalized == '2' || + normalized.contains('秋') || + normalized.contains('上') || + normalized.contains('第一') || + normalized.contains('fall') || + normalized.contains('autumn')) { + return '2'; + } + + if (normalized == '3' || + normalized.contains('夏') || + normalized.contains('暑') || + normalized.contains('第三') || + normalized.contains('summer')) { + return '3'; + } + + return null; + } +} + +class SemesterTerm { + final String year; + final String semester; + + const SemesterTerm({required this.year, required this.semester}); } /// Convert EamsCourse list to display Course list, grouping consecutive periods. diff --git a/lib/pages/schedule_page.dart b/lib/pages/schedule_page.dart index 9ce0465..e87830e 100644 --- a/lib/pages/schedule_page.dart +++ b/lib/pages/schedule_page.dart @@ -36,6 +36,7 @@ class _SchedulePageState extends State { int _currentWeek = 1; bool _initialized = false; bool _exportingCalendar = false; + bool _subscribingCalendar = false; // Settings bool _showSaturday = true; @@ -350,6 +351,197 @@ class _SchedulePageState extends State { unawaited(_exportCalendar()); } + void _startSubscribeCalendar() { + if (_subscribingCalendar) return; + unawaited(_confirmAndSubscribeCalendar()); + } + + Future _confirmAndSubscribeCalendar() async { + final confirmed = await showDialog( + context: context, + builder: (dialogContext) { + var credentialStorageAgreed = false; + + return StatefulBuilder( + builder: (context, setDialogState) { + return AlertDialog( + title: const Text('创建日历订阅'), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const Text('如果你之前已经订阅过该学期,之前的订阅链接将会失效。'), + const SizedBox(height: 8), + CheckboxListTile( + value: credentialStorageAgreed, + onChanged: (value) { + setDialogState(() { + credentialStorageAgreed = value ?? false; + }); + }, + title: Text( + '您理解并同意:订阅日历时,您的登录凭据将会被加密存储到服务器内,并用于课表订阅服务', + style: Theme.of(context).textTheme.bodySmall, + ), + controlAffinity: ListTileControlAffinity.leading, + contentPadding: EdgeInsets.zero, + ), + ], + ), + actions: [ + TextButton( + onPressed: () => Navigator.of(dialogContext).pop(false), + child: const Text('取消'), + ), + FilledButton( + onPressed: credentialStorageAgreed + ? () => Navigator.of(dialogContext).pop(true) + : null, + child: const Text('确定'), + ), + ], + ); + }, + ); + }, + ); + + if (confirmed != true || !mounted) return; + await _subscribeCalendar(); + } + + Future _subscribeCalendar() async { + if (_subscribingCalendar) return; + + setState(() { + _subscribingCalendar = true; + }); + + try { + final semesterId = _schedule.selectedSemesterId; + if (semesterId == null || semesterId.isEmpty) { + throw Exception('Missing semesterId'); + } + final auth = ServiceProvider.of(context).authService; + final result = await auth.createCalendarSubscription( + semesterId: semesterId, + ); + + final data = result['data'] as Map?; + final subscribeUrl = data?['subscribeUrl'] as String?; + if (!mounted) return; + if (subscribeUrl?.isNotEmpty == true) { + if (isIos() && await _openIosCalendarSubscription(subscribeUrl!)) { + if (!mounted) return; + showAdaptiveFeedback( + context: context, + message: '已打开系统日历订阅', + style: AdaptiveFeedbackStyle.success, + ); + return; + } + await _copyCalendarSubscriptionUrl(subscribeUrl!); + return; + } + + showAdaptiveFeedback( + context: context, + message: '日历订阅已创建', + style: AdaptiveFeedbackStyle.success, + ); + } catch (_) { + if (!mounted) return; + showAdaptiveFeedback( + context: context, + message: '创建日历订阅失败', + style: AdaptiveFeedbackStyle.error, + ); + } finally { + if (mounted) { + setState(() { + _subscribingCalendar = false; + }); + } + } + } + + Future _openIosCalendarSubscription(String subscribeUrl) async { + final uri = Uri.tryParse(subscribeUrl); + if (uri == null) return false; + + final calendarUri = uri.scheme == 'https' || uri.scheme == 'http' + ? uri.replace(scheme: 'webcal') + : uri; + + try { + return launchUrl(calendarUri, mode: LaunchMode.externalApplication); + } catch (_) { + return false; + } + } + + Future _copyCalendarSubscriptionUrl(String subscribeUrl) async { + try { + await Clipboard.setData(ClipboardData(text: subscribeUrl)); + if (!mounted) return; + showAdaptiveFeedback( + context: context, + message: '日历订阅链接已复制到剪贴板', + style: AdaptiveFeedbackStyle.success, + ); + } catch (_) { + if (!mounted) return; + showAdaptiveFeedback( + context: context, + message: '无法自动复制,请手动复制订阅链接', + style: AdaptiveFeedbackStyle.info, + ); + await _showManualCalendarSubscriptionCopy(subscribeUrl); + } + } + + Future _showManualCalendarSubscriptionCopy(String subscribeUrl) async { + final controller = TextEditingController(text: subscribeUrl); + final focusNode = FocusNode(); + try { + await showDialog( + context: context, + builder: (dialogContext) { + return AlertDialog( + title: const Text('手动复制订阅链接'), + content: TextField( + controller: controller, + focusNode: focusNode, + readOnly: true, + autofocus: false, + showCursor: false, + keyboardType: TextInputType.none, + enableInteractiveSelection: true, + maxLines: 3, + minLines: 1, + decoration: const InputDecoration( + labelText: '订阅链接', + border: OutlineInputBorder(), + ), + onTap: () { + unawaited(_dismissKeyboard()); + }, + ), + actions: [ + FilledButton( + onPressed: () => Navigator.of(dialogContext).pop(), + child: const Text('完成'), + ), + ], + ); + }, + ); + } finally { + focusNode.dispose(); + controller.dispose(); + } + } + Future _saveCalendarFile( IcsSaveLocation location, { required String calendarName, @@ -601,6 +793,13 @@ class _SchedulePageState extends State { ? 'arrow.triangle.2.circlepath' : 'square.and.arrow.up', ), + IosNativeNavigationBarMenuItem( + value: 'subscribeCalendar', + title: _subscribingCalendar ? '正在创建订阅…' : '订阅日历', + sfSymbol: _subscribingCalendar + ? 'arrow.triangle.2.circlepath' + : 'calendar.badge.plus', + ), ], ), ], @@ -665,17 +864,6 @@ class _SchedulePageState extends State { tooltip: 'Next week', onPressed: _nextWeek, ), - IconButton( - tooltip: _exportingCalendar ? '正在导出课表' : '导出课表', - onPressed: _exportingCalendar ? null : _startExportCalendar, - icon: _exportingCalendar - ? const SizedBox( - width: 20, - height: 20, - child: CircularProgressIndicator(strokeWidth: 2), - ) - : const Icon(Icons.ios_share_rounded), - ), if (isDesktopLayout(context)) IconButton( key: _viewSettingsAnchorKey, @@ -708,6 +896,19 @@ class _SchedulePageState extends State { checked: _showGhostCourses, child: const Text('显示非本周课程'), ), + const PopupMenuDivider(), + PopupMenuItem( + value: 'exportCalendar', + enabled: !_exportingCalendar, + child: Text(_exportingCalendar ? '正在导出…' : '导出课表'), + ), + PopupMenuItem( + value: 'subscribeCalendar', + enabled: !_subscribingCalendar, + child: Text( + _subscribingCalendar ? '正在创建订阅…' : '订阅日历', + ), + ), ], ), ], @@ -884,6 +1085,8 @@ class _SchedulePageState extends State { }); case 'exportCalendar': _startExportCalendar(); + case 'subscribeCalendar': + _startSubscribeCalendar(); } } @@ -969,6 +1172,22 @@ class _SchedulePageState extends State { _startExportCalendar(); }, ), + DesktopMenuRow( + leading: _subscribingCalendar + ? const SizedBox( + width: 18, + height: 18, + child: CircularProgressIndicator(strokeWidth: 2), + ) + : const Icon(Icons.calendar_month_outlined, size: 20), + title: Text('订阅日历', style: theme.textTheme.bodyMedium), + onTap: _subscribingCalendar + ? null + : () { + close(); + _startSubscribeCalendar(); + }, + ), ], ); }, diff --git a/lib/services/auth_service.dart b/lib/services/auth_service.dart index 4418013..3c85e17 100644 --- a/lib/services/auth_service.dart +++ b/lib/services/auth_service.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'package:flutter/foundation.dart'; +import 'package:http/http.dart' as http; import '../models/user_session.dart'; import 'api_base_url.dart'; @@ -81,6 +82,53 @@ class AuthService extends ChangeNotifier { } } + Future> createCalendarSubscription({ + required String semesterId, + }) async { + final session = _session; + if (session == null) { + throw Exception('Not logged in'); + } + if (semesterId.isEmpty) { + throw Exception('Missing semesterId'); + } + + Future postCreate() { + final currentSession = _session!; + return _http.post( + Uri.parse('$_baseUrl/calendar/create'), + headers: _jsonHeaders(), + body: jsonEncode({ + 'studentId': currentSession.studentId.isNotEmpty + ? currentSession.studentId + : currentSession.userId, + 'semesterId': semesterId, + 'tgc': currentSession.tgc, + 'sessionToken': currentSession.sessionToken, + 'tenantId': currentSession.tenantId, + 'userId': currentSession.userId, + 'cookies': currentSession.cookies, + }), + tag: 'createCalendarSubscription', + ); + } + + var resp = await postCreate(); + if (resp.statusCode == 401 && await tryRenewSession()) { + resp = await postCreate(); + } + + final data = jsonDecode(resp.body) as Map; + if (resp.statusCode != 200 || data['success'] != true) { + throw Exception( + data['error'] as String? ?? + 'Request failed with status ${resp.statusCode}', + ); + } + + return data; + } + // -- SMS Login Flow -- Future sendSmsCode(String phone) async { diff --git a/lib/services/schedule_service.dart b/lib/services/schedule_service.dart index 8219edf..4f20acd 100644 --- a/lib/services/schedule_service.dart +++ b/lib/services/schedule_service.dart @@ -36,7 +36,9 @@ class ScheduleService extends ChangeNotifier { if (_termBegin == null) return 1; final diff = DateTime.now().difference(_termBegin!).inDays; if (diff < 0) return 1; - return ((diff ~/ 7) + 1).clamp(1, 25).toInt(); + final week = (diff ~/ 7) + 1; + if (week > 25) return 1; + return week; } Map _jsonHeaders() => { @@ -132,26 +134,11 @@ class ScheduleService extends ChangeNotifier { } Future _fetchTermBeginForSemester(String semesterId) async { - // Try to find the year and semester number from semesterInfo if (_semesterInfo == null) return; - String? year; - String? semNum; - for (final yearEntry in _semesterInfo!.semesters.entries) { - for (final semEntry in yearEntry.value.entries) { - if (semEntry.value == semesterId) { - // yearEntry.key is like "2024-2025" - year = yearEntry.key.split('-').first; - // Map label to number - semNum = semEntry.key.contains('春') ? '1' : '2'; - break; - } - } - if (year != null) break; - } - - if (year == null || semNum == null) return; - await fetchTermBegin(year, semNum, semesterId); + final term = _semesterInfo!.findSemesterTerm(semesterId); + if (term == null) return; + await fetchTermBegin(term.year, term.semester, semesterId); } Future fetchTermBegin( diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 41f528c..10f08c9 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -11,6 +11,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST + jni ) set(PLUGIN_BUNDLED_LIBRARIES) diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 931d63d..401e761 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -8,7 +8,6 @@ import Foundation import dynamic_color import flutter_secure_storage_macos import package_info_plus -import path_provider_foundation import shared_preferences_foundation import url_launcher_macos import webview_flutter_wkwebview @@ -17,7 +16,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin")) FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) - PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) WebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "WebViewFlutterPlugin")) diff --git a/pubspec.lock b/pubspec.lock index c6b48fa..9207b84 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,16 +5,16 @@ packages: dependency: "direct main" description: name: animations - sha256: d3d6dcfb218225bbe68e87ccf6378bbb2e32a94900722c5f81611dad089911cb - url: "https://pub.flutter-io.cn" + sha256: "9cb469212ea51be27097f23b519d594c01171721347b55df9334fff653659e7f" + url: "https://pub.dev" source: hosted - version: "2.0.11" + version: "2.2.0" archive: dependency: transitive description: name: archive sha256: a96e8b390886ee8abb49b7bd3ac8df6f451c621619f52a26e815fdcf568959ff - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.0.9" args: @@ -22,103 +22,119 @@ packages: description: name: args sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.7.0" async: dependency: transitive description: name: async - sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" - url: "https://pub.flutter-io.cn" + sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37 + url: "https://pub.dev" source: hosted - version: "2.11.0" + version: "2.13.1" boolean_selector: dependency: transitive description: name: boolean_selector - sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" - url: "https://pub.flutter-io.cn" + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" + url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" characters: dependency: transitive description: name: characters - sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" - url: "https://pub.flutter-io.cn" + sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b + url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.1" checked_yaml: dependency: transitive description: name: checked_yaml - sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff - url: "https://pub.flutter-io.cn" + sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f" + url: "https://pub.dev" source: hosted - version: "2.0.3" + version: "2.0.4" cli_util: dependency: transitive description: name: cli_util sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.4.2" clock: dependency: transitive description: name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf - url: "https://pub.flutter-io.cn" + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b + url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" + code_assets: + dependency: transitive + description: + name: code_assets + sha256: bf394f466ba9205f1812a0433b392d6af280f155f56651eda7c18cc32ed493b8 + url: "https://pub.dev" + source: hosted + version: "1.2.1" collection: dependency: transitive description: name: collection - sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf - url: "https://pub.flutter-io.cn" + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" + url: "https://pub.dev" + source: hosted + version: "1.19.1" + crypto: + dependency: transitive + description: + name: crypto + sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf + url: "https://pub.dev" source: hosted - version: "1.19.0" + version: "3.0.7" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 - url: "https://pub.flutter-io.cn" + sha256: "41e005c33bd814be4d3096aff55b1908d419fde52ca656c8c47719ec745873cd" + url: "https://pub.dev" source: hosted - version: "1.0.8" + version: "1.0.9" dynamic_color: dependency: "direct main" description: name: dynamic_color sha256: eae98052fa6e2826bdac3dd2e921c6ce2903be15c6b7f8b6d8a5d49b5086298d - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.7.0" fake_async: dependency: transitive description: name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" - url: "https://pub.flutter-io.cn" + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" + url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.3" ffi: dependency: transitive description: name: ffi - sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" - url: "https://pub.flutter-io.cn" + sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45" + url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.2.0" file: dependency: transitive description: name: file sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "7.0.1" flutter: @@ -131,7 +147,7 @@ packages: description: name: flutter_launcher_icons sha256: "10f13781741a2e3972126fae08393d3c4e01fa4cd7473326b94b72cf594195e7" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.14.4" flutter_lints: @@ -139,7 +155,7 @@ packages: description: name: flutter_lints sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "5.0.0" flutter_secure_storage: @@ -147,7 +163,7 @@ packages: description: name: flutter_secure_storage sha256: "9cad52d75ebc511adfae3d447d5d13da15a55a92c9410e50f67335b6d21d16ea" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "9.2.4" flutter_secure_storage_linux: @@ -155,7 +171,7 @@ packages: description: name: flutter_secure_storage_linux sha256: be76c1d24a97d0b98f8b54bce6b481a380a6590df992d0098f868ad54dc8f688 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.2.3" flutter_secure_storage_macos: @@ -163,7 +179,7 @@ packages: description: name: flutter_secure_storage_macos sha256: "6c0a2795a2d1de26ae202a0d78527d163f4acbb11cde4c75c670f3a0fc064247" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.1.3" flutter_secure_storage_ohos: @@ -180,7 +196,7 @@ packages: description: name: flutter_secure_storage_platform_interface sha256: cf91ad32ce5adef6fba4d736a542baca9daf3beac4db2d04be350b87f69ac4a8 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.2" flutter_secure_storage_web: @@ -188,7 +204,7 @@ packages: description: name: flutter_secure_storage_web sha256: f4ebff989b4f07b2656fb16b47852c0aab9fed9b4ec1c70103368337bc1886a9 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.2.1" flutter_secure_storage_windows: @@ -196,7 +212,7 @@ packages: description: name: flutter_secure_storage_windows sha256: b20b07cb5ed4ed74fc567b78a72936203f587eba460af1df11281c9326cd3709 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.1.2" flutter_test: @@ -214,15 +230,23 @@ packages: description: name: fullscreen_window sha256: "262a19366157542c3e1fa07232ee7e8a5c82e5223d912b04a2771c47aa6a048d" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.2.1" + hooks: + dependency: transitive + description: + name: hooks + sha256: "9a62a50b50b769a737bc0a8ff381f333529df3ab746b2f6b02e83760231455ba" + url: "https://pub.dev" + source: hosted + version: "2.0.2" http: dependency: "direct main" description: name: http sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.6.0" http_parser: @@ -230,105 +254,145 @@ packages: description: name: http_parser sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.1.2" image: dependency: transitive description: name: image - sha256: f9881ff4998044947ec38d098bc7c8316ae1186fa786eddffdb867b9bc94dfce - url: "https://pub.flutter-io.cn" + sha256: "6300175e00616bbc832e2fc91bfa4d776af5402c81c7151bee6905bb08473c52" + url: "https://pub.dev" source: hosted - version: "4.8.0" + version: "4.9.1" intl: dependency: "direct main" description: name: intl sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.20.2" + jni: + dependency: transitive + description: + name: jni + sha256: c2230682d5bc2362c1c9e8d3c7f406d9cbba23ab3f2e203a025dd47e0fb2e68f + url: "https://pub.dev" + source: hosted + version: "1.0.0" + jni_flutter: + dependency: transitive + description: + name: jni_flutter + sha256: "8b59e590786050b1cd866677dddaf76b1ade5e7bc751abe04b86e84d379d3ba6" + url: "https://pub.dev" + source: hosted + version: "1.0.1" js: dependency: transitive description: name: js sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "0.6.7" json_annotation: dependency: transitive description: name: json_annotation - sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" - url: "https://pub.flutter-io.cn" + sha256: "2a743920d81b7910627f68ee2c9ac1fc0bfee32b9fc3403587d7c6791ca12f80" + url: "https://pub.dev" source: hosted - version: "4.9.0" + version: "4.12.0" leak_tracker: dependency: transitive description: name: leak_tracker - sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" - url: "https://pub.flutter-io.cn" + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" + url: "https://pub.dev" source: hosted - version: "10.0.7" + version: "11.0.2" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" - url: "https://pub.flutter-io.cn" + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" + url: "https://pub.dev" source: hosted - version: "3.0.8" + version: "3.0.10" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" - url: "https://pub.flutter-io.cn" + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" + url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" lints: dependency: transitive description: name: lints sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "5.1.1" + logging: + dependency: transitive + description: + name: logging + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 + url: "https://pub.dev" + source: hosted + version: "1.3.0" matcher: dependency: transitive description: name: matcher - sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb - url: "https://pub.flutter-io.cn" + sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 + url: "https://pub.dev" source: hosted - version: "0.12.16+1" + version: "0.12.19" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec - url: "https://pub.flutter-io.cn" + sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" + url: "https://pub.dev" source: hosted - version: "0.11.1" + version: "0.13.0" meta: dependency: transitive description: name: meta - sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 - url: "https://pub.flutter-io.cn" + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" + url: "https://pub.dev" + source: hosted + version: "1.17.0" + objective_c: + dependency: transitive + description: + name: objective_c + sha256: "6cb691c686fa2838c6deb34980d426145c2a5d537491cb83d463c33cdbc726ed" + url: "https://pub.dev" source: hosted - version: "1.15.0" + version: "9.4.1" open_filex: dependency: "direct main" description: name: open_filex sha256: "9976da61b6a72302cf3b1efbce259200cd40232643a467aac7370addf94d6900" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "4.7.0" + package_config: + dependency: transitive + description: + name: package_config + sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc + url: "https://pub.dev" + source: hosted + version: "2.2.0" package_info_plus: dependency: "direct main" description: @@ -343,47 +407,47 @@ packages: description: name: package_info_plus_platform_interface sha256: "9bc8ba46813a4cc42c66ab781470711781940780fd8beddd0c3da62506d3a6c6" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.0.1" path: dependency: transitive description: name: path - sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" - url: "https://pub.flutter-io.cn" + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" + url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.9.1" path_provider: dependency: "direct main" description: name: path_provider sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.5" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: d0d310befe2c8ab9e7f393288ccbb11b60c019c6b5afc21973eeee4dda2b35e9 - url: "https://pub.flutter-io.cn" + sha256: "69cbd515a62b94d32a7944f086b2f82b4ac40a1d45bebfc00813a430ab2dabcd" + url: "https://pub.dev" source: hosted - version: "2.2.17" + version: "2.3.1" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942" - url: "https://pub.flutter-io.cn" + sha256: "2a376b7d6392d80cd3705782d2caa734ca4727776db0b6ec36ef3f1855197699" + url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.6.0" path_provider_linux: dependency: transitive description: name: path_provider_linux sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.2.1" path_provider_platform_interface: @@ -391,7 +455,7 @@ packages: description: name: path_provider_platform_interface sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.2" path_provider_windows: @@ -399,23 +463,23 @@ packages: description: name: path_provider_windows sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.3.0" petitparser: dependency: transitive description: name: petitparser - sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 - url: "https://pub.flutter-io.cn" + sha256: "91bd59303e9f769f108f8df05e371341b15d59e995e6806aefab827b58336675" + url: "https://pub.dev" source: hosted - version: "6.0.2" + version: "7.0.2" platform: dependency: transitive description: name: platform sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.1.6" plugin_platform_interface: @@ -423,7 +487,7 @@ packages: description: name: plugin_platform_interface sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.1.8" posix: @@ -431,39 +495,55 @@ packages: description: name: posix sha256: "185ef7606574f789b40f289c233efa52e96dead518aed988e040a10737febb07" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "6.5.0" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + record_use: + dependency: transitive + description: + name: record_use + sha256: "2551bd8eecfe95d14ae75f6021ad0248be5c27f138c2ec12fcb52b500b3ba1ed" + url: "https://pub.dev" + source: hosted + version: "0.6.0" shared_preferences: dependency: "direct main" description: name: shared_preferences - sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5" - url: "https://pub.flutter-io.cn" + sha256: c3025c5534b01739267eb7d76959bbc25a6d10f6988e1c2a3036940133dd10bf + url: "https://pub.dev" source: hosted - version: "2.5.3" + version: "2.5.5" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "5bcf0772a761b04f8c6bf814721713de6f3e5d9d89caf8d3fe031b02a342379e" - url: "https://pub.flutter-io.cn" + sha256: e8d4762b1e2e8578fc4d0fd548cebf24afd24f49719c08974df92834565e2c53 + url: "https://pub.dev" source: hosted - version: "2.4.11" + version: "2.4.23" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03" - url: "https://pub.flutter-io.cn" + sha256: "4e7eaffc2b17ba398759f1151415869a34771ba11ebbccd1b0145472a619a64f" + url: "https://pub.dev" source: hosted - version: "2.5.4" + version: "2.5.6" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.4.1" shared_preferences_ohos: @@ -479,16 +559,16 @@ packages: dependency: transitive description: name: shared_preferences_platform_interface - sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" - url: "https://pub.flutter-io.cn" + sha256: "649dc798a33931919ea356c4305c2d1f81619ea6e92244070b520187b5140ef9" + url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.2" shared_preferences_web: dependency: transitive description: name: shared_preferences_web sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.4.3" shared_preferences_windows: @@ -496,7 +576,7 @@ packages: description: name: shared_preferences_windows sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.4.1" sky_engine: @@ -508,56 +588,56 @@ packages: dependency: transitive description: name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" - url: "https://pub.flutter-io.cn" + sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab" + url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.10.2" stack_trace: dependency: transitive description: name: stack_trace - sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" - url: "https://pub.flutter-io.cn" + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" + url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.12.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 - url: "https://pub.flutter-io.cn" + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" + url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" string_scanner: dependency: transitive description: name: string_scanner - sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" - url: "https://pub.flutter-io.cn" + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" + url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.1" term_glyph: dependency: transitive description: name: term_glyph - sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 - url: "https://pub.flutter-io.cn" + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" + url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.2" test_api: dependency: transitive description: name: test_api - sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" - url: "https://pub.flutter-io.cn" + sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a" + url: "https://pub.dev" source: hosted - version: "0.7.3" + version: "0.7.10" typed_data: dependency: transitive description: name: typed_data sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.4.0" url_launcher: @@ -565,41 +645,41 @@ packages: description: name: url_launcher sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8 - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "6.3.2" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "0aedad096a85b49df2e4725fa32118f9fa580f3b14af7a2d2221896a02cd5656" - url: "https://pub.flutter-io.cn" + sha256: "17bc677f0b301615530dd1d67e0a9828cafa2d0b6b6eae4cd3679b7eac4a273c" + url: "https://pub.dev" source: hosted - version: "6.3.17" + version: "6.3.30" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "7f2022359d4c099eea7df3fdf739f7d3d3b9faf3166fb1dd390775176e0b76cb" - url: "https://pub.flutter-io.cn" + sha256: "580fe5dfb51671ae38191d316e027f6b76272b026370708c2d898799750a02b0" + url: "https://pub.dev" source: hosted - version: "6.3.3" + version: "6.4.1" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935" - url: "https://pub.flutter-io.cn" + sha256: d5e14138b3bc193a0f63c10a53c94b91d399df0512b1f29b94a043db7482384a + url: "https://pub.dev" source: hosted - version: "3.2.1" + version: "3.2.2" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - sha256: "17ba2000b847f334f16626a574c702b196723af2a289e7a93ffcb79acff855c2" - url: "https://pub.flutter-io.cn" + sha256: "368adf46f71ad3c21b8f06614adb38346f193f3a59ba8fe9a2fd74133070ba18" + url: "https://pub.dev" source: hosted - version: "3.2.2" + version: "3.2.5" url_launcher_ohos: dependency: "direct overridden" description: @@ -614,47 +694,47 @@ packages: description: name: url_launcher_platform_interface sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "2.3.2" url_launcher_web: dependency: transitive description: name: url_launcher_web - sha256: "4bd2b7b4dc4d4d0b94e5babfffbca8eac1a126c7f3d6ecbc1a11013faa3abba2" - url: "https://pub.flutter-io.cn" + sha256: "85c81589622fbc87c1c683aaea164d3604a7777495a79d91e39ffcdec39ddb34" + url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.3" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77" - url: "https://pub.flutter-io.cn" + sha256: "712c70ab1b99744ff066053cbe3e80c73332b38d46e5e945c98689b2e66fc15f" + url: "https://pub.dev" source: hosted - version: "3.1.4" + version: "3.1.5" vector_math: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" - url: "https://pub.flutter-io.cn" + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b + url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.2.0" vm_service: dependency: transitive description: name: vm_service - sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b - url: "https://pub.flutter-io.cn" + sha256: "0016aef94fc66495ac78af5859181e3f3bf2026bd8eecc72b9565601e19ab360" + url: "https://pub.dev" source: hosted - version: "14.3.0" + version: "15.2.0" web: dependency: "direct main" description: name: web sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.1" webview_flutter: @@ -670,8 +750,8 @@ packages: dependency: transitive description: path: "packages/webview_flutter/webview_flutter_android" - ref: "br_webview_flutter-v4.13.0_ohos" - resolved-ref: "8d70938aa190eb7d7cd4d66f0d16fddb3c2d03ba" + ref: de942e79c9057b32ad31106508bd87c0d60aef83 + resolved-ref: de942e79c9057b32ad31106508bd87c0d60aef83 url: "https://gitcode.com/openharmony-tpc/flutter_packages.git" source: git version: "4.7.0" @@ -679,8 +759,8 @@ packages: dependency: transitive description: path: "packages/webview_flutter/webview_flutter_ohos" - ref: "br_webview_flutter-v4.13.0_ohos" - resolved-ref: "8d70938aa190eb7d7cd4d66f0d16fddb3c2d03ba" + ref: de942e79c9057b32ad31106508bd87c0d60aef83 + resolved-ref: de942e79c9057b32ad31106508bd87c0d60aef83 url: "https://gitcode.com/openharmony-tpc/flutter_packages.git" source: git version: "4.7.0" @@ -697,8 +777,8 @@ packages: dependency: transitive description: path: "packages/webview_flutter/webview_flutter_wkwebview" - ref: "br_webview_flutter-v4.13.0_ohos" - resolved-ref: "8d70938aa190eb7d7cd4d66f0d16fddb3c2d03ba" + ref: de942e79c9057b32ad31106508bd87c0d60aef83 + resolved-ref: de942e79c9057b32ad31106508bd87c0d60aef83 url: "https://gitcode.com/openharmony-tpc/flutter_packages.git" source: git version: "3.22.0" @@ -707,41 +787,41 @@ packages: description: name: webview_win_floating sha256: "40b4f6c66554d3eb9c486952b5c072e2478f9471f64e6d63e92ddc4e527b7aa8" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.0.3" win32: dependency: transitive description: name: win32 - sha256: daf97c9d80197ed7b619040e86c8ab9a9dad285e7671ee7390f9180cc828a51e - url: "https://pub.flutter-io.cn" + sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e + url: "https://pub.dev" source: hosted - version: "5.10.1" + version: "5.15.0" xdg_directories: dependency: transitive description: name: xdg_directories sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "1.1.0" xml: dependency: transitive description: name: xml - sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 - url: "https://pub.flutter-io.cn" + sha256: "67f0aff7be013d107995e9b75bf4e7f2c3ef2dfdb2c8e68024bba0a7fd5756a4" + url: "https://pub.dev" source: hosted - version: "6.5.0" + version: "7.0.1" yaml: dependency: transitive description: name: yaml sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce - url: "https://pub.flutter-io.cn" + url: "https://pub.dev" source: hosted version: "3.1.3" sdks: - dart: ">=3.6.2 <4.0.0" - flutter: ">=3.27.0" + dart: ">=3.11.0 <4.0.0" + flutter: ">=3.38.4" diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 0a2c976..873284c 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -11,6 +11,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST + jni ) set(PLUGIN_BUNDLED_LIBRARIES)