mirror of
https://github.com/pmret/website.git
synced 2024-11-08 12:12:27 +01:00
Merge branch 'party' into main
This commit is contained in:
commit
7052cb5b08
@ -1,10 +1,6 @@
|
||||
import React, { useState, useEffect } from "react"
|
||||
import React, { useState, useEffect, useMemo } from "react"
|
||||
import { createPortal } from "react-dom"
|
||||
import { Area, XAxis, YAxis, AreaChart, CartesianGrid, Tooltip, ResponsiveContainer } from "recharts"
|
||||
import { scalePow } from "d3-scale"
|
||||
|
||||
const scale = scalePow()
|
||||
.exponent(30)
|
||||
import { Area, XAxis, YAxis, AreaChart, CartesianGrid, Tooltip, ResponsiveContainer, Text } from "recharts"
|
||||
|
||||
const csvVersions = {
|
||||
"1": {
|
||||
@ -67,17 +63,6 @@ export default function ProgressPane({ captionPortal, nonce, color, version }) {
|
||||
</div>
|
||||
}
|
||||
|
||||
const monthDates = []
|
||||
{
|
||||
let date = new Date(2020, 3, 1)
|
||||
while (date < Date.now()) {
|
||||
monthDates.push(date / 1000)
|
||||
|
||||
date = new Date(date) // clone
|
||||
date.setMonth(date.getMonth() + 1)
|
||||
}
|
||||
}
|
||||
|
||||
function DataView({ data, captionPortal, nonce, color }) {
|
||||
const latest = data[data.length - 1]
|
||||
const oldest = data[0]
|
||||
@ -85,6 +70,10 @@ function DataView({ data, captionPortal, nonce, color }) {
|
||||
|
||||
const [selectedEntry, setSelectedEntry] = useState(latest)
|
||||
|
||||
if (!selectedEntry && latest) {
|
||||
setSelectedEntry(latest)
|
||||
}
|
||||
|
||||
function renderTooltip(tip) {
|
||||
const entry = data.find(row => row.timestamp === tip.label)
|
||||
|
||||
@ -97,13 +86,31 @@ function DataView({ data, captionPortal, nonce, color }) {
|
||||
|
||||
const maxPercent = latest ? Math.ceil(latest.percentBytes / 25) * 25 : 25
|
||||
|
||||
const monthDates = useMemo(() => {
|
||||
const monthDates = []
|
||||
|
||||
if (oldest) {
|
||||
let date = new Date(oldest.timestamp * 1000)
|
||||
date.setDate(0)
|
||||
|
||||
while (date < Date.now()) {
|
||||
monthDates.push(date / 1000)
|
||||
|
||||
date = new Date(date) // clone
|
||||
date.setMonth(date.getMonth() + 1)
|
||||
}
|
||||
|
||||
return monthDates
|
||||
}
|
||||
}, [oldest && oldest.timestamp])
|
||||
|
||||
return <>
|
||||
<div className="shadow-box flex-grow">
|
||||
<div className="shadow-box-inner" style={{ paddingRight: ".7em", paddingTop: ".7em", "--text-outline": "transparent", background: "#e2e1d8" }}>
|
||||
<div className="progress-chart">
|
||||
<ResponsiveContainer>
|
||||
<AreaChart data={data}>
|
||||
<XAxis dataKey="timestamp" type="number" scale={scale} domain={["dataMin", Date.now()/1000]} ticks={monthDates} tickFormatter={formatTimestampMonth} interval={0}/>
|
||||
<XAxis dataKey="timestamp" type="number" scale="linear" domain={["dataMin", Date.now()/1000]} ticks={monthDates} tickFormatter={formatTimestampMonth}/>
|
||||
<YAxis type="number" unit="%" domain={[0, maxPercent]} tickCount={maxPercent / 5 + 1}/>
|
||||
|
||||
<CartesianGrid stroke="#d9d0c9"/>
|
||||
@ -122,6 +129,9 @@ function DataView({ data, captionPortal, nonce, color }) {
|
||||
</AreaChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
{latest && <div className="progress-percent" title="Latest matched percentage">
|
||||
{formatPercent(latest.percentBytes)}
|
||||
</div>}
|
||||
</div>
|
||||
|
||||
<button className={"shadow-box-title " + color}>
|
||||
@ -144,15 +154,16 @@ function formatTimestamp(timestamp, options={}) {
|
||||
|
||||
function formatTimestampMonth(timestamp) {
|
||||
const date = new Date(timestamp * 1000)
|
||||
const [day, month, year] = new Intl.DateTimeFormat("en-GB", {
|
||||
dateStyle: "medium",
|
||||
}).format(date).split(" ")
|
||||
|
||||
if (month === "Jan") {
|
||||
return year
|
||||
if (date.getMonth() == 0) {
|
||||
return date.getFullYear().toString()
|
||||
} else {
|
||||
return new Intl.DateTimeFormat([], { month: "short" }).format(date)
|
||||
}
|
||||
}
|
||||
|
||||
return month
|
||||
function formatPercent(alpha) {
|
||||
return Math.round(alpha * 100) / 100 + "%"
|
||||
}
|
||||
|
||||
function EntryInfo({ entry, isLatest }) {
|
||||
@ -170,17 +181,12 @@ function EntryInfo({ entry, isLatest }) {
|
||||
<a href={`https://github.com/pmret/papermario/commit/${entry.commit}`}>
|
||||
{entry.commit.substr(0, 8)}
|
||||
</a>
|
||||
{isLatest && " (latest)"}
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td width="200">Matched</td>
|
||||
<td className="thin align-right">
|
||||
{Math.round(entry.percentBytes * 100) / 100}% bytes
|
||||
({entry.matchingFuncs}/{entry.totalFuncs} functions)
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{isLatest && " (latest commit)"}
|
||||
|
||||
<br/>
|
||||
|
||||
<span className="thin">
|
||||
Matched {formatPercent(entry.percentBytes)} bytes ({entry.matchingFuncs}/{entry.totalFuncs} functions)
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
|
@ -7,7 +7,8 @@ html {
|
||||
--dark: #313131;
|
||||
--light: #d6d6ce;
|
||||
|
||||
font-size: 32px;
|
||||
font-size: 21px;
|
||||
font-size: clamp(21px, 1.5vw, 32px);
|
||||
font-family: "Paper Mario Dialog Redesigned", sans-serif;
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
@ -32,6 +33,13 @@ body {
|
||||
background-repeat: repeat-x;
|
||||
background-size: contain;
|
||||
animation: clouds linear 30s infinite normal;
|
||||
|
||||
/* centre children */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
padding: 1vw 1vh;
|
||||
}
|
||||
|
||||
@keyframes clouds {
|
||||
@ -55,13 +63,13 @@ p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
a:any-link {
|
||||
a:any-link:not(.tab) {
|
||||
color: #3796ff;
|
||||
--text-outline: #d3e5f9;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
button {
|
||||
button, .tab {
|
||||
all: unset;
|
||||
|
||||
border-radius: 100em;
|
||||
@ -80,9 +88,11 @@ button {
|
||||
|
||||
user-select: none;
|
||||
text-align: center;
|
||||
|
||||
color: var(--light);
|
||||
}
|
||||
|
||||
button.red {
|
||||
button.red, .tab.red {
|
||||
border-top-color: #f04e54;
|
||||
border-left-color: #f04e54;
|
||||
background: #b4313e;
|
||||
@ -90,7 +100,7 @@ button.red {
|
||||
border-right-color: #7f1729;
|
||||
}
|
||||
|
||||
button.yellow {
|
||||
button.yellow, .tab.yellow {
|
||||
border-top-color: #f0c74e;
|
||||
border-left-color: #f0c74e;
|
||||
background: #b48b31;
|
||||
@ -98,7 +108,7 @@ button.yellow {
|
||||
border-right-color: #7f5617;
|
||||
}
|
||||
|
||||
button.blurple {
|
||||
button.blurple, .tab.blurple {
|
||||
border-top-color: #98a9e2;
|
||||
border-left-color: #98a9e2;
|
||||
background: #7289da;
|
||||
@ -106,7 +116,7 @@ button.blurple {
|
||||
border-right-color: #4E5D94;
|
||||
}
|
||||
|
||||
button.github {
|
||||
button.github, .tab.github {
|
||||
border-top-color: #554e4e;
|
||||
border-left-color: #554e4e;
|
||||
background: #322f2f;
|
||||
@ -114,7 +124,7 @@ button.github {
|
||||
border-right-color: #171515;
|
||||
}
|
||||
|
||||
button.teal {
|
||||
button.teal, .tab.teal {
|
||||
border-top-color: #22eec9;
|
||||
border-left-color: #22eec9;
|
||||
background: #14a98e;
|
||||
@ -122,7 +132,7 @@ button.teal {
|
||||
border-right-color: #076d5a;
|
||||
}
|
||||
|
||||
button.green {
|
||||
button.green, .tab.green {
|
||||
border-top-color: #68ff51;
|
||||
border-left-color: #68ff51;
|
||||
background: #47b836;
|
||||
@ -130,11 +140,11 @@ button.green {
|
||||
border-right-color: #2a791e;
|
||||
}
|
||||
|
||||
button.inactive {
|
||||
button.inactive, .tab.inactive {
|
||||
filter: brightness(0.6);
|
||||
}
|
||||
|
||||
button:hover {
|
||||
button:hover, .tab:hover {
|
||||
filter: brightness(1.0);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
@ -142,29 +152,40 @@ button:hover {
|
||||
.tab {
|
||||
margin-right: .25em;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#container {
|
||||
/* TODO: use flex on body */
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
width: 80%;
|
||||
max-width: 95%;
|
||||
height: 80%;
|
||||
max-height: 950%;
|
||||
width: 100%;
|
||||
max-width: 1600px;
|
||||
height: 100%;
|
||||
max-height: 1100px;
|
||||
}
|
||||
|
||||
@media (min-width: 2100px) {
|
||||
#container {
|
||||
max-width: 90%;
|
||||
max-height: 90%;
|
||||
|
||||
width: max(80vw, calc(80vh * 16/11));
|
||||
height: max(calc(80vw * 11/16), 80vh);
|
||||
}
|
||||
}
|
||||
|
||||
nav {
|
||||
margin-bottom: -.6em;
|
||||
z-index: 1;
|
||||
width: 95%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media (min-width: 600px) {
|
||||
nav {
|
||||
margin-left: 48px;
|
||||
}
|
||||
}
|
||||
|
||||
main {
|
||||
@ -195,6 +216,14 @@ main {
|
||||
box-shadow: 0 2px 16px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
@media (max-width: 800px) {
|
||||
main {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
main > :last-child {
|
||||
padding-bottom: 1.5em;
|
||||
}
|
||||
@ -251,6 +280,14 @@ main > * {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@media (max-width: 800px) {
|
||||
.shadow-box {
|
||||
padding: .5em;
|
||||
margin: .3em;
|
||||
margin-bottom: .5em;
|
||||
}
|
||||
}
|
||||
|
||||
.shadow-box-inner {
|
||||
border-radius: 12px;
|
||||
box-shadow: inset .4em .4em rgba(0, 0, 0, 0.15);
|
||||
@ -264,6 +301,7 @@ main > * {
|
||||
height: 100%;
|
||||
|
||||
display: flex;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
background: white;
|
||||
@ -275,7 +313,8 @@ button.shadow-box-title {
|
||||
bottom: -1em;
|
||||
transform: translateX(-50%);
|
||||
|
||||
width: 60%;
|
||||
width: 90%;
|
||||
max-width: 600px;
|
||||
|
||||
text-align: center;
|
||||
|
||||
@ -300,7 +339,7 @@ button.shadow-box-title {
|
||||
|
||||
border-radius: 1rem;
|
||||
width: 85%;
|
||||
height: 4rem;
|
||||
min-height: 4rem;
|
||||
|
||||
padding: .5em 1em;
|
||||
margin-top: -2em;
|
||||
@ -312,13 +351,23 @@ button.shadow-box-title {
|
||||
.progress-chart {
|
||||
flex: 1;
|
||||
|
||||
font-size: 18px;
|
||||
font-size: 14px;
|
||||
overflow: hidden;
|
||||
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
.progress-percent {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
|
||||
font-size: max(48px, 10vw);
|
||||
color: rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.outline-invert {
|
||||
color: var(--dark);
|
||||
--text-outline: var(--light);
|
||||
|
@ -2,6 +2,7 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width"/>
|
||||
<title>Paper Mario Decompilation</title>
|
||||
|
||||
<link rel="stylesheet" href="index.css"/>
|
||||
|
19
src/main.jsx
19
src/main.jsx
@ -77,22 +77,27 @@ function App() {
|
||||
return <>
|
||||
<nav>
|
||||
{tabs.map((tab, index) => {
|
||||
return <button
|
||||
return <a
|
||||
key={tab.name}
|
||||
className={clsx("tab", tab.color, { "inactive": index !== tabIndex })}
|
||||
onClick={() => {
|
||||
href={tab.slug}
|
||||
onClick={evt => {
|
||||
const q = window.matchMedia("(prefers-reduced-motion: reduce)")
|
||||
if (!q.matches) {
|
||||
switchToTab(index, true)
|
||||
evt.preventDefault()
|
||||
}
|
||||
}}
|
||||
>
|
||||
{tab.name}
|
||||
</button>
|
||||
</a>
|
||||
})}
|
||||
<button className="tab blurple inactive" onClick={() => window.open("https://discord.gg/urUm3VG")}>
|
||||
<a className="tab blurple inactive" href="https://discord.gg/urUm3VG">
|
||||
Discord
|
||||
</button>
|
||||
<button className="tab github inactive" onClick={() => window.open("https://github.com/pmret/papermario")}>
|
||||
</a>
|
||||
<a className="tab github inactive" href="https://github.com/pmret/papermario">
|
||||
GitHub
|
||||
</button>
|
||||
</a>
|
||||
</nav>
|
||||
<main id="main" ref={pane} className={clsx(tabs[paneIndex].color)} style={{
|
||||
transform: `perspective(4000px) rotateX(${rotation}deg)`,
|
||||
|
Loading…
Reference in New Issue
Block a user