From 004a921299039aeedc8cc49c243746ddd6e72c7b Mon Sep 17 00:00:00 2001 From: Lonami Exo Date: Thu, 27 Oct 2022 18:42:48 +0200 Subject: [PATCH] Use UDL dictionaries to simplify return values --- .../lonami/talaria/data/DialogRepository.kt | 41 +---- .../java/dev/lonami/talaria/models/Dialog.kt | 8 - .../lonami/talaria/models/MessagePreview.kt | 11 -- .../lonami/talaria/ui/screens/DialogScreen.kt | 12 +- .../lonami/talaria/ui/state/DialogUiState.kt | 2 +- native/src/lib.rs | 149 +++++++----------- native/src/talaria.udl | 25 +-- 7 files changed, 85 insertions(+), 163 deletions(-) delete mode 100644 app/src/main/java/dev/lonami/talaria/models/Dialog.kt delete mode 100644 app/src/main/java/dev/lonami/talaria/models/MessagePreview.kt diff --git a/app/src/main/java/dev/lonami/talaria/data/DialogRepository.kt b/app/src/main/java/dev/lonami/talaria/data/DialogRepository.kt index da1eb53..cc23beb 100644 --- a/app/src/main/java/dev/lonami/talaria/data/DialogRepository.kt +++ b/app/src/main/java/dev/lonami/talaria/data/DialogRepository.kt @@ -1,10 +1,10 @@ package dev.lonami.talaria.data -import dev.lonami.talaria.models.Dialog -import dev.lonami.talaria.models.MessagePreview -import uniffi.talaria.* -import java.time.LocalDateTime -import java.time.format.DateTimeFormatter +import uniffi.talaria.Dialog +import uniffi.talaria.MessageAck +import uniffi.talaria.MessagePreview +import uniffi.talaria.getDialogs +import java.time.Instant interface DialogRepository { fun loadDialogs(): List @@ -12,34 +12,7 @@ interface DialogRepository { class NativeDialogRepository : DialogRepository { override fun loadDialogs(): List { - val dialogs = mutableListOf() - - val dialogPtr = getDialogs() - try { - val dialogCount = dialogCount(dialogPtr) - for (i in 0U until dialogCount) { - dialogs.add( - Dialog( - id = dialogPacked(dialogPtr, i), - title = dialogTitle(dialogPtr, i), - lastMessage = MessagePreview( - sender = dialogSender(dialogPtr, i), - text = dialogText(dialogPtr, i), - date = LocalDateTime.parse( - dialogTime(dialogPtr, i), - DateTimeFormatter.ISO_OFFSET_DATE_TIME - ), - ack = dialogAck(dialogPtr, i), - ), - pinned = dialogPin(dialogPtr, i) != 0U - ) - ) - } - } finally { - freeDialogs(dialogPtr) - } - - return dialogs + return getDialogs() } } @@ -65,7 +38,7 @@ class MockDialogRepository : DialogRepository { } else { "Sample Message $i" }, - date = LocalDateTime.now(), + date = Instant.now(), ack = when (i % 3) { 0 -> MessageAck.RECEIVED 1 -> MessageAck.SENT diff --git a/app/src/main/java/dev/lonami/talaria/models/Dialog.kt b/app/src/main/java/dev/lonami/talaria/models/Dialog.kt deleted file mode 100644 index 61e8b42..0000000 --- a/app/src/main/java/dev/lonami/talaria/models/Dialog.kt +++ /dev/null @@ -1,8 +0,0 @@ -package dev.lonami.talaria.models - -data class Dialog( - val id: String, - val title: String, - val lastMessage: MessagePreview?, - val pinned: Boolean, -) diff --git a/app/src/main/java/dev/lonami/talaria/models/MessagePreview.kt b/app/src/main/java/dev/lonami/talaria/models/MessagePreview.kt deleted file mode 100644 index b4c53a0..0000000 --- a/app/src/main/java/dev/lonami/talaria/models/MessagePreview.kt +++ /dev/null @@ -1,11 +0,0 @@ -package dev.lonami.talaria.models - -import uniffi.talaria.MessageAck -import java.time.LocalDateTime - -data class MessagePreview( - val sender: String, - val text: String, - val date: LocalDateTime, - val ack: MessageAck, -) diff --git a/app/src/main/java/dev/lonami/talaria/ui/screens/DialogScreen.kt b/app/src/main/java/dev/lonami/talaria/ui/screens/DialogScreen.kt index b576c7d..efd9c83 100644 --- a/app/src/main/java/dev/lonami/talaria/ui/screens/DialogScreen.kt +++ b/app/src/main/java/dev/lonami/talaria/ui/screens/DialogScreen.kt @@ -23,10 +23,12 @@ import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import dev.lonami.talaria.R import dev.lonami.talaria.data.MockDialogRepository -import dev.lonami.talaria.models.Dialog import dev.lonami.talaria.ui.state.DialogViewModel import dev.lonami.talaria.ui.theme.TalariaTheme +import uniffi.talaria.Dialog import uniffi.talaria.MessageAck +import java.time.LocalDateTime +import java.time.ZoneOffset import java.time.format.DateTimeFormatter import java.time.format.FormatStyle @@ -54,8 +56,8 @@ fun Dialog(dialog: Dialog, onDialogSelected: () -> Unit, modifier: Modifier = Mo Text( stringResource( R.string.message_preview, - dialog.lastMessage.sender, - dialog.lastMessage.text + dialog.lastMessage!!.sender, + dialog.lastMessage!!.text ), maxLines = 1, overflow = TextOverflow.Ellipsis, @@ -65,7 +67,7 @@ fun Dialog(dialog: Dialog, onDialogSelected: () -> Unit, modifier: Modifier = Mo Column { if (dialog.lastMessage != null) { Row { - when (dialog.lastMessage.ack) { + when (dialog.lastMessage!!.ack) { MessageAck.RECEIVED -> {} MessageAck.SENT -> Icon( painterResource(R.drawable.sent), @@ -78,7 +80,7 @@ fun Dialog(dialog: Dialog, onDialogSelected: () -> Unit, modifier: Modifier = Mo } Spacer(Modifier.width(8.dp)) Text( - dialog.lastMessage.date.format( + LocalDateTime.ofInstant(dialog.lastMessage!!.date, ZoneOffset.UTC).format( DateTimeFormatter.ofLocalizedTime( FormatStyle.SHORT ) diff --git a/app/src/main/java/dev/lonami/talaria/ui/state/DialogUiState.kt b/app/src/main/java/dev/lonami/talaria/ui/state/DialogUiState.kt index 2191812..8efaf99 100644 --- a/app/src/main/java/dev/lonami/talaria/ui/state/DialogUiState.kt +++ b/app/src/main/java/dev/lonami/talaria/ui/state/DialogUiState.kt @@ -1,5 +1,5 @@ package dev.lonami.talaria.ui.state -import dev.lonami.talaria.models.Dialog +import uniffi.talaria.Dialog data class DialogUiState(val dialogs: List = listOf()) diff --git a/native/src/lib.rs b/native/src/lib.rs index 7e7c565..f252be1 100644 --- a/native/src/lib.rs +++ b/native/src/lib.rs @@ -3,7 +3,7 @@ mod db; -use grammers_client::types::{Dialog, LoginToken}; +use grammers_client::types::{Dialog as OgDialog, LoginToken}; use grammers_client::{Client, Config, InitParams}; use grammers_session::{PackedChat, Session, UpdateState}; use grammers_tl_types as tl; @@ -15,6 +15,7 @@ use std::future::Future; use std::net::SocketAddr; use std::net::{Ipv4Addr, Ipv6Addr}; use std::sync::Mutex; +use std::time::SystemTime; use tokio::runtime; use tokio::runtime::Runtime; @@ -52,6 +53,22 @@ pub enum MessageAck { Sent, } +#[derive(Debug, Clone)] +pub struct MessagePreview { + sender: String, + text: String, + date: SystemTime, + ack: MessageAck, +} + +#[derive(Debug, Clone)] +pub struct Dialog { + id: String, + title: String, + lastMessage: Option, + pinned: bool, +} + fn block_on(future: F) -> F::Output { if RUNTIME.get().is_none() { RUNTIME @@ -199,7 +216,7 @@ async fn sign_in(token: LoginToken, code: &str) -> Result<()> { Ok(()) } -async fn get_dialogs() -> Result> { +async fn get_dialogs() -> Result> { let client = CLIENT.get().ok_or("Client not initialized")?; let mut result = Vec::new(); @@ -264,105 +281,49 @@ pub fn signIn(token_ptr: u64, code: String) { } } -pub fn getDialogs() -> u64 { +pub fn getDialogs() -> Vec { match block_on(get_dialogs()) { - Ok(dialogs) => Box::into_raw(Box::new(dialogs)) as u64, + Ok(dialogs) => dialogs + .into_iter() + .map(|d| Dialog { + id: d.chat().pack().to_hex(), + title: d.chat().name().to_string(), + lastMessage: d.last_message.map(|m| MessagePreview { + sender: if let Some(sender) = m.sender() { + sender.name().to_string() + } else { + "unknown".to_string() + }, + text: m.text().to_string(), + date: m.date().into(), + ack: if m.outgoing() { + match &d.dialog { + tl::enums::Dialog::Dialog(d) => { + if m.id() <= d.read_inbox_max_id { + MessageAck::Seen + } else { + MessageAck::Sent + } + } + tl::enums::Dialog::Folder(_) => MessageAck::Received, + } + } else { + MessageAck::Received + }, + }), + pinned: match d.dialog { + tl::enums::Dialog::Dialog(d) => d.pinned, + tl::enums::Dialog::Folder(f) => f.pinned, + }, + }) + .collect(), Err(e) => { error!("Failed to get dialogs: {}", e); - 0 as u64 + Vec::new() } } } -pub fn dialogCount(dialogsPtr: u64) -> u32 { - let dialogs = unsafe { &mut *(dialogsPtr as *mut Vec) }; - dialogs.len() as u32 -} - -pub fn dialogPacked(dialogsPtr: u64, index: u32) -> String { - let dialogs = unsafe { &mut *(dialogsPtr as *mut Vec) }; - - dialogs[index as usize].chat().pack().to_hex() -} - -pub fn dialogTitle(dialogsPtr: u64, index: u32) -> String { - let dialogs = unsafe { &mut *(dialogsPtr as *mut Vec) }; - - dialogs[index as usize].chat().name().to_string() -} - -pub fn dialogSender(dialogsPtr: u64, index: u32) -> String { - let dialogs = unsafe { &mut *(dialogsPtr as *mut Vec) }; - - if let Some(msg) = dialogs[index as usize].last_message.as_ref() { - if let Some(sender) = msg.sender() { - sender.name().to_string() - } else { - "unknown".to_string() - } - } else { - String::new() - } -} - -pub fn dialogText(dialogsPtr: u64, index: u32) -> String { - let dialogs = unsafe { &mut *(dialogsPtr as *mut Vec) }; - - if let Some(msg) = dialogs[index as usize].last_message.as_ref() { - msg.text().to_string() - } else { - "".to_string() - } -} - -pub fn dialogTime(dialogsPtr: u64, index: u32) -> String { - let dialogs = unsafe { &mut *(dialogsPtr as *mut Vec) }; - - if let Some(msg) = dialogs[index as usize].last_message.as_ref() { - msg.date().to_rfc3339().to_string() - } else { - String::new() - } -} - -pub fn dialogAck(dialogsPtr: u64, index: u32) -> MessageAck { - let dialogs = unsafe { &mut *(dialogsPtr as *mut Vec) }; - - let dialog = &dialogs[index as usize]; - if let Some(msg) = dialog.last_message.as_ref() { - if msg.outgoing() { - match &dialog.dialog { - tl::enums::Dialog::Dialog(d) => { - if msg.id() <= d.read_inbox_max_id { - MessageAck::Seen - } else { - MessageAck::Sent - } - } - tl::enums::Dialog::Folder(_) => MessageAck::Received, - } - } else { - MessageAck::Received - } - } else { - MessageAck::Received - } -} - -pub fn dialogPin(dialogsPtr: u64, index: u32) -> u32 { - let dialogs = unsafe { &mut *(dialogsPtr as *mut Vec) }; - - let pinned = match &dialogs[index as usize].dialog { - tl::enums::Dialog::Dialog(d) => d.pinned, - tl::enums::Dialog::Folder(f) => f.pinned, - }; - pinned as u32 -} - -pub fn freeDialogs(dialogsPtr: u64) { - let _ = unsafe { Box::from_raw(dialogsPtr as *mut Vec) }; -} - pub fn sendMessage(packed: String, text: String) { let packed = PackedChat::from_hex(&packed).unwrap(); match block_on(send_message(packed, &text)) { diff --git a/native/src/talaria.udl b/native/src/talaria.udl index 43eed21..7918645 100644 --- a/native/src/talaria.udl +++ b/native/src/talaria.udl @@ -4,21 +4,26 @@ enum MessageAck { "Sent", }; +dictionary MessagePreview { + string sender; + string text; + timestamp date; + MessageAck ack; +}; + +dictionary Dialog { + string id; + string title; + MessagePreview? lastMessage; + boolean pinned; +}; + namespace talaria { void initDatabase(string path); void initClient(); boolean needLogin(); u64 requestLoginCode(string phone); void signIn(u64 tokenPtr, string code); - u64 getDialogs(); - u32 dialogCount(u64 dialogsPtr); - string dialogPacked(u64 dialogsPtr, u32 index); - string dialogTitle(u64 dialogsPtr, u32 index); - string dialogSender(u64 dialogsPtr, u32 index); - string dialogText(u64 dialogsPtr, u32 index); - string dialogTime(u64 dialogsPtr, u32 index); - MessageAck dialogAck(u64 dialogsPtr, u32 index); - u32 dialogPin(u64 dialogsPtr, u32 index); - void freeDialogs(u64 dialogsPtr); + sequence getDialogs(); void sendMessage(string packed, string text); };