import 'dart:async'; import 'dart:typed_data'; import 'package:halkyon_learn_flutter/src/feature/studyset/data/studyset_gateway.dart'; /// A [StudysetGateway] in memory: ids are `studyset-1`, `studyset-2`, …, and /// [receiveRemoteChange] and [receiveRemoteDeletion] play a sync that brought /// changes. class FakeStudysetGateway() implements StudysetGateway { final _rows = {}; final _remoteChanges = StreamController.broadcast(); var _nextId = 1; /// Every payload written, in order, as (id, payload). final writes = <(String, ByteData)>[]; /// The ids of the deleted rows, in order. final deleted = []; /// Every move, in order, as (id, parent, position). final moves = <(String, String?, String)>[]; /// When set, reading the studysets fails with it. Exception? failReads; /// Stores [payload] as if another device had written it and a sync had /// brought it here, with the other columns given. void receiveRemoteChange( String id, ByteData payload, { String? parentId, String position = 'a0', DateTime? archivedAt, DateTime? deletedAt, DateTime? starredAt, DateTime? updatedAt, }) { _rows[id] = ( id: id, payload: payload, parentId: parentId, position: position, archivedAt: archivedAt, deletedAt: deletedAt, starredAt: starredAt, updatedAt: updatedAt, ); _remoteChanges.add(null); } /// Removes the studyset [id] as if another device had deleted it and a /// sync had brought that here. void receiveRemoteDeletion(String id) { _rows.remove(id); _remoteChanges.add(null); } @override Future> all() async { if (failReads case final error?) { throw error; } return [..._rows.values]; } @override Future insert( ByteData payload, DateTime updatedAt, { String? parentId, String position = 'a0', }) async { final id = 'studyset-${_nextId++}'; _rows[id] = ( id: id, payload: payload, parentId: parentId, position: position, archivedAt: null, deletedAt: null, starredAt: null, updatedAt: updatedAt, ); writes.add((id, payload)); return id; } @override Future updatePayload( String id, ByteData payload, DateTime updatedAt, ) async { if (_rows[id] case final row?) { _rows[id] = ( id: id, payload: payload, parentId: row.parentId, position: row.position, archivedAt: row.archivedAt, deletedAt: row.deletedAt, starredAt: row.starredAt, updatedAt: updatedAt, ); writes.add((id, payload)); } } @override Future updateStarredAt( String id, DateTime? starredAt, DateTime updatedAt, ) async { if (_rows[id] case final row?) { _rows[id] = ( id: id, payload: row.payload, parentId: row.parentId, position: row.position, archivedAt: row.archivedAt, deletedAt: row.deletedAt, starredAt: starredAt, updatedAt: updatedAt, ); } } @override Future updateParent( String id, String? parentId, String position, DateTime updatedAt, ) async { if (_rows[id] case final row?) { _rows[id] = ( id: id, payload: row.payload, parentId: parentId, position: position, archivedAt: row.archivedAt, deletedAt: row.deletedAt, starredAt: row.starredAt, updatedAt: updatedAt, ); moves.add((id, parentId, position)); } } @override Future updatePosition( String id, String position, DateTime updatedAt, ) async { if (_rows[id] case final row?) { _rows[id] = ( id: id, payload: row.payload, parentId: row.parentId, position: position, archivedAt: row.archivedAt, deletedAt: row.deletedAt, starredAt: row.starredAt, updatedAt: updatedAt, ); moves.add((id, row.parentId, position)); } } @override Future updateArchivedAt( String id, DateTime? archivedAt, DateTime updatedAt, ) async { if (_rows[id] case final row?) { _rows[id] = ( id: id, payload: row.payload, parentId: row.parentId, position: row.position, archivedAt: archivedAt, deletedAt: row.deletedAt, starredAt: row.starredAt, updatedAt: updatedAt, ); } } @override Future updateDeletedAt( String id, DateTime? deletedAt, DateTime updatedAt, ) async { if (_rows[id] case final row?) { _rows[id] = ( id: id, payload: row.payload, parentId: row.parentId, position: row.position, archivedAt: row.archivedAt, deletedAt: deletedAt, starredAt: row.starredAt, updatedAt: updatedAt, ); } } @override Future delete(String id) async { _rows.remove(id); deleted.add(id); } @override Stream get remoteChanges => _remoteChanges.stream; }