fix(profile): the handle's hint says it is private until the profile is public (ADR 0020, D5)
All checks were successful
CI / check (push) Successful in 29m38s
CI / deploy (push) Successful in 2m3s

A handle alone is private: its page and `profiles.byHandle` answer as
for a handle nobody has until its person fills in their profile or
publishes something. The hint under it said "Others find you as @…"
all the same, also after removing a profile (D27). It now says it is
private until then, by the rule the instance's `isPublic` applies.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-10-25 00:21:35 +02:00
commit 885ba79210
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64
7 changed files with 44 additions and 6 deletions

View file

@ -485,6 +485,8 @@
"publicProfileHandleHint": "Buchstaben, Ziffern und Unterstriche, bis zu 30",
"publicProfileAddress": "Andere finden dich als @{address}",
"@publicProfileAddress": {"placeholders": {"address": {"type": "String"}}},
"publicProfileAddressPrivate": "Privat, bis du dein Profil ausfüllst oder etwas veröffentlichst; dann finden dich andere als @{address}.",
"@publicProfileAddressPrivate": {"placeholders": {"address": {"type": "String"}}},
"publicProfileHandleFixed": "Fest, seit du veröffentlicht hast: Andere verweisen darauf.",
"publicProfileBio": "Über dich",
"publicProfileLinks": "Links",

View file

@ -550,6 +550,8 @@
"publicProfileHandleHint": "Letters, digits and underscores, up to 30",
"publicProfileAddress": "Others find you as @{address}",
"@publicProfileAddress": {"placeholders": {"address": {"type": "String"}}},
"publicProfileAddressPrivate": "Private until you fill in your profile or publish something; then others find you as @{address}.",
"@publicProfileAddressPrivate": {"placeholders": {"address": {"type": "String"}}},
"publicProfileHandleFixed": "Fixed since you published: others refer to it.",
"publicProfileBio": "Bio",
"publicProfileLinks": "Links",

View file

@ -2914,6 +2914,12 @@ abstract class AppLocalizations {
/// **'Others find you as @{address}'**
String publicProfileAddress(String address);
/// No description provided for @publicProfileAddressPrivate.
///
/// In en, this message translates to:
/// **'Private until you fill in your profile or publish something; then others find you as @{address}.'**
String publicProfileAddressPrivate(String address);
/// No description provided for @publicProfileHandleFixed.
///
/// In en, this message translates to:

View file

@ -1766,6 +1766,11 @@ class AppLocalizationsDe extends AppLocalizations {
return 'Andere finden dich als @$address';
}
@override
String publicProfileAddressPrivate(String address) {
return 'Privat, bis du dein Profil ausfüllst oder etwas veröffentlichst; dann finden dich andere als @$address.';
}
@override
String get publicProfileHandleFixed =>
'Fest, seit du veröffentlicht hast: Andere verweisen darauf.';

View file

@ -1750,6 +1750,11 @@ class AppLocalizationsEn extends AppLocalizations {
return 'Others find you as @$address';
}
@override
String publicProfileAddressPrivate(String address) {
return 'Private until you fill in your profile or publish something; then others find you as @$address.';
}
@override
String get publicProfileHandleFixed =>
'Fixed since you published: others refer to it.';

View file

@ -342,6 +342,10 @@ class _ProfileFormState() extends State<_ProfileForm> {
onTap: fixed ? null : _chooseHandle,
helperText: switch (profile) {
PublicProfile(handleFixed: true) => l10n.publicProfileHandleFixed,
// Its handle alone is private (ADR 0020, D5), as the instance's
// `isPublic` has it: nothing published, nothing filled in.
final profile? when !_showsSomething(profile) =>
l10n.publicProfileAddressPrivate(profile.address),
final profile? => l10n.publicProfileAddress(profile.address),
null => l10n.publicProfileHandleFirst,
},

View file

@ -16,6 +16,12 @@ import '../../support/fake_profile_gateway.dart';
import '../../support/pump_app.dart';
import '../../support/test_dependencies.dart';
/// The handle's hint while the profile is public, and while it is not.
const publicHint = 'Others find you as @raisondetredev@halkyon.eu';
const privateHint =
'Private until you fill in your profile or publish something; then '
'others find you as @raisondetredev@halkyon.eu.';
void main() {
/// Opens the Profile tab of a person whose profile the instance answers
/// through [profiles].
@ -92,10 +98,7 @@ void main() {
await tester.tap(find.widgetWithText(FilledButton, 'Choose'));
await tester.pumpAndSettle();
expect(
find.text('Others find you as @raisondetredev@halkyon.eu'),
findsOneWidget,
);
expect(find.text(publicHint), findsOneWidget);
expect(find.text('@raisondetredev'), findsOneWidget);
expect(profiles.profile!.displayName, 'Tizian');
expect(profiles.profile!.bio, 'Learning Japanese.');
@ -244,12 +247,14 @@ void main() {
find.widgetWithText(TextField, 'https://halkyon.app'),
findsNothing,
);
// Nothing is left to remove.
// Nothing is left to remove, and the handle is private again.
expect(find.text('Remove profile'), findsNothing);
expect(find.text(privateHint), findsOneWidget);
});
testWidgets('offers no removing while nothing is filled in: the handle '
'alone is private already', (tester) async {
'alone is private already, as its hint says (ADR 0020, D5), until '
'something is filled in', (tester) async {
await showProfile(
tester,
FakeProfileGateway(
@ -262,6 +267,15 @@ void main() {
expect(find.text('@raisondetredev'), findsOneWidget);
expect(find.text('Remove profile'), findsNothing);
expect(find.text(privateHint), findsOneWidget);
expect(find.text(publicHint), findsNothing);
await tester.enterText(field('Display name'), 'Tizian');
await tester.testTextInput.receiveAction(TextInputAction.done);
await tester.pumpAndSettle();
expect(find.text(publicHint), findsOneWidget);
expect(find.text(privateHint), findsNothing);
});
testWidgets('a saved profile takes a picture as its avatar, and gives it '