refactor(app): FeedbackPerson moves into core as PublicPerson

A second feature needs it: discussions name their writers as reports and
suggestions do, by what their public profile shows.

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-15 23:52:31 +02:00
commit 25237b8011
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64
7 changed files with 29 additions and 21 deletions

View file

@ -0,0 +1,15 @@
import 'package:equatable/equatable.dart';
/// Someone writing in public (reports, suggestions, discussions), as their
/// public profile shows them.
final class const PublicPerson({
required final String handle,
final String displayName = '',
final String? avatarUrl,
}) with Equatable {
/// How they are named: their display name, else their handle.
String get name => displayName.isEmpty ? '@$handle' : displayName;
@override
List<Object?> get props => [handle, displayName, avatarUrl];
}

View file

@ -2,6 +2,7 @@ import 'dart:developer';
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:halkyon_learn_flutter/src/core/profile/public_person.dart';
import 'package:halkyon_learn_flutter/src/feature/feedback/data/feedback_repository.dart'; import 'package:halkyon_learn_flutter/src/feature/feedback/data/feedback_repository.dart';
import 'package:halkyon_learn_flutter/src/feature/feedback/model/feedback.dart'; import 'package:halkyon_learn_flutter/src/feature/feedback/model/feedback.dart';
@ -198,7 +199,7 @@ final class const FeedbackListEventAccepted(final FeedbackThread thread)
} }
/// The author keeps [person] from writing on their studysets. /// The author keeps [person] from writing on their studysets.
final class const FeedbackListEventBlocked(final FeedbackPerson person) final class const FeedbackListEventBlocked(final PublicPerson person)
extends FeedbackListEvent { extends FeedbackListEvent {
@override @override
List<Object?> get props => [person]; List<Object?> get props => [person];

View file

@ -5,6 +5,7 @@ import 'package:crypto/crypto.dart';
import 'package:halkyon_learn_flutter/src/core/asset/data/asset_repository.dart'; import 'package:halkyon_learn_flutter/src/core/asset/data/asset_repository.dart';
import 'package:halkyon_learn_flutter/src/core/content/published_ref.dart'; import 'package:halkyon_learn_flutter/src/core/content/published_ref.dart';
import 'package:halkyon_learn_flutter/src/core/content/rich_content.dart'; import 'package:halkyon_learn_flutter/src/core/content/rich_content.dart';
import 'package:halkyon_learn_flutter/src/core/profile/public_person.dart';
import 'package:halkyon_learn_flutter/src/feature/card/data/card_payload.dart'; import 'package:halkyon_learn_flutter/src/feature/card/data/card_payload.dart';
import 'package:halkyon_learn_flutter/src/feature/card/data/card_repository.dart'; import 'package:halkyon_learn_flutter/src/feature/card/data/card_repository.dart';
import 'package:halkyon_learn_flutter/src/feature/card/model/card_content.dart'; import 'package:halkyon_learn_flutter/src/feature/card/model/card_content.dart';
@ -244,7 +245,7 @@ class FeedbackRepository(
_server.markSeen(thread.threadId); _server.markSeen(thread.threadId);
/// Keeps [person] from writing on the person's published studysets. /// Keeps [person] from writing on the person's published studysets.
Future<void> block(FeedbackPerson person) => _server.block(person.handle); Future<void> block(PublicPerson person) => _server.block(person.handle);
/// Lets the person with [handle] write on them again. /// Lets the person with [handle] write on them again.
Future<void> unblock(String handle) => _server.unblock(handle); Future<void> unblock(String handle) => _server.unblock(handle);

View file

@ -2,6 +2,7 @@ import 'dart:developer';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:halkyon_learn_client/halkyon_learn_client.dart' as protocol; import 'package:halkyon_learn_client/halkyon_learn_client.dart' as protocol;
import 'package:halkyon_learn_flutter/src/core/profile/public_person.dart';
import 'package:halkyon_learn_flutter/src/feature/feedback/data/feedback_gateway.dart'; import 'package:halkyon_learn_flutter/src/feature/feedback/data/feedback_gateway.dart';
import 'package:halkyon_learn_flutter/src/feature/feedback/data/feedback_payload.dart'; import 'package:halkyon_learn_flutter/src/feature/feedback/data/feedback_payload.dart';
import 'package:halkyon_learn_flutter/src/feature/feedback/model/feedback.dart'; import 'package:halkyon_learn_flutter/src/feature/feedback/model/feedback.dart';
@ -105,7 +106,7 @@ class ServerpodFeedbackGateway(final protocol.Client _client)
} }
} }
FeedbackPerson _person(protocol.FeedbackPerson person) => FeedbackPerson( PublicPerson _person(protocol.FeedbackPerson person) => PublicPerson(
handle: person.handle, handle: person.handle,
displayName: person.displayName, displayName: person.displayName,
avatarUrl: person.avatarUrl, avatarUrl: person.avatarUrl,

View file

@ -1,4 +1,5 @@
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:halkyon_learn_flutter/src/core/profile/public_person.dart';
import 'package:halkyon_learn_flutter/src/feature/card/model/card_content.dart'; import 'package:halkyon_learn_flutter/src/feature/card/model/card_content.dart';
/// What a thread of feedback on a published studyset is (ADR 0005, rule 6). /// What a thread of feedback on a published studyset is (ADR 0005, rule 6).
@ -42,19 +43,6 @@ final class const FeedbackTarget({
List<Object?> get props => [kind, item, version]; List<Object?> get props => [kind, item, version];
} }
/// Someone in a thread, as their public profile shows them.
final class const FeedbackPerson({
required final String handle,
final String displayName = '',
final String? avatarUrl,
}) with Equatable {
/// How they are named: their display name, else their handle.
String get name => displayName.isEmpty ? '@$handle' : displayName;
@override
List<Object?> get props => [handle, displayName, avatarUrl];
}
/// A file the content a suggestion proposes names: the writer's asset row, /// A file the content a suggestion proposes names: the writer's asset row,
/// and what the author needs to take it into their own files. /// and what the author needs to take it into their own files.
final class const FeedbackFile({ final class const FeedbackFile({
@ -70,7 +58,7 @@ final class const FeedbackFile({
/// A reply in a thread: by its writer or by the studyset's author. /// A reply in a thread: by its writer or by the studyset's author.
final class const FeedbackMessage({ final class const FeedbackMessage({
required final String id, required final String id,
required final FeedbackPerson by, required final PublicPerson by,
required final bool fromAuthor, required final bool fromAuthor,
required final String body, required final String body,
required final DateTime createdAt, required final DateTime createdAt,
@ -88,7 +76,7 @@ final class const FeedbackThread({
required final String studysetTitle, required final String studysetTitle,
required final String location, required final String location,
required final FeedbackKind kind, required final FeedbackKind kind,
required final FeedbackPerson writer, required final PublicPerson writer,
required final FeedbackTarget target, required final FeedbackTarget target,
required final DateTime createdAt, required final DateTime createdAt,

View file

@ -6,6 +6,7 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:halkyon_learn_flutter/src/core/asset/data/asset_repository.dart'; import 'package:halkyon_learn_flutter/src/core/asset/data/asset_repository.dart';
import 'package:halkyon_learn_flutter/src/core/content/published_ref.dart'; import 'package:halkyon_learn_flutter/src/core/content/published_ref.dart';
import 'package:halkyon_learn_flutter/src/core/content/rich_content.dart'; import 'package:halkyon_learn_flutter/src/core/content/rich_content.dart';
import 'package:halkyon_learn_flutter/src/core/profile/public_person.dart';
import 'package:halkyon_learn_flutter/src/feature/card/data/card_repository.dart'; import 'package:halkyon_learn_flutter/src/feature/card/data/card_repository.dart';
import 'package:halkyon_learn_flutter/src/feature/card/model/card_content.dart'; import 'package:halkyon_learn_flutter/src/feature/card/model/card_content.dart';
import 'package:halkyon_learn_flutter/src/feature/feedback/data/feedback_repository.dart'; import 'package:halkyon_learn_flutter/src/feature/feedback/data/feedback_repository.dart';
@ -148,7 +149,7 @@ void main() {
studysetTitle: 'Japanese', studysetTitle: 'Japanese',
location: 'halkyon.eu/@alice/japanese', location: 'halkyon.eu/@alice/japanese',
kind: FeedbackKind.suggestion, kind: FeedbackKind.suggestion,
writer: const FeedbackPerson(handle: 'bob'), writer: const PublicPerson(handle: 'bob'),
target: FeedbackTarget( target: FeedbackTarget(
kind: FeedbackTargetKind.card, kind: FeedbackTargetKind.card,
item: id, item: id,
@ -193,7 +194,7 @@ void main() {
studysetTitle: 'Japanese', studysetTitle: 'Japanese',
location: 'halkyon.eu/@alice/japanese', location: 'halkyon.eu/@alice/japanese',
kind: FeedbackKind.suggestion, kind: FeedbackKind.suggestion,
writer: const FeedbackPerson(handle: 'bob'), writer: const PublicPerson(handle: 'bob'),
target: const FeedbackTarget( target: const FeedbackTarget(
kind: FeedbackTargetKind.note, kind: FeedbackTargetKind.note,
item: 'gone', item: 'gone',

View file

@ -1,6 +1,7 @@
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:halkyon_learn_flutter/src/core/content/published_ref.dart'; import 'package:halkyon_learn_flutter/src/core/content/published_ref.dart';
import 'package:halkyon_learn_flutter/src/core/content/rich_content.dart'; import 'package:halkyon_learn_flutter/src/core/content/rich_content.dart';
import 'package:halkyon_learn_flutter/src/core/profile/public_person.dart';
import 'package:halkyon_learn_flutter/src/core/router/route_paths.dart'; import 'package:halkyon_learn_flutter/src/core/router/route_paths.dart';
import 'package:halkyon_learn_flutter/src/feature/auth/model/auth_status.dart'; import 'package:halkyon_learn_flutter/src/feature/auth/model/auth_status.dart';
import 'package:halkyon_learn_flutter/src/feature/card/data/card_repository.dart'; import 'package:halkyon_learn_flutter/src/feature/card/data/card_repository.dart';
@ -36,7 +37,7 @@ FeedbackThread suggestion(String item, String back, {bool unseen = false}) =>
studysetTitle: 'Japanese', studysetTitle: 'Japanese',
location: 'halkyon.eu/@alice/japanese', location: 'halkyon.eu/@alice/japanese',
kind: FeedbackKind.suggestion, kind: FeedbackKind.suggestion,
writer: const FeedbackPerson(handle: 'bob', displayName: 'Bob'), writer: const PublicPerson(handle: 'bob', displayName: 'Bob'),
target: FeedbackTarget( target: FeedbackTarget(
kind: FeedbackTargetKind.card, kind: FeedbackTargetKind.card,
item: item, item: item,