Skip to content

Commit

Permalink
Merge pull request #262 from andymandias/input-draft
Browse files Browse the repository at this point in the history
Add "Drafts" to Input
  • Loading branch information
casperstorm authored Mar 13, 2024
2 parents cf34b05 + 10a2e85 commit 7fe42d1
Show file tree
Hide file tree
Showing 11 changed files with 152 additions and 88 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
Added:

- Configuration option to enable a topic banner in channels. This can be enabled under `buffer.channel.topic`
- Messages typed into the input will persist until sent. Typed messages are saved when switching a pane to another buffer, then
are restored when that buffer is returned to.

Fix:

Expand Down
19 changes: 1 addition & 18 deletions data/src/history.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use std::collections::HashMap;
use std::path::PathBuf;
use std::time::Duration;
use std::{fmt, io};
Expand All @@ -11,7 +10,7 @@ use tokio::time::Instant;
pub use self::manager::{Manager, Resource};
use crate::time::Posix;
use crate::user::Nick;
use crate::{compression, environment, message, server, Buffer, Message};
use crate::{compression, environment, message, server, Message};

pub mod manager;

Expand All @@ -22,7 +21,6 @@ const MAX_MESSAGES: usize = 10_000;
const TRUNC_COUNT: usize = 500;
/// Duration to wait after receiving last message before flushing
const FLUSH_AFTER_LAST_RECEIVED: Duration = Duration::from_secs(5);
const INPUT_HISTORY_LENGTH: usize = 100;

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Kind {
Expand Down Expand Up @@ -274,21 +272,6 @@ pub struct View<'a> {
pub new_messages: Vec<&'a Message>,
}

#[derive(Debug, Clone, Default)]
struct Input(HashMap<Buffer, Vec<String>>);

impl Input {
fn get<'a>(&'a self, buffer: &Buffer) -> &'a [String] {
self.0.get(buffer).map(Vec::as_slice).unwrap_or_default()
}

fn push(&mut self, buffer: &Buffer, text: String) {
let history = self.0.entry(buffer.clone()).or_default();
history.insert(0, text);
history.truncate(INPUT_HISTORY_LENGTH);
}
}

#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error(transparent)]
Expand Down
12 changes: 8 additions & 4 deletions data/src/history/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ use futures::{future, Future, FutureExt};
use itertools::Itertools;
use tokio::time::Instant;

use crate::config;
use crate::config::buffer::Exclude;
use crate::history::{self, History};
use crate::message::{self, Limit};
use crate::time::Posix;
use crate::user::{Nick, NickRef};
use crate::{config, input};
use crate::{server, Buffer, Config, Input, Server, User};

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
Expand Down Expand Up @@ -173,10 +173,14 @@ impl Manager {
}

if let Some(text) = input.raw() {
self.data.input.push(input.buffer(), text.to_string());
self.data.input.record(input.buffer(), text.to_string());
}
}

pub fn record_draft(&mut self, draft: input::Draft) {
self.data.input.store_draft(draft);
}

pub fn record_message(&mut self, server: &Server, message: crate::Message) {
self.data.add_message(
server.clone(),
Expand Down Expand Up @@ -339,7 +343,7 @@ impl Manager {
});
}

pub fn input_history<'a>(&'a self, buffer: &Buffer) -> &'a [String] {
pub fn input<'a>(&'a self, buffer: &Buffer) -> input::Cache<'a> {
self.data.input.get(buffer)
}
}
Expand All @@ -365,7 +369,7 @@ fn with_limit<'a>(
#[derive(Debug, Default)]
struct Data {
map: HashMap<server::Server, HashMap<history::Kind, History>>,
input: history::Input,
input: input::Storage,
}

