mirror of
https://github.com/bretzel-app/crumbs.git
synced 2026-10-12 20:06:57 +02:00
fix: extract tags client-side for offline notes and server-side on sync
- Import extractTags in notes store to populate tags on optimistic notes - Re-extract tags on offline update when title or content changes - Run extractTags + syncNoteTags in processSyncPush after transaction Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
99602d6a24
commit
6d3ab0ba04
+10
-3
@@ -2,6 +2,7 @@ import { writable, derived } from 'svelte/store';
|
||||
import type { Note, NoteFilter, NoteCreate, NoteUpdate } from '$lib/types/index.js';
|
||||
import { addToSyncQueue, putNote, deleteNoteFromIdb, getAllNotes } from '$lib/sync/idb.js';
|
||||
import { showToast } from '$lib/stores/toast.js';
|
||||
import { extractTags } from '$lib/utils/tags.js';
|
||||
|
||||
export const notes = writable<Note[]>([]);
|
||||
export const currentFilter = writable<NoteFilter>('all');
|
||||
@@ -78,10 +79,12 @@ export async function createNote(note: NoteCreate): Promise<Note | null> {
|
||||
} catch (err) {
|
||||
if (isNetworkError(err)) {
|
||||
const now = new Date();
|
||||
const title = note.title ?? '';
|
||||
const content = note.content ?? '';
|
||||
const optimistic: Note = {
|
||||
id: crypto.randomUUID(),
|
||||
title: note.title ?? '',
|
||||
content: note.content ?? '',
|
||||
title,
|
||||
content,
|
||||
color: note.color ?? 'default',
|
||||
pinned: note.pinned ?? false,
|
||||
archived: false,
|
||||
@@ -91,7 +94,8 @@ export async function createNote(note: NoteCreate): Promise<Note | null> {
|
||||
sortOrder: 0,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
version: 1
|
||||
version: 1,
|
||||
tags: extractTags(`${title} ${content}`)
|
||||
};
|
||||
notes.update((list) => [optimistic, ...list]);
|
||||
await putNote(optimistic);
|
||||
@@ -124,6 +128,9 @@ export async function updateNote(id: string, updates: NoteUpdate): Promise<Note
|
||||
list.map((n) => {
|
||||
if (n.id === id) {
|
||||
optimistic = { ...n, ...updates, updatedAt: new Date() };
|
||||
if (updates.title !== undefined || updates.content !== undefined) {
|
||||
optimistic.tags = extractTags(`${optimistic.title} ${optimistic.content}`);
|
||||
}
|
||||
return optimistic;
|
||||
}
|
||||
return n;
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
import { db } from '$lib/server/db/index.js';
|
||||
import { notes, syncLog } from '$lib/server/db/schema.js';
|
||||
import { eq, gt } from 'drizzle-orm';
|
||||
import { extractTags } from '$lib/utils/tags.js';
|
||||
import { syncNoteTags } from '$lib/server/tags.js';
|
||||
import type { SyncQueueItem } from './idb.js';
|
||||
|
||||
/**
|
||||
* Process incoming sync changes from client.
|
||||
*/
|
||||
export async function processSyncPush(changes: SyncQueueItem[]): Promise<void> {
|
||||
const noteIdsToSyncTags: string[] = [];
|
||||
|
||||
db.transaction((tx) => {
|
||||
for (const change of changes) {
|
||||
switch (change.operation) {
|
||||
@@ -48,6 +52,10 @@ export async function processSyncPush(changes: SyncQueueItem[]): Promise<void> {
|
||||
})
|
||||
.run();
|
||||
}
|
||||
|
||||
if (change.data.title !== undefined || change.data.content !== undefined) {
|
||||
noteIdsToSyncTags.push(change.noteId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'delete': {
|
||||
@@ -66,6 +74,14 @@ export async function processSyncPush(changes: SyncQueueItem[]): Promise<void> {
|
||||
.run();
|
||||
}
|
||||
});
|
||||
|
||||
for (const noteId of noteIdsToSyncTags) {
|
||||
const note = db.select().from(notes).where(eq(notes.id, noteId)).get();
|
||||
if (note) {
|
||||
const content = `${note.title} ${note.content}`;
|
||||
syncNoteTags(noteId, extractTags(content));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user