Skip to content

Commit

Permalink
Merge pull request #59 from squidowl/fix/scroll-view
Browse files Browse the repository at this point in the history
Fix/scroll view
  • Loading branch information
tarkah authored Jun 27, 2023
2 parents 1eae22f + 863c961 commit 7a8aba5
Show file tree
Hide file tree
Showing 11 changed files with 62 additions and 64 deletions.
6 changes: 3 additions & 3 deletions data/src/environment.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::env;
use std::path::{Path, PathBuf};
use std::path::PathBuf;

pub const VERSION: &str = env!("VERSION");
pub const GIT_HASH: Option<&str> = option_env!("GIT_HASH");
Expand Down Expand Up @@ -47,7 +47,7 @@ pub(crate) fn data_dir() -> Option<PathBuf> {
}
}

#[allow(dead_code)]
fn is_absolute(path: &Path) -> bool {
#[cfg(target_os = "linux")]
fn is_absolute(path: &std::path::Path) -> bool {
path.is_absolute()
}
3 changes: 1 addition & 2 deletions data/src/history/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use tokio::time::Instant;

use crate::history::{self, History};
use crate::message::{self, Limit};
use crate::time::Posix;
use crate::user::Nick;
use crate::{server, Server};

Expand Down Expand Up @@ -246,7 +245,7 @@ fn with_limit<'a>(
collected[length.saturating_sub(n)..length].to_vec()
}
Some(Limit::Since(timestamp)) => messages
.skip_while(|message| Posix::from(message.datetime) < timestamp)
.skip_while(|message| message.received_at < timestamp)
.collect(),
None => messages.collect(),
}
Expand Down
7 changes: 5 additions & 2 deletions data/src/input.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use chrono::Utc;
use irc::proto::ChannelExt;

use crate::time::Posix;
use crate::user::Nick;
use crate::{command, message, Buffer, Command, Message, Server, User};

