fix(client): 联系/购买渠道卡点击外部打开(修空 onTap)+ 桌面账户子导航复现测试
- channel_launch: @→t.me / 邮箱→mailto / 域名→https,外部打开 - 联系页(桌面)/联系&兑换子页(移动)渠道卡接上 onTap - account_desktop_nav_test: 证明桌面设置/兑换/联系/订单导航正常(231 全绿) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013nMthbVEmQquxBRKb9Fj8u
This commit is contained in:
@@ -7,6 +7,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../l10n/app_text.dart';
|
||||
import '../pangolin_theme.dart';
|
||||
import '../services/channel_launch.dart';
|
||||
import '../state/app_providers.dart';
|
||||
import '../widgets/pangolin_icons.dart';
|
||||
|
||||
@@ -50,7 +51,9 @@ class _ChannelCard extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final c = context.pangolin;
|
||||
return Container(
|
||||
return GestureDetector(
|
||||
onTap: () => launchChannel(channel.sub),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(14),
|
||||
decoration: BoxDecoration(
|
||||
color: c.surface,
|
||||
@@ -77,7 +80,7 @@ class _ChannelCard extends StatelessWidget {
|
||||
),
|
||||
Icon(PangolinIcons.chevronRight, size: 18, color: c.fg3),
|
||||
]),
|
||||
);
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// channel_launch.dart — 联系/购买渠道点击:按 handle(sub)推导 URL 并外部打开。
|
||||
// @xxx → https://t.me/xxx (Telegram)
|
||||
// a@b.com → mailto:a@b.com
|
||||
// x.yanmei... → https://x.yanmei...
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
String channelUrl(String sub) {
|
||||
if (sub.startsWith('@')) return 'https://t.me/${sub.substring(1)}';
|
||||
if (sub.contains('@')) return 'mailto:$sub';
|
||||
return 'https://$sub';
|
||||
}
|
||||
|
||||
/// 点击渠道卡:外部打开对应 URL。失败静默(不炸 UI)。
|
||||
Future<void> launchChannel(String sub) async {
|
||||
final uri = Uri.parse(channelUrl(sub));
|
||||
try {
|
||||
if (await canLaunchUrl(uri)) {
|
||||
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||
}
|
||||
} catch (_) {}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import '../l10n/app_text.dart';
|
||||
import '../models/device.dart';
|
||||
import '../pangolin_theme.dart';
|
||||
import '../services/channel_launch.dart';
|
||||
import '../screens/settings_page.dart';
|
||||
import '../services/device_identity.dart';
|
||||
import 'adaptive_menu.dart';
|
||||
@@ -429,7 +430,7 @@ class _RedeemScreenState extends ConsumerState<RedeemScreen> {
|
||||
Widget _channel(PangolinScheme c, IconData icon, String name, String sub, bool accent) {
|
||||
return InkWell(
|
||||
borderRadius: BorderRadius.circular(PangolinRadius.lg),
|
||||
onTap: () {},
|
||||
onTap: () => launchChannel(sub),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(14),
|
||||
decoration: BoxDecoration(color: accent ? c.accentSubtle : c.surface, borderRadius: BorderRadius.circular(PangolinRadius.lg), border: Border.all(color: accent ? c.accentBorder : c.border), boxShadow: PangolinShadow.sm),
|
||||
@@ -486,7 +487,7 @@ class ContactScreen extends StatelessWidget {
|
||||
Widget _contact(PangolinScheme c, IconData icon, String name, String sub, bool accent) {
|
||||
return InkWell(
|
||||
borderRadius: BorderRadius.circular(PangolinRadius.lg),
|
||||
onTap: () {},
|
||||
onTap: () => launchChannel(sub),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(14),
|
||||
decoration: BoxDecoration(color: accent ? c.accentSubtle : c.surface, borderRadius: BorderRadius.circular(PangolinRadius.lg), border: Border.all(color: accent ? c.accentBorder : c.border), boxShadow: PangolinShadow.sm),
|
||||
|
||||
Reference in New Issue
Block a user