const { useState, useEffect, useCallback, useRef } = React;
const SK_GAMES = "jar-games-v4";
const SK_LOGO = "jar-logo-v3";
const SK_FAVS = "jar-favs-v1";
const SK_PLAYS = "jar-plays-v1";
const SAMPLE = [
{ id:"1", title:"Asphalt Urban GT", synopsis:"Corridas de rua pelas mais famosas metrópoles do mundo. Pilote carros exóticos, desvie do tráfego e ultrapasse seus rivais.", content:"Asphalt Urban GT marcou a fase em que jogos de corrida começaram a parecer mais ambiciosos nos celulares Java. Esta página reúne informações para catalogação, memória afetiva e preservação histórica: estilo de jogo, ano aproximado, gênero, observações de compatibilidade e espaço para imagens do acervo. Antes de publicar um arquivo jogável, confirme se você possui direito de distribuição ou se ele foi liberado oficialmente.", jarUrl:"", coverBase64:"", genre:"Corrida", year:"2004", gallery:[] },
{ id:"2", title:"Bomberman", synopsis:"O lendário Bomberman chegou ao celular! Posicione bombas para eliminar inimigos e abrir passagens nos labirintos.", content:"Bomberman é lembrado por partidas rápidas, labirintos simples e decisões de posicionamento. No celular, a experiência dependia muito do teclado numérico e da resolução da tela. Use este espaço para registrar versão, fabricante, controles, idioma, resolução recomendada e observações sobre desempenho no emulador.", jarUrl:"", coverBase64:"", genre:"Ação", year:"2003", gallery:[] },
{ id:"3", title:"Snake II", synopsis:"O eterno clássico do Nokia. Guie sua cobra para devorar pontos sem colidir com as paredes ou com seu próprio corpo.", content:"Snake II representa uma das formas mais reconhecíveis de jogo mobile clássico: regras simples, dificuldade crescente e partidas curtas. Esta entrada pode servir como ficha histórica, com descrição de mecânicas, curiosidades, pontuação, versões conhecidas e diferenças entre aparelhos.", jarUrl:"", coverBase64:"", genre:"Clássico",year:"2002", gallery:[] },
{ id:"4", title:"Real Football 2006", synopsis:"Futebol completo na palma da mão. Jogos, ligas, campeonatos e times reais numa experiência incrível para celular.", content:"Real Football 2006 faz parte de uma geração de jogos esportivos Java que tentava adaptar campeonatos, passes, chutes e escalações para telas pequenas. Ao cadastrar uma versão, inclua informações sobre resolução, idioma, modo de jogo, compatibilidade e origem autorizada do arquivo.", jarUrl:"", coverBase64:"", genre:"Esporte", year:"2005", gallery:[] },
{ id:"5", title:"Zuma", synopsis:"Atire esferas coloridas para eliminar cadeias antes que cheguem ao fim. Viciante e cheio de fases desafiadoras.", content:"Zuma combina raciocínio rápido, mira e combinação de cores. Em celulares antigos, jogos desse tipo se destacavam por sessões curtas e controles simples. Esta ficha pode reunir dicas, descrição de fases, observações de jogabilidade e imagens próprias enviadas pelo administrador.", jarUrl:"", coverBase64:"", genre:"Puzzle", year:"2005", gallery:[] },
];
const LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
const NUMS = "0123456789".split("");
const ALPHA = ["TODOS",...LETTERS,"0-9","#"];
const GCOLORS = { Corrida:"#e52020",Ação:"#e52020",Clássico:"#ffd23f",RPG:"#a78bfa",Esporte:"#34d399",Puzzle:"#60a5fa",Aventura:"#f97316",Luta:"#fb7185",Estratégia:"#22d3ee",Outro:"#94a3b8" };
const GENRES = Object.keys(GCOLORS);
const R="#e52020", R2="#b81818";
const ra = o=>`rgba(229,32,32,${o})`;
const gc = g=>GCOLORS[g]||GCOLORS.Outro;
const uid= ()=>Math.random().toString(36).slice(2,10);
const fl = t=>(t?.[0]||"?").toUpperCase();
function charGroup(t){
const c=fl(t);
if(LETTERS.includes(c)) return c;
if(NUMS.includes(c)) return "0-9";
return "#";
}
async function uploadFile(file){
if(window.uploadAsset) return window.uploadAsset(file);
return new Promise((res,rej)=>{const r=new FileReader();r.onload=()=>res(r.result);r.onerror=rej;r.readAsDataURL(file);});
}
const inp={width:"100%",background:"rgba(255,255,255,0.03)",border:`1px solid ${ra(0.15)}`,borderRadius:8,padding:"10px 12px",color:"#e2e8f0",fontSize:12,outline:"none",boxSizing:"border-box",fontFamily:"'IBM Plex Mono',monospace"};
const lbl={fontSize:9,letterSpacing:"0.2em",color:R,marginBottom:6,display:"block"};
const LANGS=[
{code:"pt-BR",label:"PT-BR"},
{code:"pt-PT",label:"PT-PT"},
{code:"en",label:"EN"}
];
const originalText=new WeakMap();
const MANUAL_TRANSLATIONS={
en:{
"⚙ GERENCIAR":"⚙ MANAGE",
"● ONLINE ● 5 JOGOS DISPONÍVEIS":"● ONLINE ● 5 GAMES AVAILABLE",
"BIBLIOTECA":"LIBRARY",
"JOGOS CLÁSSICOS DE CELULAR EM SEU NAVEGADOR":"CLASSIC MOBILE GAMES IN YOUR BROWSER",
"🎮 CATEGORIAS":"🎮 CATEGORIES",
"Corrida":"Racing",
"Ação":"Action",
"Clássico":"Classic",
"Esporte":"Sports",
"Puzzle":"Puzzle",
"Buscar por nome, gênero, descrição...":"Search by name, genre, description...",
"⚡ FILTROS":"⚡ FILTERS",
"TODOS":"ALL",
"5 jogos encontrados":"5 games found",
"VER JOGO":"VIEW GAME",
"JOGAR AGORA":"PLAY NOW",
"VOLTAR":"BACK",
"Sobre":"About",
"Contato":"Contact",
"Privacidade":"Privacy",
"Termos":"Terms",
"Política de Privacidade":"Privacy Policy",
"Termos de Uso":"Terms of Use"
},
"pt-PT":{
"⚙ GERENCIAR":"⚙ GERIR",
"● ONLINE ● 5 JOGOS DISPONÍVEIS":"● ONLINE ● 5 JOGOS DISPONÍVEIS",
"BIBLIOTECA":"BIBLIOTECA",
"JOGOS CLÁSSICOS DE CELULAR EM SEU NAVEGADOR":"JOGOS CLÁSSICOS DE TELEMÓVEL NO SEU NAVEGADOR",
"🎮 CATEGORIAS":"🎮 CATEGORIAS",
"Corrida":"Corridas",
"Ação":"Acção",
"Clássico":"Clássico",
"Esporte":"Desporto",
"Puzzle":"Puzzle",
"Buscar por nome, gênero, descrição...":"Pesquisar por nome, género, descrição...",
"⚡ FILTROS":"⚡ FILTROS",
"TODOS":"TODOS",
"5 jogos encontrados":"5 jogos encontrados",
"VER JOGO":"VER JOGO",
"JOGAR AGORA":"JOGAR AGORA",
"VOLTAR":"VOLTAR",
"Sobre":"Sobre",
"Contato":"Contacto",
"Privacidade":"Privacidade",
"Termos":"Termos",
"Política de Privacidade":"Política de Privacidade",
"Termos de Uso":"Termos de Utilização"
}
};
function shouldTranslateText(text){
const t=text.trim();
if(!t||t.length<2||/^[\d\s./:#()x+-]+$/.test(t)) return false;
if([".Jar","PT-BR","PT-PT","EN"].includes(t)) return false;
return /[A-Za-zÀ-ÿ]/.test(t);
}
async function translateVisiblePage(lang){
const root=document.getElementById("root");
if(!root) return;
const nodes=[];
const walker=document.createTreeWalker(root,NodeFilter.SHOW_TEXT,{
acceptNode(node){
const parent=node.parentElement;
if(!parent||["SCRIPT","STYLE","TEXTAREA","INPUT"].includes(parent.tagName)) return NodeFilter.FILTER_REJECT;
return shouldTranslateText(node.nodeValue||"")?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT;
}
});
while(walker.nextNode()) nodes.push(walker.currentNode);
const placeholderEls=[...root.querySelectorAll("input[placeholder],textarea[placeholder]")];
for(const node of nodes) if(!originalText.has(node)) originalText.set(node,node.nodeValue);
for(const el of placeholderEls) if(!el.dataset.originalPlaceholder) el.dataset.originalPlaceholder=el.getAttribute("placeholder")||"";
if(lang==="pt-BR"){
for(const node of nodes) node.nodeValue=originalText.get(node)||node.nodeValue;
for(const el of placeholderEls) el.setAttribute("placeholder",el.dataset.originalPlaceholder||"");
document.documentElement.lang="pt-BR";
return;
}
const originals=[
...nodes.map(node=>(originalText.get(node)||node.nodeValue||"").trim()),
...placeholderEls.map(el=>el.dataset.originalPlaceholder||"")
].filter(shouldTranslateText);
const unique=[...new Set(originals)].slice(0,120);
if(!unique.length||!window.translateTexts) return;
try{
const automatic=await window.translateTexts(lang,unique);
const translated={...automatic,...(MANUAL_TRANSLATIONS[lang]||{})};
for(const node of nodes){
const source=(originalText.get(node)||node.nodeValue||"").trim();
if(translated[source]) node.nodeValue=node.nodeValue.replace(source,translated[source]);
}
for(const el of placeholderEls){
const source=el.dataset.originalPlaceholder||"";
if(translated[source]) el.setAttribute("placeholder",translated[source]);
}
document.documentElement.lang=lang==="en"?"en":"pt-PT";
}catch(err){
console.warn("Traducao indisponivel",err);
}
}
function UploadBtn({accept,onFile,children}){
const ref=useRef();
return(<>{if(e.target.files[0]){try{const b=await uploadFile(e.target.files[0]);onFile(b);}catch(err){alert(err.message||"Nao foi possivel enviar o arquivo.");}e.target.value="";}}}/>>);
}
// ── HEADER ─────────────────────────────────────────────────────────────────
const DEFAULT_LOGO="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";
function Header({logo,onAdmin,onHome,onNavigate,favCount,lang,onLang,user,onAccount,showAdmin}){
const src=logo||`data:image/png;base64,${DEFAULT_LOGO}`;
return(
{favCount>0&&
♥ {favCount}
}
{showAdmin&&}
);
}
// ── GAME CARD ──────────────────────────────────────────────────────────────
function Card({game,onClick,isFav,onToggleFav,playCount}){
const [hov,setHov]=useState(false);
const c=gc(game.genre);
return(
{game.year&&{game.year}}
{playCount>0&&▶ {playCount} vezes jogado}
{game.title}
// SINOPSE
{game.synopsis||"Sem sinopse."}
{game.content&&(
// SOBRE O JOGO
{game.content}
)}
{game.gallery?.length>0&&(
// GALERIA
{game.gallery.map((img,i)=>)}
)}
{!game.jarUrl
?
⚠ URL do .JAR não configurada — adicione via painel
:
}
);
}
// ── EMULATOR ───────────────────────────────────────────────────────────────
function Emulator({game,onBack}){
return(
{game.title}
{[...Array(6)].map((_,i)=>
)}
{game.jarUrl
?
:
⚙
SEM JAR CONFIGURADO
}
);
}
// ── ADMIN ──────────────────────────────────────────────────────────────────
// ── INSTITUTIONAL PAGES ─────────────────────────────────────────────────────
const pageWrap={position:"relative",zIndex:1,maxWidth:940,margin:"0 auto",padding:"56px 24px 72px",lineHeight:1.8};
const pageTitle={fontFamily:"'Press Start 2P',monospace",fontSize:24,color:R,lineHeight:1.45,margin:"0 0 22px"};
const pageCard={background:"rgba(255,255,255,0.025)",border:"1px solid rgba(255,255,255,0.08)",borderRadius:12,padding:24,marginBottom:18};
const pageP={fontSize:13,color:"#94a3b8",margin:"0 0 14px"};
const pageH={fontSize:11,color:R,letterSpacing:"0.14em",margin:"22px 0 8px"};
function StaticPage({page,onNavigate}){
const pages={
about:{title:"Sobre o .Jar",body:[
["Nossa proposta","O .Jar é um catálogo dedicado à memória dos jogos Java para celular. A ideia é organizar fichas, imagens, informações de compatibilidade, curiosidades e registros de uma fase importante dos jogos mobile."],
["Preservação e contexto","Cada página de jogo foi pensada como uma ficha editorial. O administrador pode incluir descrição, ano, gênero, dicas, observações de controles, resolução recomendada e imagens próprias do acervo."],
["Responsabilidade","O site deve priorizar arquivos com autorização de distribuição, jogos homebrew, demos liberadas, projetos independentes ou materiais cujo uso seja permitido. Se algum conteúdo precisar ser removido, use a página de contato."]
]},
contact:{title:"Contato",body:[
["Fale com o projeto","Para pedidos de remoção, correções de informações, sugestões de jogos homebrew ou parcerias, envie uma mensagem para: contato@seudominio.com."],
["Pedidos de remoção","Se você representa o titular de algum conteúdo publicado, informe o link da página, o material questionado e uma forma de comprovar a titularidade. O objetivo é manter o acervo organizado e respeitoso."],
["Sugestões","Também aceitamos sugestões de fichas, capas autorizadas, informações históricas, versões independentes e jogos Java criados pela comunidade."]
]},
privacy:{title:"Política de Privacidade",body:[
["Dados locais","Favoritos e contagem de partidas podem ser salvos no navegador do visitante para melhorar a experiência. Esses dados ficam no próprio dispositivo e não identificam diretamente o usuário."],
["Uploads e administração","O painel administrativo salva no servidor as informações cadastradas pelo administrador, como fichas de jogos, imagens, logo e arquivos enviados."],
["Cookies e anúncios","Caso o site use Google AdSense ou ferramentas semelhantes, parceiros podem utilizar cookies, identificadores e tecnologias parecidas para medir anúncios e personalizar experiências conforme suas próprias políticas."],
["Contato","Solicitações sobre privacidade, correção ou remoção de informações podem ser enviadas para contato@seudominio.com."]
]},
terms:{title:"Termos de Uso",body:[
["Uso do site","O .Jar oferece informações, fichas e acesso a conteúdo publicado pelo administrador. O visitante deve usar o site de forma lícita e respeitar direitos autorais, marcas e regras aplicáveis."],
["Conteúdo de jogos","Arquivos jogáveis devem ser publicados apenas quando houver autorização, licença adequada, domínio público, distribuição oficial ou permissão clara. O administrador é responsável por validar a origem do material antes da publicação."],
["Emulação","O site pode abrir jogos em um emulador externo. A disponibilidade, compatibilidade e funcionamento do emulador dependem do serviço de terceiros e do arquivo utilizado."],
["Alterações","Estes termos podem ser atualizados conforme o projeto evolui, especialmente se forem adicionados login, favoritos em nuvem ou novas formas de monetização."]
]}
};
const data=pages[page]||pages.about;
return(
{e.preventDefault();onNavigate("library");}} style={{display:"inline-block",textDecoration:"none",background:"transparent",border:`1px solid ${ra(0.25)}`,color:R,borderRadius:8,padding:"8px 12px",fontSize:10,cursor:"pointer",marginBottom:24}}>← VOLTAR
{data.title}
{data.body.map(([title,text])=>(
{title.toUpperCase()}
{text}
))}
Antes de solicitar AdSense, substitua emails, domínio e textos genéricos pelas informações reais do seu projeto.