working send + view messages

This commit is contained in:
Arkitu 2025-05-03 23:11:55 +02:00
parent c629ae5ce3
commit 82c86bba16

View File

@ -1,6 +1,8 @@
use core::fmt::Write; use core::fmt::Write;
use dhcparse::dhcpv4::MAX_MESSAGE_SIZE;
use embassy_sync::{blocking_mutex::raw::ThreadModeRawMutex, mutex::Mutex}; use embassy_sync::{blocking_mutex::raw::ThreadModeRawMutex, mutex::Mutex};
use heapless::{String, Vec}; use heapless::{String, Vec};
use log::info;
use percent_encoding::percent_decode_str; use percent_encoding::percent_decode_str;
use pico_website::unwrap; use pico_website::unwrap;
use ringbuffer::{ConstGenericRingBuffer, RingBuffer}; use ringbuffer::{ConstGenericRingBuffer, RingBuffer};
@ -44,7 +46,7 @@ impl App for ChatApp {
let (path, args) = path.split_once('?').unwrap_or((path, "")); let (path, args) = path.split_once('?').unwrap_or((path, ""));
let mut load = None; let mut load = None;
let mut username = None; let mut username = None;
// let mut msg_content = None; let mut msg_content = None;
for arg in args.split('&').chain(content.split('&')) { for arg in args.split('&').chain(content.split('&')) {
match arg.split_once('=') { match arg.split_once('=') {
Some(("load", n)) => { Some(("load", n)) => {
@ -57,49 +59,76 @@ impl App for ChatApp {
} }
} }
Some(("username", u)) => { Some(("username", u)) => {
if u.len() < USERNAME_MIN_SIZE || u.len() > USERNAME_SIZE { let mut name = String::<USERNAME_SIZE>::new();
for c in percent_decode_str(u) {
if let Err(_) = name.push(c as char) {
return (HttpResCode::BadRequest, "", &[]); return (HttpResCode::BadRequest, "", &[]);
} }
username = Some(u); }
if u.len() < USERNAME_MIN_SIZE {
return (HttpResCode::BadRequest, "", &[]);
}
username = Some(name);
} }
Some(("msg", m)) => { Some(("msg", m)) => {
let mut msg = String::<MSG_SIZE>::new(); let mut msg = String::<MSG_SIZE>::new();
for c in percent_decode_str(m) { for c in percent_decode_str(m) {
msg.push(c as char); if let Err(_) = msg.push(c as char) {
}
if m.len() > MSG_SIZE {
return (HttpResCode::BadRequest, "", &[]); return (HttpResCode::BadRequest, "", &[]);
} }
// msg_content = Some(); }
msg_content = Some(msg);
} }
_ => {} _ => {}
} }
} }
info!(
"load:{:?} | username:{:?} | msg:{:?}",
load, username, msg_content
);
if path == "/chat/connect" && username.is_some() { if path == "/chat/connect" && username.is_some() {
self.res_buf.clear(); self.res_buf.clear();
unwrap(write!( unwrap(write!(
&mut self.res_buf, &mut self.res_buf,
"<div \ "<input id=\"username\" style=\"display: none;\" name=\"username\" value=\"{}\">
<div id=\"messages\" >\
<div \
class=\"message\" \ class=\"message\" \
hx-get=\"/chat/message/abs/0?load={}&username={}\" \ hx-get=\"/chat/message/0?load={}\" \
hx-target=\"this\" \ hx-target=\"this\" \
hx-swap=\"outerHTML\" \ hx-swap=\"outerHTML\" \
hx-trigger=\"load\" \ hx-trigger=\"load\" \
></div>", ></div>\
</div>\
<input \
id=\"msg\" \
name=\"msg\" \
maxlength=\"{}\" \
hx-post=\"/chat/send\" \
hx-include=\"#username\" \
hx-target=\"#messages\" \
hx-swap=\"beforeend\"\
>",
username.unwrap(),
MEMORY_SIZE, MEMORY_SIZE,
username.unwrap() MAX_MESSAGE_SIZE
)) ))
.await; .await;
return (HttpResCode::Ok, "html", &self.res_buf); return (HttpResCode::Ok, "html", &self.res_buf);
} else if path == "/chat/send" && username.is_some() { } else if path == "/chat/send" && username.is_some() && msg_content.is_some() {
return (HttpResCode::Ok, "html", &self.res_buf); let mut msgs = MESSAGES.lock().await;
} else if path.starts_with("/chat/message/abs/") && path.len() > 18 { msgs.push(Message {
let msg_id: u16 = match path[18..].parse() { author: username.unwrap(),
content: msg_content.unwrap(),
});
return (HttpResCode::NoContent, "", &[]);
} else if path.starts_with("/chat/message/") && path.len() > 14 {
let msg_id: u16 = match path[14..].parse() {
Ok(n) => n, Ok(n) => n,
Err(_) => return (HttpResCode::BadRequest, "", &[]), Err(_) => return (HttpResCode::BadRequest, "", &[]),
}; };
let msgs = MESSAGES.lock().await; let msgs = MESSAGES.lock().await;
if msg_id >= msgs.next { if msg_id > msgs.next {
return (HttpResCode::BadRequest, "", &[]); return (HttpResCode::BadRequest, "", &[]);
} }
if msg_id < msgs.next.saturating_sub(MEMORY_SIZE as u16 + 1) { if msg_id < msgs.next.saturating_sub(MEMORY_SIZE as u16 + 1) {
@ -107,18 +136,37 @@ impl App for ChatApp {
} }
self.res_buf.clear(); self.res_buf.clear();
unwrap(write!(&mut self.res_buf, "<div class=\"message\"")).await; unwrap(write!(&mut self.res_buf, "<div class=\"message\"")).await;
if let Some(n) = load { if msg_id == msgs.next {
unwrap(write!(&mut self.res_buf, " style=\"display: none;\"")).await;
}
info!("msg_id:{} | next:{}", msg_id, msgs.next);
if msg_id == msgs.next {
info!("test1");
unwrap(write!( unwrap(write!(
&mut self.res_buf, &mut self.res_buf,
" hx-get=\"/chat/message/abs/{}?load={}\" \ " hx-get=\"/chat/message/{}?load={}\" \
hx-target=\"this\" \
hx-swap=\"outerHTML\" \
hx-trigger=\"every 100ms\"",
msg_id,
load.unwrap_or(0)
))
.await;
} else {
if let Some(n) = load {
info!("test2");
unwrap(write!(
&mut self.res_buf,
" hx-get=\"/chat/message/{}?load={}\" \
hx-target=\"this\" \ hx-target=\"this\" \
hx-swap=\"afterend\" \ hx-swap=\"afterend\" \
hx-trigger=\"load\"", hx-trigger=\"load\"",
msg_id + 1, msg_id + 1,
n - 1 n - 1,
)) ))
.await; .await;
} }
info!("test3");
let msg = match msgs.get_abs(msg_id) { let msg = match msgs.get_abs(msg_id) {
Some(msg) => msg, Some(msg) => msg,
None => return (HttpResCode::NoContent, "", &[]), None => return (HttpResCode::NoContent, "", &[]),
@ -129,6 +177,8 @@ impl App for ChatApp {
msg.author, msg.content msg.author, msg.content
)) ))
.await; .await;
};
return (HttpResCode::Ok, "html", &self.res_buf); return (HttpResCode::Ok, "html", &self.res_buf);
} else { } else {
(HttpResCode::NotFound, "", &[]) (HttpResCode::NotFound, "", &[])
@ -151,11 +201,15 @@ impl Messages {
const fn new() -> Self { const fn new() -> Self {
Self { Self {
inner: ConstGenericRingBuffer::new(), inner: ConstGenericRingBuffer::new(),
next: 2, next: 0,
} }
} }
fn get_abs(&self, id: u16) -> Option<&Message> { fn get_abs(&self, id: u16) -> Option<&Message> {
self.inner self.inner.get_signed((id as isize) - (self.next as isize))
.get_signed((id as isize) + 1 - (self.next as isize)) }
fn push(&mut self, msg: Message) {
info!("{}: {}", msg.author, msg.content);
self.inner.push(msg);
self.next += 1;
} }
} }