import 'dart:convert'; import 'dart:typed_data'; import 'package:halkyon_learn_flutter/src/feature/feedback/data/feedback_gateway.dart'; import 'package:halkyon_learn_flutter/src/feature/feedback/model/feedback.dart'; /// A [FeedbackWriteGateway] in memory: what was written, in order. class FakeFeedbackWriteGateway() implements FeedbackWriteGateway { /// The threads written: their published studyset, kind and payload JSON. final threads = < ({String publicationId, FeedbackKind kind, Map json}) >[]; /// The replies written, by thread. final messages = <({String threadId, Map json})>[]; /// The decisions written, by thread. final decisions = <({String threadId, FeedbackDecision decision})>[]; @override Future insertThread({ required String publicationId, required FeedbackKind kind, required ByteData payload, }) async { threads.add(( publicationId: publicationId, kind: kind, json: _json(payload), )); return 'thread-${threads.length}'; } @override Future insertMessage(String threadId, ByteData payload) async => messages.add((threadId: threadId, json: _json(payload))); @override Future insertDecision( String threadId, FeedbackDecision decision, ) async => decisions.add((threadId: threadId, decision: decision)); static Map _json(ByteData payload) => jsonDecode(utf8.decode(Uint8List.sublistView(payload))) as Map; } /// A [FeedbackServerGateway] in memory: [threads] as the instance gathers /// them (all public, for the inbox too), [files] by SHA-256. class FakeFeedbackServerGateway({ final List threads = const [], final Map files = const {}, }) implements FeedbackServerGateway { late var _threads = [...threads]; /// The threads read, and the people blocked. final seen = []; final blocked = []; /// When set, every request fails with it. Exception? fail; /// Replaces what the instance gathers. set gathered(List threads) => _threads = [...threads]; Future _maybeFail() async { if (fail case final error?) { throw error; } } @override Future> threadsOf(String publicId) async { await _maybeFail(); return [ for (final thread in _threads) if (thread.publicId == publicId) thread, ]; } @override Future> inbox() async { await _maybeFail(); return [ for (final thread in _threads) if (thread.mine || thread.forMe) thread, ]; } @override Future unseen() async => (await inbox()).where((thread) => thread.unseen).length; @override Future markSeen(String threadId) async { await _maybeFail(); seen.add(threadId); } @override Future block(String handle) async => blocked.add(handle); @override Future unblock(String handle) async => blocked.remove(handle); @override Future> blockedPeople() async => [...blocked]; @override Future file(String threadId, String sha256) async { await _maybeFail(); return files[sha256]!; } }