multiverse/widgets/room_view/
input.rs1use clap::{Parser, Subcommand};
2use crossterm::event::KeyEvent;
3use matrix_sdk::Room;
4use ratatui::{prelude::*, widgets::*};
5use style::palette::tailwind;
6use tui_textarea::TextArea;
7
8#[derive(Debug, Parser)]
9#[command(name = "multiverse", disable_help_flag = true, disable_help_subcommand = true)]
10struct Cli {
11 #[command(subcommand)]
12 command: Command,
13}
14
15#[derive(Debug, Subcommand)]
16pub enum Command {
17 Invite { user_id: String },
18 Leave,
19 Subscribe,
20 Unsubscribe,
21}
22
23pub enum MessageOrCommand {
24 Message(String),
25 Command(Command),
26}
27
28#[derive(Default)]
30pub struct Input {
31 textarea: TextArea<'static>,
33}
34
35impl Input {
36 pub fn new() -> Self {
38 let textarea = TextArea::default();
39
40 Self { textarea }
41 }
42
43 pub fn handle_key_press(&mut self, event: KeyEvent) {
45 self.textarea.input(event);
46 }
47
48 pub fn get_input(&self) -> Result<MessageOrCommand, clap::Error> {
50 let input = self.textarea.lines().join("\n");
51
52 if let Some(input) = input.strip_prefix("/") {
53 let arguments = input.split_whitespace();
54
55 Cli::try_parse_from(std::iter::once("multiverse").chain(arguments))
60 .map(|cli| MessageOrCommand::Command(cli.command))
61 } else {
62 Ok(MessageOrCommand::Message(input))
63 }
64 }
65
66 pub fn is_empty(&self) -> bool {
69 self.textarea.is_empty()
70 }
71
72 pub fn clear(&mut self) {
74 self.textarea = TextArea::default();
75 }
76}
77
78impl<'a> StatefulWidget for &'a mut Input {
79 type State = Option<&'a Room>;
80
81 fn render(self, area: Rect, buf: &mut Buffer, room: &mut Self::State)
82 where
83 Self: Sized,
84 {
85 if let Some(room) = room.as_deref() {
90 let is_encrypted = room.encryption_state().is_encrypted();
91
92 if is_encrypted {
93 self.textarea.set_placeholder_text("(Send an encrypted message)");
94 } else {
95 self.textarea.set_placeholder_text("(Send an unencrypted message)");
96 }
97 } else {
98 self.textarea.set_placeholder_text("(No room selected)");
99 }
100
101 let input_block = Block::new().borders(Borders::NONE).bg(tailwind::BLUE.c400);
103
104 self.textarea.set_block(input_block);
106 self.textarea.render(area, buf);
107 }
108}