feat: shop is change
This commit is contained in:
@@ -19,6 +19,23 @@ class AppConfig {
|
|||||||
defaultValue: '',
|
defaultValue: '',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// App ID تپسل (از پنلِ تپسل). تا زمانی که تنظیم نشود، تبلیغِ ویدیویی-جایزهای
|
||||||
|
/// («سکه رایگان») نمایش داده نمیشود. با `--dart-define=TAPSELL_APP_ID=...`
|
||||||
|
/// یا مقداردهیِ پیشفرض اینجا فعال میشود.
|
||||||
|
static const String tapsellAppId = String.fromEnvironment(
|
||||||
|
'TAPSELL_APP_ID',
|
||||||
|
defaultValue: '',
|
||||||
|
);
|
||||||
|
|
||||||
|
/// شناسهی جایگاهِ (zone) تبلیغِ ویدیویی-جایزهای تپسل.
|
||||||
|
static const String tapsellRewardedZoneId = String.fromEnvironment(
|
||||||
|
'TAPSELL_REWARDED_ZONE',
|
||||||
|
defaultValue: '',
|
||||||
|
);
|
||||||
|
|
||||||
|
/// آیا تبلیغِ جایزهای فعال است؟ فقط وقتی App ID تپسل موجود باشد.
|
||||||
|
static bool get adsEnabled => tapsellAppId.isNotEmpty;
|
||||||
|
|
||||||
/// آدرس پایهی سرور.
|
/// آدرس پایهی سرور.
|
||||||
/// - موبایل واقعی روی همان Wi-Fi: IP محلی مک (پیشفرض فعلی).
|
/// - موبایل واقعی روی همان Wi-Fi: IP محلی مک (پیشفرض فعلی).
|
||||||
/// - امولاتور اندروید: `--dart-define=BASE_URL=http://10.0.2.2:8080`
|
/// - امولاتور اندروید: `--dart-define=BASE_URL=http://10.0.2.2:8080`
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ class ShopScreen extends StatelessWidget {
|
|||||||
gradient: const LinearGradient(
|
gradient: const LinearGradient(
|
||||||
begin: Alignment.topCenter,
|
begin: Alignment.topCenter,
|
||||||
end: Alignment.bottomCenter,
|
end: Alignment.bottomCenter,
|
||||||
colors: [Color(0xFF4A0C16), Color(0xFF2A0710)],
|
colors: [AppColors.lapisMid, AppColors.lapisLo],
|
||||||
),
|
),
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
@@ -155,9 +155,9 @@ class _ShopTabs extends StatelessWidget {
|
|||||||
gradient: LinearGradient(
|
gradient: LinearGradient(
|
||||||
begin: Alignment.topCenter,
|
begin: Alignment.topCenter,
|
||||||
end: Alignment.bottomCenter,
|
end: Alignment.bottomCenter,
|
||||||
colors: [AppColors.panel, AppColors.lapis],
|
colors: [AppColors.lapis, AppColors.suitDark],
|
||||||
),
|
),
|
||||||
borderRadius: BorderRadius.vertical(bottom: Radius.circular(12)),
|
borderRadius: BorderRadius.all(Radius.circular(12)),
|
||||||
),
|
),
|
||||||
indicatorSize: TabBarIndicatorSize.tab,
|
indicatorSize: TabBarIndicatorSize.tab,
|
||||||
labelColor: AppColors.gold,
|
labelColor: AppColors.gold,
|
||||||
@@ -188,6 +188,8 @@ class _CoinsTab extends StatelessWidget {
|
|||||||
return _grid(
|
return _grid(
|
||||||
note: 'با داشتن اشتراک VIP در هر خرید ۱۰٪ سکه اضافه هدیه میگیرید.',
|
note: 'با داشتن اشتراک VIP در هر خرید ۱۰٪ سکه اضافه هدیه میگیرید.',
|
||||||
children: [
|
children: [
|
||||||
|
// «سکه رایگان» (تبلیغِ ویدیویی-جایزهای) فقط وقتی App ID تپسل تنظیم شده باشد.
|
||||||
|
if (AppConfig.adsEnabled)
|
||||||
_ItemCard(
|
_ItemCard(
|
||||||
title: 'سکه رایگان',
|
title: 'سکه رایگان',
|
||||||
glowColor: AppColors.successDark,
|
glowColor: AppColors.successDark,
|
||||||
@@ -210,8 +212,9 @@ class _CoinsTab extends StatelessWidget {
|
|||||||
action: _PriceButton(
|
action: _PriceButton(
|
||||||
label: '${p.priceToman} تومان',
|
label: '${p.priceToman} تومان',
|
||||||
onTap:
|
onTap:
|
||||||
() =>
|
() => context.read<ShopBloc>().add(
|
||||||
context.read<ShopBloc>().add(PurchaseEvent('coin', p.id, sku: p.sku)),
|
PurchaseEvent('coin', p.id, sku: p.sku),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -291,8 +294,9 @@ class _VipTab extends StatelessWidget {
|
|||||||
action: _PriceButton(
|
action: _PriceButton(
|
||||||
label: '${p.priceToman} تومان',
|
label: '${p.priceToman} تومان',
|
||||||
onTap:
|
onTap:
|
||||||
() =>
|
() => context.read<ShopBloc>().add(
|
||||||
context.read<ShopBloc>().add(PurchaseEvent('vip', p.id, sku: p.sku)),
|
PurchaseEvent('vip', p.id, sku: p.sku),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -366,15 +370,15 @@ class _CarpetsTabState extends State<_CarpetsTab> {
|
|||||||
|
|
||||||
Future<void> _act(Carpet c, {required bool buy}) async {
|
Future<void> _act(Carpet c, {required bool buy}) async {
|
||||||
setState(() => _busy = c.id);
|
setState(() => _busy = c.id);
|
||||||
final err = buy ? await _api.buyCarpet(c.id) : await _api.selectCarpet(c.id);
|
final err =
|
||||||
|
buy ? await _api.buyCarpet(c.id) : await _api.selectCarpet(c.id);
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
setState(() => _busy = null);
|
setState(() => _busy = null);
|
||||||
if (err == null) {
|
if (err == null) {
|
||||||
context.read<WalletBloc>().add(LoadWalletEvent());
|
context.read<WalletBloc>().add(LoadWalletEvent());
|
||||||
_reload();
|
_reload();
|
||||||
} else {
|
} else {
|
||||||
ScaffoldMessenger.of(context)
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(err)));
|
||||||
.showSnackBar(SnackBar(content: Text(err)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -385,12 +389,15 @@ class _CarpetsTabState extends State<_CarpetsTab> {
|
|||||||
builder: (context, snap) {
|
builder: (context, snap) {
|
||||||
if (snap.connectionState != ConnectionState.done) {
|
if (snap.connectionState != ConnectionState.done) {
|
||||||
return const Center(
|
return const Center(
|
||||||
child: CircularProgressIndicator(color: AppColors.gold));
|
child: CircularProgressIndicator(color: AppColors.gold),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (!snap.hasData) {
|
if (!snap.hasData) {
|
||||||
return Center(
|
return Center(
|
||||||
child: TextButton(
|
child: TextButton(
|
||||||
onPressed: _reload, child: const Text('تلاش مجدد')),
|
onPressed: _reload,
|
||||||
|
child: const Text('تلاش مجدد'),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
final cat = snap.data!;
|
final cat = snap.data!;
|
||||||
@@ -435,20 +442,25 @@ class _CarpetCard extends StatelessWidget {
|
|||||||
gradient: const LinearGradient(
|
gradient: const LinearGradient(
|
||||||
begin: Alignment.topCenter,
|
begin: Alignment.topCenter,
|
||||||
end: Alignment.bottomCenter,
|
end: Alignment.bottomCenter,
|
||||||
colors: [Color(0xFF6E1322), Color(0xFF3A0A12)],
|
colors: [AppColors.lapisHi, AppColors.lapisLo],
|
||||||
),
|
),
|
||||||
borderRadius: BorderRadius.circular(14),
|
borderRadius: BorderRadius.circular(14),
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color: selected ? AppColors.gold : AppColors.goldDark,
|
color: selected ? AppColors.gold : AppColors.goldDark,
|
||||||
width: selected ? 2 : 1.4),
|
width: selected ? 2 : 1.4,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Text(c.title,
|
Text(
|
||||||
|
c.title,
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: AppColors.gold, fontWeight: FontWeight.bold)),
|
color: AppColors.gold,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
const SizedBox(height: 6),
|
const SizedBox(height: 6),
|
||||||
Expanded(child: _preview(c)),
|
Expanded(child: _preview(c)),
|
||||||
const SizedBox(height: 6),
|
const SizedBox(height: 6),
|
||||||
@@ -461,37 +473,51 @@ class _CarpetCard extends StatelessWidget {
|
|||||||
Widget _preview(Carpet c) {
|
Widget _preview(Carpet c) {
|
||||||
final frame = ClipRRect(
|
final frame = ClipRRect(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
child: c.isClassic
|
child:
|
||||||
|
c.isClassic
|
||||||
? Container(
|
? Container(
|
||||||
color: const Color(0xFF0E3614),
|
color: const Color(0xFF0E3614),
|
||||||
child: const Center(
|
child: const Center(
|
||||||
child: Icon(Icons.casino, color: AppColors.gold, size: 36)),
|
child: Icon(Icons.casino, color: AppColors.gold, size: 36),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
: Image.network(
|
: Image.network(
|
||||||
c.imageUrl,
|
c.imageUrl,
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
errorBuilder: (_, __, ___) => Container(
|
errorBuilder:
|
||||||
color: const Color(0xFF2A0710),
|
(_, __, ___) => Container(
|
||||||
child: const Icon(Icons.image_not_supported,
|
color: AppColors.lapisLo,
|
||||||
color: AppColors.goldDark)),
|
child: const Icon(
|
||||||
|
Icons.image_not_supported,
|
||||||
|
color: AppColors.goldDark,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return Stack(fit: StackFit.expand, children: [
|
return Stack(
|
||||||
|
fit: StackFit.expand,
|
||||||
|
children: [
|
||||||
frame,
|
frame,
|
||||||
if (c.vip && !c.owned)
|
if (c.vip && !c.owned)
|
||||||
const Positioned(
|
const Positioned(
|
||||||
top: 4,
|
top: 4,
|
||||||
left: 4,
|
left: 4,
|
||||||
child: Chip(
|
child: Chip(
|
||||||
label: Text('VIP',
|
label: Text(
|
||||||
|
'VIP',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Colors.white, fontSize: 10, fontWeight: FontWeight.bold)),
|
color: Colors.white,
|
||||||
|
fontSize: 10,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
backgroundColor: AppColors.goldDark,
|
backgroundColor: AppColors.goldDark,
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
]);
|
],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _action(Carpet c) {
|
Widget _action(Carpet c) {
|
||||||
@@ -567,7 +593,7 @@ class _ItemCard extends StatelessWidget {
|
|||||||
gradient: const LinearGradient(
|
gradient: const LinearGradient(
|
||||||
begin: Alignment.topCenter,
|
begin: Alignment.topCenter,
|
||||||
end: Alignment.bottomCenter,
|
end: Alignment.bottomCenter,
|
||||||
colors: [Color(0xFF6E1322), AppColors.bg],
|
colors: [AppColors.lapisHi, AppColors.lapisLo],
|
||||||
),
|
),
|
||||||
borderRadius: BorderRadius.circular(14),
|
borderRadius: BorderRadius.circular(14),
|
||||||
border: Border.all(color: AppColors.gold, width: 1.6),
|
border: Border.all(color: AppColors.gold, width: 1.6),
|
||||||
@@ -740,7 +766,10 @@ class _PriceButton extends StatelessWidget {
|
|||||||
? const [Color(0xFF555555), Color(0xFF333333)]
|
? const [Color(0xFF555555), Color(0xFF333333)]
|
||||||
: green
|
: green
|
||||||
? const [AppColors.success, AppColors.successDark]
|
? const [AppColors.success, AppColors.successDark]
|
||||||
: const [Color(0xFFD83A4A), Color(0xFF8E0E1B)];
|
: const [
|
||||||
|
AppColors.accent,
|
||||||
|
Color(0xFF7A1019),
|
||||||
|
]; // شنگرفِ ایرانی (همرنگِ تم)
|
||||||
return Opacity(
|
return Opacity(
|
||||||
opacity: disabled ? 0.85 : 1,
|
opacity: disabled ? 0.85 : 1,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ class _VipPackageTile extends StatelessWidget {
|
|||||||
gradient: const LinearGradient(
|
gradient: const LinearGradient(
|
||||||
begin: Alignment.topCenter,
|
begin: Alignment.topCenter,
|
||||||
end: Alignment.bottomCenter,
|
end: Alignment.bottomCenter,
|
||||||
colors: [Color(0xFF6E1322), AppColors.bg],
|
colors: [AppColors.lapisHi, AppColors.lapisLo],
|
||||||
),
|
),
|
||||||
borderRadius: BorderRadius.circular(14),
|
borderRadius: BorderRadius.circular(14),
|
||||||
border: Border.all(color: AppColors.gold, width: 1.4),
|
border: Border.all(color: AppColors.gold, width: 1.4),
|
||||||
|
|||||||
Reference in New Issue
Block a user