116 lines
3.2 KiB
Dart
116 lines
3.2 KiB
Dart
|
|
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<String, Object?> json})
|
||
|
|
>[];
|
||
|
|
|
||
|
|
/// The replies written, by thread.
|
||
|
|
final messages = <({String threadId, Map<String, Object?> json})>[];
|
||
|
|
|
||
|
|
/// The decisions written, by thread.
|
||
|
|
final decisions = <({String threadId, FeedbackDecision decision})>[];
|
||
|
|
|
||
|
|
@override
|
||
|
|
Future<String> 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<void> insertMessage(String threadId, ByteData payload) async =>
|
||
|
|
messages.add((threadId: threadId, json: _json(payload)));
|
||
|
|
|
||
|
|
@override
|
||
|
|
Future<void> insertDecision(
|
||
|
|
String threadId,
|
||
|
|
FeedbackDecision decision,
|
||
|
|
) async => decisions.add((threadId: threadId, decision: decision));
|
||
|
|
|
||
|
|
static Map<String, Object?> _json(ByteData payload) =>
|
||
|
|
jsonDecode(utf8.decode(Uint8List.sublistView(payload)))
|
||
|
|
as Map<String, Object?>;
|
||
|
|
}
|
||
|
|
|
||
|
|
/// A [FeedbackServerGateway] in memory: [threads] as the instance gathers
|
||
|
|
/// them (all public, for the inbox too), [files] by SHA-256.
|
||
|
|
class FakeFeedbackServerGateway({
|
||
|
|
final List<FeedbackThread> threads = const [],
|
||
|
|
final Map<String, Uint8List> files = const {},
|
||
|
|
}) implements FeedbackServerGateway {
|
||
|
|
late var _threads = [...threads];
|
||
|
|
|
||
|
|
/// The threads read, and the people blocked.
|
||
|
|
final seen = <String>[];
|
||
|
|
final blocked = <String>[];
|
||
|
|
|
||
|
|
/// When set, every request fails with it.
|
||
|
|
Exception? fail;
|
||
|
|
|
||
|
|
/// Replaces what the instance gathers.
|
||
|
|
set gathered(List<FeedbackThread> threads) => _threads = [...threads];
|
||
|
|
|
||
|
|
Future<void> _maybeFail() async {
|
||
|
|
if (fail case final error?) {
|
||
|
|
throw error;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
@override
|
||
|
|
Future<List<FeedbackThread>> threadsOf(String publicId) async {
|
||
|
|
await _maybeFail();
|
||
|
|
return [
|
||
|
|
for (final thread in _threads)
|
||
|
|
if (thread.publicId == publicId) thread,
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
@override
|
||
|
|
Future<List<FeedbackThread>> inbox() async {
|
||
|
|
await _maybeFail();
|
||
|
|
return [
|
||
|
|
for (final thread in _threads)
|
||
|
|
if (thread.mine || thread.forMe) thread,
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
@override
|
||
|
|
Future<int> unseen() async =>
|
||
|
|
(await inbox()).where((thread) => thread.unseen).length;
|
||
|
|
|
||
|
|
@override
|
||
|
|
Future<void> markSeen(String threadId) async {
|
||
|
|
await _maybeFail();
|
||
|
|
seen.add(threadId);
|
||
|
|
}
|
||
|
|
|
||
|
|
@override
|
||
|
|
Future<void> block(String handle) async => blocked.add(handle);
|
||
|
|
|
||
|
|
@override
|
||
|
|
Future<void> unblock(String handle) async => blocked.remove(handle);
|
||
|
|
|
||
|
|
@override
|
||
|
|
Future<List<String>> blockedPeople() async => [...blocked];
|
||
|
|
|
||
|
|
@override
|
||
|
|
Future<Uint8List> file(String threadId, String sha256) async {
|
||
|
|
await _maybeFail();
|
||
|
|
return files[sha256]!;
|
||
|
|
}
|
||
|
|
}
|