Initial commit: 91dj android client dev_1.0.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:analytics_sdk/manager/sdk_context.dart';
|
||||
import 'package:analytics_sdk/utils/widget_bridge.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// 埋点调试条 - 展示设备信息、埋点流程 7 步,便于排查某机型上报问题
|
||||
///
|
||||
/// release 包自动隐藏(无性能影响);debug 包由 WidgetBridge 内的 enableDebugBanner 控制。
|
||||
class AnalyticsDebugBanner extends StatelessWidget {
|
||||
const AnalyticsDebugBanner({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (kReleaseMode || !WidgetBridge.enableDebugBanner) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
return const _AnalyticsDebugBannerContent();
|
||||
}
|
||||
}
|
||||
|
||||
class _AnalyticsDebugBannerContent extends StatefulWidget {
|
||||
const _AnalyticsDebugBannerContent();
|
||||
|
||||
@override
|
||||
State<_AnalyticsDebugBannerContent> createState() =>
|
||||
_AnalyticsDebugBannerContentState();
|
||||
}
|
||||
|
||||
class _AnalyticsDebugBannerContentState
|
||||
extends State<_AnalyticsDebugBannerContent> {
|
||||
List<Map<String, String>> _steps = [];
|
||||
Timer? _refreshTimer;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_refreshSteps();
|
||||
_refreshTimer = Timer.periodic(
|
||||
const Duration(seconds: 2), (_) => _refreshSteps());
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_refreshTimer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _refreshSteps() {
|
||||
try {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_steps = WidgetBridge.getDebugSteps();
|
||||
});
|
||||
}
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
final brand = SdkContext.deviceBrand ?? '';
|
||||
final model = SdkContext.deviceModel ?? '';
|
||||
final deviceInfo = brand.isNotEmpty || model.isNotEmpty
|
||||
? '$brand $model'.trim()
|
||||
: (kIsWeb
|
||||
? 'Web'
|
||||
: defaultTargetPlatform == TargetPlatform.android
|
||||
? 'Android'
|
||||
: defaultTargetPlatform == TargetPlatform.iOS
|
||||
? 'iOS'
|
||||
: defaultTargetPlatform.name);
|
||||
final deviceId = SdkContext.deviceId ?? '';
|
||||
final channel = SdkContext.channel ?? '';
|
||||
|
||||
return IgnorePointer(
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.black.withOpacity(0.55),
|
||||
border: const Border(
|
||||
bottom: BorderSide(color: Colors.white, width: 2)),
|
||||
),
|
||||
child: SafeArea(
|
||||
bottom: false,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Text(
|
||||
'【埋点测试包】',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white,
|
||||
shadows: [
|
||||
Shadow(
|
||||
color: Colors.black,
|
||||
offset: Offset(1, 1),
|
||||
blurRadius: 2),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
Text(
|
||||
'设备: $deviceInfo',
|
||||
style: const TextStyle(fontSize: 12, color: Colors.white),
|
||||
),
|
||||
Text(
|
||||
'deviceId: ${deviceId.isEmpty ? "未获取" : "${deviceId.length > 16 ? deviceId.substring(0, 16) : deviceId}..."}',
|
||||
style: const TextStyle(fontSize: 11, color: Colors.white70),
|
||||
),
|
||||
Text(
|
||||
'渠道: ${channel.isEmpty ? "未获取" : channel}',
|
||||
style: const TextStyle(fontSize: 11, color: Colors.white70),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
const Text(
|
||||
'埋点流程(卡在某步=该机型问题)',
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.yellow),
|
||||
),
|
||||
..._steps.map((s) {
|
||||
final status = s['status'] ?? '';
|
||||
final isOk = status.startsWith('✓');
|
||||
final isFail = status.startsWith('✗');
|
||||
var detail = s['detail'] ?? '';
|
||||
if (detail.toString().length > 35) {
|
||||
detail = '${detail.toString().substring(0, 35)}...';
|
||||
}
|
||||
final detailStr =
|
||||
detail.isNotEmpty && detail != '-' ? ' ($detail)' : '';
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 2),
|
||||
child: Text(
|
||||
'${s['name']}: $status$detailStr',
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
color: isOk
|
||||
? Colors.greenAccent
|
||||
: isFail
|
||||
? Colors.orange
|
||||
: Colors.white70,
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user