Merge pull request #824 from joshuamegnauth54/issue-775-respect-military-time-opt
Respect military time config from time applet
This commit is contained in:
commit
e7e608a3fe
4 changed files with 125 additions and 64 deletions
40
src/app.rs
40
src/app.rs
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright 2023 System76 <info@system76.com>
|
// Copyright 2023 System76 <info@system76.com>
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
|
use cosmic::iced::mouse::Event::CursorMoved;
|
||||||
#[cfg(feature = "wayland")]
|
#[cfg(feature = "wayland")]
|
||||||
use cosmic::iced::{
|
use cosmic::iced::{
|
||||||
event::wayland::{Event as WaylandEvent, OutputEvent, OverlapNotifyEvent},
|
event::wayland::{Event as WaylandEvent, OutputEvent, OverlapNotifyEvent},
|
||||||
|
|
@ -55,7 +56,6 @@ use std::{
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
time::{self, Instant},
|
time::{self, Instant},
|
||||||
};
|
};
|
||||||
use cosmic::iced::mouse::Event::CursorMoved;
|
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
use trash::TrashItem;
|
use trash::TrashItem;
|
||||||
#[cfg(feature = "wayland")]
|
#[cfg(feature = "wayland")]
|
||||||
|
|
@ -552,7 +552,7 @@ pub struct App {
|
||||||
tab_dnd_hover: Option<(Entity, Instant)>,
|
tab_dnd_hover: Option<(Entity, Instant)>,
|
||||||
nav_drag_id: DragId,
|
nav_drag_id: DragId,
|
||||||
tab_drag_id: DragId,
|
tab_drag_id: DragId,
|
||||||
auto_scroll_speed: Option<i16>
|
auto_scroll_speed: Option<i16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
|
|
@ -1458,9 +1458,14 @@ impl App {
|
||||||
|
|
||||||
let mut children = Vec::with_capacity(1);
|
let mut children = Vec::with_capacity(1);
|
||||||
let entity = entity_opt.unwrap_or_else(|| self.tab_model.active());
|
let entity = entity_opt.unwrap_or_else(|| self.tab_model.active());
|
||||||
|
let military_time = self.config.tab.military_time;
|
||||||
match kind {
|
match kind {
|
||||||
PreviewKind::Custom(PreviewItem(item)) => {
|
PreviewKind::Custom(PreviewItem(item)) => {
|
||||||
children.push(item.preview_view(Some(&self.mime_app_cache), IconSizes::default()));
|
children.push(item.preview_view(
|
||||||
|
Some(&self.mime_app_cache),
|
||||||
|
IconSizes::default(),
|
||||||
|
military_time,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
PreviewKind::Location(location) => {
|
PreviewKind::Location(location) => {
|
||||||
if let Some(tab) = self.tab_model.data::<Tab>(entity) {
|
if let Some(tab) = self.tab_model.data::<Tab>(entity) {
|
||||||
|
|
@ -1470,6 +1475,7 @@ impl App {
|
||||||
children.push(item.preview_view(
|
children.push(item.preview_view(
|
||||||
Some(&self.mime_app_cache),
|
Some(&self.mime_app_cache),
|
||||||
tab.config.icon_sizes,
|
tab.config.icon_sizes,
|
||||||
|
military_time,
|
||||||
));
|
));
|
||||||
// Only show one property view to avoid issues like hangs when generating
|
// Only show one property view to avoid issues like hangs when generating
|
||||||
// preview images on thousands of files
|
// preview images on thousands of files
|
||||||
|
|
@ -1487,6 +1493,7 @@ impl App {
|
||||||
children.push(item.preview_view(
|
children.push(item.preview_view(
|
||||||
Some(&self.mime_app_cache),
|
Some(&self.mime_app_cache),
|
||||||
tab.config.icon_sizes,
|
tab.config.icon_sizes,
|
||||||
|
military_time,
|
||||||
));
|
));
|
||||||
// Only show one property view to avoid issues like hangs when generating
|
// Only show one property view to avoid issues like hangs when generating
|
||||||
// preview images on thousands of files
|
// preview images on thousands of files
|
||||||
|
|
@ -1498,6 +1505,7 @@ impl App {
|
||||||
children.push(item.preview_view(
|
children.push(item.preview_view(
|
||||||
Some(&self.mime_app_cache),
|
Some(&self.mime_app_cache),
|
||||||
tab.config.icon_sizes,
|
tab.config.icon_sizes,
|
||||||
|
military_time,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1934,7 +1942,10 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
Message::CursorMoved(pos) => {
|
Message::CursorMoved(pos) => {
|
||||||
let entity = self.tab_model.active();
|
let entity = self.tab_model.active();
|
||||||
return self.update(Message::TabMessage(Some(entity), tab::Message::CursorMoved(pos)));
|
return self.update(Message::TabMessage(
|
||||||
|
Some(entity),
|
||||||
|
tab::Message::CursorMoved(pos),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
Message::Cut(entity_opt) => {
|
Message::Cut(entity_opt) => {
|
||||||
let paths = self.selected_paths(entity_opt);
|
let paths = self.selected_paths(entity_opt);
|
||||||
|
|
@ -2800,7 +2811,10 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
Message::ScrollTab(scroll_speed) => {
|
Message::ScrollTab(scroll_speed) => {
|
||||||
let entity = self.tab_model.active();
|
let entity = self.tab_model.active();
|
||||||
return self.update(Message::TabMessage(Some(entity), tab::Message::ScrollTab((scroll_speed as f32) / 10.0)));
|
return self.update(Message::TabMessage(
|
||||||
|
Some(entity),
|
||||||
|
tab::Message::ScrollTab((scroll_speed as f32) / 10.0),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
Message::SearchActivate => {
|
Message::SearchActivate => {
|
||||||
return if self.search_get().is_none() {
|
return if self.search_get().is_none() {
|
||||||
|
|
@ -2944,11 +2958,9 @@ impl Application for App {
|
||||||
// further resolution isn't necessary
|
// further resolution isn't necessary
|
||||||
if let Some(scroll_speed_float) = scroll_speed {
|
if let Some(scroll_speed_float) = scroll_speed {
|
||||||
self.auto_scroll_speed = Some((scroll_speed_float * 10.0) as i16);
|
self.auto_scroll_speed = Some((scroll_speed_float * 10.0) as i16);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
self.auto_scroll_speed = None;
|
self.auto_scroll_speed = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
tab::Command::ChangeLocation(tab_title, tab_path, selection_paths) => {
|
tab::Command::ChangeLocation(tab_title, tab_path, selection_paths) => {
|
||||||
self.activate_nav_model_location(&tab_path);
|
self.activate_nav_model_location(&tab_path);
|
||||||
|
|
@ -4160,15 +4172,16 @@ impl Application for App {
|
||||||
apply_to_all,
|
apply_to_all,
|
||||||
tx,
|
tx,
|
||||||
} => {
|
} => {
|
||||||
|
let military_time = self.config.tab.military_time;
|
||||||
let dialog = widget::dialog()
|
let dialog = widget::dialog()
|
||||||
.title(fl!("replace-title", filename = to.name.as_str()))
|
.title(fl!("replace-title", filename = to.name.as_str()))
|
||||||
.body(fl!("replace-warning-operation"))
|
.body(fl!("replace-warning-operation"))
|
||||||
.control(
|
.control(
|
||||||
to.replace_view(fl!("original-file"), IconSizes::default())
|
to.replace_view(fl!("original-file"), IconSizes::default(), military_time)
|
||||||
.map(|x| Message::TabMessage(None, x)),
|
.map(|x| Message::TabMessage(None, x)),
|
||||||
)
|
)
|
||||||
.control(
|
.control(
|
||||||
from.replace_view(fl!("replace-with"), IconSizes::default())
|
from.replace_view(fl!("replace-with"), IconSizes::default(), military_time)
|
||||||
.map(|x| Message::TabMessage(None, x)),
|
.map(|x| Message::TabMessage(None, x)),
|
||||||
)
|
)
|
||||||
.primary_action(widget::button::suggested(fl!("replace")).on_press(
|
.primary_action(widget::button::suggested(fl!("replace")).on_press(
|
||||||
|
|
@ -4561,7 +4574,7 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
Event::Mouse(CursorMoved { position: pos }) => Some(Message::CursorMoved(pos)),
|
Event::Mouse(CursorMoved { position: pos }) => Some(Message::CursorMoved(pos)),
|
||||||
_ => None,
|
_ => None,
|
||||||
}),
|
}),
|
||||||
|
|
@ -4735,8 +4748,9 @@ impl Application for App {
|
||||||
|
|
||||||
if let Some(scroll_speed) = self.auto_scroll_speed {
|
if let Some(scroll_speed) = self.auto_scroll_speed {
|
||||||
subscriptions.push(
|
subscriptions.push(
|
||||||
iced::time::every(time::Duration::from_millis(10)).with(scroll_speed)
|
iced::time::every(time::Duration::from_millis(10))
|
||||||
.map(|(scroll_speed, _)| Message::ScrollTab(scroll_speed))
|
.with(scroll_speed)
|
||||||
|
.map(|(scroll_speed, _)| Message::ScrollTab(scroll_speed)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
use std::{any::TypeId, num::NonZeroU16, path::PathBuf};
|
use std::{any::TypeId, num::NonZeroU16, path::PathBuf};
|
||||||
|
|
||||||
use cosmic::{
|
use cosmic::{
|
||||||
cosmic_config::{self, cosmic_config_derive::CosmicConfigEntry, CosmicConfigEntry},
|
cosmic_config::{self, cosmic_config_derive::CosmicConfigEntry, ConfigGet, CosmicConfigEntry},
|
||||||
iced::Subscription,
|
iced::Subscription,
|
||||||
theme, Application,
|
theme, Application,
|
||||||
};
|
};
|
||||||
|
|
@ -197,6 +197,10 @@ pub struct TabConfig {
|
||||||
pub show_hidden: bool,
|
pub show_hidden: bool,
|
||||||
/// Icon zoom
|
/// Icon zoom
|
||||||
pub icon_sizes: IconSizes,
|
pub icon_sizes: IconSizes,
|
||||||
|
#[serde(skip, default = "military_time_enabled")]
|
||||||
|
/// 24 hour clock; this is neither serialized nor deserialized because we use the user's global
|
||||||
|
/// preference rather than save it
|
||||||
|
pub military_time: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for TabConfig {
|
impl Default for TabConfig {
|
||||||
|
|
@ -206,6 +210,22 @@ impl Default for TabConfig {
|
||||||
folders_first: true,
|
folders_first: true,
|
||||||
show_hidden: false,
|
show_hidden: false,
|
||||||
icon_sizes: IconSizes::default(),
|
icon_sizes: IconSizes::default(),
|
||||||
|
military_time: military_time_enabled(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return whether the user enabled military time via the Time applet.
|
||||||
|
fn military_time_enabled() -> bool {
|
||||||
|
// Borrowed from COSMIC Greeter
|
||||||
|
match cosmic_config::Config::new("com.system76.CosmicAppletTime", 1) {
|
||||||
|
Ok(config_handler) => config_handler.get("military_time").unwrap_or_default(),
|
||||||
|
Err(err) => {
|
||||||
|
log::error!(
|
||||||
|
"failed to create CosmicAppletTime config handler: {:?}",
|
||||||
|
err
|
||||||
|
);
|
||||||
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -472,16 +472,17 @@ impl App {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn preview<'a>(&'a self, kind: &'a PreviewKind) -> Element<'a, tab::Message> {
|
fn preview<'a>(&'a self, kind: &'a PreviewKind) -> Element<'a, tab::Message> {
|
||||||
|
let military_time = self.tab.config.military_time;
|
||||||
let mut children = Vec::with_capacity(1);
|
let mut children = Vec::with_capacity(1);
|
||||||
match kind {
|
match kind {
|
||||||
PreviewKind::Custom(PreviewItem(item)) => {
|
PreviewKind::Custom(PreviewItem(item)) => {
|
||||||
children.push(item.preview_view(None, IconSizes::default()));
|
children.push(item.preview_view(None, IconSizes::default(), military_time));
|
||||||
}
|
}
|
||||||
PreviewKind::Location(location) => {
|
PreviewKind::Location(location) => {
|
||||||
if let Some(items) = self.tab.items_opt() {
|
if let Some(items) = self.tab.items_opt() {
|
||||||
for item in items.iter() {
|
for item in items.iter() {
|
||||||
if item.location_opt.as_ref() == Some(location) {
|
if item.location_opt.as_ref() == Some(location) {
|
||||||
children.push(item.preview_view(None, self.tab.config.icon_sizes));
|
children.push(item.preview_view(None, self.tab.config.icon_sizes, military_time));
|
||||||
// Only show one property view to avoid issues like hangs when generating
|
// Only show one property view to avoid issues like hangs when generating
|
||||||
// preview images on thousands of files
|
// preview images on thousands of files
|
||||||
break;
|
break;
|
||||||
|
|
@ -493,7 +494,7 @@ impl App {
|
||||||
if let Some(items) = self.tab.items_opt() {
|
if let Some(items) = self.tab.items_opt() {
|
||||||
for item in items.iter() {
|
for item in items.iter() {
|
||||||
if item.selected {
|
if item.selected {
|
||||||
children.push(item.preview_view(None, self.tab.config.icon_sizes));
|
children.push(item.preview_view(None, self.tab.config.icon_sizes, military_time));
|
||||||
// Only show one property view to avoid issues like hangs when generating
|
// Only show one property view to avoid issues like hangs when generating
|
||||||
// preview images on thousands of files
|
// preview images on thousands of files
|
||||||
break;
|
break;
|
||||||
|
|
@ -501,7 +502,7 @@ impl App {
|
||||||
}
|
}
|
||||||
if children.is_empty() {
|
if children.is_empty() {
|
||||||
if let Some(item) = &self.tab.parent_item_opt {
|
if let Some(item) = &self.tab.parent_item_opt {
|
||||||
children.push(item.preview_view(None, self.tab.config.icon_sizes));
|
children.push(item.preview_view(None, self.tab.config.icon_sizes, military_time));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
118
src/tab.rs
118
src/tab.rs
|
|
@ -87,7 +87,9 @@ const DRAG_SCROLL_DISTANCE: f32 = 15.0;
|
||||||
|
|
||||||
//TODO: adjust for locales?
|
//TODO: adjust for locales?
|
||||||
const DATE_TIME_FORMAT: &str = "%b %-d, %-Y, %-I:%M %p";
|
const DATE_TIME_FORMAT: &str = "%b %-d, %-Y, %-I:%M %p";
|
||||||
|
const DATE_TIME_FORMAT_MILITARY: &str = "%b %-d, %-Y, %-H:%M %p";
|
||||||
const TIME_FORMAT: &str = "%-I:%M %p";
|
const TIME_FORMAT: &str = "%-I:%M %p";
|
||||||
|
const TIME_FORMAT_MILITARY: &str = "%-H:%M %p";
|
||||||
static SPECIAL_DIRS: Lazy<HashMap<PathBuf, &'static str>> = Lazy::new(|| {
|
static SPECIAL_DIRS: Lazy<HashMap<PathBuf, &'static str>> = Lazy::new(|| {
|
||||||
let mut special_dirs = HashMap::new();
|
let mut special_dirs = HashMap::new();
|
||||||
if let Some(dir) = dirs::document_dir() {
|
if let Some(dir) = dirs::document_dir() {
|
||||||
|
|
@ -380,10 +382,13 @@ fn format_permissions(metadata: &Metadata, owner: PermissionOwner) -> String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FormatTime(SystemTime);
|
struct FormatTime {
|
||||||
|
pub time: SystemTime,
|
||||||
|
pub military_time: bool,
|
||||||
|
}
|
||||||
|
|
||||||
impl FormatTime {
|
impl FormatTime {
|
||||||
fn from_secs(secs: i64) -> Option<Self> {
|
fn from_secs(secs: i64, military_time: bool) -> Option<Self> {
|
||||||
// This looks convoluted because we need to ensure the units match up
|
// This looks convoluted because we need to ensure the units match up
|
||||||
let secs: u64 = secs.try_into().ok()?;
|
let secs: u64 = secs.try_into().ok()?;
|
||||||
let now = SystemTime::now();
|
let now = SystemTime::now();
|
||||||
|
|
@ -393,31 +398,51 @@ impl FormatTime {
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|now_secs| now_secs.checked_sub(secs))
|
.and_then(|now_secs| now_secs.checked_sub(secs))
|
||||||
.map(Duration::from_secs)?;
|
.map(Duration::from_secs)?;
|
||||||
now.checked_add(filetime_diff).map(FormatTime)
|
now.checked_add(filetime_diff).map(|time| Self {
|
||||||
|
time,
|
||||||
|
military_time,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for FormatTime {
|
impl Display for FormatTime {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let date_time = chrono::DateTime::<chrono::Local>::from(self.0);
|
let date_time = chrono::DateTime::<chrono::Local>::from(self.time);
|
||||||
let now = chrono::Local::now();
|
let now = chrono::Local::now();
|
||||||
if date_time.date_naive() == now.date_naive() {
|
if date_time.date_naive() == now.date_naive() {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"{}, {}",
|
"{}, {}",
|
||||||
fl!("today"),
|
fl!("today"),
|
||||||
date_time.format_localized(TIME_FORMAT, *LANGUAGE_CHRONO)
|
date_time.format_localized(
|
||||||
|
if self.military_time {
|
||||||
|
TIME_FORMAT_MILITARY
|
||||||
|
} else {
|
||||||
|
TIME_FORMAT
|
||||||
|
},
|
||||||
|
*LANGUAGE_CHRONO
|
||||||
|
)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
date_time
|
date_time
|
||||||
.format_localized(DATE_TIME_FORMAT, *LANGUAGE_CHRONO)
|
.format_localized(
|
||||||
|
if self.military_time {
|
||||||
|
DATE_TIME_FORMAT_MILITARY
|
||||||
|
} else {
|
||||||
|
DATE_TIME_FORMAT
|
||||||
|
},
|
||||||
|
*LANGUAGE_CHRONO,
|
||||||
|
)
|
||||||
.fmt(f)
|
.fmt(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_time(time: SystemTime) -> FormatTime {
|
const fn format_time(time: SystemTime, military_time: bool) -> FormatTime {
|
||||||
FormatTime(time)
|
FormatTime {
|
||||||
|
time,
|
||||||
|
military_time,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
|
@ -1497,6 +1522,7 @@ impl Item {
|
||||||
&'a self,
|
&'a self,
|
||||||
mime_app_cache_opt: Option<&'a mime_app::MimeAppCache>,
|
mime_app_cache_opt: Option<&'a mime_app::MimeAppCache>,
|
||||||
sizes: IconSizes,
|
sizes: IconSizes,
|
||||||
|
military_time: bool,
|
||||||
) -> Element<'a, Message> {
|
) -> Element<'a, Message> {
|
||||||
let cosmic_theme::Spacing {
|
let cosmic_theme::Spacing {
|
||||||
space_xxxs,
|
space_xxxs,
|
||||||
|
|
@ -1558,21 +1584,21 @@ impl Item {
|
||||||
if let Ok(time) = metadata.created() {
|
if let Ok(time) = metadata.created() {
|
||||||
details = details.push(widget::text::body(fl!(
|
details = details.push(widget::text::body(fl!(
|
||||||
"item-created",
|
"item-created",
|
||||||
created = format_time(time).to_string()
|
created = format_time(time, military_time).to_string()
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(time) = metadata.modified() {
|
if let Ok(time) = metadata.modified() {
|
||||||
details = details.push(widget::text::body(fl!(
|
details = details.push(widget::text::body(fl!(
|
||||||
"item-modified",
|
"item-modified",
|
||||||
modified = format_time(time).to_string()
|
modified = format_time(time, military_time).to_string()
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(time) = metadata.accessed() {
|
if let Ok(time) = metadata.accessed() {
|
||||||
details = details.push(widget::text::body(fl!(
|
details = details.push(widget::text::body(fl!(
|
||||||
"item-accessed",
|
"item-accessed",
|
||||||
accessed = format_time(time).to_string()
|
accessed = format_time(time, military_time).to_string()
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1638,7 +1664,12 @@ impl Item {
|
||||||
column.into()
|
column.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn replace_view(&self, heading: String, sizes: IconSizes) -> Element<'_, Message> {
|
pub fn replace_view(
|
||||||
|
&self,
|
||||||
|
heading: String,
|
||||||
|
sizes: IconSizes,
|
||||||
|
military_time: bool,
|
||||||
|
) -> Element<'_, Message> {
|
||||||
let cosmic_theme::Spacing { space_xxxs, .. } = theme::active().cosmic().spacing;
|
let cosmic_theme::Spacing { space_xxxs, .. } = theme::active().cosmic().spacing;
|
||||||
|
|
||||||
let mut row = widget::row().spacing(space_xxxs);
|
let mut row = widget::row().spacing(space_xxxs);
|
||||||
|
|
@ -1662,7 +1693,7 @@ impl Item {
|
||||||
if let Ok(time) = metadata.modified() {
|
if let Ok(time) = metadata.modified() {
|
||||||
column = column.push(widget::text::body(format!(
|
column = column.push(widget::text::body(format!(
|
||||||
"Last modified: {}",
|
"Last modified: {}",
|
||||||
format_time(time)
|
format_time(time, military_time)
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1873,7 +1904,7 @@ impl Tab {
|
||||||
viewport_rect: None,
|
viewport_rect: None,
|
||||||
virtual_cursor_offset: None,
|
virtual_cursor_offset: None,
|
||||||
last_scroll_position: None,
|
last_scroll_position: None,
|
||||||
last_scroll_offset: None
|
last_scroll_offset: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2228,7 +2259,7 @@ impl Tab {
|
||||||
// if our mouse is above the scrollable viewport, we want to scroll up
|
// if our mouse is above the scrollable viewport, we want to scroll up
|
||||||
let drag_start_point = Point {
|
let drag_start_point = Point {
|
||||||
x: viewport.x,
|
x: viewport.x,
|
||||||
y: viewport.y
|
y: viewport.y,
|
||||||
};
|
};
|
||||||
// diff_y should be NEGATIVE here when close to y=0 (above the MouseArea)
|
// diff_y should be NEGATIVE here when close to y=0 (above the MouseArea)
|
||||||
// and positive when below the viewport
|
// and positive when below the viewport
|
||||||
|
|
@ -2241,39 +2272,30 @@ impl Tab {
|
||||||
0.0
|
0.0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
commands.push(Command::AutoScroll(Some(scroll_y)));
|
commands.push(Command::AutoScroll(Some(scroll_y)));
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if let Some(last_scroll_offset) = self.last_scroll_offset {
|
if let Some(last_scroll_offset) = self.last_scroll_offset {
|
||||||
if let Some(last_scroll_position) = self.last_scroll_position {
|
if let Some(last_scroll_position) = self.last_scroll_position {
|
||||||
self.virtual_cursor_offset = Some(Point {
|
self.virtual_cursor_offset = Some(Point {
|
||||||
x: 0.0,
|
x: 0.0,
|
||||||
y: (pos.y - last_scroll_position.y + last_scroll_offset.y)
|
y: (pos.y - last_scroll_position.y
|
||||||
|
+ last_scroll_offset.y),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
}
|
|
||||||
else {
|
|
||||||
if let Some(last_scroll_position) = self.last_scroll_position {
|
if let Some(last_scroll_position) = self.last_scroll_position {
|
||||||
self.virtual_cursor_offset = Some(Point {
|
self.virtual_cursor_offset = Some(Point {
|
||||||
x: 0.0,
|
x: 0.0,
|
||||||
y: (pos.y - last_scroll_position.y)
|
y: (pos.y - last_scroll_position.y),
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
self.virtual_cursor_offset = Some(Point {
|
|
||||||
x: 0.0,
|
|
||||||
y: 0.0
|
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
self.virtual_cursor_offset = Some(Point { x: 0.0, y: 0.0 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
commands.push(Command::AutoScroll(None));
|
commands.push(Command::AutoScroll(None));
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// reset our virtual cursor offset when we're back in bounds
|
// reset our virtual cursor offset when we're back in bounds
|
||||||
self.virtual_cursor_offset = None;
|
self.virtual_cursor_offset = None;
|
||||||
self.last_scroll_position = Some(pos);
|
self.last_scroll_position = Some(pos);
|
||||||
|
|
@ -2292,13 +2314,11 @@ impl Tab {
|
||||||
x: viewport.x - scroll_pos.x,
|
x: viewport.x - scroll_pos.x,
|
||||||
y: viewport.y - scroll_pos.y,
|
y: viewport.y - scroll_pos.y,
|
||||||
width: viewport.width,
|
width: viewport.width,
|
||||||
height: viewport.height
|
height: viewport.height,
|
||||||
});
|
});
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
self.viewport_rect = Some(viewport);
|
self.viewport_rect = Some(viewport);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Message::DragEnd(_) => {
|
Message::DragEnd(_) => {
|
||||||
self.clicked = None;
|
self.clicked = None;
|
||||||
|
|
@ -2947,7 +2967,7 @@ impl Tab {
|
||||||
Message::ScrollTab(scroll_speed) => {
|
Message::ScrollTab(scroll_speed) => {
|
||||||
let mut new_offset = Point {
|
let mut new_offset = Point {
|
||||||
x: 0.0,
|
x: 0.0,
|
||||||
y: scroll_speed
|
y: scroll_speed,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(virtual_cursor_offset) = self.virtual_cursor_offset {
|
if let Some(virtual_cursor_offset) = self.virtual_cursor_offset {
|
||||||
|
|
@ -2961,17 +2981,20 @@ impl Tab {
|
||||||
if let Some(global_cursor_position) = self.global_cursor_position {
|
if let Some(global_cursor_position) = self.global_cursor_position {
|
||||||
new_offset.x = global_cursor_position.x - last_scroll_position.x;
|
new_offset.x = global_cursor_position.x - last_scroll_position.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.virtual_cursor_offset = Some(new_offset);
|
self.virtual_cursor_offset = Some(new_offset);
|
||||||
self.last_scroll_offset = Some(new_offset);
|
self.last_scroll_offset = Some(new_offset);
|
||||||
|
|
||||||
commands.push(Command::Iced(
|
commands.push(Command::Iced(
|
||||||
scrollable::scroll_by(self.scrollable_id.clone(), AbsoluteOffset {
|
scrollable::scroll_by(
|
||||||
x: 0.0,
|
self.scrollable_id.clone(),
|
||||||
y: scroll_speed
|
AbsoluteOffset {
|
||||||
}).into(),
|
x: 0.0,
|
||||||
|
y: scroll_speed,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Message::ScrollToFocus => {
|
Message::ScrollToFocus => {
|
||||||
|
|
@ -4311,14 +4334,17 @@ impl Tab {
|
||||||
y += 1;
|
y += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let military_time = self.config.military_time;
|
||||||
let modified_text = match &item.metadata {
|
let modified_text = match &item.metadata {
|
||||||
ItemMetadata::Path { metadata, .. } => match metadata.modified() {
|
ItemMetadata::Path { metadata, .. } => match metadata.modified() {
|
||||||
Ok(time) => format_time(time).to_string(),
|
Ok(time) => format_time(time, military_time).to_string(),
|
||||||
Err(_) => String::new(),
|
Err(_) => String::new(),
|
||||||
},
|
},
|
||||||
ItemMetadata::Trash { entry, .. } => FormatTime::from_secs(entry.time_deleted)
|
ItemMetadata::Trash { entry, .. } => {
|
||||||
.map(|t| t.to_string())
|
FormatTime::from_secs(entry.time_deleted, military_time)
|
||||||
.unwrap_or_default(),
|
.map(|t| t.to_string())
|
||||||
|
.unwrap_or_default()
|
||||||
|
}
|
||||||
_ => String::new(),
|
_ => String::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue