/* wp:polyfill */
"use strict";

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