@wordpress/editor
Version:
Enhanced block editor for WordPress posts.
198 lines (190 loc) • 6.87 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _element = require("@wordpress/element");
var _compose = require("@wordpress/compose");
var _data = require("@wordpress/data");
var _i18n = require("@wordpress/i18n");
var _blocks = require("@wordpress/blocks");
var _notices = require("@wordpress/notices");
var _autosaveMonitor = _interopRequireDefault(require("../autosave-monitor"));
var _localAutosave = require("../../store/local-autosave");
var _store = require("../../store");
var _jsxRuntime = require("react/jsx-runtime");
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
const requestIdleCallback = window.requestIdleCallback ? window.requestIdleCallback : window.requestAnimationFrame;
let hasStorageSupport;
/**
* Function which returns true if the current environment supports browser
* sessionStorage, or false otherwise. The result of this function is cached and
* reused in subsequent invocations.
*/
const hasSessionStorageSupport = () => {
if (hasStorageSupport !== undefined) {
return hasStorageSupport;
}
try {
// Private Browsing in Safari 10 and earlier will throw an error when
// attempting to set into sessionStorage. The test here is intentional in
// causing a thrown error as condition bailing from local autosave.
window.sessionStorage.setItem('__wpEditorTestSessionStorage', '');
window.sessionStorage.removeItem('__wpEditorTestSessionStorage');
hasStorageSupport = true;
} catch {
hasStorageSupport = false;
}
return hasStorageSupport;
};
/**
* Custom hook which manages the creation of a notice prompting the user to
* restore a local autosave, if one exists.
*/
function useAutosaveNotice() {
const {
postId,
isEditedPostNew,
hasRemoteAutosave
} = (0, _data.useSelect)(select => ({
postId: select(_store.store).getCurrentPostId(),
isEditedPostNew: select(_store.store).isEditedPostNew(),
hasRemoteAutosave: !!select(_store.store).getEditorSettings().autosave
}), []);
const {
getEditedPostAttribute
} = (0, _data.useSelect)(_store.store);
const {
createWarningNotice,
removeNotice
} = (0, _data.useDispatch)(_notices.store);
const {
editPost,
resetEditorBlocks
} = (0, _data.useDispatch)(_store.store);
(0, _element.useEffect)(() => {
let localAutosave = (0, _localAutosave.localAutosaveGet)(postId, isEditedPostNew);
if (!localAutosave) {
return;
}
try {
localAutosave = JSON.parse(localAutosave);
} catch {
// Not usable if it can't be parsed.
return;
}
const {
post_title: title,
content,
excerpt
} = localAutosave;
const edits = {
title,
content,
excerpt
};
{
// Only display a notice if there is a difference between what has been
// saved and that which is stored in sessionStorage.
const hasDifference = Object.keys(edits).some(key => {
return edits[key] !== getEditedPostAttribute(key);
});
if (!hasDifference) {
// If there is no difference, it can be safely ejected from storage.
(0, _localAutosave.localAutosaveClear)(postId, isEditedPostNew);
return;
}
}
if (hasRemoteAutosave) {
return;
}
const id = 'wpEditorAutosaveRestore';
createWarningNotice((0, _i18n.__)('The backup of this post in your browser is different from the version below.'), {
id,
actions: [{
label: (0, _i18n.__)('Restore the backup'),
onClick() {
const {
content: editsContent,
...editsWithoutContent
} = edits;
editPost(editsWithoutContent);
resetEditorBlocks((0, _blocks.parse)(edits.content));
removeNotice(id);
}
}]
});
}, [isEditedPostNew, postId]);
}
/**
* Custom hook which ejects a local autosave after a successful save occurs.
*/
function useAutosavePurge() {
const {
postId,
isEditedPostNew,
isDirty,
isAutosaving,
didError
} = (0, _data.useSelect)(select => ({
postId: select(_store.store).getCurrentPostId(),
isEditedPostNew: select(_store.store).isEditedPostNew(),
isDirty: select(_store.store).isEditedPostDirty(),
isAutosaving: select(_store.store).isAutosavingPost(),
didError: select(_store.store).didPostSaveRequestFail()
}), []);
const lastIsDirtyRef = (0, _element.useRef)(isDirty);
const lastIsAutosavingRef = (0, _element.useRef)(isAutosaving);
(0, _element.useEffect)(() => {
if (!didError && (lastIsAutosavingRef.current && !isAutosaving || lastIsDirtyRef.current && !isDirty)) {
(0, _localAutosave.localAutosaveClear)(postId, isEditedPostNew);
}
lastIsDirtyRef.current = isDirty;
lastIsAutosavingRef.current = isAutosaving;
}, [isDirty, isAutosaving, didError]);
// Once the isEditedPostNew changes from true to false, let's clear the auto-draft autosave.
const wasEditedPostNew = (0, _compose.usePrevious)(isEditedPostNew);
const prevPostId = (0, _compose.usePrevious)(postId);
(0, _element.useEffect)(() => {
if (prevPostId === postId && wasEditedPostNew && !isEditedPostNew) {
(0, _localAutosave.localAutosaveClear)(postId, true);
}
}, [isEditedPostNew, postId]);
}
function LocalAutosaveMonitor() {
const {
autosave
} = (0, _data.useDispatch)(_store.store);
const deferredAutosave = (0, _element.useCallback)(() => {
requestIdleCallback(() => autosave({
local: true
}));
}, []);
useAutosaveNotice();
useAutosavePurge();
const localAutosaveInterval = (0, _data.useSelect)(select => select(_store.store).getEditorSettings().localAutosaveInterval, []);
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_autosaveMonitor.default, {
interval: localAutosaveInterval,
autosave: deferredAutosave
});
}
/**
* Monitors local autosaves of a post in the editor.
* It uses several hooks and functions to manage autosave behavior:
* - `useAutosaveNotice` hook: Manages the creation of a notice prompting the user to restore a local autosave, if one exists.
* - `useAutosavePurge` hook: Ejects a local autosave after a successful save occurs.
* - `hasSessionStorageSupport` function: Checks if the current environment supports browser sessionStorage.
* - `LocalAutosaveMonitor` component: Uses the `AutosaveMonitor` component to perform autosaves at a specified interval.
*
* The module also checks for sessionStorage support and conditionally exports the `LocalAutosaveMonitor` component based on that.
*
* @module LocalAutosaveMonitor
*/
var _default = exports.default = (0, _compose.ifCondition)(hasSessionStorageSupport)(LocalAutosaveMonitor);
//# sourceMappingURL=index.js.map