diff --git a/main.js b/main.js index 78ecef9..f2a1886 100644 --- a/main.js +++ b/main.js @@ -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) { diff --git a/manifest.json b/manifest.json index b12c0f0..ed0f38b 100644 --- a/manifest.json +++ b/manifest.json @@ -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", diff --git a/styles.css b/styles.css index c1f6b2b..131efe4 100644 --- a/styles.css +++ b/styles.css @@ -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),