Explore lists its studysets in a grid as the library does: each card in the studyset's colour along the top, its title under its secondary title, the start of its description and what it holds, then, quieter, its author's handle, the release and the licence, and a compact Add. A tap opens the summary, which shows the colour too. The Publish sheet has a Description on Explore, starting from the latest release's, else the studyset's own, and sent with the release: a studyset may introduce itself to strangers while its own description stays empty in the library. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
96 lines
2.9 KiB
Dart
96 lines
2.9 KiB
Dart
import 'package:halkyon_learn_flutter/src/core/content/rich_content.dart';
|
|
import 'package:halkyon_learn_flutter/src/feature/publish/data/publish_gateway.dart';
|
|
import 'package:halkyon_learn_flutter/src/feature/publish/model/publication.dart';
|
|
|
|
/// A [PublishGateway] in memory, on an instance whose account domain is
|
|
/// `halkyon.eu`, for the person `raisondetredev`: each publish a release
|
|
/// (unless [refusals] has one waiting), the name fixed from the first.
|
|
class FakePublishGateway({
|
|
/// The studysets published, by id.
|
|
final Map<String, Publication> publications = const {},
|
|
}) implements PublishGateway {
|
|
late final _publications = {...publications};
|
|
|
|
/// Refusals to answer the next publishes with, the first first.
|
|
final refusals = <PublishRefused>[];
|
|
|
|
/// What each publish was asked: the studyset, name and notes.
|
|
final publishes = <({String studysetId, String slug, String notes})>[];
|
|
|
|
/// The description for Explore each publish sent, in order.
|
|
final descriptions = <RichContent?>[];
|
|
|
|
/// When set, every request fails with it.
|
|
Exception? fail;
|
|
|
|
@override
|
|
Future<Publication?> publication(String studysetId) async {
|
|
if (fail case final error?) {
|
|
throw error;
|
|
}
|
|
return _publications[studysetId];
|
|
}
|
|
|
|
@override
|
|
Future<Set<String>> published() async {
|
|
if (fail case final error?) {
|
|
throw error;
|
|
}
|
|
return {
|
|
for (final MapEntry(:key, :value) in _publications.entries)
|
|
if (!value.withdrawn) key,
|
|
};
|
|
}
|
|
|
|
@override
|
|
Future<Publication> withdraw(String studysetId) async {
|
|
if (fail case final error?) {
|
|
throw error;
|
|
}
|
|
final before = _publications[studysetId]!;
|
|
return _publications[studysetId] = Publication(
|
|
publicId: before.publicId,
|
|
slug: before.slug,
|
|
location: before.location,
|
|
releases: before.releases,
|
|
withdrawn: true,
|
|
);
|
|
}
|
|
|
|
@override
|
|
Future<Publication> publish(
|
|
String studysetId, {
|
|
required String slug,
|
|
required String notes,
|
|
RichContent? description,
|
|
}) async {
|
|
if (fail case final error?) {
|
|
throw error;
|
|
}
|
|
publishes.add((studysetId: studysetId, slug: slug, notes: notes));
|
|
descriptions.add(description);
|
|
if (refusals.isNotEmpty) {
|
|
throw refusals.removeAt(0);
|
|
}
|
|
final before = _publications[studysetId];
|
|
if (before != null && before.slug != slug) {
|
|
throw PublishRefused(PublishProblem.slugFixed);
|
|
}
|
|
return _publications[studysetId] = Publication(
|
|
publicId: before?.publicId ?? 'public-$studysetId',
|
|
// A release brings a withdrawn studyset back.
|
|
slug: slug,
|
|
location: 'halkyon.eu/@raisondetredev/$slug',
|
|
releases: [
|
|
Release(
|
|
version: (before?.latest?.version ?? 0) + 1,
|
|
releasedAt: DateTime.utc(2026, 10, 9),
|
|
license: 'CC-BY-SA-4.0',
|
|
notes: notes,
|
|
description: description,
|
|
),
|
|
...?before?.releases,
|
|
],
|
|
);
|
|
}
|
|
}
|