Merge pull request #84 from gamosoft/features/new-features
Features/new features
This commit is contained in:
commit
64cc6432a2
|
|
@ -0,0 +1,27 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="439" height="512" viewBox="40 30 120 140">
|
||||
<defs>
|
||||
<linearGradient id="logoGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color: #667eea;"/>
|
||||
<stop offset="100%" style="stop-color: #764ba2;"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- Main document shape -->
|
||||
<rect x="40" y="30" width="120" height="140" rx="8" fill="url(#logoGradient)"/>
|
||||
|
||||
<!-- Paper fold effect at top right -->
|
||||
<path d="M 140 30 L 140 50 L 160 50 Z" fill="#5568d3"/>
|
||||
|
||||
<!-- Lines representing text on the document -->
|
||||
<line x1="60" y1="70" x2="140" y2="70" stroke="white" stroke-width="4" stroke-linecap="round" opacity="0.9"/>
|
||||
<line x1="60" y1="90" x2="140" y2="90" stroke="white" stroke-width="4" stroke-linecap="round" opacity="0.9"/>
|
||||
<line x1="60" y1="110" x2="120" y2="110" stroke="white" stroke-width="4" stroke-linecap="round" opacity="0.9"/>
|
||||
|
||||
<!-- Discovery symbol - a magnifying glass -->
|
||||
<g transform="translate(100, 135)">
|
||||
<circle cx="0" cy="0" r="18" fill="none" stroke="white" stroke-width="4"/>
|
||||
<line x1="13" y1="13" x2="25" y2="25" stroke="white" stroke-width="4" stroke-linecap="round"/>
|
||||
<circle cx="0" cy="0" r="10" fill="white" opacity="0.3"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
|
|
@ -0,0 +1,26 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="40 30 120 140">
|
||||
<defs>
|
||||
<linearGradient id="logoGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color: rgb(102, 126, 234); stop-opacity: 1; --darkreader-inline-stopcolor: var(--darkreader-text-667eea, #67a0ea);" data-darkreader-inline-stopcolor=""/>
|
||||
<stop offset="100%" style="stop-color: rgb(118, 75, 162); stop-opacity: 1; --darkreader-inline-stopcolor: var(--darkreader-text-764ba2, #926bba);" data-darkreader-inline-stopcolor=""/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<!-- Main document shape -->
|
||||
<rect x="40" y="30" width="120" height="140" rx="8" fill="url(#logoGradient)"/>
|
||||
|
||||
<!-- Paper fold effect at top right -->
|
||||
<path d="M 140 30 L 140 50 L 160 50 Z" fill="#5568d3" data-darkreader-inline-fill="" style="--darkreader-inline-fill: var(--darkreader-text-5568d3, #5f91d6);"/>
|
||||
|
||||
<!-- Lines representing text on the document -->
|
||||
<line x1="60" y1="70" x2="140" y2="70" stroke="white" stroke-width="4" stroke-linecap="round" opacity="0.9" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: var(--darkreader-border-ffffff, #303436);"/>
|
||||
<line x1="60" y1="90" x2="140" y2="90" stroke="white" stroke-width="4" stroke-linecap="round" opacity="0.9" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: var(--darkreader-border-ffffff, #303436);"/>
|
||||
<line x1="60" y1="110" x2="120" y2="110" stroke="white" stroke-width="4" stroke-linecap="round" opacity="0.9" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: var(--darkreader-border-ffffff, #303436);"/>
|
||||
|
||||
<!-- Discovery symbol - a magnifying glass -->
|
||||
<g transform="translate(100, 135)">
|
||||
<circle cx="0" cy="0" r="18" fill="none" stroke="white" stroke-width="4" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: var(--darkreader-text-ffffff, #e8e6e3);"/>
|
||||
<line x1="13" y1="13" x2="25" y2="25" stroke="white" stroke-width="4" stroke-linecap="round" data-darkreader-inline-stroke="" style="--darkreader-inline-stroke: var(--darkreader-border-ffffff, #303436);"/>
|
||||
<circle cx="0" cy="0" r="10" fill="white" opacity="0.3" data-darkreader-inline-fill="" style="--darkreader-inline-fill: var(--darkreader-text-ffffff, #e8e6e3);"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
|
|
@ -49,6 +49,7 @@
|
|||
- **Browser history** - Back/forward buttons navigate between notes
|
||||
- **Shareable links** - Bookmark or share direct links to notes with highlighted terms
|
||||
- **Refresh safe** - Page reload keeps you on the same note with search context
|
||||
- **Copy link button** - One-click copy of note URL to clipboard
|
||||
|
||||
## 🎨 Customization
|
||||
|
||||
|
|
@ -275,6 +276,7 @@ date: {{date}}
|
|||
| `Ctrl+B` | `Cmd+B` | Bold | `**text**` |
|
||||
| `Ctrl+I` | `Cmd+I` | Italic | `*text*` |
|
||||
| `Ctrl+K` | `Cmd+K` | Insert link | `[text](url)` |
|
||||
| `Ctrl+Alt+T` | `Cmd+Option+T` | Insert table | 3x3 table placeholder |
|
||||
|
||||
## 🚀 Performance
|
||||
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ function noteApp() {
|
|||
totalMatches: 0, // Total number of matches in the note
|
||||
isSaving: false,
|
||||
lastSaved: false,
|
||||
linkCopied: false,
|
||||
saveTimeout: null,
|
||||
|
||||
// Theme state
|
||||
|
|
@ -461,6 +462,12 @@ function noteApp() {
|
|||
e.preventDefault();
|
||||
this.insertLink();
|
||||
}
|
||||
|
||||
// Ctrl/Cmd + Alt + T for table
|
||||
if ((e.ctrlKey || e.metaKey) && e.altKey && e.key === 't') {
|
||||
e.preventDefault();
|
||||
this.insertTable();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -2548,6 +2555,39 @@ function noteApp() {
|
|||
this.autoSave();
|
||||
},
|
||||
|
||||
// Insert a markdown table placeholder
|
||||
insertTable() {
|
||||
const editor = document.getElementById('note-editor');
|
||||
if (!editor) return;
|
||||
|
||||
const cursorPos = editor.selectionStart;
|
||||
|
||||
// Basic 3x3 table placeholder
|
||||
const table = `| Header 1 | Header 2 | Header 3 |
|
||||
|----------|----------|----------|
|
||||
| Cell 1 | Cell 2 | Cell 3 |
|
||||
| Cell 4 | Cell 5 | Cell 6 |
|
||||
`;
|
||||
|
||||
// Add newline before if not at start of line
|
||||
const textBefore = this.noteContent.substring(0, cursorPos);
|
||||
const needsNewlineBefore = textBefore.length > 0 && !textBefore.endsWith('\n');
|
||||
const prefix = needsNewlineBefore ? '\n\n' : '';
|
||||
|
||||
// Insert the table
|
||||
this.noteContent = textBefore + prefix + table + this.noteContent.substring(cursorPos);
|
||||
|
||||
// Position cursor at first header for easy editing
|
||||
this.$nextTick(() => {
|
||||
const newPos = cursorPos + prefix.length + 2; // After "| "
|
||||
editor.setSelectionRange(newPos, newPos + 8); // Select "Header 1"
|
||||
editor.focus();
|
||||
});
|
||||
|
||||
// Trigger autosave
|
||||
this.autoSave();
|
||||
},
|
||||
|
||||
// Save current note
|
||||
async saveNote() {
|
||||
if (!this.currentNote) return;
|
||||
|
|
@ -3975,6 +4015,34 @@ function noteApp() {
|
|||
}
|
||||
},
|
||||
|
||||
// Copy current note link to clipboard
|
||||
async copyNoteLink() {
|
||||
if (!this.currentNote) return;
|
||||
|
||||
// Build the full URL
|
||||
const pathWithoutExtension = this.currentNote.replace('.md', '');
|
||||
const encodedPath = pathWithoutExtension.split('/').map(segment => encodeURIComponent(segment)).join('/');
|
||||
const url = `${window.location.origin}/${encodedPath}`;
|
||||
|
||||
try {
|
||||
await navigator.clipboard.writeText(url);
|
||||
} catch (error) {
|
||||
// Fallback for older browsers
|
||||
const textArea = document.createElement('textarea');
|
||||
textArea.value = url;
|
||||
document.body.appendChild(textArea);
|
||||
textArea.select();
|
||||
document.execCommand('copy');
|
||||
document.body.removeChild(textArea);
|
||||
}
|
||||
|
||||
// Show brief "Copied!" feedback
|
||||
this.linkCopied = true;
|
||||
setTimeout(() => {
|
||||
this.linkCopied = false;
|
||||
}, 1500);
|
||||
},
|
||||
|
||||
// Homepage folder navigation methods
|
||||
goToHomepageFolder(folderPath) {
|
||||
this.showGraph = false; // Close graph when navigating
|
||||
|
|
|
|||
|
|
@ -1829,6 +1829,8 @@
|
|||
@click="viewMode = 'edit'"
|
||||
class="px-2 md:px-3 py-1 text-xs md:text-sm rounded transition"
|
||||
:style="viewMode === 'edit' ? 'background-color: var(--accent-primary); color: white;' : 'color: var(--text-secondary);'"
|
||||
@mouseenter="if (viewMode !== 'edit') $el.style.backgroundColor = 'var(--bg-secondary)'"
|
||||
@mouseleave="if (viewMode !== 'edit') $el.style.backgroundColor = 'transparent'"
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
|
|
@ -1836,6 +1838,8 @@
|
|||
@click="viewMode = 'split'"
|
||||
class="mobile-hide-split px-2 md:px-3 py-1 text-xs md:text-sm rounded transition"
|
||||
:style="viewMode === 'split' ? 'background-color: var(--accent-primary); color: white;' : 'color: var(--text-secondary);'"
|
||||
@mouseenter="if (viewMode !== 'split') $el.style.backgroundColor = 'var(--bg-secondary)'"
|
||||
@mouseleave="if (viewMode !== 'split') $el.style.backgroundColor = 'transparent'"
|
||||
>
|
||||
Split
|
||||
</button>
|
||||
|
|
@ -1843,21 +1847,50 @@
|
|||
@click="viewMode = 'preview'"
|
||||
class="px-2 md:px-3 py-1 text-xs md:text-sm rounded transition"
|
||||
:style="viewMode === 'preview' ? 'background-color: var(--accent-primary); color: white;' : 'color: var(--text-secondary);'"
|
||||
@mouseenter="if (viewMode !== 'preview') $el.style.backgroundColor = 'var(--bg-secondary)'"
|
||||
@mouseleave="if (viewMode !== 'preview') $el.style.backgroundColor = 'transparent'"
|
||||
>
|
||||
Preview
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Export HTML Button -->
|
||||
<!-- Note Actions Toolbar -->
|
||||
<div
|
||||
x-show="currentNote"
|
||||
class="flex items-center rounded overflow-hidden"
|
||||
style="background-color: var(--bg-tertiary); border: 1px solid var(--border-primary);"
|
||||
>
|
||||
<button
|
||||
@click="exportToHTML()"
|
||||
class="px-2 md:px-3 py-1 md:py-1.5 text-xs md:text-sm rounded transition hover:opacity-80"
|
||||
style="background-color: var(--accent-secondary); color: var(--text-primary);"
|
||||
class="p-2 transition"
|
||||
style="color: var(--text-secondary);"
|
||||
title="Export as HTML"
|
||||
@mouseenter="$el.style.backgroundColor = 'var(--bg-secondary)'"
|
||||
@mouseleave="$el.style.backgroundColor = 'transparent'"
|
||||
>
|
||||
<span class="hidden md:inline">📄 Export HTML</span>
|
||||
<span class="md:hidden">📄</span>
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
|
||||
</svg>
|
||||
</button>
|
||||
<div style="width: 1px; height: 20px; background-color: var(--border-primary);"></div>
|
||||
<button
|
||||
@click="copyNoteLink()"
|
||||
class="p-2 transition hover:bg-opacity-80"
|
||||
:title="linkCopied ? 'Copied!' : 'Copy link to clipboard'"
|
||||
:style="'color: ' + (linkCopied ? 'var(--success, #22c55e)' : 'var(--text-secondary)') + ';'"
|
||||
@mouseenter="$el.style.backgroundColor = 'var(--bg-secondary)'"
|
||||
@mouseleave="$el.style.backgroundColor = 'transparent'"
|
||||
>
|
||||
<!-- Link icon (default) -->
|
||||
<svg x-show="!linkCopied" class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"></path>
|
||||
</svg>
|
||||
<!-- Checkmark icon (after copy) -->
|
||||
<svg x-show="linkCopied" x-cloak class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue