release: 1.5.0

- feat: add node drag functionality (change parent and reorder)
- fix: optimize node editing experience
This commit is contained in:
ninglg 2026-07-10 15:50:39 +08:00
parent c13a4a57cb
commit 7d46f4dc0a
3 changed files with 74 additions and 24 deletions

73
main.js
View file

@ -943,7 +943,7 @@ class LightMindMapPlugin extends obsidian.Plugin {
overlay._lmmDragStartY = e.clientY;
overlay._lmmDragTimer = setTimeout(() => {
this._startDrag(overlay, node, e);
}, 200);
}, 120);
}
});
el.addEventListener('click', (e) => {
@ -1037,6 +1037,7 @@ class LightMindMapPlugin extends obsidian.Plugin {
el.contentEditable = 'true';
el.classList.add('lmm-editing');
el.spellcheck = false;
el.focus({ preventScroll: false });
const range = document.createRange();
range.selectNodeContents(el);
@ -2644,25 +2645,69 @@ class LightMindMapPlugin extends obsidian.Plugin {
if (this.app.isMobile) {
const filePath = (file.parent ? file.parent.path + '/' : '') + defaultName;
await this.app.vault.adapter.writeBinary(filePath, uint8);
new obsidian.Notice('Saved to vault: ' + filePath);
return true;
}
try {
const electron = require('electron');
const win = electron.remote.BrowserWindow.getFocusedWindow();
const result = await electron.remote.dialog.showSaveDialog(win, {
title: 'Export Mindmap as PNG',
defaultPath: defaultName,
filters: [{ name: 'PNG Image', extensions: ['png'] }]
});
if (result.canceled || !result.filePath) return false;
require('fs').writeFileSync(result.filePath, Buffer.from(arrayBuffer));
return true;
if (window.showSaveFilePicker) {
const handle = await window.showSaveFilePicker({
suggestedName: defaultName,
types: [{ description: 'PNG Image', accept: { 'image/png': ['.png'] } }]
});
const writable = await handle.createWritable();
await writable.write(arrayBuffer);
await writable.close();
return true;
}
} catch (e) {
const filePath = (file.parent ? file.parent.path + '/' : '') + defaultName;
await this.app.vault.adapter.writeBinary(filePath, uint8);
return true;
if (e.name === 'AbortError' || e.name === 'NotAllowedError') {
return false;
}
}
try {
const electron = require('electron');
const { dialog } = electron;
if (dialog && dialog.showSaveDialog) {
const result = await dialog.showSaveDialog({
title: 'Export Mindmap as PNG',
defaultPath: defaultName,
filters: [{ name: 'PNG Image', extensions: ['png'] }]
});
if (result && result.canceled) {
return false;
}
if (result && result.filePath) {
require('fs').writeFileSync(result.filePath, Buffer.from(arrayBuffer));
return true;
}
}
} catch (e) {}
try {
const electron = require('electron');
if (electron.remote && electron.remote.dialog) {
const win = electron.remote.BrowserWindow.getFocusedWindow();
const result = await electron.remote.dialog.showSaveDialog(win, {
title: 'Export Mindmap as PNG',
defaultPath: defaultName,
filters: [{ name: 'PNG Image', extensions: ['png'] }]
});
if (result && result.canceled) {
return false;
}
if (result && result.filePath) {
require('fs').writeFileSync(result.filePath, Buffer.from(arrayBuffer));
return true;
}
}
} catch (e) {}
const filePath = (file.parent ? file.parent.path + '/' : '') + defaultName;
await this.app.vault.adapter.writeBinary(filePath, uint8);
new obsidian.Notice('Saved to vault: ' + filePath);
return true;
}
async _exportPNG(overlay) {

View file

@ -1,7 +1,7 @@
{
"id": "light-mindmap",
"name": "Light Mindmap",
"version": "1.4.2",
"version": "1.5.0",
"minAppVersion": "1.4.0",
"description": "Feature-rich mindmap plugin — multiple layouts, themes, node shapes & line styles, wikilink support, node collapse, PNG export — all from plain markdown headings, no custom syntax needed.",
"author": "Light Ning",

View file

@ -290,18 +290,23 @@
cursor: text;
user-select: text;
-webkit-user-select: text;
outline: 2px solid #6366F1;
outline-offset: 3px;
outline: none;
outline-offset: 0;
z-index: 8;
min-width: 80px;
min-width: 120px;
caret-color: currentColor;
transform: none !important;
transform: scale(1.03) !important;
box-shadow:
0 0 0 2px var(--lmm-color, #6366F1),
0 0 16px var(--lmm-color, #6366F1),
0 0 28px var(--lmm-color, #6366F1) !important;
border-width: 2px !important;
border-color: var(--lmm-color, #6366F1) !important;
opacity: 0.95;
transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.lmm-node.lmm-editing.lmm-node-root,
.lmm-node.lmm-editing.lmm-node-d1 {
caret-color: #fff;
}
/* Mention autocomplete popup */
.lmm-mention-popup {
@ -682,7 +687,7 @@
pointer-events: none;
opacity: 0.95;
z-index: 1000;
transform: translate(-50%, -50%);
transform: translate(-50%, -50%) scale(1.08);
box-shadow:
0 12px 32px rgba(0, 0, 0, 0.28),
0 4px 12px rgba(0, 0, 0, 0.15),