Commit 39daf05d by tanghuan

连续点击屏幕左上角,弹出确认是否退出的对话框

1 parent 1ccaf81d
......@@ -502,6 +502,47 @@ class WebCubit extends Cubit<WebState> with WidgetsBindingObserver {
router.go('/loginMain');
}
// 连续点击退出登录的次数阈值
static const int _quickLogoutTapCount = 5;
// 相邻两次点击的最大间隔(超过则计数重置)
static const Duration _quickLogoutResetWindow = Duration(seconds: 2);
int _quickLogoutTapCounter = 0;
Timer? _quickLogoutResetTimer;
///
/// 屏幕热区点击事件入口:累计达到阈值后返回 true,由页面调起确认对话框
/// 用于 H5 因 JS 异常无响应时的兜底退出机制
///
bool onQuickLogoutTap() {
debugPrint('onQuickLogoutTap--------------------------------->');
_quickLogoutResetTimer?.cancel();
_quickLogoutTapCounter += 1;
if (_quickLogoutTapCounter >= _quickLogoutTapCount) {
_quickLogoutTapCounter = 0;
return true;
}
_quickLogoutResetTimer = Timer(_quickLogoutResetWindow, () {
_quickLogoutTapCounter = 0;
});
return false;
}
/// 执行快速退出登录:清理认证信息与 WebView 缓存,跳转登录页
Future<void> handleQuickLogout() async {
final prefs = getIt.get<SharedPreferences>();
// 删除所有 auth_ 开头的 key
for (final key in prefs.getKeys()) {
if (key.startsWith('auth_')) {
await prefs.remove(key);
}
}
// 清理 WebView 缓存,避免下次进入仍是异常页面
await clearWebCache();
router.go('/loginMain');
}
void goIm() {
router.go('/im');
}
......
......@@ -83,6 +83,26 @@ class WebPage extends StatelessWidget {
),
),
),
// 连续点击退出登录的隐形热区(左上角 60x60)
// 用于 H5 因 JS 异常无响应时的兜底退出机制
// 使用 Listener 而非 GestureDetector:避免 Android 端 WebView 平台视图
// 在手势竞技场中抢占 onTap,导致点击不生效。
Positioned(
left: 0,
top: 0,
width: 80,
height: 80,
child: Listener(
behavior: HitTestBehavior.opaque,
onPointerDown: (_) {
final triggered = ctx.read<WebCubit>().onQuickLogoutTap();
if (triggered) {
_showQuickLogoutDialog(ctx);
}
},
child: const SizedBox.expand(),
),
),
],
),
bottomNavigationBar: state.showBottomNavBar
......@@ -192,4 +212,81 @@ class WebPage extends StatelessWidget {
toolbarHeight: 40.0,
);
}
/// 连续点击达阈后弹出的退出登录确认对话框
/// 样式参照 login_main_page_v3 中的 _showAgreementDialog
Future<void> _showQuickLogoutDialog(BuildContext ctx) async {
final webCubit = ctx.read<WebCubit>();
final result = await showDialog(
context: ctx,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(5),
),
),
title: Text(
'退出登录',
style: TextStyle(
fontSize: 17,
color: Color(0xFF000000),
),
textAlign: TextAlign.center,
),
content: Text(
'检测到连续点击了屏幕,是否退出登录?',
style: TextStyle(color: Color(0xFF666666), fontSize: 14),
),
actions: [
Table(
children: [
TableRow(
children: [
TableCell(
child: TextButton(
onPressed: () {
Navigator.of(context).pop();
},
style: TextButton.styleFrom(
foregroundColor: Color(0xFF666666),
textStyle: TextStyle(fontSize: 17),
padding: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.zero,
),
),
child: Text('取消'),
),
),
TableCell(
child: TextButton(
onPressed: () {
Navigator.of(context).pop('OK');
},
style: TextButton.styleFrom(
foregroundColor: Color(0xFF7691FA),
textStyle: TextStyle(fontSize: 17),
minimumSize: Size.fromHeight(40),
padding: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.zero,
),
),
child: Text('确认'),
),
),
],
),
],
),
],
);
},
);
if (result != null) {
webCubit.handleQuickLogout();
}
}
}
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!