Skip to content

Commit

Permalink
Add scroll_to message / divider support
Browse files Browse the repository at this point in the history
  • Loading branch information
tarkah committed Oct 4, 2024
1 parent 1f4b46f commit 01335de
Show file tree
Hide file tree
Showing 13 changed files with 495 additions and 116 deletions.
8 changes: 8 additions & 0 deletions data/src/history.rs
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,14 @@ impl History {

*stored = (*stored).max(Some(read_marker));
}

pub fn read_marker(&self) -> Option<ReadMarker> {
match self {
History::Partial { read_marker, .. } | History::Full { read_marker, .. } => {
*read_marker
}
}
}
}

#[derive(Debug)]
Expand Down
60 changes: 8 additions & 52 deletions data/src/history/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ use crate::user::Nick;
use crate::{config, input};
use crate::{server, Buffer, Config, Input, Server, User};

// Hack since log messages are app wide and not scoped to any server
const LOG_SERVER_NAME: &str = "<halloy-logs>";

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Resource {
pub server: server::Server,
Expand All @@ -24,7 +21,7 @@ pub struct Resource {
impl Resource {
pub fn logs() -> Self {
Self {
server: Server::from(LOG_SERVER_NAME),
server: server::LOGS.clone(),
kind: history::Kind::Logs,
}
}
Expand Down Expand Up @@ -64,6 +61,7 @@ pub enum Message {
}

pub enum Event {
Loaded(server::Server, history::Kind),
Closed(server::Server, history::Kind, Option<history::ReadMarker>),
Exited(Vec<(Server, history::Kind, Option<history::ReadMarker>)>),
}
Expand Down Expand Up @@ -111,7 +109,8 @@ impl Manager {
"loaded history for {kind} on {server}: {} messages",
loaded.messages.len()
);
self.data.load_full(server, kind, loaded);
self.data.load_full(server.clone(), kind.clone(), loaded);
return Some(Event::Loaded(server, kind));
}
Message::LoadFull(server, kind, Err(error)) => {
log::warn!("failed to load history for {kind} on {server}: {error}");
Expand Down Expand Up @@ -245,7 +244,7 @@ impl Manager {
record: crate::log::Record,
) -> Option<impl Future<Output = Message>> {
self.data.add_message(
Server::from(LOG_SERVER_NAME),
server::LOGS.clone(),
history::Kind::Logs,
crate::Message::log(record),
)
Expand All @@ -268,57 +267,14 @@ impl Manager {
self.data.channel_joined(server, channel)
}

pub fn get_channel_messages(
&self,
server: &Server,
channel: &str,
limit: Option<Limit>,
buffer_config: &config::Buffer,
) -> Option<history::View<'_>> {
self.data.history_view(
server,
&history::Kind::Channel(channel.to_string()),
limit,
buffer_config,
)
}

pub fn get_server_messages(
&self,
server: &Server,
limit: Option<Limit>,
buffer_config: &config::Buffer,
) -> Option<history::View<'_>> {
self.data
.history_view(server, &history::Kind::Server, limit, buffer_config)
}

pub fn get_query_messages(
pub fn get_messages(
&self,
server: &Server,
nick: &Nick,
limit: Option<Limit>,
buffer_config: &config::Buffer,
) -> Option<history::View<'_>> {
self.data.history_view(
server,
&history::Kind::Query(nick.clone()),
limit,
buffer_config,
)
}

pub fn get_log_messages(
&self,
kind: &history::Kind,
limit: Option<Limit>,
buffer_config: &config::Buffer,
) -> Option<history::View<'_>> {
self.data.history_view(
&Server::from(LOG_SERVER_NAME),
&history::Kind::Logs,
limit,
buffer_config,
)
self.data.history_view(server, kind, limit, buffer_config)
}

pub fn get_unique_queries(&self, server: &Server) -> Vec<&Nick> {
Expand Down
12 changes: 10 additions & 2 deletions data/src/history/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ use serde::{Deserialize, Serialize};
use tokio::fs;

use crate::history::{dir_path, Error, Kind};
use crate::{message, server, Message};
use crate::message::source;
use crate::{server, Message};

#[derive(Debug, Clone, Copy, Default, Deserialize, Serialize)]
pub struct Metadata {
Expand All @@ -23,7 +24,14 @@ impl ReadMarker {
messages
.iter()
.rev()
.find(|message| !matches!(message.target.source(), message::Source::Internal(_)))
.find(|message| match message.target.source() {
source::Source::Internal(source) => match source {
source::Internal::Status(_) => false,
// Logs are in their own buffer and this gives us backlog support there
source::Internal::Logs => true,
},
_ => true,
})
.map(|message| message.server_time)
.map(Self)
}
Expand Down
26 changes: 9 additions & 17 deletions data/src/input.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
use std::collections::HashMap;

use chrono::Utc;
use irc::proto;
use irc::proto::format;

use crate::buffer::AutoFormat;
use crate::message::formatting;
use crate::time::Posix;
use crate::{command, message, Buffer, Command, Message, Server, User};

const INPUT_HISTORY_LENGTH: usize = 100;
Expand Down Expand Up @@ -90,24 +88,18 @@ impl Input {
targets
.split(',')
.filter_map(|target| to_target(target, message::Source::User(user.clone())))
.map(|target| Message {
received_at: Posix::now(),
server_time: Utc::now(),
direction: message::Direction::Sent,
target,
content: message::parse_fragments(text.clone(), channel_users),
id: None,
.map(|target| {
Message::sent(
target,
message::parse_fragments(text.clone(), channel_users),
)
})
.collect(),
),
Command::Me(target, action) => Some(vec![Message {
received_at: Posix::now(),
server_time: Utc::now(),
direction: message::Direction::Sent,
target: to_target(&target, message::Source::Action)?,
content: message::action_text(user.nickname(), Some(&action)),
id: None,
}]),
Command::Me(target, action) => Some(vec![Message::sent(
to_target(&target, message::Source::Action)?,
message::action_text(user.nickname(), Some(&action)),
)]),
_ => None,
}
}
Expand Down
2 changes: 1 addition & 1 deletion data/src/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ fn path() -> Result<PathBuf, Error> {
Ok(parent.join("halloy.log"))
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Record {
pub timestamp: DateTime<Utc>,
pub level: Level,
Expand Down
74 changes: 63 additions & 11 deletions data/src/message.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::borrow::Cow;
use std::hash::{DefaultHasher, Hash as _, Hasher};
use std::iter;

use chrono::{DateTime, Utc};
Expand Down Expand Up @@ -153,6 +154,7 @@ pub struct Message {
pub target: Target,
pub content: Content,
pub id: Option<String>,
pub hash: Hash,
}

impl Message {
Expand All @@ -168,6 +170,7 @@ impl Message {
| source::server::Kind::MonitoredOffline
)
}
Source::Internal(source::Internal::Logs) => true,
_ => false,
}
}
Expand All @@ -189,42 +192,70 @@ impl Message {
&channel_users,
)?;
let target = target(encoded, &our_nick, &resolve_attributes)?;
let received_at = Posix::now();
let hash = Hash::new(&received_at, &content);

Some(Message {
received_at: Posix::now(),
received_at,
server_time,
direction: Direction::Received,
target,
content,
id,
hash,
})
}

pub fn sent(target: Target, content: Content) -> Self {
let received_at = Posix::now();
let hash = Hash::new(&received_at, &content);

Message {
received_at,
server_time: Utc::now(),
direction: Direction::Sent,
target,
content,
id: None,
hash,
}
}

pub fn file_transfer_request_received(from: &Nick, filename: &str) -> Message {
let received_at = Posix::now();
let content = plain(format!("{from} wants to send you \"{filename}\""));
let hash = Hash::new(&received_at, &content);

Message {
received_at: Posix::now(),
received_at,
server_time: Utc::now(),
direction: Direction::Received,
target: Target::Query {
nick: from.clone(),
source: Source::Action,
},
content: plain(format!("{from} wants to send you \"{filename}\"")),
content,
id: None,
hash,
}
}

pub fn file_transfer_request_sent(to: &Nick, filename: &str) -> Message {
let received_at = Posix::now();
let content = plain(format!("offering to send {to} \"{filename}\""));
let hash = Hash::new(&received_at, &content);

Message {
received_at: Posix::now(),
received_at,
server_time: Utc::now(),
direction: Direction::Sent,
target: Target::Query {
nick: to.clone(),
source: Source::Action,
},
content: plain(format!("offering to send {to} \"{filename}\"")),
content,
id: None,
hash,
}
}

Expand All @@ -241,13 +272,19 @@ impl Message {
}

pub fn log(record: crate::log::Record) -> Self {
let received_at = Posix::now();
let server_time = record.timestamp;
let content = Content::Log(record);
let hash = Hash::new(&received_at, &content);

Self {
received_at: Posix::now(),
server_time: record.timestamp,
received_at,
server_time,
direction: Direction::Received,
target: Target::Logs,
content: Content::Log(record),
content,
id: None,
hash,
}
}
}
Expand Down Expand Up @@ -320,17 +357,32 @@ impl<'de> Deserialize<'de> for Message {
Content::Plain("".to_string())
};

let hash = Hash::new(&received_at, &content);

Ok(Message {
received_at,
server_time,
direction,
target,
content,
id,
hash,
})
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Hash(u64);

impl Hash {
pub fn new(received_at: &time::Posix, content: &Content) -> Self {
let mut hasher = DefaultHasher::new();
received_at.hash(&mut hasher);
content.hash(&mut hasher);
Self(hasher.finish())
}
}

pub fn plain(text: String) -> Content {
Content::Plain(text)
}
Expand Down Expand Up @@ -478,7 +530,7 @@ fn parse_user_and_channel_fragments(text: &str, channel_users: &[User]) -> Vec<F
})
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Content {
Plain(String),
Fragments(Vec<Fragment>),
Expand All @@ -495,7 +547,7 @@ impl Content {
}
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Fragment {
Text(String),
Channel(String),
Expand Down Expand Up @@ -1036,7 +1088,7 @@ pub enum Limit {

impl Limit {
pub const DEFAULT_STEP: usize = 50;
const DEFAULT_COUNT: usize = 500;
pub const DEFAULT_COUNT: usize = 500;

pub fn top() -> Self {
Self::Top(Self::DEFAULT_COUNT)
Expand Down
Loading

0 comments on commit 01335de

Please sign in to comment.