Initial commit — Meridian OS browser desktop demo
This commit is contained in:
76
js/widgets/achievements.js
Normal file
76
js/widgets/achievements.js
Normal file
@@ -0,0 +1,76 @@
|
||||
import State from '../core/state.js';
|
||||
import { Bus } from '../core/bus.js';
|
||||
|
||||
function renderAchievements(achievements) {
|
||||
const container = document.getElementById('achievements-list');
|
||||
if (!container) return;
|
||||
|
||||
if (!achievements || achievements.length === 0) {
|
||||
container.innerHTML = '<div class="achievements-empty">No achievements yet</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
// Show last 3
|
||||
const last3 = achievements.slice(-3).reverse();
|
||||
container.innerHTML = '';
|
||||
for (const achId of last3) {
|
||||
const item = document.createElement('div');
|
||||
item.className = 'achievement-item';
|
||||
item.innerHTML = `
|
||||
<div class="achievement-icon">${getInitial(achId)}</div>
|
||||
<div class="achievement-info">
|
||||
<span class="achievement-name">${escapeHtml(achId)}</span>
|
||||
<span class="achievement-game">Unlocked</span>
|
||||
</div>
|
||||
`;
|
||||
container.appendChild(item);
|
||||
}
|
||||
}
|
||||
|
||||
function getInitial(id) {
|
||||
return id.charAt(0).toUpperCase();
|
||||
}
|
||||
|
||||
function escapeHtml(str) {
|
||||
const div = document.createElement('div');
|
||||
div.textContent = str;
|
||||
return div.innerHTML;
|
||||
}
|
||||
|
||||
function showToast({ id, title, desc }) {
|
||||
const layer = document.getElementById('toast-layer');
|
||||
if (!layer) return;
|
||||
|
||||
const toast = document.createElement('div');
|
||||
toast.className = 'toast';
|
||||
toast.innerHTML = `
|
||||
<div>
|
||||
<div class="toast-title">Achievement Unlocked</div>
|
||||
<div class="toast-desc">${escapeHtml(title || desc || id)}</div>
|
||||
</div>
|
||||
<button class="toast-close" aria-label="Dismiss">×</button>
|
||||
`;
|
||||
|
||||
layer.appendChild(toast);
|
||||
|
||||
// Close button
|
||||
toast.querySelector('.toast-close').addEventListener('click', () => removeToast(toast));
|
||||
|
||||
// Auto dismiss
|
||||
setTimeout(() => removeToast(toast), 4000);
|
||||
}
|
||||
|
||||
function removeToast(toast) {
|
||||
if (!toast.parentNode) return;
|
||||
toast.classList.add('toast-removing');
|
||||
setTimeout(() => toast.remove(), 300);
|
||||
}
|
||||
|
||||
function init() {
|
||||
State.subscribe('achievements', renderAchievements);
|
||||
|
||||
// Listen for achievement unlocks
|
||||
Bus.on('achievement:unlocked', showToast);
|
||||
}
|
||||
|
||||
init();
|
||||
Reference in New Issue
Block a user