Use UDL interface to avoid passing around pointers

This commit is contained in:
Lonami Exo 2022-10-27 20:12:41 +02:00
parent 912949a079
commit 43421f6e54
3 changed files with 76 additions and 55 deletions

View File

@ -19,8 +19,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import dev.lonami.talaria.R import dev.lonami.talaria.R
import dev.lonami.talaria.ui.theme.TalariaTheme import dev.lonami.talaria.ui.theme.TalariaTheme
import uniffi.talaria.requestLoginCode import uniffi.talaria.LoginProcedure
import uniffi.talaria.signIn
enum class LoginStage { enum class LoginStage {
ASK_PHONE, ASK_PHONE,
@ -106,7 +105,7 @@ fun LoginScreen(onConfirmOtp: () -> Unit, modifier: Modifier = Modifier) {
var phone by remember { mutableStateOf("") } var phone by remember { mutableStateOf("") }
var otp by remember { mutableStateOf("") } var otp by remember { mutableStateOf("") }
var tokenPtr by remember { mutableStateOf(0UL) } val loginProcedure by remember { mutableStateOf(LoginProcedure()) }
Column( Column(
modifier = modifier modifier = modifier
@ -128,7 +127,7 @@ fun LoginScreen(onConfirmOtp: () -> Unit, modifier: Modifier = Modifier) {
phone, phone,
onPhoneChanged = { phone = it }, onPhoneChanged = { phone = it },
onSendCode = { onSendCode = {
tokenPtr = requestLoginCode(phone) loginProcedure.requestLoginCode(phone)
stage = LoginStage.ASK_CODE stage = LoginStage.ASK_CODE
} }
) )
@ -136,7 +135,7 @@ fun LoginScreen(onConfirmOtp: () -> Unit, modifier: Modifier = Modifier) {
otp, otp,
onOtpChanged = { otp = it }, onOtpChanged = { otp = it },
onConfirmOtp = { onConfirmOtp = {
signIn(tokenPtr, otp) loginProcedure.signIn(otp)
onConfirmOtp() onConfirmOtp()
} }
) )

View File

@ -64,6 +64,10 @@ impl fmt::Display for NativeError {
impl std::error::Error for NativeError {} impl std::error::Error for NativeError {}
struct LoginProcedure {
token: Mutex<Option<LoginToken>>,
}
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum MessageAck { pub enum MessageAck {
Received, Received,
@ -199,61 +203,75 @@ pub fn need_login() -> Result<bool> {
block_on(client.is_authorized()).map_err(|_| NativeError::Network) block_on(client.is_authorized()).map_err(|_| NativeError::Network)
} }
pub fn request_login_code(phone: String) -> Result<u64> { impl LoginProcedure {
let client = CLIENT.get().ok_or(NativeError::Initialization)?; fn new() -> Self {
block_on(client.request_login_code(&phone, API_ID, API_HASH)) Self {
.map(|token| Box::into_raw(Box::new(token)) as u64) token: Mutex::new(None),
.map_err(|_| NativeError::Network)
}
pub fn sign_in(token_ptr: u64, code: String) -> Result<()> {
let token = unsafe { *Box::from_raw(token_ptr as *mut LoginToken) };
let client = CLIENT.get().ok_or(NativeError::Initialization)?;
block_on(client.sign_in(&token, &code)).map_err(|_| NativeError::Network)?;
let guard = DATABASE.lock().unwrap();
let conn = match guard.as_ref() {
Some(c) => c,
None => {
error!("Database was not initialized");
return Err(NativeError::Initialization);
} }
};
let mut session = db::create_session(conn).map_err(|_| NativeError::Database)?;
let s = client.session();
if let Some(user) = s.get_user() {
session.user_id = Some(user.id);
session.dc_id = Some(user.dc);
session.bot = Some(user.bot);
} }
if let Some(state) = s.get_state() { fn request_login_code(&self, phone: String) -> Result<()> {
session.pts = Some(state.pts); let client = CLIENT.get().ok_or(NativeError::Initialization)?;
session.qts = Some(state.qts); let token = block_on(client.request_login_code(&phone, API_ID, API_HASH))
session.seq = Some(state.seq); .map_err(|_| NativeError::Network)?;
session.date = Some(state.date); *self.token.lock().unwrap() = Some(token);
Ok(())
} }
if let Some(dc_id) = session.dc_id { fn sign_in(&self, code: String) -> Result<()> {
for dc in s.get_dcs() { let token = self
if dc.id == dc_id { .token
if let Some(ipv4) = dc.ipv4 { .lock()
session.dc_addr = Some(Ipv4Addr::from(ipv4.to_le_bytes()).to_string()) .unwrap()
} else if let Some(ipv6) = dc.ipv6 { .take()
session.dc_addr = Some(Ipv6Addr::from(ipv6).to_string()) .ok_or(NativeError::Initialization)?;
let client = CLIENT.get().ok_or(NativeError::Initialization)?;
block_on(client.sign_in(&token, &code)).map_err(|_| NativeError::Network)?;
let guard = DATABASE.lock().unwrap();
let conn = match guard.as_ref() {
Some(c) => c,
None => {
error!("Database was not initialized");
return Err(NativeError::Initialization);
}
};
let mut session = db::create_session(conn).map_err(|_| NativeError::Database)?;
let s = client.session();
if let Some(user) = s.get_user() {
session.user_id = Some(user.id);
session.dc_id = Some(user.dc);
session.bot = Some(user.bot);
}
if let Some(state) = s.get_state() {
session.pts = Some(state.pts);
session.qts = Some(state.qts);
session.seq = Some(state.seq);
session.date = Some(state.date);
}
if let Some(dc_id) = session.dc_id {
for dc in s.get_dcs() {
if dc.id == dc_id {
if let Some(ipv4) = dc.ipv4 {
session.dc_addr = Some(Ipv4Addr::from(ipv4.to_le_bytes()).to_string())
} else if let Some(ipv6) = dc.ipv6 {
session.dc_addr = Some(Ipv6Addr::from(ipv6).to_string())
}
session.dc_port = Some(dc.port as u16);
session.dc_auth = dc.auth.map(|b| b.try_into().unwrap());
break;
} }
session.dc_port = Some(dc.port as u16);
session.dc_auth = dc.auth.map(|b| b.try_into().unwrap());
break;
} }
} }
db::update_session(conn, &session).map_err(|_| NativeError::Database)?;
Ok(())
} }
db::update_session(conn, &session).map_err(|_| NativeError::Database)?;
Ok(())
} }
pub fn get_dialogs() -> Result<Vec<Dialog>> { pub fn get_dialogs() -> Result<Vec<Dialog>> {

View File

@ -25,6 +25,14 @@ dictionary Dialog {
boolean pinned; boolean pinned;
}; };
interface LoginProcedure {
constructor();
[Throws=NativeError]
void request_login_code(string phone);
[Throws=NativeError]
void sign_in(string code);
};
namespace talaria { namespace talaria {
[Throws=NativeError] [Throws=NativeError]
void init_database(string path); void init_database(string path);
@ -33,10 +41,6 @@ namespace talaria {
[Throws=NativeError] [Throws=NativeError]
boolean need_login(); boolean need_login();
[Throws=NativeError] [Throws=NativeError]
u64 request_login_code(string phone);
[Throws=NativeError]
void sign_in(u64 tokenPtr, string code);
[Throws=NativeError]
sequence<Dialog> get_dialogs(); sequence<Dialog> get_dialogs();
[Throws=NativeError] [Throws=NativeError]
void send_message(string packed, string text); void send_message(string packed, string text);