diff --git a/src/components/capes/CapeCard.tsx b/src/components/capes/CapeCard.tsx index af5d751d..b45eb271 100644 --- a/src/components/capes/CapeCard.tsx +++ b/src/components/capes/CapeCard.tsx @@ -1,7 +1,6 @@ "use client"; -import type React from "react"; -import { useEffect, useState } from "react"; +import React, { useEffect, useState } from "react"; import type { CosmeticCape } from "../../types/noriskCapes"; import { useThemeStore } from "../../store/useThemeStore"; import { IconButton } from "../ui/buttons/IconButton"; @@ -26,7 +25,7 @@ const CARD_MIN_WIDTH = 210; const IMAGE_TARGET_HEIGHT = 160; const IMAGE_TARGET_WIDTH = 100; -export function CapeCard({ +export const CapeCard = React.memo(function CapeCard({ cape, onEquip, isSelected, @@ -175,4 +174,4 @@ export function CapeCard({ ); -} +}); diff --git a/src/components/capes/CapeList.tsx b/src/components/capes/CapeList.tsx index 0b049b63..e177cc13 100644 --- a/src/components/capes/CapeList.tsx +++ b/src/components/capes/CapeList.tsx @@ -58,7 +58,7 @@ interface CapeItemDisplayProps { onContextMenu?: (e: React.MouseEvent) => void; } -function CapeItemDisplay({ +const CapeItemDisplay = React.memo(function CapeItemDisplay({ cape, imageUrl, isCurrentlyEquipping, @@ -199,7 +199,7 @@ function CapeItemDisplay({ )} ); -} +}); interface AddCapeCardProps { onClick: () => void; diff --git a/src/components/profiles/detail/ContentPackRow.tsx b/src/components/profiles/detail/ContentPackRow.tsx index 5061fc6e..15a8a027 100644 --- a/src/components/profiles/detail/ContentPackRow.tsx +++ b/src/components/profiles/detail/ContentPackRow.tsx @@ -1,7 +1,6 @@ "use client"; -import type React from "react"; -import { useEffect, useRef, useState } from "react"; +import React, { useEffect, useRef, useState } from "react"; import { Icon } from "@iconify/react"; import { ToggleSwitch } from "../../ui/ToggleSwitch"; import type { ModrinthVersion } from "../../../types/modrinth"; @@ -52,7 +51,7 @@ interface ContentPackRowProps { children?: React.ReactNode; } -export function ContentPackRow({ +export const ContentPackRow = React.memo(function ContentPackRow({ contentPack, isSelected, onSelect, @@ -326,4 +325,4 @@ export function ContentPackRow({ {children} ); -} +}); diff --git a/src/components/profiles/detail/ModRow.tsx b/src/components/profiles/detail/ModRow.tsx index b1c3afab..189803a4 100644 --- a/src/components/profiles/detail/ModRow.tsx +++ b/src/components/profiles/detail/ModRow.tsx @@ -1,6 +1,6 @@ "use client"; -import { useEffect, useRef, useState } from "react"; +import React, { useEffect, useRef, useState } from "react"; import { Icon } from "@iconify/react"; import { cn } from "../../../lib/utils"; import type { Mod } from "../../../types/profile"; @@ -25,7 +25,7 @@ interface ModRowProps { style?: React.CSSProperties; } -export function ModRow({ +export const ModRow = React.memo(function ModRow({ mod, isSelected, onSelect, @@ -230,4 +230,4 @@ export function ModRow({ ); -} +}); diff --git a/src/components/profiles/detail/ModsTab.tsx b/src/components/profiles/detail/ModsTab.tsx index e0a4f8a4..9e863faf 100644 --- a/src/components/profiles/detail/ModsTab.tsx +++ b/src/components/profiles/detail/ModsTab.tsx @@ -1,6 +1,6 @@ "use client"; -import { useEffect, useRef, useState } from "react"; +import React, { useCallback, useEffect, useRef, useState } from "react"; import { ModRow } from "./ModRow"; import type { Mod, Profile } from "../../../types/profile"; import * as ProfileService from "../../../services/profile-service"; @@ -315,7 +315,7 @@ export function ModsTab({ } }, []); - const handleToggleMod = async (modId: string) => { + const handleToggleMod = useCallback(async (modId: string) => { try { const mod = mods.find((m) => m.id === modId); if (!mod) return; @@ -335,7 +335,7 @@ export function ModsTab({ `Failed to toggle mod: ${error instanceof Error ? error.message : String(error)}`, ); } - }; + }, [mods, profile.id]); const handleDeleteMod = async (modId: string) => { try { @@ -355,7 +355,7 @@ export function ModsTab({ } }; - const handleSelectMod = (modId: string) => { + const handleSelectMod = useCallback((modId: string) => { setSelectedMods((prev) => { const updated = new Set(prev); if (updated.has(modId)) { @@ -365,7 +365,7 @@ export function ModsTab({ } return updated; }); - }; + }, []); const handleSelectAll = () => { if (selectedMods.size === filteredMods.length) { diff --git a/vite.config.ts b/vite.config.ts index b3db3db6..d7928500 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -2,7 +2,6 @@ import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; import { resolve } from 'path'; -// @ts-expect-error process is a nodejs global const host = process.env.TAURI_DEV_HOST; // https://vitejs.dev/config/ @@ -36,6 +35,14 @@ export default defineConfig(async () => ({ main: resolve(__dirname, 'index.html'), updater: resolve(__dirname, 'updater.html'), logWindow: resolve(__dirname, 'log-window.html') + }, + output: { + manualChunks: { + 'react-vendor': ['react', 'react-dom'], + 'tauri-vendor': ['@tauri-apps/api'], + 'ui-vendor': ['lucide-react', 'tailwindcss'], + '3d-vendor': ['three', '@react-three/fiber'] + } } } }