182 lines
6.1 KiB
Dart
182 lines
6.1 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:taxglide/consts/app_asstes.dart';
|
|
import 'package:taxglide/consts/app_style.dart';
|
|
import 'package:taxglide/consts/comman_webscoket.dart';
|
|
import 'package:taxglide/consts/local_store.dart';
|
|
import 'package:taxglide/consts/notification_webscoket.dart';
|
|
import 'package:taxglide/controller/api_contoller.dart';
|
|
import 'package:taxglide/view/Mahi_chat/live_chat_screen.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:taxglide/consts/responsive_helper.dart';
|
|
|
|
class CommanChatBox extends ConsumerStatefulWidget {
|
|
final String? chatId;
|
|
|
|
const CommanChatBox({super.key, this.chatId});
|
|
|
|
@override
|
|
ConsumerState<CommanChatBox> createState() => _CommanChatBoxState();
|
|
}
|
|
|
|
class _CommanChatBoxState extends ConsumerState<CommanChatBox> {
|
|
bool _isWebSocketInitialized = false;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_initializeWebSocket();
|
|
}
|
|
|
|
/// ✅ Initialize WebSocket on widget load
|
|
Future<void> _initializeWebSocket() async {
|
|
if (_isWebSocketInitialized) return;
|
|
|
|
try {
|
|
final String? userId = await LocalStore().getUserId();
|
|
if (userId != null && userId.isNotEmpty) {
|
|
final wsService = CommonWebSocketService();
|
|
|
|
// Setup message handler to refresh count
|
|
wsService.onMessageReceived = (message) {
|
|
debugPrint("📨 WebSocket message received: $message");
|
|
_refreshCount();
|
|
};
|
|
|
|
// Connect WebSocket
|
|
await wsService.connect(userId: userId);
|
|
_isWebSocketInitialized = true;
|
|
debugPrint("✅ WebSocket initialized for chat box");
|
|
|
|
// ✅ Subscribe NotificationWebSocket to the chat channel early
|
|
// so notifications arrive from ANY screen, not just the chat screen.
|
|
final String chatId =
|
|
widget.chatId ?? await LocalStore().getGeneralChatId() ?? '0';
|
|
if (chatId != '0' && chatId.isNotEmpty) {
|
|
NotificationWebSocket().watchChatChannel(chatId);
|
|
debugPrint(
|
|
"👁 CommanChatBox: watching chat channel $chatId for notifications",
|
|
);
|
|
}
|
|
}
|
|
} catch (e) {
|
|
debugPrint("❌ Failed to initialize WebSocket: $e");
|
|
}
|
|
}
|
|
|
|
/// ✅ Refresh count provider
|
|
void _refreshCount() {
|
|
try {
|
|
final chatId = widget.chatId ?? "0";
|
|
// Invalidate the count provider to trigger API call
|
|
ref.invalidate(countProvider(chatId));
|
|
debugPrint("🔄 Count refreshed for chatId: $chatId");
|
|
} catch (e) {
|
|
debugPrint("❌ Error refreshing count: $e");
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return FutureBuilder<String?>(
|
|
future: widget.chatId != null
|
|
? Future.value(widget.chatId)
|
|
: LocalStore().getGeneralChatId(),
|
|
builder: (context, snapshot) {
|
|
if (!snapshot.hasData) {
|
|
return const SizedBox();
|
|
}
|
|
|
|
final id = snapshot.data ?? "0";
|
|
final r = ResponsiveUtils(context);
|
|
final countAsync = ref.watch(countProvider(id));
|
|
|
|
return Positioned(
|
|
right: 20,
|
|
bottom: r.spacing(mobile: 35, tablet: 45, desktop: 55),
|
|
child: Stack(
|
|
clipBehavior: Clip.none,
|
|
children: [
|
|
// Main Chat Button
|
|
GestureDetector(
|
|
onTap: () async {
|
|
int cid = int.tryParse(id) ?? 0;
|
|
|
|
ref.invalidate(chatMessagesProvider);
|
|
|
|
// Navigate to chat screen
|
|
Get.to(() => LiveChatScreen(chatid: cid, fileid: '0'))?.then((
|
|
_,
|
|
) {
|
|
ref.read(notificationTriggerProvider.notifier).state++;
|
|
});
|
|
},
|
|
child: Container(
|
|
width: 53,
|
|
height: 53,
|
|
decoration: BoxDecoration(
|
|
shape: BoxShape.circle,
|
|
gradient: const LinearGradient(
|
|
begin: Alignment.topCenter,
|
|
end: Alignment.bottomCenter,
|
|
colors: [Color(0xFFBD49F7), Color(0xFF630A73)],
|
|
),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withOpacity(0.25),
|
|
blurRadius: 7.2,
|
|
offset: const Offset(0, 1),
|
|
),
|
|
],
|
|
),
|
|
child: Container(
|
|
margin: const EdgeInsets.all(3),
|
|
decoration: const BoxDecoration(
|
|
color: Colors.white,
|
|
shape: BoxShape.circle,
|
|
),
|
|
child: Image.asset(AppAssets.generalchatimage),
|
|
),
|
|
),
|
|
),
|
|
|
|
// 🔴 Count Badge
|
|
Positioned(
|
|
right: -2,
|
|
top: -2,
|
|
child: countAsync.when(
|
|
loading: () => const SizedBox(),
|
|
error: (_, __) => const SizedBox(),
|
|
data: (data) {
|
|
if (data.count == 0) return const SizedBox();
|
|
return Container(
|
|
padding: const EdgeInsets.all(5),
|
|
decoration: const BoxDecoration(
|
|
color: Colors.red,
|
|
shape: BoxShape.circle,
|
|
),
|
|
child: Text(
|
|
data.count.toString(),
|
|
style: AppTextStyles.bold.copyWith(
|
|
color: Colors.white,
|
|
fontSize: 10,
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
// Don't disconnect WebSocket here as it's shared across app
|
|
super.dispose();
|
|
}
|
|
}
|