wip
This commit is contained in:
@@ -14,6 +14,8 @@ pub enum Command {
|
||||
Relays(PublicKey),
|
||||
Njump(PublicKey),
|
||||
Trace(EventId),
|
||||
Speak(EventId),
|
||||
StopSpeaking,
|
||||
}
|
||||
|
||||
// Start or stop dictation in the focused composer
|
||||
|
||||
+30
-23
@@ -30,6 +30,7 @@ use person::{Directory, Person};
|
||||
use regex::Regex;
|
||||
use settings::{AppSettings, SignerKind};
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
use speech::speaker::Speaker;
|
||||
use state::{
|
||||
FileAttachment, LocalFile, NostrRegistry, PickedFile, download_and_decrypt_file, pick_file,
|
||||
};
|
||||
@@ -65,65 +66,45 @@ pub fn init(room: WeakEntity<Room>, window: &mut Window, cx: &mut App) -> Entity
|
||||
pub struct ChatPanel {
|
||||
id: SharedString,
|
||||
focus_handle: FocusHandle,
|
||||
|
||||
/// Chat Room
|
||||
room: WeakEntity<Room>,
|
||||
|
||||
/// Person directory shared with the room
|
||||
directory: Entity<Directory>,
|
||||
|
||||
/// Message list state
|
||||
list_state: ListState,
|
||||
|
||||
/// All messages (sorted by created_at)
|
||||
messages: Vec<Message>,
|
||||
|
||||
/// O(1) message lookup by EventId
|
||||
message_index: HashMap<EventId, usize>,
|
||||
|
||||
/// All reactions
|
||||
reactions: BTreeMap<EventId, Vec<(SharedString, Option<SharedUri>, PublicKey)>>,
|
||||
|
||||
/// Mapping message ids to their rendered texts
|
||||
rendered_texts_by_id: BTreeMap<EventId, RenderedText>,
|
||||
|
||||
/// Mapping message (rumor event) ids to their reports
|
||||
reports_by_id: Arc<RwLock<BTreeMap<EventId, Vec<SendReport>>>>,
|
||||
|
||||
/// Chat input state
|
||||
input: Entity<TextareaState>,
|
||||
|
||||
/// Dictation session for the chat input
|
||||
speech: Entity<SpeechState>,
|
||||
|
||||
/// When the running dictation started, for the elapsed counter
|
||||
speech_started: Option<instant::Instant>,
|
||||
|
||||
/// Reads messages aloud
|
||||
speaker: Speaker,
|
||||
/// Subject input state
|
||||
subject_input: Entity<InputState>,
|
||||
|
||||
/// Subject bar visibility
|
||||
subject_bar: Entity<bool>,
|
||||
|
||||
/// Replies to
|
||||
replies_to: Entity<HashSet<EventId>>,
|
||||
|
||||
/// Media Attachment
|
||||
attachments: Entity<Vec<Url>>,
|
||||
|
||||
/// Uploaded, encrypted file attachments which are not sent yet
|
||||
encrypted_attachments: Entity<Vec<PendingFile>>,
|
||||
|
||||
/// Decrypted attachments of file messages, by message id
|
||||
decrypted_files: HashMap<EventId, DecryptedFile>,
|
||||
|
||||
/// Upload state
|
||||
uploading: bool,
|
||||
|
||||
/// Async operations
|
||||
tasks: Vec<Task<Result<(), Error>>>,
|
||||
|
||||
/// Event subscriptions
|
||||
subscriptions: SmallVec<[Subscription; 4]>,
|
||||
}
|
||||
|
||||
@@ -253,6 +234,7 @@ impl ChatPanel {
|
||||
input,
|
||||
speech,
|
||||
speech_started: None,
|
||||
speaker: Speaker::new(),
|
||||
subject_input,
|
||||
subject_bar,
|
||||
replies_to,
|
||||
@@ -955,6 +937,20 @@ impl ChatPanel {
|
||||
Command::Trace(id) => {
|
||||
self.open_trace(id, window, cx);
|
||||
}
|
||||
Command::Speak(id) => {
|
||||
let text = self.message(id).map(|message| message.preview());
|
||||
|
||||
if let Some(text) = text
|
||||
&& let Err(e) = self.speaker.speak(&text)
|
||||
{
|
||||
window.push_notification(Notification::error(e.to_string()), cx);
|
||||
}
|
||||
}
|
||||
Command::StopSpeaking => {
|
||||
if let Err(error) = self.speaker.stop() {
|
||||
window.push_notification(Notification::error(error.to_string()), cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1464,9 +1460,20 @@ impl ChatPanel {
|
||||
actions
|
||||
};
|
||||
|
||||
let speaking = self.speaker.speaking();
|
||||
|
||||
actions.dropdown(move |menu, _window, _cx| {
|
||||
menu.menu("Copy author", Box::new(Command::Copy(public_key)))
|
||||
let menu = menu
|
||||
.menu("Copy author", Box::new(Command::Copy(public_key)))
|
||||
.menu("Seen on", Box::new(Command::Trace(dropdown_id)))
|
||||
.separator()
|
||||
.menu("Read aloud", Box::new(Command::Speak(dropdown_id)));
|
||||
|
||||
if speaking {
|
||||
menu.menu("Stop speaking", Box::new(Command::StopSpeaking))
|
||||
} else {
|
||||
menu
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user