import 'dart:convert'; import '../utils/app_time.dart'; /// One file attached to a comment (stored in the task_attachments bucket). class ProgrammerCommentAttachment { final String path; final String name; const ProgrammerCommentAttachment({required this.path, required this.name}); Map toJson() => {'path': path, 'name': name}; factory ProgrammerCommentAttachment.fromJson(Map json) { return ProgrammerCommentAttachment( path: json['path']?.toString() ?? '', name: json['name']?.toString() ?? '', ); } } /// A comment on a programmer task (plain, online-first model). Any user who can /// see the task may comment and attach files, whether or not they are the /// assignee. class ProgrammerTaskComment { final String id; final String taskId; final String authorId; final String body; final List attachments; final DateTime createdAt; ProgrammerTaskComment({ required this.id, required this.taskId, required this.authorId, required this.body, this.attachments = const [], required this.createdAt, }); factory ProgrammerTaskComment.fromMap(Map map) { return ProgrammerTaskComment( id: map['id'].toString(), taskId: map['task_id'].toString(), authorId: map['author_id'].toString(), body: map['body'] as String? ?? '', attachments: _parseAttachments(map['attachments']), createdAt: AppTime.parse(map['created_at'] as String), ); } static List _parseAttachments(dynamic raw) { List list; if (raw is List) { list = raw; } else if (raw is String && raw.isNotEmpty) { try { final decoded = jsonDecode(raw); list = decoded is List ? decoded : const []; } catch (_) { list = const []; } } else { return const []; } return list .whereType() .map((e) => ProgrammerCommentAttachment.fromJson( e.map((k, v) => MapEntry(k.toString(), v)), )) .toList(); } }