Skip to content

Commit 04d3d15

Browse files
committed
model: Add poll and friends.
Signed-off-by: Zixuan James Li <[email protected]>
1 parent 9849197 commit 04d3d15

File tree

3 files changed

+230
-0
lines changed

3 files changed

+230
-0
lines changed

lib/api/model/polls.dart

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
import 'package:json_annotation/json_annotation.dart';
2+
3+
part 'polls.g.dart';
4+
5+
/// Data structure seen from [Submessage.content] to support Zulip's widget
6+
/// system.
7+
sealed class WidgetData {}
8+
9+
@JsonSerializable(fieldRename: FieldRename.snake)
10+
class WidgetStartData extends WidgetData {
11+
WidgetStartData({required this.widgetType, required this.extraData});
12+
13+
final WidgetType widgetType;
14+
final PollExtraData extraData;
15+
16+
factory WidgetStartData.fromJson(Map<String, dynamic> json) =>
17+
_$WidgetStartDataFromJson(json);
18+
19+
Map<String, dynamic> toJson() => _$WidgetStartDataToJson(this);
20+
}
21+
22+
@JsonSerializable(fieldRename: FieldRename.snake)
23+
class PollExtraData {
24+
const PollExtraData({required this.question, required this.options});
25+
26+
final String question;
27+
final List<String> options;
28+
29+
factory PollExtraData.fromJson(Map<String, dynamic> json) =>
30+
_$PollExtraDataFromJson(json);
31+
32+
Map<String, dynamic> toJson() => _$PollExtraDataToJson(this);
33+
}
34+
35+
enum WidgetType {
36+
poll,
37+
todo,
38+
unknown,
39+
}
40+
41+
sealed class PollEvent extends WidgetData {
42+
PollEventType get type;
43+
44+
PollEvent();
45+
46+
factory PollEvent.fromJson(Map<String, dynamic> json) {
47+
switch (json['type']) {
48+
case 'new_option': return PollOptionEvent.fromJson(json);
49+
case 'question': return PollQuestionEvent.fromJson(json);
50+
case 'vote': return PollVoteEvent.fromJson(json);
51+
default: return UnknownPollEvent(json: json);
52+
}
53+
}
54+
55+
Map<String, dynamic> toJson();
56+
}
57+
58+
@JsonSerializable(fieldRename: FieldRename.snake)
59+
class PollOptionEvent extends PollEvent {
60+
@override
61+
@JsonKey(includeToJson: true)
62+
PollEventType get type => PollEventType.newOption;
63+
64+
final String option;
65+
final int idx;
66+
67+
PollOptionEvent({
68+
required this.option,
69+
required this.idx,
70+
});
71+
72+
@override
73+
factory PollOptionEvent.fromJson(Map<String, dynamic> json) =>
74+
_$PollOptionEventFromJson(json);
75+
76+
@override
77+
Map<String, dynamic> toJson() => _$PollOptionEventToJson(this);
78+
}
79+
80+
@JsonSerializable(fieldRename: FieldRename.snake)
81+
class PollQuestionEvent extends PollEvent {
82+
@override
83+
@JsonKey(includeToJson: true)
84+
PollEventType get type => PollEventType.question;
85+
86+
final String question;
87+
88+
PollQuestionEvent({
89+
required this.question,
90+
});
91+
92+
@override
93+
factory PollQuestionEvent.fromJson(Map<String, dynamic> json) =>
94+
_$PollQuestionEventFromJson(json);
95+
96+
@override
97+
Map<String, dynamic> toJson() => _$PollQuestionEventToJson(this);
98+
}
99+
100+
@JsonSerializable(fieldRename: FieldRename.snake)
101+
class PollVoteEvent extends PollEvent {
102+
@override
103+
@JsonKey(includeToJson: true)
104+
PollEventType get type => PollEventType.vote;
105+
106+
final String key;
107+
final int vote;
108+
109+
PollVoteEvent({
110+
required this.key,
111+
required this.vote,
112+
});
113+
114+
@override
115+
factory PollVoteEvent.fromJson(Map<String, dynamic> json) =>
116+
_$PollVoteEventFromJson(json);
117+
118+
@override
119+
Map<String, dynamic> toJson() => _$PollVoteEventToJson(this);
120+
}
121+
122+
class UnknownPollEvent extends PollEvent {
123+
@override
124+
@JsonKey(includeToJson: true)
125+
PollEventType get type => PollEventType.unknown;
126+
127+
final Map<String, dynamic> json;
128+
129+
UnknownPollEvent({required this.json});
130+
131+
@override
132+
Map<String, dynamic> toJson() => json;
133+
}
134+
135+
@JsonEnum(fieldRename: FieldRename.snake)
136+
enum PollEventType {
137+
newOption,
138+
question,
139+
vote,
140+
unknown,
141+
}

lib/api/model/polls.g.dart

Lines changed: 85 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/example_data.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ StreamMessage streamMessage({
328328
List<Reaction>? reactions,
329329
int? timestamp,
330330
List<MessageFlag>? flags,
331+
List<Submessage>? submessages,
331332
}) {
332333
final effectiveStream = stream ?? _stream(streamId: defaultStreamMessageStreamId);
333334
// The use of JSON here is convenient in order to delegate parts of the data
@@ -346,6 +347,7 @@ StreamMessage streamMessage({
346347
'id': id ?? _nextMessageId(),
347348
'last_edit_timestamp': lastEditTimestamp,
348349
'subject': topic ?? 'example topic',
350+
'submessages': submessages ?? [],
349351
'timestamp': timestamp ?? 1678139636,
350352
'type': 'stream',
351353
}) as Map<String, dynamic>);
@@ -370,6 +372,7 @@ DmMessage dmMessage({
370372
int? lastEditTimestamp,
371373
int? timestamp,
372374
List<MessageFlag>? flags,
375+
List<Submessage>? submessages,
373376
}) {
374377
assert(!to.any((user) => user.userId == from.userId));
375378
return DmMessage.fromJson(deepToJson({
@@ -384,6 +387,7 @@ DmMessage dmMessage({
384387
'id': id ?? _nextMessageId(),
385388
'last_edit_timestamp': lastEditTimestamp,
386389
'subject': '',
390+
'submessages': submessages ?? [],
387391
'timestamp': timestamp ?? 1678139636,
388392
'type': 'private',
389393
}) as Map<String, dynamic>);

0 commit comments

Comments
 (0)