| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- use cursive::{views::TextArea, Cursive};
- use utils::{hash::Hashable as _, serialize::Serialize as _};
- use crate::{get_appdata, message::Message, ui, Appdata};
- // TODO (low): Create proper user objects. Related: add a way to verify a user.
- pub fn on_user_click(siv: &mut Cursive, user: &str) {
- let language = get_appdata(siv).language;
- ui::alert(siv, ui::Labels::User.localize(language), user.into());
- }
- pub fn on_message_click(siv: &mut Cursive, message_id: &str) {
- let appdata = get_appdata(siv);
- let message = appdata.messages.get(message_id);
- if let Some(message) = message {
- ui::alert(
- siv,
- ui::Labels::Message.localize(appdata.language),
- format!(
- "Time: {}\nChannel: {}\nSender: {}\nContent: {}",
- message.time, message.channel, message.sender, message.content
- ),
- );
- }
- }
- pub fn on_input_submit(siv: &mut Cursive, input_field_id: &str) {
- let text = siv
- .call_on_name(input_field_id, |view: &mut TextArea| {
- view.get_content().to_string()
- })
- .expect("Failed to retrieve input field content.");
- let appdata = get_appdata(siv);
- let language = appdata.language;
- let channel = appdata.current_channel;
- let message = Message::new(&appdata.username, &text, &channel);
- if message.is_valid() {
- // NOTE:
- // If an error was shown during send, it's likely that loading will fail too
- // so we don't need to show it again
- let mut error_dialogue_shown = false;
- match send_message(siv, message) {
- Ok(_) => clear_input_field(siv),
- Err(e) => {
- error_dialogue_shown = true;
- ui::error(siv, ui::Labels::FailedToSendMessage(e).localize(language))
- }
- };
- let res = load_messages(siv);
- if let Err(e) = res {
- if !error_dialogue_shown {
- ui::error(siv, ui::Labels::FailedToLoadMessages(e).localize(language));
- }
- }
- } else if !text.is_empty() {
- // Invalid message
- ui::error(siv, ui::Labels::InvalidMessage.localize(language));
- }
- ui::visual_update(siv);
- }
- pub fn clear_input_field(siv: &mut Cursive) {
- siv.call_on_name(ui::INPUT_FIELD_ID, |view: &mut TextArea| {
- view.set_content("");
- })
- .expect("Failed to clear input field.");
- }
- type StatusCode = u16;
- pub enum NetworkError {
- #[allow(dead_code)]
- ReqwestError(reqwest::Error),
- StatusCodeError(StatusCode),
- InvalidUrl,
- }
- fn fix_url(url: &str) -> Result<String, NetworkError> {
- if url.is_empty() {
- return Err(NetworkError::InvalidUrl);
- }
- let mut url = url.to_string();
- if !url.starts_with("http://") && !url.starts_with("https://") {
- url = format!("http://{}", url);
- }
- if !url.ends_with('/') {
- url.push('/');
- }
- Ok(url)
- }
- pub fn send_message(siv: &mut Cursive, message: Message) -> Result<(), NetworkError> {
- let url = fix_url(&get_appdata(siv).api_endpoint)?;
- let str = utils::binary::bin2hex(message.serialize_checked());
- let resp = reqwest::blocking::Client::new()
- .post(format!("{}", url))
- .body(str)
- .send()
- .map_err(|e| NetworkError::ReqwestError(e))?;
- if resp.status().is_success() {
- Ok(())
- } else {
- Err(NetworkError::StatusCodeError(resp.status().as_u16()))
- }
- }
- pub fn load_messages(siv: &mut Cursive) -> Result<(), NetworkError> {
- let appdata = get_appdata(siv);
- let url = fix_url(&appdata.api_endpoint)?;
- let resp = reqwest::blocking::Client::new()
- .get(url)
- .send()
- .map_err(|e| NetworkError::ReqwestError(e))?;
- if resp.status() != reqwest::StatusCode::OK {
- return Err(NetworkError::StatusCodeError(resp.status().as_u16()));
- }
- let bytes = resp.bytes().map_err(|e| NetworkError::ReqwestError(e))?;
- let contents = String::from_utf8_lossy(&bytes);
- let mut messages = vec![];
- for message_ser_hex in contents.split(",") {
- let Some(message_ser_bin) = utils::binary::hex2bin(message_ser_hex) else {
- continue;
- };
- let Ok(message) = Message::deserialize_checked(message_ser_bin) else {
- continue;
- };
- if message.is_valid() {
- messages.push(message);
- }
- }
- siv.with_user_data(|appdata: &mut Appdata| {
- for message in messages {
- appdata.messages.insert(message.hash().to_string(), message);
- }
- });
- Ok(())
- }
|