Use UDL dictionaries to simplify return values
This commit is contained in:
parent
1a56b03614
commit
004a921299
|
@ -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<Dialog>
|
||||
|
@ -12,34 +12,7 @@ interface DialogRepository {
|
|||
|
||||
class NativeDialogRepository : DialogRepository {
|
||||
override fun loadDialogs(): List<Dialog> {
|
||||
val dialogs = mutableListOf<Dialog>()
|
||||
|
||||
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
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
package dev.lonami.talaria.models
|
||||
|
||||
data class Dialog(
|
||||
val id: String,
|
||||
val title: String,
|
||||
val lastMessage: MessagePreview?,
|
||||
val pinned: Boolean,
|
||||
)
|
|
@ -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,
|
||||
)
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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<Dialog> = listOf())
|
||||
|
|
|
@ -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<MessagePreview>,
|
||||
pinned: bool,
|
||||
}
|
||||
|
||||
fn block_on<F: Future>(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<Vec<Dialog>> {
|
||||
async fn get_dialogs() -> Result<Vec<OgDialog>> {
|
||||
let client = CLIENT.get().ok_or("Client not initialized")?;
|
||||
|
||||
let mut result = Vec::new();
|
||||
|
@ -264,76 +281,25 @@ pub fn signIn(token_ptr: u64, code: String) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn getDialogs() -> u64 {
|
||||
pub fn getDialogs() -> Vec<Dialog> {
|
||||
match block_on(get_dialogs()) {
|
||||
Ok(dialogs) => Box::into_raw(Box::new(dialogs)) as u64,
|
||||
Err(e) => {
|
||||
error!("Failed to get dialogs: {}", e);
|
||||
0 as u64
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dialogCount(dialogsPtr: u64) -> u32 {
|
||||
let dialogs = unsafe { &mut *(dialogsPtr as *mut Vec<Dialog>) };
|
||||
dialogs.len() as u32
|
||||
}
|
||||
|
||||
pub fn dialogPacked(dialogsPtr: u64, index: u32) -> String {
|
||||
let dialogs = unsafe { &mut *(dialogsPtr as *mut Vec<Dialog>) };
|
||||
|
||||
dialogs[index as usize].chat().pack().to_hex()
|
||||
}
|
||||
|
||||
pub fn dialogTitle(dialogsPtr: u64, index: u32) -> String {
|
||||
let dialogs = unsafe { &mut *(dialogsPtr as *mut Vec<Dialog>) };
|
||||
|
||||
dialogs[index as usize].chat().name().to_string()
|
||||
}
|
||||
|
||||
pub fn dialogSender(dialogsPtr: u64, index: u32) -> String {
|
||||
let dialogs = unsafe { &mut *(dialogsPtr as *mut Vec<Dialog>) };
|
||||
|
||||
if let Some(msg) = dialogs[index as usize].last_message.as_ref() {
|
||||
if let Some(sender) = msg.sender() {
|
||||
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()
|
||||
}
|
||||
} else {
|
||||
String::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dialogText(dialogsPtr: u64, index: u32) -> String {
|
||||
let dialogs = unsafe { &mut *(dialogsPtr as *mut Vec<Dialog>) };
|
||||
|
||||
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<Dialog>) };
|
||||
|
||||
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<Dialog>) };
|
||||
|
||||
let dialog = &dialogs[index as usize];
|
||||
if let Some(msg) = dialog.last_message.as_ref() {
|
||||
if msg.outgoing() {
|
||||
match &dialog.dialog {
|
||||
},
|
||||
text: m.text().to_string(),
|
||||
date: m.date().into(),
|
||||
ack: if m.outgoing() {
|
||||
match &d.dialog {
|
||||
tl::enums::Dialog::Dialog(d) => {
|
||||
if msg.id() <= d.read_inbox_max_id {
|
||||
if m.id() <= d.read_inbox_max_id {
|
||||
MessageAck::Seen
|
||||
} else {
|
||||
MessageAck::Sent
|
||||
|
@ -343,24 +309,19 @@ pub fn dialogAck(dialogsPtr: u64, index: u32) -> MessageAck {
|
|||
}
|
||||
} else {
|
||||
MessageAck::Received
|
||||
}
|
||||
} else {
|
||||
MessageAck::Received
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dialogPin(dialogsPtr: u64, index: u32) -> u32 {
|
||||
let dialogs = unsafe { &mut *(dialogsPtr as *mut Vec<Dialog>) };
|
||||
|
||||
let pinned = match &dialogs[index as usize].dialog {
|
||||
},
|
||||
}),
|
||||
pinned: match d.dialog {
|
||||
tl::enums::Dialog::Dialog(d) => d.pinned,
|
||||
tl::enums::Dialog::Folder(f) => f.pinned,
|
||||
};
|
||||
pinned as u32
|
||||
},
|
||||
})
|
||||
.collect(),
|
||||
Err(e) => {
|
||||
error!("Failed to get dialogs: {}", e);
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn freeDialogs(dialogsPtr: u64) {
|
||||
let _ = unsafe { Box::from_raw(dialogsPtr as *mut Vec<Dialog>) };
|
||||
}
|
||||
|
||||
pub fn sendMessage(packed: String, text: String) {
|
||||
|
|
|
@ -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<Dialog> getDialogs();
|
||||
void sendMessage(string packed, string text);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue