Expose leave chat to iOS bridge
This commit is contained in:
@@ -12,6 +12,7 @@ public protocol SessionBridge: Sendable {
|
|||||||
func loadHistory(chatId: Int64) async throws -> [Message]
|
func loadHistory(chatId: Int64) async throws -> [Message]
|
||||||
func searchMessages(chatId: Int64, query: String) async throws -> [Message]
|
func searchMessages(chatId: Int64, query: String) async throws -> [Message]
|
||||||
func openProfile(chatId: Int64) async throws -> Profile
|
func openProfile(chatId: Int64) async throws -> Profile
|
||||||
|
func leaveChat(chatId: Int64) async throws
|
||||||
func sendMessage(chatId: Int64, text: String, replyToMessageId: Int64?) async throws -> Message
|
func sendMessage(chatId: Int64, text: String, replyToMessageId: Int64?) async throws -> Message
|
||||||
func editMessage(chatId: Int64, messageId: Int64, text: String) async throws -> Message
|
func editMessage(chatId: Int64, messageId: Int64, text: String) async throws -> Message
|
||||||
func deleteMessages(chatId: Int64, messageIds: [Int64]) async throws
|
func deleteMessages(chatId: Int64, messageIds: [Int64]) async throws
|
||||||
@@ -132,6 +133,12 @@ public actor FakeSessionBridge: SessionBridge {
|
|||||||
return profile
|
return profile
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func leaveChat(chatId: Int64) async throws {
|
||||||
|
chats.removeAll { $0.id == chatId }
|
||||||
|
messages.removeValue(forKey: chatId)
|
||||||
|
events.append(.chatListChanged(chats))
|
||||||
|
}
|
||||||
|
|
||||||
public func sendMessage(chatId: Int64, text: String, replyToMessageId: Int64?) async throws -> Message {
|
public func sendMessage(chatId: Int64, text: String, replyToMessageId: Int64?) async throws -> Message {
|
||||||
let message = Message(
|
let message = Message(
|
||||||
id: nextMessageId,
|
id: nextMessageId,
|
||||||
|
|||||||
@@ -73,6 +73,10 @@ public actor UniFfiSessionBridge: SessionBridge {
|
|||||||
try Self.mapProfile(handle.openProfile(chatId: chatId))
|
try Self.mapProfile(handle.openProfile(chatId: chatId))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func leaveChat(chatId: Int64) async throws {
|
||||||
|
try handle.leaveChat(chatId: chatId)
|
||||||
|
}
|
||||||
|
|
||||||
public func sendMessage(chatId: Int64, text: String, replyToMessageId: Int64?) async throws -> Message {
|
public func sendMessage(chatId: Int64, text: String, replyToMessageId: Int64?) async throws -> Message {
|
||||||
try Self.mapMessage(
|
try Self.mapMessage(
|
||||||
handle.sendMessage(chatId: chatId, text: text, replyToMessageId: replyToMessageId),
|
handle.sendMessage(chatId: chatId, text: text, replyToMessageId: replyToMessageId),
|
||||||
|
|||||||
@@ -284,6 +284,15 @@ public final class ProfileViewModel: ObservableObject {
|
|||||||
errorMessage = error.localizedDescription
|
errorMessage = error.localizedDescription
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func leave(chatId: Int64) async {
|
||||||
|
do {
|
||||||
|
try await bridge.leaveChat(chatId: chatId)
|
||||||
|
errorMessage = nil
|
||||||
|
} catch {
|
||||||
|
errorMessage = error.localizedDescription
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
|
|||||||
@@ -208,6 +208,10 @@ struct TeleTuiIOSSmokeTests {
|
|||||||
await viewModel.load(chatId: 1)
|
await viewModel.load(chatId: 1)
|
||||||
precondition(viewModel.profile?.title == "Saved Messages")
|
precondition(viewModel.profile?.title == "Saved Messages")
|
||||||
precondition(viewModel.profile?.username == "saved")
|
precondition(viewModel.profile?.username == "saved")
|
||||||
|
|
||||||
|
await viewModel.leave(chatId: 1)
|
||||||
|
let chats = try await bridge.loadChats(folderId: nil)
|
||||||
|
precondition(!chats.contains { $0.id == 1 })
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func appStorageUsesApplicationSupportStyleAccountPaths() {
|
private static func appStorageUsesApplicationSupportStyleAccountPaths() {
|
||||||
|
|||||||
@@ -249,6 +249,10 @@ impl<C: TdClientTrait> CoreSession<C> {
|
|||||||
Ok(profile)
|
Ok(profile)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn leave_chat(&mut self, chat_id: ChatId) -> Result<(), String> {
|
||||||
|
self.client.leave_chat(chat_id).await
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn set_draft(&mut self, chat_id: ChatId, text: String) -> Result<(), String> {
|
pub async fn set_draft(&mut self, chat_id: ChatId, text: String) -> Result<(), String> {
|
||||||
self.client.set_draft_message(chat_id, text.clone()).await?;
|
self.client.set_draft_message(chat_id, text.clone()).await?;
|
||||||
self.enqueue_event(CoreEvent::DraftChanged(CoreDraft { chat_id, text }));
|
self.enqueue_event(CoreEvent::DraftChanged(CoreDraft { chat_id, text }));
|
||||||
@@ -851,6 +855,7 @@ mod tests {
|
|||||||
session.emit_auth_state();
|
session.emit_auth_state();
|
||||||
session.emit_network_state();
|
session.emit_network_state();
|
||||||
let loaded_profile = session.open_profile(ChatId::new(42)).await.unwrap();
|
let loaded_profile = session.open_profile(ChatId::new(42)).await.unwrap();
|
||||||
|
session.leave_chat(ChatId::new(42)).await.unwrap();
|
||||||
session
|
session
|
||||||
.set_draft(ChatId::new(42), "Later".to_string())
|
.set_draft(ChatId::new(42), "Later".to_string())
|
||||||
.await
|
.await
|
||||||
|
|||||||
@@ -638,6 +638,13 @@ impl SessionHandle {
|
|||||||
.map_err(IosFfiError::from)
|
.map_err(IosFfiError::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn leave_chat(&self, chat_id: i64) -> Result<(), IosFfiError> {
|
||||||
|
let mut session = self.session.lock().expect("session mutex poisoned");
|
||||||
|
self.runtime
|
||||||
|
.block_on(session.leave_chat(ChatId::new(chat_id)))
|
||||||
|
.map_err(IosFfiError::from)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn send_message(
|
pub fn send_message(
|
||||||
&self,
|
&self,
|
||||||
chat_id: i64,
|
chat_id: i64,
|
||||||
@@ -1072,6 +1079,16 @@ impl SessionHandle {
|
|||||||
Ok(profile)
|
Ok(profile)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn leave_chat(&self, chat_id: i64) -> Result<(), IosFfiError> {
|
||||||
|
let mut state = self.state.lock().expect("session mutex poisoned");
|
||||||
|
state.chats.retain(|chat| chat.id != chat_id);
|
||||||
|
state.messages.remove(&chat_id);
|
||||||
|
state.profiles.remove(&chat_id);
|
||||||
|
let chats = state.chats.clone();
|
||||||
|
state.events.push(IosEvent::ChatListChanged { chats });
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn send_message(
|
pub fn send_message(
|
||||||
&self,
|
&self,
|
||||||
chat_id: i64,
|
chat_id: i64,
|
||||||
@@ -1374,6 +1391,11 @@ mod tests {
|
|||||||
assert!(events
|
assert!(events
|
||||||
.iter()
|
.iter()
|
||||||
.any(|event| matches!(event, IosEvent::IncomingNotificationCandidate { .. })));
|
.any(|event| matches!(event, IosEvent::IncomingNotificationCandidate { .. })));
|
||||||
|
|
||||||
|
session.leave_chat(chats[0].id).unwrap();
|
||||||
|
if !cfg!(feature = "core-session") {
|
||||||
|
assert!(session.load_history(chats[0].id, 20).unwrap().is_empty());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -103,6 +103,12 @@ struct Smoke {
|
|||||||
require(events.contains { if case .messageAdded = $0 { return true }; return false }, "expected messageAdded event")
|
require(events.contains { if case .messageAdded = $0 { return true }; return false }, "expected messageAdded event")
|
||||||
require(events.contains { if case .incomingNotificationCandidate = $0 { return true }; return false }, "expected notification candidate")
|
require(events.contains { if case .incomingNotificationCandidate = $0 { return true }; return false }, "expected notification candidate")
|
||||||
|
|
||||||
|
try session.leaveChat(chatId: chat.id)
|
||||||
|
let chatsAfterLeave = try session.loadChats(limit: 20)
|
||||||
|
require(chatsAfterLeave.isEmpty, "expected chat to be removed after leave")
|
||||||
|
let leaveEvents = session.pollEvents()
|
||||||
|
require(leaveEvents.contains { if case .chatListChanged = $0 { return true }; return false }, "expected chatListChanged event")
|
||||||
|
|
||||||
print("tele-ios-ffi Swift smoke passed")
|
print("tele-ios-ffi Swift smoke passed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user