feat: 增加连续点击样式处理
This commit is contained in:
@@ -137,12 +137,12 @@ class KrNodeListItem {
|
||||
final protocols = json['protocols']?.toString() ?? ''; // 协议配置JSON
|
||||
|
||||
// 🔧 打印原始节点 JSON(用于调试)
|
||||
KRLogUtil.kr_i('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', tag: 'NodeList');
|
||||
KRLogUtil.kr_i('📥 收到节点 API 原始数据:', tag: 'NodeList');
|
||||
KRLogUtil.kr_i('节点名称: ${json['name']}', tag: 'NodeList');
|
||||
KRLogUtil.kr_i('协议类型: ${json['protocol']}', tag: 'NodeList');
|
||||
KRLogUtil.kr_i('完整 JSON:', tag: 'NodeList');
|
||||
KRLogUtil.kr_i(jsonEncode(json), tag: 'NodeList');
|
||||
// KRLogUtil.kr_i('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', tag: 'NodeList');
|
||||
// KRLogUtil.kr_i('📥 收到节点 API 原始数据:', tag: 'NodeList');
|
||||
// KRLogUtil.kr_i('节点名称: ${json['name']}', tag: 'NodeList');
|
||||
// KRLogUtil.kr_i('协议类型: ${json['protocol']}', tag: 'NodeList');
|
||||
// KRLogUtil.kr_i('完整 JSON:', tag: 'NodeList');
|
||||
// KRLogUtil.kr_i(jsonEncode(json), tag: 'NodeList');
|
||||
|
||||
// 🔧 如果有 protocols 字段,从中解析 cipher(但不覆盖顶层的 port)
|
||||
if (protocols.isNotEmpty) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'dart:math';
|
||||
import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
@@ -11,6 +12,9 @@ import 'package:kaer_with_panels/app/services/global_overlay_service.dart';
|
||||
import 'package:kaer_with_panels/app/services/singbox_imp/kr_sing_box_imp.dart';
|
||||
import 'package:kaer_with_panels/singbox/model/singbox_status.dart';
|
||||
|
||||
DateTime? _hiConnectBtnNextAllowedAt;
|
||||
const Duration _hiConnectBtnDebounce = Duration(milliseconds: 800);
|
||||
|
||||
/// ✅ 按钮组件(带多层呼吸同心圆动画)
|
||||
class HIAnimatedConnectButton extends GetView<KRHomeController> {
|
||||
final VoidCallback? onTriggerSubscriptionAnimation;
|
||||
@@ -88,11 +92,16 @@ class HIAnimatedConnectButton extends GetView<KRHomeController> {
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
HapticFeedback.lightImpact();
|
||||
if (isSwitching) {
|
||||
print(
|
||||
'🔵 Switch UI 正在更新,切换中点击了按钮: status=${status.runtimeType}, isConnected=$isConnected, isSwitching=$isSwitching');
|
||||
final _now = DateTime.now();
|
||||
if (_hiConnectBtnNextAllowedAt != null &&
|
||||
_now.isBefore(_hiConnectBtnNextAllowedAt!)) {
|
||||
_hiConnectBtnNextAllowedAt =
|
||||
_now.add(_hiConnectBtnDebounce);
|
||||
return;
|
||||
}
|
||||
_hiConnectBtnNextAllowedAt =
|
||||
_now.add(_hiConnectBtnDebounce);
|
||||
|
||||
final current = controller
|
||||
.kr_subscribeService.kr_currentSubscribe.value;
|
||||
bool hasValidSubscription = false;
|
||||
|
||||
@@ -40,13 +40,13 @@ class BaseResponse<T> {
|
||||
body = jsonDecode(decrypted);
|
||||
|
||||
if (kDebugMode) {
|
||||
print('✅ 解密成功');
|
||||
print('');
|
||||
print('📦 解密后的完整数据:');
|
||||
// 格式化打印 JSON,方便调试
|
||||
final bodyStr = JsonEncoder.withIndent(' ').convert(body);
|
||||
print(bodyStr);
|
||||
print('═══════════════════════════════════════');
|
||||
// print('✅ 解密成功');
|
||||
// print('');
|
||||
// print('📦 解密后的完整数据:');
|
||||
// // 格式化打印 JSON,方便调试
|
||||
// final bodyStr = JsonEncoder.withIndent(' ').convert(body);
|
||||
// print(bodyStr);
|
||||
// print('═══════════════════════════════════════');
|
||||
}
|
||||
|
||||
KRLogUtil.kr_i('🔓 解密成功', tag: 'BaseResponse');
|
||||
|
||||
@@ -50,7 +50,7 @@ class HttpUtil {
|
||||
void initDio() {
|
||||
KRLogUtil.kr_i('🚀 HttpUtil.initDio() 开始初始化', tag: 'HttpUtil');
|
||||
// 不使用 Loggy,改用自定义简洁拦截器
|
||||
_dio.interceptors.add(_KRSimpleHttpInterceptor());
|
||||
_dio.interceptors.add(_KRSimpleHttpInterceptor(_dio));
|
||||
_dio.options.baseUrl = AppConfig.getInstance().baseUrl;
|
||||
|
||||
// 设置连接超时时间
|
||||
@@ -334,7 +334,11 @@ class HttpUtil {
|
||||
? err.requestOptions.path
|
||||
: err.requestOptions.uri.path;
|
||||
msg = '${msg.isNotEmpty ? msg : 'unknown'} ($_pathOnly)';
|
||||
KRCommonUtil.kr_showToast('请求失败($_pathOnly)', timeout: 3500);
|
||||
final _ua =
|
||||
(err.requestOptions.extra['__unknown_attempts'] as int?) ?? 0;
|
||||
if (_ua >= 2) {
|
||||
KRCommonUtil.kr_showToast('请求失败($_pathOnly)', timeout: 3500);
|
||||
}
|
||||
}
|
||||
return BaseResponse<T>.fromJson(
|
||||
{'code': code, 'msg': msg, 'data': <String, dynamic>{}});
|
||||
@@ -405,6 +409,8 @@ class MyInterceptor extends Interceptor {
|
||||
|
||||
/// 自定义简洁 HTTP 拦截器(无边框符号)
|
||||
class _KRSimpleHttpInterceptor extends Interceptor {
|
||||
final Dio _dio;
|
||||
_KRSimpleHttpInterceptor(this._dio);
|
||||
static String? _lastPath;
|
||||
static int _lastTsMs = 0;
|
||||
@override
|
||||
@@ -546,14 +552,38 @@ class _KRSimpleHttpInterceptor extends Interceptor {
|
||||
final path = (err.requestOptions.path.isNotEmpty)
|
||||
? err.requestOptions.path
|
||||
: err.requestOptions.uri.path;
|
||||
final now = DateTime.now().millisecondsSinceEpoch;
|
||||
if (!(_lastPath == path && (now - _lastTsMs) < 2000)) {
|
||||
_lastPath = path;
|
||||
_lastTsMs = now;
|
||||
KRCommonUtil.kr_showToast('请求失败($path)', timeout: 3500);
|
||||
int unknownAttempts =
|
||||
(err.requestOptions.extra['__unknown_attempts'] as int?) ?? 0;
|
||||
if (unknownAttempts < 2) {
|
||||
err.requestOptions.extra['__unknown_attempts'] = unknownAttempts + 1;
|
||||
final delayMs = unknownAttempts == 0 ? 300 : 700;
|
||||
Future.delayed(Duration(milliseconds: delayMs)).then((_) async {
|
||||
final start = DateTime.now();
|
||||
while (!KRSingBoxImp.instance.kr_isProxyReady &&
|
||||
DateTime.now().difference(start) < const Duration(seconds: 1)) {
|
||||
await Future.delayed(const Duration(milliseconds: 100));
|
||||
}
|
||||
try {
|
||||
final Response<dynamic> r =
|
||||
await _dio.fetch<dynamic>(err.requestOptions);
|
||||
handler.resolve(r);
|
||||
} catch (e) {
|
||||
handler.next(e is DioException
|
||||
? e
|
||||
: DioException(requestOptions: err.requestOptions, error: e));
|
||||
}
|
||||
});
|
||||
return;
|
||||
} else {
|
||||
final now = DateTime.now().millisecondsSinceEpoch;
|
||||
if (!(_lastPath == path && (now - _lastTsMs) < 2000)) {
|
||||
_lastPath = path;
|
||||
_lastTsMs = now;
|
||||
KRCommonUtil.kr_showToast('请求失败($path)', timeout: 3500);
|
||||
}
|
||||
KRLogUtil.kr_e('请求失败($path)',
|
||||
tag: 'HttpUtil', error: err, stackTrace: err.stackTrace);
|
||||
}
|
||||
KRLogUtil.kr_e('请求失败($path)',
|
||||
tag: 'HttpUtil', error: err, stackTrace: err.stackTrace);
|
||||
}
|
||||
handler.next(err);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user