diff --git a/src/components/common/SkinPreview3D.tsx b/src/components/common/SkinPreview3D.tsx index 2040e04..5254798 100644 --- a/src/components/common/SkinPreview3D.tsx +++ b/src/components/common/SkinPreview3D.tsx @@ -2,6 +2,8 @@ import { useEffect, useRef, memo } from 'react'; import * as THREE from 'three'; import { PCKAsset, PCKAssetType } from '../../types/pck'; +type UVSet = Record; + interface SkinPreview3DProps { asset: PCKAsset; previewUrl?: string; @@ -73,7 +75,7 @@ const SkinPreview3D = memo(function SkinPreview3D({ asset, previewUrl, className }; const isFallbackUrl = !previewUrl; - const url = previewUrl || URL.createObjectURL(new Blob([asset.data as any], { type: 'image/png' })); + const url = previewUrl || URL.createObjectURL(new Blob([asset.data], { type: 'image/png' })); const textureLoader = new THREE.TextureLoader(); let active = true; textureLoader.load(url, (texture) => { @@ -96,10 +98,10 @@ const SkinPreview3D = memo(function SkinPreview3D({ asset, previewUrl, className return new THREE.MeshLambertMaterial({ map: matTex, transparent: true, alphaTest: 0.5, side: THREE.FrontSide }); }; - const createPart = (w: number, h: number, d: number, uv: any, overlayUv?: any, isMirror = false) => { + const createPart = (w: number, h: number, d: number, uv: UVSet, overlayUv?: UVSet, isMirror = false) => { const group = new THREE.Group(); const geo = new THREE.BoxGeometry(w, h, d); - const getMats = (uvSet: any) => { + const getMats = (uvSet: UVSet) => { return [ createFaceMaterial(uvSet.right[0], uvSet.right[1], uvSet.right[2], uvSet.right[3], isMirror), // +x createFaceMaterial(uvSet.left[0], uvSet.left[1], uvSet.left[2], uvSet.left[3], isMirror), // -x diff --git a/src/components/common/SkinViewer.tsx b/src/components/common/SkinViewer.tsx index a5f819c..23cbfe0 100644 --- a/src/components/common/SkinViewer.tsx +++ b/src/components/common/SkinViewer.tsx @@ -4,6 +4,8 @@ import * as THREE from 'three'; import { useLocalStorage } from '../../hooks/useLocalStorage'; import { useConfig } from '../../context/LauncherContext'; +type UVSet = Record; + interface SkinViewerProps { username: string; setUsername: (name: string) => void; @@ -60,10 +62,10 @@ const SkinViewer = memo(function SkinViewer({ username, setUsername, playPressSo return new THREE.MeshLambertMaterial({ map: matTex, transparent: true, alphaTest: 0.5, side: THREE.FrontSide }); }; - const createPart = (w: number, h: number, d: number, uv: any, overlayUv?: any, swapMats = false, isLegacyMirror = false) => { + const createPart = (w: number, h: number, d: number, uv: UVSet, overlayUv?: UVSet, swapMats = false, isLegacyMirror = false) => { const group = new THREE.Group(); const geo = new THREE.BoxGeometry(w, h, d); - const getMats = (uvSet: any) => { + const getMats = (uvSet: UVSet) => { const flipX = isLegacyMirror; return [ createFaceMaterial(swapMats ? uvSet.right[0] : uvSet.left[0], uvSet.left[1], uvSet.left[2], uvSet.left[3], flipX), // +x (L) diff --git a/src/components/layout/AppHeader.tsx b/src/components/layout/AppHeader.tsx index c88d7ea..fffe087 100644 --- a/src/components/layout/AppHeader.tsx +++ b/src/components/layout/AppHeader.tsx @@ -6,7 +6,7 @@ const appWindow = getCurrentWindow(); interface AppHeaderProps { playPressSound: () => void; - uiFade: any; + uiFade: Record; } export const AppHeader = memo(function AppHeader({ playPressSound, uiFade }: AppHeaderProps) { diff --git a/src/components/layout/DownloadOverlay.tsx b/src/components/layout/DownloadOverlay.tsx index 74acfa5..34b188b 100644 --- a/src/components/layout/DownloadOverlay.tsx +++ b/src/components/layout/DownloadOverlay.tsx @@ -1,10 +1,11 @@ import { motion } from "framer-motion"; import { memo } from "react"; +import type { Edition } from "../../types/edition"; interface DownloadOverlayProps { downloadProgress: number | null; downloadingId: string | null; - editions: any[]; + editions: Edition[]; } export const DownloadOverlay = memo(function DownloadOverlay({ downloadProgress, downloadingId, editions }: DownloadOverlayProps) { diff --git a/src/components/modals/ChooseInstanceModal.tsx b/src/components/modals/ChooseInstanceModal.tsx index 0510c5b..637069d 100644 --- a/src/components/modals/ChooseInstanceModal.tsx +++ b/src/components/modals/ChooseInstanceModal.tsx @@ -2,6 +2,7 @@ import { useState, useEffect } from "react"; import { motion } from "framer-motion"; import { TauriService } from "../../services/TauriService"; import { lceLiveService, GameInvite } from "../../services/LceLiveService"; +import type { Edition } from "../../types/edition"; export default function ChooseInstanceModal({ isOpen, @@ -16,7 +17,7 @@ export default function ChooseInstanceModal({ onClose: () => void; playPressSound: (s?: string) => void; playBackSound: (s?: string) => void; - editions: any[]; + editions: Edition[]; installs: string[]; invite: GameInvite | null; }) { @@ -26,7 +27,7 @@ export default function ChooseInstanceModal({ const [isJoining, setIsJoining] = useState(false); const [focusIndex, setFocusIndex] = useState(0); - const validInstances = editions.filter((e: any) => + const validInstances = editions.filter((e: Edition) => installs.includes(e.instanceId) ); @@ -53,10 +54,11 @@ export default function ChooseInstanceModal({ setError(""); setStatus("Accepting invite..."); try { - const inviteData = await lceLiveService.acceptGameInvite(invite.inviteId); - const hostIp = inviteData.hostIp || (typeof invite.from !== 'string' && (invite as any).from?.hostIp); - const hostPort = inviteData.hostPort || invite.hostPort; - const sessionId = inviteData.signalingSessionId || invite.signalingSessionId || ""; + const inviteData = await lceLiveService.acceptGameInvite(invite.inviteId) as Record; + const fromIp = typeof invite.from !== 'string' ? (invite.from as unknown as Record).hostIp : undefined; + const hostIp: string = (inviteData.hostIp as string) || fromIp || invite.hostIp; + const hostPort: number = (inviteData.hostPort as number) || invite.hostPort; + const sessionId = (inviteData.signalingSessionId as string) || invite.signalingSessionId || ""; if (sessionId) { setStatus("Connecting via relay..."); @@ -77,8 +79,8 @@ export default function ChooseInstanceModal({ ]); } onClose(); - } catch (e: any) { - setError(e.toString()); + } catch (e: unknown) { + setError(e instanceof Error ? e.message : String(e)); setStatus(""); setIsJoining(false); } @@ -101,7 +103,7 @@ export default function ChooseInstanceModal({ setFocusIndex((prev) => (prev - 1 + max) % max); } else if (e.key === "Enter") { if (focusIndex === 0 && validInstances.length > 0) { - const currentIdx = validInstances.findIndex((i: any) => i.instanceId === selectedInstance); + const currentIdx = validInstances.findIndex((i: Edition) => i.instanceId === selectedInstance); const next = (currentIdx + 1) % validInstances.length; setSelectedInstance(validInstances[next].instanceId); playPressSound(); @@ -147,7 +149,7 @@ export default function ChooseInstanceModal({ {validInstances.length > 0 ? (
- {validInstances.map((inst: any) => { + {validInstances.map((inst: Edition) => { const isSelected = selectedInstance === inst.instanceId; return (
void; + onImport: (ed: { name: string; desc: string; url: string; path?: string }) => void; + playPressSound: (sound?: string) => void; + playBackSound: (sound?: string) => void; + editingEdition?: { name: string; desc: string; url: string; path?: string } | null; + initialPath?: string; +}) { const [name, setName] = useState(""); const [desc, setDesc] = useState(""); const [url, setUrl] = useState(""); diff --git a/src/components/modals/SetUidModal.tsx b/src/components/modals/SetUidModal.tsx index 79aced7..b27d368 100644 --- a/src/components/modals/SetUidModal.tsx +++ b/src/components/modals/SetUidModal.tsx @@ -1,6 +1,7 @@ import { useState, useEffect } from "react"; import { motion } from "framer-motion"; import { TauriService } from "../../services/TauriService"; +import type { Edition } from "../../types/edition"; export default function SetUidModal({ isOpen, @@ -10,7 +11,15 @@ export default function SetUidModal({ instances, installedVersions, targetInstanceId, -}: any) { +}: { + isOpen: boolean; + onClose: () => void; + playPressSound: (s?: string) => void; + playBackSound: (s?: string) => void; + instances: Edition[]; + installedVersions: string[]; + targetInstanceId: string; +}) { const [mode, setMode] = useState<"manual" | "copy">("manual"); const [uid, setUid] = useState("0xFF02F0C87E8AC1F2"); const [selectedInstance, setSelectedInstance] = useState(""); @@ -44,7 +53,7 @@ export default function SetUidModal({ } }, [isOpen, targetInstanceId]); - const validInstances = instances.filter((i: any) => installedVersions.includes(i.instanceId) && i.instanceId !== targetInstanceId); + const validInstances = instances.filter((i: Edition) => installedVersions.includes(i.instanceId) && i.instanceId !== targetInstanceId); const handleSave = async () => { playPressSound("save_click.wav"); try { @@ -74,8 +83,8 @@ export default function SetUidModal({ await TauriService.writeBinaryFile(`${targetPath}/uid.dat`, encodedUid); onClose(); - } catch (e: any) { - setError(e.toString()); + } catch (e: unknown) { + setError(e instanceof Error ? e.message : String(e)); } }; @@ -198,7 +207,7 @@ export default function SetUidModal({ {selectedInstance ? (() => { - const i = validInstances.find((inst: any) => inst.instanceId === selectedInstance); + const i = validInstances.find((inst: Edition) => inst.instanceId === selectedInstance); return i ? `${i.name} ${i.selectedBranch ? `(${i.selectedBranch})` : ""}` : "-- Select an Instance --"; })() : "-- Select an Instance --"} @@ -208,7 +217,7 @@ export default function SetUidModal({ {isDropdownOpen && validInstances.length > 0 && (
- {validInstances.map((i: any) => ( + {validInstances.map((i: Edition) => (
{ diff --git a/src/components/modals/TeamModal.tsx b/src/components/modals/TeamModal.tsx index 677a78b..5afd4cc 100644 --- a/src/components/modals/TeamModal.tsx +++ b/src/components/modals/TeamModal.tsx @@ -6,7 +6,12 @@ export default function TeamModal({ onClose, playPressSound, playSfx, -}: any) { +}: { + isOpen: boolean; + onClose: () => void; + playPressSound: () => void; + playSfx: (sound: string) => void; +}) { const [focusIndex, setFocusIndex] = useState(0); const team = [ diff --git a/src/components/views/ArcEditorView.tsx b/src/components/views/ArcEditorView.tsx index 877c9ea..1a7bb77 100644 --- a/src/components/views/ArcEditorView.tsx +++ b/src/components/views/ArcEditorView.tsx @@ -71,7 +71,7 @@ export const ArcEditorView: React.FC = () => { } setSelectedEntryIdx(null); showNotification(`Loaded ${parsed.name}`); - } catch (err: any) { + } catch (err: unknown) { if (err !== "CANCELED") { console.error("Failed to parse ARC", err); showNotification("Failed to parse ARC", "error"); @@ -96,7 +96,7 @@ export const ArcEditorView: React.FC = () => { setOpenedPath(targetPath); showNotification("ARC Saved Successfully"); } - } catch (err: any) { + } catch (err: unknown) { if (err !== "CANCELED") showNotification("Save failed", "error"); } }; @@ -109,7 +109,7 @@ export const ArcEditorView: React.FC = () => { playPressSound(); await TauriService.writeBinaryFile(path, entry.data); showNotification(`Extracted: ${entry.filename}`); - } catch (err: any) { + } catch (err: unknown) { if (err !== "CANCELED") showNotification("Extraction failed", "error"); } }; @@ -212,7 +212,7 @@ export const ArcEditorView: React.FC = () => { }; const treeData = useMemo(() => { - const root: any = { name: "", children: {}, isFolder: true }; + const root: Record = { name: "", children: {}, isFolder: true }; filteredEntries.forEach((entry) => { const parts = entry.filename.split(/\//); let current = root; @@ -237,7 +237,7 @@ export const ArcEditorView: React.FC = () => { setExpandedNodes(newExpanded); }; - const renderTree = (node: any, path: string = "") => { + const renderTree = (node: Record, path: string = "") => { const nodePath = path ? `${path}/${node.name}` : node.name; const isExpanded = expandedNodes.has(nodePath); @@ -285,7 +285,7 @@ export const ArcEditorView: React.FC = () => { exit={{ height: 0, opacity: 0 }} className="ml-4 border-l border-white/10 overflow-hidden" > - {Object.values(node.children).map((child: any) => renderTree(child, nodePath))} + {Object.values(node.children as Record).map((child: Record) => renderTree(child, nodePath))} )} @@ -306,7 +306,7 @@ export const ArcEditorView: React.FC = () => { await TauriService.writeBinaryFile(`${baseFolder}/${fileName}`, entry.data); } showNotification("All Entries Exported"); - } catch (err: any) { + } catch (err: unknown) { if (err !== "CANCELED") showNotification("Export failed", "error"); } }; diff --git a/src/components/views/ColEditorView.tsx b/src/components/views/ColEditorView.tsx index 9ea34d3..8a4622c 100644 --- a/src/components/views/ColEditorView.tsx +++ b/src/components/views/ColEditorView.tsx @@ -47,9 +47,9 @@ export default function ColEditorView() { const parsedCol = ColService.readCOL(buffer); setCol(parsedCol); showNotification(`Loaded ${file.name}`); - } catch (err: any) { + } catch (err: unknown) { console.error("Failed to parse COL", err); - showNotification(err.message || "Failed to parse COL", "error"); + showNotification(err instanceof Error ? err.message : "Failed to parse COL", "error"); } e.target.value = ""; }; @@ -67,9 +67,9 @@ export default function ColEditorView() { a.click(); URL.revokeObjectURL(url); showNotification("COL Saved Successfully"); - } catch (err: any) { + } catch (err: unknown) { console.error("Failed to save COL", err); - showNotification(err.message || "Failed to save COL", "error"); + showNotification(err instanceof Error ? err.message : "Failed to save COL", "error"); } }; diff --git a/src/components/views/GrfEditorView.tsx b/src/components/views/GrfEditorView.tsx index e68cd68..9d26ff5 100644 --- a/src/components/views/GrfEditorView.tsx +++ b/src/components/views/GrfEditorView.tsx @@ -28,9 +28,9 @@ export default function GrfEditorView() { setGrf(parsedGrf); setFilename(file.name); showNotification(`Loaded ${file.name}`); - } catch (err: any) { + } catch (err: unknown) { console.error("Failed to parse GRF", err); - showNotification(err.message || "Failed to parse GRF", "error"); + showNotification(err instanceof Error ? err.message : "Failed to parse GRF", "error"); } e.target.value = ""; }; @@ -94,7 +94,7 @@ export default function GrfEditorView() { playPressSound(); try { const buffer = GrfService.serializeGRF(grf); - const blob = new Blob([buffer as any]); + const blob = new Blob([buffer]); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; @@ -102,9 +102,9 @@ export default function GrfEditorView() { a.click(); URL.revokeObjectURL(url); showNotification("GRF Saved Successfully"); - } catch (err: any) { + } catch (err: unknown) { console.error("Failed to save GRF", err); - showNotification(err.message || "Failed to save GRF", "error"); + showNotification(err instanceof Error ? err.message : "Failed to save GRF", "error"); } }; diff --git a/src/components/views/HomeView.tsx b/src/components/views/HomeView.tsx index 19e32b0..6f87699 100644 --- a/src/components/views/HomeView.tsx +++ b/src/components/views/HomeView.tsx @@ -6,6 +6,7 @@ import { useAudio, useGame, } from "../../context/LauncherContext"; +import type { Edition } from "../../types/edition"; const HomeView = memo(function HomeView() { const { setActiveView, setShowCredits, focusSection, onNavigateToSkin } = @@ -24,7 +25,7 @@ const HomeView = memo(function HomeView() { } = useGame(); const isFocusedSection = focusSection === "menu"; - const selectedEdition = editions.find((e: any) => e.id === profile); + const selectedEdition = editions.find((e: Edition) => e.id === profile); const selectedVersionName = selectedEdition?.name || "Game"; const isInstalled = installs.includes(profile); const isDownloading = downloadingId === profile; @@ -128,7 +129,7 @@ const HomeView = memo(function HomeView() { transition={{ duration: useConfig().animationsEnabled ? 0.3 : 0 }} className="relative w-full max-w-[540px] flex flex-col space-y-3 outline-none" > - {buttons.map((btn: any, i: number) => ( + {buttons.map((btn: { label: string; action: () => void; isDanger?: boolean; disabled: boolean; id?: string }, i: number) => (