Expand Down Expand Up @@ -40,7 +41,8 @@ impl Input {

match command {
Command::Msg(target, text) => Some(Message {
datetime: Utc::now(),
received_at: Posix::now(),
server_time: Utc::now(),
direction: message::Direction::Sent,
source: source(
target,
Expand All @@ -49,7 +51,8 @@ impl Input {
text,
}),
Command::Me(target, action) => Some(Message {
datetime: Utc::now(),
received_at: Posix::now(),
server_time: Utc::now(),
direction: message::Direction::Sent,
source: source(target, message::Sender::Action)?,
text: message::action_text(our_nick, &action),
Expand Down
31 changes: 11 additions & 20 deletions data/src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ pub enum Direction {

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Message {
pub datetime: DateTime<Utc>,
pub received_at: Posix,
pub server_time: DateTime<Utc>,
pub direction: Direction,
pub source: Source,
pub text: String,
Expand Down Expand Up @@ -92,12 +93,13 @@ impl Message {
}

pub fn received(encoded: Encoded, our_nick: &Nick) -> Option<Message> {
let datetime = datetime(&encoded);
let server_time = server_time(&encoded);
let text = text(&encoded, our_nick)?;
let source = source(encoded, our_nick)?;

Some(Message {
datetime,
received_at: Posix::now(),
server_time,
direction: Direction::Received,
source,
text,
Expand Down Expand Up @@ -222,7 +224,7 @@ fn source(message: Encoded, our_nick: &Nick) -> Option<Source> {
}
}

fn datetime(message: &Encoded) -> DateTime<Utc> {
fn server_time(message: &Encoded) -> DateTime<Utc> {
message
.tags
.as_ref()
Expand Down Expand Up @@ -325,20 +327,6 @@ impl Limit {
pub fn bottom() -> Self {
Self::Bottom(Self::DEFAULT_COUNT)
}

fn value_mut(&mut self) -> Option<&mut usize> {
match self {
Limit::Top(i) => Some(i),
Limit::Bottom(i) => Some(i),
Limit::Since(_) => None,
}
}

pub fn increase(&mut self, n: usize) {
if let Some(value) = self.value_mut() {
*value += n;
}
}
}

fn is_action(text: &str) -> bool {
Expand All @@ -359,6 +347,7 @@ pub(crate) mod broadcast {
use chrono::Utc;

use super::{Direction, Message, Sender, Source};
use crate::time::Posix;
use crate::user::Nick;

fn expand(
Expand All @@ -383,7 +372,8 @@ pub(crate) mod broadcast {
) -> impl Iterator<Item = Message> {
fn message(source: Source) -> Message {
Message {
datetime: Utc::now(),
received_at: Posix::now(),
server_time: Utc::now(),
direction: Direction::Received,
source,
text: " ∙ connection to server lost".into(),
Expand All @@ -399,7 +389,8 @@ pub(crate) mod broadcast {
) -> impl Iterator<Item = Message> {
fn message(source: Source) -> Message {
Message {
datetime: Utc::now(),
received_at: Posix::now(),
server_time: Utc::now(),
direction: Direction::Received,
source,
text: " ∙ connection to server restored".into(),
Expand Down
8 changes: 0 additions & 8 deletions data/src/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,3 @@ impl Posix {
.map(|datetime| DateTime::from_utc(datetime, Utc))
}
}

impl From<DateTime<Utc>> for Posix {
fn from(datetime: DateTime<Utc>) -> Self {
let seconds = datetime.timestamp();

Self::from_seconds(seconds as u64)
}
}
2 changes: 1 addition & 1 deletion src/buffer/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub fn view<'a>(
data::message::Sender::User(user) => {
let timestamp =
settings
.format_timestamp(&message.datetime)
.format_timestamp(&message.server_time)
.map(|timestamp| {
selectable_text(timestamp).style(theme::Text::Alpha04)
});
Expand Down
2 changes: 1 addition & 1 deletion src/buffer/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub fn view<'a>(
message::Sender::User(user) => {
let timestamp =
settings
.format_timestamp(&message.datetime)
.format_timestamp(&message.server_time)
.map(|timestamp| {
selectable_text(timestamp).style(theme::Text::Alpha04)
});
Expand Down
62 changes: 38 additions & 24 deletions src/buffer/scroll_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub enum Message {
count: usize,
remaining: bool,
oldest: time::Posix,
status: Status,
viewport: scrollable::Viewport,
},
}
Expand Down Expand Up @@ -42,8 +43,9 @@ pub fn view<'a>(
let remaining = count < total;
let oldest = messages
.first()
.map(|message| message.datetime.into())
.map(|message| message.received_at)
.unwrap_or_else(time::Posix::now);
let status = state.status;

scrollable(
Column::with_children(messages.into_iter().filter_map(format).collect())
Expand All @@ -52,14 +54,15 @@ pub fn view<'a>(
)
.vertical_scroll(
scrollable::Properties::default()
.alignment(state.status.alignment())
.alignment(status.alignment())
.width(5)
.scroller_width(5),
)
.on_scroll(move |viewport| Message::Scrolled {
count,
remaining,
oldest,
status,
viewport,
})
.id(state.scrollable.clone())
Expand Down Expand Up @@ -94,13 +97,31 @@ impl State {
count,
remaining,
oldest,
status: old_status,
viewport,
} => {
let old_status = self.status;
let relative_offset = viewport.relative_offset().y;

match old_status {
_ if old_status.is_loading_zone(relative_offset) && remaining => {
Status::Loading(anchor) => {
self.status = Status::Unlocked(anchor);

if matches!(anchor, Anchor::Bottom) {
self.limit = Limit::Since(oldest);
}
// Top anchor can get stuck in loading state at
// end of scrollable.
else if old_status.is_end(relative_offset) {
if remaining {
self.status = Status::Loading(Anchor::Top);
self.limit = Limit::Top(count + Limit::DEFAULT_STEP);
} else {
self.status = Status::Idle(Anchor::Bottom);
self.limit = Limit::bottom();
}
}
}
_ if old_status.is_end(relative_offset) && remaining => {
match old_status.anchor() {
Anchor::Top => {
self.status = Status::Loading(Anchor::Top);
Expand All @@ -112,22 +133,15 @@ impl State {
}
}
}
_ if old_status.is_bottom_of_scrollable(relative_offset) => {
_ if old_status.is_bottom(relative_offset) => {
self.status = Status::Idle(Anchor::Bottom);
self.limit = Limit::bottom();
}
_ if old_status.is_top_of_scrollable(relative_offset) => {
_ if old_status.is_top(relative_offset) => {
self.status = Status::Idle(Anchor::Top);
self.limit = Limit::top();
}
Status::Idle(anchor) if !old_status.is_idle_zone(relative_offset) => {
self.status = Status::Unlocked(anchor);

if matches!(anchor, Anchor::Bottom) {
self.limit = Limit::Since(oldest);
}
}
Status::Loading(anchor) => {
Status::Idle(anchor) if !old_status.is_start(relative_offset) => {
self.status = Status::Unlocked(anchor);

if matches!(anchor, Anchor::Bottom) {
Expand Down Expand Up @@ -166,14 +180,14 @@ impl State {
}

#[derive(Debug, Clone, Copy)]
enum Status {
pub enum Status {
Idle(Anchor),
Unlocked(Anchor),
Loading(Anchor),
}

#[derive(Debug, Clone, Copy)]
enum Anchor {
pub enum Anchor {
Top,
Bottom,
}
Expand Down Expand Up @@ -201,28 +215,28 @@ impl Status {
}
}

fn is_loading_zone(self, relative_offset: f32) -> bool {
fn is_end(self, relative_offset: f32) -> bool {
match self.anchor() {
Anchor::Top => self.is_bottom_of_scrollable(relative_offset),
Anchor::Bottom => self.is_top_of_scrollable(relative_offset),
Anchor::Top => self.is_bottom(relative_offset),
Anchor::Bottom => self.is_top(relative_offset),
}
}

fn is_idle_zone(self, relative_offset: f32) -> bool {
fn is_start(self, relative_offset: f32) -> bool {
match self.anchor() {
Anchor::Top => self.is_top_of_scrollable(relative_offset),
Anchor::Bottom => self.is_bottom_of_scrollable(relative_offset),
Anchor::Top => self.is_top(relative_offset),
Anchor::Bottom => self.is_bottom(relative_offset),
}
}

fn is_top_of_scrollable(self, relative_offset: f32) -> bool {
fn is_top(self, relative_offset: f32) -> bool {
match self.alignment() {
scrollable::Alignment::Start => relative_offset == 0.0,
scrollable::Alignment::End => relative_offset == 1.0,
}
}

fn is_bottom_of_scrollable(self, relative_offset: f32) -> bool {
fn is_bottom(self, relative_offset: f32) -> bool {
match self.alignment() {
scrollable::Alignment::Start => relative_offset == 1.0,
scrollable::Alignment::End => relative_offset == 0.0,
Expand Down
2 changes: 1 addition & 1 deletion src/buffer/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub fn view<'a>(
history,
|message| {
let timestamp = settings
.format_timestamp(&message.datetime)
.format_timestamp(&message.server_time)
.map(|timestamp| selectable_text(timestamp).style(theme::Text::Alpha04));
let message = selectable_text(&message.text).style(theme::Text::Alpha04);

Expand Down
1 change: 0 additions & 1 deletion src/font.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::sync::OnceLock;

use data::Config;

use iced::font::{self, Error};
use iced::Command;

Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ use std::env;
use data::config::{self, Config};
use iced::widget::container;
use iced::{executor, Application, Command, Length, Subscription};
use screen::{dashboard, help, welcome};

use self::event::{events, Event};
pub use self::theme::Theme;
use self::widget::Element;
use screen::{dashboard, help, welcome};

pub fn main() -> iced::Result {
let mut args = env::args();
Expand Down

0 comments on commit 7a8aba5

Please sign in to comment.