hi-client/lib/app/services/global_overlay_service.dart
2025-12-01 06:54:18 -08:00

169 lines
5.1 KiB
Dart
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../modules/kr_home/views/hi_subscription_corner_button.dart';
import 'package:kaer_with_panels/main.dart';
import 'package:kaer_with_panels/app/widgets/kr_local_image.dart';
class GlobalOverlayService extends GetxService {
Color? _currentColor;
static GlobalOverlayService get instance => Get.find<GlobalOverlayService>();
VoidCallback? _subscriptionAnimationTrigger;
void registerAnimationTrigger(VoidCallback trigger) {
_subscriptionAnimationTrigger = trigger;
}
/// 触发按钮动画跳转购买页
void triggerSubscriptionAnimation() {
if (_subscriptionAnimationTrigger != null) {
_subscriptionAnimationTrigger!.call();
} else {
print('🔥 Subscription animation trigger not registered yet');
}
}
OverlayEntry? _overlayEntry;
final RxBool _isVisible = false.obs;
bool get isVisible => _isVisible.value;
@override
void onInit() {
super.onInit();
print('🔥 GlobalOverlayService: Service initialized');
}
void showSubscriptionButton([OverlayState? overlay]) {
if (_isVisible.value) return;
WidgetsBinding.instance.addPostFrameCallback((_) {
_doShowSubscriptionButton(overlay);
});
}
void _doShowSubscriptionButton([OverlayState? overlay, Color? color]) {
print('🔥 _doShowSubscriptionButton called, overlay=$overlay');
if (_isVisible.value) return;
try {
overlay ??= navigatorKey.currentState?.overlay;
if (overlay == null) {
print('🔥 GlobalOverlayService: No overlay found, cannot show subscription button');
return;
}
_overlayEntry = OverlayEntry(
builder: (context) {
final statusBarHeight = MediaQuery.of(context).padding.top < 62 ? 62 : MediaQuery.of(context).padding.top;
final double radius = 40.0 + statusBarHeight;
final double diameter = radius * 2;
return Stack(
children: [
// 1⃣ 圆背景,保持原来位置
Positioned(
top: -(diameter - (radius + statusBarHeight)),
right: -(radius - (statusBarHeight / 2)),
width: diameter,
height: diameter,
child: HISubscriptionCornerButton(
size: diameter,
color: _currentColor ?? Theme.of(context).primaryColor,
topOffset: -radius,
rightOffset: -radius,
),
),
// 2⃣ money-icon独立定位固定在屏幕右上角
Positioned(
top: MediaQuery.of(context).padding.top + 8,
right: (radius - (statusBarHeight / 2)) / 2,
child: GestureDetector(
behavior: HitTestBehavior.translucent, // 让区域可响应点击
onTap: () {
// ✅ 这里“代理”点击事件,转发到底层按钮动画逻辑
print('🔥 money-icon tapped → trigger HISubscriptionCornerButton animation');
GlobalOverlayService.instance.triggerSubscriptionAnimation();
},
child: IgnorePointer(
ignoring: false, // 不阻断事件
child: KrLocalImage(
imageName: 'money-icon',
imageType: ImageType.svg,
),
),
),
),
],
);
},
);
overlay.insert(_overlayEntry!);
_isVisible.value = true;
print('🔥 GlobalOverlayService: Subscription button shown successfully');
} catch (e) {
print('🔥 GlobalOverlayService: Error showing subscription button: $e');
}
}
void hideSubscriptionButton() {
if (!_isVisible.value) return;
_overlayEntry?.remove();
_overlayEntry = null;
_isVisible.value = false;
}
void toggleSubscriptionButton() {
if (_isVisible.value) {
hideSubscriptionButton();
} else {
showSubscriptionButton();
}
}
void safeShowSubscriptionButton() {
void _attemptShow() {
final overlay = navigatorKey.currentState?.overlay;
if (overlay == null) {
print('🔥 Overlay not ready, retrying...');
Future.delayed(const Duration(milliseconds: 200), _attemptShow);
return;
}
WidgetsBinding.instance.addPostFrameCallback((_) {
print('🔥 Overlay ready, inserting subscription button');
showSubscriptionButton(overlay);
});
}
_attemptShow();
}
void updateSubscriptionButtonColor(Color? color) {
if (_overlayEntry == null) {
print('🔥 updateSubscriptionButtonColor: OverlayEntry is null');
return;
}
_currentColor = color;
_overlayEntry!.markNeedsBuild(); // 🔥 强制刷新 UI
}
void forceShowSubscriptionButton() {
print('🔥 GlobalOverlayService: Force showing subscription button');
hideSubscriptionButton();
Future.delayed(const Duration(milliseconds: 100), () {
safeShowSubscriptionButton();
});
}
@override
void onClose() {
hideSubscriptionButton();
super.onClose();
}
}