Support composing messages in an external editor (#155)

This commit is contained in:
Leonid Dyachkov 2023-09-10 16:45:27 +03:00 committed by Ulyssa
parent 47e650c2be
commit 0565b6eb05
No known key found for this signature in database
GPG key ID: F2873CA2997B83C5
6 changed files with 141 additions and 19 deletions

View file

@ -202,6 +202,7 @@ pub enum RoomAction {
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum SendAction {
Submit,
SubmitFromEditor,
Upload(String),
UploadImage(usize, usize, Cow<'static, [u8]>),
}
@ -222,6 +223,16 @@ pub enum IambAction {
ToggleScrollbackFocus,
}
impl IambAction {
/// Indicates whether this action will draw over the screen.
pub fn scribbles(&self) -> bool {
match self {
IambAction::Send(SendAction::SubmitFromEditor) => true,
_ => false,
}
}
}
impl From<HomeserverAction> for IambAction {
fn from(act: HomeserverAction) -> Self {
IambAction::Homeserver(act)

View file

@ -266,6 +266,18 @@ fn iamb_reply(desc: CommandDescription, ctx: &mut ProgContext) -> ProgResult {
return Ok(step);
}
fn iamb_editor(desc: CommandDescription, ctx: &mut ProgContext) -> ProgResult {
if !desc.arg.text.is_empty() {
return Result::Err(CommandError::InvalidArgument);
}
let sact = IambAction::from(SendAction::SubmitFromEditor);
let step = CommandStep::Continue(sact.into(), ctx.context.take());
return Ok(step);
}
fn iamb_rooms(desc: CommandDescription, ctx: &mut ProgContext) -> ProgResult {
if !desc.arg.text.is_empty() {
return Result::Err(CommandError::InvalidArgument);
@ -537,6 +549,11 @@ fn add_iamb_commands(cmds: &mut ProgramCommands) {
aliases: vec![],
f: iamb_welcome,
});
cmds.add_command(ProgramCommand {
name: "editor".into(),
aliases: vec![],
f: iamb_editor,
});
}
pub fn setup_commands() -> ProgramCommands {

View file

@ -224,6 +224,9 @@ struct Application {
/// The tab layout before the last executed [TabAction].
last_layout: Option<TabLayoutDescription<IambInfo>>,
/// Whether we need to do a full redraw (e.g., after running a subprocess).
dirty: bool,
}
impl Application {
@ -263,6 +266,7 @@ impl Application {
screen,
focused: true,
last_layout: None,
dirty: true,
})
}
@ -314,7 +318,8 @@ impl Application {
async fn step(&mut self) -> Result<TerminalKey, std::io::Error> {
loop {
self.redraw(false, self.store.clone().lock().await.deref_mut())?;
self.redraw(self.dirty, self.store.clone().lock().await.deref_mut())?;
self.dirty = false;
if !poll(Duration::from_secs(1))? {
// Redraw in case there's new messages to show.
@ -479,6 +484,10 @@ impl Application {
ctx: ProgramContext,
store: &mut ProgramStore,
) -> IambResult<EditInfo> {
if action.scribbles() {
self.dirty = true;
}
let info = match action {
IambAction::ToggleScrollbackFocus => {
self.screen.current_window_mut()?.focus_toggle();

View file

@ -7,6 +7,7 @@ use std::path::{Path, PathBuf};
use modalkit::editing::store::RegisterError;
use std::process::Command;
use tokio;
use edit::edit as external_edit;
use matrix_sdk::{
attachment::AttachmentConfig,
@ -429,14 +430,18 @@ impl ChatState {
let mut show_echo = true;
let (event_id, msg) = match act {
SendAction::Submit => {
SendAction::Submit | SendAction::SubmitFromEditor => {
let msg = self.tbox.get();
if msg.is_blank() {
let msg = if let SendAction::SubmitFromEditor = act {
external_edit(msg.trim_end().to_string())?
} else if msg.is_blank() {
return Ok(None);
}
} else {
msg.trim_end().to_string()
};
let mut msg = text_to_message(msg.trim_end().to_string());
let mut msg = text_to_message(msg);
if let Some((_, event_id)) = &self.editing {
msg.relates_to = Some(Relation::Replacement(Replacement::new(