system_helper.dart 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. import 'package:get/get.dart';
  2. import 'package:url_launcher/url_launcher.dart';
  3. import '../app/components/ix_snackbar.dart';
  4. import '../app/constants/configs.dart';
  5. import '../app/data/sp/ix_sp.dart';
  6. import '../app/routes/app_pages.dart';
  7. import 'package:flutter_custom_tabs/flutter_custom_tabs.dart' as ct;
  8. import '../config/translations/strings_enum.dart';
  9. class SystemHelper {
  10. // static Future<void> openEmail(String email) async {
  11. // final Uri emailUri = Uri(
  12. // scheme: 'mailto',
  13. // path: email,
  14. // );
  15. // try {
  16. // await launchUrl(
  17. // emailUri,
  18. // mode: LaunchMode.externalApplication,
  19. // );
  20. // } catch (e) {
  21. // CustomSnackBar.showCustomErrorSnackBar(
  22. // title: Strings.error.tr, message: Strings.eUtilOpenEmail.tr);
  23. // }
  24. // }
  25. static Future<void> openGooglePlay(String packageName) async {
  26. final String url =
  27. 'https://play.google.com/store/apps/details?id=$packageName';
  28. try {
  29. // 直接尝试打开 Google Play 应用
  30. await launchUrl(Uri.parse(url), mode: LaunchMode.externalApplication);
  31. } catch (e) {
  32. IXSnackBar.showIXErrorSnackBar(
  33. title: Strings.error.tr,
  34. message: Strings.eUtilOpenGooglePlay.tr,
  35. );
  36. }
  37. }
  38. static Future<void> openGooglePlayUrl(String url) async {
  39. try {
  40. // 直接尝试打开 Google Play 应用
  41. await launchUrl(Uri.parse(url), mode: LaunchMode.externalApplication);
  42. } catch (e) {
  43. IXSnackBar.showIXErrorSnackBar(
  44. title: Strings.error.tr,
  45. message: Strings.eUtilOpenGooglePlay.tr,
  46. );
  47. }
  48. }
  49. static Future<void> openGoogleChrome(String url) async {
  50. try {
  51. await ct.launchUrl(
  52. Uri.parse(url),
  53. customTabsOptions: ct.CustomTabsOptions.partial(
  54. configuration: ct.PartialCustomTabsConfiguration.adaptiveSheet(
  55. initialHeight: Get.height * 0.7,
  56. initialWidth: Get.width * 0.4,
  57. activitySideSheetMaximizationEnabled: true,
  58. activitySideSheetDecorationType:
  59. ct.CustomTabsActivitySideSheetDecorationType.shadow,
  60. activitySideSheetRoundedCornersPosition:
  61. ct.CustomTabsActivitySideSheetRoundedCornersPosition.top,
  62. cornerRadius: 16,
  63. ),
  64. ),
  65. safariVCOptions: const ct.SafariViewControllerOptions.pageSheet(
  66. configuration: ct.SheetPresentationControllerConfiguration(
  67. detents: {
  68. ct.SheetPresentationControllerDetent.large,
  69. ct.SheetPresentationControllerDetent.medium,
  70. },
  71. prefersScrollingExpandsWhenScrolledToEdge: true,
  72. prefersGrabberVisible: true,
  73. prefersEdgeAttachedInCompactHeight: true,
  74. ),
  75. dismissButtonStyle: ct.SafariViewControllerDismissButtonStyle.close,
  76. ),
  77. );
  78. } catch (e) {
  79. try {
  80. await launchUrl(Uri.parse(url), mode: LaunchMode.externalApplication);
  81. } catch (e) {
  82. IXSnackBar.showIXErrorSnackBar(
  83. title: Strings.error.tr,
  84. message: Strings.eUtilOpenBrowser.tr,
  85. );
  86. }
  87. }
  88. }
  89. static Future<void> closeGoogleChrome() async {
  90. await ct.closeCustomTabs();
  91. }
  92. static Future<void> openWebPage(String url) async {
  93. try {
  94. final Uri webUri = Uri.parse(url);
  95. await launchUrl(webUri, mode: LaunchMode.externalApplication);
  96. } catch (e) {
  97. IXSnackBar.showIXErrorSnackBar(
  98. title: Strings.error.tr,
  99. message: Strings.eUtilOpenBrowser.tr,
  100. );
  101. }
  102. }
  103. static Future<void> openInAppWebPage(String url, String title) async {
  104. Get.toNamed(Routes.WEB, arguments: {'url': url, 'title': title});
  105. }
  106. static Future<void> handleDeepLink(String deepLink) async {
  107. try {
  108. final Uri uri = Uri.parse(deepLink);
  109. if (await canLaunchUrl(uri)) {
  110. await launchUrl(uri, mode: LaunchMode.externalApplication);
  111. } else {
  112. IXSnackBar.showIXErrorSnackBar(
  113. title: Strings.error.tr,
  114. message: Strings.unknownError.tr,
  115. );
  116. }
  117. } catch (e) {
  118. IXSnackBar.showIXErrorSnackBar(
  119. title: Strings.error.tr,
  120. message: Strings.unknownError.tr,
  121. );
  122. }
  123. }
  124. static void openPrivacyTerms() {
  125. final launch = IXSP.getLaunch();
  126. if (launch?.appConfig?.privacyAgreement != null &&
  127. launch?.appConfig?.privacyAgreement?.privacyTermsUrl != null) {
  128. String url = launch?.appConfig?.privacyAgreement?.privacyTermsUrl ?? '';
  129. if (url.indexOf("http") != 0) {
  130. url = '${Configs.websiteUrl}/$url';
  131. }
  132. Get.toNamed(
  133. Routes.WEB,
  134. arguments: {'url': url, 'title': Strings.privacyPolicy.tr},
  135. );
  136. } else {
  137. Get.toNamed(
  138. Routes.MARKDOWN,
  139. arguments: {'title': Strings.privacyPolicy.tr, 'filename': 'privacy'},
  140. );
  141. }
  142. }
  143. static void openTermsOfService() {
  144. final launch = IXSP.getLaunch();
  145. if (launch?.appConfig?.privacyAgreement != null &&
  146. launch?.appConfig?.privacyAgreement?.termsOfServiceUrl != null) {
  147. String url = launch?.appConfig?.privacyAgreement?.termsOfServiceUrl ?? '';
  148. if (url.indexOf("http") != 0) {
  149. url = '${Configs.websiteUrl}/$url';
  150. }
  151. Get.toNamed(
  152. Routes.WEB,
  153. arguments: {'url': url, 'title': Strings.termsOfService.tr},
  154. );
  155. } else {
  156. Get.toNamed(
  157. Routes.MARKDOWN,
  158. arguments: {'title': Strings.termsOfService.tr, 'filename': 'terms'},
  159. );
  160. }
  161. }
  162. // 打开 JS Bridge 测试页面
  163. static void openTestPage() {
  164. Get.toNamed(
  165. Routes.WEB,
  166. arguments: {
  167. // 使用 assets/ 前缀,WebView 会自动使用 loadData 加载
  168. 'url': 'assets/html/test_jsbridge.html',
  169. 'title': 'JS Bridge 测试',
  170. 'fullScreen': true,
  171. },
  172. );
  173. }
  174. }