feat(studyset): a studyset's marker says what the instance sees of it (ADR 0019)
The developer's decision of 21 Oct, on the library's cards and the
studyset's Share in its action row alike:
- a lock: private, end-to-end encrypted;
- an open lock: readable by the instance, not published;
- a globe: published.
The lock and the open lock open one dialog saying what that means and
changing it (Make non-private; Make private, or Publish…, which opens the
Publish sheet, while it isn't private); a topic's dialog says its privacy
is its tree's. The globe opens the Publish sheet, whose status for a
studyset not published now says so ("Not published") with an open lock,
as "Private" means something else now. Texts in en and de.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
e368bba2dd
commit
9fb1ab2f6c
2 changed files with 425 additions and 48 deletions
|
|
@ -90,19 +90,30 @@ void main() {
|
|||
await tester.pumpAndSettle();
|
||||
}
|
||||
|
||||
/// Opens the Publish sheet from Share: at once once published, else
|
||||
/// through what its privacy means, which leads there while it isn't
|
||||
/// private (ADR 0019).
|
||||
Future<void> openSheet(WidgetTester tester) async {
|
||||
await tester.tap(find.text('Share'));
|
||||
await tester.pumpAndSettle();
|
||||
if (find.text('Publish…').evaluate().isNotEmpty) {
|
||||
await tester.tap(find.text('Publish…'));
|
||||
await tester.pumpAndSettle();
|
||||
}
|
||||
}
|
||||
|
||||
testWidgets('a private studyset is published under a name made from its '
|
||||
"title, at its author's handle", (tester) async {
|
||||
testWidgets('a studyset not published is published under a name made '
|
||||
"from its title, at its author's handle", (tester) async {
|
||||
stored('japanese', 'Japanese', license: 'CC-BY-SA-4.0');
|
||||
await showStudyset(tester, 'japanese');
|
||||
expect(find.byIcon(LucideIcons.lock), findsOneWidget);
|
||||
// Readable by the instance and not published: an open lock.
|
||||
expect(find.byIcon(LucideIcons.lockOpen), findsOneWidget);
|
||||
|
||||
await openSheet(tester);
|
||||
expect(find.text('Private · only you can see it'), findsOneWidget);
|
||||
expect(
|
||||
find.text('Not published · only you see it in Learn'),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(
|
||||
find.text('Found at halkyon.eu/@raisondetredev/japanese'),
|
||||
findsOneWidget,
|
||||
|
|
@ -362,16 +373,20 @@ void main() {
|
|||
expect(publishing.publishes, hasLength(1));
|
||||
});
|
||||
|
||||
testWidgets('on a phone it is an icon that says the studyset is private', (
|
||||
tester,
|
||||
) async {
|
||||
testWidgets('on a phone it is an icon that says the studyset is not '
|
||||
'private, leading to publishing it', (tester) async {
|
||||
stored('japanese', 'Japanese', license: 'CC-BY-4.0');
|
||||
await showStudyset(tester, 'japanese', width: 400);
|
||||
|
||||
expect(find.byTooltip('Share: private'), findsOneWidget);
|
||||
await tester.tap(find.byTooltip('Share: private'));
|
||||
expect(find.byTooltip('Share: not private'), findsOneWidget);
|
||||
await tester.tap(find.byTooltip('Share: not private'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Private · only you can see it'), findsOneWidget);
|
||||
await tester.tap(find.text('Publish…'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
find.text('Not published · only you see it in Learn'),
|
||||
findsOneWidget,
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('an anonymous person is told how to publish, and the instance '
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import 'package:halkyon_learn_flutter/src/feature/studyset/model/studyset_conten
|
|||
import 'package:halkyon_learn_flutter/src/feature/studyset/widget/deleted_studyset_card.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/studyset/widget/studyset_card.dart';
|
||||
import 'package:halkyon_ui/halkyon_ui.dart';
|
||||
import 'package:lucide_icons_flutter/lucide_icons.dart';
|
||||
import 'package:material_ui/material_ui.dart';
|
||||
|
||||
import '../../../support/fake_card_gateway.dart';
|
||||
|
|
@ -85,6 +86,7 @@ void main() {
|
|||
DateTime? archivedAt,
|
||||
DateTime? starredAt,
|
||||
String? publishedAt,
|
||||
bool private = false,
|
||||
}) => gateway.receiveRemoteChange(
|
||||
id,
|
||||
encodeStudysetPayload(
|
||||
|
|
@ -100,6 +102,7 @@ void main() {
|
|||
),
|
||||
archivedAt: archivedAt,
|
||||
starredAt: starredAt,
|
||||
isPrivate: private,
|
||||
);
|
||||
|
||||
/// [finder] within the card of the studyset titled [title].
|
||||
|
|
@ -796,11 +799,13 @@ void main() {
|
|||
expect(onCard('Kanji', find.text('By @alice')), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('a lock while private, a globe once out on Explore, as the '
|
||||
'instance says', (tester) async {
|
||||
testWidgets('a lock while private, an open lock while the instance can '
|
||||
'read it and it is not published, a globe once out on Explore, as '
|
||||
'the instance says', (tester) async {
|
||||
stored('japanese', 'Japanese');
|
||||
stored('kanji', 'Kanji');
|
||||
stored('kana', 'Kana');
|
||||
stored('diary', 'Diary', private: true);
|
||||
final store = MemoryPublishedStore();
|
||||
|
||||
await showLibrary(
|
||||
|
|
@ -815,9 +820,25 @@ void main() {
|
|||
publishedStore: store,
|
||||
);
|
||||
|
||||
expect(
|
||||
onCard('Japanese', find.byIcon(LucideIcons.globe)),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(onCard('Japanese', find.byTooltip('Public')), findsOneWidget);
|
||||
expect(onCard('Kanji', find.byTooltip('Private')), findsOneWidget);
|
||||
expect(onCard('Kana', find.byTooltip('Private')), findsOneWidget);
|
||||
expect(
|
||||
onCard('Kanji', find.byIcon(LucideIcons.lockOpen)),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(
|
||||
onCard('Kanji', find.byTooltip('Not private, not published')),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(
|
||||
onCard('Kana', find.byTooltip('Not private, not published')),
|
||||
findsOneWidget,
|
||||
);
|
||||
expect(onCard('Diary', find.byIcon(LucideIcons.lock)), findsOneWidget);
|
||||
expect(onCard('Diary', find.byTooltip('Private')), findsOneWidget);
|
||||
// Remembered for when the instance can't be reached.
|
||||
expect(store.kept, {'japanese'});
|
||||
});
|
||||
|
|
@ -835,21 +856,74 @@ void main() {
|
|||
);
|
||||
|
||||
expect(onCard('Japanese', find.byTooltip('Public')), findsOneWidget);
|
||||
expect(onCard('Kanji', find.byTooltip('Private')), findsOneWidget);
|
||||
expect(
|
||||
onCard('Kanji', find.byTooltip('Not private, not published')),
|
||||
findsOneWidget,
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('the lock opens the Publish sheet', (tester) async {
|
||||
testWidgets('the open lock says the instance can read it, and leads to '
|
||||
'the Publish sheet or makes it private', (tester) async {
|
||||
stored('japanese', 'Japanese');
|
||||
gateway.canMakePrivate = true;
|
||||
await showLibrary(tester);
|
||||
|
||||
await tester.tap(onCard('Japanese', find.byTooltip('Private')));
|
||||
await tester.tap(
|
||||
onCard('Japanese', find.byTooltip('Not private, not published')),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text("“Japanese” isn't private"), findsOneWidget);
|
||||
await tester.tap(find.text('Publish…'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('Publish'), findsOneWidget);
|
||||
expect(
|
||||
find.text('Sign in to have a public profile and publish.'),
|
||||
findsOneWidget,
|
||||
);
|
||||
await tester.tapAt(Offset.zero);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(
|
||||
onCard('Japanese', find.byTooltip('Not private, not published')),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.widgetWithText(FilledButton, 'Make private'));
|
||||
await tester.pump();
|
||||
await tester.pump();
|
||||
expect(gateway.privacyChanges, [('japanese', true)]);
|
||||
});
|
||||
|
||||
testWidgets('the lock says it is private, offers no publishing, and makes '
|
||||
'it non-private', (tester) async {
|
||||
stored('diary', 'Diary', private: true);
|
||||
await showLibrary(tester);
|
||||
|
||||
await tester.tap(onCard('Diary', find.byTooltip('Private')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('“Diary” is private'), findsOneWidget);
|
||||
expect(find.text('Publish…'), findsNothing);
|
||||
await tester.tap(find.widgetWithText(FilledButton, 'Make non-private'));
|
||||
await tester.pump();
|
||||
await tester.pump();
|
||||
|
||||
expect(gateway.privacyChanges, [('diary', false)]);
|
||||
});
|
||||
|
||||
testWidgets('the globe opens the Publish sheet', (tester) async {
|
||||
stored('japanese', 'Japanese');
|
||||
await showLibrary(
|
||||
tester,
|
||||
identified: true,
|
||||
publishing: FakePublishGateway(
|
||||
publications: {'japanese': publication()},
|
||||
),
|
||||
publishedStore: MemoryPublishedStore({'japanese'}),
|
||||
);
|
||||
|
||||
await tester.tap(onCard('Japanese', find.byTooltip('Public')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('Publish'), findsOneWidget);
|
||||
expect(find.textContaining('halkyon.eu/@raisondetredev'), findsWidgets);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue