import React, { useState, useEffect, useMemo } from 'react'; import { Download, Share2, Twitter, Instagram, Heart, Filter, Maximize2, Calendar, X, Layers, Image as ImageIcon, Loader2, AlertCircle } from 'lucide-react'; const DATA_URL = "https://art.uni-dev.co.uk/Data.txt"; // Using corsproxy.io for better stability with raw text files const PROXY_URL = `https://corsproxy.io/?${encodeURIComponent(DATA_URL)}`; const PRESET_BACKGROUNDS = [ { id: 'none', label: 'None', class: 'bg-zinc-900' }, { id: 'grad-blue', label: 'Deep Ocean', class: 'bg-gradient-to-br from-blue-900 to-indigo-950' }, { id: 'grad-sunset', label: 'Sunset', class: 'bg-gradient-to-br from-orange-600 to-purple-900' }, { id: 'grid', label: 'Grid', class: 'bg-zinc-900 bg-[linear-gradient(to_right,#80808012_1px,transparent_1px),linear-gradient(to_bottom,#80808012_1px,transparent_1px)] bg-[size:24px_24px]' }, { id: 'white', label: 'Studio', class: 'bg-zinc-100' }, ]; const App = () => { const [assets, setAssets] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [selectedAsset, setSelectedAsset] = useState(null); const [activeBackground, setActiveBackground] = useState(PRESET_BACKGROUNDS[0]); const [filters, setFilters] = useState({ Personal: false, Business: false, Roblox: false, Fortnite: false, FullScene: false, }); useEffect(() => { const fetchData = async () => { try { setLoading(true); // Add cache buster to URL const cacheBuster = `&t=${Date.now()}`; const response = await fetch(PROXY_URL + cacheBuster); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const text = await response.text(); if (!text || text.trim().length === 0) { throw new Error("The data file is empty."); } const parsedAssets = parseCustomFormat(text); if (parsedAssets.length === 0) { throw new Error("No valid art data found in the file."); } setAssets(parsedAssets); setError(null); } catch (err) { console.error("Fetch error:", err); setError("Unable to connect to the art database. This can happen if the external server is blocking requests or the proxy is busy. Please try again in a moment."); } finally { setLoading(false); } }; fetchData(); }, []); const parseCustomFormat = (rawText) => { // Improved parser to handle various line endings and spacing const blocks = rawText.split('}').map(block => block.trim()); const results = []; blocks.forEach(block => { // Find where the actual content starts (skip the opening '{') const startIndex = block.indexOf('{'); if (startIndex === -1 && !block.includes(':')) return; const content = startIndex !== -1 ? block.substring(startIndex + 1) : block; const lines = content.split('\n'); const obj = {}; lines.forEach(line => { const colonIndex = line.indexOf(':'); if (colonIndex === -1) return; const key = line.substring(0, colonIndex).trim(); let value = line.substring(colonIndex + 1).trim(); // Handle boolean strings and nulls const lowerVal = value.toLowerCase(); if (lowerVal === 'true') value = true; else if (lowerVal === 'false') value = false; else if (lowerVal === 'null') value = null; if (key) obj[key] = value; }); if (obj.Name || obj.AssetID) { results.push(obj); } }); return results; }; const filteredAssets = useMemo(() => { return assets.filter(asset => { if (filters.Personal && !asset.TagPersonalUsage) return false; if (filters.Business && !asset.TagBusinessUsage) return false; if (filters.Roblox && !asset.TagRoblox) return false; if (filters.Fortnite && !asset.TagFortnite) return false; if (filters.FullScene && !asset.TagFullScene) return false; return true; }); }, [filters, assets]); const toggleFilter = (key) => { setFilters(prev => ({ ...prev, [key]: !prev[key] })); }; const handleDownload = (link) => { if (link && typeof link === 'string' && link.toLowerCase() !== "null") { window.open(link, '_blank'); } }; const copyShareLink = (link) => { const el = document.createElement('textarea'); el.value = link; document.body.appendChild(el); el.select(); document.execCommand('copy'); document.body.removeChild(el); }; if (loading) { return (

Syncing Database...

); } if (error) { return (

Connection Lost

{error}

); } return (
{/* Header */}
N

NEOX ARTS

Global Repository

{/* Filter Section */}
Filter By
{Object.keys(filters).map((f) => ( ))}
Active Dataset: {filteredAssets.length} Objects
{/* Gallery Grid */}
{filteredAssets.map((asset) => (
{asset.Name} { e.target.src = "https://images.unsplash.com/photo-1614728263952-84ea256f9679?auto=format&fit=crop&q=80&w=800"; }} />
{asset.BackgroundsEnabled && (
Dynamic Stage
)}

{asset.Name}

ID:{asset.AssetID}
{asset.TagRoblox && Roblox} {asset.TagFortnite && Fortnite} {asset.TagFullScene && Full Scene}
))}
{filteredAssets.length === 0 && (

Zero Matches Detected

)}
{/* Detail Modal */} {selectedAsset && (
setSelectedAsset(null)} />
{/* Viewport */}
{selectedAsset.Name} { e.target.src = "https://images.unsplash.com/photo-1614728263952-84ea256f9679?auto=format&fit=crop&q=80&w=800"; }} /> {selectedAsset.BackgroundsEnabled && (
{PRESET_BACKGROUNDS.map((bg) => (
)}
{/* Sidebar */}

{selectedAsset.Name}

{selectedAsset.CreationDate || "Legacy Entry"}
{selectedAsset.Embed && (

Metadata Analysis

"{selectedAsset.EmbedDescription && selectedAsset.EmbedDescription !== "Null" ? selectedAsset.EmbedDescription : "Visual representation calibrated for high-performance integration."}"

{selectedAsset.EmbedText || "System Identifier: " + selectedAsset.AssetID}

)}

Asset Acquisition

{['720p', '1080p', '1920p', '4k', '8k'].map(res => { const isEnabled = selectedAsset[res]; const link = selectedAsset[`${res}Link`]; return ( ); })}

Rights Profile

Personal
Commercial
{selectedAsset.TwitterProfileURL && selectedAsset.TwitterProfileURL !== "Null" && ( )} {selectedAsset.InstagramURL && selectedAsset.InstagramURL !== "Null" && ( )}
{selectedAsset.DonationButtonEnabled && ( Fuel Creative Work )}
)} {/* Footer */}
); }; export default App;