/** * pc-live | Software Store App */ const StoreApp = (() => { const WIN_ID = 'app-store'; let _apps = []; let _appsMap = {}; // app_id -> app (for dependency lookups) let _filter = { category: 'all', search: '', installedOnly: false }; // Category definitions โ icon + label. // Order here determines sidebar order. const CATEGORY_META = { all: { label: 'All Apps', icon: '๐' }, system: { label: 'System', icon: '๐ฅ' }, utility: { label: 'Utility', icon: '๐ง' }, communication: { label: 'Communication', icon: '๐ก' }, security: { label: 'Security', icon: '๐' }, business: { label: 'Business', icon: '๐ผ' }, government: { label: 'Government', icon: '๐' }, entertainment: { label: 'Entertainment', icon: '๐ฎ' }, darknet: { label: 'Darknet', icon: '๐' }, }; /* โโ Helpers โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ */ // Only show categories that actually have apps in the current list function getActiveCategories() { const present = new Set(['all']); for (const app of _apps) { if (app.category) present.add(app.category); } return Object.keys(CATEGORY_META).filter(c => present.has(c)); } function filtered() { let list = _apps; if (_filter.installedOnly) list = list.filter(a => a.installed); if (_filter.category !== 'all') list = list.filter(a => a.category === _filter.category); if (_filter.search) { const q = _filter.search.toLowerCase(); list = list.filter(a => (a.name || '').toLowerCase().includes(q) || (a.description || '').toLowerCase().includes(q) ); } return list; } /* โโ Render โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ */ function renderSidebar() { const cats = getActiveCategories(); return `
`; } function renderCard(app) { const icon = app.icon || '๐ฆ'; const priceLabel = app.price > 0 ? `$${app.price.toLocaleString()}` : 'Free'; const priceClass = app.price > 0 ? '' : 'free'; const catMeta = CATEGORY_META[app.category] || { icon: '๐' }; // Resolve missing dependencies const missingDeps = (app.dependencies || []) .filter(depId => { const d = _appsMap[depId]; return !d || !d.installed; }) .map(depId => { const d = _appsMap[depId]; return d ? d.name : depId; }); // Action buttons let action = ''; if (app.installed) { if (app.update_available) { action = ``; } else { action = ``; } if (!app.default) { action += ``; } } else { const locked = missingDeps.length > 0; action = ``; } // Info badges let badges = `${catMeta.icon} ${app.category || 'other'}`; badges += `v${app.version || '?'}`; if (app.installed) badges += `โ`; if (app.update_available) badges += `โ Update`; if (app.permissions?.job) badges += `๐ ${app.permissions.job}`; if (missingDeps.length) badges += `โ Needs: ${missingDeps.join(', ')}`; return `