core: get rid of noteIds in notebook topics

This is a BREAKING change in the core & will require updating the
clients. The way it works is instead of keeping noteIds of all the
notes in the topic, it keeps an in-memory cache. This in-memory
cache `topicReferences` lives in the notes collection & decouples
notes from notebooks/topics. This also simplifies all the different
actions where references would persist after the note was deleted.
Since the note acts as the source of truth for where it currently is,
there is nothing else to do except rebuild the `topicReferences`
cache.
This commit is contained in:
Abdullah Atta
2022-09-06 22:57:54 +05:00
committed by Abdullah Atta
parent ab38d89314
commit 201366b39e
14 changed files with 238 additions and 275 deletions

View File

@@ -17,9 +17,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { qclone } from "qclone";
import { deleteItem, findById } from "../utils/array";
export default class Topic {
/**
* @param {Object} topic
@@ -33,98 +30,36 @@ export default class Topic {
}
get totalNotes() {
return this._topic.notes.length;
return this._db.notes.topicReferences.count(this.id);
}
get id() {
return this._topic.id;
}
has(noteId) {
return this._topic.notes.indexOf(noteId) > -1;
}
async add(...noteIds) {
const topic = qclone(this._topic);
for (let noteId of noteIds) {
let note = this._db.notes.note(noteId);
if (!note || note.data.deleted) continue;
const notebooks = note.notebooks || [];
const noteNotebook = notebooks.find((nb) => nb.id === this._notebookId);
const noteHasNotebook = !!noteNotebook;
const noteHasTopic =
noteHasNotebook && noteNotebook.topics.indexOf(topic.id) > -1;
if (noteHasNotebook && !noteHasTopic) {
// 1 note can be inside multiple topics
noteNotebook.topics.push(topic.id);
} else if (!noteHasNotebook) {
notebooks.push({
id: this._notebookId,
topics: [topic.id]
});
}
if (!noteHasNotebook || !noteHasTopic) {
await this._db.notes.add({
id: noteId,
notebooks
});
}
if (!this.has(noteId)) {
topic.notes.push(noteId);
await this._save(topic);
}
}
}
async delete(...noteIds) {
const topic = qclone(this._topic);
for (let noteId of noteIds) {
let note = this._db.notes.note(noteId);
if (
!note ||
note.deleted ||
!deleteItem(topic.notes, noteId) ||
!note.notebooks
) {
continue;
}
let { notebooks } = note;
const notebook = findById(notebooks, this._notebookId);
if (!notebook) continue;
const { topics } = notebook;
if (!deleteItem(topics, topic.id)) continue;
if (topics.length <= 0) deleteItem(notebooks, notebook);
await this._db.notes.add({
id: noteId,
notebooks
});
}
return await this._save(topic);
}
async _save(topic) {
await this._db.notebooks.notebook(this._notebookId).topics.add(topic);
return this;
return this._db.notes.topicReferences.has(this.id, noteId);
}
get all() {
return this._topic.notes.reduce((arr, noteId) => {
const noteIds = this._db.notes.topicReferences.get(this.id);
if (!noteIds.length) return [];
return noteIds.reduce((arr, noteId) => {
let note = this._db.notes.note(noteId);
if (note) arr.push(note.data);
return arr;
}, []);
}
synced() {
const notes = this._topic.notes;
for (let id of notes) {
if (!this._db.notes.exists(id)) return false;
}
return true;
clear() {
const noteIds = this._db.notes.topicReferences.get(this.id);
if (!noteIds.length) return;
return this._db.notes.deleteFromNotebook(
this._notebookId,
this.id,
...noteIds
);
}
}