Show key binding hint in link popup
This commit is contained in:
parent
5e55389887
commit
48279e879a
3 changed files with 38 additions and 15 deletions
|
|
@ -1,17 +1,18 @@
|
||||||
use cove_config::Keys;
|
use cove_config::{Config, Keys};
|
||||||
use cove_input::InputEvent;
|
use cove_input::InputEvent;
|
||||||
use crossterm::event::KeyCode;
|
use crossterm::event::KeyCode;
|
||||||
use crossterm::style::Stylize;
|
use crossterm::style::Stylize;
|
||||||
use linkify::{LinkFinder, LinkKind};
|
use linkify::{LinkFinder, LinkKind};
|
||||||
use toss::widgets::Text;
|
use toss::widgets::{Join2, Text};
|
||||||
use toss::{Style, Styled, Widget};
|
use toss::{Style, Styled, Widget, WidgetExt};
|
||||||
|
|
||||||
use crate::ui::widgets::{ListBuilder, ListState, Popup};
|
use crate::ui::widgets::{ListBuilder, ListState, Popup};
|
||||||
use crate::ui::{util, UiError};
|
use crate::ui::{key_bindings, util, UiError};
|
||||||
|
|
||||||
use super::popup::PopupResult;
|
use super::popup::PopupResult;
|
||||||
|
|
||||||
pub struct LinksState {
|
pub struct LinksState {
|
||||||
|
config: &'static Config,
|
||||||
links: Vec<String>,
|
links: Vec<String>,
|
||||||
list: ListState<usize>,
|
list: ListState<usize>,
|
||||||
}
|
}
|
||||||
|
|
@ -19,7 +20,7 @@ pub struct LinksState {
|
||||||
const NUMBER_KEYS: [char; 10] = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'];
|
const NUMBER_KEYS: [char; 10] = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'];
|
||||||
|
|
||||||
impl LinksState {
|
impl LinksState {
|
||||||
pub fn new(content: &str) -> Self {
|
pub fn new(config: &'static Config, content: &str) -> Self {
|
||||||
let links = LinkFinder::new()
|
let links = LinkFinder::new()
|
||||||
.url_must_have_scheme(false)
|
.url_must_have_scheme(false)
|
||||||
.kinds(&[LinkKind::Url])
|
.kinds(&[LinkKind::Url])
|
||||||
|
|
@ -28,6 +29,7 @@ impl LinksState {
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
config,
|
||||||
links,
|
links,
|
||||||
list: ListState::new(),
|
list: ListState::new(),
|
||||||
}
|
}
|
||||||
|
|
@ -69,7 +71,24 @@ impl LinksState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Popup::new(list_builder.build(&mut self.list), "Links")
|
let hint_style = Style::new().grey().italic();
|
||||||
|
let hint = Styled::new("Open links with ", hint_style)
|
||||||
|
.and_then(key_bindings::format_binding(
|
||||||
|
&self.config.keys.general.confirm,
|
||||||
|
))
|
||||||
|
.then(" or the number keys.", hint_style);
|
||||||
|
|
||||||
|
Popup::new(
|
||||||
|
Join2::vertical(
|
||||||
|
list_builder.build(&mut self.list).segment(),
|
||||||
|
Text::new(hint)
|
||||||
|
.padding()
|
||||||
|
.with_top(1)
|
||||||
|
.segment()
|
||||||
|
.with_fixed(true),
|
||||||
|
),
|
||||||
|
"Links",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open_link_by_id(&self, id: usize) -> PopupResult {
|
fn open_link_by_id(&self, id: usize) -> PopupResult {
|
||||||
|
|
@ -110,7 +129,6 @@ impl LinksState {
|
||||||
return PopupResult::Handled;
|
return PopupResult::Handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Mention that this is possible in the UI
|
|
||||||
if let Some(key_event) = event.key_event() {
|
if let Some(key_event) = event.key_event() {
|
||||||
if key_event.modifiers.is_empty() {
|
if key_event.modifiers.is_empty() {
|
||||||
match key_event.code {
|
match key_event.code {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
use cove_config::Keys;
|
use cove_config::{Config, Keys};
|
||||||
use cove_input::InputEvent;
|
use cove_input::InputEvent;
|
||||||
use crossterm::style::Stylize;
|
use crossterm::style::Stylize;
|
||||||
use euphoxide::api::{Data, Message, MessageId, PacketType, SessionId};
|
use euphoxide::api::{Data, Message, MessageId, PacketType, SessionId};
|
||||||
|
|
@ -43,8 +43,9 @@ enum State {
|
||||||
type EuphChatState = ChatState<euph::SmallMessage, EuphRoomVault>;
|
type EuphChatState = ChatState<euph::SmallMessage, EuphRoomVault>;
|
||||||
|
|
||||||
pub struct EuphRoom {
|
pub struct EuphRoom {
|
||||||
|
config: &'static Config,
|
||||||
server_config: ServerConfig,
|
server_config: ServerConfig,
|
||||||
config: cove_config::EuphRoom,
|
room_config: cove_config::EuphRoom,
|
||||||
ui_event_tx: mpsc::UnboundedSender<UiEvent>,
|
ui_event_tx: mpsc::UnboundedSender<UiEvent>,
|
||||||
|
|
||||||
room: Option<euph::Room>,
|
room: Option<euph::Room>,
|
||||||
|
|
@ -61,14 +62,16 @@ pub struct EuphRoom {
|
||||||
|
|
||||||
impl EuphRoom {
|
impl EuphRoom {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
|
config: &'static Config,
|
||||||
server_config: ServerConfig,
|
server_config: ServerConfig,
|
||||||
config: cove_config::EuphRoom,
|
room_config: cove_config::EuphRoom,
|
||||||
vault: EuphRoomVault,
|
vault: EuphRoomVault,
|
||||||
ui_event_tx: mpsc::UnboundedSender<UiEvent>,
|
ui_event_tx: mpsc::UnboundedSender<UiEvent>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
server_config,
|
|
||||||
config,
|
config,
|
||||||
|
server_config,
|
||||||
|
room_config,
|
||||||
ui_event_tx,
|
ui_event_tx,
|
||||||
room: None,
|
room: None,
|
||||||
focus: Focus::Chat,
|
focus: Focus::Chat,
|
||||||
|
|
@ -97,9 +100,9 @@ impl EuphRoom {
|
||||||
.room(self.vault().room().to_string())
|
.room(self.vault().room().to_string())
|
||||||
.name(format!("{room}-{}", next_instance_id))
|
.name(format!("{room}-{}", next_instance_id))
|
||||||
.human(true)
|
.human(true)
|
||||||
.username(self.config.username.clone())
|
.username(self.room_config.username.clone())
|
||||||
.force_username(self.config.force_username)
|
.force_username(self.room_config.force_username)
|
||||||
.password(self.config.password.clone());
|
.password(self.room_config.password.clone());
|
||||||
*next_instance_id = next_instance_id.wrapping_add(1);
|
*next_instance_id = next_instance_id.wrapping_add(1);
|
||||||
|
|
||||||
let tx = self.ui_event_tx.clone();
|
let tx = self.ui_event_tx.clone();
|
||||||
|
|
@ -420,7 +423,7 @@ impl EuphRoom {
|
||||||
if event.matches(&keys.tree.action.links) {
|
if event.matches(&keys.tree.action.links) {
|
||||||
if let Some(id) = self.chat.cursor() {
|
if let Some(id) = self.chat.cursor() {
|
||||||
if let Some(msg) = logging_unwrap!(self.vault().msg(*id).await) {
|
if let Some(msg) = logging_unwrap!(self.vault().msg(*id).await) {
|
||||||
self.state = State::Links(LinksState::new(&msg.content));
|
self.state = State::Links(LinksState::new(self.config, &msg.content));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,7 @@ impl Rooms {
|
||||||
fn get_or_insert_room(&mut self, name: String) -> &mut EuphRoom {
|
fn get_or_insert_room(&mut self, name: String) -> &mut EuphRoom {
|
||||||
self.euph_rooms.entry(name.clone()).or_insert_with(|| {
|
self.euph_rooms.entry(name.clone()).or_insert_with(|| {
|
||||||
EuphRoom::new(
|
EuphRoom::new(
|
||||||
|
self.config,
|
||||||
self.euph_server_config.clone(),
|
self.euph_server_config.clone(),
|
||||||
self.config.euph_room(&name),
|
self.config.euph_room(&name),
|
||||||
self.vault.euph().room(name),
|
self.vault.euph().room(name),
|
||||||
|
|
@ -104,6 +105,7 @@ impl Rooms {
|
||||||
fn connect_to_room(&mut self, name: String) {
|
fn connect_to_room(&mut self, name: String) {
|
||||||
let room = self.euph_rooms.entry(name.clone()).or_insert_with(|| {
|
let room = self.euph_rooms.entry(name.clone()).or_insert_with(|| {
|
||||||
EuphRoom::new(
|
EuphRoom::new(
|
||||||
|
self.config,
|
||||||
self.euph_server_config.clone(),
|
self.euph_server_config.clone(),
|
||||||
self.config.euph_room(&name),
|
self.config.euph_room(&name),
|
||||||
self.vault.euph().room(name),
|
self.vault.euph().room(name),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue