2026-05-12 23:58:18 +00:00
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
|
|
|
initModals();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
let activeNotepadId = null; // Tracks which notepad is currently selected
|
|
|
|
|
|
|
|
|
|
function initModals() {
|
|
|
|
|
// --- Create Notepad Logic ---
|
|
|
|
|
const modalPad = document.getElementById('modal-create-pad');
|
|
|
|
|
const btnOpenPad = document.getElementById('btn-create-pad');
|
|
|
|
|
const formPad = document.getElementById('form-create-pad');
|
|
|
|
|
|
2026-10-06 19:24:25 +00:00
|
|
|
if (btnOpenPad) {
|
2026-05-12 23:58:18 +00:00
|
|
|
btnOpenPad.addEventListener('click', () => {
|
|
|
|
|
modalPad.classList.remove('hidden');
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2026-10-06 19:24:25 +00:00
|
|
|
if (formPad) {
|
2026-05-12 23:58:18 +00:00
|
|
|
formPad.addEventListener('submit', async (e) => {
|
|
|
|
|
e.preventDefault();
|
2026-10-06 19:24:25 +00:00
|
|
|
const name = document.getElementById('pad-name').value.trim();
|
2026-05-12 23:58:18 +00:00
|
|
|
const isPublic = document.getElementById('pad-public').checked;
|
2026-06-02 03:49:38 +00:00
|
|
|
const color = document.getElementById('pad-color').value;
|
2026-05-12 23:58:18 +00:00
|
|
|
|
|
|
|
|
try {
|
2026-10-06 19:24:25 +00:00
|
|
|
let encryptedKey = null;
|
|
|
|
|
let padKeyObj = null;
|
|
|
|
|
|
|
|
|
|
// For private notepads, generate an AES-GCM 256 key and wrap with user's RSA public key
|
|
|
|
|
if (!isPublic) {
|
|
|
|
|
if (!window.SpotNotes.currentUser || !window.SpotNotes.currentUser.public_key) {
|
|
|
|
|
alert('Your user account does not have an encryption key configured. Please log out and register or log in again.');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const keyData = await window.SpotCrypto.createNotepadKey(window.SpotNotes.currentUser.public_key);
|
|
|
|
|
encryptedKey = keyData.encryptedKeyB64;
|
|
|
|
|
padKeyObj = keyData.padKey;
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-12 23:58:18 +00:00
|
|
|
const res = await fetch('/api/notepads', {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: { 'Content-Type': 'application/json' },
|
2026-10-06 19:24:25 +00:00
|
|
|
body: JSON.stringify({
|
|
|
|
|
name,
|
|
|
|
|
is_public: isPublic,
|
|
|
|
|
color: color,
|
|
|
|
|
encrypted_key: encryptedKey
|
|
|
|
|
})
|
2026-05-12 23:58:18 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (res.ok) {
|
|
|
|
|
const newPad = await res.json();
|
|
|
|
|
modalPad.classList.add('hidden');
|
|
|
|
|
formPad.reset();
|
2026-10-06 19:24:25 +00:00
|
|
|
|
|
|
|
|
if (!isPublic && padKeyObj) {
|
|
|
|
|
window.SpotCrypto.setCachedPadKey(newPad.id, padKeyObj);
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-12 23:58:18 +00:00
|
|
|
// Transition to the new notepad
|
2026-10-06 19:24:25 +00:00
|
|
|
if (typeof window.SpotNotes.loadNotesForPad === 'function') {
|
|
|
|
|
window.SpotNotes.loadNotesForPad(newPad.id, newPad.name, newPad.is_public, newPad.owner_id, false, null, true, encryptedKey);
|
|
|
|
|
}
|
2026-05-12 23:58:18 +00:00
|
|
|
} else {
|
2026-10-06 19:24:25 +00:00
|
|
|
const err = await res.json();
|
|
|
|
|
alert(err.error || 'Failed to create notepad');
|
2026-05-12 23:58:18 +00:00
|
|
|
}
|
|
|
|
|
} catch (err) {
|
|
|
|
|
console.error(err);
|
2026-10-06 19:24:25 +00:00
|
|
|
alert('An error occurred during notepad creation.');
|
2026-05-12 23:58:18 +00:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// --- Create Note Logic ---
|
|
|
|
|
const modalNote = document.getElementById('modal-create-note');
|
|
|
|
|
const formNote = document.getElementById('form-create-note');
|
|
|
|
|
|
2026-10-06 19:24:25 +00:00
|
|
|
if (formNote) {
|
2026-05-12 23:58:18 +00:00
|
|
|
formNote.addEventListener('submit', async (e) => {
|
|
|
|
|
e.preventDefault();
|
2026-10-06 19:24:25 +00:00
|
|
|
const targetPadId = activeNotepadId || window.SpotNotes.activePadId;
|
|
|
|
|
if (!targetPadId) {
|
2026-05-12 23:58:18 +00:00
|
|
|
alert("No notepad selected!");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2026-10-06 19:24:25 +00:00
|
|
|
const title = document.getElementById('note-title').value.trim();
|
2026-05-12 23:58:18 +00:00
|
|
|
const content = document.getElementById('note-content').value;
|
|
|
|
|
|
|
|
|
|
// Use current map center
|
2026-10-06 19:24:25 +00:00
|
|
|
const center = window.SpotNotes.map ? window.SpotNotes.map.getCenter() : { lat: 0, lng: 0 };
|
|
|
|
|
const isPrivate = !window.SpotNotes.activePadIsPublic;
|
2026-05-12 23:58:18 +00:00
|
|
|
|
|
|
|
|
try {
|
2026-10-06 19:24:25 +00:00
|
|
|
let notePayload = {};
|
|
|
|
|
|
|
|
|
|
if (isPrivate) {
|
|
|
|
|
// Private note: client-side zero-knowledge encryption
|
|
|
|
|
let padKey = window.SpotCrypto.getCachedPadKey(targetPadId);
|
|
|
|
|
if (!padKey && window.SpotNotes.activePadEncryptedKey) {
|
|
|
|
|
padKey = await window.SpotCrypto.unwrapNotepadKey(targetPadId, window.SpotNotes.activePadEncryptedKey);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!padKey) {
|
|
|
|
|
alert("Encryption key for this private notepad is not available. Please unlock your account or re-enter via share link.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const encPayload = await window.SpotCrypto.encryptNote({
|
2026-05-12 23:58:18 +00:00
|
|
|
title,
|
|
|
|
|
content,
|
|
|
|
|
lat: center.lat,
|
2026-10-06 19:24:25 +00:00
|
|
|
lng: center.lng
|
|
|
|
|
}, padKey);
|
|
|
|
|
|
|
|
|
|
notePayload = {
|
|
|
|
|
notepad_id: targetPadId,
|
|
|
|
|
content: encPayload // Ciphertext stored at rest on server
|
|
|
|
|
};
|
|
|
|
|
} else {
|
|
|
|
|
// Public note: unencrypted at rest
|
|
|
|
|
notePayload = {
|
|
|
|
|
notepad_id: targetPadId,
|
|
|
|
|
title,
|
|
|
|
|
content,
|
|
|
|
|
lat: center.lat,
|
|
|
|
|
lng: center.lng
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const res = await fetch('/api/notes', {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: { 'Content-Type': 'application/json' },
|
|
|
|
|
body: JSON.stringify(notePayload)
|
2026-05-12 23:58:18 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (res.ok) {
|
|
|
|
|
modalNote.classList.add('hidden');
|
|
|
|
|
formNote.reset();
|
|
|
|
|
// Refresh notes
|
2026-10-06 19:24:25 +00:00
|
|
|
if (typeof window.SpotNotes.loadNotesForPad === 'function') {
|
|
|
|
|
window.SpotNotes.loadNotesForPad(targetPadId);
|
|
|
|
|
}
|
2026-05-12 23:58:18 +00:00
|
|
|
} else {
|
2026-10-06 19:24:25 +00:00
|
|
|
const err = await res.json();
|
|
|
|
|
alert(err.error || 'Failed to create note');
|
2026-05-12 23:58:18 +00:00
|
|
|
}
|
|
|
|
|
} catch (err) {
|
|
|
|
|
console.error(err);
|
2026-10-06 19:24:25 +00:00
|
|
|
alert('An error occurred during note creation.');
|
2026-05-12 23:58:18 +00:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Close buttons
|
|
|
|
|
document.querySelectorAll('.close-modal').forEach(btn => {
|
|
|
|
|
btn.addEventListener('click', (e) => {
|
|
|
|
|
e.target.closest('.modal').classList.add('hidden');
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Helper to open edit notepad modal (called from index.js)
|
2026-06-02 03:49:38 +00:00
|
|
|
window.openEditPadModal = function(id, currentName, currentPublic, currentColor = '#3388ff') {
|
2026-05-12 23:58:18 +00:00
|
|
|
document.getElementById('pad-id-edit').value = id;
|
|
|
|
|
document.getElementById('pad-name-edit').value = currentName;
|
|
|
|
|
document.getElementById('pad-public-edit').checked = currentPublic;
|
2026-06-02 03:49:38 +00:00
|
|
|
document.getElementById('pad-color-edit').value = currentColor;
|
2026-05-12 23:58:18 +00:00
|
|
|
document.getElementById('modal-edit-pad').classList.remove('hidden');
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Helper to open edit note modal (called from index.js)
|
|
|
|
|
window.openEditNoteModal = function(id, currentTitle, currentContent) {
|
|
|
|
|
document.getElementById('note-id-edit').value = id;
|
|
|
|
|
document.getElementById('note-title-edit').value = currentTitle;
|
|
|
|
|
document.getElementById('note-content-edit').value = currentContent;
|
|
|
|
|
document.getElementById('modal-edit-note').classList.remove('hidden');
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Helper to open note modal (called from index.js)
|
2026-06-02 04:22:59 +00:00
|
|
|
window.openCreateNoteModal = function(notepadId) {
|
2026-05-12 23:58:18 +00:00
|
|
|
activeNotepadId = notepadId;
|
|
|
|
|
document.getElementById('modal-create-note').classList.remove('hidden');
|
2026-06-02 04:22:59 +00:00
|
|
|
};
|