Use provided Nyancat GIF in WebUI
Rust / Clippy, Rustfmt, Tests (push) Waiting to run
Rust / Linux-x64 build (push) Blocked by required conditions
Rust / GitHub release (push) Blocked by required conditions

This commit is contained in:
2026-06-10 00:18:26 +02:00
parent 0d56082963
commit e4c161ce45
2 changed files with 22 additions and 268 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

+22 -268
View File
@@ -34,6 +34,7 @@ use tracing::{error, info, warn};
const DISPLAY_WIDTH: u32 = 960;
const DISPLAY_HEIGHT: u32 = 376;
const SYSTEM_FRAME_NAME: &str = "System Specs";
const NYAN_CAT_GIF: &[u8] = include_bytes!("../assets/nyan-cat.gif");
#[derive(Parser, Debug)]
#[command(author, version, about)]
@@ -231,6 +232,7 @@ async fn main() -> Result<()> {
.route("/api/panels/activate", post(api_activate))
.route("/api/panels/disable", post(api_disable))
.route("/api/images/delete", post(api_delete))
.route("/api/assets/nyan-cat.gif", get(api_nyan_cat))
.route("/api/images/{name}", get(api_image))
.layer(DefaultBodyLimit::max(64 * 1024 * 1024))
.with_state(state);
@@ -527,6 +529,19 @@ async fn api_image(
response
}
async fn api_nyan_cat() -> Response {
let mut response = Response::new(Body::from(NYAN_CAT_GIF));
response.headers_mut().insert(
header::CONTENT_TYPE,
HeaderValue::from_static("image/gif"),
);
response.headers_mut().insert(
header::CACHE_CONTROL,
HeaderValue::from_static("public, max-age=86400"),
);
response
}
async fn build_state_response(state: &AppState) -> Result<StateResponse> {
let monitor = load_monitor_json(state).await?;
let setup = monitor
@@ -1413,247 +1428,23 @@ const INDEX_HTML: &str = r##"<!DOCTYPE html>
position: fixed;
right: 24px;
bottom: 18px;
width: 248px;
height: 108px;
width: 260px;
pointer-events: none;
z-index: 30;
opacity: 0.96;
opacity: 0.98;
filter: drop-shadow(0 12px 24px rgba(0, 0, 0, 0.35));
image-rendering: pixelated;
}
.nyan-space {
position: absolute;
inset: 0;
}
.nyan-star {
position: absolute;
width: 6px;
height: 6px;
background: #f8fafc;
box-shadow:
6px 0 0 #f8fafc,
0 6px 0 #f8fafc,
6px 6px 0 #f8fafc;
animation: nyan-star 1.2s steps(2) infinite;
}
.nyan-star.s1 { left: 10px; top: 16px; transform: scale(0.8); }
.nyan-star.s2 { left: 48px; top: 72px; transform: scale(0.6); animation-delay: 0.25s; }
.nyan-star.s3 { left: 168px; top: 8px; transform: scale(0.7); animation-delay: 0.55s; }
.nyan-rainbow {
position: absolute;
left: 14px;
top: 37px;
width: 126px;
height: 30px;
display: grid;
grid-template-rows: repeat(6, 1fr);
gap: 1px;
animation: nyan-rainbow 0.55s steps(2) infinite;
}
.nyan-rainbow .stripe {
border-radius: 0;
}
.nyan-rainbow .s1 { background: #ff4d6d; }
.nyan-rainbow .s2 { background: #ff8c42; }
.nyan-rainbow .s3 { background: #ffd93d; }
.nyan-rainbow .s4 { background: #51cf66; }
.nyan-rainbow .s5 { background: #339af0; }
.nyan-rainbow .s6 { background: #845ef7; }
.nyan-cat {
position: absolute;
right: 0;
top: 18px;
width: 124px;
height: 76px;
animation: nyan-float 0.55s steps(2) infinite;
}
.nyan-cat::before,
.nyan-cat::after {
content: "";
position: absolute;
left: 0;
width: 18px;
height: 8px;
background: #9ca3af;
border: 3px solid #111827;
border-right: none;
box-sizing: border-box;
}
.nyan-cat::before {
top: 25px;
animation: nyan-tail 0.35s steps(2) infinite;
}
.nyan-cat::after {
top: 37px;
width: 12px;
}
.nyan-body {
position: absolute;
left: 20px;
top: 14px;
width: 56px;
height: 42px;
background: #d4a574;
border: 3px solid #111827;
box-sizing: border-box;
}
.nyan-icing {
position: absolute;
inset: 6px;
background: #f6a5c0;
border: 3px solid #111827;
box-sizing: border-box;
}
.nyan-icing .sprinkle {
position: absolute;
width: 4px;
height: 4px;
}
.nyan-icing .sp1 { left: 8px; top: 8px; background: #f8fafc; }
.nyan-icing .sp2 { left: 24px; top: 10px; background: #fde047; }
.nyan-icing .sp3 { left: 38px; top: 8px; background: #60a5fa; }
.nyan-icing .sp4 { left: 14px; top: 20px; background: #fb7185; }
.nyan-icing .sp5 { left: 32px; top: 22px; background: #4ade80; }
.nyan-icing .sp6 { left: 42px; top: 18px; background: #f8fafc; }
.nyan-head {
position: absolute;
left: 72px;
top: 8px;
width: 36px;
height: 30px;
background: #9ca3af;
border: 3px solid #111827;
box-sizing: border-box;
}
.nyan-head::before,
.nyan-head::after {
content: "";
position: absolute;
top: -10px;
width: 0;
height: 0;
border-left: 7px solid transparent;
border-right: 7px solid transparent;
border-bottom: 12px solid #111827;
}
.nyan-head::before { left: 1px; }
.nyan-head::after { right: 1px; }
.nyan-head .face {
position: absolute;
inset: 3px;
background: #b8bec7;
}
.nyan-head .eye,
.nyan-head .blush {
position: absolute;
.nyan-wrap img {
display: block;
}
.nyan-head .eye {
top: 9px;
width: 4px;
height: 4px;
background: #0f172a;
}
.nyan-head .e1 { left: 7px; }
.nyan-head .e2 { right: 7px; }
.nyan-head .blush {
top: 16px;
width: 6px;
height: 3px;
background: #ff8fab;
}
.nyan-head .b1 { left: 2px; }
.nyan-head .b2 { right: 2px; }
.nyan-head .nose {
position: absolute;
left: 13px;
top: 14px;
width: 4px;
height: 4px;
background: #0f172a;
}
.nyan-head .mouth {
position: absolute;
left: 10px;
top: 19px;
width: 10px;
height: 4px;
border-bottom: 3px solid #0f172a;
box-sizing: border-box;
}
.nyan-leg {
position: absolute;
width: 8px;
height: 12px;
background: #9ca3af;
border: 3px solid #111827;
border-top: none;
box-sizing: border-box;
animation: nyan-legs 0.35s steps(2) infinite;
}
.nyan-leg.l1 { left: 30px; top: 56px; }
.nyan-leg.l2 { left: 48px; top: 56px; animation-delay: 0.12s; }
.nyan-leg.l3 { left: 82px; top: 44px; }
.nyan-leg.l4 { left: 98px; top: 44px; animation-delay: 0.12s; }
@keyframes nyan-float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-3px); }
}
@keyframes nyan-rainbow {
0%, 100% { transform: translateX(0); opacity: 1; }
50% { transform: translateX(-8px); opacity: 0.96; }
}
@keyframes nyan-tail {
0%, 100% { transform: translateY(0) scaleX(1); }
50% { transform: translateY(-2px) scaleX(0.88); }
}
@keyframes nyan-legs {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(2px); }
}
@keyframes nyan-star {
0%, 100% { opacity: 0.35; transform: translateX(0) scale(1); }
50% { opacity: 1; transform: translateX(-4px) scale(1.1); }
width: 100%;
height: auto;
}
@media (max-width: 900px) {
.nyan-wrap {
right: 14px;
bottom: 12px;
transform: scale(0.78);
transform-origin: bottom right;
width: 180px;
}
}
</style>
@@ -1716,44 +1507,7 @@ const INDEX_HTML: &str = r##"<!DOCTYPE html>
</main>
<div id="toast" class="toast"></div>
<div class="nyan-wrap" aria-hidden="true">
<div class="nyan-space">
<span class="nyan-star s1"></span>
<span class="nyan-star s2"></span>
<span class="nyan-star s3"></span>
</div>
<div class="nyan-rainbow">
<span class="stripe s1"></span>
<span class="stripe s2"></span>
<span class="stripe s3"></span>
<span class="stripe s4"></span>
<span class="stripe s5"></span>
<span class="stripe s6"></span>
</div>
<div class="nyan-cat">
<div class="nyan-body">
<div class="nyan-icing">
<span class="sprinkle sp1"></span>
<span class="sprinkle sp2"></span>
<span class="sprinkle sp3"></span>
<span class="sprinkle sp4"></span>
<span class="sprinkle sp5"></span>
<span class="sprinkle sp6"></span>
</div>
</div>
<div class="nyan-head">
<div class="face"></div>
<span class="eye e1"></span>
<span class="eye e2"></span>
<span class="blush b1"></span>
<span class="blush b2"></span>
<span class="nose"></span>
<span class="mouth"></span>
</div>
<div class="nyan-leg l1"></div>
<div class="nyan-leg l2"></div>
<div class="nyan-leg l3"></div>
<div class="nyan-leg l4"></div>
</div>
<img src="/api/assets/nyan-cat.gif" alt="Nyancat">
</div>
<script>