forked from akai/readest
Fix Bookmarks restore from deletion (#43)
This commit is contained in:
@@ -41,7 +41,15 @@ const BookmarkToggler: React.FC<BookmarkTogglerProps> = ({ bookKey }) => {
|
||||
createdAt: Date.now(),
|
||||
updatedAt: Date.now(),
|
||||
};
|
||||
bookmarks.push(bookmark);
|
||||
const existingBookmark = bookmarks.find(
|
||||
(item) => item.type === 'bookmark' && item.cfi === cfi,
|
||||
);
|
||||
if (existingBookmark) {
|
||||
existingBookmark.deletedAt = null;
|
||||
existingBookmark.updatedAt = Date.now();
|
||||
} else {
|
||||
bookmarks.push(bookmark);
|
||||
}
|
||||
const updatedConfig = updateBooknotes(bookKey, bookmarks);
|
||||
if (updatedConfig) {
|
||||
saveConfig(envConfig, bookKey, updatedConfig, settings);
|
||||
@@ -50,14 +58,15 @@ const BookmarkToggler: React.FC<BookmarkTogglerProps> = ({ bookKey }) => {
|
||||
setIsBookmarked(false);
|
||||
const start = CFI.collapse(cfi);
|
||||
const end = CFI.collapse(cfi, true);
|
||||
const updatedConfig = updateBooknotes(
|
||||
bookKey,
|
||||
bookmarks.filter(
|
||||
(item) =>
|
||||
item.type !== 'bookmark' ||
|
||||
CFI.compare(start, item.cfi) * CFI.compare(end, item.cfi) > 0,
|
||||
),
|
||||
);
|
||||
bookmarks.forEach((item) => {
|
||||
if (
|
||||
item.type === 'bookmark' &&
|
||||
CFI.compare(start, item.cfi) * CFI.compare(end, item.cfi) <= 0
|
||||
) {
|
||||
item.deletedAt = Date.now();
|
||||
}
|
||||
});
|
||||
const updatedConfig = updateBooknotes(bookKey, bookmarks);
|
||||
if (updatedConfig) {
|
||||
saveConfig(envConfig, bookKey, updatedConfig, settings);
|
||||
}
|
||||
@@ -72,7 +81,7 @@ const BookmarkToggler: React.FC<BookmarkTogglerProps> = ({ bookKey }) => {
|
||||
const start = CFI.collapse(cfi);
|
||||
const end = CFI.collapse(cfi, true);
|
||||
const locationBookmarked = booknotes
|
||||
.filter((booknote) => booknote.type === 'bookmark')
|
||||
.filter((booknote) => booknote.type === 'bookmark' && !booknote.deletedAt)
|
||||
.some((item) => CFI.compare(start, item.cfi) * CFI.compare(end, item.cfi) <= 0);
|
||||
setIsBookmarked(locationBookmarked);
|
||||
setBookmarkRibbonVisibility(bookKey, locationBookmarked);
|
||||
|
||||
@@ -20,8 +20,9 @@ export const useNotesSync = (bookKey: string) => {
|
||||
|
||||
const lastSyncTime = useRef<number>(0);
|
||||
const syncTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
useEffect(() => {
|
||||
if (!config?.location || !user) return;
|
||||
|
||||
const getNewNotes = () => {
|
||||
if (!config?.location || !user) return [];
|
||||
const bookNotes = config.booknotes ?? [];
|
||||
const newNotes = bookNotes.filter(
|
||||
(note) => lastSyncedAtNotes < note.updatedAt || lastSyncedAtNotes < (note.deletedAt ?? 0),
|
||||
@@ -29,16 +30,23 @@ export const useNotesSync = (bookKey: string) => {
|
||||
newNotes.forEach((note) => {
|
||||
note.bookHash = bookHash;
|
||||
});
|
||||
return newNotes;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!config?.location || !user) return;
|
||||
const now = Date.now();
|
||||
const timeSinceLastSync = now - lastSyncTime.current;
|
||||
if (timeSinceLastSync > SYNC_NOTES_INTERVAL_SEC * 1000) {
|
||||
lastSyncTime.current = now;
|
||||
const newNotes = getNewNotes();
|
||||
syncNotes(newNotes, bookHash, 'both');
|
||||
} else {
|
||||
if (syncTimeoutRef.current) clearTimeout(syncTimeoutRef.current);
|
||||
syncTimeoutRef.current = setTimeout(
|
||||
() => {
|
||||
lastSyncTime.current = Date.now();
|
||||
const newNotes = getNewNotes();
|
||||
syncNotes(newNotes, bookHash, 'both');
|
||||
syncTimeoutRef.current = null;
|
||||
},
|
||||
|
||||
@@ -150,6 +150,8 @@ export async function POST(req: NextRequest) {
|
||||
}
|
||||
|
||||
if (!serverData) {
|
||||
// use server updated_at for new records
|
||||
dbRec.updated_at = new Date().toISOString();
|
||||
const { data: inserted, error: insertError } = await supabase
|
||||
.from(table)
|
||||
.insert(dbRec)
|
||||
@@ -171,6 +173,8 @@ export async function POST(req: NextRequest) {
|
||||
clientDeletedAt > serverDeletedAt || clientUpdatedAt > serverUpdatedAt;
|
||||
|
||||
if (clientIsNewer) {
|
||||
// use server updated_at for updated records
|
||||
dbRec.updated_at = new Date().toISOString();
|
||||
const { data: updated, error: updateError } = await supabase
|
||||
.from(table)
|
||||
.update(dbRec)
|
||||
|
||||
@@ -132,7 +132,7 @@ export abstract class BaseAppService implements AppService {
|
||||
const existingBook = books.filter((b) => b.hash === hash)[0];
|
||||
if (existingBook) {
|
||||
if (existingBook.deletedAt) {
|
||||
delete existingBook.deletedAt;
|
||||
existingBook.deletedAt = null;
|
||||
}
|
||||
existingBook.updatedAt = Date.now();
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ export interface Book {
|
||||
|
||||
createdAt: number;
|
||||
updatedAt: number;
|
||||
deletedAt?: number;
|
||||
deletedAt?: number | null;
|
||||
|
||||
lastUpdated?: number; // deprecated in favor of updatedAt
|
||||
}
|
||||
@@ -39,7 +39,7 @@ export interface BookNote {
|
||||
|
||||
createdAt: number;
|
||||
updatedAt: number;
|
||||
deletedAt?: number;
|
||||
deletedAt?: number | null;
|
||||
}
|
||||
|
||||
export interface BookLayout {
|
||||
|
||||
@@ -50,7 +50,7 @@ export const transformBookToDB = (book: unknown, userId: string): DBBook => {
|
||||
tags: tags && JSON.stringify(tags),
|
||||
created_at: new Date(createdAt).toISOString(),
|
||||
updated_at: new Date(updatedAt).toISOString(),
|
||||
deleted_at: deletedAt ? new Date(deletedAt).toISOString() : undefined,
|
||||
deleted_at: deletedAt ? new Date(deletedAt).toISOString() : null,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -67,7 +67,7 @@ export const transformBookFromDB = (dbBook: DBBook): Book => {
|
||||
tags: tags && JSON.parse(tags),
|
||||
createdAt: new Date(created_at!).getTime(),
|
||||
updatedAt: new Date(updated_at!).getTime(),
|
||||
deletedAt: deleted_at ? new Date(deleted_at!).getTime() : undefined,
|
||||
deletedAt: deleted_at ? new Date(deleted_at!).getTime() : null,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -87,7 +87,8 @@ export const transformBookNoteToDB = (bookNote: unknown, userId: string): DBBook
|
||||
note,
|
||||
created_at: new Date(createdAt).toISOString(),
|
||||
updated_at: new Date(updatedAt).toISOString(),
|
||||
deleted_at: deletedAt ? new Date(deletedAt).toISOString() : undefined,
|
||||
// note that only null deleted_at is updated to the database, undefined is not
|
||||
deleted_at: deletedAt ? new Date(deletedAt).toISOString() : null,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -106,6 +107,6 @@ export const transformBookNoteFromDB = (dbBookNote: DBBookNote): BookNote => {
|
||||
note,
|
||||
createdAt: new Date(created_at!).getTime(),
|
||||
updatedAt: new Date(updated_at!).getTime(),
|
||||
deletedAt: deleted_at ? new Date(deleted_at!).getTime() : undefined,
|
||||
deletedAt: deleted_at ? new Date(deleted_at!).getTime() : null,
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user