mirror of
https://github.com/encounter/decomp.dev.git
synced 2026-07-10 03:18:48 -07:00
Better graph performance, light theme fixes
This commit is contained in:
Generated
+3
-2
@@ -2354,8 +2354,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "objdiff-core"
|
||||
version = "2.0.0-beta.6"
|
||||
source = "git+https://github.com/encounter/objdiff?tag=v2.0.0-beta.6#e1ae369d172240091735c7063f85d54c5052ac62"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f5a4a551c6f2c06663c06c4b8f5829e7ed4e12c15e10f644d76021f2287bf5a8"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"byteorder",
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ mime = "0.3"
|
||||
minijinja = { version = "2.2", features = ["loader", "json"] }
|
||||
minijinja-autoreload = "2.2"
|
||||
moka = { version = "0.12", features = ["future"] }
|
||||
objdiff-core = { git = "https://github.com/encounter/objdiff", tag = "v2.0.0-beta.6", features = ["bindings"] }
|
||||
objdiff-core = { version = "2.0", features = ["bindings"] }
|
||||
#objdiff-core = { path = "../objdiff/objdiff-core", features = ["bindings"] }
|
||||
octocrab = "0.39"
|
||||
oxc = { version = "0.27", features = ["codegen", "minifier", "transformer", "semantic"] }
|
||||
|
||||
+10
-5
@@ -97,12 +97,16 @@ $breakpoints: (
|
||||
:root:not([data-theme=dark]) {
|
||||
--pico-code-kbd-color: #000;
|
||||
--pico-code-kbd-background-color: #fff;
|
||||
--progress-background-color: #{$slate-100};
|
||||
--progress-stripe-color: rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
@mixin pico-theme-dark {
|
||||
--pico-background-color: #181c25;
|
||||
--pico-code-kbd-color: #fff;
|
||||
--pico-code-kbd-background-color: #333;
|
||||
--progress-background-color: #{$slate-800};
|
||||
--progress-stripe-color: rgba(255, 255, 255, 0.15);
|
||||
}
|
||||
|
||||
[data-theme=dark] {
|
||||
@@ -163,17 +167,17 @@ $progress-height: 2rem;
|
||||
height: $progress-height;
|
||||
overflow: hidden;
|
||||
border-radius: var(--pico-border-radius);
|
||||
background-color: $slate-800;
|
||||
background-color: var(--progress-background-color);
|
||||
|
||||
.progress-section.striped {
|
||||
//animation: progress-stripes 1s linear infinite;
|
||||
background-image: linear-gradient(
|
||||
45deg,
|
||||
rgba(255, 255, 255, .15) 25%,
|
||||
var(--progress-stripe-color) 25%,
|
||||
transparent 25%,
|
||||
transparent 50%,
|
||||
rgba(255, 255, 255, .15) 50%,
|
||||
rgba(255, 255, 255, .15) 75%,
|
||||
var(--progress-stripe-color) 50%,
|
||||
var(--progress-stripe-color) 75%,
|
||||
transparent 75%,
|
||||
transparent);
|
||||
background-size: calc(1.25rem) calc(1.25rem);
|
||||
@@ -190,7 +194,7 @@ $progress-height: 2rem;
|
||||
}
|
||||
|
||||
.progress-section:nth-child(3) {
|
||||
background-color: $slate-800;
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,4 +263,5 @@ $unit-size: 0.75rem;
|
||||
--font-size: 0.875rem;
|
||||
--font-family: var(--pico-font-family);
|
||||
--tooltip-background: var(--pico-tooltip-background-color);
|
||||
--tooltip-color: var(--pico-tooltip-color);
|
||||
}
|
||||
|
||||
+43
-17
@@ -28,6 +28,7 @@ const drawTooltip = (ctx: CanvasRenderingContext2D, unit: Unit, width: number, h
|
||||
const fontSize = style.getPropertyValue('--font-size') || '16px';
|
||||
const fontFamily = style.getPropertyValue('--font-family') || 'sans-serif';
|
||||
const tooltipBackground = style.getPropertyValue('--tooltip-background') || "#fff"
|
||||
const tooltipColor = style.getPropertyValue('--tooltip-color') || "#000"
|
||||
ctx.font = `${fontWeight} ${fontSize} ${fontFamily}`;
|
||||
ctx.textBaseline = "middle";
|
||||
|
||||
@@ -65,18 +66,34 @@ const drawTooltip = (ctx: CanvasRenderingContext2D, unit: Unit, width: number, h
|
||||
ctx.lineTo(ax - margin, y - margin);
|
||||
}
|
||||
ctx.fill();
|
||||
ctx.fillStyle = "#000";
|
||||
ctx.fillStyle = tooltipColor;
|
||||
ctx.fillText(text, bx + PADDING_W, by + bh / 2);
|
||||
};
|
||||
|
||||
let hovered = null;
|
||||
let dirty = false;
|
||||
let isTouch = false;
|
||||
let cachedCanvas: HTMLCanvasElement = null;
|
||||
|
||||
const setup = (ctx: CanvasRenderingContext2D, ratio: number, width: number, height: number) => {
|
||||
ctx.setTransform(ratio, 0, 0, ratio, 0, 0); // Scale to device pixel ratio
|
||||
ctx.clearRect(0, 0, width, height);
|
||||
ctx.lineWidth = 1;
|
||||
ctx.strokeStyle = "#000";
|
||||
}
|
||||
|
||||
const drawUnits = (ctx: CanvasRenderingContext2D, units: Unit[], width: number, height: number) => {
|
||||
for (const unit of units) {
|
||||
const {x, y, w, h} = unitBounds(unit, width, height);
|
||||
ctx.fillStyle = unit.color;
|
||||
ctx.beginPath();
|
||||
ctx.rect(x, y, w, h);
|
||||
ctx.fill();
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
const draw = (canvas: HTMLCanvasElement, units: Unit[]) => {
|
||||
if (!canvas.getContext) {
|
||||
return;
|
||||
}
|
||||
const {width, height} = canvas.getBoundingClientRect();
|
||||
const ratio = window.devicePixelRatio;
|
||||
const renderWidth = width * ratio;
|
||||
@@ -91,19 +108,25 @@ const draw = (canvas: HTMLCanvasElement, units: Unit[]) => {
|
||||
canvas.width = renderWidth;
|
||||
canvas.height = renderHeight;
|
||||
}
|
||||
const ctx = canvas.getContext("2d");
|
||||
ctx.setTransform(ratio, 0, 0, ratio, 0, 0); // Scale to device pixel ratio
|
||||
ctx.clearRect(0, 0, width, height);
|
||||
ctx.lineWidth = 1;
|
||||
ctx.strokeStyle = "#000";
|
||||
for (const unit of units) {
|
||||
const {x, y, w, h} = unitBounds(unit, width, height);
|
||||
ctx.fillStyle = unit.color;
|
||||
ctx.beginPath();
|
||||
ctx.rect(x, y, w, h);
|
||||
ctx.fill();
|
||||
ctx.stroke();
|
||||
// Update cached canvas if needed
|
||||
if (cachedCanvas.width !== renderWidth || cachedCanvas.height !== renderHeight) {
|
||||
cachedCanvas.width = renderWidth;
|
||||
cachedCanvas.height = renderHeight;
|
||||
const cachedCtx = cachedCanvas.getContext("2d");
|
||||
if (!cachedCtx) {
|
||||
return;
|
||||
}
|
||||
setup(cachedCtx, ratio, width, height);
|
||||
drawUnits(cachedCtx, units, width, height);
|
||||
}
|
||||
const ctx = canvas.getContext("2d");
|
||||
if (!ctx) {
|
||||
return;
|
||||
}
|
||||
// Use 1:1 scale for rendering cached canvas
|
||||
setup(ctx, 1, renderWidth, renderHeight);
|
||||
ctx.drawImage(cachedCanvas, 0, 0);
|
||||
ctx.scale(ratio, ratio); // Restore device scale
|
||||
if (hovered) {
|
||||
const {x, y, w, h} = unitBounds(hovered, width, height);
|
||||
ctx.lineWidth = 2;
|
||||
@@ -115,9 +138,12 @@ const draw = (canvas: HTMLCanvasElement, units: Unit[]) => {
|
||||
|
||||
const drawGraph = (id: string, units: Unit[]) => {
|
||||
const canvas = document.getElementById(id) as HTMLCanvasElement;
|
||||
if (!canvas) {
|
||||
if (!canvas || !canvas.getContext) {
|
||||
return;
|
||||
}
|
||||
if (!cachedCanvas) {
|
||||
cachedCanvas = document.createElement("canvas");
|
||||
}
|
||||
const queueDraw = () => requestAnimationFrame(() => draw(canvas, units));
|
||||
const resizeObserver = new ResizeObserver(queueDraw);
|
||||
resizeObserver.observe(canvas);
|
||||
|
||||
+3
-2
@@ -1,4 +1,4 @@
|
||||
use std::{ffi::OsStr, path::PathBuf};
|
||||
use std::ffi::OsStr;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use axum::{
|
||||
@@ -8,9 +8,10 @@ use axum::{
|
||||
};
|
||||
|
||||
use super::AppError;
|
||||
use crate::util::join_normalized;
|
||||
|
||||
pub async fn get_css(Path(filename): Path<String>) -> Result<Response, AppError> {
|
||||
let mut path = PathBuf::from(format!("css/{filename}"));
|
||||
let mut path = join_normalized("css", &filename);
|
||||
if path.extension() != Some(OsStr::new("css")) {
|
||||
return Err(AppError::Status(StatusCode::NOT_FOUND));
|
||||
}
|
||||
|
||||
+4
-4
@@ -1,4 +1,4 @@
|
||||
use std::{ffi::OsStr, path::PathBuf};
|
||||
use std::ffi::OsStr;
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use axum::{
|
||||
@@ -16,10 +16,10 @@ use oxc::{
|
||||
transformer::{EnvOptions, Targets, TransformOptions, Transformer},
|
||||
};
|
||||
|
||||
use crate::handlers::AppError;
|
||||
use crate::{handlers::AppError, util::join_normalized};
|
||||
|
||||
pub async fn get_js(Path(filename): Path<String>) -> Result<Response, AppError> {
|
||||
let mut path = PathBuf::from(format!("js/{filename}"));
|
||||
let mut path = join_normalized("js", &filename);
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
enum ResponseType {
|
||||
Js,
|
||||
@@ -82,7 +82,7 @@ fn transform(
|
||||
.into_symbol_table_and_scope_tree();
|
||||
|
||||
let transform_options = TransformOptions::from_preset_env(&EnvOptions {
|
||||
targets: Targets::from_query("es2020"),
|
||||
targets: Targets::from_query("defaults"),
|
||||
..EnvOptions::default()
|
||||
})
|
||||
.map_err(|v| anyhow!("{}", v.first().unwrap()))?;
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::{iter, str::FromStr, time::Instant};
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use axum::{
|
||||
extract::{ Path, Query, State},
|
||||
extract::{Path, Query, State},
|
||||
http::{header, HeaderMap, StatusCode, Uri},
|
||||
response::{Html, IntoResponse, Response},
|
||||
Json,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use url::Url;
|
||||
|
||||
pub trait UrlExt {
|
||||
@@ -48,3 +50,10 @@ impl UrlExt for Url {
|
||||
#[inline]
|
||||
fn path_and_query(&self) -> &str { &self[url::Position::BeforePath..] }
|
||||
}
|
||||
|
||||
/// Join two paths, only including the normal components.
|
||||
pub fn join_normalized(base: impl AsRef<Path>, path: impl AsRef<Path>) -> PathBuf {
|
||||
let mut out = base.as_ref().to_path_buf();
|
||||
out.extend(path.as_ref().components().filter(|v| matches!(v, std::path::Component::Normal(_))));
|
||||
out
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
data-tooltip="{{ measures.fuzzy_match_percent | round(2) }}% fuzzy match"></div>
|
||||
</div>
|
||||
<small class="muted">
|
||||
<span title="{{ project.timestamp | date }}">Last updated: {{ project.timestamp | timeago }}</span>
|
||||
<span title="{{ project.timestamp | date }}">Updated {{ project.timestamp | timeago }}</span>
|
||||
in commit <a href="https://github.com/{{ project.owner }}/{{ project.repo }}/commit/{{ project.commit }}"
|
||||
target="_blank">{{ project.commit[:7] }}</a>
|
||||
</small>
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
<meta name="darkreader-lock">
|
||||
<meta name="description" content="Decompilation progress report for {{ project_name }}{% if current_category.id != 'all' %} ({{ current_category.name }}){% endif %}">
|
||||
<title>{{ project_short_name }}{% if current_category.id != "all" %} ({{ current_category.name }}){% endif %} • Progress Report</title>
|
||||
<link rel="stylesheet" href="/css/main.min.css?3">
|
||||
<link rel="stylesheet" href="/css/main.min.css?4">
|
||||
<script src="https://unpkg.com/htmx.org@2.0.2"
|
||||
integrity="sha384-Y7hw+L/jvKeWIRRkqWYfPcvVxHzVzn5REgzbawhxAuQGwX1XWe70vji+VSeHOThJ"
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="/js/graph.min.js?5"></script>
|
||||
<script src="/js/graph.min.js?6"></script>
|
||||
<meta property="og:title" content="{{ project_short_name }}{% if current_category.id != 'all' %} ({{ current_category.name }}){% endif %} is {{ measures.matched_code_percent | round(2) }}% decompiled">
|
||||
<meta property="og:description" content="Decompilation progress report for {{ project_name }}{% if current_category.id != 'all' %} ({{ current_category.name }}){% endif %}">
|
||||
<meta property="og:image" content="{{ image_url | safe }}">
|
||||
|
||||
Reference in New Issue
Block a user