Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
4983a7c
dart [nfc]: Use dot shorthands for MessageType
sm-sayedi Jun 9, 2026
80bed4b
api [nfc]: Move MessageType next to Message
sm-sayedi Jun 9, 2026
bb5b96a
api [nfc]: Move MessageTypeConverter.fromJson logic to MessageType.fr…
sm-sayedi Jun 9, 2026
f854928
api: Replace `stream` with `channel` for MessageType
sm-sayedi Jun 9, 2026
9c56c05
api: Change Message.type to `MessageType`, from `String`
sm-sayedi Jun 9, 2026
1aa4aac
api: Explain why MessageType cannot be unknown
sm-sayedi Jun 9, 2026
945522d
api: In sendMessage, use "channel" when supported
sm-sayedi Jun 9, 2026
acf3ce5
dart [nfc]: Use dot shorthands for TypingOp
sm-sayedi Jun 9, 2026
be1721a
api: Add TypingOp.unknown
sm-sayedi Jun 15, 2026
cce7d5b
dart [nfc]: Use dot shorthands for ReactionOp
sm-sayedi Jun 10, 2026
e6bad69
api: Add ReactionOp.unknown
sm-sayedi Jun 15, 2026
4386dad
dart [nfc]: Use dot shorthands for RealmWildcardMentionPolicy
sm-sayedi Jun 10, 2026
8704bce
api: Make InitialSnapshot.realmWildcardMentionPolicy optional
sm-sayedi Jun 15, 2026
d4e4113
api [nfc]: Explain why RealmWildcardMentionPolicy cannot be unknown
sm-sayedi Jun 10, 2026
7231600
dart [nfc]: Use dot shorthands for RealmDeleteOwnMessagePolicy
sm-sayedi Jun 10, 2026
41244cd
api [nfc]: Explain why RealmDeleteOwnMessagePolicy cannot be unknown
sm-sayedi Jun 10, 2026
6ac5120
dart [nfc]: Use dot shorthands for CustomProfileFieldType
sm-sayedi Jun 10, 2026
5499a6c
dart [nfc]: Use dot shorthands for UserSettingName
sm-sayedi Jun 10, 2026
1f30d23
api: Add UserSettingName.unknown
sm-sayedi Jun 10, 2026
f51631d
dart [nfc]: Use dot shorthands for TwentyFourHourTimeMode
sm-sayedi Jun 10, 2026
d3ee407
api [nfc]: Explain why TwentyFourHourTimeMode cannot be unknown
sm-sayedi Jun 10, 2026
a2b6829
dart [nfc]: Use dot shorthands for Emojiset
sm-sayedi Jun 10, 2026
b82124b
api [nfc]: Correct the dartdoc of Emojiset.fromRawString
sm-sayedi Jun 11, 2026
6f848e1
dart [nfc]: Use dot shorthands for UserRole
sm-sayedi Jun 10, 2026
b34b43a
dart [nfc]: Use dot shorthands for PresenceStatus
sm-sayedi Jun 10, 2026
dede1ad
api [nfc]: Explain why PresenceStatus cannot be unknown
sm-sayedi Jun 10, 2026
e246559
api [nfc]: Rename ChannelPropertyName to ChannelProperty
sm-sayedi Jun 11, 2026
9351840
dart [nfc]: Use dot shorthands for ChannelProperty
sm-sayedi Jun 11, 2026
d02b70b
api: Add ChannelProperty.unknown
sm-sayedi Jun 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 56 additions & 67 deletions lib/api/model/events.dart
Original file line number Diff line number Diff line change
Expand Up @@ -244,11 +244,11 @@ class UserSettingsUpdateEvent extends Event {
@JsonKey(includeToJson: true)
String get op => 'update';

/// The name of the setting, or null if we don't recognize it.
@JsonKey(unknownEnumValue: JsonKey.nullForUndefinedEnumValue)
final UserSettingName? property;
/// The name of the setting, or [UserSettingName.unknown] if we don't recognize it.
@JsonKey(unknownEnumValue: UserSettingName.unknown)
final UserSettingName property;

/// The new value, or null if we don't recognize the setting.
/// The new value, or null if we don't recognize the setting ([UserSettingName.unknown]).
///
/// This will have the type appropriate for [property]; for example,
/// if the setting is boolean, then `value is bool` will always be true.
Expand All @@ -261,17 +261,17 @@ class UserSettingsUpdateEvent extends Event {
static Object? _readValue(Map<dynamic, dynamic> json, String key) {
final value = json['value'];
switch (UserSettingName.fromRawString(json['property'] as String)) {
case UserSettingName.twentyFourHourTime:
case .twentyFourHourTime:
return TwentyFourHourTimeMode.fromApiValue(value as bool?);
case UserSettingName.starredMessageCounts:
case UserSettingName.displayEmojiReactionUsers:
case .starredMessageCounts:
case .displayEmojiReactionUsers:
return value as bool;
case UserSettingName.emojiset:
case .emojiset:
return Emojiset.fromRawString(value as String);
case UserSettingName.webInboxShowChannelFolders:
case UserSettingName.presenceEnabled:
case .webInboxShowChannelFolders:
case .presenceEnabled:
return value as bool;
case null:
case .unknown:
return null;
}
}
Expand Down Expand Up @@ -818,11 +818,12 @@ class ChannelUpdateEvent extends ChannelEvent {
final int streamId;
final String name;

/// The name of the channel property, or null if we don't recognize it.
@JsonKey(unknownEnumValue: JsonKey.nullForUndefinedEnumValue)
final ChannelPropertyName? property;
/// The name of the channel property,
/// or [ChannelProperty.unknown] if we don't recognize it.
@JsonKey(unknownEnumValue: ChannelProperty.unknown)
final ChannelProperty property;

/// The new value, or null if we don't recognize the property.
/// The new value, or null if we don't recognize the property ([ChannelProperty.unknown]).
///
/// This will have the type appropriate for [property]; for example,
/// if the property is boolean, then `value is bool` will always be true.
Expand All @@ -849,36 +850,36 @@ class ChannelUpdateEvent extends ChannelEvent {
/// (e.g., `value as bool`).
static Object? _readValue(Map<dynamic, dynamic> json, String key) {
final value = json['value'];
switch (ChannelPropertyName.fromRawString(json['property'] as String)) {
case ChannelPropertyName.name:
switch (ChannelProperty.fromRawString(json['property'] as String)) {
case .name:
return value as String;
case ChannelPropertyName.isArchived:
case .isArchived:
return value as bool;
case ChannelPropertyName.description:
case .description:
return value as String;
case ChannelPropertyName.firstMessageId:
case .firstMessageId:
return value as int?;
case ChannelPropertyName.inviteOnly:
case .inviteOnly:
return value as bool;
case ChannelPropertyName.messageRetentionDays:
case .messageRetentionDays:
return value as int?;
case ChannelPropertyName.topicsPolicy:
case .topicsPolicy:
return ChannelTopicsPolicy.fromApiValue(value as String);
case ChannelPropertyName.channelPostPolicy:
case .channelPostPolicy:
return ChannelPostPolicy.fromApiValue(value as int);
case ChannelPropertyName.folderId:
case .folderId:
return value as int?;
case ChannelPropertyName.canAddSubscribersGroup:
case ChannelPropertyName.canDeleteAnyMessageGroup:
case ChannelPropertyName.canDeleteOwnMessageGroup:
case ChannelPropertyName.canSendMessageGroup:
case ChannelPropertyName.canSubscribeGroup:
case .canAddSubscribersGroup:
case .canDeleteAnyMessageGroup:
case .canDeleteOwnMessageGroup:
case .canSendMessageGroup:
case .canSubscribeGroup:
return GroupSettingValue.fromJson(value);
case ChannelPropertyName.isRecentlyActive:
case .isRecentlyActive:
return value as bool;
case ChannelPropertyName.streamWeeklyTraffic:
case .streamWeeklyTraffic:
return value as int?;
case null:
case .unknown:
return null;
}
}
Expand Down Expand Up @@ -1405,8 +1406,9 @@ class DeleteMessageEvent extends Event {

final List<int> messageIds;
// final int messageId; // Not present; we support the bulk_message_deletion capability
// The server never actually sends "direct" here yet (it's "private" instead),
// but we accept both forms for forward-compatibility.
// The server never actually sends "channel" or "direct" here yet
// (it's "stream" or "private" instead), but we accept both the old
// and new forms for forward-compatibility.
@MessageTypeConverter()
final MessageType messageType;
final int? streamId;
Expand All @@ -1423,7 +1425,7 @@ class DeleteMessageEvent extends Event {
factory DeleteMessageEvent.fromJson(Map<String, dynamic> json) {
final result = _$DeleteMessageEventFromJson(json);
// Crunchy-shell validation
if (result.messageType == MessageType.stream) {
if (result.messageType == .channel) {
result.streamId as int;
result.topic as String;
}
Expand All @@ -1434,30 +1436,6 @@ class DeleteMessageEvent extends Event {
Map<String, dynamic> toJson() => _$DeleteMessageEventToJson(this);
}

/// As in [DeleteMessageEvent.messageType],
/// [UpdateMessageFlagsMessageDetail.type],
/// or [TypingEvent.messageType].
@JsonEnum(alwaysCreate: true)
enum MessageType {
stream,
direct;
}

class MessageTypeConverter extends JsonConverter<MessageType, String> {
const MessageTypeConverter();

@override
MessageType fromJson(String json) {
if (json == 'private') json = 'direct'; // TODO(server-future)
return $enumDecode(_$MessageTypeEnumMap, json);
}

@override
String toJson(MessageType object) {
return _$MessageTypeEnumMap[object]!;
}
}

/// A Zulip event of type `update_message_flags`.
///
/// For the corresponding API docs, see subclasses.
Expand Down Expand Up @@ -1536,8 +1514,9 @@ class UpdateMessageFlagsRemoveEvent extends UpdateMessageFlagsEvent {
/// As in [UpdateMessageFlagsRemoveEvent.messageDetails].
@JsonSerializable(fieldRename: FieldRename.snake)
class UpdateMessageFlagsMessageDetail {
// The server never actually sends "direct" here yet (it's "private" instead),
// but we accept both forms for forward-compatibility.
// The server never actually sends "channel" or "direct" here yet
// (it's "stream" or "private" instead), but we accept both the old
// and new forms for forward-compatibility.
@MessageTypeConverter()
final MessageType type;
final bool? mentioned;
Expand All @@ -1557,10 +1536,10 @@ class UpdateMessageFlagsMessageDetail {
final result = _$UpdateMessageFlagsMessageDetailFromJson(json);
// Crunchy-shell validation
switch (result.type) {
case MessageType.stream:
case .channel:
result.streamId as int;
result.topic as String;
case MessageType.direct:
case .direct:
result.userIds as List<int>;
}
return result;
Expand Down Expand Up @@ -1613,7 +1592,10 @@ class TypingEvent extends Event {
@JsonKey(includeToJson: true)
String get type => 'typing';

@JsonKey(unknownEnumValue: TypingOp.unknown)
final TypingOp op;
// The server never actually sends "channel" here yet (it's "stream" instead),
// but we accept both forms for forward-compatibility.
@MessageTypeConverter()
final MessageType messageType;
@JsonKey(readValue: _readSenderId)
Expand Down Expand Up @@ -1647,10 +1629,10 @@ class TypingEvent extends Event {
final result = _$TypingEventFromJson(json);
// Crunchy-shell validation
switch (result.messageType) {
case MessageType.stream:
case .channel:
result.streamId as int;
result.topic as String;
case MessageType.direct:
case .direct:
result.recipientIds as List<int>;
}
return result;
Expand All @@ -1664,7 +1646,10 @@ class TypingEvent extends Event {
@JsonEnum(fieldRename: FieldRename.snake)
enum TypingOp {
start,
stop;
stop,

/// A new, unrecognized operation.
unknown;

String toJson() => _$TypingOpEnumMap[this]!;
}
Expand Down Expand Up @@ -1743,6 +1728,7 @@ class ReactionEvent extends Event {
@JsonKey(includeToJson: true)
String get type => 'reaction';

@JsonKey(unknownEnumValue: ReactionOp.unknown)
final ReactionOp op;

final String emojiName;
Expand Down Expand Up @@ -1774,6 +1760,9 @@ class ReactionEvent extends Event {
enum ReactionOp {
add,
remove,

/// A new, unrecognized operation.
unknown;
}

/// A Zulip event of type `heartbeat`: https://zulip.com/api/get-events#heartbeat
Expand Down
72 changes: 41 additions & 31 deletions lib/api/model/events.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading