mirror of
https://github.com/storytold/designcraft.git
synced 2026-11-06 02:21:51 +00:00
Integration: #802 the start screen and Open Recent menu look recent files up on disk at most every 3 s, not every frame
This commit is contained in:
1 parent
548d700b9f
commit
acb63fe198
2 files changed
+52
-4
No files matched your search
@@ -739,8 +739,9 @@ fn recent_files(app: &mut DesignApp, ui: &mut egui::Ui) {
|
|||||||
let mut open = None;
|
let mut open = None;
|
||||||
ui.horizontal_wrapped(|ui| {
|
ui.horizontal_wrapped(|ui| {
|
||||||
for (i, path) in rows {
|
for (i, path) in rows {
|
||||||
let modified = std::fs::metadata(&path).ok().filter(|m| m.is_file()).map(|m| m.modified().ok());
|
let stat = recent_file_stat(ui.ctx(), &path);
|
||||||
let there = modified.is_some();
|
let there = stat.exists;
|
||||||
|
let modified = there.then_some(stat.modified);
|
||||||
let (cr, resp) = ui.allocate_exact_size(vec2(140.0, 170.0), Sense::click());
|
let (cr, resp) = ui.allocate_exact_size(vec2(140.0, 170.0), Sense::click());
|
||||||
let resp = resp.on_hover_text(&path);
|
let resp = resp.on_hover_text(&path);
|
||||||
ui.painter().rect_filled(cr, 6.0, if resp.hovered() { t.hover } else { t.panel });
|
ui.painter().rect_filled(cr, 6.0, if resp.hovered() { t.hover } else { t.panel });
|
||||||
@@ -778,7 +779,38 @@ fn recent_files(app: &mut DesignApp, ui: &mut egui::Ui) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The texture of a recent file's saved first-page picture, read again when the file changes.
|
/// How often a recent file is looked up on disk again, in ms: the start screen and the Open Recent
|
||||||
|
/// menu draw every frame and must not touch the file system each time.
|
||||||
|
const RECENT_STAT_MS: f64 = 3000.0;
|
||||||
|
|
||||||
|
/// A recent file as last seen on disk.
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub(crate) struct RecentStat {
|
||||||
|
pub exists: bool,
|
||||||
|
pub modified: Option<std::time::SystemTime>,
|
||||||
|
checked: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whether recent file `path` is there and when it last changed, looked up again at most every
|
||||||
|
/// [`RECENT_STAT_MS`].
|
||||||
|
pub(crate) fn recent_file_stat(ctx: &egui::Context, path: &str) -> RecentStat {
|
||||||
|
recent_file_stat_at(ctx, path, crate::now_ms())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn recent_file_stat_at(ctx: &egui::Context, path: &str, now: f64) -> RecentStat {
|
||||||
|
let key = egui::Id::new(("recent_stat", path));
|
||||||
|
if let Some(st) = ctx.data(|d| d.get_temp::<RecentStat>(key))
|
||||||
|
&& (0.0..RECENT_STAT_MS).contains(&(now - st.checked))
|
||||||
|
{
|
||||||
|
return st;
|
||||||
|
}
|
||||||
|
let meta = std::fs::metadata(path).ok().filter(std::fs::Metadata::is_file);
|
||||||
|
let st = RecentStat { exists: meta.is_some(), modified: meta.and_then(|m| m.modified().ok()), checked: now };
|
||||||
|
ctx.data_mut(|d| d.insert_temp(key, st.clone()));
|
||||||
|
st
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The texture of a recent file's saved first-page picture, decoded once per file version.
|
||||||
fn recent_preview_texture(ctx: &egui::Context, path: &str, modified: Option<std::time::SystemTime>) -> Option<egui::TextureHandle> {
|
fn recent_preview_texture(ctx: &egui::Context, path: &str, modified: Option<std::time::SystemTime>) -> Option<egui::TextureHandle> {
|
||||||
type Cached = (Option<std::time::SystemTime>, Option<egui::TextureHandle>);
|
type Cached = (Option<std::time::SystemTime>, Option<egui::TextureHandle>);
|
||||||
let key = egui::Id::new(("recent_preview", path));
|
let key = egui::Id::new(("recent_preview", path));
|
||||||
@@ -858,6 +890,22 @@ mod tests {
|
|||||||
const LAST_CONTROL: &str = "Align bottom edges";
|
const LAST_CONTROL: &str = "Align bottom edges";
|
||||||
const FIRST_CONTROL: &str = "Rotate 90° Counterclockwise";
|
const FIRST_CONTROL: &str = "Rotate 90° Counterclockwise";
|
||||||
|
|
||||||
|
/// The start screen and Open Recent menu look a recent file up on disk at most every few
|
||||||
|
/// seconds, not every frame.
|
||||||
|
#[test]
|
||||||
|
fn recent_files_are_looked_up_on_disk_every_few_seconds() {
|
||||||
|
let dir = tempfile::tempdir().unwrap();
|
||||||
|
let path = dir.path().join("a.designcraft");
|
||||||
|
std::fs::write(&path, b"x").unwrap();
|
||||||
|
let path = path.to_string_lossy().to_string();
|
||||||
|
let ctx = egui::Context::default();
|
||||||
|
let first = super::recent_file_stat_at(&ctx, &path, 10_000.0);
|
||||||
|
assert!(first.exists && first.modified.is_some());
|
||||||
|
std::fs::remove_file(&path).unwrap();
|
||||||
|
assert_eq!(super::recent_file_stat_at(&ctx, &path, 10_000.0 + super::RECENT_STAT_MS - 1.0), first, "cached");
|
||||||
|
assert!(!super::recent_file_stat_at(&ctx, &path, 10_000.0 + super::RECENT_STAT_MS).exists, "looked up again");
|
||||||
|
}
|
||||||
|
|
||||||
fn app() -> crate::DesignApp {
|
fn app() -> crate::DesignApp {
|
||||||
let mut app = crate::DesignApp::new(designcraft_engine::Session::new(), crate::Services::default());
|
let mut app = crate::DesignApp::new(designcraft_engine::Session::new(), crate::Services::default());
|
||||||
app.ui.control_bar = true;
|
app.ui.control_bar = true;
|
||||||
|
|||||||
@@ -2615,7 +2615,7 @@ fn recent_menu_items(app: &mut DesignApp, ui: &mut egui::Ui) {
|
|||||||
Item::Cmd { label, id, params, .. } => {
|
Item::Cmd { label, id, params, .. } => {
|
||||||
let path = params["index"].as_u64().and_then(|i| app.session.prefs.recent_files.get(i as usize)).cloned().unwrap_or_default();
|
let path = params["index"].as_u64().and_then(|i| app.session.prefs.recent_files.get(i as usize)).cloned().unwrap_or_default();
|
||||||
let mut text = egui::RichText::new(label);
|
let mut text = egui::RichText::new(label);
|
||||||
if !std::path::Path::new(&path).is_file() {
|
if !crate::chrome::recent_file_stat(ui.ctx(), &path).exists {
|
||||||
text = text.color(dim);
|
text = text.color(dim);
|
||||||
}
|
}
|
||||||
if ui.button(crate::rtl::widget(ui, text)).on_hover_text(&path).clicked() {
|
if ui.button(crate::rtl::widget(ui, text)).on_hover_text(&path).clicked() {
|
||||||
|
|||||||
Reference in new issue
Block a user