Fix note sync reliability and Unicode filename support
- Fixed critical bug where notes with empty category had malformed IDs (leading slash) - Added URL encoding for Czech and Unicode characters in WebDAV paths - Fixed filename sanitization to preserve Unicode characters (only remove filesystem-unsafe chars) - Updated note preview to show first non-empty line after title instead of repeating title - Adjusted default column widths for better proportions (increased window width to 1300px) - Protection mechanism now works correctly with proper note ID matching
This commit is contained in:
@@ -10,6 +10,8 @@ export class SyncManager {
|
||||
private syncInProgress: boolean = false;
|
||||
private statusCallback: ((status: SyncStatus, pendingCount: number) => void) | null = null;
|
||||
private syncCompleteCallback: (() => void) | null = null;
|
||||
private recentlyModifiedNotes: Set<number | string> = new Set();
|
||||
private readonly PROTECTION_WINDOW_MS = 10000;
|
||||
|
||||
constructor() {
|
||||
window.addEventListener('online', () => {
|
||||
@@ -110,10 +112,13 @@ export class SyncManager {
|
||||
}
|
||||
}
|
||||
|
||||
// Remove deleted notes from cache
|
||||
// Remove deleted notes from cache (but protect recently modified notes)
|
||||
for (const cachedNote of cachedNotes) {
|
||||
if (!serverMap.has(cachedNote.id)) {
|
||||
await localDB.deleteNote(cachedNote.id);
|
||||
// Don't delete notes that were recently created/updated (race condition protection)
|
||||
if (!this.recentlyModifiedNotes.has(cachedNote.id)) {
|
||||
await localDB.deleteNote(cachedNote.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,6 +241,10 @@ export class SyncManager {
|
||||
this.notifyStatus('syncing', 0);
|
||||
const note = await this.api.createNoteWebDAV(title, content, category);
|
||||
await localDB.saveNote(note);
|
||||
|
||||
// Protect this note from being deleted by background sync for a short window
|
||||
this.protectNote(note.id);
|
||||
|
||||
this.notifyStatus('idle', 0);
|
||||
|
||||
// Trigger background sync to fetch any other changes
|
||||
@@ -297,8 +306,19 @@ export class SyncManager {
|
||||
|
||||
try {
|
||||
this.notifyStatus('syncing', 0);
|
||||
const oldId = note.id;
|
||||
const updatedNote = await this.api.updateNoteWebDAV(note);
|
||||
|
||||
// If the note ID changed (due to filename change), delete the old cache entry
|
||||
if (oldId !== updatedNote.id) {
|
||||
await localDB.deleteNote(oldId);
|
||||
}
|
||||
|
||||
await localDB.saveNote(updatedNote);
|
||||
|
||||
// Protect this note from being deleted by background sync for a short window
|
||||
this.protectNote(updatedNote.id);
|
||||
|
||||
this.notifyStatus('idle', 0);
|
||||
|
||||
// Trigger background sync to fetch any other changes
|
||||
@@ -349,6 +369,10 @@ export class SyncManager {
|
||||
const movedNote = await this.api.moveNoteWebDAV(note, newCategory);
|
||||
await localDB.deleteNote(note.id);
|
||||
await localDB.saveNote(movedNote);
|
||||
|
||||
// Protect the moved note from being deleted by background sync
|
||||
this.protectNote(movedNote.id);
|
||||
|
||||
this.notifyStatus('idle', 0);
|
||||
|
||||
// Trigger background sync to fetch any other changes
|
||||
@@ -370,6 +394,14 @@ export class SyncManager {
|
||||
getOnlineStatus(): boolean {
|
||||
return this.isOnline;
|
||||
}
|
||||
|
||||
// Protect a note from being deleted during background sync for a short window
|
||||
private protectNote(noteId: number | string): void {
|
||||
this.recentlyModifiedNotes.add(noteId);
|
||||
setTimeout(() => {
|
||||
this.recentlyModifiedNotes.delete(noteId);
|
||||
}, this.PROTECTION_WINDOW_MS);
|
||||
}
|
||||
}
|
||||
|
||||
export const syncManager = new SyncManager();
|
||||
|
||||
Reference in New Issue
Block a user