api!(jsonrpc): chat_type now contains a variant of a string enum/union. Affected places: FullChat.chat_type, BasicChat.chat_type, ChatListItemFetchResult::ChatListItem.chat_type, Event:: SecurejoinInviterProgress.chat_type and MessageSearchResult.chat_type (#7285)

Actually it will be not as breaking if you used the constants, because
this pr also changes the constants.

closes #7029 

Note that I had to change the constants from enum to namespace, this has
the side effect, that you can no longer also use the constants as types,
you need to instead prefix them with `typeof ` now.
This commit is contained in:
Simon Laux
2025-11-06 13:53:48 +01:00
committed by GitHub
parent ee75094bef
commit a3328ea2de
6 changed files with 73 additions and 24 deletions

View File

@@ -6,7 +6,6 @@ use deltachat::chat::{Chat, ChatId};
use deltachat::constants::Chattype; use deltachat::constants::Chattype;
use deltachat::contact::{Contact, ContactId}; use deltachat::contact::{Contact, ContactId};
use deltachat::context::Context; use deltachat::context::Context;
use num_traits::cast::ToPrimitive;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use typescript_type_def::TypeDef; use typescript_type_def::TypeDef;
@@ -46,7 +45,7 @@ pub struct FullChat {
archived: bool, archived: bool,
pinned: bool, pinned: bool,
// subtitle - will be moved to frontend because it uses translation functions // subtitle - will be moved to frontend because it uses translation functions
chat_type: u32, chat_type: JsonrpcChatType,
is_unpromoted: bool, is_unpromoted: bool,
is_self_talk: bool, is_self_talk: bool,
contacts: Vec<ContactObject>, contacts: Vec<ContactObject>,
@@ -130,7 +129,7 @@ impl FullChat {
profile_image, //BLOBS ? profile_image, //BLOBS ?
archived: chat.get_visibility() == chat::ChatVisibility::Archived, archived: chat.get_visibility() == chat::ChatVisibility::Archived,
pinned: chat.get_visibility() == chat::ChatVisibility::Pinned, pinned: chat.get_visibility() == chat::ChatVisibility::Pinned,
chat_type: chat.get_type().to_u32().context("unknown chat type id")?, chat_type: chat.get_type().into(),
is_unpromoted: chat.is_unpromoted(), is_unpromoted: chat.is_unpromoted(),
is_self_talk: chat.is_self_talk(), is_self_talk: chat.is_self_talk(),
contacts, contacts,
@@ -192,7 +191,7 @@ pub struct BasicChat {
profile_image: Option<String>, //BLOBS ? profile_image: Option<String>, //BLOBS ?
archived: bool, archived: bool,
pinned: bool, pinned: bool,
chat_type: u32, chat_type: JsonrpcChatType,
is_unpromoted: bool, is_unpromoted: bool,
is_self_talk: bool, is_self_talk: bool,
color: String, color: String,
@@ -220,7 +219,7 @@ impl BasicChat {
profile_image, //BLOBS ? profile_image, //BLOBS ?
archived: chat.get_visibility() == chat::ChatVisibility::Archived, archived: chat.get_visibility() == chat::ChatVisibility::Archived,
pinned: chat.get_visibility() == chat::ChatVisibility::Pinned, pinned: chat.get_visibility() == chat::ChatVisibility::Pinned,
chat_type: chat.get_type().to_u32().context("unknown chat type id")?, chat_type: chat.get_type().into(),
is_unpromoted: chat.is_unpromoted(), is_unpromoted: chat.is_unpromoted(),
is_self_talk: chat.is_self_talk(), is_self_talk: chat.is_self_talk(),
color, color,
@@ -274,3 +273,37 @@ impl JsonrpcChatVisibility {
} }
} }
} }
#[derive(Clone, Serialize, Deserialize, PartialEq, TypeDef, schemars::JsonSchema)]
#[serde(rename = "ChatType")]
pub enum JsonrpcChatType {
Single,
Group,
Mailinglist,
OutBroadcast,
InBroadcast,
}
impl From<Chattype> for JsonrpcChatType {
fn from(chattype: Chattype) -> Self {
match chattype {
Chattype::Single => JsonrpcChatType::Single,
Chattype::Group => JsonrpcChatType::Group,
Chattype::Mailinglist => JsonrpcChatType::Mailinglist,
Chattype::OutBroadcast => JsonrpcChatType::OutBroadcast,
Chattype::InBroadcast => JsonrpcChatType::InBroadcast,
}
}
}
impl From<JsonrpcChatType> for Chattype {
fn from(chattype: JsonrpcChatType) -> Self {
match chattype {
JsonrpcChatType::Single => Chattype::Single,
JsonrpcChatType::Group => Chattype::Group,
JsonrpcChatType::Mailinglist => Chattype::Mailinglist,
JsonrpcChatType::OutBroadcast => Chattype::OutBroadcast,
JsonrpcChatType::InBroadcast => Chattype::InBroadcast,
}
}
}

