mirror of
https://github.com/youwen5/iamb.git
synced 2025-06-20 05:39:52 -07:00
Indicate when you're editing a message (#75)
This commit is contained in:
parent
cc1d2f3bf8
commit
4935899aed
3 changed files with 52 additions and 27 deletions
14
src/base.rs
14
src/base.rs
|
@ -103,7 +103,9 @@ pub enum VerifyAction {
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub enum MessageAction {
|
pub enum MessageAction {
|
||||||
/// Cance the current reply or edit.
|
/// Cance the current reply or edit.
|
||||||
Cancel,
|
///
|
||||||
|
/// The [bool] argument indicates whether to skip confirmation for clearing the message bar.
|
||||||
|
Cancel(bool),
|
||||||
|
|
||||||
/// Download an attachment to the given path.
|
/// Download an attachment to the given path.
|
||||||
///
|
///
|
||||||
|
@ -446,8 +448,12 @@ impl RoomInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_message_key(&self, event_id: &EventId) -> Option<&MessageKey> {
|
||||||
|
self.keys.get(event_id)?.to_message_key()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_event(&self, event_id: &EventId) -> Option<&Message> {
|
pub fn get_event(&self, event_id: &EventId) -> Option<&Message> {
|
||||||
self.messages.get(self.keys.get(event_id)?.to_message_key()?)
|
self.messages.get(self.get_message_key(event_id)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_reaction(&mut self, react: ReactionEvent) {
|
pub fn insert_reaction(&mut self, react: ReactionEvent) {
|
||||||
|
@ -489,10 +495,10 @@ impl RoomInfo {
|
||||||
|
|
||||||
match &mut msg.event {
|
match &mut msg.event {
|
||||||
MessageEvent::Original(orig) => {
|
MessageEvent::Original(orig) => {
|
||||||
orig.content = *new_content;
|
orig.content.msgtype = new_content.msgtype;
|
||||||
},
|
},
|
||||||
MessageEvent::Local(_, content) => {
|
MessageEvent::Local(_, content) => {
|
||||||
*content = new_content;
|
content.msgtype = new_content.msgtype;
|
||||||
},
|
},
|
||||||
MessageEvent::Redacted(_) |
|
MessageEvent::Redacted(_) |
|
||||||
MessageEvent::EncryptedOriginal(_) |
|
MessageEvent::EncryptedOriginal(_) |
|
||||||
|
|
|
@ -177,7 +177,7 @@ fn iamb_cancel(desc: CommandDescription, ctx: &mut ProgContext) -> ProgResult {
|
||||||
return Result::Err(CommandError::InvalidArgument);
|
return Result::Err(CommandError::InvalidArgument);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mact = IambAction::from(MessageAction::Cancel);
|
let mact = IambAction::from(MessageAction::Cancel(desc.bang));
|
||||||
let step = CommandStep::Continue(mact.into(), ctx.context.take());
|
let step = CommandStep::Continue(mact.into(), ctx.context.take());
|
||||||
|
|
||||||
return Ok(step);
|
return Ok(step);
|
||||||
|
|
|
@ -165,11 +165,20 @@ impl ChatState {
|
||||||
.ok_or(IambError::NoSelectedMessage)?;
|
.ok_or(IambError::NoSelectedMessage)?;
|
||||||
|
|
||||||
match act {
|
match act {
|
||||||
MessageAction::Cancel => {
|
MessageAction::Cancel(skip_confirm) => {
|
||||||
self.reply_to = None;
|
self.reply_to = None;
|
||||||
self.editing = None;
|
self.editing = None;
|
||||||
|
|
||||||
Ok(None)
|
if skip_confirm {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
let msg = "Would you like to clear the message bar?";
|
||||||
|
let act = PromptAction::Abort(false);
|
||||||
|
let prompt = PromptYesNo::new(msg, vec![Action::from(act)]);
|
||||||
|
let prompt = Box::new(prompt);
|
||||||
|
|
||||||
|
Err(UIError::NeedConfirm(prompt))
|
||||||
},
|
},
|
||||||
MessageAction::Download(filename, flags) => {
|
MessageAction::Download(filename, flags) => {
|
||||||
if let MessageEvent::Original(ev) = &msg.event {
|
if let MessageEvent::Original(ev) = &msg.event {
|
||||||
|
@ -286,6 +295,7 @@ impl ChatState {
|
||||||
};
|
};
|
||||||
|
|
||||||
self.tbox.set_text(text);
|
self.tbox.set_text(text);
|
||||||
|
self.reply_to = msg.reply_to().and_then(|id| info.get_message_key(&id)).cloned();
|
||||||
self.editing = self.scrollback.get_key(info);
|
self.editing = self.scrollback.get_key(info);
|
||||||
self.focus = RoomFocus::MessageBar;
|
self.focus = RoomFocus::MessageBar;
|
||||||
|
|
||||||
|
@ -742,10 +752,32 @@ impl<'a> StatefulWidget for Chat<'a> {
|
||||||
type State = ChatState;
|
type State = ChatState;
|
||||||
|
|
||||||
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
|
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
|
||||||
|
// Determine whether we have a description to show for the message bar.
|
||||||
|
let desc_spans = match (&state.editing, &state.reply_to) {
|
||||||
|
(None, None) => None,
|
||||||
|
(Some(_), None) => Some(Spans::from("Editing message")),
|
||||||
|
(editing, Some(_)) => {
|
||||||
|
state.reply_to.as_ref().and_then(|k| {
|
||||||
|
let room = self.store.application.rooms.get(state.id())?;
|
||||||
|
let msg = room.messages.get(k)?;
|
||||||
|
let user = self.store.application.settings.get_user_span(msg.sender.as_ref());
|
||||||
|
let prefix = if editing.is_some() {
|
||||||
|
Span::from("Editing reply to ")
|
||||||
|
} else {
|
||||||
|
Span::from("Replying to ")
|
||||||
|
};
|
||||||
|
let spans = Spans(vec![prefix, user]);
|
||||||
|
|
||||||
|
spans.into()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Determine the region to show each UI element.
|
||||||
let lines = state.tbox.has_lines(5).max(1) as u16;
|
let lines = state.tbox.has_lines(5).max(1) as u16;
|
||||||
let drawh = area.height;
|
let drawh = area.height;
|
||||||
let texth = lines.min(drawh).clamp(1, 5);
|
let texth = lines.min(drawh).clamp(1, 5);
|
||||||
let desch = if state.reply_to.is_some() {
|
let desch = if desc_spans.is_some() {
|
||||||
drawh.saturating_sub(texth).min(1)
|
drawh.saturating_sub(texth).min(1)
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
|
@ -756,25 +788,7 @@ impl<'a> StatefulWidget for Chat<'a> {
|
||||||
let descarea = Rect::new(area.x, scrollarea.y + scrollh, area.width, desch);
|
let descarea = Rect::new(area.x, scrollarea.y + scrollh, area.width, desch);
|
||||||
let textarea = Rect::new(area.x, descarea.y + desch, area.width, texth);
|
let textarea = Rect::new(area.x, descarea.y + desch, area.width, texth);
|
||||||
|
|
||||||
let scrollback_focused = state.focus.is_scrollback() && self.focused;
|
// Render the message bar and any description for it.
|
||||||
let scrollback = Scrollback::new(self.store).focus(scrollback_focused);
|
|
||||||
scrollback.render(scrollarea, buf, &mut state.scrollback);
|
|
||||||
|
|
||||||
let desc_spans = match (&state.editing, &state.reply_to) {
|
|
||||||
(None, None) => None,
|
|
||||||
(Some(_), _) => Some(Spans::from("Editing message")),
|
|
||||||
(_, Some(_)) => {
|
|
||||||
state.reply_to.as_ref().and_then(|k| {
|
|
||||||
let room = self.store.application.rooms.get(state.id())?;
|
|
||||||
let msg = room.messages.get(k)?;
|
|
||||||
let user = self.store.application.settings.get_user_span(msg.sender.as_ref());
|
|
||||||
let spans = Spans(vec![Span::from("Replying to "), user]);
|
|
||||||
|
|
||||||
spans.into()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(desc_spans) = desc_spans {
|
if let Some(desc_spans) = desc_spans {
|
||||||
Paragraph::new(desc_spans).render(descarea, buf);
|
Paragraph::new(desc_spans).render(descarea, buf);
|
||||||
}
|
}
|
||||||
|
@ -783,5 +797,10 @@ impl<'a> StatefulWidget for Chat<'a> {
|
||||||
|
|
||||||
let tbox = TextBox::new().prompt(prompt);
|
let tbox = TextBox::new().prompt(prompt);
|
||||||
tbox.render(textarea, buf, &mut state.tbox);
|
tbox.render(textarea, buf, &mut state.tbox);
|
||||||
|
|
||||||
|
// Render the message scrollback.
|
||||||
|
let scrollback_focused = state.focus.is_scrollback() && self.focused;
|
||||||
|
let scrollback = Scrollback::new(self.store).focus(scrollback_focused);
|
||||||
|
scrollback.render(scrollarea, buf, &mut state.scrollback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue