Showing
6 changed files
with
193 additions
and
170 deletions
| @@ -6,6 +6,7 @@ import 'package:doublefeel_flutter/app/modules/home/controllers/home_controller. | @@ -6,6 +6,7 @@ import 'package:doublefeel_flutter/app/modules/home/controllers/home_controller. | ||
| 6 | import 'package:doublefeel_flutter/app/modules/home/controllers/trend/trend_controller.dart'; | 6 | import 'package:doublefeel_flutter/app/modules/home/controllers/trend/trend_controller.dart'; |
| 7 | import 'package:doublefeel_flutter/app/modules/home/widgets/today/friend_select_bottom_sheet.dart'; | 7 | import 'package:doublefeel_flutter/app/modules/home/widgets/today/friend_select_bottom_sheet.dart'; |
| 8 | import 'package:doublefeel_flutter/app/modules/home/widgets/today/no_health_data_page.dart'; | 8 | import 'package:doublefeel_flutter/app/modules/home/widgets/today/no_health_data_page.dart'; |
| 9 | +import 'package:doublefeel_flutter/app/modules/report_common/models/report_period.dart'; | ||
| 9 | import 'package:doublefeel_flutter/app/routes/app_pages.dart'; | 10 | import 'package:doublefeel_flutter/app/routes/app_pages.dart'; |
| 10 | import 'package:doublefeel_flutter/core/constants/intent_keys.dart'; | 11 | import 'package:doublefeel_flutter/core/constants/intent_keys.dart'; |
| 11 | import 'package:doublefeel_flutter/core/constants/membership.dart'; | 12 | import 'package:doublefeel_flutter/core/constants/membership.dart'; |
| @@ -457,7 +458,8 @@ class TodayController extends GetMaterialController { | @@ -457,7 +458,8 @@ class TodayController extends GetMaterialController { | ||
| 457 | arguments: getFriendTrendArguments(TrendType.hrv), | 458 | arguments: getFriendTrendArguments(TrendType.hrv), |
| 458 | ); | 459 | ); |
| 459 | } else { | 460 | } else { |
| 460 | - Get.find<HomeController>().openTrend(TrendType.hrv); | 461 | + Get.find<HomeController>().openTrend(TrendType.hrv, |
| 462 | + period: ReportPeriod.week, date: selectedDate.value); | ||
| 461 | } | 463 | } |
| 462 | } | 464 | } |
| 463 | 465 | ||
| @@ -468,7 +470,8 @@ class TodayController extends GetMaterialController { | @@ -468,7 +470,8 @@ class TodayController extends GetMaterialController { | ||
| 468 | arguments: getFriendTrendArguments(TrendType.sleep), | 470 | arguments: getFriendTrendArguments(TrendType.sleep), |
| 469 | ); | 471 | ); |
| 470 | } else { | 472 | } else { |
| 471 | - Get.find<HomeController>().openTrend(TrendType.sleep); | 473 | + Get.find<HomeController>().openTrend(TrendType.sleep, |
| 474 | + period: ReportPeriod.day, date: selectedDate.value); | ||
| 472 | } | 475 | } |
| 473 | } | 476 | } |
| 474 | 477 | ||
| @@ -479,7 +482,8 @@ class TodayController extends GetMaterialController { | @@ -479,7 +482,8 @@ class TodayController extends GetMaterialController { | ||
| 479 | arguments: getFriendTrendArguments(TrendType.activity), | 482 | arguments: getFriendTrendArguments(TrendType.activity), |
| 480 | ); | 483 | ); |
| 481 | } else { | 484 | } else { |
| 482 | - Get.find<HomeController>().openTrend(TrendType.activity); | 485 | + Get.find<HomeController>().openTrend(TrendType.activity, |
| 486 | + period: ReportPeriod.day, date: selectedDate.value); | ||
| 483 | } | 487 | } |
| 484 | } | 488 | } |
| 485 | 489 |
| @@ -8,6 +8,7 @@ import 'package:doublefeel_flutter/app/routes/app_pages.dart'; | @@ -8,6 +8,7 @@ import 'package:doublefeel_flutter/app/routes/app_pages.dart'; | ||
| 8 | import 'package:doublefeel_flutter/app/utils/dialog_utils.dart'; | 8 | import 'package:doublefeel_flutter/app/utils/dialog_utils.dart'; |
| 9 | import 'package:doublefeel_flutter/core/config/app_environment_config.dart'; | 9 | import 'package:doublefeel_flutter/core/config/app_environment_config.dart'; |
| 10 | import 'package:doublefeel_flutter/core/theme/app_theme.dart'; | 10 | import 'package:doublefeel_flutter/core/theme/app_theme.dart'; |
| 11 | +import 'package:doublefeel_flutter/core/util/size_extensions.dart'; | ||
| 11 | import 'package:doublefeel_flutter/data/local/user_preferences_storage.dart'; | 12 | import 'package:doublefeel_flutter/data/local/user_preferences_storage.dart'; |
| 12 | import 'package:doublefeel_flutter/data/models/local/user_preferences.dart'; | 13 | import 'package:doublefeel_flutter/data/models/local/user_preferences.dart'; |
| 13 | import 'package:doublefeel_flutter/data/models/user/user_models.dart'; | 14 | import 'package:doublefeel_flutter/data/models/user/user_models.dart'; |
| @@ -460,7 +461,11 @@ class _UnlockPremiumCard extends StatelessWidget { | @@ -460,7 +461,11 @@ class _UnlockPremiumCard extends StatelessWidget { | ||
| 460 | ], | 461 | ], |
| 461 | ), | 462 | ), |
| 462 | ), | 463 | ), |
| 463 | - Image.asset('assets/images/my/bg_my_unlock_vip.png') | 464 | + Image.asset( |
| 465 | + 'assets/images/my/bg_my_unlock_vip.png', | ||
| 466 | + width: 149.w, | ||
| 467 | + height: 128.w, | ||
| 468 | + ) | ||
| 464 | ], | 469 | ], |
| 465 | ), | 470 | ), |
| 466 | )); | 471 | )); |
| @@ -130,143 +130,135 @@ class TodayTabBody extends StatelessWidget { | @@ -130,143 +130,135 @@ class TodayTabBody extends StatelessWidget { | ||
| 130 | parent: ClampingScrollPhysics(), | 130 | parent: ClampingScrollPhysics(), |
| 131 | ), | 131 | ), |
| 132 | slivers: [ | 132 | slivers: [ |
| 133 | - SliverToBoxAdapter( | ||
| 134 | - child: Container( | ||
| 135 | - width: Get.width, | ||
| 136 | - height: Get.width / 375 * (323 + pinnedHeaderHeight), | ||
| 137 | - padding: EdgeInsets.only(bottom: 32), | ||
| 138 | - child: Container( | ||
| 139 | - // margin: EdgeInsets.only(top: pinnedHeaderHeight), | ||
| 140 | - child: Column( | ||
| 141 | - mainAxisAlignment: MainAxisAlignment.end, | ||
| 142 | - children: [ | ||
| 143 | - Expanded( | ||
| 144 | - child: Obx(() => Image.asset( | ||
| 145 | - controller.v2StressScore.value?.stateBg() ?? | ||
| 146 | - 'assets/images/today/bg_stress_state_0.png', | ||
| 147 | - fit: BoxFit.cover, | ||
| 148 | - width: Get.width, | ||
| 149 | - height: Get.width / 375 * 345, | ||
| 150 | - )), | ||
| 151 | - ), | ||
| 152 | - Obx( | ||
| 153 | - () => GestureDetector( | ||
| 154 | - behavior: HitTestBehavior.opaque, | ||
| 155 | - onTap: () { | ||
| 156 | - showStressStatusExplanationBottomSheet(context); | ||
| 157 | - }, | ||
| 158 | - child: Row( | ||
| 159 | - mainAxisAlignment: MainAxisAlignment.center, | ||
| 160 | - children: [ | ||
| 161 | - Text( | ||
| 162 | - 'Hi,${controller.stressSubtitle.value}', | ||
| 163 | - textAlign: TextAlign.center, | ||
| 164 | - style: const TextStyle( | ||
| 165 | - color: Color(0xFF78787D), | ||
| 166 | - fontSize: 14, | ||
| 167 | - fontWeight: FontWeight.w500, | ||
| 168 | - ), | ||
| 169 | - ), | ||
| 170 | - const SizedBox(width: 4), | ||
| 171 | - Image.asset( | ||
| 172 | - 'assets/images/common/ic_info.png', | ||
| 173 | - width: 14, | ||
| 174 | - height: 14, | ||
| 175 | - color: const Color(0xFF78787D), | ||
| 176 | - ), | ||
| 177 | - ], | 133 | + SliverList( |
| 134 | + delegate: SliverChildListDelegate([ | ||
| 135 | + Obx(() => controller.isLoadingToday.value | ||
| 136 | + ? Container( | ||
| 137 | + width: Get.width, | ||
| 138 | + height: Get.width / 375 * 345, | ||
| 139 | + child: Align( | ||
| 140 | + alignment: Alignment(0.0, 0.5), | ||
| 141 | + child: CircularProgressIndicator()), | ||
| 142 | + ) | ||
| 143 | + : Image.asset( | ||
| 144 | + controller.v2StressScore.value!.stateBg(), | ||
| 145 | + fit: BoxFit.cover, | ||
| 146 | + width: Get.width, | ||
| 147 | + height: Get.width / 375 * 345, | ||
| 148 | + )), | ||
| 149 | + Obx( | ||
| 150 | + () => GestureDetector( | ||
| 151 | + behavior: HitTestBehavior.opaque, | ||
| 152 | + onTap: () { | ||
| 153 | + showStressStatusExplanationBottomSheet(context); | ||
| 154 | + }, | ||
| 155 | + child: Row( | ||
| 156 | + mainAxisAlignment: MainAxisAlignment.center, | ||
| 157 | + children: [ | ||
| 158 | + Text( | ||
| 159 | + 'Hi,${controller.stressSubtitle.value}', | ||
| 160 | + textAlign: TextAlign.center, | ||
| 161 | + style: const TextStyle( | ||
| 162 | + color: Color(0xFF78787D), | ||
| 163 | + fontSize: 14, | ||
| 164 | + fontWeight: FontWeight.w500, | ||
| 178 | ), | 165 | ), |
| 179 | ), | 166 | ), |
| 180 | - ), | ||
| 181 | - Container( | ||
| 182 | - height: 51, | ||
| 183 | - alignment: Alignment.topCenter, | ||
| 184 | - child: Obx( | ||
| 185 | - () => controller.isLoadingToday.value | ||
| 186 | - ? CircularProgressIndicator(strokeWidth: 2.5) | ||
| 187 | - : Text( | ||
| 188 | - controller.v2StressScore.value?.stateString() ?? | ||
| 189 | - '', | ||
| 190 | - textAlign: TextAlign.center, | ||
| 191 | - style: TextStyle( | ||
| 192 | - color: context.colors.textPrimary, | ||
| 193 | - fontSize: 28, | ||
| 194 | - fontWeight: FontWeight.w500, | ||
| 195 | - ), | ||
| 196 | - ), | 167 | + const SizedBox(width: 4), |
| 168 | + Image.asset( | ||
| 169 | + 'assets/images/common/ic_info.png', | ||
| 170 | + width: 14, | ||
| 171 | + height: 14, | ||
| 172 | + color: const Color(0xFF78787D), | ||
| 197 | ), | 173 | ), |
| 198 | - ), | 174 | + ], |
| 175 | + ), | ||
| 176 | + ), | ||
| 177 | + ), | ||
| 178 | + Obx(() => controller.isLoadingToday.value | ||
| 179 | + ? SizedBox() | ||
| 180 | + : Text( | ||
| 181 | + controller.v2StressScore.value?.stateString() ?? '', | ||
| 182 | + textAlign: TextAlign.center, | ||
| 183 | + style: TextStyle( | ||
| 184 | + color: context.colors.textPrimary, | ||
| 185 | + fontSize: 28, | ||
| 186 | + fontWeight: FontWeight.w500, | ||
| 187 | + ), | ||
| 188 | + )), | ||
| 189 | + Center( | ||
| 190 | + child: Obx( | ||
| 191 | + () => StressProgressBar( | ||
| 192 | + score: controller.v2StressScore.value?.state == 0 | ||
| 193 | + ? null | ||
| 194 | + : controller.v2StressScore.value?.comprehensiveScore, | ||
| 195 | + ), | ||
| 196 | + ), | ||
| 197 | + ), | ||
| 198 | + SizedBox( | ||
| 199 | + height: 36, | ||
| 200 | + ), | ||
| 201 | + Padding( | ||
| 202 | + padding: const EdgeInsets.symmetric(horizontal: 16.0), | ||
| 203 | + child: Column( | ||
| 204 | + children: [ | ||
| 199 | Obx( | 205 | Obx( |
| 200 | - () => StressProgressBar( | ||
| 201 | - score: controller.v2StressScore.value?.state == 0 | ||
| 202 | - ? null | ||
| 203 | - : controller.v2StressScore.value?.comprehensiveScore, | 206 | + () => controller.showHealthDataAuthCardStatus.value != 1 |
| 207 | + ? TodayHealthDataAuthCard( | ||
| 208 | + onAuthorizeTap: () { | ||
| 209 | + controller.onAuthorizeTap(); | ||
| 210 | + }, | ||
| 211 | + ) | ||
| 212 | + : const SizedBox.shrink(), | ||
| 213 | + ), | ||
| 214 | + Obx(() { | ||
| 215 | + return Get.find<UserStateService>().isVip | ||
| 216 | + ? const SizedBox.shrink() | ||
| 217 | + : GestureDetector( | ||
| 218 | + onTap: () { | ||
| 219 | + ta.track('click_doublefeel_today_status', | ||
| 220 | + properties: {'ita': '会员banner'}); | ||
| 221 | + controller.toPremiumDiscoutPage('今日-会员广告'); | ||
| 222 | + }, | ||
| 223 | + child: PremiumCard( | ||
| 224 | + controller, | ||
| 225 | + )); | ||
| 226 | + }), | ||
| 227 | + TodayAdCarousel(controller: controller), | ||
| 228 | + TodayHrvNumberCard(controller: controller), | ||
| 229 | + const SizedBox(height: 12), | ||
| 230 | + TodayHrvChartCard(controller: controller), | ||
| 231 | + const SizedBox(height: 12), | ||
| 232 | + _LatestHrvCard(controller: controller), | ||
| 233 | + if (!controller.isFriend) measureHRVButton(context), | ||
| 234 | + Padding( | ||
| 235 | + padding: const EdgeInsets.symmetric(vertical: 12), | ||
| 236 | + child: Text( | ||
| 237 | + (controller.isFriend | ||
| 238 | + ? context.l10n.reportOtherPossessiveTitle( | ||
| 239 | + context.l10n.dailyActions) | ||
| 240 | + : context.l10n.dailyActions), | ||
| 241 | + style: TextStyle( | ||
| 242 | + color: context.colors.textPrimary, | ||
| 243 | + fontSize: 16, | ||
| 244 | + fontWeight: FontWeight.w600, | ||
| 245 | + ), | ||
| 204 | ), | 246 | ), |
| 205 | ), | 247 | ), |
| 248 | + TodaySleepCard(controller: controller), | ||
| 249 | + TodayActivityCard(controller: controller), | ||
| 206 | ], | 250 | ], |
| 207 | ), | 251 | ), |
| 208 | ), | 252 | ), |
| 209 | - ), | ||
| 210 | - ), | ||
| 211 | - SliverPadding( | ||
| 212 | - padding: const EdgeInsets.symmetric(horizontal: 16), | ||
| 213 | - sliver: SliverList( | ||
| 214 | - delegate: SliverChildListDelegate([ | ||
| 215 | - Obx( | ||
| 216 | - () => controller.showHealthDataAuthCardStatus.value != 1 | ||
| 217 | - ? TodayHealthDataAuthCard( | ||
| 218 | - onAuthorizeTap: () { | ||
| 219 | - controller.onAuthorizeTap(); | ||
| 220 | - }, | ||
| 221 | - ) | ||
| 222 | - : const SizedBox.shrink(), | ||
| 223 | - ), | ||
| 224 | - Obx(() { | ||
| 225 | - return Get.find<UserStateService>().isVip | ||
| 226 | - ? const SizedBox.shrink() | ||
| 227 | - : GestureDetector( | ||
| 228 | - onTap: () { | ||
| 229 | - ta.track('click_doublefeel_today_status', | ||
| 230 | - properties: {'ita': '会员banner'}); | ||
| 231 | - controller.toPremiumDiscoutPage('今日-会员广告'); | ||
| 232 | - }, | ||
| 233 | - child: PremiumCard( | ||
| 234 | - controller, | ||
| 235 | - )); | ||
| 236 | - }), | ||
| 237 | - TodayAdCarousel(controller: controller), | ||
| 238 | - TodayHrvNumberCard(controller: controller), | ||
| 239 | - const SizedBox(height: 12), | ||
| 240 | - TodayHrvChartCard(controller: controller), | ||
| 241 | - const SizedBox(height: 12), | ||
| 242 | - _LatestHrvCard(controller: controller), | ||
| 243 | - if (!controller.isFriend) measureHRVButton(context), | ||
| 244 | - Padding( | ||
| 245 | - padding: const EdgeInsets.symmetric(vertical: 12), | ||
| 246 | - child: Text( | ||
| 247 | - (controller.isFriend | ||
| 248 | - ? context.l10n | ||
| 249 | - .reportOtherPossessiveTitle(context.l10n.dailyActions) | ||
| 250 | - : context.l10n.dailyActions), | ||
| 251 | - style: TextStyle( | ||
| 252 | - color: context.colors.textPrimary, | ||
| 253 | - fontSize: 16, | ||
| 254 | - fontWeight: FontWeight.w600, | ||
| 255 | - ), | ||
| 256 | - ), | ||
| 257 | - ), | ||
| 258 | - TodaySleepCard(controller: controller), | ||
| 259 | - TodayActivityCard(controller: controller), | ||
| 260 | - Container( | ||
| 261 | - alignment: Alignment.center, | ||
| 262 | - margin: EdgeInsets.only( | ||
| 263 | - bottom: 16, | ||
| 264 | - // top: 28, | ||
| 265 | - ), | ||
| 266 | - child: ReportBottomSlogan(), | 253 | + Container( |
| 254 | + alignment: Alignment.center, | ||
| 255 | + margin: EdgeInsets.only( | ||
| 256 | + bottom: 16, | ||
| 257 | + // top: 28, | ||
| 267 | ), | 258 | ), |
| 268 | - ]), | ||
| 269 | - ), | 259 | + child: ReportBottomSlogan(), |
| 260 | + ), | ||
| 261 | + ]), | ||
| 270 | ), | 262 | ), |
| 271 | ], | 263 | ], |
| 272 | ); | 264 | ); |
| @@ -15,8 +15,6 @@ class DfTabBar extends StatelessWidget { | @@ -15,8 +15,6 @@ class DfTabBar extends StatelessWidget { | ||
| 15 | static const double height = 56; | 15 | static const double height = 56; |
| 16 | static const double bottomMargin = 8; | 16 | static const double bottomMargin = 8; |
| 17 | 17 | ||
| 18 | - static const _selectedBgColor = Color(0xFFF3F3F3); | ||
| 19 | - | ||
| 20 | static const _tabIcons = [ | 18 | static const _tabIcons = [ |
| 21 | 'assets/images/tabbar/icon_today.png', | 19 | 'assets/images/tabbar/icon_today.png', |
| 22 | 'assets/images/tabbar/icon_trend.png', | 20 | 'assets/images/tabbar/icon_trend.png', |
| @@ -73,10 +71,11 @@ class DfTabBar extends StatelessWidget { | @@ -73,10 +71,11 @@ class DfTabBar extends StatelessWidget { | ||
| 73 | top: 0, | 71 | top: 0, |
| 74 | bottom: 0, | 72 | bottom: 0, |
| 75 | width: tabWidth, | 73 | width: tabWidth, |
| 76 | - child: const DecoratedBox( | 74 | + child: DecoratedBox( |
| 77 | decoration: BoxDecoration( | 75 | decoration: BoxDecoration( |
| 78 | - color: _selectedBgColor, | ||
| 79 | - borderRadius: BorderRadius.all(Radius.circular(24)), | 76 | + color: context.colors.backgroundPage, |
| 77 | + borderRadius: | ||
| 78 | + const BorderRadius.all(Radius.circular(24)), | ||
| 80 | ), | 79 | ), |
| 81 | ), | 80 | ), |
| 82 | ), | 81 | ), |
| @@ -104,7 +103,7 @@ class DfTabBar extends StatelessWidget { | @@ -104,7 +103,7 @@ class DfTabBar extends StatelessWidget { | ||
| 104 | tabLabels[i], | 103 | tabLabels[i], |
| 105 | style: TextStyle( | 104 | style: TextStyle( |
| 106 | fontSize: 9, | 105 | fontSize: 9, |
| 107 | - fontWeight: FontWeight.w500, | 106 | + fontWeight: FontWeight.w800, |
| 108 | color: isSelected | 107 | color: isSelected |
| 109 | ? context.colors.primary | 108 | ? context.colors.primary |
| 110 | : context.colors.textSecondary, | 109 | : context.colors.textSecondary, |
| @@ -9,6 +9,7 @@ import 'package:doublefeel_flutter/data/models/pay/apple_pay_order_response.dart | @@ -9,6 +9,7 @@ import 'package:doublefeel_flutter/data/models/pay/apple_pay_order_response.dart | ||
| 9 | import 'package:doublefeel_flutter/data/models/pay/pay_models.dart'; | 9 | import 'package:doublefeel_flutter/data/models/pay/pay_models.dart'; |
| 10 | import 'package:doublefeel_flutter/l10n/l10n_extensions.dart'; | 10 | import 'package:doublefeel_flutter/l10n/l10n_extensions.dart'; |
| 11 | import 'package:doublefeel_flutter/pigeon/platform_api.g.dart'; | 11 | import 'package:doublefeel_flutter/pigeon/platform_api.g.dart'; |
| 12 | +import 'package:flutter/material.dart'; | ||
| 12 | import 'package:get/get.dart'; | 13 | import 'package:get/get.dart'; |
| 13 | 14 | ||
| 14 | import '../../../routes/app_pages.dart'; | 15 | import '../../../routes/app_pages.dart'; |
| @@ -24,6 +25,7 @@ class MembershipDetailController extends GetxController { | @@ -24,6 +25,7 @@ class MembershipDetailController extends GetxController { | ||
| 24 | final PlatformHostApi _platformHostApi = PlatformHostApi(); | 25 | final PlatformHostApi _platformHostApi = PlatformHostApi(); |
| 25 | 26 | ||
| 26 | final isRestoring = false.obs; | 27 | final isRestoring = false.obs; |
| 28 | + final scrollController = ScrollController(); | ||
| 27 | 29 | ||
| 28 | final isUnlocking = false.obs; | 30 | final isUnlocking = false.obs; |
| 29 | Future<void> unlock() async { | 31 | Future<void> unlock() async { |
| @@ -139,6 +141,12 @@ class MembershipDetailController extends GetxController { | @@ -139,6 +141,12 @@ class MembershipDetailController extends GetxController { | ||
| 139 | _refreshVipInfo(); | 141 | _refreshVipInfo(); |
| 140 | } | 142 | } |
| 141 | 143 | ||
| 144 | + @override | ||
| 145 | + void onClose() { | ||
| 146 | + scrollController.dispose(); | ||
| 147 | + super.onClose(); | ||
| 148 | + } | ||
| 149 | + | ||
| 142 | String? _nonEmpty(String? value) { | 150 | String? _nonEmpty(String? value) { |
| 143 | final trimmed = value?.trim(); | 151 | final trimmed = value?.trim(); |
| 144 | if (trimmed == null || trimmed.isEmpty) return null; | 152 | if (trimmed == null || trimmed.isEmpty) return null; |
| @@ -17,43 +17,58 @@ class MembershipDetailView extends GetView<MembershipDetailController> { | @@ -17,43 +17,58 @@ class MembershipDetailView extends GetView<MembershipDetailController> { | ||
| 17 | Widget build(BuildContext context) { | 17 | Widget build(BuildContext context) { |
| 18 | final userPrefs = Get.find<UserPreferencesStorage>(); | 18 | final userPrefs = Get.find<UserPreferencesStorage>(); |
| 19 | return Scaffold( | 19 | return Scaffold( |
| 20 | - appBar: AppBar( | ||
| 21 | - leading: IconButton( | ||
| 22 | - highlightColor: Colors.transparent, | ||
| 23 | - splashColor: Colors.transparent, | ||
| 24 | - padding: EdgeInsets.zero, | ||
| 25 | - onPressed: Get.back, | ||
| 26 | - icon: Image.asset( | ||
| 27 | - 'assets/images/common/ic_nav_back.webp', | ||
| 28 | - width: 24, | ||
| 29 | - height: 24, | ||
| 30 | - ), | ||
| 31 | - ), | ||
| 32 | - actions: [ | ||
| 33 | - Padding( | ||
| 34 | - padding: const EdgeInsets.only(right: 20.0), | ||
| 35 | - child: TextButton( | ||
| 36 | - onPressed: controller.isRestoring.value | ||
| 37 | - ? null | ||
| 38 | - : controller.restorePurchase, | ||
| 39 | - style: TextButton.styleFrom( | ||
| 40 | - foregroundColor: PurchaseColors.title, | ||
| 41 | - padding: const EdgeInsets.symmetric(horizontal: 16), | ||
| 42 | - textStyle: const TextStyle(fontSize: 14, height: 1.2), | 20 | + appBar: PreferredSize( |
| 21 | + preferredSize: const Size.fromHeight(kToolbarHeight), | ||
| 22 | + child: AnimatedBuilder( | ||
| 23 | + animation: controller.scrollController, | ||
| 24 | + builder: (context, _) { | ||
| 25 | + final opacity = controller.scrollController.hasClients | ||
| 26 | + ? (controller.scrollController.offset / 80).clamp(0.0, 1.0) | ||
| 27 | + : 0.0; | ||
| 28 | + return AppBar( | ||
| 29 | + backgroundColor: | ||
| 30 | + context.colors.backgroundPage.withOpacity(opacity), | ||
| 31 | + surfaceTintColor: Colors.transparent, | ||
| 32 | + leading: IconButton( | ||
| 33 | + highlightColor: Colors.transparent, | ||
| 34 | + splashColor: Colors.transparent, | ||
| 35 | + padding: EdgeInsets.zero, | ||
| 36 | + onPressed: Get.back, | ||
| 37 | + icon: Image.asset( | ||
| 38 | + 'assets/images/common/ic_nav_back.webp', | ||
| 39 | + width: 24, | ||
| 40 | + height: 24, | ||
| 41 | + ), | ||
| 43 | ), | 42 | ), |
| 44 | - child: controller.isRestoring.value | ||
| 45 | - ? const SizedBox( | ||
| 46 | - width: 16, | ||
| 47 | - height: 16, | ||
| 48 | - child: CircularProgressIndicator(strokeWidth: 2), | ||
| 49 | - ) | ||
| 50 | - : Text(context.l10n.purchaseRestore), | ||
| 51 | - ), | ||
| 52 | - ), | ||
| 53 | - ], | 43 | + actions: [ |
| 44 | + Padding( | ||
| 45 | + padding: const EdgeInsets.only(right: 20.0), | ||
| 46 | + child: TextButton( | ||
| 47 | + onPressed: controller.isRestoring.value | ||
| 48 | + ? null | ||
| 49 | + : controller.restorePurchase, | ||
| 50 | + style: TextButton.styleFrom( | ||
| 51 | + foregroundColor: PurchaseColors.title, | ||
| 52 | + padding: const EdgeInsets.symmetric(horizontal: 16), | ||
| 53 | + textStyle: const TextStyle(fontSize: 14, height: 1.2), | ||
| 54 | + ), | ||
| 55 | + child: controller.isRestoring.value | ||
| 56 | + ? const SizedBox( | ||
| 57 | + width: 16, | ||
| 58 | + height: 16, | ||
| 59 | + child: CircularProgressIndicator(strokeWidth: 2), | ||
| 60 | + ) | ||
| 61 | + : Text(context.l10n.purchaseRestore), | ||
| 62 | + ), | ||
| 63 | + ), | ||
| 64 | + ], | ||
| 65 | + ); | ||
| 66 | + }, | ||
| 67 | + ), | ||
| 54 | ), | 68 | ), |
| 55 | extendBodyBehindAppBar: true, | 69 | extendBodyBehindAppBar: true, |
| 56 | body: SingleChildScrollView( | 70 | body: SingleChildScrollView( |
| 71 | + controller: controller.scrollController, | ||
| 57 | physics: const ClampingScrollPhysics(), | 72 | physics: const ClampingScrollPhysics(), |
| 58 | padding: EdgeInsets.only( | 73 | padding: EdgeInsets.only( |
| 59 | bottom: MediaQuery.paddingOf(context).bottom + 16, | 74 | bottom: MediaQuery.paddingOf(context).bottom + 16, |
-
Please register or login to post a comment