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>
This commit is contained in:
parent
25237b8011
commit
5efa552489
8 changed files with 28214 additions and 27 deletions
|
|
@ -32,6 +32,14 @@ import 'package:halkyon_learn_client/src/protocol/dictionary/dictionary_key_hit.
|
|||
as _ii0vb6vg;
|
||||
import 'package:halkyon_learn_client/src/protocol/dictionary/dictionary_source.dart'
|
||||
as _i8vj64sp;
|
||||
import 'package:halkyon_learn_client/src/protocol/discussion/discussion_refusal.dart'
|
||||
as _ikbvm73t;
|
||||
import 'package:halkyon_learn_client/src/protocol/discussion/discussion_summary.dart'
|
||||
as _i7lxdcg2;
|
||||
import 'package:halkyon_learn_client/src/protocol/discussion/discussion_target.dart'
|
||||
as _iy0rtcfg;
|
||||
import 'package:halkyon_learn_client/src/protocol/discussion/discussion_view.dart'
|
||||
as _i31gsvwz;
|
||||
import 'package:halkyon_learn_client/src/protocol/explore/explore_entry.dart'
|
||||
as _iyigb6vc;
|
||||
import 'package:halkyon_learn_client/src/protocol/explore/explore_query.dart'
|
||||
|
|
@ -508,6 +516,214 @@ class EndpointDictionary extends _isc.EndpointRef {
|
|||
);
|
||||
}
|
||||
|
||||
/// A published studyset's discussions (ADR 0013), for everyone signed in to
|
||||
/// read: questions about it, a topic in it or one of its items, with their
|
||||
/// answers and comments; but for what its author hid, and what people the
|
||||
/// author blocked wrote.
|
||||
/// {@category Endpoint}
|
||||
class EndpointDiscussions extends _isc.EndpointRef {
|
||||
EndpointDiscussions(_isc.EndpointCaller caller) : super(caller);
|
||||
|
||||
@override
|
||||
String get name => 'discussions';
|
||||
|
||||
/// The questions on the published studyset [publicId], those last active
|
||||
/// first, [discussionPage] to a [page] (the first without): within [topic] (a studyset of
|
||||
/// the release, by its id: questions about it and what is inside it),
|
||||
/// about [item] alone, or with [query] in their titles. A page may hold
|
||||
/// fewer than it could, when the caller may not see some. Throws
|
||||
/// [NotFoundException] for a studyset never published.
|
||||
_ida.Future<List<_i7lxdcg2.DiscussionSummary>> list(
|
||||
_isc.UuidValue publicId, {
|
||||
String? topic,
|
||||
_iy0rtcfg.DiscussionTarget? item,
|
||||
String? query,
|
||||
int? page,
|
||||
}) => caller.callServerEndpoint<List<_i7lxdcg2.DiscussionSummary>>(
|
||||
'discussions',
|
||||
'list',
|
||||
{
|
||||
'publicId': publicId,
|
||||
'topic': topic,
|
||||
'item': item,
|
||||
'query': query,
|
||||
'page': page,
|
||||
},
|
||||
);
|
||||
|
||||
/// The question [questionId] with its answers and comments, as the caller
|
||||
/// may see them. Throws [NotFoundException] for one they may not see.
|
||||
_ida.Future<_i31gsvwz.DiscussionView> read(_isc.UuidValue questionId) =>
|
||||
caller.callServerEndpoint<_i31gsvwz.DiscussionView>(
|
||||
'discussions',
|
||||
'read',
|
||||
{'questionId': questionId},
|
||||
);
|
||||
|
||||
/// Why the caller may not ask about the published studyset [publicId];
|
||||
/// null when they may. Throws [NotFoundException] for one never
|
||||
/// published.
|
||||
_ida.Future<_ikbvm73t.DiscussionRefusal?> askRefusal(
|
||||
_isc.UuidValue publicId,
|
||||
) => caller.callServerEndpoint<_ikbvm73t.DiscussionRefusal?>(
|
||||
'discussions',
|
||||
'askRefusal',
|
||||
{'publicId': publicId},
|
||||
);
|
||||
}
|
||||
|
||||
/// Writing in published studysets' discussions (ADR 0013), and the inbox
|
||||
/// of those a person follows. For people with an identity and a public
|
||||
/// profile, whom the studyset's author hasn't blocked: posts name their
|
||||
/// writer.
|
||||
/// {@category Endpoint}
|
||||
class EndpointDiscussion extends _isc.EndpointRef {
|
||||
EndpointDiscussion(_isc.EndpointCaller caller) : super(caller);
|
||||
|
||||
@override
|
||||
String get name => 'discussion';
|
||||
|
||||
/// Asks [title], with [body] (rich text), about [target] of the published
|
||||
/// studyset [publicId] (the studyset as a whole when it names no item);
|
||||
/// returns the question's id. Throws
|
||||
/// [DiscussionRefusedException] when the caller may not, the text won't
|
||||
/// do, the release lacks the target or the studyset was withdrawn, and
|
||||
/// [NotFoundException] for a studyset never published.
|
||||
_ida.Future<_isc.UuidValue> ask(
|
||||
_isc.UuidValue publicId,
|
||||
_iy0rtcfg.DiscussionTarget target,
|
||||
String title,
|
||||
String body,
|
||||
) => caller.callServerEndpoint<_isc.UuidValue>(
|
||||
'discussion',
|
||||
'ask',
|
||||
{
|
||||
'publicId': publicId,
|
||||
'target': target,
|
||||
'title': title,
|
||||
'body': body,
|
||||
},
|
||||
);
|
||||
|
||||
/// Answers the question [questionId] with [body] (rich text); returns the
|
||||
/// answer's id. Throws [NotFoundException] for a question the caller
|
||||
/// can't see, or one deleted, and [DiscussionRefusedException] when they
|
||||
/// may not write or the text won't do.
|
||||
_ida.Future<_isc.UuidValue> answer(
|
||||
_isc.UuidValue questionId,
|
||||
String body,
|
||||
) => caller.callServerEndpoint<_isc.UuidValue>(
|
||||
'discussion',
|
||||
'answer',
|
||||
{
|
||||
'questionId': questionId,
|
||||
'body': body,
|
||||
},
|
||||
);
|
||||
|
||||
/// Comments [text] (plain text) on [onId], a question or an answer;
|
||||
/// returns the comment's id. Throws [NotFoundException] for something the
|
||||
/// caller can't see, a comment, or something deleted, and
|
||||
/// [DiscussionRefusedException] when they may not write or the text won't
|
||||
/// do.
|
||||
_ida.Future<_isc.UuidValue> comment(
|
||||
_isc.UuidValue onId,
|
||||
String text,
|
||||
) => caller.callServerEndpoint<_isc.UuidValue>(
|
||||
'discussion',
|
||||
'comment',
|
||||
{
|
||||
'onId': onId,
|
||||
'text': text,
|
||||
},
|
||||
);
|
||||
|
||||
/// Changes what the caller's post [postId] says to [body] (rich text, a
|
||||
/// comment's plain text), a question's title to [title] where given.
|
||||
/// Throws [NotFoundException] for a post that isn't theirs, or one
|
||||
/// deleted, and [DiscussionRefusedException] when the text won't do.
|
||||
_ida.Future<void> edit(
|
||||
_isc.UuidValue postId,
|
||||
String body, {
|
||||
String? title,
|
||||
}) => caller.callServerEndpoint<void>(
|
||||
'discussion',
|
||||
'edit',
|
||||
{
|
||||
'postId': postId,
|
||||
'body': body,
|
||||
'title': title,
|
||||
},
|
||||
);
|
||||
|
||||
/// Deletes the caller's post [postId]: for good when nobody else replied
|
||||
/// under it, else its title, text and writer go and it stays for the
|
||||
/// replies. Throws [NotFoundException] for a post that isn't theirs.
|
||||
_ida.Future<void> delete(_isc.UuidValue postId) =>
|
||||
caller.callServerEndpoint<void>(
|
||||
'discussion',
|
||||
'delete',
|
||||
{'postId': postId},
|
||||
);
|
||||
|
||||
/// Accepts [answerId] as the answer to the caller's question
|
||||
/// [questionId], in place of any before; null accepts none. Throws
|
||||
/// [NotFoundException] for a question that isn't theirs, or an answer
|
||||
/// that isn't one of its own.
|
||||
_ida.Future<void> accept(
|
||||
_isc.UuidValue questionId,
|
||||
_isc.UuidValue? answerId,
|
||||
) => caller.callServerEndpoint<void>(
|
||||
'discussion',
|
||||
'accept',
|
||||
{
|
||||
'questionId': questionId,
|
||||
'answerId': answerId,
|
||||
},
|
||||
);
|
||||
|
||||
/// Hides the post [postId] on one of the caller's published studysets
|
||||
/// ([hidden]), or shows it again: hidden, only its writer and the author
|
||||
/// see it. Throws [NotFoundException] for a post on anyone else's.
|
||||
_ida.Future<void> hide(
|
||||
_isc.UuidValue postId,
|
||||
bool hidden,
|
||||
) => caller.callServerEndpoint<void>(
|
||||
'discussion',
|
||||
'hide',
|
||||
{
|
||||
'postId': postId,
|
||||
'hidden': hidden,
|
||||
},
|
||||
);
|
||||
|
||||
/// The discussions the caller follows, those last active first: those on
|
||||
/// their published studysets, and those they asked, answered or commented
|
||||
/// in; each saying whether others wrote in it since they last read it.
|
||||
_ida.Future<List<_i7lxdcg2.DiscussionSummary>> inbox() =>
|
||||
caller.callServerEndpoint<List<_i7lxdcg2.DiscussionSummary>>(
|
||||
'discussion',
|
||||
'inbox',
|
||||
{},
|
||||
);
|
||||
|
||||
/// How many discussions of the caller's inbox have something new.
|
||||
_ida.Future<int> unseen() => caller.callServerEndpoint<int>(
|
||||
'discussion',
|
||||
'unseen',
|
||||
{},
|
||||
);
|
||||
|
||||
/// Records that the caller has read the discussion [questionId] as it is
|
||||
/// now. Throws [NotFoundException] for a question there isn't.
|
||||
_ida.Future<void> markSeen(_isc.UuidValue questionId) =>
|
||||
caller.callServerEndpoint<void>(
|
||||
'discussion',
|
||||
'markSeen',
|
||||
{'questionId': questionId},
|
||||
);
|
||||
}
|
||||
|
||||
/// Explore (ADR 0005, rule 4): the studysets published on this instance,
|
||||
/// found by fit (search, languages, kinds of content), never by popularity,
|
||||
/// the newest release first; and their releases, to learn from as a copy.
|
||||
|
|
@ -934,6 +1150,8 @@ class Client extends _isc.ServerpodClientShared {
|
|||
gitHubSignIn = EndpointGitHubSignIn(this);
|
||||
gitHubUpgrade = EndpointGitHubUpgrade(this);
|
||||
dictionary = EndpointDictionary(this);
|
||||
discussions = EndpointDiscussions(this);
|
||||
discussion = EndpointDiscussion(this);
|
||||
explore = EndpointExplore(this);
|
||||
feedback = EndpointFeedback(this);
|
||||
inbox = EndpointInbox(this);
|
||||
|
|
@ -964,6 +1182,10 @@ class Client extends _isc.ServerpodClientShared {
|
|||
|
||||
late final EndpointDictionary dictionary;
|
||||
|
||||
late final EndpointDiscussions discussions;
|
||||
|
||||
late final EndpointDiscussion discussion;
|
||||
|
||||
late final EndpointExplore explore;
|
||||
|
||||
late final EndpointFeedback feedback;
|
||||
|
|
@ -992,6 +1214,8 @@ class Client extends _isc.ServerpodClientShared {
|
|||
'gitHubSignIn': gitHubSignIn,
|
||||
'gitHubUpgrade': gitHubUpgrade,
|
||||
'dictionary': dictionary,
|
||||
'discussions': discussions,
|
||||
'discussion': discussion,
|
||||
'explore': explore,
|
||||
'feedback': feedback,
|
||||
'inbox': inbox,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,239 @@
|
|||
/* 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:halkyon_learn_client/src/protocol/protocol.dart' as _itx5j3f5;
|
||||
import 'package:serverpod_client/serverpod_client.dart' as _isc;
|
||||
import '../feedback/feedback_person.dart' as _i4q3oto5;
|
||||
|
||||
/// A question, an answer or a comment as the app shows it.
|
||||
abstract class DiscussionPostView
|
||||
implements _isc.SerializableModel, _isc.ProtocolSerialization {
|
||||
DiscussionPostView._({
|
||||
required this.id,
|
||||
required this.kind,
|
||||
this.parentId,
|
||||
this.by,
|
||||
required this.fromAuthor,
|
||||
this.title,
|
||||
required this.body,
|
||||
required this.createdAt,
|
||||
this.editedAt,
|
||||
required this.deleted,
|
||||
required this.hidden,
|
||||
required this.mine,
|
||||
});
|
||||
|
||||
factory DiscussionPostView({
|
||||
required _isc.UuidValue id,
|
||||
required String kind,
|
||||
_isc.UuidValue? parentId,
|
||||
_i4q3oto5.FeedbackPerson? by,
|
||||
required bool fromAuthor,
|
||||
String? title,
|
||||
required String body,
|
||||
required DateTime createdAt,
|
||||
DateTime? editedAt,
|
||||
required bool deleted,
|
||||
required bool hidden,
|
||||
required bool mine,
|
||||
}) = _DiscussionPostViewImpl;
|
||||
|
||||
factory DiscussionPostView.fromJson(Map<String, dynamic> jsonSerialization) {
|
||||
return DiscussionPostView(
|
||||
id: _isc.UuidValueJsonExtension.fromJson(jsonSerialization['id']),
|
||||
kind: jsonSerialization['kind'] as String,
|
||||
parentId: jsonSerialization['parentId'] == null
|
||||
? null
|
||||
: _isc.UuidValueJsonExtension.fromJson(jsonSerialization['parentId']),
|
||||
by: jsonSerialization['by'] == null
|
||||
? null
|
||||
: _itx5j3f5.Protocol().deserialize<_i4q3oto5.FeedbackPerson>(
|
||||
jsonSerialization['by'],
|
||||
),
|
||||
fromAuthor: _isc.BoolJsonExtension.fromJson(
|
||||
jsonSerialization['fromAuthor'],
|
||||
),
|
||||
title: jsonSerialization['title'] as String?,
|
||||
body: jsonSerialization['body'] as String,
|
||||
createdAt: _isc.DateTimeJsonExtension.fromJson(
|
||||
jsonSerialization['createdAt'],
|
||||
),
|
||||
editedAt: jsonSerialization['editedAt'] == null
|
||||
? null
|
||||
: _isc.DateTimeJsonExtension.fromJson(jsonSerialization['editedAt']),
|
||||
deleted: _isc.BoolJsonExtension.fromJson(jsonSerialization['deleted']),
|
||||
hidden: _isc.BoolJsonExtension.fromJson(jsonSerialization['hidden']),
|
||||
mine: _isc.BoolJsonExtension.fromJson(jsonSerialization['mine']),
|
||||
);
|
||||
}
|
||||
|
||||
_isc.UuidValue id;
|
||||
|
||||
/// 'question', 'answer' or 'comment'.
|
||||
String kind;
|
||||
|
||||
/// What a comment is on, its question or an answer; null otherwise.
|
||||
_isc.UuidValue? parentId;
|
||||
|
||||
/// Who wrote it, as their public profile shows them; null once deleted,
|
||||
/// or when its writer has no public profile any more.
|
||||
_i4q3oto5.FeedbackPerson? by;
|
||||
|
||||
/// Whether its writer is the published studyset's author.
|
||||
bool fromAuthor;
|
||||
|
||||
/// A question's title.
|
||||
String? title;
|
||||
|
||||
/// What it says: rich text (the document's JSON), a comment's plain text;
|
||||
/// empty once deleted.
|
||||
String body;
|
||||
|
||||
/// When it was written and last edited, in UTC.
|
||||
DateTime createdAt;
|
||||
|
||||
DateTime? editedAt;
|
||||
|
||||
bool deleted;
|
||||
|
||||
/// Whether the author hid it: then only its writer and the author see it.
|
||||
bool hidden;
|
||||
|
||||
/// Whether the viewer wrote it.
|
||||
bool mine;
|
||||
|
||||
/// Returns a shallow copy of this [DiscussionPostView]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
DiscussionPostView copyWith({
|
||||
_isc.UuidValue? id,
|
||||
String? kind,
|
||||
_isc.UuidValue? parentId,
|
||||
_i4q3oto5.FeedbackPerson? by,
|
||||
bool? fromAuthor,
|
||||
String? title,
|
||||
String? body,
|
||||
DateTime? createdAt,
|
||||
DateTime? editedAt,
|
||||
bool? deleted,
|
||||
bool? hidden,
|
||||
bool? mine,
|
||||
});
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'__className__': 'DiscussionPostView',
|
||||
'id': id.toJson(),
|
||||
'kind': kind,
|
||||
if (parentId != null) 'parentId': parentId?.toJson(),
|
||||
if (by != null) 'by': by?.toJson(),
|
||||
'fromAuthor': fromAuthor,
|
||||
if (title != null) 'title': title,
|
||||
'body': body,
|
||||
'createdAt': createdAt.toJson(),
|
||||
if (editedAt != null) 'editedAt': editedAt?.toJson(),
|
||||
'deleted': deleted,
|
||||
'hidden': hidden,
|
||||
'mine': mine,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJsonForProtocol() {
|
||||
return {
|
||||
'__className__': 'DiscussionPostView',
|
||||
'id': id.toJson(),
|
||||
'kind': kind,
|
||||
if (parentId != null) 'parentId': parentId?.toJson(),
|
||||
if (by != null) 'by': by?.toJsonForProtocol(),
|
||||
'fromAuthor': fromAuthor,
|
||||
if (title != null) 'title': title,
|
||||
'body': body,
|
||||
'createdAt': createdAt.toJson(),
|
||||
if (editedAt != null) 'editedAt': editedAt?.toJson(),
|
||||
'deleted': deleted,
|
||||
'hidden': hidden,
|
||||
'mine': mine,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return _isc.SerializationManager.encode(this);
|
||||
}
|
||||
}
|
||||
|
||||
class _Undefined {}
|
||||
|
||||
class _DiscussionPostViewImpl extends DiscussionPostView {
|
||||
_DiscussionPostViewImpl({
|
||||
required _isc.UuidValue id,
|
||||
required String kind,
|
||||
_isc.UuidValue? parentId,
|
||||
_i4q3oto5.FeedbackPerson? by,
|
||||
required bool fromAuthor,
|
||||
String? title,
|
||||
required String body,
|
||||
required DateTime createdAt,
|
||||
DateTime? editedAt,
|
||||
required bool deleted,
|
||||
required bool hidden,
|
||||
required bool mine,
|
||||
}) : super._(
|
||||
id: id,
|
||||
kind: kind,
|
||||
parentId: parentId,
|
||||
by: by,
|
||||
fromAuthor: fromAuthor,
|
||||
title: title,
|
||||
body: body,
|
||||
createdAt: createdAt,
|
||||
editedAt: editedAt,
|
||||
deleted: deleted,
|
||||
hidden: hidden,
|
||||
mine: mine,
|
||||
);
|
||||
|
||||
/// Returns a shallow copy of this [DiscussionPostView]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
@override
|
||||
DiscussionPostView copyWith({
|
||||
_isc.UuidValue? id,
|
||||
String? kind,
|
||||
Object? parentId = _Undefined,
|
||||
Object? by = _Undefined,
|
||||
bool? fromAuthor,
|
||||
Object? title = _Undefined,
|
||||
String? body,
|
||||
DateTime? createdAt,
|
||||
Object? editedAt = _Undefined,
|
||||
bool? deleted,
|
||||
bool? hidden,
|
||||
bool? mine,
|
||||
}) {
|
||||
return DiscussionPostView(
|
||||
id: id ?? this.id,
|
||||
kind: kind ?? this.kind,
|
||||
parentId: parentId is _isc.UuidValue? ? parentId : this.parentId,
|
||||
by: by is _i4q3oto5.FeedbackPerson? ? by : this.by?.copyWith(),
|
||||
fromAuthor: fromAuthor ?? this.fromAuthor,
|
||||
title: title is String? ? title : this.title,
|
||||
body: body ?? this.body,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
editedAt: editedAt is DateTime? ? editedAt : this.editedAt,
|
||||
deleted: deleted ?? this.deleted,
|
||||
hidden: hidden ?? this.hidden,
|
||||
mine: mine ?? this.mine,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/* 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;
|
||||
|
||||
/// Why writing in a discussion was refused; nothing changed.
|
||||
enum DiscussionRefusal implements _isc.SerializableModel {
|
||||
/// The person signed in without an identity: anything involving other
|
||||
/// people needs one.
|
||||
noIdentity,
|
||||
|
||||
/// The person has no public profile: posts name their writer.
|
||||
noProfile,
|
||||
|
||||
/// The studyset's author keeps the person from writing on their
|
||||
/// studysets.
|
||||
blocked,
|
||||
|
||||
/// The author took the studyset off Explore: what is there stays
|
||||
/// readable, but nobody asks anything new.
|
||||
withdrawn,
|
||||
|
||||
/// The release doesn't hold what the question would be about.
|
||||
notInRelease,
|
||||
|
||||
/// A title or text left empty.
|
||||
empty,
|
||||
|
||||
/// A title, text or comment longer than allowed.
|
||||
tooLong,
|
||||
|
||||
/// More posts in the last hour than a person may write.
|
||||
tooMany;
|
||||
|
||||
static DiscussionRefusal fromJson(String name) {
|
||||
switch (name) {
|
||||
case 'noIdentity':
|
||||
return DiscussionRefusal.noIdentity;
|
||||
case 'noProfile':
|
||||
return DiscussionRefusal.noProfile;
|
||||
case 'blocked':
|
||||
return DiscussionRefusal.blocked;
|
||||
case 'withdrawn':
|
||||
return DiscussionRefusal.withdrawn;
|
||||
case 'notInRelease':
|
||||
return DiscussionRefusal.notInRelease;
|
||||
case 'empty':
|
||||
return DiscussionRefusal.empty;
|
||||
case 'tooLong':
|
||||
return DiscussionRefusal.tooLong;
|
||||
case 'tooMany':
|
||||
return DiscussionRefusal.tooMany;
|
||||
default:
|
||||
throw ArgumentError(
|
||||
'Value "$name" cannot be converted to "DiscussionRefusal"',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
String toJson() => name;
|
||||
|
||||
@override
|
||||
String toString() => name;
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
/* 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;
|
||||
import '../discussion/discussion_refusal.dart' as _i5ff9exj;
|
||||
|
||||
/// Writing in a discussion was refused; nothing changed.
|
||||
abstract class DiscussionRefusedException
|
||||
implements
|
||||
_isc.SerializableException,
|
||||
_isc.SerializableModel,
|
||||
_isc.ProtocolSerialization {
|
||||
DiscussionRefusedException._({required this.reason});
|
||||
|
||||
factory DiscussionRefusedException({
|
||||
required _i5ff9exj.DiscussionRefusal reason,
|
||||
}) = _DiscussionRefusedExceptionImpl;
|
||||
|
||||
factory DiscussionRefusedException.fromJson(
|
||||
Map<String, dynamic> jsonSerialization,
|
||||
) {
|
||||
return DiscussionRefusedException(
|
||||
reason: _i5ff9exj.DiscussionRefusal.fromJson(
|
||||
(jsonSerialization['reason'] as String),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Why it was refused.
|
||||
_i5ff9exj.DiscussionRefusal reason;
|
||||
|
||||
/// Returns a shallow copy of this [DiscussionRefusedException]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
DiscussionRefusedException copyWith({_i5ff9exj.DiscussionRefusal? reason});
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'__className__': 'DiscussionRefusedException',
|
||||
'reason': reason.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJsonForProtocol() {
|
||||
return {
|
||||
'__className__': 'DiscussionRefusedException',
|
||||
'reason': reason.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'DiscussionRefusedException(reason: $reason)';
|
||||
}
|
||||
}
|
||||
|
||||
class _DiscussionRefusedExceptionImpl extends DiscussionRefusedException {
|
||||
_DiscussionRefusedExceptionImpl({required _i5ff9exj.DiscussionRefusal reason})
|
||||
: super._(reason: reason);
|
||||
|
||||
/// Returns a shallow copy of this [DiscussionRefusedException]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
@override
|
||||
DiscussionRefusedException copyWith({_i5ff9exj.DiscussionRefusal? reason}) {
|
||||
return DiscussionRefusedException(reason: reason ?? this.reason);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,281 @@
|
|||
/* 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:halkyon_learn_client/src/protocol/protocol.dart' as _itx5j3f5;
|
||||
import 'package:serverpod_client/serverpod_client.dart' as _isc;
|
||||
import '../discussion/discussion_target.dart' as _iqswgn91;
|
||||
import '../feedback/feedback_person.dart' as _i4q3oto5;
|
||||
|
||||
/// A question as a list shows it.
|
||||
abstract class DiscussionSummary
|
||||
implements _isc.SerializableModel, _isc.ProtocolSerialization {
|
||||
DiscussionSummary._({
|
||||
required this.questionId,
|
||||
required this.publicId,
|
||||
required this.studysetTitle,
|
||||
required this.title,
|
||||
this.asker,
|
||||
required this.askerIsAuthor,
|
||||
required this.target,
|
||||
required this.createdAt,
|
||||
required this.activeAt,
|
||||
required this.answers,
|
||||
required this.accepted,
|
||||
required this.deleted,
|
||||
required this.hidden,
|
||||
required this.mine,
|
||||
required this.unseen,
|
||||
});
|
||||
|
||||
factory DiscussionSummary({
|
||||
required _isc.UuidValue questionId,
|
||||
required _isc.UuidValue publicId,
|
||||
required String studysetTitle,
|
||||
required String title,
|
||||
_i4q3oto5.FeedbackPerson? asker,
|
||||
required bool askerIsAuthor,
|
||||
required _iqswgn91.DiscussionTarget target,
|
||||
required DateTime createdAt,
|
||||
required DateTime activeAt,
|
||||
required int answers,
|
||||
required bool accepted,
|
||||
required bool deleted,
|
||||
required bool hidden,
|
||||
required bool mine,
|
||||
required bool unseen,
|
||||
}) = _DiscussionSummaryImpl;
|
||||
|
||||
factory DiscussionSummary.fromJson(Map<String, dynamic> jsonSerialization) {
|
||||
return DiscussionSummary(
|
||||
questionId: _isc.UuidValueJsonExtension.fromJson(
|
||||
jsonSerialization['questionId'],
|
||||
),
|
||||
publicId: _isc.UuidValueJsonExtension.fromJson(
|
||||
jsonSerialization['publicId'],
|
||||
),
|
||||
studysetTitle: jsonSerialization['studysetTitle'] as String,
|
||||
title: jsonSerialization['title'] as String,
|
||||
asker: jsonSerialization['asker'] == null
|
||||
? null
|
||||
: _itx5j3f5.Protocol().deserialize<_i4q3oto5.FeedbackPerson>(
|
||||
jsonSerialization['asker'],
|
||||
),
|
||||
askerIsAuthor: _isc.BoolJsonExtension.fromJson(
|
||||
jsonSerialization['askerIsAuthor'],
|
||||
),
|
||||
target: _itx5j3f5.Protocol().deserialize<_iqswgn91.DiscussionTarget>(
|
||||
jsonSerialization['target'],
|
||||
),
|
||||
createdAt: _isc.DateTimeJsonExtension.fromJson(
|
||||
jsonSerialization['createdAt'],
|
||||
),
|
||||
activeAt: _isc.DateTimeJsonExtension.fromJson(
|
||||
jsonSerialization['activeAt'],
|
||||
),
|
||||
answers: jsonSerialization['answers'] as int,
|
||||
accepted: _isc.BoolJsonExtension.fromJson(jsonSerialization['accepted']),
|
||||
deleted: _isc.BoolJsonExtension.fromJson(jsonSerialization['deleted']),
|
||||
hidden: _isc.BoolJsonExtension.fromJson(jsonSerialization['hidden']),
|
||||
mine: _isc.BoolJsonExtension.fromJson(jsonSerialization['mine']),
|
||||
unseen: _isc.BoolJsonExtension.fromJson(jsonSerialization['unseen']),
|
||||
);
|
||||
}
|
||||
|
||||
_isc.UuidValue questionId;
|
||||
|
||||
/// The published studyset it is on, and its title.
|
||||
_isc.UuidValue publicId;
|
||||
|
||||
String studysetTitle;
|
||||
|
||||
/// Its title; empty once deleted.
|
||||
String title;
|
||||
|
||||
/// Who asked it; null once deleted, or without a public profile.
|
||||
_i4q3oto5.FeedbackPerson? asker;
|
||||
|
||||
bool askerIsAuthor;
|
||||
|
||||
/// What it is about.
|
||||
_iqswgn91.DiscussionTarget target;
|
||||
|
||||
/// When it was asked, and when anything last happened in it, in UTC.
|
||||
DateTime createdAt;
|
||||
|
||||
DateTime activeAt;
|
||||
|
||||
/// How many answers the viewer sees, and whether one is accepted.
|
||||
int answers;
|
||||
|
||||
bool accepted;
|
||||
|
||||
bool deleted;
|
||||
|
||||
bool hidden;
|
||||
|
||||
/// Whether the viewer asked it.
|
||||
bool mine;
|
||||
|
||||
/// Whether others wrote in it since the viewer last read it, where it is
|
||||
/// theirs to follow: they asked, answered or commented, or it is on their
|
||||
/// studyset.
|
||||
bool unseen;
|
||||
|
||||
/// Returns a shallow copy of this [DiscussionSummary]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
DiscussionSummary copyWith({
|
||||
_isc.UuidValue? questionId,
|
||||
_isc.UuidValue? publicId,
|
||||
String? studysetTitle,
|
||||
String? title,
|
||||
_i4q3oto5.FeedbackPerson? asker,
|
||||
bool? askerIsAuthor,
|
||||
_iqswgn91.DiscussionTarget? target,
|
||||
DateTime? createdAt,
|
||||
DateTime? activeAt,
|
||||
int? answers,
|
||||
bool? accepted,
|
||||
bool? deleted,
|
||||
bool? hidden,
|
||||
bool? mine,
|
||||
bool? unseen,
|
||||
});
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'__className__': 'DiscussionSummary',
|
||||
'questionId': questionId.toJson(),
|
||||
'publicId': publicId.toJson(),
|
||||
'studysetTitle': studysetTitle,
|
||||
'title': title,
|
||||
if (asker != null) 'asker': asker?.toJson(),
|
||||
'askerIsAuthor': askerIsAuthor,
|
||||
'target': target.toJson(),
|
||||
'createdAt': createdAt.toJson(),
|
||||
'activeAt': activeAt.toJson(),
|
||||
'answers': answers,
|
||||
'accepted': accepted,
|
||||
'deleted': deleted,
|
||||
'hidden': hidden,
|
||||
'mine': mine,
|
||||
'unseen': unseen,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJsonForProtocol() {
|
||||
return {
|
||||
'__className__': 'DiscussionSummary',
|
||||
'questionId': questionId.toJson(),
|
||||
'publicId': publicId.toJson(),
|
||||
'studysetTitle': studysetTitle,
|
||||
'title': title,
|
||||
if (asker != null) 'asker': asker?.toJsonForProtocol(),
|
||||
'askerIsAuthor': askerIsAuthor,
|
||||
'target': target.toJsonForProtocol(),
|
||||
'createdAt': createdAt.toJson(),
|
||||
'activeAt': activeAt.toJson(),
|
||||
'answers': answers,
|
||||
'accepted': accepted,
|
||||
'deleted': deleted,
|
||||
'hidden': hidden,
|
||||
'mine': mine,
|
||||
'unseen': unseen,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return _isc.SerializationManager.encode(this);
|
||||
}
|
||||
}
|
||||
|
||||
class _Undefined {}
|
||||
|
||||
class _DiscussionSummaryImpl extends DiscussionSummary {
|
||||
_DiscussionSummaryImpl({
|
||||
required _isc.UuidValue questionId,
|
||||
required _isc.UuidValue publicId,
|
||||
required String studysetTitle,
|
||||
required String title,
|
||||
_i4q3oto5.FeedbackPerson? asker,
|
||||
required bool askerIsAuthor,
|
||||
required _iqswgn91.DiscussionTarget target,
|
||||
required DateTime createdAt,
|
||||
required DateTime activeAt,
|
||||
required int answers,
|
||||
required bool accepted,
|
||||
required bool deleted,
|
||||
required bool hidden,
|
||||
required bool mine,
|
||||
required bool unseen,
|
||||
}) : super._(
|
||||
questionId: questionId,
|
||||
publicId: publicId,
|
||||
studysetTitle: studysetTitle,
|
||||
title: title,
|
||||
asker: asker,
|
||||
askerIsAuthor: askerIsAuthor,
|
||||
target: target,
|
||||
createdAt: createdAt,
|
||||
activeAt: activeAt,
|
||||
answers: answers,
|
||||
accepted: accepted,
|
||||
deleted: deleted,
|
||||
hidden: hidden,
|
||||
mine: mine,
|
||||
unseen: unseen,
|
||||
);
|
||||
|
||||
/// Returns a shallow copy of this [DiscussionSummary]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
@override
|
||||
DiscussionSummary copyWith({
|
||||
_isc.UuidValue? questionId,
|
||||
_isc.UuidValue? publicId,
|
||||
String? studysetTitle,
|
||||
String? title,
|
||||
Object? asker = _Undefined,
|
||||
bool? askerIsAuthor,
|
||||
_iqswgn91.DiscussionTarget? target,
|
||||
DateTime? createdAt,
|
||||
DateTime? activeAt,
|
||||
int? answers,
|
||||
bool? accepted,
|
||||
bool? deleted,
|
||||
bool? hidden,
|
||||
bool? mine,
|
||||
bool? unseen,
|
||||
}) {
|
||||
return DiscussionSummary(
|
||||
questionId: questionId ?? this.questionId,
|
||||
publicId: publicId ?? this.publicId,
|
||||
studysetTitle: studysetTitle ?? this.studysetTitle,
|
||||
title: title ?? this.title,
|
||||
asker: asker is _i4q3oto5.FeedbackPerson?
|
||||
? asker
|
||||
: this.asker?.copyWith(),
|
||||
askerIsAuthor: askerIsAuthor ?? this.askerIsAuthor,
|
||||
target: target ?? this.target.copyWith(),
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
activeAt: activeAt ?? this.activeAt,
|
||||
answers: answers ?? this.answers,
|
||||
accepted: accepted ?? this.accepted,
|
||||
deleted: deleted ?? this.deleted,
|
||||
hidden: hidden ?? this.hidden,
|
||||
mine: mine ?? this.mine,
|
||||
unseen: unseen ?? this.unseen,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
/* 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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,236 @@
|
|||
/* 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:halkyon_learn_client/src/protocol/protocol.dart' as _itx5j3f5;
|
||||
import 'package:serverpod_client/serverpod_client.dart' as _isc;
|
||||
import '../discussion/discussion_post_view.dart' as _iv1wx9mv;
|
||||
import '../discussion/discussion_refusal.dart' as _i5ff9exj;
|
||||
import '../discussion/discussion_target.dart' as _iqswgn91;
|
||||
|
||||
/// A discussion as the app shows it: the question, its answers, the accepted
|
||||
/// one first, then the oldest first, and the comments on both, oldest first.
|
||||
abstract class DiscussionView
|
||||
implements _isc.SerializableModel, _isc.ProtocolSerialization {
|
||||
DiscussionView._({
|
||||
required this.question,
|
||||
required this.publicId,
|
||||
required this.studysetTitle,
|
||||
required this.location,
|
||||
required this.target,
|
||||
required this.answers,
|
||||
required this.comments,
|
||||
this.acceptedAnswerId,
|
||||
required this.asker,
|
||||
required this.author,
|
||||
this.refusal,
|
||||
});
|
||||
|
||||
factory DiscussionView({
|
||||
required _iv1wx9mv.DiscussionPostView question,
|
||||
required _isc.UuidValue publicId,
|
||||
required String studysetTitle,
|
||||
required String location,
|
||||
required _iqswgn91.DiscussionTarget target,
|
||||
required List<_iv1wx9mv.DiscussionPostView> answers,
|
||||
required List<_iv1wx9mv.DiscussionPostView> comments,
|
||||
_isc.UuidValue? acceptedAnswerId,
|
||||
required bool asker,
|
||||
required bool author,
|
||||
_i5ff9exj.DiscussionRefusal? refusal,
|
||||
}) = _DiscussionViewImpl;
|
||||
|
||||
factory DiscussionView.fromJson(Map<String, dynamic> jsonSerialization) {
|
||||
return DiscussionView(
|
||||
question: _itx5j3f5.Protocol().deserialize<_iv1wx9mv.DiscussionPostView>(
|
||||
jsonSerialization['question'],
|
||||
),
|
||||
publicId: _isc.UuidValueJsonExtension.fromJson(
|
||||
jsonSerialization['publicId'],
|
||||
),
|
||||
studysetTitle: jsonSerialization['studysetTitle'] as String,
|
||||
location: jsonSerialization['location'] as String,
|
||||
target: _itx5j3f5.Protocol().deserialize<_iqswgn91.DiscussionTarget>(
|
||||
jsonSerialization['target'],
|
||||
),
|
||||
answers: _itx5j3f5.Protocol()
|
||||
.deserialize<List<_iv1wx9mv.DiscussionPostView>>(
|
||||
jsonSerialization['answers'],
|
||||
),
|
||||
comments: _itx5j3f5.Protocol()
|
||||
.deserialize<List<_iv1wx9mv.DiscussionPostView>>(
|
||||
jsonSerialization['comments'],
|
||||
),
|
||||
acceptedAnswerId: jsonSerialization['acceptedAnswerId'] == null
|
||||
? null
|
||||
: _isc.UuidValueJsonExtension.fromJson(
|
||||
jsonSerialization['acceptedAnswerId'],
|
||||
),
|
||||
asker: _isc.BoolJsonExtension.fromJson(jsonSerialization['asker']),
|
||||
author: _isc.BoolJsonExtension.fromJson(jsonSerialization['author']),
|
||||
refusal: jsonSerialization['refusal'] == null
|
||||
? null
|
||||
: _i5ff9exj.DiscussionRefusal.fromJson(
|
||||
(jsonSerialization['refusal'] as String),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_iv1wx9mv.DiscussionPostView question;
|
||||
|
||||
/// The published studyset it is on: its public id, title and location.
|
||||
_isc.UuidValue publicId;
|
||||
|
||||
String studysetTitle;
|
||||
|
||||
String location;
|
||||
|
||||
/// What it is about.
|
||||
_iqswgn91.DiscussionTarget target;
|
||||
|
||||
List<_iv1wx9mv.DiscussionPostView> answers;
|
||||
|
||||
List<_iv1wx9mv.DiscussionPostView> comments;
|
||||
|
||||
_isc.UuidValue? acceptedAnswerId;
|
||||
|
||||
/// Whether the viewer asked it, and so may accept an answer.
|
||||
bool asker;
|
||||
|
||||
/// Whether the viewer is the studyset's author, and so may hide posts.
|
||||
bool author;
|
||||
|
||||
/// Why the viewer may not write in it; null when they may.
|
||||
_i5ff9exj.DiscussionRefusal? refusal;
|
||||
|
||||
/// Returns a shallow copy of this [DiscussionView]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
DiscussionView copyWith({
|
||||
_iv1wx9mv.DiscussionPostView? question,
|
||||
_isc.UuidValue? publicId,
|
||||
String? studysetTitle,
|
||||
String? location,
|
||||
_iqswgn91.DiscussionTarget? target,
|
||||
List<_iv1wx9mv.DiscussionPostView>? answers,
|
||||
List<_iv1wx9mv.DiscussionPostView>? comments,
|
||||
_isc.UuidValue? acceptedAnswerId,
|
||||
bool? asker,
|
||||
bool? author,
|
||||
_i5ff9exj.DiscussionRefusal? refusal,
|
||||
});
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'__className__': 'DiscussionView',
|
||||
'question': question.toJson(),
|
||||
'publicId': publicId.toJson(),
|
||||
'studysetTitle': studysetTitle,
|
||||
'location': location,
|
||||
'target': target.toJson(),
|
||||
'answers': answers.toJson(valueToJson: (v) => v.toJson()),
|
||||
'comments': comments.toJson(valueToJson: (v) => v.toJson()),
|
||||
if (acceptedAnswerId != null)
|
||||
'acceptedAnswerId': acceptedAnswerId?.toJson(),
|
||||
'asker': asker,
|
||||
'author': author,
|
||||
if (refusal != null) 'refusal': refusal?.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJsonForProtocol() {
|
||||
return {
|
||||
'__className__': 'DiscussionView',
|
||||
'question': question.toJsonForProtocol(),
|
||||
'publicId': publicId.toJson(),
|
||||
'studysetTitle': studysetTitle,
|
||||
'location': location,
|
||||
'target': target.toJsonForProtocol(),
|
||||
'answers': answers.toJson(valueToJson: (v) => v.toJsonForProtocol()),
|
||||
'comments': comments.toJson(valueToJson: (v) => v.toJsonForProtocol()),
|
||||
if (acceptedAnswerId != null)
|
||||
'acceptedAnswerId': acceptedAnswerId?.toJson(),
|
||||
'asker': asker,
|
||||
'author': author,
|
||||
if (refusal != null) 'refusal': refusal?.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return _isc.SerializationManager.encode(this);
|
||||
}
|
||||
}
|
||||
|
||||
class _Undefined {}
|
||||
|
||||
class _DiscussionViewImpl extends DiscussionView {
|
||||
_DiscussionViewImpl({
|
||||
required _iv1wx9mv.DiscussionPostView question,
|
||||
required _isc.UuidValue publicId,
|
||||
required String studysetTitle,
|
||||
required String location,
|
||||
required _iqswgn91.DiscussionTarget target,
|
||||
required List<_iv1wx9mv.DiscussionPostView> answers,
|
||||
required List<_iv1wx9mv.DiscussionPostView> comments,
|
||||
_isc.UuidValue? acceptedAnswerId,
|
||||
required bool asker,
|
||||
required bool author,
|
||||
_i5ff9exj.DiscussionRefusal? refusal,
|
||||
}) : super._(
|
||||
question: question,
|
||||
publicId: publicId,
|
||||
studysetTitle: studysetTitle,
|
||||
location: location,
|
||||
target: target,
|
||||
answers: answers,
|
||||
comments: comments,
|
||||
acceptedAnswerId: acceptedAnswerId,
|
||||
asker: asker,
|
||||
author: author,
|
||||
refusal: refusal,
|
||||
);
|
||||
|
||||
/// Returns a shallow copy of this [DiscussionView]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_isc.useResult
|
||||
@override
|
||||
DiscussionView copyWith({
|
||||
_iv1wx9mv.DiscussionPostView? question,
|
||||
_isc.UuidValue? publicId,
|
||||
String? studysetTitle,
|
||||
String? location,
|
||||
_iqswgn91.DiscussionTarget? target,
|
||||
List<_iv1wx9mv.DiscussionPostView>? answers,
|
||||
List<_iv1wx9mv.DiscussionPostView>? comments,
|
||||
Object? acceptedAnswerId = _Undefined,
|
||||
bool? asker,
|
||||
bool? author,
|
||||
Object? refusal = _Undefined,
|
||||
}) {
|
||||
return DiscussionView(
|
||||
question: question ?? this.question.copyWith(),
|
||||
publicId: publicId ?? this.publicId,
|
||||
studysetTitle: studysetTitle ?? this.studysetTitle,
|
||||
location: location ?? this.location,
|
||||
target: target ?? this.target.copyWith(),
|
||||
answers: answers ?? this.answers.map((e0) => e0.copyWith()).toList(),
|
||||
comments: comments ?? this.comments.map((e0) => e0.copyWith()).toList(),
|
||||
acceptedAnswerId: acceptedAnswerId is _isc.UuidValue?
|
||||
? acceptedAnswerId
|
||||
: this.acceptedAnswerId,
|
||||
asker: asker ?? this.asker,
|
||||
author: author ?? this.author,
|
||||
refusal: refusal is _i5ff9exj.DiscussionRefusal? ? refusal : this.refusal,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -23,6 +23,8 @@ import 'package:halkyon_learn_client/src/protocol/dictionary/dictionary_key_hit.
|
|||
as _ii0vb6vg;
|
||||
import 'package:halkyon_learn_client/src/protocol/dictionary/dictionary_source.dart'
|
||||
as _i8vj64sp;
|
||||
import 'package:halkyon_learn_client/src/protocol/discussion/discussion_summary.dart'
|
||||
as _i7lxdcg2;
|
||||
import 'package:halkyon_learn_client/src/protocol/explore/explore_entry.dart'
|
||||
as _iyigb6vc;
|
||||
import 'package:halkyon_learn_client/src/protocol/feedback/feedback_view.dart'
|
||||
|
|
@ -58,6 +60,12 @@ import 'dictionary/dictionary_hit.dart' as _ivbh47kc;
|
|||
import 'dictionary/dictionary_key.dart' as _i9gd3xbn;
|
||||
import 'dictionary/dictionary_key_hit.dart' as _i6b9unou;
|
||||
import 'dictionary/dictionary_source.dart' as _ie12eb65;
|
||||
import 'discussion/discussion_post_view.dart' as _ifltqotq;
|
||||
import 'discussion/discussion_refusal.dart' as _iysrt1r7;
|
||||
import 'discussion/discussion_refused_exception.dart' as _i1nsp6ib;
|
||||
import 'discussion/discussion_summary.dart' as _i5mmlb7v;
|
||||
import 'discussion/discussion_target.dart' as _ijf8cxgd;
|
||||
import 'discussion/discussion_view.dart' as _ixby8mme;
|
||||
import 'explore/explore_entry.dart' as _iaxdli27;
|
||||
import 'explore/explore_query.dart' as _ibl9h9o9;
|
||||
import 'explore/release_content.dart' as _ievpeb4f;
|
||||
|
|
@ -114,6 +122,12 @@ export 'dictionary/dictionary_hit.dart';
|
|||
export 'dictionary/dictionary_key.dart';
|
||||
export 'dictionary/dictionary_key_hit.dart';
|
||||
export 'dictionary/dictionary_source.dart';
|
||||
export 'discussion/discussion_post_view.dart';
|
||||
export 'discussion/discussion_refusal.dart';
|
||||
export 'discussion/discussion_refused_exception.dart';
|
||||
export 'discussion/discussion_summary.dart';
|
||||
export 'discussion/discussion_target.dart';
|
||||
export 'discussion/discussion_view.dart';
|
||||
export 'explore/explore_entry.dart';
|
||||
export 'explore/explore_query.dart';
|
||||
export 'explore/release_content.dart';
|
||||
|
|
@ -2364,6 +2378,24 @@ class Protocol extends _isd.DatabaseSerializationManager {
|
|||
if (t == _ie12eb65.DictionarySource) {
|
||||
return _ie12eb65.DictionarySource.fromJson(data) as T;
|
||||
}
|
||||
if (t == _ifltqotq.DiscussionPostView) {
|
||||
return _ifltqotq.DiscussionPostView.fromJson(data) as T;
|
||||
}
|
||||
if (t == _iysrt1r7.DiscussionRefusal) {
|
||||
return _iysrt1r7.DiscussionRefusal.fromJson(data) as T;
|
||||
}
|
||||
if (t == _i1nsp6ib.DiscussionRefusedException) {
|
||||
return _i1nsp6ib.DiscussionRefusedException.fromJson(data) as T;
|
||||
}
|
||||
if (t == _i5mmlb7v.DiscussionSummary) {
|
||||
return _i5mmlb7v.DiscussionSummary.fromJson(data) as T;
|
||||
}
|
||||
if (t == _ijf8cxgd.DiscussionTarget) {
|
||||
return _ijf8cxgd.DiscussionTarget.fromJson(data) as T;
|
||||
}
|
||||
if (t == _ixby8mme.DiscussionView) {
|
||||
return _ixby8mme.DiscussionView.fromJson(data) as T;
|
||||
}
|
||||
if (t == _iaxdli27.ExploreEntry) {
|
||||
return _iaxdli27.ExploreEntry.fromJson(data) as T;
|
||||
}
|
||||
|
|
@ -2561,6 +2593,32 @@ class Protocol extends _isd.DatabaseSerializationManager {
|
|||
return (data != null ? _ie12eb65.DictionarySource.fromJson(data) : null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_ifltqotq.DiscussionPostView?>()) {
|
||||
return (data != null ? _ifltqotq.DiscussionPostView.fromJson(data) : null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_iysrt1r7.DiscussionRefusal?>()) {
|
||||
return (data != null ? _iysrt1r7.DiscussionRefusal.fromJson(data) : null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_i1nsp6ib.DiscussionRefusedException?>()) {
|
||||
return (data != null
|
||||
? _i1nsp6ib.DiscussionRefusedException.fromJson(data)
|
||||
: null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_i5mmlb7v.DiscussionSummary?>()) {
|
||||
return (data != null ? _i5mmlb7v.DiscussionSummary.fromJson(data) : null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_ijf8cxgd.DiscussionTarget?>()) {
|
||||
return (data != null ? _ijf8cxgd.DiscussionTarget.fromJson(data) : null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_ixby8mme.DiscussionView?>()) {
|
||||
return (data != null ? _ixby8mme.DiscussionView.fromJson(data) : null)
|
||||
as T;
|
||||
}
|
||||
if (t == _isc.getType<_iaxdli27.ExploreEntry?>()) {
|
||||
return (data != null ? _iaxdli27.ExploreEntry.fromJson(data) : null) as T;
|
||||
}
|
||||
|
|
@ -2696,6 +2754,12 @@ class Protocol extends _isd.DatabaseSerializationManager {
|
|||
.toList()
|
||||
as T;
|
||||
}
|
||||
if (t == List<_ifltqotq.DiscussionPostView>) {
|
||||
return (data as List)
|
||||
.map((e) => deserialize<_ifltqotq.DiscussionPostView>(e))
|
||||
.toList()
|
||||
as T;
|
||||
}
|
||||
if (t == List<_iaswq7ap.ReleaseItem>) {
|
||||
return (data as List)
|
||||
.map((e) => deserialize<_iaswq7ap.ReleaseItem>(e))
|
||||
|
|
@ -2765,6 +2829,12 @@ class Protocol extends _isd.DatabaseSerializationManager {
|
|||
)
|
||||
as T;
|
||||
}
|
||||
if (t == List<_i7lxdcg2.DiscussionSummary>) {
|
||||
return (data as List)
|
||||
.map((e) => deserialize<_i7lxdcg2.DiscussionSummary>(e))
|
||||
.toList()
|
||||
as T;
|
||||
}
|
||||
if (t == List<_iyigb6vc.ExploreEntry>) {
|
||||
return (data as List)
|
||||
.map((e) => deserialize<_iyigb6vc.ExploreEntry>(e))
|
||||
|
|
@ -2818,6 +2888,12 @@ class Protocol extends _isd.DatabaseSerializationManager {
|
|||
_i9gd3xbn.DictionaryKey => 'DictionaryKey',
|
||||
_i6b9unou.DictionaryKeyHit => 'DictionaryKeyHit',
|
||||
_ie12eb65.DictionarySource => 'DictionarySource',
|
||||
_ifltqotq.DiscussionPostView => 'DiscussionPostView',
|
||||
_iysrt1r7.DiscussionRefusal => 'DiscussionRefusal',
|
||||
_i1nsp6ib.DiscussionRefusedException => 'DiscussionRefusedException',
|
||||
_i5mmlb7v.DiscussionSummary => 'DiscussionSummary',
|
||||
_ijf8cxgd.DiscussionTarget => 'DiscussionTarget',
|
||||
_ixby8mme.DiscussionView => 'DiscussionView',
|
||||
_iaxdli27.ExploreEntry => 'ExploreEntry',
|
||||
_ibl9h9o9.ExploreQuery => 'ExploreQuery',
|
||||
_ievpeb4f.ReleaseContent => 'ReleaseContent',
|
||||
|
|
@ -2914,6 +2990,18 @@ class Protocol extends _isd.DatabaseSerializationManager {
|
|||
return 'DictionaryKeyHit';
|
||||
case _ie12eb65.DictionarySource():
|
||||
return 'DictionarySource';
|
||||
case _ifltqotq.DiscussionPostView():
|
||||
return 'DiscussionPostView';
|
||||
case _iysrt1r7.DiscussionRefusal():
|
||||
return 'DiscussionRefusal';
|
||||
case _i1nsp6ib.DiscussionRefusedException():
|
||||
return 'DiscussionRefusedException';
|
||||
case _i5mmlb7v.DiscussionSummary():
|
||||
return 'DiscussionSummary';
|
||||
case _ijf8cxgd.DiscussionTarget():
|
||||
return 'DiscussionTarget';
|
||||
case _ixby8mme.DiscussionView():
|
||||
return 'DiscussionView';
|
||||
case _iaxdli27.ExploreEntry():
|
||||
return 'ExploreEntry';
|
||||
case _ibl9h9o9.ExploreQuery():
|
||||
|
|
@ -3077,6 +3165,24 @@ class Protocol extends _isd.DatabaseSerializationManager {
|
|||
if (dataClassName == 'DictionarySource') {
|
||||
return deserialize<_ie12eb65.DictionarySource>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'DiscussionPostView') {
|
||||
return deserialize<_ifltqotq.DiscussionPostView>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'DiscussionRefusal') {
|
||||
return deserialize<_iysrt1r7.DiscussionRefusal>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'DiscussionRefusedException') {
|
||||
return deserialize<_i1nsp6ib.DiscussionRefusedException>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'DiscussionSummary') {
|
||||
return deserialize<_i5mmlb7v.DiscussionSummary>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'DiscussionTarget') {
|
||||
return deserialize<_ijf8cxgd.DiscussionTarget>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'DiscussionView') {
|
||||
return deserialize<_ixby8mme.DiscussionView>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'ExploreEntry') {
|
||||
return deserialize<_iaxdli27.ExploreEntry>(data['data']);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue