diff --git a/src/app/compatibility/avm2/class_box.tsx b/src/app/compatibility/avm2/class_box.tsx
index 0d68b691..f10c2fa3 100644
--- a/src/app/compatibility/avm2/class_box.tsx
+++ b/src/app/compatibility/avm2/class_box.tsx
@@ -14,9 +14,9 @@ import classes from "./avm2.module.css";
import React from "react";
import {
ClassStatus,
- ProgressIcon,
displayedPercentage,
} from "@/app/compatibility/avm2/report_utils";
+import { ProgressIcon } from "@/app/compatibility/avm2/icons";
export function ClassBox(props: ClassStatus) {
const [opened, { toggle }] = useDisclosure(false);
diff --git a/src/app/compatibility/avm2/icons.tsx b/src/app/compatibility/avm2/icons.tsx
new file mode 100644
index 00000000..102834b0
--- /dev/null
+++ b/src/app/compatibility/avm2/icons.tsx
@@ -0,0 +1,54 @@
+import { rem, ThemeIcon } from "@mantine/core";
+import { IconCheck, IconProgress, IconX } from "@tabler/icons-react";
+
+export function IconDone() {
+ return (
+
+
+
+ );
+}
+
+export function IconStub() {
+ return (
+
+
+
+ );
+}
+
+export function IconMissing() {
+ return (
+
+
+
+ );
+}
+
+export function ProgressIcon(type: "stub" | "missing" | "done") {
+ switch (type) {
+ case "stub":
+ return ;
+ case "missing":
+ return ;
+ case "done":
+ return ;
+ }
+}
diff --git a/src/app/compatibility/avm2/page.tsx b/src/app/compatibility/avm2/page.tsx
index 0b1d447c..c70f7eba 100644
--- a/src/app/compatibility/avm2/page.tsx
+++ b/src/app/compatibility/avm2/page.tsx
@@ -13,11 +13,13 @@ import classes from "./avm2.module.css";
import { ClassBox } from "@/app/compatibility/avm2/class_box";
import {
getReportByNamespace,
+ NamespaceStatus,
+} from "@/app/compatibility/avm2/report_utils";
+import {
IconDone,
IconMissing,
IconStub,
- NamespaceStatus,
-} from "@/app/compatibility/avm2/report_utils";
+} from "@/app/compatibility/avm2/icons";
import Link from "next/link";
function NamespaceBox(props: NamespaceStatus) {
diff --git a/src/app/compatibility/avm2/report_utils.tsx b/src/app/compatibility/avm2/report_utils.tsx
index 73ebfb07..68fe2dc8 100644
--- a/src/app/compatibility/avm2/report_utils.tsx
+++ b/src/app/compatibility/avm2/report_utils.tsx
@@ -1,59 +1,4 @@
-import { rem, ThemeIcon } from "@mantine/core";
-import { IconCheck, IconProgress, IconX } from "@tabler/icons-react";
import { fetchReport } from "@/app/downloads/github";
-import React from "react";
-
-export function IconDone() {
- return (
-
-
-
- );
-}
-
-export function IconStub() {
- return (
-
-
-
- );
-}
-
-export function IconMissing() {
- return (
-
-
-
- );
-}
-
-export function ProgressIcon(type: "stub" | "missing" | "done") {
- switch (type) {
- case "stub":
- return ;
- case "missing":
- return ;
- case "done":
- return ;
- }
-}
export interface SummaryStatistics {
max_points: number;
diff --git a/src/components/logo.tsx b/src/components/logo.tsx
index b950a93c..67393270 100644
--- a/src/components/logo.tsx
+++ b/src/components/logo.tsx
@@ -1,6 +1,6 @@
"use client";
-import React from "react";
+import React, { useEffect, useRef, useState } from "react";
import Image from "next/image";
import Script from "next/script";
import classes from "../app/index.module.css";
@@ -27,44 +27,29 @@ interface LogoProps {
className?: string;
}
-interface LogoState {
- player: RufflePlayer | null;
-}
-
-export default class InteractiveLogo extends React.Component<
- LogoProps,
- LogoState
-> {
- private readonly container: React.RefObject;
- private player: RufflePlayer | null = null;
+export default function InteractiveLogo({ className }: LogoProps) {
+ const container = useRef(null);
+ const [player, setPlayer] = useState(null);
- constructor(props: LogoProps) {
- super(props);
-
- this.container = React.createRef();
- this.state = {
- player: null,
- };
- }
+ const removeRufflePlayer = () => {
+ player?.remove();
+ setPlayer(null);
+ };
- private removeRufflePlayer() {
- this.player?.remove();
- this.player = null;
- this.setState({ player: null });
- }
-
- private load() {
- if (this.player) {
+ const loadPlayer = () => {
+ if (player) {
// Already loaded.
return;
}
- this.player = (window.RufflePlayer as PublicAPI)?.newest()?.createPlayer();
+ const rufflePlayer = (window.RufflePlayer as PublicAPI)
+ ?.newest()
+ ?.createPlayer();
- if (this.player) {
- this.container.current!.appendChild(this.player);
+ if (rufflePlayer) {
+ container.current!.appendChild(rufflePlayer);
- this.player
+ rufflePlayer
.load({
url: "/logo-anim.swf",
autoplay: "on",
@@ -75,39 +60,33 @@ export default class InteractiveLogo extends React.Component<
preferredRenderer: "canvas",
})
.catch(() => {
- this.removeRufflePlayer();
+ removeRufflePlayer();
});
- this.player.style.width = "100%";
- this.player.style.height = "100%";
- this.setState({ player: this.player });
+ rufflePlayer.style.width = "100%";
+ rufflePlayer.style.height = "100%";
+ setPlayer(rufflePlayer);
}
- }
-
- componentDidMount() {
- this.load();
- }
-
- componentWillUnmount() {
- this.removeRufflePlayer();
- }
-
- render() {
- return (
- <>
-