feat: Implement image caching for game covers, enhance frontend game list item layout, add Factorio to the game list, and ignore the cache directory.
This commit is contained in:
parent
04e21708b2
commit
70e1a555c0
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
target/
|
target/
|
||||||
|
cache/
|
||||||
@ -123,6 +123,26 @@ async fn get_game_thumbnail(
|
|||||||
title: &str,
|
title: &str,
|
||||||
game_list: &rocket::State<Mutex<Vec<Game>>>,
|
game_list: &rocket::State<Mutex<Vec<Game>>>,
|
||||||
) -> Option<(rocket::http::ContentType, Vec<u8>)> {
|
) -> Option<(rocket::http::ContentType, Vec<u8>)> {
|
||||||
|
// 1. Sanitize title for filename
|
||||||
|
let safe_title: String = title
|
||||||
|
.chars()
|
||||||
|
.map(|c| if c.is_alphanumeric() { c } else { '_' })
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let cache_dir = "cache";
|
||||||
|
let _ = std::fs::create_dir_all(cache_dir);
|
||||||
|
let cache_path_bin = format!("{}/{}.bin", cache_dir, safe_title);
|
||||||
|
let cache_path_type = format!("{}/{}.type", cache_dir, safe_title);
|
||||||
|
|
||||||
|
// 2. Check cache
|
||||||
|
if let (Ok(bytes), Ok(type_str)) = (
|
||||||
|
std::fs::read(&cache_path_bin),
|
||||||
|
std::fs::read_to_string(&cache_path_type),
|
||||||
|
) && let Some(ct) = rocket::http::ContentType::parse_flexible(&type_str)
|
||||||
|
{
|
||||||
|
return Some((ct, bytes));
|
||||||
|
}
|
||||||
|
|
||||||
let games = game_list.lock().await;
|
let games = game_list.lock().await;
|
||||||
let game = games.iter().find(|g| g.title == title)?;
|
let game = games.iter().find(|g| g.title == title)?;
|
||||||
|
|
||||||
@ -174,6 +194,11 @@ async fn get_game_thumbnail(
|
|||||||
.and_then(rocket::http::ContentType::parse_flexible)
|
.and_then(rocket::http::ContentType::parse_flexible)
|
||||||
.unwrap_or(rocket::http::ContentType::Binary);
|
.unwrap_or(rocket::http::ContentType::Binary);
|
||||||
let bytes = resp.bytes().await.ok()?.to_vec();
|
let bytes = resp.bytes().await.ok()?.to_vec();
|
||||||
|
|
||||||
|
// 3. Write to cache
|
||||||
|
let _ = std::fs::write(&cache_path_bin, &bytes);
|
||||||
|
let _ = std::fs::write(&cache_path_type, content_type.to_string());
|
||||||
|
|
||||||
Some((content_type, bytes))
|
Some((content_type, bytes))
|
||||||
}
|
}
|
||||||
Err(_) => None,
|
Err(_) => None,
|
||||||
|
|||||||
@ -125,20 +125,26 @@ export function GameFilter() {
|
|||||||
style={{
|
style={{
|
||||||
textDecoration: "none",
|
textDecoration: "none",
|
||||||
color: "inherit",
|
color: "inherit",
|
||||||
display: "block",
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<strong>{game}</strong>
|
<div>
|
||||||
<div
|
<strong>{game}</strong>
|
||||||
style={{
|
<div
|
||||||
fontSize: "0.9em",
|
style={{
|
||||||
color: "#4caf50",
|
fontSize: "0.9em",
|
||||||
marginTop: "0.5rem",
|
color: "#4caf50",
|
||||||
}}
|
marginTop: "0.5rem",
|
||||||
>
|
}}
|
||||||
✓ All {selectedPeople.size} selected would play
|
>
|
||||||
|
✓ All {selectedPeople.size} selected would play
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style={{ width: "100px", marginLeft: "1rem" }}>
|
||||||
|
<GameImage game={game} />
|
||||||
</div>
|
</div>
|
||||||
<GameImage game={game} />
|
|
||||||
</Link>
|
</Link>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@ -45,6 +45,10 @@
|
|||||||
{
|
{
|
||||||
"title": " Asylum Life",
|
"title": " Asylum Life",
|
||||||
"would_play": true
|
"would_play": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Factorio",
|
||||||
|
"would_play": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user