Merge branch 'dev_chad_v1.0' into 'dev_reason_v1.0'
Google Map& Google 订阅支付 See merge request !1
Showing
15 changed files
with
633 additions
and
187 deletions
lib/apis/api_base.dart
0 → 100644
| 1 | +import 'dart:convert'; | ||
| 2 | + | ||
| 3 | +import 'package:Parlando/apis/api_response.dart'; | ||
| 4 | +import 'package:Parlando/net/dio_utils.dart'; | ||
| 5 | +import 'package:common_utils/common_utils.dart'; | ||
| 6 | +import 'package:dio/dio.dart'; | ||
| 7 | +import 'package:flutter/material.dart'; | ||
| 8 | + | ||
| 9 | +class BaseApi { | ||
| 10 | + Future<Response<T>> post<T>( | ||
| 11 | + String path, { | ||
| 12 | + data, | ||
| 13 | + Map<String, dynamic>? queryParameters, | ||
| 14 | + Options? options, | ||
| 15 | + CancelToken? cancelToken, | ||
| 16 | + ProgressCallback? onSendProgress, | ||
| 17 | + ProgressCallback? onReceiveProgress, | ||
| 18 | + }) { | ||
| 19 | + return _getDio().post<T>( | ||
| 20 | + path, | ||
| 21 | + data: data, | ||
| 22 | + queryParameters: queryParameters, | ||
| 23 | + options: options, | ||
| 24 | + cancelToken: cancelToken, | ||
| 25 | + onSendProgress: onSendProgress, | ||
| 26 | + onReceiveProgress: onReceiveProgress, | ||
| 27 | + ); | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + Dio _getDio() { | ||
| 31 | + return DioUtils.instance.dio; | ||
| 32 | + } | ||
| 33 | +} |
lib/apis/api_order.dart
0 → 100644
| 1 | +import 'dart:convert'; | ||
| 2 | + | ||
| 3 | +import 'package:Parlando/apis/api_base.dart'; | ||
| 4 | +import 'package:Parlando/apis/api_response.dart'; | ||
| 5 | +import 'package:common_utils/common_utils.dart'; | ||
| 6 | +import 'package:dio/dio.dart'; | ||
| 7 | +import 'package:flutter/material.dart'; | ||
| 8 | + | ||
| 9 | +class OrderApi extends BaseApi { | ||
| 10 | + OrderApi._privateConstructor(); | ||
| 11 | + | ||
| 12 | + static final OrderApi _instance = OrderApi._privateConstructor(); | ||
| 13 | + | ||
| 14 | + static OrderApi get request { | ||
| 15 | + return _instance; | ||
| 16 | + } | ||
| 17 | + | ||
| 18 | + Future<dynamic> createOrder(String productId) { | ||
| 19 | + var data = {"goods_id": productId}; | ||
| 20 | + return post("order", data: data).then((value) { | ||
| 21 | + if (TextUtil.isEmpty(value.data)) { | ||
| 22 | + return {}; | ||
| 23 | + } | ||
| 24 | + return json.decode(value.data); | ||
| 25 | + }); | ||
| 26 | + } | ||
| 27 | +} |
lib/base/base_state.dart
0 → 100644
| 1 | +import 'package:flutter/material.dart'; | ||
| 2 | +import 'package:flutter_easyloading/flutter_easyloading.dart'; | ||
| 3 | + | ||
| 4 | +abstract class BaseState<T extends StatefulWidget> extends State<T> { | ||
| 5 | + bool _isFirstBuild = true; | ||
| 6 | + | ||
| 7 | + @override | ||
| 8 | + Widget build(BuildContext context) { | ||
| 9 | + if (_isFirstBuild) { | ||
| 10 | + onFirstBuildBody(context); | ||
| 11 | + _isFirstBuild = false; | ||
| 12 | + } | ||
| 13 | + return buildBody(context); | ||
| 14 | + } | ||
| 15 | + | ||
| 16 | + Widget buildBody(BuildContext context); | ||
| 17 | + | ||
| 18 | + void onFirstBuildBody(BuildContext context) {} | ||
| 19 | + | ||
| 20 | + showLoading({String text = 'Loading...'}) { | ||
| 21 | + EasyLoading.show(status: text); | ||
| 22 | + } | ||
| 23 | + | ||
| 24 | + hideLoading() { | ||
| 25 | + EasyLoading.dismiss(); | ||
| 26 | + } | ||
| 27 | + | ||
| 28 | + toast(String text) { | ||
| 29 | + EasyLoading.showToast(text); | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + Widget buildLoading() { | ||
| 33 | + return const Center(child: CircularProgressIndicator()); | ||
| 34 | + } | ||
| 35 | +} |
lib/extension/widget_ext.dart
0 → 100644
| 1 | +import 'package:flutter/material.dart'; | ||
| 2 | + | ||
| 3 | +extension WidgetExt on Widget { | ||
| 4 | + Expanded expanded({int flex = 1}) { | ||
| 5 | + return Expanded(flex: flex, child: this); | ||
| 6 | + } | ||
| 7 | + | ||
| 8 | + SafeArea safe() { | ||
| 9 | + return SafeArea(child: this); | ||
| 10 | + } | ||
| 11 | + | ||
| 12 | + ClipRRect round({double? radius, BorderRadius? borderRadius}) { | ||
| 13 | + return ClipRRect( | ||
| 14 | + borderRadius: borderRadius ?? BorderRadius.all(Radius.circular(radius ?? 5)), | ||
| 15 | + child: this, | ||
| 16 | + ); | ||
| 17 | + } | ||
| 18 | + | ||
| 19 | + Container height(double height, {Alignment? alignment}) { | ||
| 20 | + return Container(height: height, alignment: alignment, child: this); | ||
| 21 | + } | ||
| 22 | + | ||
| 23 | + Container height48({Alignment? alignment}) { | ||
| 24 | + return Container(height: 48, alignment: alignment, child: this); | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + Container paddingALL(double padding) { | ||
| 28 | + return Container(child: this, padding: EdgeInsets.all(padding)); | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + Container paddingTopBottom(double padding) { | ||
| 32 | + return Container(child: this, padding: EdgeInsets.only(bottom: padding, top: padding)); | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | + Container paddingBottom(double padding) { | ||
| 36 | + return Container(child: this, padding: EdgeInsets.only(bottom: padding)); | ||
| 37 | + } | ||
| 38 | + | ||
| 39 | + Container paddingTop(double padding) { | ||
| 40 | + return Container(child: this, padding: EdgeInsets.only(top: padding)); | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + Widget paddingLeftRight(double padding) { | ||
| 44 | + return Container(child: this, padding: EdgeInsets.only(left: padding, right: padding)); | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + Container paddingLeft(double padding) { | ||
| 48 | + return Container(child: this, padding: EdgeInsets.only(left: padding)); | ||
| 49 | + } | ||
| 50 | + | ||
| 51 | + Container paddingRight(double padding) { | ||
| 52 | + return Container(child: this, padding: EdgeInsets.only(right: padding)); | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + Row rowRight() { | ||
| 56 | + return Row(mainAxisAlignment: MainAxisAlignment.end, children: [this]); | ||
| 57 | + } | ||
| 58 | + | ||
| 59 | + Row rowLeft() { | ||
| 60 | + return Row(mainAxisAlignment: MainAxisAlignment.start, children: [this]); | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + Row rowCenter() { | ||
| 64 | + return Row(mainAxisAlignment: MainAxisAlignment.center, children: [this]); | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + Widget click( | ||
| 68 | + GestureTapCallback? onTap, { | ||
| 69 | + Color? color, | ||
| 70 | + double? radius, | ||
| 71 | + BorderRadius? borderRadius, | ||
| 72 | + Color? bgColor, | ||
| 73 | + }) { | ||
| 74 | + if (color != null) { | ||
| 75 | + var border = radius == null ? null : BorderRadius.all(Radius.circular(radius)); | ||
| 76 | + return getMaterialInkWell( | ||
| 77 | + this, | ||
| 78 | + onTap, | ||
| 79 | + color, | ||
| 80 | + borderRadius: borderRadius ?? border, | ||
| 81 | + bgColor: bgColor, | ||
| 82 | + ); | ||
| 83 | + } | ||
| 84 | + return getWhiteInkWell(this, onTap); | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + ///当InkWell效果失效时,使用这个套件 | ||
| 88 | + Widget getMaterialInkWell( | ||
| 89 | + Widget widget, | ||
| 90 | + GestureTapCallback? onTap, | ||
| 91 | + Color? color, { | ||
| 92 | + BorderRadius? borderRadius, | ||
| 93 | + Color? splashColor, | ||
| 94 | + Color? bgColor = Colors.white, | ||
| 95 | + }) { | ||
| 96 | + return Material( | ||
| 97 | + color: bgColor, | ||
| 98 | + child: Ink( | ||
| 99 | + decoration: BoxDecoration( | ||
| 100 | + color: color, | ||
| 101 | + borderRadius: borderRadius, | ||
| 102 | + ), | ||
| 103 | + child: InkWell( | ||
| 104 | + onTap: onTap, | ||
| 105 | + splashColor: splashColor, | ||
| 106 | + borderRadius: borderRadius, | ||
| 107 | + child: widget, | ||
| 108 | + ), | ||
| 109 | + ), | ||
| 110 | + ); | ||
| 111 | + } | ||
| 112 | + | ||
| 113 | + ///当InkWell效果失效时,使用这个套件 | ||
| 114 | + Widget getWhiteInkWell(Widget widget, GestureTapCallback? onTap, {BorderRadius? borderRadius}) { | ||
| 115 | + return Material( | ||
| 116 | + child: Ink( | ||
| 117 | + color: Colors.white, | ||
| 118 | + child: InkWell(onTap: onTap, child: widget), | ||
| 119 | + ), | ||
| 120 | + ); | ||
| 121 | + } | ||
| 122 | +} |
| ... | @@ -116,17 +116,19 @@ Map<String, dynamic> $MembershipDataToJson(MembershipData entity) { | ... | @@ -116,17 +116,19 @@ Map<String, dynamic> $MembershipDataToJson(MembershipData entity) { |
| 116 | 116 | ||
| 117 | MembershipDataGoodsList $MembershipDataGoodsListFromJson( | 117 | MembershipDataGoodsList $MembershipDataGoodsListFromJson( |
| 118 | Map<String, dynamic> json) { | 118 | Map<String, dynamic> json) { |
| 119 | - final MembershipDataGoodsList membershipDataGoodsList = | 119 | + final MembershipDataGoodsList membershipDataGoodsList = MembershipDataGoodsList(); |
| 120 | - MembershipDataGoodsList(); | ||
| 121 | final int? id = jsonConvert.convert<int>(json['id']); | 120 | final int? id = jsonConvert.convert<int>(json['id']); |
| 122 | if (id != null) { | 121 | if (id != null) { |
| 123 | membershipDataGoodsList.id = id; | 122 | membershipDataGoodsList.id = id; |
| 124 | } | 123 | } |
| 125 | - final String? membershipId = | 124 | + final String? membershipId = jsonConvert.convert<String>(json['membership_id']); |
| 126 | - jsonConvert.convert<String>(json['membership_id']); | ||
| 127 | if (membershipId != null) { | 125 | if (membershipId != null) { |
| 128 | membershipDataGoodsList.membershipId = membershipId; | 126 | membershipDataGoodsList.membershipId = membershipId; |
| 129 | } | 127 | } |
| 128 | + final String? iapId = jsonConvert.convert<String>(json['iap_id']); | ||
| 129 | + if (iapId != null) { | ||
| 130 | + membershipDataGoodsList.iapId = iapId; | ||
| 131 | + } | ||
| 130 | final String? name = jsonConvert.convert<String>(json['name']); | 132 | final String? name = jsonConvert.convert<String>(json['name']); |
| 131 | if (name != null) { | 133 | if (name != null) { |
| 132 | membershipDataGoodsList.name = name; | 134 | membershipDataGoodsList.name = name; |
| ... | @@ -192,6 +194,7 @@ Map<String, dynamic> $MembershipDataGoodsListToJson( | ... | @@ -192,6 +194,7 @@ Map<String, dynamic> $MembershipDataGoodsListToJson( |
| 192 | final Map<String, dynamic> data = <String, dynamic>{}; | 194 | final Map<String, dynamic> data = <String, dynamic>{}; |
| 193 | data['id'] = entity.id; | 195 | data['id'] = entity.id; |
| 194 | data['membership_id'] = entity.membershipId; | 196 | data['membership_id'] = entity.membershipId; |
| 197 | + data['iap_id'] = entity.iapId; | ||
| 195 | data['name'] = entity.name; | 198 | data['name'] = entity.name; |
| 196 | data['price'] = entity.price; | 199 | data['price'] = entity.price; |
| 197 | data['line_price'] = entity.linePrice; | 200 | data['line_price'] = entity.linePrice; | ... | ... |
| ... | @@ -6,6 +6,7 @@ import 'package:dio/dio.dart'; | ... | @@ -6,6 +6,7 @@ import 'package:dio/dio.dart'; |
| 6 | import 'package:flustars/flustars.dart'; | 6 | import 'package:flustars/flustars.dart'; |
| 7 | import 'package:flutter/material.dart'; | 7 | import 'package:flutter/material.dart'; |
| 8 | import 'package:flutter/services.dart'; | 8 | import 'package:flutter/services.dart'; |
| 9 | +import 'package:flutter_easyloading/flutter_easyloading.dart'; | ||
| 9 | import 'package:oktoast/oktoast.dart'; | 10 | import 'package:oktoast/oktoast.dart'; |
| 10 | import 'package:provider/provider.dart'; | 11 | import 'package:provider/provider.dart'; |
| 11 | import 'package:quick_actions/quick_actions.dart'; | 12 | import 'package:quick_actions/quick_actions.dart'; |
| ... | @@ -60,8 +61,7 @@ Future<void> main() async { | ... | @@ -60,8 +61,7 @@ Future<void> main() async { |
| 60 | await SpUtil.getInstance(); | 61 | await SpUtil.getInstance(); |
| 61 | 62 | ||
| 62 | WidgetsFlutterBinding.ensureInitialized(); | 63 | WidgetsFlutterBinding.ensureInitialized(); |
| 63 | - SystemChrome.setPreferredOrientations( | 64 | + SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]); |
| 64 | - [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]); | ||
| 65 | 65 | ||
| 66 | /// 1.22 预览功能: 在输入频率与显示刷新率不匹配情况下提供平滑的滚动效果 | 66 | /// 1.22 预览功能: 在输入频率与显示刷新率不匹配情况下提供平滑的滚动效果 |
| 67 | // GestureBinding.instance?.resamplingEnabled = true; | 67 | // GestureBinding.instance?.resamplingEnabled = true; |
| ... | @@ -69,8 +69,7 @@ Future<void> main() async { | ... | @@ -69,8 +69,7 @@ Future<void> main() async { |
| 69 | handleError(() => runApp(MyApp())); | 69 | handleError(() => runApp(MyApp())); |
| 70 | 70 | ||
| 71 | /// 隐藏状态栏。为启动页、引导页设置。完成后修改回显示状态栏。 | 71 | /// 隐藏状态栏。为启动页、引导页设置。完成后修改回显示状态栏。 |
| 72 | - SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, | 72 | + SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: [SystemUiOverlay.bottom]); |
| 73 | - overlays: [SystemUiOverlay.bottom]); | ||
| 74 | // TODO(weilu): 启动体验不佳。状态栏、导航栏在冷启动开始的一瞬间为黑色,且无法通过隐藏、修改颜色等方式进行处理。。。 | 73 | // TODO(weilu): 启动体验不佳。状态栏、导航栏在冷启动开始的一瞬间为黑色,且无法通过隐藏、修改颜色等方式进行处理。。。 |
| 75 | // 相关问题跟踪:https://github.com/flutter/flutter/issues/73351 | 74 | // 相关问题跟踪:https://github.com/flutter/flutter/issues/73351 |
| 76 | if (Platform.isAndroid) { | 75 | if (Platform.isAndroid) { |
| ... | @@ -133,8 +132,7 @@ class MyApp extends StatelessWidget { | ... | @@ -133,8 +132,7 @@ class MyApp extends StatelessWidget { |
| 133 | } | 132 | } |
| 134 | 133 | ||
| 135 | quickActions.setShortcutItems(<ShortcutItem>[ | 134 | quickActions.setShortcutItems(<ShortcutItem>[ |
| 136 | - const ShortcutItem( | 135 | + const ShortcutItem(type: 'demo', localizedTitle: '发一言', icon: 'flutter_dash_black'), |
| 137 | - type: 'demo', localizedTitle: '发一言', icon: 'flutter_dash_black'), | ||
| 138 | ]); | 136 | ]); |
| 139 | } | 137 | } |
| 140 | } | 138 | } |
| ... | @@ -149,8 +147,7 @@ class MyApp extends StatelessWidget { | ... | @@ -149,8 +147,7 @@ class MyApp extends StatelessWidget { |
| 149 | ChangeNotifierProvider(create: (_) => MembershipViewProvider()) | 147 | ChangeNotifierProvider(create: (_) => MembershipViewProvider()) |
| 150 | ], | 148 | ], |
| 151 | child: Consumer2<ThemeProvider, LocaleProvider>( | 149 | child: Consumer2<ThemeProvider, LocaleProvider>( |
| 152 | - builder: | 150 | + builder: (_, ThemeProvider provider, LocaleProvider localeProvider, __) { |
| 153 | - (_, ThemeProvider provider, LocaleProvider localeProvider, __) { | ||
| 154 | return _buildMaterialApp(provider, localeProvider); | 151 | return _buildMaterialApp(provider, localeProvider); |
| 155 | }, | 152 | }, |
| 156 | ), | 153 | ), |
| ... | @@ -159,15 +156,13 @@ class MyApp extends StatelessWidget { | ... | @@ -159,15 +156,13 @@ class MyApp extends StatelessWidget { |
| 159 | /// Toast 配置 | 156 | /// Toast 配置 |
| 160 | return OKToast( | 157 | return OKToast( |
| 161 | backgroundColor: Colors.black54, | 158 | backgroundColor: Colors.black54, |
| 162 | - textPadding: | 159 | + textPadding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 10.0), |
| 163 | - const EdgeInsets.symmetric(horizontal: 16.0, vertical: 10.0), | ||
| 164 | radius: 20.0, | 160 | radius: 20.0, |
| 165 | position: ToastPosition.bottom, | 161 | position: ToastPosition.bottom, |
| 166 | child: app); | 162 | child: app); |
| 167 | } | 163 | } |
| 168 | 164 | ||
| 169 | - Widget _buildMaterialApp( | 165 | + Widget _buildMaterialApp(ThemeProvider provider, LocaleProvider localeProvider) { |
| 170 | - ThemeProvider provider, LocaleProvider localeProvider) { | ||
| 171 | return MaterialApp( | 166 | return MaterialApp( |
| 172 | title: '一言', | 167 | title: '一言', |
| 173 | // showPerformanceOverlay: true, //显示性能标签 | 168 | // showPerformanceOverlay: true, //显示性能标签 |
| ... | @@ -185,7 +180,7 @@ class MyApp extends StatelessWidget { | ... | @@ -185,7 +180,7 @@ class MyApp extends StatelessWidget { |
| 185 | supportedLocales: ParlandoLocalizations.supportedLocales, | 180 | supportedLocales: ParlandoLocalizations.supportedLocales, |
| 186 | locale: localeProvider.locale, | 181 | locale: localeProvider.locale, |
| 187 | navigatorKey: navigatorKey, | 182 | navigatorKey: navigatorKey, |
| 188 | - builder: (BuildContext context, Widget? child) { | 183 | + builder: EasyLoading.init(builder: (context, child) { |
| 189 | /// 仅针对安卓 | 184 | /// 仅针对安卓 |
| 190 | if (Device.isAndroid) { | 185 | if (Device.isAndroid) { |
| 191 | /// 切换深色模式会触发此方法,这里设置导航栏颜色 | 186 | /// 切换深色模式会触发此方法,这里设置导航栏颜色 |
| ... | @@ -197,7 +192,7 @@ class MyApp extends StatelessWidget { | ... | @@ -197,7 +192,7 @@ class MyApp extends StatelessWidget { |
| 197 | data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0), | 192 | data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0), |
| 198 | child: child!, | 193 | child: child!, |
| 199 | ); | 194 | ); |
| 200 | - }, | 195 | + }), |
| 201 | 196 | ||
| 202 | /// 因为使用了fluro,这里设置主要针对Web | 197 | /// 因为使用了fluro,这里设置主要针对Web |
| 203 | onUnknownRoute: (_) { | 198 | onUnknownRoute: (_) { |
| ... | @@ -236,4 +231,4 @@ Future<bool> requestLocationPermission() async { | ... | @@ -236,4 +231,4 @@ Future<bool> requestLocationPermission() async { |
| 236 | return false; | 231 | return false; |
| 237 | } | 232 | } |
| 238 | } | 233 | } |
| 239 | -} | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 234 | +} | ... | ... |
| ... | @@ -65,6 +65,8 @@ class MembershipDataGoodsList { | ... | @@ -65,6 +65,8 @@ class MembershipDataGoodsList { |
| 65 | int? id; | 65 | int? id; |
| 66 | @JSONField(name: "membership_id") | 66 | @JSONField(name: "membership_id") |
| 67 | String? membershipId; | 67 | String? membershipId; |
| 68 | + @JSONField(name: "iap_id") | ||
| 69 | + String? iapId; | ||
| 68 | String? name; | 70 | String? name; |
| 69 | String? price; | 71 | String? price; |
| 70 | @JSONField(name: "line_price") | 72 | @JSONField(name: "line_price") | ... | ... |
This diff is collapsed. Click to expand it.
| ... | @@ -41,6 +41,7 @@ class Results { | ... | @@ -41,6 +41,7 @@ class Results { |
| 41 | PlusCode? plusCode; | 41 | PlusCode? plusCode; |
| 42 | dynamic rating; | 42 | dynamic rating; |
| 43 | int? userRatingsTotal; | 43 | int? userRatingsTotal; |
| 44 | + bool isSelect = false; | ||
| 44 | 45 | ||
| 45 | Results( | 46 | Results( |
| 46 | {this.geometry, | 47 | {this.geometry, |
| ... | @@ -58,11 +59,11 @@ class Results { | ... | @@ -58,11 +59,11 @@ class Results { |
| 58 | this.openingHours, | 59 | this.openingHours, |
| 59 | this.plusCode, | 60 | this.plusCode, |
| 60 | this.rating, | 61 | this.rating, |
| 61 | - this.userRatingsTotal}); | 62 | + this.userRatingsTotal, |
| 63 | + this.isSelect = false}); | ||
| 62 | 64 | ||
| 63 | Results.fromJson(Map<String, dynamic> json) { | 65 | Results.fromJson(Map<String, dynamic> json) { |
| 64 | - geometry = | 66 | + geometry = json['geometry'] != null ? Geometry.fromJson(json['geometry']) : null; |
| 65 | - json['geometry'] != null ? Geometry.fromJson(json['geometry']) : null; | ||
| 66 | icon = json['icon']; | 67 | icon = json['icon']; |
| 67 | iconBackgroundColor = json['icon_background_color']; | 68 | iconBackgroundColor = json['icon_background_color']; |
| 68 | iconMaskBaseUri = json['icon_mask_base_uri']; | 69 | iconMaskBaseUri = json['icon_mask_base_uri']; |
| ... | @@ -79,11 +80,8 @@ class Results { | ... | @@ -79,11 +80,8 @@ class Results { |
| 79 | types = json['types'].cast<String>(); | 80 | types = json['types'].cast<String>(); |
| 80 | vicinity = json['vicinity']; | 81 | vicinity = json['vicinity']; |
| 81 | businessStatus = json['business_status']; | 82 | businessStatus = json['business_status']; |
| 82 | - openingHours = json['opening_hours'] != null | 83 | + openingHours = json['opening_hours'] != null ? OpeningHours.fromJson(json['opening_hours']) : null; |
| 83 | - ? OpeningHours.fromJson(json['opening_hours']) | 84 | + plusCode = json['plus_code'] != null ? PlusCode.fromJson(json['plus_code']) : null; |
| 84 | - : null; | ||
| 85 | - plusCode = | ||
| 86 | - json['plus_code'] != null ? PlusCode.fromJson(json['plus_code']) : null; | ||
| 87 | rating = json['rating']; | 85 | rating = json['rating']; |
| 88 | userRatingsTotal = json['user_ratings_total']; | 86 | userRatingsTotal = json['user_ratings_total']; |
| 89 | } | 87 | } |
| ... | @@ -125,10 +123,8 @@ class Geometry { | ... | @@ -125,10 +123,8 @@ class Geometry { |
| 125 | Geometry({this.location, this.viewport}); | 123 | Geometry({this.location, this.viewport}); |
| 126 | 124 | ||
| 127 | Geometry.fromJson(Map<String, dynamic> json) { | 125 | Geometry.fromJson(Map<String, dynamic> json) { |
| 128 | - location = | 126 | + location = json['location'] != null ? Location.fromJson(json['location']) : null; |
| 129 | - json['location'] != null ? Location.fromJson(json['location']) : null; | 127 | + viewport = json['viewport'] != null ? Viewport.fromJson(json['viewport']) : null; |
| 130 | - viewport = | ||
| 131 | - json['viewport'] != null ? Viewport.fromJson(json['viewport']) : null; | ||
| 132 | } | 128 | } |
| 133 | 129 | ||
| 134 | Map<String, dynamic> toJson() { | 130 | Map<String, dynamic> toJson() { |
| ... | @@ -169,10 +165,8 @@ class Viewport { | ... | @@ -169,10 +165,8 @@ class Viewport { |
| 169 | Viewport({this.northeast, this.southwest}); | 165 | Viewport({this.northeast, this.southwest}); |
| 170 | 166 | ||
| 171 | Viewport.fromJson(Map<String, dynamic> json) { | 167 | Viewport.fromJson(Map<String, dynamic> json) { |
| 172 | - northeast = | 168 | + northeast = json['northeast'] != null ? Location.fromJson(json['northeast']) : null; |
| 173 | - json['northeast'] != null ? Location.fromJson(json['northeast']) : null; | 169 | + southwest = json['southwest'] != null ? Location.fromJson(json['southwest']) : null; |
| 174 | - southwest = | ||
| 175 | - json['southwest'] != null ? Location.fromJson(json['southwest']) : null; | ||
| 176 | } | 170 | } |
| 177 | 171 | ||
| 178 | Map<String, dynamic> toJson() { | 172 | Map<String, dynamic> toJson() { | ... | ... |
lib/payment/payment_sdk.dart
0 → 100644
| 1 | +import 'dart:async'; | ||
| 2 | + | ||
| 3 | +import 'package:Parlando/apis/api_order.dart'; | ||
| 4 | +import 'package:Parlando/membership/models/membership_entity.dart'; | ||
| 5 | +import 'package:common_utils/common_utils.dart'; | ||
| 6 | +import 'package:in_app_purchase/in_app_purchase.dart'; | ||
| 7 | + | ||
| 8 | +class PaymentSdk { | ||
| 9 | + PaymentSdk._privateConstructor(); | ||
| 10 | + | ||
| 11 | + static final PaymentSdk _instance = PaymentSdk._privateConstructor(); | ||
| 12 | + | ||
| 13 | + static PaymentSdk get instance { | ||
| 14 | + return _instance; | ||
| 15 | + } | ||
| 16 | + | ||
| 17 | + static const Set<String> _kIds = <String>{'yearly_yiyan_vip', 'monthly_yiyan_vip'}; | ||
| 18 | + | ||
| 19 | + StreamSubscription<List<PurchaseDetails>>? _subscription; | ||
| 20 | + List<ProductDetails> products = []; | ||
| 21 | + Function? onPaySuccess; | ||
| 22 | + Function? onPending; | ||
| 23 | + Function? onFailed; | ||
| 24 | + Function? onCancel; | ||
| 25 | + | ||
| 26 | + initState({ | ||
| 27 | + Function? onPaySuccess, | ||
| 28 | + Function? onPending, | ||
| 29 | + Function? onFailed, | ||
| 30 | + Function? onCancel, | ||
| 31 | + }) { | ||
| 32 | + this.onPaySuccess = onPaySuccess; | ||
| 33 | + this.onPending = onPending; | ||
| 34 | + this.onFailed = onFailed; | ||
| 35 | + this.onCancel = onCancel; | ||
| 36 | + final Stream<List<PurchaseDetails>> purchaseUpdated = InAppPurchase.instance.purchaseStream; | ||
| 37 | + _subscription = purchaseUpdated.listen((purchaseDetailsList) { | ||
| 38 | + _listenToPurchaseUpdated(purchaseDetailsList); | ||
| 39 | + }, onDone: () { | ||
| 40 | + _subscription?.cancel(); | ||
| 41 | + }, onError: (error) { | ||
| 42 | + // handle error here. | ||
| 43 | + }); | ||
| 44 | + } | ||
| 45 | + | ||
| 46 | + Future<List<ProductDetails>> queryProducts() async { | ||
| 47 | + final bool available = await InAppPurchase.instance.isAvailable(); | ||
| 48 | + if (!available) { | ||
| 49 | + return []; | ||
| 50 | + } | ||
| 51 | + final ProductDetailsResponse response = await InAppPurchase.instance.queryProductDetails(_kIds); | ||
| 52 | + return products = response.productDetails; | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + buy(ProductDetails details, MembershipDataGoodsList e) { | ||
| 56 | + OrderApi.request.createOrder(e.id.toString()).then((value) { | ||
| 57 | + var orderId = value?['data']?['data']?['order_sn']; | ||
| 58 | + if (TextUtil.isEmpty(orderId)) { | ||
| 59 | + onFailed?.call(); | ||
| 60 | + return; | ||
| 61 | + } | ||
| 62 | + final PurchaseParam purchaseParam = PurchaseParam(productDetails: details, applicationUserName: orderId); | ||
| 63 | + if (_isConsumable(details)) { | ||
| 64 | + InAppPurchase.instance.buyConsumable(purchaseParam: purchaseParam); | ||
| 65 | + } else { | ||
| 66 | + InAppPurchase.instance.buyNonConsumable(purchaseParam: purchaseParam); | ||
| 67 | + } | ||
| 68 | + }); | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + void _listenToPurchaseUpdated(List<PurchaseDetails> purchaseDetailsList) async { | ||
| 72 | + for (var purchaseDetails in purchaseDetailsList) { | ||
| 73 | + if (purchaseDetails.status == PurchaseStatus.pending) { | ||
| 74 | + onPending?.call(); | ||
| 75 | + } else { | ||
| 76 | + if (purchaseDetails.status == PurchaseStatus.error) { | ||
| 77 | + _handleError(purchaseDetails.error!); | ||
| 78 | + } else if (purchaseDetails.status == PurchaseStatus.purchased || purchaseDetails.status == PurchaseStatus.restored) { | ||
| 79 | + bool valid = await _verifyPurchase(purchaseDetails); | ||
| 80 | + if (valid) { | ||
| 81 | + _deliverProduct(purchaseDetails); | ||
| 82 | + } else { | ||
| 83 | + _handleInvalidPurchase(purchaseDetails); | ||
| 84 | + } | ||
| 85 | + } else { | ||
| 86 | + onCancel?.call(); | ||
| 87 | + } | ||
| 88 | + if (purchaseDetails.pendingCompletePurchase) { | ||
| 89 | + await InAppPurchase.instance.completePurchase(purchaseDetails); | ||
| 90 | + } | ||
| 91 | + } | ||
| 92 | + } | ||
| 93 | + } | ||
| 94 | + | ||
| 95 | + _verifyPurchase(PurchaseDetails purchaseDetails) async { | ||
| 96 | + return true; | ||
| 97 | + } | ||
| 98 | + | ||
| 99 | + void _deliverProduct(PurchaseDetails purchaseDetails) { | ||
| 100 | + onPaySuccess?.call(); | ||
| 101 | + } | ||
| 102 | + | ||
| 103 | + void _handleInvalidPurchase(PurchaseDetails purchaseDetails) { | ||
| 104 | + onFailed?.call(); | ||
| 105 | + } | ||
| 106 | + | ||
| 107 | + void _handleError(IAPError iapError) { | ||
| 108 | + onFailed?.call(); | ||
| 109 | + } | ||
| 110 | + | ||
| 111 | + bool _isConsumable(ProductDetails details) { | ||
| 112 | + return true; | ||
| 113 | + } | ||
| 114 | + | ||
| 115 | + void restore() { | ||
| 116 | + InAppPurchase.instance.restorePurchases(); | ||
| 117 | + } | ||
| 118 | + | ||
| 119 | + void dispose() { | ||
| 120 | + onPaySuccess = null; | ||
| 121 | + onPending = null; | ||
| 122 | + onFailed = null; | ||
| 123 | + onCancel = null; | ||
| 124 | + _subscription?.cancel(); | ||
| 125 | + } | ||
| 126 | +} |
| ... | @@ -26,7 +26,7 @@ class PaymentService { | ... | @@ -26,7 +26,7 @@ class PaymentService { |
| 26 | late StreamSubscription<PurchaseResult?> _purchaseErrorSubscription; | 26 | late StreamSubscription<PurchaseResult?> _purchaseErrorSubscription; |
| 27 | 27 | ||
| 28 | /// List of product ids you want to fetch | 28 | /// List of product ids you want to fetch |
| 29 | - final List<String> _productIds = ['test.yiyan.vip.1.month']; | 29 | + final List<String> _productIds = ['yearly_yiyan_vip', 'monthly_yiyan_vip']; |
| 30 | 30 | ||
| 31 | /// All available products will be store in this list | 31 | /// All available products will be store in this list |
| 32 | late List<IAPItem> _products; | 32 | late List<IAPItem> _products; |
| ... | @@ -36,12 +36,12 @@ class PaymentService { | ... | @@ -36,12 +36,12 @@ class PaymentService { |
| 36 | 36 | ||
| 37 | /// view of the app will subscribe to this to get notified | 37 | /// view of the app will subscribe to this to get notified |
| 38 | /// when premium status of the user changes | 38 | /// when premium status of the user changes |
| 39 | - final ObserverList<Function> _proStatusChangedListeners = | 39 | + final ObserverList<Function> _proStatusChangedListeners = ObserverList<Function>(); |
| 40 | - ObserverList<Function>(); | ||
| 41 | 40 | ||
| 42 | /// view of the app will subscribe to this to get errors of the purchase | 41 | /// view of the app will subscribe to this to get errors of the purchase |
| 43 | - final ObserverList<Function(String)> _errorListeners = | 42 | + final ObserverList<Function(String)> _errorListeners = ObserverList<Function(String)>(); |
| 44 | - ObserverList<Function(String)>(); | 43 | + |
| 44 | + final ObserverList<Function> _connectListeners = ObserverList<Function>(); | ||
| 45 | 45 | ||
| 46 | /// logged in user's premium status | 46 | /// logged in user's premium status |
| 47 | bool _isProUser = false; | 47 | bool _isProUser = false; |
| ... | @@ -68,6 +68,20 @@ class PaymentService { | ... | @@ -68,6 +68,20 @@ class PaymentService { |
| 68 | _errorListeners.remove(callback); | 68 | _errorListeners.remove(callback); |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | + addConnectListener(Function? callback) { | ||
| 72 | + if (callback == null) { | ||
| 73 | + return; | ||
| 74 | + } | ||
| 75 | + _connectListeners.add(callback); | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + removeConnectListener(Function? callback) { | ||
| 79 | + if (callback == null) { | ||
| 80 | + return; | ||
| 81 | + } | ||
| 82 | + _connectListeners.remove(callback); | ||
| 83 | + } | ||
| 84 | + | ||
| 71 | /// Call this method to notify all the subsctibers of _proStatusChangedListeners | 85 | /// Call this method to notify all the subsctibers of _proStatusChangedListeners |
| 72 | void _callProStatusChangedListeners() { | 86 | void _callProStatusChangedListeners() { |
| 73 | for (var callback in _proStatusChangedListeners) { | 87 | for (var callback in _proStatusChangedListeners) { |
| ... | @@ -84,18 +98,19 @@ class PaymentService { | ... | @@ -84,18 +98,19 @@ class PaymentService { |
| 84 | 98 | ||
| 85 | /// Call this method at the startup of you app to initialize connection | 99 | /// Call this method at the startup of you app to initialize connection |
| 86 | /// with billing server and get all the necessary data | 100 | /// with billing server and get all the necessary data |
| 87 | - void initConnection() { | 101 | + void initConnection() async { |
| 88 | - var result = FlutterInappPurchase.instance.initialize(); | 102 | + var result = await FlutterInappPurchase.instance.initialize(); |
| 89 | print("___________________________"); | 103 | print("___________________________"); |
| 90 | print("result:$result"); | 104 | print("result:$result"); |
| 91 | - _connectionSubscription = | 105 | + _connectionSubscription = FlutterInappPurchase.connectionUpdated.listen((connected) { |
| 92 | - FlutterInappPurchase.connectionUpdated.listen((connected) {}); | 106 | + for (var value in _connectListeners) { |
| 107 | + value.call(); | ||
| 108 | + } | ||
| 109 | + }); | ||
| 93 | 110 | ||
| 94 | - _purchaseUpdatedSubscription = | 111 | + _purchaseUpdatedSubscription = FlutterInappPurchase.purchaseUpdated.listen(_handlePurchaseUpdate); |
| 95 | - FlutterInappPurchase.purchaseUpdated.listen(_handlePurchaseUpdate); | ||
| 96 | 112 | ||
| 97 | - _purchaseErrorSubscription = | 113 | + _purchaseErrorSubscription = FlutterInappPurchase.purchaseError.listen(_handlePurchaseError); |
| 98 | - FlutterInappPurchase.purchaseError.listen(_handlePurchaseError); | ||
| 99 | 114 | ||
| 100 | _getItems(); | 115 | _getItems(); |
| 101 | _getPastPurchases(); | 116 | _getPastPurchases(); |
| ... | @@ -191,14 +206,14 @@ class PaymentService { | ... | @@ -191,14 +206,14 @@ class PaymentService { |
| 191 | } | 206 | } |
| 192 | 207 | ||
| 193 | Future<void> _getItems() async { | 208 | Future<void> _getItems() async { |
| 194 | - List<IAPItem> items = | 209 | + List<IAPItem> items = await FlutterInappPurchase.instance.getSubscriptions(_productIds); |
| 195 | - await FlutterInappPurchase.instance.getSubscriptions(_productIds); | 210 | + print("############${items.length}"); |
| 196 | _products = []; | 211 | _products = []; |
| 197 | for (var item in items) { | 212 | for (var item in items) { |
| 198 | _products.add(item); | 213 | _products.add(item); |
| 199 | } | 214 | } |
| 200 | print("############"); | 215 | print("############"); |
| 201 | - print(_products); | 216 | + print("############${_products}"); |
| 202 | } | 217 | } |
| 203 | 218 | ||
| 204 | void _getPastPurchases() async { | 219 | void _getPastPurchases() async { |
| ... | @@ -206,8 +221,7 @@ class PaymentService { | ... | @@ -206,8 +221,7 @@ class PaymentService { |
| 206 | if (Platform.isIOS) { | 221 | if (Platform.isIOS) { |
| 207 | return; | 222 | return; |
| 208 | } | 223 | } |
| 209 | - List<PurchasedItem>? purchasedItems = | 224 | + List<PurchasedItem>? purchasedItems = await FlutterInappPurchase.instance.getAvailablePurchases(); |
| 210 | - await FlutterInappPurchase.instance.getAvailablePurchases(); | ||
| 211 | 225 | ||
| 212 | for (var purchasedItem in purchasedItems!) { | 226 | for (var purchasedItem in purchasedItems!) { |
| 213 | bool isValid = false; | 227 | bool isValid = false; |
| ... | @@ -236,8 +250,7 @@ class PaymentService { | ... | @@ -236,8 +250,7 @@ class PaymentService { |
| 236 | 250 | ||
| 237 | Future<void> buyProduct(IAPItem item) async { | 251 | Future<void> buyProduct(IAPItem item) async { |
| 238 | try { | 252 | try { |
| 239 | - await FlutterInappPurchase.instance | 253 | + await FlutterInappPurchase.instance.requestSubscription(item.productId.toString()); |
| 240 | - .requestSubscription(item.productId.toString()); | ||
| 241 | } catch (error) { | 254 | } catch (error) { |
| 242 | Toast.show("购买失败!"); | 255 | Toast.show("购买失败!"); |
| 243 | } | 256 | } | ... | ... |
| 1 | import 'dart:async'; | 1 | import 'dart:async'; |
| 2 | import 'dart:convert'; | 2 | import 'dart:convert'; |
| 3 | +import 'package:Parlando/extension/widget_ext.dart'; | ||
| 3 | import 'package:Parlando/models/nearby_response.dart' as nearby; | 4 | import 'package:Parlando/models/nearby_response.dart' as nearby; |
| 4 | import 'package:Parlando/routers/fluro_navigator.dart'; | 5 | import 'package:Parlando/routers/fluro_navigator.dart'; |
| 6 | +import 'package:Parlando/util/log_utils.dart'; | ||
| 5 | import 'package:Parlando/util/toast_utils.dart'; | 7 | import 'package:Parlando/util/toast_utils.dart'; |
| 6 | import 'package:flutter/material.dart'; | 8 | import 'package:flutter/material.dart'; |
| 7 | import 'package:Parlando/widgets/my_button.dart'; | 9 | import 'package:Parlando/widgets/my_button.dart'; |
| ... | @@ -19,26 +21,17 @@ class AddressSelectPage extends StatefulWidget { | ... | @@ -19,26 +21,17 @@ class AddressSelectPage extends StatefulWidget { |
| 19 | } | 21 | } |
| 20 | 22 | ||
| 21 | class AddressSelectPageState extends State<AddressSelectPage> { | 23 | class AddressSelectPageState extends State<AddressSelectPage> { |
| 22 | - List<nearby.Results> _list = []; | 24 | + List<nearby.Results> _nearByList = []; |
| 23 | - int _index = 0; | ||
| 24 | final ScrollController _controller = ScrollController(); | 25 | final ScrollController _controller = ScrollController(); |
| 25 | - LatLng _center = const LatLng(45.521563, -122.677433); | 26 | + LatLng? _center; |
| 26 | late GoogleMapController mapController; | 27 | late GoogleMapController mapController; |
| 27 | - bool isLoading = false; | 28 | + bool isLoading = true; |
| 28 | - int _markerIdCounter = 1; | ||
| 29 | Map<MarkerId, Marker> markers = <MarkerId, Marker>{}; | 29 | Map<MarkerId, Marker> markers = <MarkerId, Marker>{}; |
| 30 | late StreamSubscription _locationSubscription; | 30 | late StreamSubscription _locationSubscription; |
| 31 | - String radius = "1000"; | 31 | + String radiusMax = "1000"; |
| 32 | String apiKey = "AIzaSyDQZsMULyO-UtiSht4_MFi1uHT4BIqasjw"; | 32 | String apiKey = "AIzaSyDQZsMULyO-UtiSht4_MFi1uHT4BIqasjw"; |
| 33 | - nearby.NearbyPlacesResponse nearbyPlacesResponse = | 33 | + nearby.NearbyPlacesResponse nearbyPlacesResponse = nearby.NearbyPlacesResponse(); |
| 34 | - nearby.NearbyPlacesResponse(); | ||
| 35 | 34 | ||
| 36 | - @override | ||
| 37 | - void dispose() { | ||
| 38 | - _controller.dispose(); | ||
| 39 | - _locationSubscription.cancel(); | ||
| 40 | - super.dispose(); | ||
| 41 | - } | ||
| 42 | 35 | ||
| 43 | @override | 36 | @override |
| 44 | void initState() { | 37 | void initState() { |
| ... | @@ -64,116 +57,168 @@ class AddressSelectPageState extends State<AddressSelectPage> { | ... | @@ -64,116 +57,168 @@ class AddressSelectPageState extends State<AddressSelectPage> { |
| 64 | return; | 57 | return; |
| 65 | } | 58 | } |
| 66 | } | 59 | } |
| 67 | - | 60 | + var currentLocation = await location.getLocation(); |
| 68 | - _locationSubscription = | 61 | + _center = LatLng(currentLocation.latitude!, currentLocation.longitude!); |
| 69 | - location.onLocationChanged.listen((LocationData currentLocation) { | 62 | + getNearbyPlaces(""); |
| 70 | - _center = LatLng(currentLocation.latitude!, currentLocation.longitude!); | 63 | + _goToCurrentCenter(); |
| 71 | - }); | ||
| 72 | } | 64 | } |
| 73 | 65 | ||
| 74 | void getNearbyPlaces(String keyword) async { | 66 | void getNearbyPlaces(String keyword) async { |
| 75 | - String uri = | 67 | + String host = 'https://maps.googleapis.com/maps/api/place/nearbysearch/json'; |
| 76 | - '${'https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=${_center.latitude},${_center.longitude}&radius=$radius'}&key=$apiKey&keyword=$keyword'; | 68 | + String location = 'location=${_center?.latitude},${_center?.longitude}'; |
| 69 | + String radius = 'radius=$radiusMax'; | ||
| 70 | + String types = 'type=point_of_interest'; | ||
| 71 | + String uri = '${'$host?$location&$radius'}&key=$apiKey&keyword=$keyword&$types'; | ||
| 72 | + print(uri); | ||
| 77 | var url = Uri.parse(uri); | 73 | var url = Uri.parse(uri); |
| 78 | var response = await http.post(url); | 74 | var response = await http.post(url); |
| 79 | - nearbyPlacesResponse = | 75 | + nearbyPlacesResponse = nearby.NearbyPlacesResponse.fromJson(jsonDecode(response.body)); |
| 80 | - nearby.NearbyPlacesResponse.fromJson(jsonDecode(response.body)); | 76 | + _nearByList = nearbyPlacesResponse.results!; |
| 81 | - _list = nearbyPlacesResponse.results!; | 77 | + if (_nearByList.isNotEmpty) { |
| 78 | + selectItemLocation(_nearByList[0]); | ||
| 79 | + } | ||
| 82 | setState(() { | 80 | setState(() { |
| 83 | isLoading = false; | 81 | isLoading = false; |
| 84 | }); | 82 | }); |
| 83 | + buildMarkers(); | ||
| 85 | } | 84 | } |
| 86 | 85 | ||
| 87 | void _onMapCreated(GoogleMapController controller) { | 86 | void _onMapCreated(GoogleMapController controller) { |
| 88 | mapController = controller; | 87 | mapController = controller; |
| 89 | - final String markerIdVal = 'marker_id_$_markerIdCounter'; | ||
| 90 | - _markerIdCounter++; | ||
| 91 | - final MarkerId markerId = MarkerId(markerIdVal); | ||
| 92 | - final Marker marker = Marker( | ||
| 93 | - markerId: markerId, | ||
| 94 | - position: _center, | ||
| 95 | - ); | ||
| 96 | - mapController.moveCamera(CameraUpdate.newLatLng(_center)); | ||
| 97 | - setState(() { | ||
| 98 | - markers[markerId] = marker; | ||
| 99 | - }); | ||
| 100 | getNearbyPlaces(""); | 88 | getNearbyPlaces(""); |
| 101 | } | 89 | } |
| 102 | 90 | ||
| 91 | + void _goToCurrentCenter() { | ||
| 92 | + if (_center != null) { | ||
| 93 | + mapController.moveCamera(CameraUpdate.newLatLng(_center!)); | ||
| 94 | + } | ||
| 95 | + } | ||
| 96 | + | ||
| 103 | @override | 97 | @override |
| 104 | Widget build(BuildContext context) { | 98 | Widget build(BuildContext context) { |
| 99 | + var loaderView = const GFLoader().expanded(flex: 11); | ||
| 100 | + Widget realList = ListView.separated( | ||
| 101 | + controller: _controller, | ||
| 102 | + itemCount: _nearByList.length, | ||
| 103 | + separatorBuilder: (_, index) => const Divider(), | ||
| 104 | + itemBuilder: (_, index) { | ||
| 105 | + var item = _nearByList[index]; | ||
| 106 | + return _AddressItem( | ||
| 107 | + isSelected: item.isSelect, | ||
| 108 | + data: item, | ||
| 109 | + onTap: () { | ||
| 110 | + selectItemLocation(item); | ||
| 111 | + }, | ||
| 112 | + ); | ||
| 113 | + }, | ||
| 114 | + ).expanded(flex: 11); | ||
| 115 | + if (_nearByList.isEmpty) { | ||
| 116 | + realList = const Center(child: Text("没有找到任何地点")).expanded(flex: 11); | ||
| 117 | + } | ||
| 118 | + var listHolder = isLoading ? loaderView : realList; | ||
| 119 | + | ||
| 120 | + var searchBar = SearchBar( | ||
| 121 | + hintText: '搜索地址', | ||
| 122 | + onPressed: (text) async { | ||
| 123 | + isLoading = true; | ||
| 124 | + _controller.animateTo(0.0, duration: const Duration(milliseconds: 10), curve: Curves.ease); | ||
| 125 | + // 构造检索参数 | ||
| 126 | + getNearbyPlaces(text); | ||
| 127 | + setState(() { | ||
| 128 | + | ||
| 129 | + }); | ||
| 130 | + }, | ||
| 131 | + ); | ||
| 132 | + var map = GoogleMap( | ||
| 133 | + onMapCreated: _onMapCreated, | ||
| 134 | + initialCameraPosition: CameraPosition(target: _center ?? const LatLng(45.521563, -122.677433), zoom: 16.0), | ||
| 135 | + markers: Set<Marker>.of(markers.values), | ||
| 136 | + myLocationEnabled: true, | ||
| 137 | + myLocationButtonEnabled: true, | ||
| 138 | + ).expanded(flex: 9); | ||
| 139 | + | ||
| 105 | return Scaffold( | 140 | return Scaffold( |
| 106 | resizeToAvoidBottomInset: false, | 141 | resizeToAvoidBottomInset: false, |
| 107 | - appBar: SearchBar( | 142 | + appBar: searchBar, |
| 108 | - hintText: '搜索地址', | 143 | + body: Column( |
| 109 | - onPressed: (text) async { | 144 | + children: <Widget>[map, listHolder, initButton()], |
| 110 | - isLoading = true; | 145 | + ).safe(), |
| 111 | - _controller.animateTo(0.0, | ||
| 112 | - duration: const Duration(milliseconds: 10), curve: Curves.ease); | ||
| 113 | - _index = 0; | ||
| 114 | - // 构造检索参数 | ||
| 115 | - getNearbyPlaces(text); | ||
| 116 | - }, | ||
| 117 | - ), | ||
| 118 | - body: SafeArea( | ||
| 119 | - child: Column( | ||
| 120 | - children: <Widget>[ | ||
| 121 | - Expanded( | ||
| 122 | - flex: 9, | ||
| 123 | - child: GoogleMap( | ||
| 124 | - onMapCreated: _onMapCreated, | ||
| 125 | - initialCameraPosition: CameraPosition( | ||
| 126 | - target: _center, | ||
| 127 | - zoom: 16.0, | ||
| 128 | - ), | ||
| 129 | - markers: Set<Marker>.of(markers.values), | ||
| 130 | - ), | ||
| 131 | - ), | ||
| 132 | - Expanded( | ||
| 133 | - flex: 11, | ||
| 134 | - child: isLoading | ||
| 135 | - ? const GFLoader() | ||
| 136 | - : ListView.separated( | ||
| 137 | - controller: _controller, | ||
| 138 | - itemCount: _list.length, | ||
| 139 | - separatorBuilder: (_, index) => const Divider(), | ||
| 140 | - itemBuilder: (_, index) { | ||
| 141 | - return _AddressItem( | ||
| 142 | - isSelected: _index == index, | ||
| 143 | - date: _list[index], | ||
| 144 | - onTap: () { | ||
| 145 | - _index = index; | ||
| 146 | - setState(() {}); | ||
| 147 | - }, | ||
| 148 | - ); | ||
| 149 | - }, | ||
| 150 | - ), | ||
| 151 | - ), | ||
| 152 | - MyButton( | ||
| 153 | - onPressed: () { | ||
| 154 | - if (_list.isEmpty) { | ||
| 155 | - Toast.show('未选择地址!'); | ||
| 156 | - return; | ||
| 157 | - } | ||
| 158 | - NavigatorUtils.goBackWithParams(context, _list[_index]); | ||
| 159 | - }, | ||
| 160 | - text: '确认选择地址', | ||
| 161 | - ) | ||
| 162 | - ], | ||
| 163 | - ), | ||
| 164 | - ), | ||
| 165 | ); | 146 | ); |
| 166 | } | 147 | } |
| 148 | + | ||
| 149 | + initButton() { | ||
| 150 | + return MyButton( | ||
| 151 | + onPressed: () { | ||
| 152 | + var selected = _nearByList.where((element) => element.isSelect); | ||
| 153 | + if (selected.isEmpty) { | ||
| 154 | + Toast.show('未选择地址!'); | ||
| 155 | + return; | ||
| 156 | + } | ||
| 157 | + | ||
| 158 | + NavigatorUtils.goBackWithParams(context, selected.first); | ||
| 159 | + }, | ||
| 160 | + text: '确认选择地址', | ||
| 161 | + ); | ||
| 162 | + } | ||
| 163 | + | ||
| 164 | + void buildMarkers() { | ||
| 165 | + markers.clear(); | ||
| 166 | + for (var value in _nearByList) { | ||
| 167 | + final MarkerId markerId = MarkerId(buildMarkerId(value)); | ||
| 168 | + final Marker marker = Marker( | ||
| 169 | + icon: value.isSelect ? BitmapDescriptor.defaultMarker : BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueBlue), | ||
| 170 | + markerId: markerId, | ||
| 171 | + position: buildMarkerLocation(value), | ||
| 172 | + ); | ||
| 173 | + markers[markerId] = marker; | ||
| 174 | + } | ||
| 175 | + setState(() {}); | ||
| 176 | + } | ||
| 177 | + | ||
| 178 | + String buildMarkerId(nearby.Results value) { | ||
| 179 | + var lat = value.geometry?.location?.lat; | ||
| 180 | + var lng = value.geometry?.location?.lng; | ||
| 181 | + return "$lat-$lng"; | ||
| 182 | + } | ||
| 183 | + | ||
| 184 | + LatLng buildMarkerLocation(nearby.Results value) { | ||
| 185 | + var lat = value.geometry?.location?.lat; | ||
| 186 | + var lng = value.geometry?.location?.lng; | ||
| 187 | + return LatLng(lat ?? 0, lng ?? 0); | ||
| 188 | + } | ||
| 189 | + | ||
| 190 | + void selectItemLocation(nearby.Results item) { | ||
| 191 | + for (var element in _nearByList) { | ||
| 192 | + element.isSelect = false; | ||
| 193 | + } | ||
| 194 | + item.isSelect = true; | ||
| 195 | + var lat = item.geometry?.location?.lat; | ||
| 196 | + var lng = item.geometry?.location?.lng; | ||
| 197 | + if (lat != null && lng != null) { | ||
| 198 | + _center = LatLng(lat, lng); | ||
| 199 | + } | ||
| 200 | + _goToCurrentCenter(); | ||
| 201 | + setState(() {}); | ||
| 202 | + buildMarkers(); | ||
| 203 | + } | ||
| 204 | + | ||
| 205 | + @override | ||
| 206 | + void dispose() { | ||
| 207 | + _controller.dispose(); | ||
| 208 | + _locationSubscription.cancel(); | ||
| 209 | + super.dispose(); | ||
| 210 | + } | ||
| 167 | } | 211 | } |
| 168 | 212 | ||
| 169 | class _AddressItem extends StatelessWidget { | 213 | class _AddressItem extends StatelessWidget { |
| 170 | const _AddressItem({ | 214 | const _AddressItem({ |
| 171 | Key? key, | 215 | Key? key, |
| 172 | - required this.date, | 216 | + required this.data, |
| 173 | this.isSelected = false, | 217 | this.isSelected = false, |
| 174 | this.onTap, | 218 | this.onTap, |
| 175 | }) : super(key: key); | 219 | }) : super(key: key); |
| 176 | - final nearby.Results date; | 220 | + |
| 221 | + final nearby.Results data; | ||
| 177 | final bool isSelected; | 222 | final bool isSelected; |
| 178 | final GestureTapCallback? onTap; | 223 | final GestureTapCallback? onTap; |
| 179 | 224 | ||
| ... | @@ -187,15 +232,8 @@ class _AddressItem extends StatelessWidget { | ... | @@ -187,15 +232,8 @@ class _AddressItem extends StatelessWidget { |
| 187 | height: 50.0, | 232 | height: 50.0, |
| 188 | child: Row( | 233 | child: Row( |
| 189 | children: <Widget>[ | 234 | children: <Widget>[ |
| 190 | - Expanded( | 235 | + Text('${data.name}').expanded(), |
| 191 | - child: Text( | 236 | + Visibility(visible: isSelected, child: const Icon(Icons.done, color: Colors.blue)) |
| 192 | - '${date.name} ${date.vicinity}', | ||
| 193 | - ), | ||
| 194 | - ), | ||
| 195 | - Visibility( | ||
| 196 | - visible: isSelected, | ||
| 197 | - child: const Icon(Icons.done, color: Colors.blue), | ||
| 198 | - ) | ||
| 199 | ], | 237 | ], |
| 200 | ), | 238 | ), |
| 201 | ), | 239 | ), | ... | ... |
| ... | @@ -28,7 +28,7 @@ packages: | ... | @@ -28,7 +28,7 @@ packages: |
| 28 | name: archive | 28 | name: archive |
| 29 | url: "https://pub.flutter-io.cn" | 29 | url: "https://pub.flutter-io.cn" |
| 30 | source: hosted | 30 | source: hosted |
| 31 | - version: "3.3.0" | 31 | + version: "3.1.11" |
| 32 | args: | 32 | args: |
| 33 | dependency: transitive | 33 | dependency: transitive |
| 34 | description: | 34 | description: |
| ... | @@ -42,7 +42,7 @@ packages: | ... | @@ -42,7 +42,7 @@ packages: |
| 42 | name: async | 42 | name: async |
| 43 | url: "https://pub.flutter-io.cn" | 43 | url: "https://pub.flutter-io.cn" |
| 44 | source: hosted | 44 | source: hosted |
| 45 | - version: "2.9.0" | 45 | + version: "2.8.2" |
| 46 | boolean_selector: | 46 | boolean_selector: |
| 47 | dependency: transitive | 47 | dependency: transitive |
| 48 | description: | 48 | description: |
| ... | @@ -112,21 +112,21 @@ packages: | ... | @@ -112,21 +112,21 @@ packages: |
| 112 | name: cached_network_image | 112 | name: cached_network_image |
| 113 | url: "https://pub.flutter-io.cn" | 113 | url: "https://pub.flutter-io.cn" |
| 114 | source: hosted | 114 | source: hosted |
| 115 | - version: "3.2.2" | 115 | + version: "3.2.1" |
| 116 | cached_network_image_platform_interface: | 116 | cached_network_image_platform_interface: |
| 117 | dependency: transitive | 117 | dependency: transitive |
| 118 | description: | 118 | description: |
| 119 | name: cached_network_image_platform_interface | 119 | name: cached_network_image_platform_interface |
| 120 | url: "https://pub.flutter-io.cn" | 120 | url: "https://pub.flutter-io.cn" |
| 121 | source: hosted | 121 | source: hosted |
| 122 | - version: "2.0.0" | 122 | + version: "1.0.0" |
| 123 | cached_network_image_web: | 123 | cached_network_image_web: |
| 124 | dependency: transitive | 124 | dependency: transitive |
| 125 | description: | 125 | description: |
| 126 | name: cached_network_image_web | 126 | name: cached_network_image_web |
| 127 | url: "https://pub.flutter-io.cn" | 127 | url: "https://pub.flutter-io.cn" |
| 128 | source: hosted | 128 | source: hosted |
| 129 | - version: "1.0.2" | 129 | + version: "1.0.1" |
| 130 | camera: | 130 | camera: |
| 131 | dependency: "direct main" | 131 | dependency: "direct main" |
| 132 | description: | 132 | description: |
| ... | @@ -168,7 +168,14 @@ packages: | ... | @@ -168,7 +168,14 @@ packages: |
| 168 | name: characters | 168 | name: characters |
| 169 | url: "https://pub.flutter-io.cn" | 169 | url: "https://pub.flutter-io.cn" |
| 170 | source: hosted | 170 | source: hosted |
| 171 | - version: "1.2.1" | 171 | + version: "1.2.0" |
| 172 | + charcode: | ||
| 173 | + dependency: transitive | ||
| 174 | + description: | ||
| 175 | + name: charcode | ||
| 176 | + url: "https://pub.flutter-io.cn" | ||
| 177 | + source: hosted | ||
| 178 | + version: "1.3.1" | ||
| 172 | checked_yaml: | 179 | checked_yaml: |
| 173 | dependency: transitive | 180 | dependency: transitive |
| 174 | description: | 181 | description: |
| ... | @@ -189,7 +196,7 @@ packages: | ... | @@ -189,7 +196,7 @@ packages: |
| 189 | name: clock | 196 | name: clock |
| 190 | url: "https://pub.flutter-io.cn" | 197 | url: "https://pub.flutter-io.cn" |
| 191 | source: hosted | 198 | source: hosted |
| 192 | - version: "1.1.1" | 199 | + version: "1.1.0" |
| 193 | code_builder: | 200 | code_builder: |
| 194 | dependency: transitive | 201 | dependency: transitive |
| 195 | description: | 202 | description: |
| ... | @@ -224,7 +231,7 @@ packages: | ... | @@ -224,7 +231,7 @@ packages: |
| 224 | name: coverage | 231 | name: coverage |
| 225 | url: "https://pub.flutter-io.cn" | 232 | url: "https://pub.flutter-io.cn" |
| 226 | source: hosted | 233 | source: hosted |
| 227 | - version: "1.5.0" | 234 | + version: "1.2.0" |
| 228 | cross_file: | 235 | cross_file: |
| 229 | dependency: transitive | 236 | dependency: transitive |
| 230 | description: | 237 | description: |
| ... | @@ -238,7 +245,7 @@ packages: | ... | @@ -238,7 +245,7 @@ packages: |
| 238 | name: crypto | 245 | name: crypto |
| 239 | url: "https://pub.flutter-io.cn" | 246 | url: "https://pub.flutter-io.cn" |
| 240 | source: hosted | 247 | source: hosted |
| 241 | - version: "3.0.2" | 248 | + version: "3.0.1" |
| 242 | csslib: | 249 | csslib: |
| 243 | dependency: transitive | 250 | dependency: transitive |
| 244 | description: | 251 | description: |
| ... | @@ -336,7 +343,7 @@ packages: | ... | @@ -336,7 +343,7 @@ packages: |
| 336 | name: fake_async | 343 | name: fake_async |
| 337 | url: "https://pub.flutter-io.cn" | 344 | url: "https://pub.flutter-io.cn" |
| 338 | source: hosted | 345 | source: hosted |
| 339 | - version: "1.3.1" | 346 | + version: "1.3.0" |
| 340 | ffi: | 347 | ffi: |
| 341 | dependency: transitive | 348 | dependency: transitive |
| 342 | description: | 349 | description: |
| ... | @@ -410,6 +417,13 @@ packages: | ... | @@ -410,6 +417,13 @@ packages: |
| 410 | url: "https://pub.flutter-io.cn" | 417 | url: "https://pub.flutter-io.cn" |
| 411 | source: hosted | 418 | source: hosted |
| 412 | version: "1.1.2" | 419 | version: "1.1.2" |
| 420 | + flutter_easyloading: | ||
| 421 | + dependency: "direct main" | ||
| 422 | + description: | ||
| 423 | + name: flutter_easyloading | ||
| 424 | + url: "https://pub.flutter-io.cn" | ||
| 425 | + source: hosted | ||
| 426 | + version: "3.0.5" | ||
| 413 | flutter_facebook_auth: | 427 | flutter_facebook_auth: |
| 414 | dependency: "direct main" | 428 | dependency: "direct main" |
| 415 | description: | 429 | description: |
| ... | @@ -463,7 +477,7 @@ packages: | ... | @@ -463,7 +477,7 @@ packages: |
| 463 | name: flutter_native_splash | 477 | name: flutter_native_splash |
| 464 | url: "https://pub.flutter-io.cn" | 478 | url: "https://pub.flutter-io.cn" |
| 465 | source: hosted | 479 | source: hosted |
| 466 | - version: "2.2.10+1" | 480 | + version: "2.2.9" |
| 467 | flutter_plugin_android_lifecycle: | 481 | flutter_plugin_android_lifecycle: |
| 468 | dependency: transitive | 482 | dependency: transitive |
| 469 | description: | 483 | description: |
| ... | @@ -703,6 +717,34 @@ packages: | ... | @@ -703,6 +717,34 @@ packages: |
| 703 | url: "https://pub.flutter-io.cn" | 717 | url: "https://pub.flutter-io.cn" |
| 704 | source: hosted | 718 | source: hosted |
| 705 | version: "2.6.2" | 719 | version: "2.6.2" |
| 720 | + in_app_purchase: | ||
| 721 | + dependency: "direct main" | ||
| 722 | + description: | ||
| 723 | + name: in_app_purchase | ||
| 724 | + url: "https://pub.flutter-io.cn" | ||
| 725 | + source: hosted | ||
| 726 | + version: "3.0.8" | ||
| 727 | + in_app_purchase_android: | ||
| 728 | + dependency: transitive | ||
| 729 | + description: | ||
| 730 | + name: in_app_purchase_android | ||
| 731 | + url: "https://pub.flutter-io.cn" | ||
| 732 | + source: hosted | ||
| 733 | + version: "0.2.3+6" | ||
| 734 | + in_app_purchase_platform_interface: | ||
| 735 | + dependency: transitive | ||
| 736 | + description: | ||
| 737 | + name: in_app_purchase_platform_interface | ||
| 738 | + url: "https://pub.flutter-io.cn" | ||
| 739 | + source: hosted | ||
| 740 | + version: "1.3.2" | ||
| 741 | + in_app_purchase_storekit: | ||
| 742 | + dependency: transitive | ||
| 743 | + description: | ||
| 744 | + name: in_app_purchase_storekit | ||
| 745 | + url: "https://pub.flutter-io.cn" | ||
| 746 | + source: hosted | ||
| 747 | + version: "0.3.3" | ||
| 706 | integration_test: | 748 | integration_test: |
| 707 | dependency: "direct dev" | 749 | dependency: "direct dev" |
| 708 | description: flutter | 750 | description: flutter |
| ... | @@ -757,6 +799,13 @@ packages: | ... | @@ -757,6 +799,13 @@ packages: |
| 757 | url: "https://pub.flutter-io.cn" | 799 | url: "https://pub.flutter-io.cn" |
| 758 | source: hosted | 800 | source: hosted |
| 759 | version: "4.1.0" | 801 | version: "4.1.0" |
| 802 | + lint: | ||
| 803 | + dependency: transitive | ||
| 804 | + description: | ||
| 805 | + name: lint | ||
| 806 | + url: "https://pub.flutter-io.cn" | ||
| 807 | + source: hosted | ||
| 808 | + version: "1.10.0" | ||
| 760 | lints: | 809 | lints: |
| 761 | dependency: transitive | 810 | dependency: transitive |
| 762 | description: | 811 | description: |
| ... | @@ -805,21 +854,21 @@ packages: | ... | @@ -805,21 +854,21 @@ packages: |
| 805 | name: matcher | 854 | name: matcher |
| 806 | url: "https://pub.flutter-io.cn" | 855 | url: "https://pub.flutter-io.cn" |
| 807 | source: hosted | 856 | source: hosted |
| 808 | - version: "0.12.12" | 857 | + version: "0.12.11" |
| 809 | material_color_utilities: | 858 | material_color_utilities: |
| 810 | dependency: transitive | 859 | dependency: transitive |
| 811 | description: | 860 | description: |
| 812 | name: material_color_utilities | 861 | name: material_color_utilities |
| 813 | url: "https://pub.flutter-io.cn" | 862 | url: "https://pub.flutter-io.cn" |
| 814 | source: hosted | 863 | source: hosted |
| 815 | - version: "0.1.5" | 864 | + version: "0.1.4" |
| 816 | meta: | 865 | meta: |
| 817 | dependency: transitive | 866 | dependency: transitive |
| 818 | description: | 867 | description: |
| 819 | name: meta | 868 | name: meta |
| 820 | url: "https://pub.flutter-io.cn" | 869 | url: "https://pub.flutter-io.cn" |
| 821 | source: hosted | 870 | source: hosted |
| 822 | - version: "1.8.0" | 871 | + version: "1.7.0" |
| 823 | mime: | 872 | mime: |
| 824 | dependency: transitive | 873 | dependency: transitive |
| 825 | description: | 874 | description: |
| ... | @@ -868,7 +917,7 @@ packages: | ... | @@ -868,7 +917,7 @@ packages: |
| 868 | name: path | 917 | name: path |
| 869 | url: "https://pub.flutter-io.cn" | 918 | url: "https://pub.flutter-io.cn" |
| 870 | source: hosted | 919 | source: hosted |
| 871 | - version: "1.8.2" | 920 | + version: "1.8.1" |
| 872 | path_provider: | 921 | path_provider: |
| 873 | dependency: "direct main" | 922 | dependency: "direct main" |
| 874 | description: | 923 | description: |
| ... | @@ -1272,7 +1321,7 @@ packages: | ... | @@ -1272,7 +1321,7 @@ packages: |
| 1272 | name: source_span | 1321 | name: source_span |
| 1273 | url: "https://pub.flutter-io.cn" | 1322 | url: "https://pub.flutter-io.cn" |
| 1274 | source: hosted | 1323 | source: hosted |
| 1275 | - version: "1.9.0" | 1324 | + version: "1.8.2" |
| 1276 | sp_util: | 1325 | sp_util: |
| 1277 | dependency: transitive | 1326 | dependency: transitive |
| 1278 | description: | 1327 | description: |
| ... | @@ -1293,7 +1342,7 @@ packages: | ... | @@ -1293,7 +1342,7 @@ packages: |
| 1293 | name: sqflite | 1342 | name: sqflite |
| 1294 | url: "https://pub.flutter-io.cn" | 1343 | url: "https://pub.flutter-io.cn" |
| 1295 | source: hosted | 1344 | source: hosted |
| 1296 | - version: "2.1.0+1" | 1345 | + version: "2.0.3+1" |
| 1297 | sqflite_common: | 1346 | sqflite_common: |
| 1298 | dependency: transitive | 1347 | dependency: transitive |
| 1299 | description: | 1348 | description: |
| ... | @@ -1335,14 +1384,14 @@ packages: | ... | @@ -1335,14 +1384,14 @@ packages: |
| 1335 | name: string_scanner | 1384 | name: string_scanner |
| 1336 | url: "https://pub.flutter-io.cn" | 1385 | url: "https://pub.flutter-io.cn" |
| 1337 | source: hosted | 1386 | source: hosted |
| 1338 | - version: "1.1.1" | 1387 | + version: "1.1.0" |
| 1339 | sync_http: | 1388 | sync_http: |
| 1340 | dependency: transitive | 1389 | dependency: transitive |
| 1341 | description: | 1390 | description: |
| 1342 | name: sync_http | 1391 | name: sync_http |
| 1343 | url: "https://pub.flutter-io.cn" | 1392 | url: "https://pub.flutter-io.cn" |
| 1344 | source: hosted | 1393 | source: hosted |
| 1345 | - version: "0.3.1" | 1394 | + version: "0.3.0" |
| 1346 | synchronized: | 1395 | synchronized: |
| 1347 | dependency: transitive | 1396 | dependency: transitive |
| 1348 | description: | 1397 | description: |
| ... | @@ -1363,28 +1412,28 @@ packages: | ... | @@ -1363,28 +1412,28 @@ packages: |
| 1363 | name: term_glyph | 1412 | name: term_glyph |
| 1364 | url: "https://pub.flutter-io.cn" | 1413 | url: "https://pub.flutter-io.cn" |
| 1365 | source: hosted | 1414 | source: hosted |
| 1366 | - version: "1.2.1" | 1415 | + version: "1.2.0" |
| 1367 | test: | 1416 | test: |
| 1368 | dependency: "direct dev" | 1417 | dependency: "direct dev" |
| 1369 | description: | 1418 | description: |
| 1370 | name: test | 1419 | name: test |
| 1371 | url: "https://pub.flutter-io.cn" | 1420 | url: "https://pub.flutter-io.cn" |
| 1372 | source: hosted | 1421 | source: hosted |
| 1373 | - version: "1.21.4" | 1422 | + version: "1.21.1" |
| 1374 | test_api: | 1423 | test_api: |
| 1375 | dependency: transitive | 1424 | dependency: transitive |
| 1376 | description: | 1425 | description: |
| 1377 | name: test_api | 1426 | name: test_api |
| 1378 | url: "https://pub.flutter-io.cn" | 1427 | url: "https://pub.flutter-io.cn" |
| 1379 | source: hosted | 1428 | source: hosted |
| 1380 | - version: "0.4.12" | 1429 | + version: "0.4.9" |
| 1381 | test_core: | 1430 | test_core: |
| 1382 | dependency: transitive | 1431 | dependency: transitive |
| 1383 | description: | 1432 | description: |
| 1384 | name: test_core | 1433 | name: test_core |
| 1385 | url: "https://pub.flutter-io.cn" | 1434 | url: "https://pub.flutter-io.cn" |
| 1386 | source: hosted | 1435 | source: hosted |
| 1387 | - version: "0.4.16" | 1436 | + version: "0.4.13" |
| 1388 | timing: | 1437 | timing: |
| 1389 | dependency: transitive | 1438 | dependency: transitive |
| 1390 | description: | 1439 | description: |
| ... | @@ -1405,7 +1454,7 @@ packages: | ... | @@ -1405,7 +1454,7 @@ packages: |
| 1405 | name: typed_data | 1454 | name: typed_data |
| 1406 | url: "https://pub.flutter-io.cn" | 1455 | url: "https://pub.flutter-io.cn" |
| 1407 | source: hosted | 1456 | source: hosted |
| 1408 | - version: "1.3.1" | 1457 | + version: "1.3.0" |
| 1409 | universal_io: | 1458 | universal_io: |
| 1410 | dependency: transitive | 1459 | dependency: transitive |
| 1411 | description: | 1460 | description: |
| ... | @@ -1538,7 +1587,7 @@ packages: | ... | @@ -1538,7 +1587,7 @@ packages: |
| 1538 | name: vm_service | 1587 | name: vm_service |
| 1539 | url: "https://pub.flutter-io.cn" | 1588 | url: "https://pub.flutter-io.cn" |
| 1540 | source: hosted | 1589 | source: hosted |
| 1541 | - version: "9.0.0" | 1590 | + version: "8.2.2" |
| 1542 | wakelock: | 1591 | wakelock: |
| 1543 | dependency: "direct main" | 1592 | dependency: "direct main" |
| 1544 | description: | 1593 | description: |
| ... | @@ -1659,5 +1708,5 @@ packages: | ... | @@ -1659,5 +1708,5 @@ packages: |
| 1659 | source: hosted | 1708 | source: hosted |
| 1660 | version: "3.1.1" | 1709 | version: "3.1.1" |
| 1661 | sdks: | 1710 | sdks: |
| 1662 | - dart: ">=2.18.0 <3.0.0" | 1711 | + dart: ">=2.17.0 <3.0.0" |
| 1663 | - flutter: ">=3.3.0" | 1712 | + flutter: ">=3.0.0" | ... | ... |
| ... | @@ -101,6 +101,8 @@ dependencies: | ... | @@ -101,6 +101,8 @@ dependencies: |
| 101 | 101 | ||
| 102 | # A Dart timer that can be paused, resumed and reset. | 102 | # A Dart timer that can be paused, resumed and reset. |
| 103 | pausable_timer: ^1.0.0+3 | 103 | pausable_timer: ^1.0.0+3 |
| 104 | + | ||
| 105 | + flutter_easyloading: ^3.0.0 | ||
| 104 | email_validator: ^2.0.1 | 106 | email_validator: ^2.0.1 |
| 105 | 107 | ||
| 106 | getwidget: ^2.0.5 | 108 | getwidget: ^2.0.5 |
| ... | @@ -114,7 +116,10 @@ dependencies: | ... | @@ -114,7 +116,10 @@ dependencies: |
| 114 | animated_radial_menu: | 116 | animated_radial_menu: |
| 115 | path: plugins/animated_radial | 117 | path: plugins/animated_radial |
| 116 | 118 | ||
| 119 | + # 非官方库 暂时不删 | ||
| 117 | flutter_inapp_purchase: ^5.3.0 | 120 | flutter_inapp_purchase: ^5.3.0 |
| 121 | + # Flutter官方支付支持库 | ||
| 122 | + in_app_purchase: ^3.0.8 | ||
| 118 | 123 | ||
| 119 | jpush_flutter: ^2.2.9 | 124 | jpush_flutter: ^2.2.9 |
| 120 | share_plus: ^4.0.10 | 125 | share_plus: ^4.0.10 |
| ... | @@ -125,7 +130,8 @@ dependencies: | ... | @@ -125,7 +130,8 @@ dependencies: |
| 125 | google_fonts: ^3.0.1 | 130 | google_fonts: ^3.0.1 |
| 126 | wakelock: ^0.6.1+2 | 131 | wakelock: ^0.6.1+2 |
| 127 | location: ^4.4.0 | 132 | location: ^4.4.0 |
| 128 | - google_maps_flutter: ^2.1.10 | 133 | + # GoogleMap支持库 |
| 134 | + google_maps_flutter: ^2.2.1 | ||
| 129 | http: ^0.13.5 | 135 | http: ^0.13.5 |
| 130 | 136 | ||
| 131 | dependency_overrides: | 137 | dependency_overrides: | ... | ... |
-
Please register or login to post a comment