File indexing completed on 2024-05-12 04:45:56

0001 #include "notessyncer.h"
0002 #include "controllers/notes/notescontroller.h"
0003 #include "db/db.h"
0004 
0005 #include <QDateTime>
0006 
0007 #include <MauiKit3/FileBrowsing/fmstatic.h>
0008 #include <MauiKit3/Accounts/mauiaccounts.h>
0009 #include <MauiKit3/FileBrowsing/tagging.h>
0010 
0011 NotesSyncer::NotesSyncer(QObject *parent)
0012     : Syncer(parent)
0013     , tag(Tagging::getInstance())
0014     , db(DB::getInstance())
0015     , m_notesController(new NotesController(this)) // local handler for notes
0016 {
0017     connect(MauiAccounts::instance(), &MauiAccounts::currentAccountChanged, [&](QVariantMap) {
0018         this->getRemoteNotes();
0019     });
0020 
0021     connect(this->m_notesController, &NotesController::noteReady, this, &NotesSyncer::noteReady);
0022 }
0023 
0024 void NotesSyncer::insertNote(FMH::MODEL &note)
0025 {
0026     if (!this->m_notesController->insertNote(note))
0027         return;
0028 
0029     if (this->validProvider())
0030         this->getProvider().insertNote(note);
0031 
0032     Q_EMIT this->noteInserted(note, {STATE::TYPE::LOCAL, STATE::STATUS::OK, "Note saved locally"});
0033 }
0034 
0035 void NotesSyncer::updateNote(QString id, FMH::MODEL &note)
0036 {
0037     if (!this->m_notesController->updateNote(note, id))
0038     {
0039         qWarning() << "The note could not be updated locally, "
0040                       "therefore it was not attempted to update it on the remote server provider, "
0041                       "even if it existed.";
0042         return;
0043     }
0044 
0045     // to update remote note we need to pass the stamp as the id
0046     const auto stamp = NotesSyncer::noteStampFromId(id);
0047     if (!stamp.isEmpty()) {
0048         if (this->validProvider())
0049             this->getProvider().updateNote(stamp, note);
0050     }
0051 
0052     Q_EMIT this->noteUpdated(note, {STATE::TYPE::LOCAL, STATE::STATUS::OK, "Note updated on the DB locally"});
0053 }
0054 
0055 void NotesSyncer::removeNote(const QString &id)
0056 {
0057     // to remove the remote note we need to pass the stamp as the id,
0058     // and before removing the note locally we need to retireved first
0059 
0060     const auto stamp = NotesSyncer::noteStampFromId(id);
0061     if (!this->m_notesController->removeNote(id)) {
0062         qWarning() << "The note could not be inserted locally, "
0063                       "therefore it was not attempted to insert it to the remote provider server, "
0064                       "even if it existed.";
0065         return;
0066     }
0067 
0068     if (!stamp.isEmpty()) {
0069         if (this->validProvider())
0070             this->getProvider().removeNote(stamp);
0071     }
0072 
0073     Q_EMIT this->noteRemoved(FMH::MODEL(), {STATE::TYPE::LOCAL, STATE::STATUS::OK, "The note has been removed from the local DB"});
0074 }
0075 
0076 void NotesSyncer::getNotes()
0077 {
0078     this->getLocalNotes();
0079     this->getRemoteNotes();
0080 }
0081 
0082 void NotesSyncer::getLocalNotes()
0083 {
0084     this->m_notesController->getNotes();
0085 }
0086 
0087 void NotesSyncer::getRemoteNotes()
0088 {
0089     if (this->validProvider())
0090         this->getProvider().getNotes();
0091     else
0092         qWarning() << "Failed to fetch online notes. Credentials are missing  or the provider has not been set";
0093 }
0094 
0095 const QString NotesSyncer::noteIdFromStamp(const QString &provider, const QString &stamp)
0096 {
0097     return [&]() -> const QString {
0098         const auto data = DB::getInstance()->getDBData(QString("select id from notes_sync where server = '%1' AND stamp = '%2'").arg(provider, stamp));
0099         return data.isEmpty() ? QString() : data.first()[FMH::MODEL_KEY::ID];
0100     }();
0101 }
0102 
0103 const QString NotesSyncer::noteStampFromId(const QString &id)
0104 {
0105     return [&]() -> const QString {
0106         const auto data = DB::getInstance()->getDBData(QString("select stamp from notes_sync where id = '%1'").arg(id));
0107         return data.isEmpty() ? QString() : data.first()[FMH::MODEL_KEY::STAMP];
0108     }();
0109 }
0110 
0111 void NotesSyncer::setConections()
0112 {
0113     connect(&this->getProvider(), &AbstractNotesProvider::noteInserted, [&](FMH::MODEL note) {
0114         qDebug() << "STAMP ID OF THE NEWLY INSERTED NOTE" << note[FMH::MODEL_KEY::STAMP] << note;
0115         this->db->insert(OWL::TABLEMAP[OWL::TABLE::NOTES_SYNC], FMH::toMap(FMH::filterModel(note, {FMH::MODEL_KEY::ID, FMH::MODEL_KEY::STAMP, FMH::MODEL_KEY::USER, FMH::MODEL_KEY::SERVER})));
0116         Q_EMIT this->noteInserted(note, {STATE::TYPE::REMOTE, STATE::STATUS::OK, "Note inserted on the server provider"});
0117     });
0118 
0119     connect(&this->getProvider(), &AbstractNotesProvider::notesReady, [&](FMH::MODEL_LIST notes) {
0120         //        qDebug()<< "SERVER NOETS READY "<< notes;
0121 
0122         // if there are no notes in the provider server, then just return
0123         if (notes.isEmpty())
0124             return;
0125 
0126         // there might be two case scenarios:
0127         // the note exists locally in the db, so it needs to be updated with the server version
0128         // the note does not exists locally, so it needs to be inserted into the db
0129         for (auto &note : notes) {
0130             const auto id = NotesSyncer::noteIdFromStamp(this->getProvider().provider(), note[FMH::MODEL_KEY::STAMP]);
0131             note[FMH::MODEL_KEY::ID] = id;
0132             note[FMH::MODEL_KEY::FAVORITE] = note[FMH::MODEL_KEY::FAVORITE] == "true" ? "1" : "0";
0133             qDebug() << "REMOTE NOTE MAPPED ID" << id << note[FMH::MODEL_KEY::STAMP];
0134 
0135             // if the id is empty then the note does not exists, so the note is inserted locally
0136             if (id.isEmpty()) {
0137                 if (!this->m_notesController->insertNote(note))
0138                     continue;
0139 
0140                 this->db->insert(OWL::TABLEMAP[OWL::TABLE::NOTES_SYNC], FMH::toMap(FMH::filterModel(note, {FMH::MODEL_KEY::ID, FMH::MODEL_KEY::STAMP, FMH::MODEL_KEY::USER, FMH::MODEL_KEY::SERVER})));
0141                 Q_EMIT this->noteInserted(note, {STATE::TYPE::LOCAL, STATE::STATUS::OK, "Note inserted on local db, from the server provider"});
0142 
0143             } else {
0144                 // the note does exists locally, so update it
0145                 note[FMH::MODEL_KEY::URL] = [&]() -> const QString {
0146                     const auto data = DB::getInstance()->getDBData(QString("select url from notes where id = '%1'").arg(id));
0147                     return data.isEmpty() ? QString() : data.first()[FMH::MODEL_KEY::URL];
0148                 }();
0149 
0150                 auto remoteDate = QDateTime::fromSecsSinceEpoch(note[FMH::MODEL_KEY::MODIFIED].toInt());
0151                 auto localDate = QFileInfo(QUrl(note[FMH::MODEL_KEY::URL]).toLocalFile()).lastModified();
0152 
0153                 qDebug() << "UPDATING FROM REMOTE" << note[FMH::MODEL_KEY::URL] << localDate.secsTo(QDateTime::currentDateTime()) << remoteDate.secsTo(QDateTime::currentDateTime());
0154 
0155                 if (remoteDate <= localDate)
0156                     continue;
0157 
0158                 if (!this->m_notesController->updateNote(note, id))
0159                     continue;
0160 
0161                 Q_EMIT this->noteUpdated(note, {STATE::TYPE::LOCAL, STATE::STATUS::OK, "Note updated on local db, from the server provider"});
0162             }
0163         }
0164     });
0165 
0166     connect(&this->getProvider(), &AbstractNotesProvider::noteUpdated, [&](FMH::MODEL note) {
0167         const auto id = NotesSyncer::noteIdFromStamp(this->getProvider().provider(), note[FMH::MODEL_KEY::STAMP]);
0168         note[FMH::MODEL_KEY::ID] = id;
0169 
0170         if (!note.isEmpty())
0171             this->m_notesController->updateNote(note, id);
0172         Q_EMIT this->noteUpdated(note, {STATE::TYPE::REMOTE, STATE::STATUS::OK, "Note updated on server provider"});
0173     });
0174 
0175     connect(&this->getProvider(), &AbstractNotesProvider::noteRemoved, [&]() {
0176         Q_EMIT this->noteRemoved(FMH::MODEL(), {STATE::TYPE::REMOTE, STATE::STATUS::OK, "The note has been removed from the remove server provider"});
0177     });
0178 }