| 1 |
/******/ (() => { // webpackBootstrap |
| 2 |
/******/ "use strict"; |
| 3 |
/******/ // The require scope |
| 4 |
/******/ var __webpack_require__ = {}; |
| 5 |
/******/ |
| 6 |
/************************************************************************/ |
| 7 |
/******/ /* webpack/runtime/compat get default export */ |
| 8 |
/******/ (() => { |
| 9 |
/******/ // getDefaultExport function for compatibility with non-harmony modules |
| 10 |
/******/ __webpack_require__.n = (module) => { |
| 11 |
/******/ var getter = module && module.__esModule ? |
| 12 |
/******/ () => (module['default']) : |
| 13 |
/******/ () => (module); |
| 14 |
/******/ __webpack_require__.d(getter, { a: getter }); |
| 15 |
/******/ return getter; |
| 16 |
/******/ }; |
| 17 |
/******/ })(); |
| 18 |
/******/ |
| 19 |
/******/ /* webpack/runtime/define property getters */ |
| 20 |
/******/ (() => { |
| 21 |
/******/ // define getter functions for harmony exports |
| 22 |
/******/ __webpack_require__.d = (exports, definition) => { |
| 23 |
/******/ for(var key in definition) { |
| 24 |
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { |
| 25 |
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); |
| 26 |
/******/ } |
| 27 |
/******/ } |
| 28 |
/******/ }; |
| 29 |
/******/ })(); |
| 30 |
/******/ |
| 31 |
/******/ /* webpack/runtime/hasOwnProperty shorthand */ |
| 32 |
/******/ (() => { |
| 33 |
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) |
| 34 |
/******/ })(); |
| 35 |
/******/ |
| 36 |
/******/ /* webpack/runtime/make namespace object */ |
| 37 |
/******/ (() => { |
| 38 |
/******/ // define __esModule on exports |
| 39 |
/******/ __webpack_require__.r = (exports) => { |
| 40 |
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { |
| 41 |
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); |
| 42 |
/******/ } |
| 43 |
/******/ Object.defineProperty(exports, '__esModule', { value: true }); |
| 44 |
/******/ }; |
| 45 |
/******/ })(); |
| 46 |
/******/ |
| 47 |
/************************************************************************/ |
| 48 |
var __webpack_exports__ = {}; |
| 49 |
// ESM COMPAT FLAG |
| 50 |
__webpack_require__.r(__webpack_exports__); |
| 51 |
|
| 52 |
// EXPORTS |
| 53 |
__webpack_require__.d(__webpack_exports__, { |
| 54 |
"__unstableCreatePersistenceLayer": () => (/* binding */ __unstableCreatePersistenceLayer), |
| 55 |
"create": () => (/* reexport */ create) |
| 56 |
}); |
| 57 |
|
| 58 |
;// CONCATENATED MODULE: external ["wp","apiFetch"] |
| 59 |
const external_wp_apiFetch_namespaceObject = window["wp"]["apiFetch"]; |
| 60 |
var external_wp_apiFetch_default = /*#__PURE__*/__webpack_require__.n(external_wp_apiFetch_namespaceObject); |
| 61 |
;// CONCATENATED MODULE: ./packages/preferences-persistence/build-module/create/debounce-async.js |
| 62 |
/** |
| 63 |
* Performs a leading edge debounce of async functions. |
| 64 |
* |
| 65 |
* If three functions are throttled at the same time: |
| 66 |
* - The first happens immediately. |
| 67 |
* - The second is never called. |
| 68 |
* - The third happens `delayMS` milliseconds after the first has resolved. |
| 69 |
* |
| 70 |
* This is distinct from `lodash.debounce` in that it waits for promise |
| 71 |
* resolution. |
| 72 |
* |
| 73 |
* @param {Function} func A function that returns a promise. |
| 74 |
* @param {number} delayMS A delay in milliseconds. |
| 75 |
* |
| 76 |
* @return {Function} A function that debounce whatever function is passed |
| 77 |
* to it. |
| 78 |
*/ |
| 79 |
function debounceAsync(func, delayMS) { |
| 80 |
let timeoutId; |
| 81 |
let activePromise; |
| 82 |
return async function debounced() { |
| 83 |
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { |
| 84 |
args[_key] = arguments[_key]; |
| 85 |
} |
| 86 |
|
| 87 |
// This is a leading edge debounce. If there's no promise or timeout |
| 88 |
// in progress, call the debounced function immediately. |
| 89 |
if (!activePromise && !timeoutId) { |
| 90 |
return new Promise((resolve, reject) => { |
| 91 |
// Keep a reference to the promise. |
| 92 |
activePromise = func(...args).then(function () { |
| 93 |
resolve(...arguments); |
| 94 |
}).catch(error => { |
| 95 |
reject(error); |
| 96 |
}).finally(() => { |
| 97 |
// As soon this promise is complete, clear the way for the |
| 98 |
// next one to happen immediately. |
| 99 |
activePromise = null; |
| 100 |
}); |
| 101 |
}); |
| 102 |
} |
| 103 |
|
| 104 |
if (activePromise) { |
| 105 |
// Let any active promises finish before queuing the next request. |
| 106 |
await activePromise; |
| 107 |
} // Clear any active timeouts, abandoning any requests that have |
| 108 |
// been queued but not been made. |
| 109 |
|
| 110 |
|
| 111 |
if (timeoutId) { |
| 112 |
clearTimeout(timeoutId); |
| 113 |
timeoutId = null; |
| 114 |
} // Trigger any trailing edge calls to the function. |
| 115 |
|
| 116 |
|
| 117 |
return new Promise((resolve, reject) => { |
| 118 |
// Schedule the next request but with a delay. |
| 119 |
timeoutId = setTimeout(() => { |
| 120 |
activePromise = func(...args).then(function () { |
| 121 |
resolve(...arguments); |
| 122 |
}).catch(error => { |
| 123 |
reject(error); |
| 124 |
}).finally(() => { |
| 125 |
// As soon this promise is complete, clear the way for the |
| 126 |
// next one to happen immediately. |
| 127 |
activePromise = null; |
| 128 |
timeoutId = null; |
| 129 |
}); |
| 130 |
}, delayMS); |
| 131 |
}); |
| 132 |
}; |
| 133 |
} |
| 134 |
|
| 135 |
;// CONCATENATED MODULE: ./packages/preferences-persistence/build-module/create/index.js |
| 136 |
/** |
| 137 |
* WordPress dependencies |
| 138 |
*/ |
| 139 |
|
| 140 |
/** |
| 141 |
* Internal dependencies |
| 142 |
*/ |
| 143 |
|
| 144 |
|
| 145 |
const EMPTY_OBJECT = {}; |
| 146 |
const localStorage = window.localStorage; |
| 147 |
/** |
| 148 |
* Creates a persistence layer that stores data in WordPress user meta via the |
| 149 |
* REST API. |
| 150 |
* |
| 151 |
* @param {Object} options |
| 152 |
* @param {?Object} options.preloadedData Any persisted preferences data that should be preloaded. |
| 153 |
* When set, the persistence layer will avoid fetching data |
| 154 |
* from the REST API. |
| 155 |
* @param {?string} options.localStorageRestoreKey The key to use for restoring the localStorage backup, used |
| 156 |
* when the persistence layer calls `localStorage.getItem` or |
| 157 |
* `localStorage.setItem`. |
| 158 |
* @param {?number} options.requestDebounceMS Debounce requests to the API so that they only occur at |
| 159 |
* minimum every `requestDebounceMS` milliseconds, and don't |
| 160 |
* swamp the server. Defaults to 2500ms. |
| 161 |
* |
| 162 |
* @return {Object} A persistence layer for WordPress user meta. |
| 163 |
*/ |
| 164 |
|
| 165 |
function create() { |
| 166 |
let { |
| 167 |
preloadedData, |
| 168 |
localStorageRestoreKey = 'WP_PREFERENCES_RESTORE_DATA', |
| 169 |
requestDebounceMS = 2500 |
| 170 |
} = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; |
| 171 |
let cache = preloadedData; |
| 172 |
const debouncedApiFetch = debounceAsync((external_wp_apiFetch_default()), requestDebounceMS); |
| 173 |
|
| 174 |
async function get() { |
| 175 |
var _user$meta; |
| 176 |
|
| 177 |
if (cache) { |
| 178 |
return cache; |
| 179 |
} |
| 180 |
|
| 181 |
const user = await external_wp_apiFetch_default()({ |
| 182 |
path: '/wp/v2/users/me?context=edit' |
| 183 |
}); |
| 184 |
const serverData = user === null || user === void 0 ? void 0 : (_user$meta = user.meta) === null || _user$meta === void 0 ? void 0 : _user$meta.persisted_preferences; |
| 185 |
const localData = JSON.parse(localStorage.getItem(localStorageRestoreKey)); // Date parse returns NaN for invalid input. Coerce anything invalid |
| 186 |
// into a conveniently comparable zero. |
| 187 |
|
| 188 |
const serverTimestamp = Date.parse(serverData === null || serverData === void 0 ? void 0 : serverData._modified) || 0; |
| 189 |
const localTimestamp = Date.parse(localData === null || localData === void 0 ? void 0 : localData._modified) || 0; // Prefer server data if it exists and is more recent. |
| 190 |
// Otherwise fallback to localStorage data. |
| 191 |
|
| 192 |
if (serverData && serverTimestamp >= localTimestamp) { |
| 193 |
cache = serverData; |
| 194 |
} else if (localData) { |
| 195 |
cache = localData; |
| 196 |
} else { |
| 197 |
cache = EMPTY_OBJECT; |
| 198 |
} |
| 199 |
|
| 200 |
return cache; |
| 201 |
} |
| 202 |
|
| 203 |
function set(newData) { |
| 204 |
const dataWithTimestamp = { ...newData, |
| 205 |
_modified: new Date().toISOString() |
| 206 |
}; |
| 207 |
cache = dataWithTimestamp; // Store data in local storage as a fallback. If for some reason the |
| 208 |
// api request does not complete or becomes unavailable, this data |
| 209 |
// can be used to restore preferences. |
| 210 |
|
| 211 |
localStorage.setItem(localStorageRestoreKey, JSON.stringify(dataWithTimestamp)); // The user meta endpoint seems susceptible to errors when consecutive |
| 212 |
// requests are made in quick succession. Ensure there's a gap between |
| 213 |
// any consecutive requests. |
| 214 |
// |
| 215 |
// Catch and do nothing with errors from the REST API. |
| 216 |
|
| 217 |
debouncedApiFetch({ |
| 218 |
path: '/wp/v2/users/me', |
| 219 |
method: 'PUT', |
| 220 |
// `keepalive` will still send the request in the background, |
| 221 |
// even when a browser unload event might interrupt it. |
| 222 |
// This should hopefully make things more resilient. |
| 223 |
// This does have a size limit of 64kb, but the data is usually |
| 224 |
// much less. |
| 225 |
keepalive: true, |
| 226 |
data: { |
| 227 |
meta: { |
| 228 |
persisted_preferences: dataWithTimestamp |
| 229 |
} |
| 230 |
} |
| 231 |
}).catch(() => {}); |
| 232 |
} |
| 233 |
|
| 234 |
return { |
| 235 |
get, |
| 236 |
set |
| 237 |
}; |
| 238 |
} |
| 239 |
|
| 240 |
;// CONCATENATED MODULE: ./packages/preferences-persistence/build-module/migrations/legacy-local-storage-data/move-feature-preferences.js |
| 241 |
/** |
| 242 |
* Move the 'features' object in local storage from the sourceStoreName to the |
| 243 |
* preferences store data structure. |
| 244 |
* |
| 245 |
* Previously, editors used a data structure like this for feature preferences: |
| 246 |
* ```js |
| 247 |
* { |
| 248 |
* 'core/edit-post': { |
| 249 |
* preferences: { |
| 250 |
* features; { |
| 251 |
* topToolbar: true, |
| 252 |
* // ... other boolean 'feature' preferences |
| 253 |
* }, |
| 254 |
* }, |
| 255 |
* }, |
| 256 |
* } |
| 257 |
* ``` |
| 258 |
* |
| 259 |
* And for a while these feature preferences lived in the interface package: |
| 260 |
* ```js |
| 261 |
* { |
| 262 |
* 'core/interface': { |
| 263 |
* preferences: { |
| 264 |
* features: { |
| 265 |
* 'core/edit-post': { |
| 266 |
* topToolbar: true |
| 267 |
* } |
| 268 |
* } |
| 269 |
* } |
| 270 |
* } |
| 271 |
* } |
| 272 |
* ``` |
| 273 |
* |
| 274 |
* In the preferences store, 'features' aren't considered special, they're |
| 275 |
* merged to the root level of the scope along with other preferences: |
| 276 |
* ```js |
| 277 |
* { |
| 278 |
* 'core/preferences': { |
| 279 |
* preferences: { |
| 280 |
* 'core/edit-post': { |
| 281 |
* topToolbar: true, |
| 282 |
* // ... any other preferences. |
| 283 |
* } |
| 284 |
* } |
| 285 |
* } |
| 286 |
* } |
| 287 |
* ``` |
| 288 |
* |
| 289 |
* This function handles moving from either the source store or the interface |
| 290 |
* store to the preferences data structure. |
| 291 |
* |
| 292 |
* @param {Object} state The state before migration. |
| 293 |
* @param {string} sourceStoreName The name of the store that has persisted |
| 294 |
* preferences to migrate to the preferences |
| 295 |
* package. |
| 296 |
* @return {Object} The migrated state |
| 297 |
*/ |
| 298 |
function moveFeaturePreferences(state, sourceStoreName) { |
| 299 |
var _state$interfaceStore, _state$interfaceStore2, _state$interfaceStore3, _state$sourceStoreNam, _state$sourceStoreNam2, _state$preferencesSto; |
| 300 |
|
| 301 |
const preferencesStoreName = 'core/preferences'; |
| 302 |
const interfaceStoreName = 'core/interface'; // Features most recently (and briefly) lived in the interface package. |
| 303 |
// If data exists there, prioritize using that for the migration. If not |
| 304 |
// also check the original package as the user may have updated from an |
| 305 |
// older block editor version. |
| 306 |
|
| 307 |
const interfaceFeatures = state === null || state === void 0 ? void 0 : (_state$interfaceStore = state[interfaceStoreName]) === null || _state$interfaceStore === void 0 ? void 0 : (_state$interfaceStore2 = _state$interfaceStore.preferences) === null || _state$interfaceStore2 === void 0 ? void 0 : (_state$interfaceStore3 = _state$interfaceStore2.features) === null || _state$interfaceStore3 === void 0 ? void 0 : _state$interfaceStore3[sourceStoreName]; |
| 308 |
const sourceFeatures = state === null || state === void 0 ? void 0 : (_state$sourceStoreNam = state[sourceStoreName]) === null || _state$sourceStoreNam === void 0 ? void 0 : (_state$sourceStoreNam2 = _state$sourceStoreNam.preferences) === null || _state$sourceStoreNam2 === void 0 ? void 0 : _state$sourceStoreNam2.features; |
| 309 |
const featuresToMigrate = interfaceFeatures ? interfaceFeatures : sourceFeatures; |
| 310 |
|
| 311 |
if (!featuresToMigrate) { |
| 312 |
return state; |
| 313 |
} |
| 314 |
|
| 315 |
const existingPreferences = state === null || state === void 0 ? void 0 : (_state$preferencesSto = state[preferencesStoreName]) === null || _state$preferencesSto === void 0 ? void 0 : _state$preferencesSto.preferences; // Avoid migrating features again if they've previously been migrated. |
| 316 |
|
| 317 |
if (existingPreferences !== null && existingPreferences !== void 0 && existingPreferences[sourceStoreName]) { |
| 318 |
return state; |
| 319 |
} |
| 320 |
|
| 321 |
let updatedInterfaceState; |
| 322 |
|
| 323 |
if (interfaceFeatures) { |
| 324 |
var _state$interfaceStore4, _state$interfaceStore5; |
| 325 |
|
| 326 |
const otherInterfaceState = state === null || state === void 0 ? void 0 : state[interfaceStoreName]; |
| 327 |
const otherInterfaceScopes = state === null || state === void 0 ? void 0 : (_state$interfaceStore4 = state[interfaceStoreName]) === null || _state$interfaceStore4 === void 0 ? void 0 : (_state$interfaceStore5 = _state$interfaceStore4.preferences) === null || _state$interfaceStore5 === void 0 ? void 0 : _state$interfaceStore5.features; |
| 328 |
updatedInterfaceState = { |
| 329 |
[interfaceStoreName]: { ...otherInterfaceState, |
| 330 |
preferences: { |
| 331 |
features: { ...otherInterfaceScopes, |
| 332 |
[sourceStoreName]: undefined |
| 333 |
} |
| 334 |
} |
| 335 |
} |
| 336 |
}; |
| 337 |
} |
| 338 |
|
| 339 |
let updatedSourceState; |
| 340 |
|
| 341 |
if (sourceFeatures) { |
| 342 |
var _state$sourceStoreNam3; |
| 343 |
|
| 344 |
const otherSourceState = state === null || state === void 0 ? void 0 : state[sourceStoreName]; |
| 345 |
const sourcePreferences = state === null || state === void 0 ? void 0 : (_state$sourceStoreNam3 = state[sourceStoreName]) === null || _state$sourceStoreNam3 === void 0 ? void 0 : _state$sourceStoreNam3.preferences; |
| 346 |
updatedSourceState = { |
| 347 |
[sourceStoreName]: { ...otherSourceState, |
| 348 |
preferences: { ...sourcePreferences, |
| 349 |
features: undefined |
| 350 |
} |
| 351 |
} |
| 352 |
}; |
| 353 |
} // Set the feature values in the interface store, the features |
| 354 |
// object is keyed by 'scope', which matches the store name for |
| 355 |
// the source. |
| 356 |
|
| 357 |
|
| 358 |
return { ...state, |
| 359 |
[preferencesStoreName]: { |
| 360 |
preferences: { ...existingPreferences, |
| 361 |
[sourceStoreName]: featuresToMigrate |
| 362 |
} |
| 363 |
}, |
| 364 |
...updatedInterfaceState, |
| 365 |
...updatedSourceState |
| 366 |
}; |
| 367 |
} |
| 368 |
|
| 369 |
;// CONCATENATED MODULE: ./packages/preferences-persistence/build-module/migrations/legacy-local-storage-data/move-third-party-feature-preferences.js |
| 370 |
/** |
| 371 |
* The interface package previously had a public API that could be used by |
| 372 |
* plugins to set persisted boolean 'feature' preferences. |
| 373 |
* |
| 374 |
* While usage was likely non-existent or very small, this function ensures |
| 375 |
* those are migrated to the preferences data structure. The interface |
| 376 |
* package's APIs have now been deprecated and use the preferences store. |
| 377 |
* |
| 378 |
* This will convert data that looks like this: |
| 379 |
* ```js |
| 380 |
* { |
| 381 |
* 'core/interface': { |
| 382 |
* preferences: { |
| 383 |
* features: { |
| 384 |
* 'my-plugin': { |
| 385 |
* myPluginFeature: true |
| 386 |
* } |
| 387 |
* } |
| 388 |
* } |
| 389 |
* } |
| 390 |
* } |
| 391 |
* ``` |
| 392 |
* |
| 393 |
* To this: |
| 394 |
* ```js |
| 395 |
* * { |
| 396 |
* 'core/preferences': { |
| 397 |
* preferences: { |
| 398 |
* 'my-plugin': { |
| 399 |
* myPluginFeature: true |
| 400 |
* } |
| 401 |
* } |
| 402 |
* } |
| 403 |
* } |
| 404 |
* ``` |
| 405 |
* |
| 406 |
* @param {Object} state The local storage state |
| 407 |
* |
| 408 |
* @return {Object} The state with third party preferences moved to the |
| 409 |
* preferences data structure. |
| 410 |
*/ |
| 411 |
function moveThirdPartyFeaturePreferencesToPreferences(state) { |
| 412 |
var _state$interfaceStore, _state$interfaceStore2; |
| 413 |
|
| 414 |
const interfaceStoreName = 'core/interface'; |
| 415 |
const preferencesStoreName = 'core/preferences'; |
| 416 |
const interfaceScopes = state === null || state === void 0 ? void 0 : (_state$interfaceStore = state[interfaceStoreName]) === null || _state$interfaceStore === void 0 ? void 0 : (_state$interfaceStore2 = _state$interfaceStore.preferences) === null || _state$interfaceStore2 === void 0 ? void 0 : _state$interfaceStore2.features; |
| 417 |
const interfaceScopeKeys = interfaceScopes ? Object.keys(interfaceScopes) : []; |
| 418 |
|
| 419 |
if (!(interfaceScopeKeys !== null && interfaceScopeKeys !== void 0 && interfaceScopeKeys.length)) { |
| 420 |
return state; |
| 421 |
} |
| 422 |
|
| 423 |
return interfaceScopeKeys.reduce(function (convertedState, scope) { |
| 424 |
var _convertedState$prefe, _convertedState$prefe2, _convertedState$prefe3, _convertedState$inter, _convertedState$inter2; |
| 425 |
|
| 426 |
if (scope.startsWith('core')) { |
| 427 |
return convertedState; |
| 428 |
} |
| 429 |
|
| 430 |
const featuresToMigrate = interfaceScopes === null || interfaceScopes === void 0 ? void 0 : interfaceScopes[scope]; |
| 431 |
|
| 432 |
if (!featuresToMigrate) { |
| 433 |
return convertedState; |
| 434 |
} |
| 435 |
|
| 436 |
const existingMigratedData = convertedState === null || convertedState === void 0 ? void 0 : (_convertedState$prefe = convertedState[preferencesStoreName]) === null || _convertedState$prefe === void 0 ? void 0 : (_convertedState$prefe2 = _convertedState$prefe.preferences) === null || _convertedState$prefe2 === void 0 ? void 0 : _convertedState$prefe2[scope]; |
| 437 |
|
| 438 |
if (existingMigratedData) { |
| 439 |
return convertedState; |
| 440 |
} |
| 441 |
|
| 442 |
const otherPreferencesScopes = convertedState === null || convertedState === void 0 ? void 0 : (_convertedState$prefe3 = convertedState[preferencesStoreName]) === null || _convertedState$prefe3 === void 0 ? void 0 : _convertedState$prefe3.preferences; |
| 443 |
const otherInterfaceState = convertedState === null || convertedState === void 0 ? void 0 : convertedState[interfaceStoreName]; |
| 444 |
const otherInterfaceScopes = convertedState === null || convertedState === void 0 ? void 0 : (_convertedState$inter = convertedState[interfaceStoreName]) === null || _convertedState$inter === void 0 ? void 0 : (_convertedState$inter2 = _convertedState$inter.preferences) === null || _convertedState$inter2 === void 0 ? void 0 : _convertedState$inter2.features; |
| 445 |
return { ...convertedState, |
| 446 |
[preferencesStoreName]: { |
| 447 |
preferences: { ...otherPreferencesScopes, |
| 448 |
[scope]: featuresToMigrate |
| 449 |
} |
| 450 |
}, |
| 451 |
[interfaceStoreName]: { ...otherInterfaceState, |
| 452 |
preferences: { |
| 453 |
features: { ...otherInterfaceScopes, |
| 454 |
[scope]: undefined |
| 455 |
} |
| 456 |
} |
| 457 |
} |
| 458 |
}; |
| 459 |
}, state); |
| 460 |
} |
| 461 |
|
| 462 |
;// CONCATENATED MODULE: ./packages/preferences-persistence/build-module/migrations/legacy-local-storage-data/move-individual-preference.js |
| 463 |
const identity = arg => arg; |
| 464 |
/** |
| 465 |
* Migrates an individual item inside the `preferences` object for a package's store. |
| 466 |
* |
| 467 |
* Previously, some packages had individual 'preferences' of any data type, and many used |
| 468 |
* complex nested data structures. For example: |
| 469 |
* ```js |
| 470 |
* { |
| 471 |
* 'core/edit-post': { |
| 472 |
* preferences: { |
| 473 |
* panels: { |
| 474 |
* publish: { |
| 475 |
* opened: true, |
| 476 |
* enabled: true, |
| 477 |
* } |
| 478 |
* }, |
| 479 |
* // ...other preferences. |
| 480 |
* }, |
| 481 |
* }, |
| 482 |
* } |
| 483 |
* |
| 484 |
* This function supports moving an individual preference like 'panels' above into the |
| 485 |
* preferences package data structure. |
| 486 |
* |
| 487 |
* It supports moving a preference to a particular scope in the preferences store and |
| 488 |
* optionally converting the data using a `convert` function. |
| 489 |
* |
| 490 |
* ``` |
| 491 |
* |
| 492 |
* @param {Object} state The original state. |
| 493 |
* @param {Object} migrate An options object that contains details of the migration. |
| 494 |
* @param {string} migrate.from The name of the store to migrate from. |
| 495 |
* @param {string} migrate.to The scope in the preferences store to migrate to. |
| 496 |
* @param {string} key The key in the preferences object to migrate. |
| 497 |
* @param {?Function} convert A function that converts preferences from one format to another. |
| 498 |
*/ |
| 499 |
|
| 500 |
|
| 501 |
function moveIndividualPreferenceToPreferences(state, _ref, key) { |
| 502 |
var _state$sourceStoreNam, _state$sourceStoreNam2, _state$preferencesSto, _state$preferencesSto2, _state$preferencesSto3, _state$preferencesSto4, _state$preferencesSto5, _state$preferencesSto6, _state$sourceStoreNam3; |
| 503 |
|
| 504 |
let { |
| 505 |
from: sourceStoreName, |
| 506 |
to: scope |
| 507 |
} = _ref; |
| 508 |
let convert = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : identity; |
| 509 |
const preferencesStoreName = 'core/preferences'; |
| 510 |
const sourcePreference = state === null || state === void 0 ? void 0 : (_state$sourceStoreNam = state[sourceStoreName]) === null || _state$sourceStoreNam === void 0 ? void 0 : (_state$sourceStoreNam2 = _state$sourceStoreNam.preferences) === null || _state$sourceStoreNam2 === void 0 ? void 0 : _state$sourceStoreNam2[key]; // There's nothing to migrate, exit early. |
| 511 |
|
| 512 |
if (sourcePreference === undefined) { |
| 513 |
return state; |
| 514 |
} |
| 515 |
|
| 516 |
const targetPreference = state === null || state === void 0 ? void 0 : (_state$preferencesSto = state[preferencesStoreName]) === null || _state$preferencesSto === void 0 ? void 0 : (_state$preferencesSto2 = _state$preferencesSto.preferences) === null || _state$preferencesSto2 === void 0 ? void 0 : (_state$preferencesSto3 = _state$preferencesSto2[scope]) === null || _state$preferencesSto3 === void 0 ? void 0 : _state$preferencesSto3[key]; // There's existing data at the target, so don't overwrite it, exit early. |
| 517 |
|
| 518 |
if (targetPreference) { |
| 519 |
return state; |
| 520 |
} |
| 521 |
|
| 522 |
const otherScopes = state === null || state === void 0 ? void 0 : (_state$preferencesSto4 = state[preferencesStoreName]) === null || _state$preferencesSto4 === void 0 ? void 0 : _state$preferencesSto4.preferences; |
| 523 |
const otherPreferences = state === null || state === void 0 ? void 0 : (_state$preferencesSto5 = state[preferencesStoreName]) === null || _state$preferencesSto5 === void 0 ? void 0 : (_state$preferencesSto6 = _state$preferencesSto5.preferences) === null || _state$preferencesSto6 === void 0 ? void 0 : _state$preferencesSto6[scope]; |
| 524 |
const otherSourceState = state === null || state === void 0 ? void 0 : state[sourceStoreName]; |
| 525 |
const allSourcePreferences = state === null || state === void 0 ? void 0 : (_state$sourceStoreNam3 = state[sourceStoreName]) === null || _state$sourceStoreNam3 === void 0 ? void 0 : _state$sourceStoreNam3.preferences; // Pass an object with the key and value as this allows the convert |
| 526 |
// function to convert to a data structure that has different keys. |
| 527 |
|
| 528 |
const convertedPreferences = convert({ |
| 529 |
[key]: sourcePreference |
| 530 |
}); |
| 531 |
return { ...state, |
| 532 |
[preferencesStoreName]: { |
| 533 |
preferences: { ...otherScopes, |
| 534 |
[scope]: { ...otherPreferences, |
| 535 |
...convertedPreferences |
| 536 |
} |
| 537 |
} |
| 538 |
}, |
| 539 |
[sourceStoreName]: { ...otherSourceState, |
| 540 |
preferences: { ...allSourcePreferences, |
| 541 |
[key]: undefined |
| 542 |
} |
| 543 |
} |
| 544 |
}; |
| 545 |
} |
| 546 |
|
| 547 |
;// CONCATENATED MODULE: ./packages/preferences-persistence/build-module/migrations/legacy-local-storage-data/move-interface-enable-items.js |
| 548 |
/** |
| 549 |
* Migrates interface 'enableItems' data to the preferences store. |
| 550 |
* |
| 551 |
* The interface package stores this data in this format: |
| 552 |
* ```js |
| 553 |
* { |
| 554 |
* enableItems: { |
| 555 |
* singleEnableItems: { |
| 556 |
* complementaryArea: { |
| 557 |
* 'core/edit-post': 'edit-post/document', |
| 558 |
* 'core/edit-site': 'edit-site/global-styles', |
| 559 |
* } |
| 560 |
* }, |
| 561 |
* multipleEnableItems: { |
| 562 |
* pinnedItems: { |
| 563 |
* 'core/edit-post': { |
| 564 |
* 'plugin-1': true, |
| 565 |
* }, |
| 566 |
* 'core/edit-site': { |
| 567 |
* 'plugin-2': true, |
| 568 |
* }, |
| 569 |
* }, |
| 570 |
* } |
| 571 |
* } |
| 572 |
* } |
| 573 |
* ``` |
| 574 |
* |
| 575 |
* and it should be converted it to: |
| 576 |
* ```js |
| 577 |
* { |
| 578 |
* 'core/edit-post': { |
| 579 |
* complementaryArea: 'edit-post/document', |
| 580 |
* pinnedItems: { |
| 581 |
* 'plugin-1': true, |
| 582 |
* }, |
| 583 |
* }, |
| 584 |
* 'core/edit-site': { |
| 585 |
* complementaryArea: 'edit-site/global-styles', |
| 586 |
* pinnedItems: { |
| 587 |
* 'plugin-2': true, |
| 588 |
* }, |
| 589 |
* }, |
| 590 |
* } |
| 591 |
* ``` |
| 592 |
* |
| 593 |
* @param {Object} state The local storage state. |
| 594 |
*/ |
| 595 |
function moveInterfaceEnableItems(state) { |
| 596 |
var _state$interfaceStore, _state$preferencesSto, _state$preferencesSto2, _sourceEnableItems$si, _sourceEnableItems$si2, _sourceEnableItems$mu, _sourceEnableItems$mu2; |
| 597 |
|
| 598 |
const interfaceStoreName = 'core/interface'; |
| 599 |
const preferencesStoreName = 'core/preferences'; |
| 600 |
const sourceEnableItems = state === null || state === void 0 ? void 0 : (_state$interfaceStore = state[interfaceStoreName]) === null || _state$interfaceStore === void 0 ? void 0 : _state$interfaceStore.enableItems; // There's nothing to migrate, exit early. |
| 601 |
|
| 602 |
if (!sourceEnableItems) { |
| 603 |
return state; |
| 604 |
} |
| 605 |
|
| 606 |
const allPreferences = (_state$preferencesSto = state === null || state === void 0 ? void 0 : (_state$preferencesSto2 = state[preferencesStoreName]) === null || _state$preferencesSto2 === void 0 ? void 0 : _state$preferencesSto2.preferences) !== null && _state$preferencesSto !== void 0 ? _state$preferencesSto : {}; // First convert complementaryAreas into the right format. |
| 607 |
// Use the existing preferences as the accumulator so that the data is |
| 608 |
// merged. |
| 609 |
|
| 610 |
const sourceComplementaryAreas = (_sourceEnableItems$si = sourceEnableItems === null || sourceEnableItems === void 0 ? void 0 : (_sourceEnableItems$si2 = sourceEnableItems.singleEnableItems) === null || _sourceEnableItems$si2 === void 0 ? void 0 : _sourceEnableItems$si2.complementaryArea) !== null && _sourceEnableItems$si !== void 0 ? _sourceEnableItems$si : {}; |
| 611 |
const preferencesWithConvertedComplementaryAreas = Object.keys(sourceComplementaryAreas).reduce((accumulator, scope) => { |
| 612 |
var _accumulator$scope; |
| 613 |
|
| 614 |
const data = sourceComplementaryAreas[scope]; // Don't overwrite any existing data in the preferences store. |
| 615 |
|
| 616 |
if (accumulator !== null && accumulator !== void 0 && (_accumulator$scope = accumulator[scope]) !== null && _accumulator$scope !== void 0 && _accumulator$scope.complementaryArea) { |
| 617 |
return accumulator; |
| 618 |
} |
| 619 |
|
| 620 |
return { ...accumulator, |
| 621 |
[scope]: { ...accumulator[scope], |
| 622 |
complementaryArea: data |
| 623 |
} |
| 624 |
}; |
| 625 |
}, allPreferences); // Next feed the converted complementary areas back into a reducer that |
| 626 |
// converts the pinned items, resulting in the fully migrated data. |
| 627 |
|
| 628 |
const sourcePinnedItems = (_sourceEnableItems$mu = sourceEnableItems === null || sourceEnableItems === void 0 ? void 0 : (_sourceEnableItems$mu2 = sourceEnableItems.multipleEnableItems) === null || _sourceEnableItems$mu2 === void 0 ? void 0 : _sourceEnableItems$mu2.pinnedItems) !== null && _sourceEnableItems$mu !== void 0 ? _sourceEnableItems$mu : {}; |
| 629 |
const allConvertedData = Object.keys(sourcePinnedItems).reduce((accumulator, scope) => { |
| 630 |
var _accumulator$scope2; |
| 631 |
|
| 632 |
const data = sourcePinnedItems[scope]; // Don't overwrite any existing data in the preferences store. |
| 633 |
|
| 634 |
if (accumulator !== null && accumulator !== void 0 && (_accumulator$scope2 = accumulator[scope]) !== null && _accumulator$scope2 !== void 0 && _accumulator$scope2.pinnedItems) { |
| 635 |
return accumulator; |
| 636 |
} |
| 637 |
|
| 638 |
return { ...accumulator, |
| 639 |
[scope]: { ...accumulator[scope], |
| 640 |
pinnedItems: data |
| 641 |
} |
| 642 |
}; |
| 643 |
}, preferencesWithConvertedComplementaryAreas); |
| 644 |
const otherInterfaceItems = state[interfaceStoreName]; |
| 645 |
return { ...state, |
| 646 |
[preferencesStoreName]: { |
| 647 |
preferences: allConvertedData |
| 648 |
}, |
| 649 |
[interfaceStoreName]: { ...otherInterfaceItems, |
| 650 |
enableItems: undefined |
| 651 |
} |
| 652 |
}; |
| 653 |
} |
| 654 |
|
| 655 |
;// CONCATENATED MODULE: ./packages/preferences-persistence/build-module/migrations/legacy-local-storage-data/convert-edit-post-panels.js |
| 656 |
/** |
| 657 |
* Convert the post editor's panels state from: |
| 658 |
* ``` |
| 659 |
* { |
| 660 |
* panels: { |
| 661 |
* tags: { |
| 662 |
* enabled: true, |
| 663 |
* opened: true, |
| 664 |
* }, |
| 665 |
* permalinks: { |
| 666 |
* enabled: false, |
| 667 |
* opened: false, |
| 668 |
* }, |
| 669 |
* }, |
| 670 |
* } |
| 671 |
* ``` |
| 672 |
* |
| 673 |
* to a new, more concise data structure: |
| 674 |
* { |
| 675 |
* inactivePanels: [ |
| 676 |
* 'permalinks', |
| 677 |
* ], |
| 678 |
* openPanels: [ |
| 679 |
* 'tags', |
| 680 |
* ], |
| 681 |
* } |
| 682 |
* |
| 683 |
* @param {Object} preferences A preferences object. |
| 684 |
* |
| 685 |
* @return {Object} The converted data. |
| 686 |
*/ |
| 687 |
function convertEditPostPanels(preferences) { |
| 688 |
var _preferences$panels; |
| 689 |
|
| 690 |
const panels = (_preferences$panels = preferences === null || preferences === void 0 ? void 0 : preferences.panels) !== null && _preferences$panels !== void 0 ? _preferences$panels : {}; |
| 691 |
return Object.keys(panels).reduce((convertedData, panelName) => { |
| 692 |
const panel = panels[panelName]; |
| 693 |
|
| 694 |
if ((panel === null || panel === void 0 ? void 0 : panel.enabled) === false) { |
| 695 |
convertedData.inactivePanels.push(panelName); |
| 696 |
} |
| 697 |
|
| 698 |
if ((panel === null || panel === void 0 ? void 0 : panel.opened) === true) { |
| 699 |
convertedData.openPanels.push(panelName); |
| 700 |
} |
| 701 |
|
| 702 |
return convertedData; |
| 703 |
}, { |
| 704 |
inactivePanels: [], |
| 705 |
openPanels: [] |
| 706 |
}); |
| 707 |
} |
| 708 |
|
| 709 |
;// CONCATENATED MODULE: ./packages/preferences-persistence/build-module/migrations/legacy-local-storage-data/index.js |
| 710 |
/** |
| 711 |
* Internal dependencies |
| 712 |
*/ |
| 713 |
|
| 714 |
|
| 715 |
|
| 716 |
|
| 717 |
|
| 718 |
/** |
| 719 |
* Gets the legacy local storage data for a given user. |
| 720 |
* |
| 721 |
* @param {string | number} userId The user id. |
| 722 |
* |
| 723 |
* @return {Object | null} The local storage data. |
| 724 |
*/ |
| 725 |
|
| 726 |
function getLegacyData(userId) { |
| 727 |
const key = `WP_DATA_USER_${userId}`; |
| 728 |
const unparsedData = window.localStorage.getItem(key); |
| 729 |
return JSON.parse(unparsedData); |
| 730 |
} |
| 731 |
/** |
| 732 |
* Converts data from the old `@wordpress/data` package format. |
| 733 |
* |
| 734 |
* @param {Object | null | undefined} data The legacy data in its original format. |
| 735 |
* |
| 736 |
* @return {Object | undefined} The converted data or `undefined` if there was |
| 737 |
* nothing to convert. |
| 738 |
*/ |
| 739 |
|
| 740 |
|
| 741 |
function convertLegacyData(data) { |
| 742 |
var _data, _data$corePreference; |
| 743 |
|
| 744 |
if (!data) { |
| 745 |
return; |
| 746 |
} // Move boolean feature preferences from each editor into the |
| 747 |
// preferences store data structure. |
| 748 |
|
| 749 |
|
| 750 |
data = moveFeaturePreferences(data, 'core/edit-widgets'); |
| 751 |
data = moveFeaturePreferences(data, 'core/customize-widgets'); |
| 752 |
data = moveFeaturePreferences(data, 'core/edit-post'); |
| 753 |
data = moveFeaturePreferences(data, 'core/edit-site'); // Move third party boolean feature preferences from the interface package |
| 754 |
// to the preferences store data structure. |
| 755 |
|
| 756 |
data = moveThirdPartyFeaturePreferencesToPreferences(data); // Move and convert the interface store's `enableItems` data into the |
| 757 |
// preferences data structure. |
| 758 |
|
| 759 |
data = moveInterfaceEnableItems(data); // Move individual ad-hoc preferences from various packages into the |
| 760 |
// preferences store data structure. |
| 761 |
|
| 762 |
data = moveIndividualPreferenceToPreferences(data, { |
| 763 |
from: 'core/edit-post', |
| 764 |
to: 'core/edit-post' |
| 765 |
}, 'hiddenBlockTypes'); |
| 766 |
data = moveIndividualPreferenceToPreferences(data, { |
| 767 |
from: 'core/edit-post', |
| 768 |
to: 'core/edit-post' |
| 769 |
}, 'editorMode'); |
| 770 |
data = moveIndividualPreferenceToPreferences(data, { |
| 771 |
from: 'core/edit-post', |
| 772 |
to: 'core/edit-post' |
| 773 |
}, 'preferredStyleVariations'); |
| 774 |
data = moveIndividualPreferenceToPreferences(data, { |
| 775 |
from: 'core/edit-post', |
| 776 |
to: 'core/edit-post' |
| 777 |
}, 'panels', convertEditPostPanels); |
| 778 |
data = moveIndividualPreferenceToPreferences(data, { |
| 779 |
from: 'core/editor', |
| 780 |
to: 'core/edit-post' |
| 781 |
}, 'isPublishSidebarEnabled'); |
| 782 |
data = moveIndividualPreferenceToPreferences(data, { |
| 783 |
from: 'core/edit-site', |
| 784 |
to: 'core/edit-site' |
| 785 |
}, 'editorMode'); // The new system is only concerned with persisting |
| 786 |
// 'core/preferences' preferences reducer, so only return that. |
| 787 |
|
| 788 |
return (_data = data) === null || _data === void 0 ? void 0 : (_data$corePreference = _data['core/preferences']) === null || _data$corePreference === void 0 ? void 0 : _data$corePreference.preferences; |
| 789 |
} |
| 790 |
/** |
| 791 |
* Gets the legacy local storage data for the given user and returns the |
| 792 |
* data converted to the new format. |
| 793 |
* |
| 794 |
* @param {string | number} userId The user id. |
| 795 |
* |
| 796 |
* @return {Object | undefined} The converted data or undefined if no local |
| 797 |
* storage data could be found. |
| 798 |
*/ |
| 799 |
|
| 800 |
function convertLegacyLocalStorageData(userId) { |
| 801 |
const data = getLegacyData(userId); |
| 802 |
return convertLegacyData(data); |
| 803 |
} |
| 804 |
|
| 805 |
;// CONCATENATED MODULE: ./packages/preferences-persistence/build-module/migrations/preferences-package-data/convert-complementary-areas.js |
| 806 |
function convertComplementaryAreas(state) { |
| 807 |
return Object.keys(state).reduce((stateAccumulator, scope) => { |
| 808 |
const scopeData = state[scope]; // If a complementary area is truthy, convert it to the `isComplementaryAreaVisible` boolean. |
| 809 |
|
| 810 |
if (scopeData !== null && scopeData !== void 0 && scopeData.complementaryArea) { |
| 811 |
const updatedScopeData = { ...scopeData |
| 812 |
}; |
| 813 |
delete updatedScopeData.complementaryArea; |
| 814 |
updatedScopeData.isComplementaryAreaVisible = true; |
| 815 |
stateAccumulator[scope] = updatedScopeData; |
| 816 |
return stateAccumulator; |
| 817 |
} |
| 818 |
|
| 819 |
return stateAccumulator; |
| 820 |
}, state); |
| 821 |
} |
| 822 |
|
| 823 |
;// CONCATENATED MODULE: ./packages/preferences-persistence/build-module/migrations/preferences-package-data/index.js |
| 824 |
/** |
| 825 |
* Internal dependencies |
| 826 |
*/ |
| 827 |
|
| 828 |
function convertPreferencesPackageData(data) { |
| 829 |
return convertComplementaryAreas(data); |
| 830 |
} |
| 831 |
|
| 832 |
;// CONCATENATED MODULE: ./packages/preferences-persistence/build-module/index.js |
| 833 |
/** |
| 834 |
* Internal dependencies |
| 835 |
*/ |
| 836 |
|
| 837 |
|
| 838 |
|
| 839 |
|
| 840 |
/** |
| 841 |
* Creates the persistence layer with preloaded data. |
| 842 |
* |
| 843 |
* It prioritizes any data from the server, but falls back first to localStorage |
| 844 |
* restore data, and then to any legacy data. |
| 845 |
* |
| 846 |
* This function is used internally by WordPress in an inline script, so |
| 847 |
* prefixed with `__unstable`. |
| 848 |
* |
| 849 |
* @param {Object} serverData Preferences data preloaded from the server. |
| 850 |
* @param {string} userId The user id. |
| 851 |
* |
| 852 |
* @return {Object} The persistence layer initialized with the preloaded data. |
| 853 |
*/ |
| 854 |
|
| 855 |
function __unstableCreatePersistenceLayer(serverData, userId) { |
| 856 |
const localStorageRestoreKey = `WP_PREFERENCES_USER_${userId}`; |
| 857 |
const localData = JSON.parse(window.localStorage.getItem(localStorageRestoreKey)); // Date parse returns NaN for invalid input. Coerce anything invalid |
| 858 |
// into a conveniently comparable zero. |
| 859 |
|
| 860 |
const serverModified = Date.parse(serverData && serverData._modified) || 0; |
| 861 |
const localModified = Date.parse(localData && localData._modified) || 0; |
| 862 |
let preloadedData; |
| 863 |
|
| 864 |
if (serverData && serverModified >= localModified) { |
| 865 |
preloadedData = convertPreferencesPackageData(serverData); |
| 866 |
} else if (localData) { |
| 867 |
preloadedData = convertPreferencesPackageData(localData); |
| 868 |
} else { |
| 869 |
// Check if there is data in the legacy format from the old persistence system. |
| 870 |
preloadedData = convertLegacyLocalStorageData(userId); |
| 871 |
} |
| 872 |
|
| 873 |
return create({ |
| 874 |
preloadedData, |
| 875 |
localStorageRestoreKey |
| 876 |
}); |
| 877 |
} |
| 878 |
|
| 879 |
(window.wp = window.wp || {}).preferencesPersistence = __webpack_exports__; |
| 880 |
/******/ })() |
| 881 |
; |