mirror of
https://github.com/saymrwulf/xous-core.git
synced 2026-11-04 04:27:34 +00:00
remove logic from status primitive and make the interface simpler
- status bar text is just status bar text now - idle animation runs/stops based on an explicit run/stop message Note that at the moment if one starts the busy bar and a modal pops up, you might overflow the queue of the ui drawing thread with animation requests, because the thread blocks when the modal is summoned. Modals "take the screen" anyways, so maybe the solution to this is to add an additional interlock around any modal calls within the UI main thread. Need to think about it a bit more.
This commit is contained in:
parent
d844c4306c
commit
4e027b676c
6 changed files with 68 additions and 75 deletions
|
|
@ -18,6 +18,10 @@
|
|||
"ja": "WARNING: clock not set *EN*",
|
||||
"zh": "WARNING: clock not set *EN*"
|
||||
},
|
||||
"mtxchat.status.default" : {
|
||||
"en": "Use ← for login menu",
|
||||
"en-tts": "Use ← for login menu"
|
||||
},
|
||||
"mtxchat.filter.failed": {
|
||||
"en": "error: could not create filter",
|
||||
"en-tts": "error: could not create filter",
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ pub struct MtxChat<'a> {
|
|||
modals: Modals,
|
||||
new_username: bool,
|
||||
new_room: bool,
|
||||
status: String,
|
||||
}
|
||||
impl<'a> MtxChat<'a> {
|
||||
pub fn new(chat: &Chat) -> MtxChat {
|
||||
|
|
@ -91,6 +92,8 @@ impl<'a> MtxChat<'a> {
|
|||
let trng = Trng::new(&xns).unwrap();
|
||||
let pddb = pddb::Pddb::new();
|
||||
pddb.try_mount();
|
||||
let status = t!("mtxchat.status.default", locales::LANG).to_owned();
|
||||
chat.set_status_text(&status);
|
||||
MtxChat {
|
||||
chat: chat,
|
||||
trng: trng,
|
||||
|
|
@ -113,6 +116,7 @@ impl<'a> MtxChat<'a> {
|
|||
modals: modals,
|
||||
new_username: false,
|
||||
new_room: false,
|
||||
status,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -241,7 +245,6 @@ impl<'a> MtxChat<'a> {
|
|||
|
||||
pub fn connect(&mut self) -> bool {
|
||||
log::info!("Attempting connect to Matrix server");
|
||||
self.chat.set_busy_state(Some(t!("mtxchat.busy.connecting", locales::LANG).to_owned())).expect("couldn't set busy state");
|
||||
if self.wifi() {
|
||||
if self.login() {
|
||||
if let Some(_room_id) = self.get_room_id() {
|
||||
|
|
@ -253,7 +256,6 @@ impl<'a> MtxChat<'a> {
|
|||
.show_notification(t!("mtxchat.listen.patience", locales::LANG), None)
|
||||
.expect("notification failed");
|
||||
}
|
||||
self.chat.set_busy_state(None).expect("couldn't clear busy state");
|
||||
return true;
|
||||
} else {
|
||||
self.modals
|
||||
|
|
@ -275,11 +277,12 @@ impl<'a> MtxChat<'a> {
|
|||
.expect("notification failed");
|
||||
}
|
||||
self.dialogue_set(None);
|
||||
self.chat.set_busy_state(None).expect("couldn't clear busy state");
|
||||
false
|
||||
}
|
||||
|
||||
pub fn login(&mut self) -> bool {
|
||||
self.chat.set_status_text(t!("mtxchat.busy.connecting", locales::LANG));
|
||||
self.chat.set_busy_state(true);
|
||||
self.token = self.get(TOKEN_KEY).unwrap_or(None);
|
||||
self.logged_in = false;
|
||||
|
||||
|
|
@ -338,6 +341,8 @@ impl<'a> MtxChat<'a> {
|
|||
self.unset(USER_DOMAIN_KEY)
|
||||
.expect("failed to unset user domain");
|
||||
}
|
||||
self.chat.set_status_text(&self.status);
|
||||
self.chat.set_busy_state(false);
|
||||
self.logged_in
|
||||
}
|
||||
|
||||
|
|
@ -629,7 +634,8 @@ impl<'a> MtxChat<'a> {
|
|||
&self.room_id,
|
||||
) {
|
||||
(true, Some(token), Some(user_domain), Some(room_id)) => {
|
||||
self.chat.set_busy_state(Some(t!("mtxchat.busy.sending", locales::LANG).to_owned())).expect("couldn't set busy state");
|
||||
self.chat.set_status_text(t!("mtxchat.busy.sending", locales::LANG));
|
||||
self.chat.set_busy_state(true);
|
||||
log::info!("txn_id = {}", txn_id);
|
||||
let mut url = Url::parse("https://matrix.org").unwrap();
|
||||
url.set_host(Some(user_domain)).expect("failed to set host");
|
||||
|
|
@ -638,7 +644,8 @@ impl<'a> MtxChat<'a> {
|
|||
} else {
|
||||
"FAILED TO SEND"
|
||||
};
|
||||
self.chat.set_busy_state(None).expect("couldn't clear busy state");
|
||||
self.chat.set_status_text(&self.status);
|
||||
self.chat.set_busy_state(false);
|
||||
r
|
||||
}
|
||||
(false, _, _, _) => "Not logged in",
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@
|
|||
"en-tts": "no dialogues available to read"
|
||||
},
|
||||
"chat.status.initial" : {
|
||||
"en": "use ← for login menu",
|
||||
"en-tts": "use ← for login menu"
|
||||
"en": "Idle",
|
||||
"en-tts": "Idle"
|
||||
},
|
||||
"chat.help.navigation": {
|
||||
"en": "use ↑ & ↓ to scroll thru old posts\nuse ← & → to show menus\nF1-F4 dont do anything yet.",
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@ pub enum ChatOp {
|
|||
/// Find a Post by timestamp and Author
|
||||
PostFind,
|
||||
PostFlag,
|
||||
/// Set status bar text
|
||||
SetStatusText,
|
||||
/// Run or stop the busy animation.
|
||||
SetBusyAnimationState,
|
||||
/// Update just the state of the busy animation, if any. Internal opcode.
|
||||
|
|
@ -133,8 +135,5 @@ pub enum AuthorFlag {
|
|||
|
||||
#[derive(Archive, Serialize, Deserialize, Debug)]
|
||||
pub struct BusyMessage {
|
||||
/// If None, restores the last non-busy status bar message, and stops the animation.
|
||||
/// If Some, updates the status bar to contain the busy message and
|
||||
/// starts the animation running.
|
||||
pub busy_msg: Option<xous_ipc::String<128>>,
|
||||
pub busy_msg: xous_ipc::String<128>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use std::thread;
|
|||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use std::sync::{Arc, atomic::AtomicBool, atomic::Ordering};
|
||||
|
||||
use xous::{Error, CID, SID};
|
||||
use xous::{Error, CID, SID, msg_scalar_unpack};
|
||||
use xous_ipc::Buffer;
|
||||
|
||||
pub struct Chat {
|
||||
|
|
@ -239,32 +239,31 @@ impl Chat {
|
|||
.expect("failed to Redraw Chat UI");
|
||||
}
|
||||
|
||||
/// Run or stop the busy/waiting animation.
|
||||
/// Set the status bar text.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// `msg` - If `Some()`, updates the status bar to show the `msg` and start the animation running
|
||||
/// If `None`, restores the last status message before being busy and stops the animation.
|
||||
pub fn set_busy_state(&self, msg: Option<String>) -> Result<(), Error> {
|
||||
/// `msg` - the text to show
|
||||
///
|
||||
/// This method implements the latest recommendation of panicing on internal errors.
|
||||
pub fn set_status_text(&self, msg: &str) {
|
||||
let bm = BusyMessage {
|
||||
busy_msg: match msg {
|
||||
None => None,
|
||||
Some(m) => {
|
||||
Some(
|
||||
xous_ipc::String::from_str(&m)
|
||||
)
|
||||
}
|
||||
}
|
||||
busy_msg: xous_ipc::String::from_str(msg)
|
||||
};
|
||||
match Buffer::into_buf(bm) {
|
||||
Ok(buf) => match buf.send(self.cid, ChatOp::SetBusyAnimationState as u32) {
|
||||
Ok(..) => {
|
||||
Ok(())
|
||||
}
|
||||
Err(_) => Err(xous::Error::InternalError),
|
||||
},
|
||||
Err(_) => Err(xous::Error::InternalError),
|
||||
}
|
||||
Buffer::into_buf(bm).expect("internal error").send(
|
||||
self.cid, ChatOp::SetStatusText as u32
|
||||
).expect("internal error");
|
||||
}
|
||||
|
||||
pub fn set_busy_state(&self, run: bool) {
|
||||
xous::send_message(
|
||||
self.cid,
|
||||
xous::Message::new_scalar(ChatOp::SetBusyAnimationState as usize,
|
||||
if run { 1 } else { 0 },
|
||||
0, 0, 0),
|
||||
)
|
||||
.map(|_| ())
|
||||
.expect("internal error");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -299,6 +298,7 @@ pub fn busy_animator(
|
|||
ChatOp::UpdateBusy as usize, 0, 0, 0, 0)
|
||||
).ok();
|
||||
tt.sleep_ms(crate::BUSY_ANIMATION_RATE_MS).unwrap();
|
||||
log::info!("busy!");
|
||||
xous::try_send_message(busy_bumper_cid,
|
||||
xous::Message::new_scalar(
|
||||
BusyAnimOp::Pump as usize, 0, 0, 0, 0)
|
||||
|
|
@ -346,37 +346,32 @@ pub fn server(
|
|||
loop {
|
||||
let msg = xous::receive_message(sid).unwrap();
|
||||
log::debug!("got message {:?}", msg);
|
||||
if ui.is_busy() {
|
||||
if !run_busy_animation.swap(true, Ordering::SeqCst) {
|
||||
// only send off the Pump request on the transition from false->true; this causes the machine to run
|
||||
xous::try_send_message(busy_bumper_cid,
|
||||
xous::Message::new_scalar(
|
||||
BusyAnimOp::Pump as usize, 0, 0, 0, 0)
|
||||
).ok();
|
||||
}
|
||||
} else {
|
||||
// make sure the animation stops running. Not sure if this is the most efficient way to handle this,
|
||||
// but I think an atomic bool set is just a couple dozen CPU cycles...?
|
||||
run_busy_animation.store(false, Ordering::SeqCst);
|
||||
}
|
||||
match FromPrimitive::from_usize(msg.body.id()) {
|
||||
Some(ChatOp::UpdateBusy) => {
|
||||
ui.redraw_busy().expect("CHAT couldn't redraw");
|
||||
}
|
||||
Some(ChatOp::SetBusyAnimationState) => {
|
||||
Some(ChatOp::SetStatusText) => {
|
||||
let buffer = unsafe {
|
||||
Buffer::from_memory_message(msg.body.memory_message().unwrap())
|
||||
};
|
||||
let s = buffer.to_original::<BusyMessage, _>().unwrap();
|
||||
match s.busy_msg {
|
||||
Some(msg) => {
|
||||
ui.set_busy(msg.as_str().unwrap());
|
||||
}
|
||||
None => {
|
||||
ui.clear_busy();
|
||||
}
|
||||
}
|
||||
ui.set_status_text(s.busy_msg.as_str().unwrap());
|
||||
}
|
||||
Some(ChatOp::SetBusyAnimationState) => msg_scalar_unpack!(msg, state, _, _, _, {
|
||||
if state != 0 {
|
||||
ui.set_busy_state(true);
|
||||
if !run_busy_animation.swap(true, Ordering::SeqCst) {
|
||||
// only send off the Pump request on the transition from false->true; this causes the machine to run
|
||||
xous::try_send_message(busy_bumper_cid,
|
||||
xous::Message::new_scalar(
|
||||
BusyAnimOp::Pump as usize, 0, 0, 0, 0)
|
||||
).ok();
|
||||
}
|
||||
} else {
|
||||
ui.set_busy_state(false);
|
||||
run_busy_animation.store(false, Ordering::SeqCst)
|
||||
}
|
||||
}),
|
||||
Some(ChatOp::DialogueSave) => {
|
||||
log::info!("ChatOp::DialogueSave");
|
||||
ui.dialogue_save().expect("failed to save Dialogue");
|
||||
|
|
|
|||
|
|
@ -64,8 +64,6 @@ pub(crate) struct Ui {
|
|||
status_tv: TextView,
|
||||
/// track the last time we update the status bar; use this avoid double-updating busy animations
|
||||
status_last_update_ms: u64,
|
||||
/// track the last non-busy message so we can restore it when the busy state stops
|
||||
status_last_msg: Option<String>,
|
||||
bubble_width: u16,
|
||||
margin: Point, // margin to edge of canvas
|
||||
bubble_margin: Point, // margin of text in bubbles
|
||||
|
|
@ -163,7 +161,6 @@ impl Ui {
|
|||
status_height,
|
||||
status_tv,
|
||||
status_last_update_ms,
|
||||
status_last_msg: None,
|
||||
post_selected: None,
|
||||
post_anchor: None,
|
||||
post_topdown: false,
|
||||
|
|
@ -642,16 +639,8 @@ impl Ui {
|
|||
self.status_tv.busy_animation_state.is_some()
|
||||
}
|
||||
|
||||
/// If not currently busy, save the current status bar message and kick off the animation.
|
||||
/// Updates the text of the status bar in all cases.
|
||||
pub(crate) fn set_busy(&mut self, msg: &str) {
|
||||
if self.status_tv.busy_animation_state.is_none() {
|
||||
// stash a copy of the last message that wasn't a busy message
|
||||
self.status_last_msg = Some(
|
||||
self.status_tv.to_str().to_owned()
|
||||
);
|
||||
self.status_tv.busy_animation_state = Some(0);
|
||||
}
|
||||
/// Set the status bar text
|
||||
pub(crate) fn set_status_text(&mut self, msg: &str) {
|
||||
self.status_tv.clear_str();
|
||||
write!(self.status_tv, "{}", msg).ok();
|
||||
xous::send_message(self.app_cid.unwrap(),
|
||||
|
|
@ -659,13 +648,12 @@ impl Ui {
|
|||
ChatOp::UpdateBusy as usize, 0, 0, 0, 0)
|
||||
).ok();
|
||||
}
|
||||
|
||||
/// Stops the busy animation state
|
||||
pub(crate) fn clear_busy(&mut self) {
|
||||
self.status_tv.busy_animation_state = None;
|
||||
if let Some(prev_msg) = self.status_last_msg.take() {
|
||||
self.status_tv.clear_str();
|
||||
write!(self.status_tv, "{}", prev_msg).ok();
|
||||
/// Sets the status bar to animate the busy animation
|
||||
pub(crate) fn set_busy_state(&mut self, run: bool) {
|
||||
if run {
|
||||
self.status_tv.busy_animation_state = Some(0); // the "glitch" to 0 is intentional, gives an indicator that a new op has started
|
||||
} else {
|
||||
self.status_tv.busy_animation_state = None;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue