fix: preview store item effects
This commit is contained in:
parent
2684fd4673
commit
a800a0f941
@ -1,17 +1,10 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:yumi/app_localizations.dart';
|
||||
import 'package:yumi/ui_kit/components/sc_compontent.dart';
|
||||
import 'package:yumi/ui_kit/components/sc_tts.dart';
|
||||
import 'package:yumi/app/constants/sc_global_config.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:yumi/ui_kit/components/sc_page_list.dart';
|
||||
import 'package:yumi/shared/tools/sc_loading_manager.dart';
|
||||
import 'package:yumi/shared/data_sources/sources/repositories/sc_store_repository_imp.dart';
|
||||
import 'package:yumi/shared/business_logic/models/res/store_list_res.dart';
|
||||
import 'package:yumi/services/auth/user_profile_manager.dart';
|
||||
import 'package:yumi/ui_kit/widgets/store/props_store_chatbox_detail_dialog.dart';
|
||||
import 'package:yumi/ui_kit/widgets/store/store_bag_page_helpers.dart';
|
||||
|
||||
@ -20,8 +13,10 @@ import '../../../shared/data_sources/models/enum/sc_props_type.dart';
|
||||
|
||||
///聊天气泡框
|
||||
class StoreChatboxPage extends SCPageList {
|
||||
const StoreChatboxPage({super.key});
|
||||
|
||||
@override
|
||||
_StoreChatboxPageState createState() => _StoreChatboxPageState();
|
||||
SCPageListState createState() => _StoreChatboxPageState();
|
||||
}
|
||||
|
||||
class _StoreChatboxPageState
|
||||
@ -41,7 +36,7 @@ class _StoreChatboxPageState
|
||||
crossAxisCount: gridViewCount,
|
||||
mainAxisSpacing: 12.w,
|
||||
crossAxisSpacing: 12.w,
|
||||
childAspectRatio: 0.78,
|
||||
childAspectRatio: 0.88,
|
||||
);
|
||||
loadData(1);
|
||||
}
|
||||
@ -59,100 +54,15 @@ class _StoreChatboxPageState
|
||||
|
||||
@override
|
||||
Widget buildItem(StoreListResBean res) {
|
||||
return GestureDetector(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color:
|
||||
res.isSelecte
|
||||
? const Color(0xff18F2B1).withValues(alpha: 0.1)
|
||||
: SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemBackgroundColor(),
|
||||
border: Border.all(
|
||||
color:
|
||||
res.isSelecte
|
||||
? SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemSelectedBorderColor()
|
||||
: SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemUnselectedBorderColor(),
|
||||
width: 1.w,
|
||||
),
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.w)),
|
||||
),
|
||||
child: Stack(
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
SizedBox(height: 10.w),
|
||||
netImage(
|
||||
url: res.res.propsResources?.cover ?? "",
|
||||
height: 45.w,
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
SizedBox(height: 10.w),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(width: 10.w),
|
||||
Expanded(
|
||||
child: Text.rich(
|
||||
textAlign: TextAlign.center,
|
||||
TextSpan(
|
||||
children: [
|
||||
WidgetSpan(
|
||||
alignment: PlaceholderAlignment.middle,
|
||||
child: Image.asset(
|
||||
SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemGoldIcon(),
|
||||
width: 22.w,
|
||||
),
|
||||
),
|
||||
TextSpan(text: " "),
|
||||
disCount < 1
|
||||
? TextSpan(
|
||||
text: "${res.res.propsPrices![0].amount}",
|
||||
style: TextStyle(
|
||||
fontSize: 12.sp,
|
||||
color:
|
||||
SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemPriceTextColor(),
|
||||
fontWeight: FontWeight.w600,
|
||||
decoration: TextDecoration.lineThrough,
|
||||
),
|
||||
)
|
||||
: TextSpan(),
|
||||
disCount < 1 ? TextSpan(text: " ") : TextSpan(),
|
||||
TextSpan(
|
||||
text:
|
||||
"${((res.res.propsPrices![0].amount ?? 0) * disCount).toInt()}/${res.res.propsPrices![0].days} ${SCAppLocalizations.of(context)!.day}",
|
||||
style: TextStyle(
|
||||
fontSize: 12.sp,
|
||||
color:
|
||||
SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemPriceTextColor(),
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
strutStyle: StrutStyle(
|
||||
height: 1.3, // 行高倍数
|
||||
fontWeight: FontWeight.w500,
|
||||
forceStrutHeight: true, // 强制应用行高
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 10.w),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
_selectItem(res);
|
||||
_showDetail(res.res);
|
||||
},
|
||||
return SCStoreGridItemCard(
|
||||
res: res.res,
|
||||
selected: res.isSelecte,
|
||||
discount: disCount,
|
||||
coverHeight: 45.w,
|
||||
previewWidth: 88.w,
|
||||
previewHeight: 58.w,
|
||||
onPreviewTap: () => _togglePreview(res),
|
||||
onDetailsTap: () => _showDetail(res.res),
|
||||
);
|
||||
}
|
||||
|
||||
@ -191,39 +101,14 @@ class _StoreChatboxPageState
|
||||
);
|
||||
}
|
||||
|
||||
void _selectItem(StoreListResBean res) {
|
||||
void _togglePreview(StoreListResBean res) {
|
||||
final shouldSelect = !res.isSelecte;
|
||||
for (var value in items) {
|
||||
value.isSelecte = false;
|
||||
}
|
||||
res.isSelecte = true;
|
||||
res.isSelecte = shouldSelect;
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
void _buy(StoreListResBean res) {
|
||||
if (res.res.propsPrices!.isEmpty) {
|
||||
return;
|
||||
}
|
||||
SCLoadingManager.show();
|
||||
num days = res.res.propsPrices![0].days ?? 0;
|
||||
SCStoreRepositoryImp()
|
||||
.storePurchasing(
|
||||
res.res.id ?? "",
|
||||
SCPropsType.CHAT_BUBBLE.name,
|
||||
SCCurrencyType.GOLD.name,
|
||||
"$days",
|
||||
)
|
||||
.then((value) {
|
||||
SCTts.show(SCAppLocalizations.of(context)!.purchaseIsSuccessful);
|
||||
Provider.of<SocialChatUserProfileManager>(
|
||||
context,
|
||||
listen: false,
|
||||
).updateBalance(value);
|
||||
SCLoadingManager.hide();
|
||||
})
|
||||
.catchError((e) {
|
||||
SCLoadingManager.hide();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class StoreListResBean {
|
||||
|
||||
@ -1,13 +1,10 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:yumi/app/constants/sc_global_config.dart';
|
||||
import 'package:yumi/app_localizations.dart';
|
||||
import 'package:yumi/shared/business_logic/models/res/store_list_res.dart';
|
||||
import 'package:yumi/shared/data_sources/models/enum/sc_currency_type.dart';
|
||||
import 'package:yumi/shared/data_sources/models/enum/sc_props_type.dart';
|
||||
import 'package:yumi/shared/data_sources/sources/repositories/sc_store_repository_imp.dart';
|
||||
import 'package:yumi/ui_kit/components/sc_compontent.dart';
|
||||
import 'package:yumi/ui_kit/components/sc_page_list.dart';
|
||||
import 'package:yumi/ui_kit/widgets/store/props_store_data_card_detail_dialog.dart';
|
||||
import 'package:yumi/ui_kit/widgets/store/store_bag_page_helpers.dart';
|
||||
@ -35,7 +32,7 @@ class StoreDataCardPageState
|
||||
crossAxisCount: gridViewCount,
|
||||
mainAxisSpacing: 12.w,
|
||||
crossAxisSpacing: 12.w,
|
||||
childAspectRatio: 0.78,
|
||||
childAspectRatio: 0.88,
|
||||
);
|
||||
loadData(1);
|
||||
}
|
||||
@ -54,101 +51,20 @@ class StoreDataCardPageState
|
||||
@override
|
||||
Widget buildItem(StoreDataCardListResBean item) {
|
||||
final res = item;
|
||||
final prices = res.res.propsPrices ?? const <PropsPrices>[];
|
||||
final firstPrice = prices.isNotEmpty ? prices.first : null;
|
||||
return GestureDetector(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color:
|
||||
res.isSelecte
|
||||
? const Color(0xff18F2B1).withValues(alpha: 0.1)
|
||||
: SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemBackgroundColor(),
|
||||
border: Border.all(
|
||||
color:
|
||||
res.isSelecte
|
||||
? SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemSelectedBorderColor()
|
||||
: SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemUnselectedBorderColor(),
|
||||
width: 1.w,
|
||||
),
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.w)),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(height: 10.w),
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(6.w),
|
||||
child: netImage(
|
||||
url: res.res.propsResources?.cover ?? "",
|
||||
width: 72.w,
|
||||
height: 50.w,
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 12.w),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(width: 10.w),
|
||||
Expanded(
|
||||
child: Text.rich(
|
||||
textAlign: TextAlign.center,
|
||||
TextSpan(
|
||||
children: [
|
||||
WidgetSpan(
|
||||
alignment: PlaceholderAlignment.middle,
|
||||
child: Image.asset(
|
||||
SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemGoldIcon(),
|
||||
width: 22.w,
|
||||
),
|
||||
),
|
||||
const TextSpan(text: " "),
|
||||
if (disCount < 1)
|
||||
TextSpan(
|
||||
text: "${firstPrice?.amount ?? 0}",
|
||||
style: TextStyle(
|
||||
fontSize: 12.sp,
|
||||
color:
|
||||
SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemPriceTextColor(),
|
||||
fontWeight: FontWeight.w600,
|
||||
decoration: TextDecoration.lineThrough,
|
||||
),
|
||||
),
|
||||
if (disCount < 1) const TextSpan(text: " "),
|
||||
TextSpan(
|
||||
text:
|
||||
"${((firstPrice?.amount ?? 0) * disCount).toInt()}/${firstPrice?.days ?? 0} ${SCAppLocalizations.of(context)!.day}",
|
||||
style: TextStyle(
|
||||
fontSize: 12.sp,
|
||||
color:
|
||||
SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemPriceTextColor(),
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
strutStyle: const StrutStyle(
|
||||
height: 1.3,
|
||||
fontWeight: FontWeight.w500,
|
||||
forceStrutHeight: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 10.w),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
_selectItem(res);
|
||||
_showDetail(res.res);
|
||||
},
|
||||
return SCStoreGridItemCard(
|
||||
res: res.res,
|
||||
selected: res.isSelecte,
|
||||
discount: disCount,
|
||||
previewKind: SCStoreItemPreviewKind.dataCard,
|
||||
coverWidth: 72.w,
|
||||
coverHeight: 50.w,
|
||||
previewWidth: 88.w,
|
||||
previewHeight: 58.w,
|
||||
coverFit: BoxFit.cover,
|
||||
previewFit: BoxFit.cover,
|
||||
coverBorderRadius: BorderRadius.circular(6.w),
|
||||
onPreviewTap: () => _togglePreview(res),
|
||||
onDetailsTap: () => _showDetail(res.res),
|
||||
);
|
||||
}
|
||||
|
||||
@ -184,11 +100,12 @@ class StoreDataCardPageState
|
||||
);
|
||||
}
|
||||
|
||||
void _selectItem(StoreDataCardListResBean res) {
|
||||
void _togglePreview(StoreDataCardListResBean res) {
|
||||
final shouldSelect = !res.isSelecte;
|
||||
for (final value in items) {
|
||||
value.isSelecte = false;
|
||||
}
|
||||
res.isSelecte = true;
|
||||
res.isSelecte = shouldSelect;
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,16 +1,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:yumi/app_localizations.dart';
|
||||
import 'package:yumi/ui_kit/components/sc_compontent.dart';
|
||||
import 'package:yumi/ui_kit/components/sc_tts.dart';
|
||||
import 'package:yumi/app/constants/sc_global_config.dart';
|
||||
import 'package:yumi/shared/tools/sc_loading_manager.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:yumi/ui_kit/components/sc_page_list.dart';
|
||||
import 'package:yumi/shared/data_sources/sources/repositories/sc_store_repository_imp.dart';
|
||||
import 'package:yumi/shared/business_logic/models/res/store_list_res.dart';
|
||||
import 'package:yumi/services/auth/user_profile_manager.dart';
|
||||
import 'package:yumi/ui_kit/widgets/store/props_store_headdress_detail_dialog.dart';
|
||||
import 'package:yumi/ui_kit/widgets/store/store_bag_page_helpers.dart';
|
||||
|
||||
@ -19,8 +12,10 @@ import '../../../shared/data_sources/models/enum/sc_props_type.dart';
|
||||
|
||||
///头饰
|
||||
class StoreHeaddressPage extends SCPageList {
|
||||
const StoreHeaddressPage({super.key});
|
||||
|
||||
@override
|
||||
_StoreHeaddressPageState createState() => _StoreHeaddressPageState();
|
||||
SCPageListState createState() => _StoreHeaddressPageState();
|
||||
}
|
||||
|
||||
class _StoreHeaddressPageState
|
||||
@ -40,7 +35,7 @@ class _StoreHeaddressPageState
|
||||
crossAxisCount: gridViewCount,
|
||||
mainAxisSpacing: 12.w,
|
||||
crossAxisSpacing: 12.w,
|
||||
childAspectRatio: 0.78,
|
||||
childAspectRatio: 0.88,
|
||||
);
|
||||
loadData(1);
|
||||
}
|
||||
@ -58,100 +53,13 @@ class _StoreHeaddressPageState
|
||||
|
||||
@override
|
||||
Widget buildItem(StoreListResBean res) {
|
||||
return GestureDetector(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color:
|
||||
res.isSelecte
|
||||
? const Color(0xff18F2B1).withValues(alpha: 0.1)
|
||||
: SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemBackgroundColor(),
|
||||
border: Border.all(
|
||||
color:
|
||||
res.isSelecte
|
||||
? SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemSelectedBorderColor()
|
||||
: SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemUnselectedBorderColor(),
|
||||
width: 1.w,
|
||||
),
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.w)),
|
||||
),
|
||||
child: Stack(
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
SizedBox(height: 10.w),
|
||||
netImage(
|
||||
url: res.res.propsResources?.cover ?? "",
|
||||
width: 55.w,
|
||||
height: 55.w,
|
||||
),
|
||||
SizedBox(height: 10.w),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(width: 10.w),
|
||||
Expanded(
|
||||
child: Text.rich(
|
||||
textAlign: TextAlign.center,
|
||||
TextSpan(
|
||||
children: [
|
||||
WidgetSpan(
|
||||
alignment: PlaceholderAlignment.middle,
|
||||
child: Image.asset(
|
||||
SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemGoldIcon(),
|
||||
width: 22.w,
|
||||
),
|
||||
),
|
||||
TextSpan(text: " "),
|
||||
disCount < 1
|
||||
? TextSpan(
|
||||
text: "${res.res.propsPrices![0].amount}",
|
||||
style: TextStyle(
|
||||
fontSize: 12.sp,
|
||||
color:
|
||||
SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemPriceTextColor(),
|
||||
fontWeight: FontWeight.w600,
|
||||
decoration: TextDecoration.lineThrough,
|
||||
),
|
||||
)
|
||||
: TextSpan(),
|
||||
disCount < 1 ? TextSpan(text: " ") : TextSpan(),
|
||||
TextSpan(
|
||||
text:
|
||||
"${((res.res.propsPrices![0].amount ?? 0) * disCount).toInt()}/${res.res.propsPrices![0].days} ${SCAppLocalizations.of(context)!.day}",
|
||||
style: TextStyle(
|
||||
fontSize: 12.sp,
|
||||
color:
|
||||
SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemPriceTextColor(),
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
strutStyle: StrutStyle(
|
||||
height: 1.3, // 行高倍数
|
||||
fontWeight: FontWeight.w500,
|
||||
forceStrutHeight: true, // 强制应用行高
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 10.w),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
_selectItem(res);
|
||||
_showDetail(res.res);
|
||||
},
|
||||
return SCStoreGridItemCard(
|
||||
res: res.res,
|
||||
selected: res.isSelecte,
|
||||
discount: disCount,
|
||||
previewKind: SCStoreItemPreviewKind.avatarFrame,
|
||||
onPreviewTap: () => _togglePreview(res),
|
||||
onDetailsTap: () => _showDetail(res.res),
|
||||
);
|
||||
}
|
||||
|
||||
@ -190,39 +98,14 @@ class _StoreHeaddressPageState
|
||||
);
|
||||
}
|
||||
|
||||
void _selectItem(StoreListResBean res) {
|
||||
void _togglePreview(StoreListResBean res) {
|
||||
final shouldSelect = !res.isSelecte;
|
||||
for (var value in items) {
|
||||
value.isSelecte = false;
|
||||
}
|
||||
res.isSelecte = true;
|
||||
res.isSelecte = shouldSelect;
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
void _buy(StoreListResBean res) {
|
||||
if (res.res.propsPrices!.isEmpty) {
|
||||
return;
|
||||
}
|
||||
SCLoadingManager.show();
|
||||
num days = res.res.propsPrices![0].days ?? 0;
|
||||
SCStoreRepositoryImp()
|
||||
.storePurchasing(
|
||||
res.res.id ?? "",
|
||||
SCPropsType.AVATAR_FRAME.name,
|
||||
SCCurrencyType.GOLD.name,
|
||||
"$days",
|
||||
)
|
||||
.then((value) {
|
||||
SCTts.show(SCAppLocalizations.of(context)!.purchaseIsSuccessful);
|
||||
Provider.of<SocialChatUserProfileManager>(
|
||||
context,
|
||||
listen: false,
|
||||
).updateBalance(value);
|
||||
SCLoadingManager.hide();
|
||||
})
|
||||
.catchError((e) {
|
||||
SCLoadingManager.hide();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class StoreListResBean {
|
||||
|
||||
@ -1,10 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:yumi/app_localizations.dart';
|
||||
import 'package:yumi/ui_kit/components/sc_compontent.dart';
|
||||
import 'package:yumi/ui_kit/components/sc_page_list.dart';
|
||||
import 'package:yumi/app/constants/sc_global_config.dart';
|
||||
import 'package:yumi/shared/data_sources/sources/repositories/sc_store_repository_imp.dart';
|
||||
import 'package:yumi/shared/business_logic/models/res/store_list_res.dart';
|
||||
import 'package:yumi/ui_kit/widgets/store/props_store_mountains_detail_dialog.dart';
|
||||
@ -16,10 +13,10 @@ import '../../../shared/data_sources/models/enum/sc_props_type.dart';
|
||||
|
||||
///坐骑
|
||||
class StoreMountainsPage extends SCPageList {
|
||||
StoreMountainsPage();
|
||||
const StoreMountainsPage({super.key});
|
||||
|
||||
@override
|
||||
_StoreMountainsPageState createState() => _StoreMountainsPageState();
|
||||
SCPageListState createState() => _StoreMountainsPageState();
|
||||
}
|
||||
|
||||
class _StoreMountainsPageState
|
||||
@ -39,16 +36,11 @@ class _StoreMountainsPageState
|
||||
crossAxisCount: gridViewCount,
|
||||
mainAxisSpacing: 12.w,
|
||||
crossAxisSpacing: 12.w,
|
||||
childAspectRatio: 0.78,
|
||||
childAspectRatio: 0.88,
|
||||
);
|
||||
loadData(1);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
@ -62,100 +54,12 @@ class _StoreMountainsPageState
|
||||
|
||||
@override
|
||||
Widget buildItem(StoreListResBean res) {
|
||||
return GestureDetector(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color:
|
||||
res.isSelecte
|
||||
? const Color(0xff18F2B1).withValues(alpha: 0.1)
|
||||
: SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemBackgroundColor(),
|
||||
border: Border.all(
|
||||
color:
|
||||
res.isSelecte
|
||||
? SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemSelectedBorderColor()
|
||||
: SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemUnselectedBorderColor(),
|
||||
width: 1.w,
|
||||
),
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.w)),
|
||||
),
|
||||
child: Stack(
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
SizedBox(height: 10.w),
|
||||
netImage(
|
||||
url: res.res.propsResources?.cover ?? "",
|
||||
width: 55.w,
|
||||
height: 55.w,
|
||||
),
|
||||
SizedBox(height: 10.w),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(width: 10.w),
|
||||
Expanded(
|
||||
child: Text.rich(
|
||||
textAlign: TextAlign.center,
|
||||
TextSpan(
|
||||
children: [
|
||||
WidgetSpan(
|
||||
alignment: PlaceholderAlignment.middle,
|
||||
child: Image.asset(
|
||||
SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemGoldIcon(),
|
||||
width: 22.w,
|
||||
),
|
||||
),
|
||||
TextSpan(text: " "),
|
||||
disCount < 1
|
||||
? TextSpan(
|
||||
text: "${res.res.propsPrices![0].amount}",
|
||||
style: TextStyle(
|
||||
fontSize: 12.sp,
|
||||
color:
|
||||
SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemPriceTextColor(),
|
||||
fontWeight: FontWeight.w600,
|
||||
decoration: TextDecoration.lineThrough,
|
||||
),
|
||||
)
|
||||
: TextSpan(),
|
||||
disCount < 1 ? TextSpan(text: " ") : TextSpan(),
|
||||
TextSpan(
|
||||
text:
|
||||
"${((res.res.propsPrices![0].amount ?? 0) * disCount).toInt()}/${res.res.propsPrices![0].days} ${SCAppLocalizations.of(context)!.day}",
|
||||
style: TextStyle(
|
||||
fontSize: 12.sp,
|
||||
color:
|
||||
SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemPriceTextColor(),
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
strutStyle: StrutStyle(
|
||||
height: 1.3, // 行高倍数
|
||||
fontWeight: FontWeight.w500,
|
||||
forceStrutHeight: true, // 强制应用行高
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 10.w),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
_selectItem(res);
|
||||
_showDetail(res.res);
|
||||
},
|
||||
return SCStoreGridItemCard(
|
||||
res: res.res,
|
||||
selected: res.isSelecte,
|
||||
discount: disCount,
|
||||
onPreviewTap: () => _togglePreview(res),
|
||||
onDetailsTap: () => _showDetail(res.res),
|
||||
);
|
||||
}
|
||||
|
||||
@ -194,11 +98,12 @@ class _StoreMountainsPageState
|
||||
);
|
||||
}
|
||||
|
||||
void _selectItem(StoreListResBean res) {
|
||||
void _togglePreview(StoreListResBean res) {
|
||||
final shouldSelect = !res.isSelecte;
|
||||
for (var value in items) {
|
||||
value.isSelecte = false;
|
||||
}
|
||||
res.isSelecte = true;
|
||||
res.isSelecte = shouldSelect;
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,16 +1,10 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:yumi/app_localizations.dart';
|
||||
import 'package:yumi/ui_kit/components/sc_compontent.dart';
|
||||
import 'package:yumi/ui_kit/components/sc_page_list.dart';
|
||||
import 'package:yumi/ui_kit/components/sc_tts.dart';
|
||||
import 'package:yumi/app/constants/sc_global_config.dart';
|
||||
import 'package:yumi/shared/data_sources/sources/repositories/sc_store_repository_imp.dart';
|
||||
import 'package:yumi/shared/business_logic/models/res/store_list_res.dart';
|
||||
import 'package:yumi/services/auth/user_profile_manager.dart';
|
||||
import 'package:yumi/ui_kit/widgets/store/props_store_theme_detail_dialog.dart';
|
||||
import 'package:yumi/ui_kit/widgets/store/store_bag_page_helpers.dart';
|
||||
import 'package:yumi/modules/store/headdress/store_headdress_page.dart';
|
||||
@ -20,10 +14,10 @@ import '../../../shared/data_sources/models/enum/sc_props_type.dart';
|
||||
|
||||
///房间主题
|
||||
class StoreThemePage extends SCPageList {
|
||||
StoreThemePage();
|
||||
const StoreThemePage({super.key});
|
||||
|
||||
@override
|
||||
_StoreThemePagePageState createState() => _StoreThemePagePageState();
|
||||
SCPageListState createState() => _StoreThemePagePageState();
|
||||
}
|
||||
|
||||
class _StoreThemePagePageState
|
||||
@ -43,7 +37,7 @@ class _StoreThemePagePageState
|
||||
crossAxisCount: gridViewCount,
|
||||
mainAxisSpacing: 12.w,
|
||||
crossAxisSpacing: 12.w,
|
||||
childAspectRatio: 0.78,
|
||||
childAspectRatio: 0.88,
|
||||
);
|
||||
loadData(1);
|
||||
}
|
||||
@ -61,101 +55,13 @@ class _StoreThemePagePageState
|
||||
|
||||
@override
|
||||
Widget buildItem(StoreListResBean res) {
|
||||
return GestureDetector(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color:
|
||||
res.isSelecte
|
||||
? const Color(0xff18F2B1).withValues(alpha: 0.1)
|
||||
: SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemBackgroundColor(),
|
||||
border: Border.all(
|
||||
color:
|
||||
res.isSelecte
|
||||
? SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemSelectedBorderColor()
|
||||
: SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemUnselectedBorderColor(),
|
||||
width: 1.w,
|
||||
),
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.w)),
|
||||
),
|
||||
child: Stack(
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
SizedBox(height: 10.w),
|
||||
netImage(
|
||||
url: res.res.propsResources?.cover ?? "",
|
||||
width: 55.w,
|
||||
height: 55.w,
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.w)),
|
||||
),
|
||||
SizedBox(height: 10.w),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(width: 10.w),
|
||||
Expanded(
|
||||
child: Text.rich(
|
||||
textAlign: TextAlign.center,
|
||||
TextSpan(
|
||||
children: [
|
||||
WidgetSpan(
|
||||
alignment: PlaceholderAlignment.middle,
|
||||
child: Image.asset(
|
||||
SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemGoldIcon(),
|
||||
width: 22.w,
|
||||
),
|
||||
),
|
||||
TextSpan(text: " "),
|
||||
disCount < 1
|
||||
? TextSpan(
|
||||
text: "${res.res.propsPrices![0].amount}",
|
||||
style: TextStyle(
|
||||
fontSize: 12.sp,
|
||||
color:
|
||||
SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemPriceTextColor(),
|
||||
fontWeight: FontWeight.w600,
|
||||
decoration: TextDecoration.lineThrough,
|
||||
),
|
||||
)
|
||||
: TextSpan(),
|
||||
disCount < 1 ? TextSpan(text: " ") : TextSpan(),
|
||||
TextSpan(
|
||||
text:
|
||||
"${((res.res.propsPrices![0].amount ?? 0) * disCount).toInt()}/${res.res.propsPrices![0].days} ${SCAppLocalizations.of(context)!.day}",
|
||||
style: TextStyle(
|
||||
fontSize: 12.sp,
|
||||
color:
|
||||
SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemPriceTextColor(),
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
strutStyle: StrutStyle(
|
||||
height: 1.3, // 行高倍数
|
||||
fontWeight: FontWeight.w500,
|
||||
forceStrutHeight: true, // 强制应用行高
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 10.w),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
_selectItem(res);
|
||||
_showDetail(res.res);
|
||||
},
|
||||
return SCStoreGridItemCard(
|
||||
res: res.res,
|
||||
selected: res.isSelecte,
|
||||
discount: disCount,
|
||||
coverBorderRadius: BorderRadius.all(Radius.circular(8.w)),
|
||||
onPreviewTap: () => _togglePreview(res),
|
||||
onDetailsTap: () => _showDetail(res.res),
|
||||
);
|
||||
}
|
||||
|
||||
@ -194,34 +100,12 @@ class _StoreThemePagePageState
|
||||
}
|
||||
}
|
||||
|
||||
void _selectItem(StoreListResBean res) {
|
||||
void _togglePreview(StoreListResBean res) {
|
||||
final shouldSelect = !res.isSelecte;
|
||||
for (var value in items) {
|
||||
value.isSelecte = false;
|
||||
}
|
||||
res.isSelecte = true;
|
||||
res.isSelecte = shouldSelect;
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
void _buy(StoreListResBean res) {
|
||||
num days = 0;
|
||||
if (res.res.propsPrices!.length > 1) {
|
||||
days = res.res.propsPrices![1].days ?? 0;
|
||||
} else {
|
||||
days = res.res.propsPrices![0].days ?? 0;
|
||||
}
|
||||
SCStoreRepositoryImp()
|
||||
.storePurchasing(
|
||||
res.res.id ?? "",
|
||||
SCPropsType.THEME.name,
|
||||
SCCurrencyType.GOLD.name,
|
||||
"$days",
|
||||
)
|
||||
.then((value) {
|
||||
SCTts.show(SCAppLocalizations.of(context)!.purchaseIsSuccessful);
|
||||
Provider.of<SocialChatUserProfileManager>(
|
||||
context,
|
||||
listen: false,
|
||||
).updateBalance(value);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,12 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:yumi/app/constants/sc_global_config.dart';
|
||||
import 'package:yumi/app_localizations.dart';
|
||||
import 'package:yumi/shared/business_logic/models/res/store_list_res.dart';
|
||||
import 'package:yumi/shared/data_sources/sources/local/user_manager.dart';
|
||||
import 'package:yumi/ui_kit/components/sc_compontent.dart';
|
||||
import 'package:yumi/ui_kit/components/text/sc_text.dart';
|
||||
import 'package:yumi/ui_kit/widgets/props/sc_data_card_resource_view.dart';
|
||||
|
||||
const Duration _kStoreBagSkeletonAnimationDuration = Duration(
|
||||
milliseconds: 1450,
|
||||
@ -11,6 +17,8 @@ const Color _kStoreBagSkeletonBoneBase = Color(0xFF2B5C53);
|
||||
const Color _kStoreBagSkeletonBoneHighlight = Color(0xFF5F8177);
|
||||
const Color _kStoreBagSkeletonBorder = Color(0x66D8B57B);
|
||||
|
||||
enum SCStoreItemPreviewKind { resource, avatarFrame, dataCard }
|
||||
|
||||
Widget buildStoreBagItemTitle(
|
||||
String content, {
|
||||
required double fontSize,
|
||||
@ -86,7 +94,7 @@ class SCStoreGridSkeleton extends StatelessWidget {
|
||||
crossAxisCount: 3,
|
||||
mainAxisSpacing: 12.w,
|
||||
crossAxisSpacing: 12.w,
|
||||
childAspectRatio: 0.78,
|
||||
childAspectRatio: 0.88,
|
||||
),
|
||||
itemCount: itemCount,
|
||||
itemBuilder: (context, index) => _buildStoreCardSkeleton(progress),
|
||||
@ -95,6 +103,228 @@ class SCStoreGridSkeleton extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class SCStoreGridItemCard extends StatelessWidget {
|
||||
const SCStoreGridItemCard({
|
||||
super.key,
|
||||
required this.res,
|
||||
required this.selected,
|
||||
required this.discount,
|
||||
required this.onPreviewTap,
|
||||
required this.onDetailsTap,
|
||||
this.previewKind = SCStoreItemPreviewKind.resource,
|
||||
this.coverWidth,
|
||||
this.coverHeight,
|
||||
this.previewWidth,
|
||||
this.previewHeight,
|
||||
this.coverFit = BoxFit.contain,
|
||||
this.previewFit = BoxFit.contain,
|
||||
this.coverBorderRadius,
|
||||
});
|
||||
|
||||
final StoreListRes res;
|
||||
final bool selected;
|
||||
final double discount;
|
||||
final VoidCallback onPreviewTap;
|
||||
final VoidCallback onDetailsTap;
|
||||
final SCStoreItemPreviewKind previewKind;
|
||||
final double? coverWidth;
|
||||
final double? coverHeight;
|
||||
final double? previewWidth;
|
||||
final double? previewHeight;
|
||||
final BoxFit coverFit;
|
||||
final BoxFit previewFit;
|
||||
final BorderRadius? coverBorderRadius;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final firstPrice =
|
||||
(res.propsPrices?.isNotEmpty ?? false) ? res.propsPrices!.first : null;
|
||||
final amount = ((firstPrice?.amount ?? 0) * discount).toInt();
|
||||
final tagText = _buildDurationTag(context, firstPrice?.days);
|
||||
|
||||
return GestureDetector(
|
||||
onTap: onDetailsTap,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color:
|
||||
selected
|
||||
? const Color(0xff18F2B1).withValues(alpha: 0.1)
|
||||
: SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemBackgroundColor(),
|
||||
border: Border.all(
|
||||
color:
|
||||
selected
|
||||
? SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemSelectedBorderColor()
|
||||
: SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemUnselectedBorderColor(),
|
||||
width: 1.w,
|
||||
),
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.w)),
|
||||
),
|
||||
child: Stack(
|
||||
children: [
|
||||
PositionedDirectional(
|
||||
top: 6.w,
|
||||
start: 6.w,
|
||||
child: _buildDurationBadge(tagText),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(6.w, 16.w, 6.w, 8.w),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
_buildPreviewTapArea(),
|
||||
SizedBox(height: 8.w),
|
||||
_buildPriceRow(amount, firstPrice),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildPreviewTapArea() {
|
||||
return GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: onPreviewTap,
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
height:
|
||||
previewHeight ??
|
||||
coverHeight ??
|
||||
(previewKind == SCStoreItemPreviewKind.avatarFrame ? 64.w : 62.w),
|
||||
child: Center(child: selected ? _buildPreview() : _buildCover()),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildCover() {
|
||||
Widget child = netImage(
|
||||
url: res.propsResources?.cover ?? "",
|
||||
width: coverWidth ?? 58.w,
|
||||
height: coverHeight ?? 58.w,
|
||||
fit: coverFit,
|
||||
);
|
||||
if (coverBorderRadius != null) {
|
||||
child = ClipRRect(borderRadius: coverBorderRadius!, child: child);
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
Widget _buildPreview() {
|
||||
switch (previewKind) {
|
||||
case SCStoreItemPreviewKind.avatarFrame:
|
||||
return head(
|
||||
url: AccountStorage().getCurrentUser()?.userProfile?.userAvatar ?? "",
|
||||
width: previewWidth ?? 64.w,
|
||||
height: previewHeight ?? 64.w,
|
||||
headdress: res.propsResources?.sourceUrl,
|
||||
headdressCover: res.propsResources?.cover,
|
||||
);
|
||||
case SCStoreItemPreviewKind.dataCard:
|
||||
return ClipRRect(
|
||||
borderRadius: BorderRadius.circular(6.w),
|
||||
child: SizedBox(
|
||||
width: previewWidth ?? 88.w,
|
||||
height: previewHeight ?? 58.w,
|
||||
child: SCDataCardResourceView(
|
||||
resource: res.propsResources,
|
||||
fit: previewFit,
|
||||
),
|
||||
),
|
||||
);
|
||||
case SCStoreItemPreviewKind.resource:
|
||||
return SizedBox(
|
||||
width: previewWidth ?? 72.w,
|
||||
height: previewHeight ?? 62.w,
|
||||
child: SCDataCardResourceView(
|
||||
resource: res.propsResources,
|
||||
fit: previewFit,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildPriceRow(int amount, PropsPrices? firstPrice) {
|
||||
return SizedBox(
|
||||
width: double.infinity,
|
||||
height: 22.w,
|
||||
child: FittedBox(
|
||||
fit: BoxFit.scaleDown,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Image.asset(
|
||||
SCGlobalConfig.businessLogicStrategy.getStoreItemGoldIcon(),
|
||||
width: 18.w,
|
||||
height: 18.w,
|
||||
),
|
||||
SizedBox(width: 4.w),
|
||||
if (discount < 1) ...[
|
||||
text(
|
||||
"${firstPrice?.amount ?? 0}",
|
||||
fontSize: 12.sp,
|
||||
textColor:
|
||||
SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemPriceTextColor(),
|
||||
fontWeight: FontWeight.w600,
|
||||
decoration: TextDecoration.lineThrough,
|
||||
),
|
||||
SizedBox(width: 4.w),
|
||||
],
|
||||
text(
|
||||
"$amount",
|
||||
fontSize: 13.sp,
|
||||
textColor:
|
||||
SCGlobalConfig.businessLogicStrategy
|
||||
.getStoreItemPriceTextColor(),
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildDurationBadge(String tagText) {
|
||||
if (tagText.isEmpty) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
return Container(
|
||||
constraints: BoxConstraints(maxWidth: 58.w),
|
||||
padding: EdgeInsets.symmetric(horizontal: 6.w, vertical: 2.w),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xff18F2B1).withValues(alpha: 0.16),
|
||||
borderRadius: BorderRadius.circular(4.w),
|
||||
border: Border.all(
|
||||
color: const Color(0xff18F2B1).withValues(alpha: 0.28),
|
||||
width: 0.5.w,
|
||||
),
|
||||
),
|
||||
child: text(
|
||||
tagText,
|
||||
fontSize: 9.sp,
|
||||
textColor:
|
||||
SCGlobalConfig.businessLogicStrategy.getStoreItemPriceTextColor(),
|
||||
fontWeight: FontWeight.w600,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String _buildDurationTag(BuildContext context, num? days) {
|
||||
if (days == null) {
|
||||
return "";
|
||||
}
|
||||
final normalizedDays = days % 1 == 0 ? days.toInt().toString() : "$days";
|
||||
return "$normalizedDays ${SCAppLocalizations.of(context)!.day}";
|
||||
}
|
||||
}
|
||||
|
||||
class SCBagGridSkeleton extends StatelessWidget {
|
||||
const SCBagGridSkeleton({
|
||||
super.key,
|
||||
@ -130,9 +360,18 @@ Widget _buildStoreCardSkeleton(double progress) {
|
||||
return DecoratedBox(
|
||||
decoration: _buildStoreBagShellDecoration(radius: 8.w),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10.w, vertical: 10.w),
|
||||
padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 8.w),
|
||||
child: Column(
|
||||
children: [
|
||||
Align(
|
||||
alignment: AlignmentDirectional.centerStart,
|
||||
child: _buildStoreBagSkeletonBone(
|
||||
progress,
|
||||
width: 42.w,
|
||||
height: 14.w,
|
||||
borderRadius: BorderRadius.circular(4.w),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 2.w),
|
||||
_buildStoreBagSkeletonBone(
|
||||
progress,
|
||||
@ -140,14 +379,7 @@ Widget _buildStoreCardSkeleton(double progress) {
|
||||
height: 55.w,
|
||||
borderRadius: BorderRadius.circular(12.w),
|
||||
),
|
||||
SizedBox(height: 10.w),
|
||||
_buildStoreBagSkeletonBone(
|
||||
progress,
|
||||
width: double.infinity,
|
||||
height: 12.w,
|
||||
borderRadius: BorderRadius.circular(999.w),
|
||||
),
|
||||
SizedBox(height: 10.w),
|
||||
SizedBox(height: 8.w),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
@ -166,13 +398,6 @@ Widget _buildStoreCardSkeleton(double progress) {
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 6.w),
|
||||
_buildStoreBagSkeletonBone(
|
||||
progress,
|
||||
width: 48.w,
|
||||
height: 11.w,
|
||||
borderRadius: BorderRadius.circular(999.w),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user