Show key binding hint in link popup

This commit is contained in:
Joscha 2023-04-29 16:31:23 +02:00
parent 5e55389887
commit 48279e879a
3 changed files with 38 additions and 15 deletions

View file

@ -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 {

View file

@ -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;

View file

@ -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),