diff --git a/lib/core/config.dart b/lib/core/config.dart index 651ad94..999a9da 100644 --- a/lib/core/config.dart +++ b/lib/core/config.dart @@ -19,6 +19,23 @@ class AppConfig { 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 محلی مک (پیش‌فرض فعلی). /// - امولاتور اندروید: `--dart-define=BASE_URL=http://10.0.2.2:8080` diff --git a/lib/feature/shop/presentation/screen/shop_screen.dart b/lib/feature/shop/presentation/screen/shop_screen.dart index 1205331..80670be 100644 --- a/lib/feature/shop/presentation/screen/shop_screen.dart +++ b/lib/feature/shop/presentation/screen/shop_screen.dart @@ -54,7 +54,7 @@ class ShopScreen extends StatelessWidget { gradient: const LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, - colors: [Color(0xFF4A0C16), Color(0xFF2A0710)], + colors: [AppColors.lapisMid, AppColors.lapisLo], ), borderRadius: BorderRadius.circular(16), border: Border.all( @@ -155,9 +155,9 @@ class _ShopTabs extends StatelessWidget { gradient: LinearGradient( begin: Alignment.topCenter, 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, labelColor: AppColors.gold, @@ -188,17 +188,19 @@ class _CoinsTab extends StatelessWidget { return _grid( note: 'با داشتن اشتراک VIP در هر خرید ۱۰٪ سکه اضافه هدیه می‌گیرید.', children: [ - _ItemCard( - title: 'سکه رایگان', - glowColor: AppColors.successDark, - icon: Icons.card_giftcard, - subtitle: 'با دیدن تبلیغ', - action: _PriceButton( - label: 'رایگان', - green: true, - onTap: () => context.read().add(AdRewardEvent()), + // «سکه رایگان» (تبلیغِ ویدیویی-جایزه‌ای) فقط وقتی App ID تپسل تنظیم شده باشد. + if (AppConfig.adsEnabled) + _ItemCard( + title: 'سکه رایگان', + glowColor: AppColors.successDark, + icon: Icons.card_giftcard, + subtitle: 'با دیدن تبلیغ', + action: _PriceButton( + label: 'رایگان', + green: true, + onTap: () => context.read().add(AdRewardEvent()), + ), ), - ), for (final p in packages) _ItemCard( title: p.title, @@ -210,8 +212,9 @@ class _CoinsTab extends StatelessWidget { action: _PriceButton( label: '${p.priceToman} تومان', onTap: - () => - context.read().add(PurchaseEvent('coin', p.id, sku: p.sku)), + () => context.read().add( + PurchaseEvent('coin', p.id, sku: p.sku), + ), ), ), ], @@ -291,8 +294,9 @@ class _VipTab extends StatelessWidget { action: _PriceButton( label: '${p.priceToman} تومان', onTap: - () => - context.read().add(PurchaseEvent('vip', p.id, sku: p.sku)), + () => context.read().add( + PurchaseEvent('vip', p.id, sku: p.sku), + ), ), ), ], @@ -361,20 +365,20 @@ class _CarpetsTabState extends State<_CarpetsTab> { } void _reload() => setState(() { - _future = _api.getCarpets(); - }); + _future = _api.getCarpets(); + }); Future _act(Carpet c, {required bool buy}) async { 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; setState(() => _busy = null); if (err == null) { context.read().add(LoadWalletEvent()); _reload(); } else { - ScaffoldMessenger.of(context) - .showSnackBar(SnackBar(content: Text(err))); + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(err))); } } @@ -385,12 +389,15 @@ class _CarpetsTabState extends State<_CarpetsTab> { builder: (context, snap) { if (snap.connectionState != ConnectionState.done) { return const Center( - child: CircularProgressIndicator(color: AppColors.gold)); + child: CircularProgressIndicator(color: AppColors.gold), + ); } if (!snap.hasData) { return Center( child: TextButton( - onPressed: _reload, child: const Text('تلاش مجدد')), + onPressed: _reload, + child: const Text('تلاش مجدد'), + ), ); } final cat = snap.data!; @@ -435,20 +442,25 @@ class _CarpetCard extends StatelessWidget { gradient: const LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, - colors: [Color(0xFF6E1322), Color(0xFF3A0A12)], + colors: [AppColors.lapisHi, AppColors.lapisLo], ), borderRadius: BorderRadius.circular(14), border: Border.all( - color: selected ? AppColors.gold : AppColors.goldDark, - width: selected ? 2 : 1.4), + color: selected ? AppColors.gold : AppColors.goldDark, + width: selected ? 2 : 1.4, + ), ), child: Column( children: [ - Text(c.title, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: const TextStyle( - color: AppColors.gold, fontWeight: FontWeight.bold)), + Text( + c.title, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: const TextStyle( + color: AppColors.gold, + fontWeight: FontWeight.bold, + ), + ), const SizedBox(height: 6), Expanded(child: _preview(c)), const SizedBox(height: 6), @@ -461,37 +473,51 @@ class _CarpetCard extends StatelessWidget { Widget _preview(Carpet c) { final frame = ClipRRect( borderRadius: BorderRadius.circular(8), - child: c.isClassic - ? Container( - color: const Color(0xFF0E3614), - child: const Center( - child: Icon(Icons.casino, color: AppColors.gold, size: 36)), - ) - : Image.network( - c.imageUrl, - fit: BoxFit.cover, - errorBuilder: (_, __, ___) => Container( - color: const Color(0xFF2A0710), - child: const Icon(Icons.image_not_supported, - color: AppColors.goldDark)), - ), + child: + c.isClassic + ? Container( + color: const Color(0xFF0E3614), + child: const Center( + child: Icon(Icons.casino, color: AppColors.gold, size: 36), + ), + ) + : Image.network( + c.imageUrl, + fit: BoxFit.cover, + errorBuilder: + (_, __, ___) => Container( + color: AppColors.lapisLo, + child: const Icon( + Icons.image_not_supported, + color: AppColors.goldDark, + ), + ), + ), ); - return Stack(fit: StackFit.expand, children: [ - frame, - if (c.vip && !c.owned) - const Positioned( - top: 4, - left: 4, - child: Chip( - label: Text('VIP', + return Stack( + fit: StackFit.expand, + children: [ + frame, + if (c.vip && !c.owned) + const Positioned( + top: 4, + left: 4, + child: Chip( + label: Text( + 'VIP', style: TextStyle( - color: Colors.white, fontSize: 10, fontWeight: FontWeight.bold)), - backgroundColor: AppColors.goldDark, - padding: EdgeInsets.zero, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + color: Colors.white, + fontSize: 10, + fontWeight: FontWeight.bold, + ), + ), + backgroundColor: AppColors.goldDark, + padding: EdgeInsets.zero, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + ), ), - ), - ]); + ], + ); } Widget _action(Carpet c) { @@ -567,7 +593,7 @@ class _ItemCard extends StatelessWidget { gradient: const LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, - colors: [Color(0xFF6E1322), AppColors.bg], + colors: [AppColors.lapisHi, AppColors.lapisLo], ), borderRadius: BorderRadius.circular(14), border: Border.all(color: AppColors.gold, width: 1.6), @@ -740,7 +766,10 @@ class _PriceButton extends StatelessWidget { ? const [Color(0xFF555555), Color(0xFF333333)] : green ? const [AppColors.success, AppColors.successDark] - : const [Color(0xFFD83A4A), Color(0xFF8E0E1B)]; + : const [ + AppColors.accent, + Color(0xFF7A1019), + ]; // شنگرفِ ایرانی (هم‌رنگِ تم) return Opacity( opacity: disabled ? 0.85 : 1, child: GestureDetector( diff --git a/lib/feature/shop/presentation/screen/vip_screen.dart b/lib/feature/shop/presentation/screen/vip_screen.dart index d7f4f19..f375e41 100644 --- a/lib/feature/shop/presentation/screen/vip_screen.dart +++ b/lib/feature/shop/presentation/screen/vip_screen.dart @@ -155,7 +155,7 @@ class _VipPackageTile extends StatelessWidget { gradient: const LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, - colors: [Color(0xFF6E1322), AppColors.bg], + colors: [AppColors.lapisHi, AppColors.lapisLo], ), borderRadius: BorderRadius.circular(14), border: Border.all(color: AppColors.gold, width: 1.4),