diff --git a/package-lock.json b/package-lock.json index 56be594..2f1b1c2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.1.0", "dependencies": { "@tauri-apps/api": "^2", + "@tauri-apps/plugin-dialog": "^2.6.0", "@tauri-apps/plugin-opener": "^2", "@tiptap/extension-strike": "^2.27.2", "@tiptap/extension-underline": "^2.27.2", @@ -1489,6 +1490,15 @@ "node": ">= 10" } }, + "node_modules/@tauri-apps/plugin-dialog": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-dialog/-/plugin-dialog-2.6.0.tgz", + "integrity": "sha512-q4Uq3eY87TdcYzXACiYSPhmpBA76shgmQswGkSVio4C82Sz2W4iehe9TnKYwbq7weHiL88Yw19XZm7v28+Micg==", + "license": "MIT OR Apache-2.0", + "dependencies": { + "@tauri-apps/api": "^2.8.0" + } + }, "node_modules/@tauri-apps/plugin-opener": { "version": "2.5.3", "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-opener/-/plugin-opener-2.5.3.tgz", diff --git a/package.json b/package.json index 8bd3bd1..39bb239 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ }, "dependencies": { "@tauri-apps/api": "^2", + "@tauri-apps/plugin-dialog": "^2.6.0", "@tauri-apps/plugin-opener": "^2", "@tiptap/extension-strike": "^2.27.2", "@tiptap/extension-underline": "^2.27.2", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 5e72991..4392bdb 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -22,4 +22,5 @@ tauri = { version = "2", features = [] } tauri-plugin-opener = "2" serde = { version = "1", features = ["derive"] } serde_json = "1" +tauri-plugin-dialog = "2.6.0" diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 4a277ef..dfbcf1a 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -8,6 +8,7 @@ fn greet(name: &str) -> String { pub fn run() { tauri::Builder::default() .plugin(tauri_plugin_opener::init()) + .plugin(tauri_plugin_dialog::init()) .invoke_handler(tauri::generate_handler![greet]) .run(tauri::generate_context!()) .expect("error while running tauri application"); diff --git a/src/components/NoteEditor.tsx b/src/components/NoteEditor.tsx index bd4d010..145b928 100644 --- a/src/components/NoteEditor.tsx +++ b/src/components/NoteEditor.tsx @@ -7,6 +7,7 @@ import TurndownService from 'turndown'; import { marked } from 'marked'; import jsPDF from 'jspdf'; import html2canvas from 'html2canvas'; +import { message } from '@tauri-apps/plugin-dialog'; import { Note } from '../types'; interface NoteEditorProps { @@ -154,8 +155,9 @@ export function NoteEditor({ note, onUpdateNote, fontSize, onUnsavedChanges }: N // Create a temporary container with better styling for PDF const container = document.createElement('div'); - container.style.width = '210mm'; // A4 width - container.style.padding = '20mm'; + const contentWidth = 170; // A4 width (210mm) - margins (20mm each side) + container.style.width = `${contentWidth}mm`; + container.style.padding = '0'; container.style.backgroundColor = 'white'; container.style.position = 'absolute'; container.style.left = '-9999px'; @@ -188,7 +190,7 @@ export function NoteEditor({ note, onUpdateNote, fontSize, onUnsavedChanges }: N // Remove temporary container document.body.removeChild(container); - // Create PDF with multi-page support + // Create PDF with multi-page support and margins const pdf = new jsPDF({ orientation: 'portrait', unit: 'mm', @@ -197,36 +199,54 @@ export function NoteEditor({ note, onUpdateNote, fontSize, onUnsavedChanges }: N const pageWidth = 210; // A4 width in mm const pageHeight = 297; // A4 height in mm - const imgWidth = pageWidth; + const margin = 20; // 20mm margins on all sides + const contentWidthMm = pageWidth - (2 * margin); + const contentHeightMm = pageHeight - (2 * margin); + + const imgWidth = contentWidthMm; const imgHeight = (canvas.height * imgWidth) / canvas.width; let heightLeft = imgHeight; let position = 0; - // Add first page - pdf.addImage(canvas.toDataURL('image/png'), 'PNG', 0, position, imgWidth, imgHeight); - heightLeft -= pageHeight; + // Add first page with margins + pdf.addImage(canvas.toDataURL('image/png'), 'PNG', margin, margin + position, imgWidth, imgHeight); + heightLeft -= contentHeightMm; // Add additional pages if needed while (heightLeft > 0) { position = heightLeft - imgHeight; pdf.addPage(); - pdf.addImage(canvas.toDataURL('image/png'), 'PNG', 0, position, imgWidth, imgHeight); - heightLeft -= pageHeight; + pdf.addImage(canvas.toDataURL('image/png'), 'PNG', margin, margin + position, imgWidth, imgHeight); + heightLeft -= contentHeightMm; } // Save the PDF const fileName = `${localTitle || 'note'}.pdf`; pdf.save(fileName); - // Show success message - setTimeout(() => { - alert(`PDF exported successfully!\n\nFile: ${fileName}\nLocation: Downloads folder`); + // Show success message using Tauri dialog + setTimeout(async () => { + try { + await message(`PDF exported successfully!\n\nFile: ${fileName}\nLocation: Downloads folder`, { + title: 'Export Complete', + kind: 'info', + }); + } catch (err) { + console.log('Dialog shown successfully or not available'); + } setIsExportingPDF(false); }, 500); } catch (error) { console.error('PDF export failed:', error); - alert('Failed to export PDF. Please try again.'); + try { + await message('Failed to export PDF. Please try again.', { + title: 'Export Failed', + kind: 'error', + }); + } catch (err) { + console.error('Could not show error dialog'); + } setIsExportingPDF(false); } };