Files
meridian-os/js/apps/notepad.js

83 lines
2.5 KiB
JavaScript

// Notepad app — simple text editor with localStorage persistence.
const uid = () => Date.now().toString(36) + Math.random().toString(36).slice(2, 7);
export default {
id: 'notepad',
title: 'Notepad',
render(container, api) {
const docId = uid();
const storageKey = `meridian:notepad:${docId}`;
let renamed = false;
let saveTimer = null;
// Load saved content
const saved = localStorage.getItem(storageKey);
let docTitle = 'Untitled';
let content = saved !== null ? saved : '';
// Build UI
const toolbar = document.createElement('div');
toolbar.className = 'app-toolbar';
const titleEl = document.createElement('span');
titleEl.className = 'doc-title';
titleEl.textContent = docTitle;
titleEl.title = 'Click to rename';
titleEl.style.cursor = 'pointer';
titleEl.addEventListener('click', () => {
const newName = prompt('Rename document:', titleEl.textContent);
if (newName !== null && newName.trim()) {
docTitle = newName.trim();
titleEl.textContent = docTitle;
renamed = true;
api.setTitle(docTitle);
}
});
const saveBtn = document.createElement('button');
saveBtn.className = 'btn-amber';
saveBtn.textContent = 'Save';
saveBtn.addEventListener('click', () => {
saveContent();
saveBtn.textContent = 'Saved!';
setTimeout(() => { saveBtn.textContent = 'Save'; }, 1200);
});
toolbar.appendChild(titleEl);
toolbar.appendChild(saveBtn);
const textarea = document.createElement('textarea');
textarea.value = content;
const statusbar = document.createElement('div');
statusbar.className = 'app-status';
function updateCounts() {
const text = textarea.value;
const chars = text.length;
const words = text.trim() === '' ? 0 : text.trim().split(/\s+/).length;
statusbar.textContent = `${words} word${words !== 1 ? 's' : ''} · ${chars} character${chars !== 1 ? 's' : ''}`;
}
textarea.addEventListener('input', () => {
updateCounts();
api.bus.emit('text:typed', { chars: textarea.value.length });
// Auto-save after 1s of inactivity
clearTimeout(saveTimer);
saveTimer = setTimeout(saveContent, 1000);
});
function saveContent() {
localStorage.setItem(storageKey, textarea.value);
}
container.style.cssText = 'height:100%;display:flex;flex-direction:column;';
container.appendChild(toolbar);
container.appendChild(textarea);
container.appendChild(statusbar);
updateCounts();
},
};