2018-05-09 13:39:17 +02:00
|
|
|
const Setting = require('lib/models/Setting');
|
2019-02-24 20:02:50 +02:00
|
|
|
const Tag = require('lib/models/Tag');
|
2020-04-19 11:11:46 +02:00
|
|
|
const BaseModel = require('lib/BaseModel');
|
2020-02-29 14:39:15 +02:00
|
|
|
const Note = require('lib/models/Note');
|
2018-05-21 17:26:01 +02:00
|
|
|
const { reg } = require('lib/registry.js');
|
2019-05-22 16:56:07 +02:00
|
|
|
const ResourceFetcher = require('lib/services/ResourceFetcher');
|
2020-04-08 02:00:01 +02:00
|
|
|
const DecryptionWorker = require('lib/services/DecryptionWorker');
|
2018-05-09 13:39:17 +02:00
|
|
|
|
2019-02-24 20:02:50 +02:00
|
|
|
const reduxSharedMiddleware = async function(store, next, action) {
|
2018-05-09 11:49:31 +02:00
|
|
|
const newState = store.getState();
|
|
|
|
|
2019-02-24 20:02:50 +02:00
|
|
|
let refreshTags = false;
|
|
|
|
|
2018-05-09 11:49:31 +02:00
|
|
|
if (action.type == 'FOLDER_SET_COLLAPSED' || action.type == 'FOLDER_TOGGLE') {
|
|
|
|
Setting.setValue('collapsedFolderIds', newState.collapsedFolderIds);
|
|
|
|
}
|
2018-05-21 17:26:01 +02:00
|
|
|
|
|
|
|
if (action.type === 'SETTING_UPDATE_ONE' && !!action.key.match(/^sync\.\d+\.path$/)) {
|
|
|
|
reg.resetSyncTarget();
|
|
|
|
}
|
2019-02-24 20:02:50 +02:00
|
|
|
|
2020-04-19 11:11:46 +02:00
|
|
|
let mustAutoAddResources = false;
|
|
|
|
|
2019-05-22 16:56:07 +02:00
|
|
|
if (action.type === 'SETTING_UPDATE_ONE' && action.key === 'sync.resourceDownloadMode') {
|
2020-04-19 11:11:46 +02:00
|
|
|
mustAutoAddResources = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (action.type === 'DECRYPTION_WORKER_SET' && action.state === 'idle' && action.decryptedItemCounts && !!action.decryptedItemCounts[BaseModel.TYPE_NOTE]) {
|
|
|
|
mustAutoAddResources = true;
|
2019-05-22 16:56:07 +02:00
|
|
|
}
|
|
|
|
|
2020-04-08 02:00:01 +02:00
|
|
|
// In general the DecryptionWorker is started via events, such as when an encrypted note
|
|
|
|
// is received via sync, or after an encrypted has been downloaded. However, in some cases,
|
|
|
|
// in particular when an item cannot be decrypted, the service won't retry automatically,
|
|
|
|
// since it's not useful because the data most likely is corrupted. In some
|
|
|
|
// cases the user might want to retry anyway, so we enable this by starting the service
|
|
|
|
// automatically after each full sync (which is triggered when the user presses the sync
|
|
|
|
// button, but not when a note is saved).
|
|
|
|
if (action.type === 'SYNC_COMPLETED' && action.isFullSync) {
|
|
|
|
DecryptionWorker.instance().scheduleStart();
|
|
|
|
}
|
|
|
|
|
2019-11-11 08:14:56 +02:00
|
|
|
if (action.type == 'NOTE_DELETE' ||
|
|
|
|
action.type == 'NOTE_UPDATE_ONE' ||
|
|
|
|
action.type == 'NOTE_UPDATE_ALL' ||
|
|
|
|
action.type == 'NOTE_TAG_REMOVE' ||
|
|
|
|
action.type == 'TAG_UPDATE_ONE') {
|
2019-02-24 20:02:50 +02:00
|
|
|
refreshTags = true;
|
|
|
|
}
|
|
|
|
|
2020-03-06 20:49:30 +02:00
|
|
|
if (action.type === 'NOTE_SELECT' || action.type === 'NAV_BACK') {
|
2020-02-29 14:39:15 +02:00
|
|
|
const noteIds = newState.provisionalNoteIds.slice();
|
|
|
|
for (const noteId of noteIds) {
|
|
|
|
if (action.id === noteId) continue;
|
2020-03-06 20:49:30 +02:00
|
|
|
reg.logger().info('Provisional was not modified - deleting it');
|
2020-02-29 14:39:15 +02:00
|
|
|
await Note.delete(noteId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-27 01:42:14 +02:00
|
|
|
if (action.type === 'NOTE_DELETE' ||
|
|
|
|
action.type === 'NOTE_SELECT' ||
|
2020-03-15 13:45:33 +02:00
|
|
|
action.type === 'NOTE_SELECT_TOGGLE' ||
|
|
|
|
action.type === 'TAG_UPDATE_ONE' ||
|
|
|
|
action.type === 'TAG_UPDATE_ALL') {
|
2020-01-06 23:23:22 +02:00
|
|
|
let noteTags = [];
|
|
|
|
|
|
|
|
// We don't need to show tags unless only one note is selected.
|
|
|
|
// For new notes, the old note is still selected, but we don't want to show any tags.
|
2020-02-29 14:39:15 +02:00
|
|
|
if (newState.selectedNoteIds &&
|
2020-01-06 23:23:22 +02:00
|
|
|
newState.selectedNoteIds.length === 1) {
|
|
|
|
noteTags = await Tag.tagsByNoteId(newState.selectedNoteIds[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
store.dispatch({
|
|
|
|
type: 'SET_NOTE_TAGS',
|
|
|
|
items: noteTags,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-04-19 11:11:46 +02:00
|
|
|
if (mustAutoAddResources) {
|
|
|
|
ResourceFetcher.instance().autoAddResources();
|
|
|
|
}
|
2020-01-06 23:23:22 +02:00
|
|
|
|
2019-02-24 20:02:50 +02:00
|
|
|
if (refreshTags) {
|
|
|
|
store.dispatch({
|
|
|
|
type: 'TAG_UPDATE_ALL',
|
|
|
|
items: await Tag.allWithNotes(),
|
|
|
|
});
|
|
|
|
}
|
2020-06-13 18:17:32 +02:00
|
|
|
|
|
|
|
// For debugging purposes: it seems in some case an empty note is saved to
|
|
|
|
// the note array, so in that case display a log statements so that it can
|
|
|
|
// be debugged.
|
|
|
|
// https://discourse.joplinapp.org/t/how-to-recover-corrupted-database/9367/3?u=laurent
|
|
|
|
if (action.type.indexOf('NOTE_') === 0) {
|
|
|
|
for (const note of newState.notes) {
|
|
|
|
if (!note) {
|
|
|
|
reg.logger().error('Detected empty element in note array', action);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-07-29 15:43:53 +02:00
|
|
|
};
|
2018-05-09 11:49:31 +02:00
|
|
|
|
2019-07-29 15:43:53 +02:00
|
|
|
module.exports = reduxSharedMiddleware;
|
2020-01-06 23:23:22 +02:00
|
|
|
|