impl Data {
Expand Down
47 changes: 47 additions & 0 deletions data/src/input.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::collections::HashMap;

use chrono::Utc;
use irc::proto;
use irc::proto::format;
Expand All @@ -6,6 +8,8 @@ use crate::time::Posix;
use crate::user::NickRef;
use crate::{command, message, Buffer, Command, Message, Server, User};

const INPUT_HISTORY_LENGTH: usize = 100;

pub fn parse(buffer: Buffer, input: &str) -> Result<Input, Error> {
let content = match command::parse(input, Some(&buffer)) {
Ok(command) => Content::Command(command),
Expand Down Expand Up @@ -126,6 +130,49 @@ impl Content {
}
}

#[derive(Debug, Clone)]
pub struct Draft {
pub buffer: Buffer,
pub text: String,
}

#[derive(Debug, Clone, Default)]
pub struct Storage {
sent: HashMap<Buffer, Vec<String>>,
draft: HashMap<Buffer, String>,
}

impl Storage {
pub fn get<'a>(&'a self, buffer: &Buffer) -> Cache<'a> {
Cache {
history: self.sent.get(buffer).map(Vec::as_slice).unwrap_or_default(),
draft: self
.draft
.get(buffer)
.map(AsRef::as_ref)
.unwrap_or_default(),
}
}

pub fn record(&mut self, buffer: &Buffer, text: String) {
self.draft.remove(buffer);
let history = self.sent.entry(buffer.clone()).or_default();
history.insert(0, text);
history.truncate(INPUT_HISTORY_LENGTH);
}

pub fn store_draft(&mut self, draft: Draft) {
self.draft.insert(draft.buffer, draft.text);
}
}

/// Cached values for a buffers input
#[derive(Debug, Clone, Copy)]
pub struct Cache<'a> {
pub history: &'a [String],
pub draft: &'a str,
}

#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error(
Expand Down
30 changes: 19 additions & 11 deletions src/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,17 +159,25 @@ impl Buffer {
}
}

