pogdark-app-flutter/lib/status_page.dart

271 lines
9.1 KiB
Dart
Raw Normal View History

import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
import 'shared_preferences_provider.dart';
class StatusPage extends StatefulWidget {
final VoidCallback toggleProfile;
const StatusPage({super.key, required this.toggleProfile});
@override
StatusPageState createState() => StatusPageState();
}
class StatusPageState extends State<StatusPage> {
final WebSocketChannel channel = WebSocketChannel.connect(
Uri.parse('wss://api.pogdark.com:8889/ws'),
);
late final Stream<dynamic> broadcastStream;
late StreamController<dynamic> controller;
List<Map<String, dynamic>> messages = []; // To hold user messages
@override
void initState() {
super.initState();
controller = StreamController<dynamic>.broadcast();
controller.addStream(channel.stream);
broadcastStream = channel.stream.asBroadcastStream();
}
List<Map<String, dynamic>> _getMessagesByStatus(String status) {
return messages.where((message) => message['Status'] == status).toList();
}
void _sendStatus(String id, String name, String? image, String status) async {
final prefsProvider =
Provider.of<SharedPreferencesProvider>(context, listen: false);
if (!mounted) return;
// Check if the status is already active; if so, clear it, otherwise set it
final isStatusActive = prefsProvider.getCurrentStatus() == status;
final newStatus = isStatusActive ? '' : status;
// Update the status in SharedPreferences
await prefsProvider.setCurrentStatus(newStatus);
// Send the message to the WebSocket
final message = jsonEncode({
'Id': id,
'Name': name,
'Image': image,
'Status': newStatus.isEmpty ? 'expired' : newStatus,
'Timestamp': DateTime.now().toIso8601String(),
});
channel.sink.add(message);
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'Status "${newStatus.isEmpty ? 'cleared' : newStatus}" sent!')),
);
}
}
void _handleIncomingMessage(Map<String, dynamic> message) async {
final prefsProvider =
Provider.of<SharedPreferencesProvider>(context, listen: false);
final status = message['Status'];
final incomingId = message['Id'];
messages.removeWhere((msg) => msg['Id'] == incomingId);
// Check if the message status is "expired" and update SharedPreferences
if (status == 'expired') {
await prefsProvider.setCurrentStatus('');
} else {
messages.add(message);
}
}
Widget _buildMessageItem(Map<String, dynamic> message) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0),
child: Align(
alignment: Alignment.centerLeft,
child: Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: Colors.blue.shade50,
borderRadius: BorderRadius.circular(12),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
CircleAvatar(
radius: 20,
backgroundImage: message['Image'] != null
? Image.memory(base64Decode(message['Image'])).image
: const AssetImage('assets/default_profile_image.png'),
),
const SizedBox(width: 8),
Text(
"${message['Name']}",
style: const TextStyle(
fontSize: 16, fontWeight: FontWeight.bold),
),
],
),
const SizedBox(height: 4),
Text(
"Received at: ${message['Timestamp']}",
style: const TextStyle(fontSize: 12, color: Colors.grey),
),
],
),
),
),
);
}
// Function to get the background color based on the current status
Color getButtonColor(String buttonStatus) {
final prefsProvider = Provider.of<SharedPreferencesProvider>(context);
final currentStatus = prefsProvider.getCurrentStatus();
return currentStatus == buttonStatus ? Colors.blueAccent : Colors.grey;
}
// Function to get the text color based on the current status
Color getButtonTextColor(String buttonStatus) {
final prefsProvider = Provider.of<SharedPreferencesProvider>(context);
final currentStatus = prefsProvider.getCurrentStatus();
return currentStatus == buttonStatus ? Colors.white : Colors.black;
}
@override
Widget build(BuildContext context) {
final prefsProvider = Provider.of<SharedPreferencesProvider>(context);
final userName = prefsProvider.getUserName();
final userLogo = prefsProvider.getUserLogo();
final userId = prefsProvider.getUserId();
return Scaffold(
appBar: AppBar(
title: Image.asset(
'assets/pogdark_logo.png',
height: 40,
),
backgroundColor: Colors.blueAccent,
),
body: StreamBuilder(
stream: controller.stream,
builder: (context, snapshot) {
if (snapshot.hasData) {
final newMessage =
jsonDecode(snapshot.data as String) as Map<String, dynamic>;
_handleIncomingMessage(newMessage);
}
final onTheWayMessages = _getMessagesByStatus('is on the way');
final arrivedMessages = _getMessagesByStatus('has arrived');
return Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Expanded(
child: Row(
children: [
Expanded(
child: Column(
children: [
const Text(
'On the Way',
style: TextStyle(
fontSize: 18, fontWeight: FontWeight.bold),
),
Expanded(
child: ListView.builder(
itemCount: onTheWayMessages.length,
itemBuilder: (context, index) {
return _buildMessageItem(
onTheWayMessages[index]);
},
),
),
],
),
),
Expanded(
child: Column(
children: [
const Text(
'Arrived',
style: TextStyle(
fontSize: 18, fontWeight: FontWeight.bold),
),
Expanded(
child: ListView.builder(
itemCount: arrivedMessages.length,
itemBuilder: (context, index) {
return _buildMessageItem(
arrivedMessages[index]);
},
),
),
],
),
),
],
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: getButtonColor('is on the way'),
),
onPressed: () => _sendStatus(
userId, userName, userLogo, 'is on the way'),
child: Text(
'On the Way',
style: TextStyle(
color: getButtonTextColor('is on the way')),
),
),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: getButtonColor('has arrived'),
),
onPressed: () => _sendStatus(
userId, userName, userLogo, 'has arrived'),
child: Text(
'Arrived',
style:
TextStyle(color: getButtonTextColor('has arrived')),
),
),
2024-11-10 04:43:40 +00:00
IconButton(
icon: const Icon(Icons.edit, color: Colors.blueAccent),
onPressed: widget.toggleProfile,
tooltip: 'Edit Profile',
),
],
),
],
),
);
},
),
);
}
@override
void dispose() {
channel.sink.close();
super.dispose();
}
}