-
Card Details
-
-
@@ -899,6 +919,13 @@ chmod 755 kbtd
sourceCardIndex: null
};
+ let cardDetailModalState = {
+ card: null,
+ originalTitle: '',
+ originalContent: '',
+ baseIndent: ''
+ };
+
function h(tag, props = {}, ...children) {
const el = document.createElement(tag);
for (const [k, v] of Object.entries(props)) {
@@ -1043,6 +1070,65 @@ chmod 755 kbtd
}
}
+ function detectIndentInFile(text) {
+ const lines = text.split('\n');
+ let minIndent = null;
+
+ for (const line of lines) {
+ if (line.trim() === '') continue;
+
+ const match = line.match(/^(\s+)/);
+ if (match) {
+ const indent = match[1];
+ if (minIndent === null || indent.length < minIndent.length) {
+ minIndent = indent;
+ }
+ }
+ }
+
+ return minIndent || ' ';
+ }
+
+ function detectBaseIndent(nestedLines) {
+ if (nestedLines.length === 0) return '';
+
+ let minIndent = null;
+
+ for (const line of nestedLines) {
+ if (line.trim() === '') continue;
+
+ const match = line.match(/^(\s+)/);
+ if (match) {
+ const indent = match[1];
+ if (minIndent === null || indent.length < minIndent.length) {
+ minIndent = indent;
+ }
+ }
+ }
+
+ return minIndent || '';
+ }
+
+ function stripBaseIndent(nestedLines, baseIndent) {
+ if (!baseIndent) return nestedLines.join('\n');
+
+ return nestedLines.map(line => {
+ if (line.startsWith(baseIndent)) {
+ return line.substring(baseIndent.length);
+ }
+ return line;
+ }).join('\n');
+ }
+
+ function applyBaseIndent(text, baseIndent) {
+ if (!text.trim()) return [];
+
+ return text.split('\n').map(line => {
+ if (line.trim() === '') return '';
+ return baseIndent + line;
+ });
+ }
+
function parseMarkdown(text) {
const lines = text.split('\n');
const sections = [];
@@ -1174,6 +1260,29 @@ chmod 755 kbtd
return null;
}
+ async function updateCardInFile(lineNumber, newTitle, newNestedContent, baseIndent) {
+ console.log('updateCardInFile:', lineNumber, newTitle, newNestedContent, baseIndent);
+ await modifyFileLines(lines => {
+ const cardInfo = findCardByLineNumber(lineNumber);
+ if (!cardInfo) {
+ console.error('Could not find card with line number', lineNumber);
+ return;
+ }
+
+ const card = cardInfo.card;
+ const oldNestedLineCount = card.nestedLines.length;
+
+ const checkbox = card.completed ? '[x]' : '[ ]';
+ const newCardLine = `- ${checkbox} ${newTitle}`;
+
+ const newNestedLines = applyBaseIndent(newNestedContent, baseIndent);
+
+ lines.splice(lineNumber, 1 + oldNestedLineCount, newCardLine, ...newNestedLines);
+
+ console.log('Updated card at line', lineNumber);
+ });
+ }
+
async function moveLineInFile(fromLine, toLine, targetColumnIndex, insertPosition) {
console.log('moveLineInFile: from line', fromLine, 'to line', toLine, 'targetColumnIndex:', targetColumnIndex, 'insertPosition:', insertPosition);
await modifyFileLines(lines => {
@@ -1547,15 +1656,95 @@ chmod 755 kbtd
};
}
- function openCardDetailModal(card) {
- $('#card-detail-title').textContent = card.text;
- const fullText = [card.originalLine, ...card.nestedLines].join('\n');
- $('#card-detail-content').textContent = fullText;
+ async function openCardDetailModal(card) {
+ const file = await state.fileHandle.getFile();
+ const text = await file.text();
+ const defaultIndent = detectIndentInFile(text);
+
+ const baseIndent = card.nestedLines.length > 0
+ ? detectBaseIndent(card.nestedLines)
+ : defaultIndent;
+
+ const strippedContent = stripBaseIndent(card.nestedLines, baseIndent);
+
+ cardDetailModalState = {
+ card: card,
+ originalTitle: card.text,
+ originalContent: strippedContent,
+ baseIndent: baseIndent
+ };
+
+ $('#card-detail-title-input').value = card.text;
+ $('#card-detail-content-textarea').value = strippedContent;
+
+ updateCardDetailButtons();
+
$('#card-detail-modal').classList.add('active');
}
+ function updateCardDetailButtons() {
+ const titleInput = $('#card-detail-title-input');
+ const contentTextarea = $('#card-detail-content-textarea');
+ const buttonsContainer = $('#card-detail-buttons');
+
+ const titleChanged = titleInput.value !== cardDetailModalState.originalTitle;
+ const contentChanged = contentTextarea.value !== cardDetailModalState.originalContent;
+ const isModified = titleChanged || contentChanged;
+
+ if (isModified) {
+ buttonsContainer.replaceChildren(
+ h('button', {
+ id: 'card-detail-cancel-btn',
+ textContent: 'Cancel',
+ onclick: closeCardDetailModal
+ }),
+ h('button', {
+ id: 'card-detail-save-btn',
+ textContent: 'Save',
+ onclick: saveCardDetail
+ })
+ );
+ } else {
+ buttonsContainer.replaceChildren(
+ h('button', {
+ id: 'card-detail-close-btn',
+ textContent: 'Close',
+ onclick: closeCardDetailModal
+ })
+ );
+ }
+ }
+
+ async function saveCardDetail() {
+ const titleInput = $('#card-detail-title-input');
+ const contentTextarea = $('#card-detail-content-textarea');
+
+ const newTitle = titleInput.value.trim();
+ const newContent = contentTextarea.value;
+
+ if (!newTitle) {
+ alert('Title cannot be empty');
+ return;
+ }
+
+ await updateCardInFile(
+ cardDetailModalState.card.lineNumber,
+ newTitle,
+ newContent,
+ cardDetailModalState.baseIndent
+ );
+
+ closeCardDetailModal();
+ }
+
function closeCardDetailModal() {
$('#card-detail-modal').classList.remove('active');
+ cardDetailModalState = {
+ card: null,
+ originalTitle: '',
+ originalContent: '',
+ baseIndent: ''
+ };
}
function openAboutModal() {
@@ -1634,16 +1823,12 @@ chmod 755 kbtd
ondragend: handleDragEnd,
ondragenter: (e) => handleCardDragEnter(e, cardDiv, colIndex, cardIndex),
onclick: (e) => {
- if (hasNestedContent && !e.target.closest('.card-menu-btn')) {
+ if (!e.target.closest('.card-menu-btn')) {
openCardDetailModal(card);
}
}
});
- if (hasNestedContent) {
- cardDiv.style.cursor = 'pointer';
- }
-
const expandIndicator = hasNestedContent ?
h('span', {
className: 'card-expand-indicator',
@@ -1966,6 +2151,9 @@ chmod 755 kbtd
}
});
+ $('#card-detail-title-input').addEventListener('input', updateCardDetailButtons);
+ $('#card-detail-content-textarea').addEventListener('input', updateCardDetailButtons);
+
async function openRecentProject(projectName) {
console.log('Opening recent project:', projectName);
state.filePath = projectName;
@@ -2192,10 +2380,6 @@ chmod 755 kbtd
closeAboutModal();
};
- $('#card-detail-close-btn').onclick = () => {
- closeCardDetailModal();
- };
-
$('#change-file-btn').onclick = () => {
showScreen('landing-screen');
$('#project-name-input').value = state.filePath || '';