View File

@@ -11,6 +11,7 @@ use num_traits::cast::ToPrimitive;
use serde::Serialize; use serde::Serialize;
use typescript_type_def::TypeDef; use typescript_type_def::TypeDef;
use super::chat::JsonrpcChatType;
use super::color_int_to_hex_string; use super::color_int_to_hex_string;
use super::message::MessageViewtype; use super::message::MessageViewtype;
@@ -23,7 +24,7 @@ pub enum ChatListItemFetchResult {
name: String, name: String,
avatar_path: Option<String>, avatar_path: Option<String>,
color: String, color: String,
chat_type: u32, chat_type: JsonrpcChatType,
last_updated: Option<i64>, last_updated: Option<i64>,
summary_text1: String, summary_text1: String,
summary_text2: String, summary_text2: String,
@@ -151,7 +152,7 @@ pub(crate) async fn get_chat_list_item_by_id(
name: chat.get_name().to_owned(), name: chat.get_name().to_owned(),
avatar_path, avatar_path,
color, color,
chat_type: chat.get_type().to_u32().context("unknown chat type id")?, chat_type: chat.get_type().into(),
last_updated, last_updated,
summary_text1, summary_text1,
summary_text2, summary_text2,

View File

@@ -1,8 +1,9 @@
use deltachat::{Event as CoreEvent, EventType as CoreEventType}; use deltachat::{Event as CoreEvent, EventType as CoreEventType};
use num_traits::ToPrimitive;
use serde::Serialize; use serde::Serialize;
use typescript_type_def::TypeDef; use typescript_type_def::TypeDef;
use super::chat::JsonrpcChatType;
#[derive(Serialize, TypeDef, schemars::JsonSchema)] #[derive(Serialize, TypeDef, schemars::JsonSchema)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct Event { pub struct Event {
@@ -307,7 +308,7 @@ pub enum EventType {
/// The type of the joined chat. /// The type of the joined chat.
/// This can take the same values /// This can take the same values
/// as `BasicChat.chatType` ([`crate::api::types::chat::BasicChat::chat_type`]). /// as `BasicChat.chatType` ([`crate::api::types::chat::BasicChat::chat_type`]).
chat_type: u32, chat_type: JsonrpcChatType,
/// ID of the chat in case of success. /// ID of the chat in case of success.
chat_id: u32, chat_id: u32,
@@ -570,7 +571,7 @@ impl From<CoreEventType> for EventType {
progress, progress,
} => SecurejoinInviterProgress { } => SecurejoinInviterProgress {
contact_id: contact_id.to_u32(), contact_id: contact_id.to_u32(),
chat_type: chat_type.to_u32().unwrap_or(0), chat_type: chat_type.into(),
chat_id: chat_id.to_u32(), chat_id: chat_id.to_u32(),
progress, progress,
}, },

View File

@@ -16,6 +16,7 @@ use num_traits::cast::ToPrimitive;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use typescript_type_def::TypeDef; use typescript_type_def::TypeDef;
use super::chat::JsonrpcChatType;
use super::color_int_to_hex_string; use super::color_int_to_hex_string;
use super::contact::ContactObject; use super::contact::ContactObject;
use super::reactions::JsonrpcReactions; use super::reactions::JsonrpcReactions;
@@ -531,7 +532,7 @@ pub struct MessageSearchResult {
chat_profile_image: Option<String>, chat_profile_image: Option<String>,
chat_color: String, chat_color: String,
chat_name: String, chat_name: String,
chat_type: u32, chat_type: JsonrpcChatType,
is_chat_contact_request: bool, is_chat_contact_request: bool,
is_chat_archived: bool, is_chat_archived: bool,
message: String, message: String,
@@ -569,7 +570,7 @@ impl MessageSearchResult {
chat_id: chat.id.to_u32(), chat_id: chat.id.to_u32(),
chat_name: chat.get_name().to_owned(), chat_name: chat.get_name().to_owned(),
chat_color, chat_color,
chat_type: chat.get_type().to_u32().context("unknown chat type id")?, chat_type: chat.get_type().into(),
chat_profile_image, chat_profile_image,
is_chat_contact_request: chat.is_contact_request(), is_chat_contact_request: chat.is_contact_request(),
is_chat_archived: chat.get_visibility() == ChatVisibility::Archived, is_chat_archived: chat.get_visibility() == ChatVisibility::Archived,

View File

@@ -45,15 +45,30 @@ const constants = data
key.startsWith("DC_SOCKET_") || key.startsWith("DC_SOCKET_") ||
key.startsWith("DC_LP_AUTH_") || key.startsWith("DC_LP_AUTH_") ||
key.startsWith("DC_PUSH_") || key.startsWith("DC_PUSH_") ||
key.startsWith("DC_TEXT1_") key.startsWith("DC_TEXT1_") ||
key.startsWith("DC_CHAT_TYPE")
); );
}) })
.map((row) => { .map((row) => {
return ` ${row.key}: ${row.value}`; return ` export const ${row.key} = ${row.value};`;
}) })
.join(",\n"); .join("\n");
writeFileSync( writeFileSync(
resolve(__dirname, "../generated/constants.ts"), resolve(__dirname, "../generated/constants.ts"),
`// Generated!\n\nexport enum C {\n${constants.replace(/:/g, " =")},\n}\n`, `// Generated!
export namespace C {
${constants}
/** @deprecated 10-8-2025 compare string directly with \`== "Group"\` */
export const DC_CHAT_TYPE_GROUP = "Group";
/** @deprecated 10-8-2025 compare string directly with \`== "InBroadcast"\`*/
export const DC_CHAT_TYPE_IN_BROADCAST = "InBroadcast";
/** @deprecated 10-8-2025 compare string directly with \`== "Mailinglist"\` */
export const DC_CHAT_TYPE_MAILINGLIST = "Mailinglist";
/** @deprecated 10-8-2025 compare string directly with \`== "OutBroadcast"\` */
export const DC_CHAT_TYPE_OUT_BROADCAST = "OutBroadcast";
/** @deprecated 10-8-2025 compare string directly with \`== "Single"\` */
export const DC_CHAT_TYPE_SINGLE = "Single";
}\n`,
); );

View File

@@ -91,19 +91,17 @@ class ChatId(IntEnum):
LAST_SPECIAL = 9 LAST_SPECIAL = 9
class ChatType(IntEnum): class ChatType(str, Enum):
"""Chat type.""" """Chat type."""
UNDEFINED = 0 SINGLE = "Single"
SINGLE = 100
"""1:1 chat, i.e. a direct chat with a single contact""" """1:1 chat, i.e. a direct chat with a single contact"""
GROUP = 120 GROUP = "Group"
MAILINGLIST = 140 MAILINGLIST = "Mailinglist"
OUT_BROADCAST = 160 OUT_BROADCAST = "OutBroadcast"
"""Outgoing broadcast channel, called "Channel" in the UI. """Outgoing broadcast channel, called "Channel" in the UI.
The user can send into this channel, The user can send into this channel,
@@ -115,7 +113,7 @@ class ChatType(IntEnum):
which would make it hard to grep for it. which would make it hard to grep for it.
""" """
IN_BROADCAST = 165 IN_BROADCAST = "InBroadcast"
"""Incoming broadcast channel, called "Channel" in the UI. """Incoming broadcast channel, called "Channel" in the UI.
This channel is read-only, This channel is read-only,