pub fn insert_user_to_input(&mut self, user: User) -> Command<Message> {
match self {
Buffer::Empty | Buffer::Server(_) => Command::none(),
Buffer::Channel(channel) => channel
.input_view
.insert_user(user)
.map(|message| Message::Channel(channel::Message::InputView(message))),
Buffer::Query(query) => query
.input_view
.insert_user(user)
.map(|message| Message::Query(query::Message::InputView(message))),
pub fn insert_user_to_input(
&mut self,
user: User,
history: &mut history::Manager,
) -> Command<Message> {
if let Some(buffer) = self.data() {
match self {
Buffer::Empty | Buffer::Server(_) => Command::none(),
Buffer::Channel(channel) => channel
.input_view
.insert_user(user, buffer, history)
.map(|message| Message::Channel(channel::Message::InputView(message))),
Buffer::Query(query) => query
.input_view
.insert_user(user, buffer, history)
.map(|message| Message::Query(query::Message::InputView(message))),
}
} else {
Command::none()
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/buffer/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub fn view<'a>(
is_focused: bool,
) -> Element<'a, Message> {
let buffer = state.buffer();
let input_history = history.input_history(&buffer);
let input = history.input(&buffer);
let our_nick = clients.nickname(&state.server);

let messages = container(
Expand Down Expand Up @@ -128,10 +128,10 @@ pub fn view<'a>(
input_view::view(
&state.input_view,
buffer,
input,
users,
channels,
input_history,
is_focused,
is_focused
)
.map(Message::InputView)
});
Expand Down
44 changes: 25 additions & 19 deletions src/buffer/input_view.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use data::input::{Cache, Draft};
use data::user::User;
use data::{client, history, Buffer, Input};
use iced::Command;
Expand All @@ -10,26 +11,26 @@ pub enum Event {

#[derive(Debug, Clone)]
pub enum Message {
Input(String),
Input(Draft),
Send(Input),
Completion(String),
Completion(Draft),
}

pub fn view<'a>(
state: &'a State,
buffer: Buffer,
cache: Cache<'a>,
users: &'a [User],
channels: &'a [String],
history: &'a [String],
buffer_focused: bool,
) -> Element<'a, Message> {
input(
state.input_id.clone(),
buffer,
&state.input,
cache.draft,
cache.history,
users,
channels,
history,
buffer_focused,
Message::Input,
Message::Send,
Expand All @@ -40,7 +41,6 @@ pub fn view<'a>(
#[derive(Debug, Clone)]
pub struct State {
input_id: input::Id,
input: String,
}

impl Default for State {
Expand All @@ -53,7 +53,6 @@ impl State {
pub fn new() -> Self {
Self {
input_id: input::Id::unique(),
input: String::default(),
}
}

Expand All @@ -64,14 +63,12 @@ impl State {
history: &mut history::Manager,
) -> (Command<Message>, Option<Event>) {
match message {
Message::Input(input) => {
self.input = input;
Message::Input(draft) => {
history.record_draft(draft);

(Command::none(), None)
}
Message::Send(input) => {
self.input.clear();

if let Some(encoded) = input.encoded() {
clients.send(input.buffer(), encoded);
}
Expand All @@ -82,8 +79,8 @@ impl State {

(Command::none(), Some(Event::InputSent))
}
Message::Completion(input) => {
self.input = input;
Message::Completion(draft) => {
history.record_draft(draft);

(input::move_cursor_to_end(self.input_id.clone()), None)
}
Expand All @@ -98,15 +95,24 @@ impl State {
input::reset(self.input_id.clone())
}

pub fn insert_user(&mut self, user: User) -> Command<Message> {
if self.input.is_empty() {
self.input = format!("{}: ", user.nickname());
} else if self.input.ends_with(' ') {
self.input = format!("{}{}", self.input, user.nickname());
pub fn insert_user(
&mut self,
user: User,
buffer: Buffer,
history: &mut history::Manager,
) -> Command<Message> {
let mut text = history.input(&buffer).draft.to_string();

if text.is_empty() {
text = format!("{}: ", user.nickname());
} else if text.ends_with(' ') {
text = format!("{}{}", text, user.nickname());
} else {
self.input = format!("{} {}", self.input, user.nickname());
text = format!("{} {}", text, user.nickname());
}

history.record_draft(Draft { buffer, text });

input::move_cursor_to_end(self.input_id.clone())
}
}
13 changes: 3 additions & 10 deletions src/buffer/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub fn view<'a>(
is_focused: bool,
) -> Element<'a, Message> {
let buffer = state.buffer();
let input_history = history.input_history(&buffer);
let input = history.input(&buffer);

let messages = container(
scroll_view::view(
Expand Down Expand Up @@ -101,15 +101,8 @@ pub fn view<'a>(
let text_input = show_text_input.then(|| {
column![
vertical_space(4),
input_view::view(
&state.input_view,
buffer,
&[],
channels,
input_history,
is_focused
)
.map(Message::InputView)
input_view::view(&state.input_view, buffer, input, &[], channels, is_focused)
.map(Message::InputView)
]
.width(Length::Fill)
});
Expand Down
15 changes: 4 additions & 11 deletions src/buffer/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub fn view<'a>(
is_focused: bool,
) -> Element<'a, Message> {
let buffer = state.buffer();
let input_history = history.input_history(&buffer);
let input = history.input(&buffer);

let messages = container(
scroll_view::view(
Expand Down Expand Up @@ -65,15 +65,8 @@ pub fn view<'a>(
let text_input = show_text_input.then(|| {
column![
vertical_space(4),
input_view::view(
&state.input_view,
buffer,
&[],
channels,
input_history,
is_focused
)
.map(Message::InputView)
input_view::view(&state.input_view, buffer, input, &[], channels, is_focused)
.map(Message::InputView)
]
.width(Length::Fill)
});
Expand All @@ -93,7 +86,7 @@ pub fn view<'a>(
pub struct Server {
pub server: data::server::Server,
pub scroll_view: scroll_view::State,
input_view: input_view::State,
pub input_view: input_view::State,
}

impl Server {
Expand Down
Loading

0 comments on commit 7fe42d1

Please sign in to comment.