mirror of
https://github.com/trafficlunar/tomodachi-share.git
synced 2026-06-28 14:44:15 +00:00
feat: mii rendering
This commit is contained in:
parent
3a2e4c9b63
commit
fb4d790b3d
3 changed files with 67 additions and 7 deletions
|
|
@ -4,12 +4,14 @@ import { useEffect, useState } from "react";
|
|||
import { useDropzone } from "react-dropzone";
|
||||
import { Icon } from "@iconify/react";
|
||||
|
||||
import { AES_CCM } from "@trafficlunar/asmcrypto.js";
|
||||
import Mii from "@pretendonetwork/mii-js";
|
||||
import qrcode from "qrcode-generator";
|
||||
|
||||
import TagSelector from "./submit/tag-selector";
|
||||
import QrUpload from "./submit/qr-upload";
|
||||
import QrScanner from "./submit/qr-scanner";
|
||||
|
||||
import { AES_CCM } from "@trafficlunar/asmcrypto.js";
|
||||
|
||||
const key = new Uint8Array([0x59, 0xfc, 0x81, 0x7e, 0x64, 0x46, 0xea, 0x61, 0x90, 0x34, 0x7b, 0x20, 0xe9, 0xbd, 0xce, 0x52]);
|
||||
|
||||
export default function SubmitForm() {
|
||||
|
|
@ -22,10 +24,14 @@ export default function SubmitForm() {
|
|||
const [isQrScannerOpen, setIsQrScannerOpen] = useState(false);
|
||||
const [qrBytes, setQrBytes] = useState<Uint8Array>(new Uint8Array());
|
||||
|
||||
const [studioUrl, setStudioUrl] = useState<string | undefined>();
|
||||
const [generatedQrCodeUrl, setGeneratedQrCodeUrl] = useState<string | undefined>();
|
||||
|
||||
useEffect(() => {
|
||||
if (qrBytes.length == 0) return;
|
||||
|
||||
const decrypt = async () => {
|
||||
const decode = async () => {
|
||||
// Decrypt the QR code
|
||||
const nonce = qrBytes.subarray(0, 8);
|
||||
const content = qrBytes.subarray(8, 0x70);
|
||||
|
||||
|
|
@ -33,17 +39,45 @@ export default function SubmitForm() {
|
|||
nonceWithZeros.set(nonce, 0);
|
||||
|
||||
const decrypted = AES_CCM.decrypt(content, key, nonceWithZeros, undefined, 16);
|
||||
const result = new Uint8Array([...decrypted.subarray(0, 12), ...qrBytes.subarray(0, 8), ...decrypted.subarray(12, decrypted.length - 4)]);
|
||||
const result = new Uint8Array(96);
|
||||
result.set(decrypted.subarray(0, 12), 0);
|
||||
result.set(nonce, 12);
|
||||
result.set(decrypted.subarray(12), 20);
|
||||
|
||||
console.log(result);
|
||||
// Convert to Mii class
|
||||
const buffer = Buffer.from(result);
|
||||
const mii = new Mii(buffer);
|
||||
|
||||
setStudioUrl(mii.studioUrl({ width: 128 }));
|
||||
|
||||
// Generate a new QR code for aesthetic reasons
|
||||
const byteString = String.fromCharCode(...qrBytes);
|
||||
const generatedCode = qrcode(0, "L");
|
||||
generatedCode.addData(byteString, "Byte");
|
||||
generatedCode.make();
|
||||
|
||||
setGeneratedQrCodeUrl(generatedCode.createDataURL());
|
||||
};
|
||||
|
||||
decrypt();
|
||||
decode();
|
||||
}, [qrBytes]);
|
||||
|
||||
return (
|
||||
<form onSubmit={(e) => e.preventDefault()} className="grid grid-cols-2">
|
||||
<div className="p-4">
|
||||
<div className="p-4 flex flex-col gap-2">
|
||||
<div className="flex justify-center gap-2">
|
||||
<img
|
||||
src={studioUrl}
|
||||
alt="Nintendo Studio URL"
|
||||
className="aspect-square size-32 bg-orange-100 rounded-xl border-2 border-amber-500 text-[0px]"
|
||||
/>
|
||||
<img
|
||||
src={generatedQrCodeUrl}
|
||||
alt="Generated QR Code"
|
||||
className="aspect-square size-32 bg-orange-100 rounded-xl border-2 border-amber-500 text-[0px]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="p-2 border-2 bg-orange-100 border-amber-500 rounded-2xl shadow-lg h-48">
|
||||
<div
|
||||
{...getRootProps({
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue