feat(library): who made a studyset, and whether it is public

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>
This commit is contained in:
Tizian 「ティツィアーン」 2026-10-10 05:17:10 +02:00
commit bc3e8d9ac3
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -17,6 +17,7 @@ import '../../support/fake_learning_path_gateway.dart';
import '../../support/fake_note_gateway.dart';
import '../../support/fake_profile_gateway.dart';
import '../../support/fake_publish_gateway.dart';
import '../../support/memory_published_store.dart';
RichContent text(String text) => RichContent.plain(text);
@ -37,7 +38,7 @@ void main() {
});
PublishBloc bloc() => PublishBloc(
PublishRepository(publishing),
PublishRepository(publishing, MemoryPublishedStore()),
ProfileRepository(
FakeProfileGateway(
profile: const PublicProfile(
@ -108,7 +109,7 @@ void main() {
expect(ready.outcome, PublishOutcome.published);
expect(ready.publication!.latest!.version, 1);
expect(calls, ['sync']);
expect(publishing.published.single.notes, 'First lessons.');
expect(publishing.publishes.single.notes, 'First lessons.');
await publisher.close();
});
@ -123,7 +124,7 @@ void main() {
final ready = await publish(publisher);
expect(ready.outcome, PublishOutcome.published);
expect(publishing.published, hasLength(2));
expect(publishing.publishes, hasLength(2));
expect(cardGateway.written.last.parents, hasLength(2));
expect((await cards.cardsOf('japanese')).single.heads, hasLength(1));
expect(calls, ['sync', 'sync']);
@ -150,7 +151,7 @@ void main() {
title: '猫',
),
]);
expect(publishing.published, hasLength(1));
expect(publishing.publishes, hasLength(1));
expect(cardGateway.written, hasLength(written));
await publisher.close();
});