Each card's foot now says who made the studyset: "By you", or for a copy of a published studyset its author's handle. Beside the star, a lock or a globe says whether it is out on Explore, and opens the Publish sheet. The instance says which of the person's studysets are published and not withdrawn (`PublishEndpoint.published`, additive: older apps don't call it), and the app remembers that in the person's folder, so the library shows it offline too; publishing, withdrawing and looking one up keep it current. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MMm7usAo6q9ZZRoPkWjoxi Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
89 lines
2.6 KiB
Dart
89 lines
2.6 KiB
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})>[];
|
|
|
|
/// 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,
|
|
}) async {
|
|
if (fail case final error?) {
|
|
throw error;
|
|
}
|
|
publishes.add((studysetId: studysetId, slug: slug, notes: notes));
|
|
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,
|
|
),
|
|
...?before?.releases,
|
|
],
|
|
);
|
|
}
|
|
}
|