forked from Lonami/Talaria
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
|
package dev.lonami.talaria.data
|
||||||
|
|
||||||
import dev.lonami.talaria.models.Dialog
|
import uniffi.talaria.Dialog
|
||||||
import dev.lonami.talaria.models.MessagePreview
|
import uniffi.talaria.MessageAck
|
||||||
import uniffi.talaria.*
|
import uniffi.talaria.MessagePreview
|
||||||
import java.time.LocalDateTime
|
import uniffi.talaria.getDialogs
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.Instant
|
||||||
|
|
||||||
interface DialogRepository {
|
interface DialogRepository {
|
||||||
fun loadDialogs(): List<Dialog>
|
fun loadDialogs(): List<Dialog>
|
||||||
|
@ -12,34 +12,7 @@ interface DialogRepository {
|
||||||
|
|
||||||
class NativeDialogRepository : DialogRepository {
|
class NativeDialogRepository : DialogRepository {
|
||||||
override fun loadDialogs(): List<Dialog> {
|
override fun loadDialogs(): List<Dialog> {
|
||||||
val dialogs = mutableListOf<Dialog>()
|
return getDialogs()
|
||||||
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +38,7 @@ class MockDialogRepository : DialogRepository {
|
||||||
} else {
|
} else {
|
||||||
"Sample Message $i"
|
"Sample Message $i"
|
||||||
},
|
},
|
||||||
date = LocalDateTime.now(),
|
date = Instant.now(),
|
||||||
ack = when (i % 3) {
|
ack = when (i % 3) {
|
||||||
0 -> MessageAck.RECEIVED
|
0 -> MessageAck.RECEIVED
|
||||||
1 -> MessageAck.SENT
|
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 androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import dev.lonami.talaria.R
|
import dev.lonami.talaria.R
|
||||||
import dev.lonami.talaria.data.MockDialogRepository
|
import dev.lonami.talaria.data.MockDialogRepository
|
||||||
import dev.lonami.talaria.models.Dialog
|
|
||||||
import dev.lonami.talaria.ui.state.DialogViewModel
|
import dev.lonami.talaria.ui.state.DialogViewModel
|
||||||
import dev.lonami.talaria.ui.theme.TalariaTheme
|
import dev.lonami.talaria.ui.theme.TalariaTheme
|
||||||
|
import uniffi.talaria.Dialog
|
||||||
import uniffi.talaria.MessageAck
|
import uniffi.talaria.MessageAck
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
import java.time.ZoneOffset
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
import java.time.format.FormatStyle
|
import java.time.format.FormatStyle
|
||||||
|
|
||||||
|
@ -54,8 +56,8 @@ fun Dialog(dialog: Dialog, onDialogSelected: () -> Unit, modifier: Modifier = Mo
|
||||||
Text(
|
Text(
|
||||||
stringResource(
|
stringResource(
|
||||||
R.string.message_preview,
|
R.string.message_preview,
|
||||||
dialog.lastMessage.sender,
|
dialog.lastMessage!!.sender,
|
||||||
dialog.lastMessage.text
|
dialog.lastMessage!!.text
|
||||||
),
|
),
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
@ -65,7 +67,7 @@ fun Dialog(dialog: Dialog, onDialogSelected: () -> Unit, modifier: Modifier = Mo
|
||||||
Column {
|
Column {
|
||||||
if (dialog.lastMessage != null) {
|
if (dialog.lastMessage != null) {
|
||||||
Row {
|
Row {
|
||||||
when (dialog.lastMessage.ack) {
|
when (dialog.lastMessage!!.ack) {
|
||||||
MessageAck.RECEIVED -> {}
|
MessageAck.RECEIVED -> {}
|
||||||
MessageAck.SENT -> Icon(
|
MessageAck.SENT -> Icon(
|
||||||
painterResource(R.drawable.sent),
|
painterResource(R.drawable.sent),
|
||||||
|
@ -78,7 +80,7 @@ fun Dialog(dialog: Dialog, onDialogSelected: () -> Unit, modifier: Modifier = Mo
|
||||||
}
|
}
|
||||||
Spacer(Modifier.width(8.dp))
|
Spacer(Modifier.width(8.dp))
|
||||||
Text(
|
Text(
|
||||||
dialog.lastMessage.date.format(
|
LocalDateTime.ofInstant(dialog.lastMessage!!.date, ZoneOffset.UTC).format(
|
||||||
DateTimeFormatter.ofLocalizedTime(
|
DateTimeFormatter.ofLocalizedTime(
|
||||||
FormatStyle.SHORT
|
FormatStyle.SHORT
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
package dev.lonami.talaria.ui.state
|
package dev.lonami.talaria.ui.state
|
||||||
|
|
||||||
import dev.lonami.talaria.models.Dialog
|
import uniffi.talaria.Dialog
|
||||||
|
|
||||||
data class DialogUiState(val dialogs: List<Dialog> = listOf())
|
data class DialogUiState(val dialogs: List<Dialog> = listOf())
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
mod db;
|
mod db;
|
||||||
|
|
||||||
use grammers_client::types::{Dialog, LoginToken};
|
use grammers_client::types::{Dialog as OgDialog, LoginToken};
|
||||||
use grammers_client::{Client, Config, InitParams};
|
use grammers_client::{Client, Config, InitParams};
|
||||||
use grammers_session::{PackedChat, Session, UpdateState};
|
use grammers_session::{PackedChat, Session, UpdateState};
|
||||||
use grammers_tl_types as tl;
|
use grammers_tl_types as tl;
|
||||||
|
@ -15,6 +15,7 @@ use std::future::Future;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::net::{Ipv4Addr, Ipv6Addr};
|
use std::net::{Ipv4Addr, Ipv6Addr};
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
use std::time::SystemTime;
|
||||||
use tokio::runtime;
|
use tokio::runtime;
|
||||||
use tokio::runtime::Runtime;
|
use tokio::runtime::Runtime;
|
||||||
|
|
||||||
|
@ -52,6 +53,22 @@ pub enum MessageAck {
|
||||||
Sent,
|
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 {
|
fn block_on<F: Future>(future: F) -> F::Output {
|
||||||
if RUNTIME.get().is_none() {
|
if RUNTIME.get().is_none() {
|
||||||
RUNTIME
|
RUNTIME
|
||||||
|
@ -199,7 +216,7 @@ async fn sign_in(token: LoginToken, code: &str) -> Result<()> {
|
||||||
Ok(())
|
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 client = CLIENT.get().ok_or("Client not initialized")?;
|
||||||
|
|
||||||
let mut result = Vec::new();
|
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()) {
|
match block_on(get_dialogs()) {
|
||||||
Ok(dialogs) => Box::into_raw(Box::new(dialogs)) as u64,
|
Ok(dialogs) => dialogs
|
||||||
Err(e) => {
|
.into_iter()
|
||||||
error!("Failed to get dialogs: {}", e);
|
.map(|d| Dialog {
|
||||||
0 as u64
|
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() {
|
||||||
|
|
||||||
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() {
|
|
||||||
sender.name().to_string()
|
sender.name().to_string()
|
||||||
} else {
|
} else {
|
||||||
"unknown".to_string()
|
"unknown".to_string()
|
||||||
}
|
},
|
||||||
} else {
|
text: m.text().to_string(),
|
||||||
String::new()
|
date: m.date().into(),
|
||||||
}
|
ack: if m.outgoing() {
|
||||||
}
|
match &d.dialog {
|
||||||
|
|
||||||
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 {
|
|
||||||
tl::enums::Dialog::Dialog(d) => {
|
tl::enums::Dialog::Dialog(d) => {
|
||||||
if msg.id() <= d.read_inbox_max_id {
|
if m.id() <= d.read_inbox_max_id {
|
||||||
MessageAck::Seen
|
MessageAck::Seen
|
||||||
} else {
|
} else {
|
||||||
MessageAck::Sent
|
MessageAck::Sent
|
||||||
|
@ -343,24 +309,19 @@ pub fn dialogAck(dialogsPtr: u64, index: u32) -> MessageAck {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
MessageAck::Received
|
MessageAck::Received
|
||||||
}
|
},
|
||||||
} else {
|
}),
|
||||||
MessageAck::Received
|
pinned: match d.dialog {
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
|
||||||
tl::enums::Dialog::Dialog(d) => d.pinned,
|
tl::enums::Dialog::Dialog(d) => d.pinned,
|
||||||
tl::enums::Dialog::Folder(f) => f.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) {
|
pub fn sendMessage(packed: String, text: String) {
|
||||||
|
|
|
@ -4,21 +4,26 @@ enum MessageAck {
|
||||||
"Sent",
|
"Sent",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
dictionary MessagePreview {
|
||||||
|
string sender;
|
||||||
|
string text;
|
||||||
|
timestamp date;
|
||||||
|
MessageAck ack;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary Dialog {
|
||||||
|
string id;
|
||||||
|
string title;
|
||||||
|
MessagePreview? lastMessage;
|
||||||
|
boolean pinned;
|
||||||
|
};
|
||||||
|
|
||||||
namespace talaria {
|
namespace talaria {
|
||||||
void initDatabase(string path);
|
void initDatabase(string path);
|
||||||
void initClient();
|
void initClient();
|
||||||
boolean needLogin();
|
boolean needLogin();
|
||||||
u64 requestLoginCode(string phone);
|
u64 requestLoginCode(string phone);
|
||||||
void signIn(u64 tokenPtr, string code);
|
void signIn(u64 tokenPtr, string code);
|
||||||
u64 getDialogs();
|
sequence<Dialog> 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);
|
|
||||||
void sendMessage(string packed, string text);
|
void sendMessage(string packed, string text);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue