mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 16:30:28 +00:00
feat: Implement compact JSON handling for map drawings and add chat notifications for sent/received drawings
This commit is contained in:
@@ -54,11 +54,29 @@ abstract class MapDrawing {
|
||||
/// Convert to JSON for persistence
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
/// Convert to JSON for network transmission (includes sender name)
|
||||
Map<String, dynamic> toNetworkJson(String senderName) {
|
||||
final json = toJson();
|
||||
json['sender'] = senderName;
|
||||
return json;
|
||||
/// Convert to JSON for network transmission (compact format)
|
||||
/// Uses short field names and excludes createdAt to minimize message size
|
||||
Map<String, dynamic> toNetworkJson(String senderName);
|
||||
|
||||
/// Parse network JSON (compact format)
|
||||
static MapDrawing? fromNetworkJson(Map<String, dynamic> json) {
|
||||
final typeStr = json['t'] as String?;
|
||||
if (typeStr == null) return null;
|
||||
|
||||
try {
|
||||
final type = DrawingShapeType.values.firstWhere(
|
||||
(e) => e.name == typeStr,
|
||||
);
|
||||
|
||||
switch (type) {
|
||||
case DrawingShapeType.line:
|
||||
return LineDrawing.fromNetworkJson(json);
|
||||
case DrawingShapeType.rectangle:
|
||||
return RectangleDrawing.fromNetworkJson(json);
|
||||
}
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// Create from JSON
|
||||
@@ -107,6 +125,18 @@ class LineDrawing extends MapDrawing {
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toNetworkJson(String senderName) {
|
||||
// Compact format: t=type, c=color, s=sender, p=points
|
||||
// Points are encoded as flat array [lat1,lon1,lat2,lon2,...]
|
||||
return {
|
||||
't': type.name,
|
||||
'c': color.value,
|
||||
's': senderName,
|
||||
'p': points.expand((p) => [p.latitude, p.longitude]).toList(),
|
||||
};
|
||||
}
|
||||
|
||||
static LineDrawing fromJson(Map<String, dynamic> json) {
|
||||
final pointsJson = json['points'] as List<dynamic>;
|
||||
final points = pointsJson.map((p) => LatLng(p['lat'] as double, p['lon'] as double)).toList();
|
||||
@@ -122,6 +152,25 @@ class LineDrawing extends MapDrawing {
|
||||
);
|
||||
}
|
||||
|
||||
static LineDrawing fromNetworkJson(Map<String, dynamic> json) {
|
||||
// Parse compact format
|
||||
final pointsFlat = (json['p'] as List<dynamic>).cast<double>();
|
||||
final points = <LatLng>[];
|
||||
for (int i = 0; i < pointsFlat.length; i += 2) {
|
||||
points.add(LatLng(pointsFlat[i], pointsFlat[i + 1]));
|
||||
}
|
||||
final senderName = json['s'] as String?;
|
||||
|
||||
return LineDrawing(
|
||||
id: DateTime.now().millisecondsSinceEpoch.toString(), // Generate new ID
|
||||
color: Color(json['c'] as int),
|
||||
createdAt: DateTime.now(),
|
||||
points: points,
|
||||
senderName: senderName,
|
||||
isReceived: true,
|
||||
);
|
||||
}
|
||||
|
||||
/// Create a copy with updated points
|
||||
LineDrawing copyWith({List<LatLng>? points}) {
|
||||
return LineDrawing(
|
||||
@@ -169,6 +218,17 @@ class RectangleDrawing extends MapDrawing {
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toNetworkJson(String senderName) {
|
||||
// Compact format: t=type, c=color, s=sender, b=bounds [lat1,lon1,lat2,lon2]
|
||||
return {
|
||||
't': type.name,
|
||||
'c': color.value,
|
||||
's': senderName,
|
||||
'b': [topLeft.latitude, topLeft.longitude, bottomRight.latitude, bottomRight.longitude],
|
||||
};
|
||||
}
|
||||
|
||||
static RectangleDrawing fromJson(Map<String, dynamic> json) {
|
||||
final topLeftJson = json['topLeft'] as Map<String, dynamic>;
|
||||
final bottomRightJson = json['bottomRight'] as Map<String, dynamic>;
|
||||
@@ -185,6 +245,22 @@ class RectangleDrawing extends MapDrawing {
|
||||
);
|
||||
}
|
||||
|
||||
static RectangleDrawing fromNetworkJson(Map<String, dynamic> json) {
|
||||
// Parse compact format
|
||||
final bounds = (json['b'] as List<dynamic>).cast<double>();
|
||||
final senderName = json['s'] as String?;
|
||||
|
||||
return RectangleDrawing(
|
||||
id: DateTime.now().millisecondsSinceEpoch.toString(), // Generate new ID
|
||||
color: Color(json['c'] as int),
|
||||
createdAt: DateTime.now(),
|
||||
topLeft: LatLng(bounds[0], bounds[1]),
|
||||
bottomRight: LatLng(bounds[2], bounds[3]),
|
||||
senderName: senderName,
|
||||
isReceived: true,
|
||||
);
|
||||
}
|
||||
|
||||
/// Create a copy with updated corners
|
||||
RectangleDrawing copyWith({
|
||||
LatLng? topLeft,
|
||||
|
||||
@@ -72,10 +72,20 @@ class AppProvider with ChangeNotifier {
|
||||
if (drawing != null) {
|
||||
debugPrint('🎨 [AppProvider] Drawing parsed successfully: ${drawing.type.name} from ${drawing.senderName ?? "unknown"}');
|
||||
drawingProvider.addReceivedDrawing(drawing);
|
||||
|
||||
// Add informational message to chat
|
||||
final drawingTypeStr = drawing.type.name.substring(0, 1).toUpperCase() +
|
||||
drawing.type.name.substring(1);
|
||||
final infoMessage = message.copyWith(
|
||||
text: '📍 Received map drawing ($drawingTypeStr) from ${drawing.senderName ?? "unknown"}',
|
||||
);
|
||||
messagesProvider.addMessage(
|
||||
infoMessage,
|
||||
contactLookup: (name) => '',
|
||||
);
|
||||
} else {
|
||||
debugPrint('⚠️ [AppProvider] Failed to parse drawing message');
|
||||
}
|
||||
// Don't add drawing messages to the message list
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,8 +25,8 @@ class DrawingMessageParser {
|
||||
// Parse JSON
|
||||
final json = jsonDecode(jsonStr) as Map<String, dynamic>;
|
||||
|
||||
// Use existing fromJson method
|
||||
return MapDrawing.fromJson(json);
|
||||
// Use compact network format parser
|
||||
return MapDrawing.fromNetworkJson(json);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'package:provider/provider.dart';
|
||||
import '../../providers/drawing_provider.dart';
|
||||
import '../../providers/connection_provider.dart';
|
||||
import '../../providers/contacts_provider.dart';
|
||||
import '../../providers/messages_provider.dart';
|
||||
import '../../models/map_drawing.dart';
|
||||
import '../../models/contact.dart';
|
||||
|
||||
@@ -480,6 +481,13 @@ class DrawingToolbar extends StatelessWidget {
|
||||
return;
|
||||
}
|
||||
|
||||
// Add informational message to chat
|
||||
final messagesProvider = Provider.of<MessagesProvider>(context, listen: false);
|
||||
messagesProvider.logSystemMessage(
|
||||
text: '📤 Sent ${drawings.length} map drawing${drawings.length > 1 ? 's' : ''} to Public Channel',
|
||||
level: 'info',
|
||||
);
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
@@ -547,6 +555,13 @@ class DrawingToolbar extends StatelessWidget {
|
||||
return;
|
||||
}
|
||||
|
||||
// Add informational message to chat
|
||||
final messagesProvider = Provider.of<MessagesProvider>(context, listen: false);
|
||||
messagesProvider.logSystemMessage(
|
||||
text: '📤 Sent ${drawings.length} map drawing${drawings.length > 1 ? 's' : ''} to ${room.advName}',
|
||||
level: 'info',
|
||||
);
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
|
||||
Reference in New Issue
Block a user