From 54cb08db3d64113cab03c4b731d0efbb74804cbe Mon Sep 17 00:00:00 2001 From: Simon Laux Date: Thu, 6 Nov 2025 13:16:58 +0100 Subject: [PATCH 1/5] 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` --- deltachat-jsonrpc/src/api/types/chat.rs | 43 +++++++++++++++++--- deltachat-jsonrpc/src/api/types/chat_list.rs | 5 ++- deltachat-jsonrpc/src/api/types/events.rs | 7 ++-- deltachat-jsonrpc/src/api/types/message.rs | 4 +- 4 files changed, 48 insertions(+), 11 deletions(-) diff --git a/deltachat-jsonrpc/src/api/types/chat.rs b/deltachat-jsonrpc/src/api/types/chat.rs index 3e62e9c52f..f062be6e2a 100644 --- a/deltachat-jsonrpc/src/api/types/chat.rs +++ b/deltachat-jsonrpc/src/api/types/chat.rs @@ -6,7 +6,6 @@ use deltachat::chat::{Chat, ChatId}; use deltachat::constants::Chattype; use deltachat::contact::{Contact, ContactId}; use deltachat::context::Context; -use num_traits::cast::ToPrimitive; use serde::{Deserialize, Serialize}; use typescript_type_def::TypeDef; @@ -46,7 +45,7 @@ pub struct FullChat { archived: bool, pinned: bool, // subtitle - will be moved to frontend because it uses translation functions - chat_type: u32, + chat_type: JSONRPCChatType, is_unpromoted: bool, is_self_talk: bool, contacts: Vec, @@ -130,7 +129,7 @@ impl FullChat { profile_image, //BLOBS ? archived: chat.get_visibility() == chat::ChatVisibility::Archived, 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_self_talk: chat.is_self_talk(), contacts, @@ -192,7 +191,7 @@ pub struct BasicChat { profile_image: Option, //BLOBS ? archived: bool, pinned: bool, - chat_type: u32, + chat_type: JSONRPCChatType, is_unpromoted: bool, is_self_talk: bool, color: String, @@ -220,7 +219,7 @@ impl BasicChat { profile_image, //BLOBS ? archived: chat.get_visibility() == chat::ChatVisibility::Archived, 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_self_talk: chat.is_self_talk(), 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 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 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, + } + } +} diff --git a/deltachat-jsonrpc/src/api/types/chat_list.rs b/deltachat-jsonrpc/src/api/types/chat_list.rs index 2157967ea8..5c857acbaa 100644 --- a/deltachat-jsonrpc/src/api/types/chat_list.rs +++ b/deltachat-jsonrpc/src/api/types/chat_list.rs @@ -11,6 +11,7 @@ use num_traits::cast::ToPrimitive; use serde::Serialize; use typescript_type_def::TypeDef; +use super::chat::JSONRPCChatType; use super::color_int_to_hex_string; use super::message::MessageViewtype; @@ -23,7 +24,7 @@ pub enum ChatListItemFetchResult { name: String, avatar_path: Option, color: String, - chat_type: u32, + chat_type: JSONRPCChatType, last_updated: Option, summary_text1: String, summary_text2: String, @@ -151,7 +152,7 @@ pub(crate) async fn get_chat_list_item_by_id( name: chat.get_name().to_owned(), avatar_path, color, - chat_type: chat.get_type().to_u32().context("unknown chat type id")?, + chat_type: chat.get_type().into(), last_updated, summary_text1, summary_text2, diff --git a/deltachat-jsonrpc/src/api/types/events.rs b/deltachat-jsonrpc/src/api/types/events.rs index d957f82e9f..9aa9b47d3e 100644 --- a/deltachat-jsonrpc/src/api/types/events.rs +++ b/deltachat-jsonrpc/src/api/types/events.rs @@ -1,8 +1,9 @@ use deltachat::{Event as CoreEvent, EventType as CoreEventType}; -use num_traits::ToPrimitive; use serde::Serialize; use typescript_type_def::TypeDef; +use super::chat::JSONRPCChatType; + #[derive(Serialize, TypeDef, schemars::JsonSchema)] #[serde(rename_all = "camelCase")] pub struct Event { @@ -307,7 +308,7 @@ pub enum EventType { /// The type of the joined chat. /// This can take the same values /// as `BasicChat.chatType` ([`crate::api::types::chat::BasicChat::chat_type`]). - chat_type: u32, + chat_type: JSONRPCChatType, /// ID of the chat in case of success. chat_id: u32, @@ -570,7 +571,7 @@ impl From for EventType { progress, } => SecurejoinInviterProgress { 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(), progress, }, diff --git a/deltachat-jsonrpc/src/api/types/message.rs b/deltachat-jsonrpc/src/api/types/message.rs index dd5a2023fa..f76ef9ef27 100644 --- a/deltachat-jsonrpc/src/api/types/message.rs +++ b/deltachat-jsonrpc/src/api/types/message.rs @@ -16,6 +16,7 @@ use num_traits::cast::ToPrimitive; use serde::{Deserialize, Serialize}; use typescript_type_def::TypeDef; +use super::chat::JSONRPCChatType; use super::color_int_to_hex_string; use super::contact::ContactObject; use super::reactions::JsonrpcReactions; @@ -532,6 +533,7 @@ pub struct MessageSearchResult { chat_color: String, chat_name: String, chat_type: u32, + chat_type: JSONRPCChatType, is_chat_contact_request: bool, is_chat_archived: bool, message: String, @@ -569,7 +571,7 @@ impl MessageSearchResult { chat_id: chat.id.to_u32(), chat_name: chat.get_name().to_owned(), chat_color, - chat_type: chat.get_type().to_u32().context("unknown chat type id")?, + chat_type: chat.get_type().into(), chat_profile_image, is_chat_contact_request: chat.is_contact_request(), is_chat_archived: chat.get_visibility() == ChatVisibility::Archived, From 296f4ef385036f4ae747c9480455081c4b284b31 Mon Sep 17 00:00:00 2001 From: Simon Laux Date: Wed, 8 Oct 2025 15:01:27 +0200 Subject: [PATCH 2/5] update typescript client constants --- .../typescript/scripts/generate-constants.js | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/deltachat-jsonrpc/typescript/scripts/generate-constants.js b/deltachat-jsonrpc/typescript/scripts/generate-constants.js index 3bc83f9697..51e9e1bb08 100755 --- a/deltachat-jsonrpc/typescript/scripts/generate-constants.js +++ b/deltachat-jsonrpc/typescript/scripts/generate-constants.js @@ -45,15 +45,30 @@ const constants = data key.startsWith("DC_SOCKET_") || key.startsWith("DC_LP_AUTH_") || key.startsWith("DC_PUSH_") || - key.startsWith("DC_TEXT1_") + key.startsWith("DC_TEXT1_") || + key.startsWith("DC_CHAT_TYPE") ); }) .map((row) => { - return ` ${row.key}: ${row.value}`; + return ` ${row.key} = ${row.value}`; }) .join(",\n"); writeFileSync( resolve(__dirname, "../generated/constants.ts"), - `// Generated!\n\nexport enum C {\n${constants.replace(/:/g, " =")},\n}\n`, + `// Generated! + +export enum C { +${constants}, + /** @deprecated 10-8-2025 compare string directly with \`== "Group"\` */ + DC_CHAT_TYPE_GROUP = "Group", + /** @deprecated 10-8-2025 compare string directly with \`== "InBroadcast"\`*/ + DC_CHAT_TYPE_IN_BROADCAST = "InBroadcast", + /** @deprecated 10-8-2025 compare string directly with \`== "Mailinglist"\` */ + DC_CHAT_TYPE_MAILINGLIST = "Mailinglist", + /** @deprecated 10-8-2025 compare string directly with \`== "OutBroadcast"\` */ + DC_CHAT_TYPE_OUT_BROADCAST = "OutBroadcast", + /** @deprecated 10-8-2025 compare string directly with \`== "Single"\` */ + DC_CHAT_TYPE_SINGLE = "Single", +}\n`, ); From 96375d0949ccee29a3e6ef2e024367e6c0dd721a Mon Sep 17 00:00:00 2001 From: Simon Laux Date: Wed, 8 Oct 2025 15:50:35 +0200 Subject: [PATCH 3/5] adapt python `ChatType` enum constant --- .../src/deltachat_rpc_client/const.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/deltachat-rpc-client/src/deltachat_rpc_client/const.py b/deltachat-rpc-client/src/deltachat_rpc_client/const.py index c985bdfe1a..03ae2d7b3a 100644 --- a/deltachat-rpc-client/src/deltachat_rpc_client/const.py +++ b/deltachat-rpc-client/src/deltachat_rpc_client/const.py @@ -91,19 +91,17 @@ class ChatId(IntEnum): LAST_SPECIAL = 9 -class ChatType(IntEnum): +class ChatType(str, Enum): """Chat type.""" - UNDEFINED = 0 - - SINGLE = 100 + SINGLE = "Single" """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. The user can send into this channel, @@ -115,7 +113,7 @@ class ChatType(IntEnum): which would make it hard to grep for it. """ - IN_BROADCAST = 165 + IN_BROADCAST = "InBroadcast" """Incoming broadcast channel, called "Channel" in the UI. This channel is read-only, From b1cfd3a6a6f67790c04841e6b6930ab2b0c5918b Mon Sep 17 00:00:00 2001 From: Simon Laux Date: Wed, 8 Oct 2025 16:01:08 +0200 Subject: [PATCH 4/5] js: change constants from enum to namespace to fix type issues --- .../typescript/scripts/generate-constants.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/deltachat-jsonrpc/typescript/scripts/generate-constants.js b/deltachat-jsonrpc/typescript/scripts/generate-constants.js index 51e9e1bb08..e8b09d2e16 100755 --- a/deltachat-jsonrpc/typescript/scripts/generate-constants.js +++ b/deltachat-jsonrpc/typescript/scripts/generate-constants.js @@ -50,25 +50,25 @@ const constants = data ); }) .map((row) => { - return ` ${row.key} = ${row.value}`; + return ` export const ${row.key} = ${row.value};`; }) - .join(",\n"); + .join("\n"); writeFileSync( resolve(__dirname, "../generated/constants.ts"), `// Generated! -export enum C { -${constants}, +export namespace C { +${constants} /** @deprecated 10-8-2025 compare string directly with \`== "Group"\` */ - DC_CHAT_TYPE_GROUP = "Group", + export const DC_CHAT_TYPE_GROUP = "Group"; /** @deprecated 10-8-2025 compare string directly with \`== "InBroadcast"\`*/ - DC_CHAT_TYPE_IN_BROADCAST = "InBroadcast", + export const DC_CHAT_TYPE_IN_BROADCAST = "InBroadcast"; /** @deprecated 10-8-2025 compare string directly with \`== "Mailinglist"\` */ - DC_CHAT_TYPE_MAILINGLIST = "Mailinglist", + export const DC_CHAT_TYPE_MAILINGLIST = "Mailinglist"; /** @deprecated 10-8-2025 compare string directly with \`== "OutBroadcast"\` */ - DC_CHAT_TYPE_OUT_BROADCAST = "OutBroadcast", + export const DC_CHAT_TYPE_OUT_BROADCAST = "OutBroadcast"; /** @deprecated 10-8-2025 compare string directly with \`== "Single"\` */ - DC_CHAT_TYPE_SINGLE = "Single", + export const DC_CHAT_TYPE_SINGLE = "Single"; }\n`, ); From a58cc42701d56a7436266ee1165e08377e314dd7 Mon Sep 17 00:00:00 2001 From: Simon Laux Date: Mon, 20 Oct 2025 16:59:54 +0200 Subject: [PATCH 5/5] rename `JSONRPCChatType` to `JsonrpcChatType` --- deltachat-jsonrpc/src/api/types/chat.rs | 32 ++++++++++---------- deltachat-jsonrpc/src/api/types/chat_list.rs | 4 +-- deltachat-jsonrpc/src/api/types/events.rs | 4 +-- deltachat-jsonrpc/src/api/types/message.rs | 5 ++- 4 files changed, 22 insertions(+), 23 deletions(-) diff --git a/deltachat-jsonrpc/src/api/types/chat.rs b/deltachat-jsonrpc/src/api/types/chat.rs index f062be6e2a..66403ef3a3 100644 --- a/deltachat-jsonrpc/src/api/types/chat.rs +++ b/deltachat-jsonrpc/src/api/types/chat.rs @@ -45,7 +45,7 @@ pub struct FullChat { archived: bool, pinned: bool, // subtitle - will be moved to frontend because it uses translation functions - chat_type: JSONRPCChatType, + chat_type: JsonrpcChatType, is_unpromoted: bool, is_self_talk: bool, contacts: Vec, @@ -191,7 +191,7 @@ pub struct BasicChat { profile_image: Option, //BLOBS ? archived: bool, pinned: bool, - chat_type: JSONRPCChatType, + chat_type: JsonrpcChatType, is_unpromoted: bool, is_self_talk: bool, color: String, @@ -276,7 +276,7 @@ impl JsonrpcChatVisibility { #[derive(Clone, Serialize, Deserialize, PartialEq, TypeDef, schemars::JsonSchema)] #[serde(rename = "ChatType")] -pub enum JSONRPCChatType { +pub enum JsonrpcChatType { Single, Group, Mailinglist, @@ -284,26 +284,26 @@ pub enum JSONRPCChatType { InBroadcast, } -impl From for JSONRPCChatType { +impl From 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, + Chattype::Single => JsonrpcChatType::Single, + Chattype::Group => JsonrpcChatType::Group, + Chattype::Mailinglist => JsonrpcChatType::Mailinglist, + Chattype::OutBroadcast => JsonrpcChatType::OutBroadcast, + Chattype::InBroadcast => JsonrpcChatType::InBroadcast, } } } -impl From for Chattype { - fn from(chattype: JSONRPCChatType) -> Self { +impl From 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, + JsonrpcChatType::Single => Chattype::Single, + JsonrpcChatType::Group => Chattype::Group, + JsonrpcChatType::Mailinglist => Chattype::Mailinglist, + JsonrpcChatType::OutBroadcast => Chattype::OutBroadcast, + JsonrpcChatType::InBroadcast => Chattype::InBroadcast, } } } diff --git a/deltachat-jsonrpc/src/api/types/chat_list.rs b/deltachat-jsonrpc/src/api/types/chat_list.rs index 5c857acbaa..a07641b2b2 100644 --- a/deltachat-jsonrpc/src/api/types/chat_list.rs +++ b/deltachat-jsonrpc/src/api/types/chat_list.rs @@ -11,7 +11,7 @@ use num_traits::cast::ToPrimitive; use serde::Serialize; use typescript_type_def::TypeDef; -use super::chat::JSONRPCChatType; +use super::chat::JsonrpcChatType; use super::color_int_to_hex_string; use super::message::MessageViewtype; @@ -24,7 +24,7 @@ pub enum ChatListItemFetchResult { name: String, avatar_path: Option, color: String, - chat_type: JSONRPCChatType, + chat_type: JsonrpcChatType, last_updated: Option, summary_text1: String, summary_text2: String, diff --git a/deltachat-jsonrpc/src/api/types/events.rs b/deltachat-jsonrpc/src/api/types/events.rs index 9aa9b47d3e..f7957e32db 100644 --- a/deltachat-jsonrpc/src/api/types/events.rs +++ b/deltachat-jsonrpc/src/api/types/events.rs @@ -2,7 +2,7 @@ use deltachat::{Event as CoreEvent, EventType as CoreEventType}; use serde::Serialize; use typescript_type_def::TypeDef; -use super::chat::JSONRPCChatType; +use super::chat::JsonrpcChatType; #[derive(Serialize, TypeDef, schemars::JsonSchema)] #[serde(rename_all = "camelCase")] @@ -308,7 +308,7 @@ pub enum EventType { /// The type of the joined chat. /// This can take the same values /// as `BasicChat.chatType` ([`crate::api::types::chat::BasicChat::chat_type`]). - chat_type: JSONRPCChatType, + chat_type: JsonrpcChatType, /// ID of the chat in case of success. chat_id: u32, diff --git a/deltachat-jsonrpc/src/api/types/message.rs b/deltachat-jsonrpc/src/api/types/message.rs index f76ef9ef27..567e3ffdc9 100644 --- a/deltachat-jsonrpc/src/api/types/message.rs +++ b/deltachat-jsonrpc/src/api/types/message.rs @@ -16,7 +16,7 @@ use num_traits::cast::ToPrimitive; use serde::{Deserialize, Serialize}; use typescript_type_def::TypeDef; -use super::chat::JSONRPCChatType; +use super::chat::JsonrpcChatType; use super::color_int_to_hex_string; use super::contact::ContactObject; use super::reactions::JsonrpcReactions; @@ -532,8 +532,7 @@ pub struct MessageSearchResult { chat_profile_image: Option, chat_color: String, chat_name: String, - chat_type: u32, - chat_type: JSONRPCChatType, + chat_type: JsonrpcChatType, is_chat_contact_request: bool, is_chat_archived: bool, message: String,