halkyon/halkyon_learn_client/lib/src/protocol/discussion/discussion_target.dart
Tizian 「ティツィアーン」 5efa552489
feat(discussions): questions on published studysets, answered by learners
A learner asks about a published studyset, a topic in it, or one card,
note or step of a release, and others answer, as on Stack Exchange
(ADR 0013): questions and answers in the app's editor without images,
sounds or videos, comments of up to 600 characters under the question
and each answer. There are no votes: the asker accepts an answer, which
comes first, then the oldest; the author's posts are marked. The
instance reads from git's file list which topics a question's target
sits in, so a topic lists what is asked within it and below it.

Posts live in two server-only tables, written through endpoints, so the
synced tables stay as they are and v0.17.0 keeps syncing. Everyone
signed in reads; writing needs an identity and a public profile; the
studyset's author hides posts and blocks people with feedback's blocks;
a withdrawn studyset takes no new questions; anyone writes at most 30
posts an hour. A post with others' replies under it is emptied when
deleted, else deleted; deletePerson deletes what a person wrote the same
way, and a published studyset's deletion takes its discussions with it.

The migration adds Serverpod's gen_random_uuid_v7(), discussion_post
and discussion_seen with their indexes and cascading foreign keys, and
changes nothing else.

In the app, discussions open from a copy's studyset or topic menu, a
studied card's "Ask about this", Explore's summary and the Publish
sheet; the Profile tab's inbox lists those the person follows, and its
count includes what is new in them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-10-17 19:46:32 +02:00

106 lines
2.7 KiB
Dart

/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */
/* To generate run: "serverpod generate" */
// ignore_for_file: implementation_imports
// ignore_for_file: library_private_types_in_public_api
// ignore_for_file: non_constant_identifier_names
// ignore_for_file: public_member_api_docs
// ignore_for_file: type_literal_in_constant_pattern
// ignore_for_file: use_super_parameters
// ignore_for_file: invalid_use_of_internal_member
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:serverpod_client/serverpod_client.dart' as _isc;
/// What a question is about: the published studyset or a topic in it
/// ('studyset'), or one of its cards, notes or steps ('card', 'note',
/// 'step'), by its id in release [version].
abstract class DiscussionTarget
implements _isc.SerializableModel, _isc.ProtocolSerialization {
DiscussionTarget._({
required this.kind,
required this.item,
required this.version,
});
factory DiscussionTarget({
required String kind,
required String item,
required int version,
}) = _DiscussionTargetImpl;
factory DiscussionTarget.fromJson(Map<String, dynamic> jsonSerialization) {
return DiscussionTarget(
kind: jsonSerialization['kind'] as String,
item: jsonSerialization['item'] as String,
version: jsonSerialization['version'] as int,
);
}
String kind;
String item;
int version;
/// Returns a shallow copy of this [DiscussionTarget]
/// with some or all fields replaced by the given arguments.
@_isc.useResult
DiscussionTarget copyWith({
String? kind,
String? item,
int? version,
});
@override
Map<String, dynamic> toJson() {
return {
'__className__': 'DiscussionTarget',
'kind': kind,
'item': item,
'version': version,
};
}
@override
Map<String, dynamic> toJsonForProtocol() {
return {
'__className__': 'DiscussionTarget',
'kind': kind,
'item': item,
'version': version,
};
}
@override
String toString() {
return _isc.SerializationManager.encode(this);
}
}
class _DiscussionTargetImpl extends DiscussionTarget {
_DiscussionTargetImpl({
required String kind,
required String item,
required int version,
}) : super._(
kind: kind,
item: item,
version: version,
);
/// Returns a shallow copy of this [DiscussionTarget]
/// with some or all fields replaced by the given arguments.
@_isc.useResult
@override
DiscussionTarget copyWith({
String? kind,
String? item,
int? version,
}) {
return DiscussionTarget(
kind: kind ?? this.kind,
item: item ?? this.item,
version: version ?? this.version,
);
}
}