Commit 57589833e4087e094eef821ce65083033cca6139

Authored by 常守达
1 parent 76a7b3a9

fix(today):UI、loading修改

... ... @@ -6,6 +6,7 @@ import 'package:doublefeel_flutter/app/modules/home/controllers/home_controller.
import 'package:doublefeel_flutter/app/modules/home/controllers/trend/trend_controller.dart';
import 'package:doublefeel_flutter/app/modules/home/widgets/today/friend_select_bottom_sheet.dart';
import 'package:doublefeel_flutter/app/modules/home/widgets/today/no_health_data_page.dart';
import 'package:doublefeel_flutter/app/modules/report_common/models/report_period.dart';
import 'package:doublefeel_flutter/app/routes/app_pages.dart';
import 'package:doublefeel_flutter/core/constants/intent_keys.dart';
import 'package:doublefeel_flutter/core/constants/membership.dart';
... ... @@ -457,7 +458,8 @@ class TodayController extends GetMaterialController {
arguments: getFriendTrendArguments(TrendType.hrv),
);
} else {
Get.find<HomeController>().openTrend(TrendType.hrv);
Get.find<HomeController>().openTrend(TrendType.hrv,
period: ReportPeriod.week, date: selectedDate.value);
}
}
... ... @@ -468,7 +470,8 @@ class TodayController extends GetMaterialController {
arguments: getFriendTrendArguments(TrendType.sleep),
);
} else {
Get.find<HomeController>().openTrend(TrendType.sleep);
Get.find<HomeController>().openTrend(TrendType.sleep,
period: ReportPeriod.day, date: selectedDate.value);
}
}
... ... @@ -479,7 +482,8 @@ class TodayController extends GetMaterialController {
arguments: getFriendTrendArguments(TrendType.activity),
);
} else {
Get.find<HomeController>().openTrend(TrendType.activity);
Get.find<HomeController>().openTrend(TrendType.activity,
period: ReportPeriod.day, date: selectedDate.value);
}
}
... ...
... ... @@ -8,6 +8,7 @@ import 'package:doublefeel_flutter/app/routes/app_pages.dart';
import 'package:doublefeel_flutter/app/utils/dialog_utils.dart';
import 'package:doublefeel_flutter/core/config/app_environment_config.dart';
import 'package:doublefeel_flutter/core/theme/app_theme.dart';
import 'package:doublefeel_flutter/core/util/size_extensions.dart';
import 'package:doublefeel_flutter/data/local/user_preferences_storage.dart';
import 'package:doublefeel_flutter/data/models/local/user_preferences.dart';
import 'package:doublefeel_flutter/data/models/user/user_models.dart';
... ... @@ -460,7 +461,11 @@ class _UnlockPremiumCard extends StatelessWidget {
],
),
),
Image.asset('assets/images/my/bg_my_unlock_vip.png')
Image.asset(
'assets/images/my/bg_my_unlock_vip.png',
width: 149.w,
height: 128.w,
)
],
),
));
... ...
... ... @@ -130,143 +130,135 @@ class TodayTabBody extends StatelessWidget {
parent: ClampingScrollPhysics(),
),
slivers: [
SliverToBoxAdapter(
child: Container(
width: Get.width,
height: Get.width / 375 * (323 + pinnedHeaderHeight),
padding: EdgeInsets.only(bottom: 32),
child: Container(
// margin: EdgeInsets.only(top: pinnedHeaderHeight),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Expanded(
child: Obx(() => Image.asset(
controller.v2StressScore.value?.stateBg() ??
'assets/images/today/bg_stress_state_0.png',
fit: BoxFit.cover,
width: Get.width,
height: Get.width / 375 * 345,
)),
),
Obx(
() => GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
showStressStatusExplanationBottomSheet(context);
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Hi,${controller.stressSubtitle.value}',
textAlign: TextAlign.center,
style: const TextStyle(
color: Color(0xFF78787D),
fontSize: 14,
fontWeight: FontWeight.w500,
),
),
const SizedBox(width: 4),
Image.asset(
'assets/images/common/ic_info.png',
width: 14,
height: 14,
color: const Color(0xFF78787D),
),
],
SliverList(
delegate: SliverChildListDelegate([
Obx(() => controller.isLoadingToday.value
? Container(
width: Get.width,
height: Get.width / 375 * 345,
child: Align(
alignment: Alignment(0.0, 0.5),
child: CircularProgressIndicator()),
)
: Image.asset(
controller.v2StressScore.value!.stateBg(),
fit: BoxFit.cover,
width: Get.width,
height: Get.width / 375 * 345,
)),
Obx(
() => GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
showStressStatusExplanationBottomSheet(context);
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Hi,${controller.stressSubtitle.value}',
textAlign: TextAlign.center,
style: const TextStyle(
color: Color(0xFF78787D),
fontSize: 14,
fontWeight: FontWeight.w500,
),
),
),
Container(
height: 51,
alignment: Alignment.topCenter,
child: Obx(
() => controller.isLoadingToday.value
? CircularProgressIndicator(strokeWidth: 2.5)
: Text(
controller.v2StressScore.value?.stateString() ??
'',
textAlign: TextAlign.center,
style: TextStyle(
color: context.colors.textPrimary,
fontSize: 28,
fontWeight: FontWeight.w500,
),
),
const SizedBox(width: 4),
Image.asset(
'assets/images/common/ic_info.png',
width: 14,
height: 14,
color: const Color(0xFF78787D),
),
),
],
),
),
),
Obx(() => controller.isLoadingToday.value
? SizedBox()
: Text(
controller.v2StressScore.value?.stateString() ?? '',
textAlign: TextAlign.center,
style: TextStyle(
color: context.colors.textPrimary,
fontSize: 28,
fontWeight: FontWeight.w500,
),
)),
Center(
child: Obx(
() => StressProgressBar(
score: controller.v2StressScore.value?.state == 0
? null
: controller.v2StressScore.value?.comprehensiveScore,
),
),
),
SizedBox(
height: 36,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Column(
children: [
Obx(
() => StressProgressBar(
score: controller.v2StressScore.value?.state == 0
? null
: controller.v2StressScore.value?.comprehensiveScore,
() => controller.showHealthDataAuthCardStatus.value != 1
? TodayHealthDataAuthCard(
onAuthorizeTap: () {
controller.onAuthorizeTap();
},
)
: const SizedBox.shrink(),
),
Obx(() {
return Get.find<UserStateService>().isVip
? const SizedBox.shrink()
: GestureDetector(
onTap: () {
ta.track('click_doublefeel_today_status',
properties: {'ita': '会员banner'});
controller.toPremiumDiscoutPage('今日-会员广告');
},
child: PremiumCard(
controller,
));
}),
TodayAdCarousel(controller: controller),
TodayHrvNumberCard(controller: controller),
const SizedBox(height: 12),
TodayHrvChartCard(controller: controller),
const SizedBox(height: 12),
_LatestHrvCard(controller: controller),
if (!controller.isFriend) measureHRVButton(context),
Padding(
padding: const EdgeInsets.symmetric(vertical: 12),
child: Text(
(controller.isFriend
? context.l10n.reportOtherPossessiveTitle(
context.l10n.dailyActions)
: context.l10n.dailyActions),
style: TextStyle(
color: context.colors.textPrimary,
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
),
TodaySleepCard(controller: controller),
TodayActivityCard(controller: controller),
],
),
),
),
),
SliverPadding(
padding: const EdgeInsets.symmetric(horizontal: 16),
sliver: SliverList(
delegate: SliverChildListDelegate([
Obx(
() => controller.showHealthDataAuthCardStatus.value != 1
? TodayHealthDataAuthCard(
onAuthorizeTap: () {
controller.onAuthorizeTap();
},
)
: const SizedBox.shrink(),
),
Obx(() {
return Get.find<UserStateService>().isVip
? const SizedBox.shrink()
: GestureDetector(
onTap: () {
ta.track('click_doublefeel_today_status',
properties: {'ita': '会员banner'});
controller.toPremiumDiscoutPage('今日-会员广告');
},
child: PremiumCard(
controller,
));
}),
TodayAdCarousel(controller: controller),
TodayHrvNumberCard(controller: controller),
const SizedBox(height: 12),
TodayHrvChartCard(controller: controller),
const SizedBox(height: 12),
_LatestHrvCard(controller: controller),
if (!controller.isFriend) measureHRVButton(context),
Padding(
padding: const EdgeInsets.symmetric(vertical: 12),
child: Text(
(controller.isFriend
? context.l10n
.reportOtherPossessiveTitle(context.l10n.dailyActions)
: context.l10n.dailyActions),
style: TextStyle(
color: context.colors.textPrimary,
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
),
TodaySleepCard(controller: controller),
TodayActivityCard(controller: controller),
Container(
alignment: Alignment.center,
margin: EdgeInsets.only(
bottom: 16,
// top: 28,
),
child: ReportBottomSlogan(),
Container(
alignment: Alignment.center,
margin: EdgeInsets.only(
bottom: 16,
// top: 28,
),
]),
),
child: ReportBottomSlogan(),
),
]),
),
],
);
... ...
... ... @@ -15,8 +15,6 @@ class DfTabBar extends StatelessWidget {
static const double height = 56;
static const double bottomMargin = 8;
static const _selectedBgColor = Color(0xFFF3F3F3);
static const _tabIcons = [
'assets/images/tabbar/icon_today.png',
'assets/images/tabbar/icon_trend.png',
... ... @@ -73,10 +71,11 @@ class DfTabBar extends StatelessWidget {
top: 0,
bottom: 0,
width: tabWidth,
child: const DecoratedBox(
child: DecoratedBox(
decoration: BoxDecoration(
color: _selectedBgColor,
borderRadius: BorderRadius.all(Radius.circular(24)),
color: context.colors.backgroundPage,
borderRadius:
const BorderRadius.all(Radius.circular(24)),
),
),
),
... ... @@ -104,7 +103,7 @@ class DfTabBar extends StatelessWidget {
tabLabels[i],
style: TextStyle(
fontSize: 9,
fontWeight: FontWeight.w500,
fontWeight: FontWeight.w800,
color: isSelected
? context.colors.primary
: context.colors.textSecondary,
... ...
... ... @@ -9,6 +9,7 @@ import 'package:doublefeel_flutter/data/models/pay/apple_pay_order_response.dart
import 'package:doublefeel_flutter/data/models/pay/pay_models.dart';
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
import 'package:doublefeel_flutter/pigeon/platform_api.g.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../../routes/app_pages.dart';
... ... @@ -24,6 +25,7 @@ class MembershipDetailController extends GetxController {
final PlatformHostApi _platformHostApi = PlatformHostApi();
final isRestoring = false.obs;
final scrollController = ScrollController();
final isUnlocking = false.obs;
Future<void> unlock() async {
... ... @@ -139,6 +141,12 @@ class MembershipDetailController extends GetxController {
_refreshVipInfo();
}
@override
void onClose() {
scrollController.dispose();
super.onClose();
}
String? _nonEmpty(String? value) {
final trimmed = value?.trim();
if (trimmed == null || trimmed.isEmpty) return null;
... ...
... ... @@ -17,43 +17,58 @@ class MembershipDetailView extends GetView<MembershipDetailController> {
Widget build(BuildContext context) {
final userPrefs = Get.find<UserPreferencesStorage>();
return Scaffold(
appBar: AppBar(
leading: IconButton(
highlightColor: Colors.transparent,
splashColor: Colors.transparent,
padding: EdgeInsets.zero,
onPressed: Get.back,
icon: Image.asset(
'assets/images/common/ic_nav_back.webp',
width: 24,
height: 24,
),
),
actions: [
Padding(
padding: const EdgeInsets.only(right: 20.0),
child: TextButton(
onPressed: controller.isRestoring.value
? null
: controller.restorePurchase,
style: TextButton.styleFrom(
foregroundColor: PurchaseColors.title,
padding: const EdgeInsets.symmetric(horizontal: 16),
textStyle: const TextStyle(fontSize: 14, height: 1.2),
appBar: PreferredSize(
preferredSize: const Size.fromHeight(kToolbarHeight),
child: AnimatedBuilder(
animation: controller.scrollController,
builder: (context, _) {
final opacity = controller.scrollController.hasClients
? (controller.scrollController.offset / 80).clamp(0.0, 1.0)
: 0.0;
return AppBar(
backgroundColor:
context.colors.backgroundPage.withOpacity(opacity),
surfaceTintColor: Colors.transparent,
leading: IconButton(
highlightColor: Colors.transparent,
splashColor: Colors.transparent,
padding: EdgeInsets.zero,
onPressed: Get.back,
icon: Image.asset(
'assets/images/common/ic_nav_back.webp',
width: 24,
height: 24,
),
),
child: controller.isRestoring.value
? const SizedBox(
width: 16,
height: 16,
child: CircularProgressIndicator(strokeWidth: 2),
)
: Text(context.l10n.purchaseRestore),
),
),
],
actions: [
Padding(
padding: const EdgeInsets.only(right: 20.0),
child: TextButton(
onPressed: controller.isRestoring.value
? null
: controller.restorePurchase,
style: TextButton.styleFrom(
foregroundColor: PurchaseColors.title,
padding: const EdgeInsets.symmetric(horizontal: 16),
textStyle: const TextStyle(fontSize: 14, height: 1.2),
),
child: controller.isRestoring.value
? const SizedBox(
width: 16,
height: 16,
child: CircularProgressIndicator(strokeWidth: 2),
)
: Text(context.l10n.purchaseRestore),
),
),
],
);
},
),
),
extendBodyBehindAppBar: true,
body: SingleChildScrollView(
controller: controller.scrollController,
physics: const ClampingScrollPhysics(),
padding: EdgeInsets.only(
bottom: MediaQuery.paddingOf(context).bottom + 16,
... ...