All checks were successful
Build Flutter Web and Docker Image for Local Registry / Build Flutter Web App (push) Successful in 3m7s
220 lines
7.2 KiB
Dart
220 lines
7.2 KiB
Dart
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) {
|
|
final message = jsonEncode({
|
|
'Id': id,
|
|
'Name': name,
|
|
'Image': image,
|
|
'Status': status,
|
|
'Timestamp': DateTime.now().toIso8601String(),
|
|
});
|
|
channel.sink.add(message);
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(content: Text('Status "$status" sent!')),
|
|
);
|
|
}
|
|
|
|
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),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
@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,
|
|
actions: [
|
|
IconButton(
|
|
icon: const Icon(Icons.edit),
|
|
onPressed: widget.toggleProfile, // Open ProfileScreen overlay
|
|
),
|
|
],
|
|
),
|
|
body: StreamBuilder(
|
|
stream: controller.stream,
|
|
builder: (context, snapshot) {
|
|
if (snapshot.hasData) {
|
|
final newMessage =
|
|
jsonDecode(snapshot.data as String) as Map<String, dynamic>;
|
|
|
|
final incomingId = newMessage['Id'];
|
|
messages.removeWhere((msg) => msg['Id'] == incomingId);
|
|
if (newMessage['Status'] != 'expired' &&
|
|
newMessage['Status'] != "is leaving") {
|
|
messages.add(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(
|
|
onPressed: () => _sendStatus(
|
|
userId, userName, userLogo, 'is on the way'),
|
|
child: const Text('On the Way'),
|
|
),
|
|
ElevatedButton(
|
|
onPressed: () => _sendStatus(
|
|
userId, userName, userLogo, 'has arrived'),
|
|
child: const Text('Arrived'),
|
|
),
|
|
ElevatedButton(
|
|
onPressed: () =>
|
|
_sendStatus(userId, userName, userLogo, 'is leaving'),
|
|
child: const Text('Leaving'),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
);
|
|
},
|
|
),
|
|
);
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
channel.sink.close();
|
|
super.dispose();
|
|
}
|
|
}
|