Preserve typing events in iOS FFI
This commit is contained in:
@@ -173,6 +173,7 @@ public enum SessionEvent: Equatable, Sendable {
|
|||||||
case reactionChanged(Int64, Int64, [Reaction])
|
case reactionChanged(Int64, Int64, [Reaction])
|
||||||
case incomingNotificationCandidate(ChatSummary, Message, String)
|
case incomingNotificationCandidate(ChatSummary, Message, String)
|
||||||
case networkChanged(NetworkState)
|
case networkChanged(NetworkState)
|
||||||
|
case typingChanged(TypingState)
|
||||||
case draftChanged(Draft)
|
case draftChanged(Draft)
|
||||||
case profileLoaded(Profile)
|
case profileLoaded(Profile)
|
||||||
case mediaDownloadProgress(fileId: Int32, downloadedSize: Int64, totalSize: Int64)
|
case mediaDownloadProgress(fileId: Int32, downloadedSize: Int64, totalSize: Int64)
|
||||||
@@ -185,3 +186,8 @@ public enum NetworkState: Equatable, Sendable {
|
|||||||
case updating
|
case updating
|
||||||
case ready
|
case ready
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum TypingState: Equatable, Sendable {
|
||||||
|
case idle
|
||||||
|
case typing(chatId: Int64, userId: Int64, text: String)
|
||||||
|
}
|
||||||
|
|||||||
@@ -155,6 +155,15 @@ public actor UniFfiSessionBridge: SessionBridge {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static func mapTypingState(_ state: IosTypingState) -> TypingState {
|
||||||
|
switch state {
|
||||||
|
case .idle:
|
||||||
|
.idle
|
||||||
|
case let .typing(chatId, userId, text):
|
||||||
|
.typing(chatId: chatId, userId: userId, text: text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static func mapFolder(_ folder: IosFolder) -> Folder {
|
private static func mapFolder(_ folder: IosFolder) -> Folder {
|
||||||
Folder(id: folder.id, name: folder.name)
|
Folder(id: folder.id, name: folder.name)
|
||||||
}
|
}
|
||||||
@@ -236,6 +245,8 @@ public actor UniFfiSessionBridge: SessionBridge {
|
|||||||
)
|
)
|
||||||
case let .networkChanged(state):
|
case let .networkChanged(state):
|
||||||
.networkChanged(mapNetworkState(state))
|
.networkChanged(mapNetworkState(state))
|
||||||
|
case let .typingChanged(state):
|
||||||
|
.typingChanged(mapTypingState(state))
|
||||||
case let .draftChanged(draft):
|
case let .draftChanged(draft):
|
||||||
.draftChanged(mapDraft(draft))
|
.draftChanged(mapDraft(draft))
|
||||||
case let .profileLoaded(profile):
|
case let .profileLoaded(profile):
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ public final class SessionStore: ObservableObject {
|
|||||||
@Published public private(set) var account: Account
|
@Published public private(set) var account: Account
|
||||||
@Published public private(set) var authState: AuthState = .waitTdlibParameters
|
@Published public private(set) var authState: AuthState = .waitTdlibParameters
|
||||||
@Published public private(set) var networkState: NetworkState = .ready
|
@Published public private(set) var networkState: NetworkState = .ready
|
||||||
|
@Published public private(set) var typingState: TypingState = .idle
|
||||||
@Published public private(set) var errorMessage: String?
|
@Published public private(set) var errorMessage: String?
|
||||||
|
|
||||||
public let bridge: SessionBridge
|
public let bridge: SessionBridge
|
||||||
@@ -40,6 +41,8 @@ public final class SessionStore: ObservableObject {
|
|||||||
authState = state
|
authState = state
|
||||||
case let .networkChanged(state):
|
case let .networkChanged(state):
|
||||||
networkState = state
|
networkState = state
|
||||||
|
case let .typingChanged(state):
|
||||||
|
typingState = state
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ struct TeleTuiIOSSmokeTests {
|
|||||||
precondition(store.authState == .waitPhoneNumber)
|
precondition(store.authState == .waitPhoneNumber)
|
||||||
await store.refreshNetworkState()
|
await store.refreshNetworkState()
|
||||||
precondition(store.networkState == .ready)
|
precondition(store.networkState == .ready)
|
||||||
|
store.apply(events: [.typingChanged(.typing(chatId: 1, userId: 10, text: "typing"))])
|
||||||
|
precondition(store.typingState == .typing(chatId: 1, userId: 10, text: "typing"))
|
||||||
|
|
||||||
viewModel.phone = "+10000000000"
|
viewModel.phone = "+10000000000"
|
||||||
await viewModel.submitCurrentStep()
|
await viewModel.submitCurrentStep()
|
||||||
|
|||||||
@@ -813,6 +813,18 @@ mod tests {
|
|||||||
CoreNetworkState::from(&NetworkState::WaitingForNetwork),
|
CoreNetworkState::from(&NetworkState::WaitingForNetwork),
|
||||||
CoreNetworkState::WaitingForNetwork
|
CoreNetworkState::WaitingForNetwork
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
CoreTypingState::Typing {
|
||||||
|
chat_id: ChatId::new(42),
|
||||||
|
user_id: UserId::new(7),
|
||||||
|
text: "typing".to_string(),
|
||||||
|
},
|
||||||
|
CoreTypingState::Typing {
|
||||||
|
chat_id: ChatId::new(42),
|
||||||
|
user_id: UserId::new(7),
|
||||||
|
text: "typing".to_string(),
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use std::collections::HashMap;
|
|||||||
use tele_core::session::{
|
use tele_core::session::{
|
||||||
CoreAuthState, CoreChatSummary, CoreDownloadedFile, CoreDraft, CoreEvent, CoreFolder,
|
CoreAuthState, CoreChatSummary, CoreDownloadedFile, CoreDraft, CoreEvent, CoreFolder,
|
||||||
CoreMedia, CoreMessage, CoreNetworkState, CoreProfile, CoreReaction, CoreSearchResult,
|
CoreMedia, CoreMessage, CoreNetworkState, CoreProfile, CoreReaction, CoreSearchResult,
|
||||||
CoreSession,
|
CoreSession, CoreTypingState,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "core-session")]
|
#[cfg(feature = "core-session")]
|
||||||
use tele_core::tdlib::{ChatInfo, MessageBuilder, NetworkState, ProfileInfo};
|
use tele_core::tdlib::{ChatInfo, MessageBuilder, NetworkState, ProfileInfo};
|
||||||
@@ -86,6 +86,30 @@ impl From<CoreNetworkState> for IosNetworkState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, uniffi::Enum)]
|
||||||
|
pub enum IosTypingState {
|
||||||
|
Idle,
|
||||||
|
Typing {
|
||||||
|
chat_id: i64,
|
||||||
|
user_id: i64,
|
||||||
|
text: String,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "core-session")]
|
||||||
|
impl From<CoreTypingState> for IosTypingState {
|
||||||
|
fn from(value: CoreTypingState) -> Self {
|
||||||
|
match value {
|
||||||
|
CoreTypingState::Idle => Self::Idle,
|
||||||
|
CoreTypingState::Typing { chat_id, user_id, text } => Self::Typing {
|
||||||
|
chat_id: chat_id.as_i64(),
|
||||||
|
user_id: user_id.as_i64(),
|
||||||
|
text,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, uniffi::Enum)]
|
#[derive(Debug, Clone, PartialEq, Eq, uniffi::Enum)]
|
||||||
pub enum IosDownloadState {
|
pub enum IosDownloadState {
|
||||||
NotDownloaded,
|
NotDownloaded,
|
||||||
@@ -412,6 +436,9 @@ pub enum IosEvent {
|
|||||||
downloaded_size: i64,
|
downloaded_size: i64,
|
||||||
total_size: i64,
|
total_size: i64,
|
||||||
},
|
},
|
||||||
|
TypingChanged {
|
||||||
|
state: IosTypingState,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "core-session")]
|
#[cfg(feature = "core-session")]
|
||||||
@@ -455,7 +482,7 @@ impl From<CoreEvent> for IosEvent {
|
|||||||
CoreEvent::MediaDownloadProgress { file_id, downloaded_size, total_size } => {
|
CoreEvent::MediaDownloadProgress { file_id, downloaded_size, total_size } => {
|
||||||
Self::MediaDownloadProgress { file_id, downloaded_size, total_size }
|
Self::MediaDownloadProgress { file_id, downloaded_size, total_size }
|
||||||
}
|
}
|
||||||
CoreEvent::TypingChanged(_) => Self::NetworkChanged { state: IosNetworkState::Ready },
|
CoreEvent::TypingChanged(state) => Self::TypingChanged { state: state.into() },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1363,4 +1390,21 @@ mod tests {
|
|||||||
|
|
||||||
assert!(format!("{error}").contains("real TDLib sessions"));
|
assert!(format!("{error}").contains("real TDLib sessions"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "core-session")]
|
||||||
|
#[test]
|
||||||
|
fn typing_events_are_preserved_for_ios() {
|
||||||
|
let event = IosEvent::from(CoreEvent::TypingChanged(CoreTypingState::Typing {
|
||||||
|
chat_id: ChatId::new(1),
|
||||||
|
user_id: tele_core::types::UserId::new(2),
|
||||||
|
text: "typing".to_string(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
assert!(matches!(
|
||||||
|
event,
|
||||||
|
IosEvent::TypingChanged {
|
||||||
|
state: IosTypingState::Typing { chat_id: 1, user_id: 2, text }
|
||||||
|
} if text == "typing"
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user