import 'dart:typed_data'; import 'package:halkyon_learn_flutter/src/feature/profile/data/profile_gateway.dart'; import 'package:halkyon_learn_flutter/src/feature/profile/model/public_profile.dart'; /// A [ProfileGateway] in memory, on an instance whose account domain is /// `halkyon.eu`: one profile, refusing the handles others have (whatever /// their case) and, once its handle is fixed, any other handle. class FakeProfileGateway({ /// The person's profile; null while they have none. var PublicProfile? profile, /// Handles others have. final Set taken = const {}, }) implements ProfileGateway { /// When set, every request fails with it. Exception? fail; @override Future mine() async { if (fail case final error?) { throw error; } return profile; } /// The handles checked, in order. final checked = []; @override Future checkHandle(String handle) async { if (fail case final error?) { throw error; } checked.add(handle); return _problemOf(handle); } ProfileProblem? _problemOf(String handle) { final current = profile; if (!RegExp(r'^[A-Za-z0-9_]{1,30}$').hasMatch(handle)) { return ProfileProblem.handleInvalid; } if (handle.toLowerCase() == 'admin') { return ProfileProblem.handleReserved; } if (taken.any((other) => other.toLowerCase() == handle.toLowerCase())) { return ProfileProblem.handleTaken; } if (current != null && current.handleFixed && current.handle.toLowerCase() != handle.toLowerCase()) { return ProfileProblem.published; } return null; } /// Every profile saved, in order. final saves = []; @override Future save({ required String handle, required String displayName, required String bio, required List links, }) async { if (fail case final error?) { throw error; } final current = profile; if (_problemOf(handle) case final problem?) { throw ProfileRefused(problem); } final saved = profile = PublicProfile( handle: handle, address: '$handle@halkyon.eu', displayName: displayName, bio: bio, links: links, handleFixed: current?.handleFixed ?? false, ); saves.add(saved); return saved; } /// The avatars set, in order. final avatars = []; @override Future setAvatar(Uint8List png) async { if (fail case final error?) { throw error; } avatars.add(png); final current = profile!; return profile = PublicProfile( handle: current.handle, address: current.address, displayName: current.displayName, bio: current.bio, links: current.links, avatarUrl: 'https://learn.halkyon.eu/avatars/${avatars.length}.png', handleFixed: current.handleFixed, ); } @override Future removeAvatar() async { final current = profile!; return profile = PublicProfile( handle: current.handle, address: current.address, displayName: current.displayName, bio: current.bio, links: current.links, handleFixed: current.handleFixed, ); } @override Future remove() async { if (fail case final error?) { throw error; } if (profile?.handleFixed ?? false) { throw ProfileRefused(ProfileProblem.published); } profile = null; } }