import 'profile.dart'; /// Types of notifications enum NotificationType { appreciate, // Someone appreciated your post chain, // Someone chained your post follow, // Someone followed you follow_request, // Someone requested to follow you new_follower, // Someone followed you (public or approved) request_accepted, // Someone accepted your follow request comment, // Someone commented on your post mention, // Someone mentioned you } /// Notification model class AppNotification { final String id; final NotificationType type; final Profile? actor; // User who performed the action final String? postId; final String? postBody; final Map? metadata; final DateTime createdAt; final bool isRead; final DateTime? archivedAt; const AppNotification({ required this.id, required this.type, this.actor, this.postId, this.postBody, this.metadata, required this.createdAt, this.isRead = false, this.archivedAt, }); factory AppNotification.fromJson(Map json) { final metadataValue = json['metadata']; Map? metadata; if (metadataValue is Map) { metadata = Map.from(metadataValue); } // Extract post body from nested post object or direct field String? postBody = json['post_body'] as String?; if (postBody == null && json['post'] is Map) { postBody = (json['post'] as Map)['body'] as String?; } return AppNotification( id: json['id'] as String, type: NotificationType.values.firstWhere( (e) => e.name == json['type'], orElse: () => NotificationType.appreciate, ), actor: json['actor'] != null ? Profile.fromJson(json['actor'] as Map) : null, postId: json['post_id'] as String?, postBody: postBody, metadata: metadata, createdAt: DateTime.parse(json['created_at'] as String), isRead: json['is_read'] as bool? ?? false, archivedAt: json['archived_at'] != null ? DateTime.parse(json['archived_at'] as String) : null, ); } Map toJson() { return { 'id': id, 'type': type.name, 'actor': actor?.toJson(), 'post_id': postId, 'post_body': postBody, 'metadata': metadata, 'created_at': createdAt.toIso8601String(), 'is_read': isRead, 'archived_at': archivedAt?.toIso8601String(), }; } AppNotification copyWith({ String? id, NotificationType? type, Profile? actor, String? postId, String? postBody, Map? metadata, DateTime? createdAt, bool? isRead, DateTime? archivedAt, }) { return AppNotification( id: id ?? this.id, type: type ?? this.type, actor: actor ?? this.actor, postId: postId ?? this.postId, postBody: postBody ?? this.postBody, metadata: metadata ?? this.metadata, createdAt: createdAt ?? this.createdAt, isRead: isRead ?? this.isRead, archivedAt: archivedAt ?? this.archivedAt, ); } String? get followerIdFromMetadata { final value = metadata?['follower_id']; return value is String ? value : null; } String get message { final actorName = actor?.displayName ?? 'Someone'; switch (type) { case NotificationType.appreciate: return '$actorName appreciated your post'; case NotificationType.chain: return '$actorName chained your post'; case NotificationType.follow: return '$actorName started following you'; case NotificationType.follow_request: return '$actorName requested to follow you'; case NotificationType.new_follower: return '$actorName followed you'; case NotificationType.request_accepted: return '$actorName accepted your follow request'; case NotificationType.comment: return '$actorName commented on your post'; case NotificationType.mention: return '$actorName mentioned you'; } } }