| [ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 (function() { 2 "use strict"; 3 var wp; 4 (wp ||= {}).uploadMedia = (() => { 5 var __create = Object.create; 6 var __defProp = Object.defineProperty; 7 var __getOwnPropDesc = Object.getOwnPropertyDescriptor; 8 var __getOwnPropNames = Object.getOwnPropertyNames; 9 var __getProtoOf = Object.getPrototypeOf; 10 var __hasOwnProp = Object.prototype.hasOwnProperty; 11 var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { 12 get: (a, b) => (typeof require !== "undefined" ? require : a)[b] 13 }) : x)(function(x) { 14 if (typeof require !== "undefined") return require.apply(this, arguments); 15 throw Error('Dynamic require of "' + x + '" is not supported'); 16 }); 17 var __commonJS = (cb, mod) => function __require2() { 18 return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; 19 }; 20 var __export = (target, all) => { 21 for (var name in all) 22 __defProp(target, name, { get: all[name], enumerable: true }); 23 }; 24 var __copyProps = (to, from, except, desc) => { 25 if (from && typeof from === "object" || typeof from === "function") { 26 for (let key of __getOwnPropNames(from)) 27 if (!__hasOwnProp.call(to, key) && key !== except) 28 __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); 29 } 30 return to; 31 }; 32 var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( 33 // If the importer is in node compatibility mode or this is not an ESM 34 // file that has been converted to a CommonJS file using a Babel- 35 // compatible transform (i.e. "__esModule" has not been set), then set 36 // "default" to the CommonJS "module.exports" for node compatibility. 37 isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, 38 mod 39 )); 40 var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); 41 42 // package-external:@wordpress/data 43 var require_data = __commonJS({ 44 "package-external:@wordpress/data"(exports, module) { 45 module.exports = window.wp.data; 46 } 47 }); 48 49 // package-external:@wordpress/i18n 50 var require_i18n = __commonJS({ 51 "package-external:@wordpress/i18n"(exports, module) { 52 module.exports = window.wp.i18n; 53 } 54 }); 55 56 // package-external:@wordpress/url 57 var require_url = __commonJS({ 58 "package-external:@wordpress/url"(exports, module) { 59 module.exports = window.wp.url; 60 } 61 }); 62 63 // package-external:@wordpress/blob 64 var require_blob = __commonJS({ 65 "package-external:@wordpress/blob"(exports, module) { 66 module.exports = window.wp.blob; 67 } 68 }); 69 70 // package-external:@wordpress/private-apis 71 var require_private_apis = __commonJS({ 72 "package-external:@wordpress/private-apis"(exports, module) { 73 module.exports = window.wp.privateApis; 74 } 75 }); 76 77 // package-external:@wordpress/element 78 var require_element = __commonJS({ 79 "package-external:@wordpress/element"(exports, module) { 80 module.exports = window.wp.element; 81 } 82 }); 83 84 // package-external:@wordpress/compose 85 var require_compose = __commonJS({ 86 "package-external:@wordpress/compose"(exports, module) { 87 module.exports = window.wp.compose; 88 } 89 }); 90 91 // vendor-external:react/jsx-runtime 92 var require_jsx_runtime = __commonJS({ 93 "vendor-external:react/jsx-runtime"(exports, module) { 94 module.exports = window.ReactJSXRuntime; 95 } 96 }); 97 98 // packages/upload-media/build-module/index.mjs 99 var index_exports = {}; 100 __export(index_exports, { 101 ErrorCode: () => ErrorCode, 102 MediaUploadProvider: () => provider_default, 103 UploadError: () => UploadError, 104 clearFeatureDetectionCache: () => clearFeatureDetectionCache, 105 detectClientSideMediaSupport: () => detectClientSideMediaSupport, 106 getErrorMessage: () => getErrorMessage, 107 getHeicConversionAdvice: () => getHeicConversionAdvice, 108 getHeicUnsupportedMessage: () => getHeicUnsupportedMessage, 109 isClientSideMediaSupported: () => isClientSideMediaSupported, 110 isHeicCanvasSupported: () => isHeicCanvasSupported, 111 store: () => store 112 }); 113 114 // packages/upload-media/build-module/store/index.mjs 115 var import_data = __toESM(require_data(), 1); 116 117 // packages/upload-media/build-module/store/types.mjs 118 var Type = /* @__PURE__ */ ((Type2) => { 119 Type2["Unknown"] = "REDUX_UNKNOWN"; 120 Type2["Add"] = "ADD_ITEM"; 121 Type2["Prepare"] = "PREPARE_ITEM"; 122 Type2["Cancel"] = "CANCEL_ITEM"; 123 Type2["Remove"] = "REMOVE_ITEM"; 124 Type2["RetryItem"] = "RETRY_ITEM"; 125 Type2["ScheduleRetry"] = "SCHEDULE_RETRY"; 126 Type2["PauseItem"] = "PAUSE_ITEM"; 127 Type2["ResumeItem"] = "RESUME_ITEM"; 128 Type2["PauseQueue"] = "PAUSE_QUEUE"; 129 Type2["ResumeQueue"] = "RESUME_QUEUE"; 130 Type2["OperationStart"] = "OPERATION_START"; 131 Type2["OperationFinish"] = "OPERATION_FINISH"; 132 Type2["AddOperations"] = "ADD_OPERATIONS"; 133 Type2["CacheBlobUrl"] = "CACHE_BLOB_URL"; 134 Type2["RevokeBlobUrls"] = "REVOKE_BLOB_URLS"; 135 Type2["UpdateProgress"] = "UPDATE_PROGRESS"; 136 Type2["AccumulateSubSize"] = "ACCUMULATE_SUB_SIZE"; 137 Type2["UpdateSettings"] = "UPDATE_SETTINGS"; 138 return Type2; 139 })(Type || {}); 140 var ItemStatus = /* @__PURE__ */ ((ItemStatus2) => { 141 ItemStatus2["Queued"] = "QUEUED"; 142 ItemStatus2["Processing"] = "PROCESSING"; 143 ItemStatus2["Paused"] = "PAUSED"; 144 ItemStatus2["PendingRetry"] = "PENDING_RETRY"; 145 ItemStatus2["Uploaded"] = "UPLOADED"; 146 ItemStatus2["Error"] = "ERROR"; 147 return ItemStatus2; 148 })(ItemStatus || {}); 149 var OperationType = /* @__PURE__ */ ((OperationType2) => { 150 OperationType2["Prepare"] = "PREPARE"; 151 OperationType2["Upload"] = "UPLOAD"; 152 OperationType2["ResizeCrop"] = "RESIZE_CROP"; 153 OperationType2["Rotate"] = "ROTATE"; 154 OperationType2["TranscodeImage"] = "TRANSCODE_IMAGE"; 155 OperationType2["TranscodeGif"] = "TRANSCODE_GIF"; 156 OperationType2["ThumbnailGeneration"] = "THUMBNAIL_GENERATION"; 157 OperationType2["Finalize"] = "FINALIZE"; 158 OperationType2["DetectUltraHdr"] = "DETECT_ULTRAHDR"; 159 return OperationType2; 160 })(OperationType || {}); 161 162 // packages/upload-media/build-module/store/constants.mjs 163 var STORE_NAME = "core/upload-media"; 164 var DEFAULT_MAX_CONCURRENT_UPLOADS = 5; 165 var DEFAULT_MAX_CONCURRENT_IMAGE_PROCESSING = 2; 166 var DEFAULT_RETRY_SETTINGS = { 167 maxRetryAttempts: 3, 168 initialRetryDelayMs: 1e3, 169 maxRetryDelayMs: 3e4, 170 backoffMultiplier: 2, 171 retryJitter: 0.1 172 }; 173 var CLIENT_SIDE_SUPPORTED_MIME_TYPES = [ 174 "image/jpeg", 175 "image/png", 176 "image/gif", 177 "image/webp", 178 "image/avif" 179 ]; 180 var HEIC_MIME_TYPES = [ 181 "image/heic", 182 "image/heif" 183 ]; 184 185 // packages/upload-media/build-module/store/reducer.mjs 186 var noop = () => { 187 }; 188 var DEFAULT_STATE = { 189 queue: [], 190 queueStatus: "active", 191 blobUrls: {}, 192 settings: { 193 mediaUpload: noop, 194 maxConcurrentUploads: DEFAULT_MAX_CONCURRENT_UPLOADS, 195 maxConcurrentImageProcessing: DEFAULT_MAX_CONCURRENT_IMAGE_PROCESSING, 196 retry: { ...DEFAULT_RETRY_SETTINGS } 197 } 198 }; 199 function reducer(state = DEFAULT_STATE, action = { type: Type.Unknown }) { 200 switch (action.type) { 201 case Type.PauseQueue: { 202 return { 203 ...state, 204 queueStatus: "paused" 205 }; 206 } 207 case Type.ResumeQueue: { 208 return { 209 ...state, 210 queueStatus: "active" 211 }; 212 } 213 case Type.PauseItem: 214 return { 215 ...state, 216 queue: state.queue.map( 217 (item) => item.id === action.id ? { 218 ...item, 219 status: ItemStatus.Paused 220 } : item 221 ) 222 }; 223 case Type.ResumeItem: 224 return { 225 ...state, 226 queue: state.queue.map( 227 (item) => item.id === action.id ? { 228 ...item, 229 status: ItemStatus.Processing 230 } : item 231 ) 232 }; 233 case Type.Add: 234 return { 235 ...state, 236 queue: [...state.queue, action.item] 237 }; 238 case Type.Cancel: 239 return { 240 ...state, 241 queue: state.queue.map( 242 (item) => item.id === action.id ? { 243 ...item, 244 error: action.error 245 } : item 246 ) 247 }; 248 case Type.RetryItem: 249 return { 250 ...state, 251 queue: state.queue.map( 252 (item) => item.id === action.id ? { 253 ...item, 254 status: ItemStatus.Processing, 255 error: void 0, 256 retryCount: (item.retryCount ?? 0) + 1, 257 abortController: new AbortController() 258 } : item 259 ) 260 }; 261 case Type.ScheduleRetry: 262 return { 263 ...state, 264 queue: state.queue.map( 265 (item) => item.id === action.id ? { 266 ...item, 267 status: ItemStatus.PendingRetry, 268 error: action.error, 269 retryCount: action.retryCount, 270 nextRetryTimestamp: action.nextRetryTimestamp 271 } : item 272 ) 273 }; 274 case Type.Remove: 275 return { 276 ...state, 277 queue: state.queue.filter((item) => item.id !== action.id) 278 }; 279 case Type.OperationStart: { 280 return { 281 ...state, 282 queue: state.queue.map( 283 (item) => item.id === action.id ? { 284 ...item, 285 currentOperation: action.operation 286 } : item 287 ) 288 }; 289 } 290 case Type.AddOperations: 291 return { 292 ...state, 293 queue: state.queue.map((item) => { 294 if (item.id !== action.id) { 295 return item; 296 } 297 return { 298 ...item, 299 operations: [ 300 ...item.operations || [], 301 ...action.operations 302 ] 303 }; 304 }) 305 }; 306 case Type.OperationFinish: 307 return { 308 ...state, 309 queue: state.queue.map((item) => { 310 if (item.id !== action.id) { 311 return item; 312 } 313 const operations = item.operations ? item.operations.slice(1) : []; 314 const attachment = item.attachment || action.item.attachment ? { 315 ...item.attachment, 316 ...action.item.attachment 317 } : void 0; 318 return { 319 ...item, 320 currentOperation: void 0, 321 operations, 322 ...action.item, 323 attachment, 324 additionalData: { 325 ...item.additionalData, 326 ...action.item.additionalData 327 } 328 }; 329 }) 330 }; 331 case Type.CacheBlobUrl: { 332 const blobUrls = state.blobUrls[action.id] || []; 333 return { 334 ...state, 335 blobUrls: { 336 ...state.blobUrls, 337 [action.id]: [...blobUrls, action.blobUrl] 338 } 339 }; 340 } 341 case Type.RevokeBlobUrls: { 342 const newBlobUrls = { ...state.blobUrls }; 343 delete newBlobUrls[action.id]; 344 return { 345 ...state, 346 blobUrls: newBlobUrls 347 }; 348 } 349 case Type.UpdateProgress: 350 return { 351 ...state, 352 queue: state.queue.map( 353 (item) => item.id === action.id ? { 354 ...item, 355 progress: action.progress 356 } : item 357 ) 358 }; 359 case Type.AccumulateSubSize: 360 return { 361 ...state, 362 queue: state.queue.map( 363 (item) => item.id === action.id ? { 364 ...item, 365 subSizes: [ 366 ...item.subSizes || [], 367 action.subSize 368 ] 369 } : item 370 ) 371 }; 372 case Type.UpdateSettings: { 373 return { 374 ...state, 375 settings: { 376 ...state.settings, 377 ...action.settings 378 } 379 }; 380 } 381 } 382 return state; 383 } 384 var reducer_default = reducer; 385 386 // packages/upload-media/build-module/store/selectors.mjs 387 var selectors_exports = {}; 388 __export(selectors_exports, { 389 getItems: () => getItems, 390 getSettings: () => getSettings, 391 isUploading: () => isUploading, 392 isUploadingById: () => isUploadingById, 393 isUploadingByUrl: () => isUploadingByUrl 394 }); 395 function getItems(state) { 396 return state.queue; 397 } 398 function isUploading(state) { 399 return state.queue.length >= 1; 400 } 401 function isUploadingByUrl(state, url) { 402 return state.queue.some( 403 (item) => item.attachment?.url === url || item.sourceUrl === url 404 ); 405 } 406 function isUploadingById(state, attachmentId) { 407 return state.queue.some( 408 (item) => item.attachment?.id === attachmentId || item.sourceAttachmentId === attachmentId 409 ); 410 } 411 function getSettings(state) { 412 return state.settings; 413 } 414 415 // packages/upload-media/build-module/store/private-selectors.mjs 416 var private_selectors_exports = {}; 417 __export(private_selectors_exports, { 418 getActiveImageProcessingCount: () => getActiveImageProcessingCount, 419 getActiveUploadCount: () => getActiveUploadCount, 420 getActiveVideoProcessingCount: () => getActiveVideoProcessingCount, 421 getAllItems: () => getAllItems, 422 getBlobUrls: () => getBlobUrls, 423 getFailedItems: () => getFailedItems, 424 getItem: () => getItem, 425 getItemProgress: () => getItemProgress, 426 getPendingImageProcessing: () => getPendingImageProcessing, 427 getPendingUploads: () => getPendingUploads, 428 getPendingVideoProcessing: () => getPendingVideoProcessing, 429 hasPendingItemsByParentId: () => hasPendingItemsByParentId, 430 isBatchUploaded: () => isBatchUploaded, 431 isPaused: () => isPaused 432 }); 433 function getAllItems(state) { 434 return state.queue; 435 } 436 function getItem(state, id) { 437 return state.queue.find((item) => item.id === id); 438 } 439 function isBatchUploaded(state, batchId) { 440 const batchItems = state.queue.filter( 441 (item) => batchId === item.batchId 442 ); 443 return batchItems.length === 0; 444 } 445 function isPaused(state) { 446 return state.queueStatus === "paused"; 447 } 448 function getBlobUrls(state, id) { 449 return state.blobUrls[id] || []; 450 } 451 function getActiveUploadCount(state) { 452 return state.queue.filter( 453 (item) => item.currentOperation === OperationType.Upload 454 ).length; 455 } 456 function getPendingUploads(state) { 457 return state.queue.filter((item) => { 458 const nextOperation = Array.isArray(item.operations?.[0]) ? item.operations[0][0] : item.operations?.[0]; 459 return nextOperation === OperationType.Upload && item.currentOperation !== OperationType.Upload; 460 }); 461 } 462 function getActiveImageProcessingCount(state) { 463 return state.queue.filter( 464 (item) => item.currentOperation === OperationType.ResizeCrop || item.currentOperation === OperationType.Rotate 465 ).length; 466 } 467 function getActiveVideoProcessingCount(state) { 468 return state.queue.filter( 469 (item) => item.currentOperation === OperationType.TranscodeGif 470 ).length; 471 } 472 function getPendingImageProcessing(state) { 473 return state.queue.filter((item) => { 474 const nextOperation = Array.isArray(item.operations?.[0]) ? item.operations[0][0] : item.operations?.[0]; 475 return (nextOperation === OperationType.ResizeCrop || nextOperation === OperationType.Rotate) && item.currentOperation !== OperationType.ResizeCrop && item.currentOperation !== OperationType.Rotate; 476 }); 477 } 478 function getPendingVideoProcessing(state) { 479 return state.queue.filter((item) => { 480 const nextOperation = Array.isArray(item.operations?.[0]) ? item.operations[0][0] : item.operations?.[0]; 481 return nextOperation === OperationType.TranscodeGif && item.currentOperation !== OperationType.TranscodeGif; 482 }); 483 } 484 function getFailedItems(state) { 485 return state.queue.filter((item) => item.error !== void 0); 486 } 487 function hasPendingItemsByParentId(state, parentId) { 488 return state.queue.some((item) => item.parentId === parentId); 489 } 490 function getItemProgress(state, id) { 491 const item = state.queue.find((i) => i.id === id); 492 return item?.progress; 493 } 494 495 // packages/upload-media/build-module/store/actions.mjs 496 var actions_exports = {}; 497 __export(actions_exports, { 498 addItems: () => addItems, 499 cancelItem: () => cancelItem, 500 executeRetry: () => executeRetry, 501 retryItem: () => retryItem, 502 scheduleRetry: () => scheduleRetry 503 }); 504 505 // node_modules/uuid/dist/stringify.js 506 var byteToHex = []; 507 for (let i = 0; i < 256; ++i) { 508 byteToHex.push((i + 256).toString(16).slice(1)); 509 } 510 function unsafeStringify(arr, offset = 0) { 511 return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); 512 } 513 514 // node_modules/uuid/dist/rng.js 515 var rnds8 = new Uint8Array(16); 516 function rng() { 517 return crypto.getRandomValues(rnds8); 518 } 519 520 // node_modules/uuid/dist/v4.js 521 function v4(options, buf, offset) { 522 if (!buf && !options && crypto.randomUUID) { 523 return crypto.randomUUID(); 524 } 525 return _v4(options, buf, offset); 526 } 527 function _v4(options, buf, offset) { 528 options = options || {}; 529 const rnds = options.random ?? options.rng?.() ?? rng(); 530 if (rnds.length < 16) { 531 throw new Error("Random bytes length must be >= 16"); 532 } 533 rnds[6] = rnds[6] & 15 | 64; 534 rnds[8] = rnds[8] & 63 | 128; 535 if (buf) { 536 offset = offset || 0; 537 if (offset < 0 || offset + 16 > buf.length) { 538 throw new RangeError(`UUID byte range $offset}:$offset + 15} is out of buffer bounds`); 539 } 540 for (let i = 0; i < 16; ++i) { 541 buf[offset + i] = rnds[i]; 542 } 543 return buf; 544 } 545 return unsafeStringify(rnds); 546 } 547 var v4_default = v4; 548 549 // packages/upload-media/build-module/store/actions.mjs 550 var import_i18n5 = __toESM(require_i18n(), 1); 551 552 // packages/upload-media/build-module/store/utils/retry.mjs 553 function calculateRetryDelay(options) { 554 const { attempt, initialDelay, maxDelay, multiplier, jitter } = options; 555 const exponentialDelay = initialDelay * Math.pow(multiplier, attempt - 1); 556 const cappedDelay = Math.min(exponentialDelay, maxDelay); 557 const jitterFactor = 1 + (Math.random() * 2 - 1) * jitter; 558 return Math.floor(cappedDelay * jitterFactor); 559 } 560 var RETRYABLE_MESSAGE_PATTERNS = [ 561 /network/i, 562 /timeout/i, 563 /ECONNRESET/i, 564 /fetch failed/i, 565 /connection/i, 566 /socket/i, 567 /ETIMEDOUT/i, 568 /ENOTFOUND/i, 569 /Could not get a valid response/i, 570 /Failed to fetch/i, 571 /Load failed/i 572 ]; 573 function shouldRetryError(error, retryCount, maxRetries) { 574 if (retryCount >= maxRetries) { 575 return false; 576 } 577 const message = typeof error === "string" ? error : error?.message || ""; 578 return RETRYABLE_MESSAGE_PATTERNS.some( 579 (pattern) => pattern.test(message) 580 ); 581 } 582 var retryTimers = /* @__PURE__ */ new Map(); 583 function clearRetryTimer(id) { 584 const pendingTimer = retryTimers.get(id); 585 if (pendingTimer !== void 0) { 586 clearTimeout(pendingTimer); 587 retryTimers.delete(id); 588 } 589 } 590 591 // packages/upload-media/build-module/image-file.mjs 592 var ImageFile = class extends File { 593 width = 0; 594 height = 0; 595 originalWidth = 0; 596 originalHeight = 0; 597 get wasResized() { 598 return (this.originalWidth || 0) > this.width || (this.originalHeight || 0) > this.height; 599 } 600 constructor(file, width, height, originalWidth, originalHeight) { 601 super([file], file.name, { 602 type: file.type, 603 lastModified: file.lastModified 604 }); 605 this.width = width; 606 this.height = height; 607 this.originalWidth = originalWidth; 608 this.originalHeight = originalHeight; 609 } 610 }; 611 612 // packages/upload-media/build-module/utils.mjs 613 var import_url = __toESM(require_url(), 1); 614 var import_i18n = __toESM(require_i18n(), 1); 615 function convertBlobToFile(fileOrBlob) { 616 if (fileOrBlob instanceof File) { 617 return fileOrBlob; 618 } 619 if ("name" in fileOrBlob && typeof fileOrBlob.name === "string") { 620 return new File([fileOrBlob], fileOrBlob.name, { 621 type: fileOrBlob.type, 622 lastModified: fileOrBlob.lastModified 623 }); 624 } 625 const ext = fileOrBlob.type.split("/")[1]; 626 const mediaType = "application/pdf" === fileOrBlob.type ? "document" : fileOrBlob.type.split("/")[0]; 627 return new File([fileOrBlob], `$mediaType}.$ext}`, { 628 type: fileOrBlob.type 629 }); 630 } 631 function renameFile(file, name) { 632 return new File([file], name, { 633 type: file.type, 634 lastModified: file.lastModified 635 }); 636 } 637 function cloneFile(file) { 638 return renameFile(file, file.name); 639 } 640 function getFileBasename(name) { 641 return name.includes(".") ? name.split(".").slice(0, -1).join(".") : name; 642 } 643 function isAnimatedGif(buffer) { 644 const view = new Uint8Array(buffer); 645 if (view.length < 4 || view[0] !== 71 || view[1] !== 73 || view[2] !== 70 || view[3] !== 56) { 646 return false; 647 } 648 let frameCount = 0; 649 for (let i = 0; i < view.length - 2; i++) { 650 if (view[i] === 0 && view[i + 1] === 33 && view[i + 2] === 249) { 651 frameCount++; 652 if (frameCount > 1) { 653 return true; 654 } 655 } 656 } 657 return false; 658 } 659 660 // packages/upload-media/build-module/store/utils/index.mjs 661 var vipsModulePromise; 662 var vipsModule; 663 function loadVipsModule() { 664 if (!vipsModulePromise) { 665 vipsModulePromise = import("@wordpress/vips/worker").then( 666 (mod) => { 667 vipsModule = mod; 668 return mod; 669 } 670 ); 671 } 672 return vipsModulePromise; 673 } 674 async function vipsConvertImageFormat(id, file, type, options = {}) { 675 const { vipsConvertImageFormat: convertImageFormat } = await loadVipsModule(); 676 const buffer = await convertImageFormat( 677 id, 678 await file.arrayBuffer(), 679 file.type, 680 type, 681 options 682 ); 683 const ext = type.split("/")[1]; 684 const fileName = `$getFileBasename(file.name)}.$ext}`; 685 return new File([new Blob([buffer])], fileName, { 686 type 687 }); 688 } 689 async function vipsHasTransparency(url) { 690 const { vipsHasTransparency: hasTransparency } = await loadVipsModule(); 691 const response = await fetch(url); 692 if (!response.ok) { 693 throw new Error(`Failed to fetch image: $response.status}`); 694 } 695 return hasTransparency(await response.arrayBuffer()); 696 } 697 async function vipsGetUltraHdrInfo(buffer) { 698 const { vipsGetUltraHdrInfo: getUltraHdrInfo } = await loadVipsModule(); 699 return getUltraHdrInfo(buffer); 700 } 701 async function vipsResizeImage(id, file, resize, options = {}) { 702 const { 703 smartCrop = false, 704 addSuffix = false, 705 signal, 706 scaledSuffix, 707 quality, 708 stripMeta, 709 maxBitdepth 710 } = options; 711 if (signal?.aborted) { 712 throw new Error("Operation aborted"); 713 } 714 const { vipsResizeImage: resizeImage } = await loadVipsModule(); 715 const { buffer, width, height, originalWidth, originalHeight } = await resizeImage(id, await file.arrayBuffer(), file.type, resize, { 716 smartCrop, 717 quality, 718 stripMeta, 719 maxBitdepth 720 }); 721 let fileName = file.name; 722 const wasResized = originalWidth > width || originalHeight > height; 723 if (wasResized) { 724 const basename = getFileBasename(file.name); 725 if (scaledSuffix) { 726 fileName = file.name.replace(basename, `$basename}-scaled`); 727 } else if (addSuffix) { 728 fileName = file.name.replace( 729 basename, 730 `$basename}-$width}x$height}` 731 ); 732 } 733 } 734 const resultFile = new ImageFile( 735 new File( 736 [new Blob([buffer], { type: file.type })], 737 fileName, 738 { 739 type: file.type 740 } 741 ), 742 width, 743 height, 744 originalWidth, 745 originalHeight 746 ); 747 return resultFile; 748 } 749 async function vipsRotateImage(id, file, orientation, signal) { 750 if (signal?.aborted) { 751 throw new Error("Operation aborted"); 752 } 753 if (orientation === 1) { 754 return file; 755 } 756 const { vipsRotateImage: rotateImage } = await loadVipsModule(); 757 const { buffer, width, height } = await rotateImage( 758 id, 759 await file.arrayBuffer(), 760 file.type, 761 orientation 762 ); 763 const basename = getFileBasename(file.name); 764 const fileName = file.name.replace(basename, `$basename}-rotated`); 765 const resultFile = new ImageFile( 766 new File( 767 [new Blob([buffer], { type: file.type })], 768 fileName, 769 { 770 type: file.type 771 } 772 ), 773 width, 774 height 775 ); 776 return resultFile; 777 } 778 async function vipsCancelOperations(id) { 779 if (!vipsModule) { 780 return false; 781 } 782 return vipsModule.vipsCancelOperations(id); 783 } 784 function terminateVipsWorker() { 785 if (vipsModule) { 786 vipsModule.terminateVipsWorker(); 787 } 788 } 789 var completedVipsOperations = 0; 790 var MAX_VIPS_OPS_BEFORE_RECYCLE = 50; 791 function maybeRecycleVipsWorker(activeImageProcessingCount) { 792 completedVipsOperations++; 793 if (completedVipsOperations >= MAX_VIPS_OPS_BEFORE_RECYCLE && activeImageProcessingCount === 0) { 794 terminateVipsWorker(); 795 completedVipsOperations = 0; 796 } 797 } 798 799 // packages/upload-media/build-module/store/utils/video-conversion.mjs 800 var UNSUPPORTED_ERROR_PREFIX = "Unsupported"; 801 var SIZE_LIMIT_ERROR_PREFIX = `$UNSUPPORTED_ERROR_PREFIX}: GIF exceeds maximum conversion size`; 802 var CONVERSION_TIMEOUT_ERROR_PREFIX = "GIF to video conversion timed out"; 803 var DEFAULT_CONVERSION_TIMEOUT = 3e4; 804 function isUnsupportedConversionError(error) { 805 return error instanceof Error && error.message.startsWith(UNSUPPORTED_ERROR_PREFIX); 806 } 807 function isSizeLimitConversionError(error) { 808 return error instanceof Error && error.message.startsWith(SIZE_LIMIT_ERROR_PREFIX); 809 } 810 function isConversionTimeoutError(error) { 811 return error instanceof Error && error.message.startsWith(CONVERSION_TIMEOUT_ERROR_PREFIX); 812 } 813 var videoConversionModulePromise; 814 var videoConversionModule; 815 function loadVideoConversionModule() { 816 if (!videoConversionModulePromise) { 817 videoConversionModulePromise = import("@wordpress/video-conversion/worker").then((mod) => { 818 videoConversionModule = mod; 819 return mod; 820 }).catch((error) => { 821 videoConversionModulePromise = void 0; 822 throw error; 823 }); 824 } 825 return videoConversionModulePromise; 826 } 827 async function convertGifToVideo(id, file, outputMimeType, { 828 maxDimensions, 829 timeout = DEFAULT_CONVERSION_TIMEOUT, 830 maxTotalPixels 831 } = {}) { 832 const mod = await loadVideoConversionModule(); 833 const conversion = mod.convertGifToVideo( 834 id, 835 file, 836 outputMimeType, 837 maxDimensions, 838 maxTotalPixels 839 ); 840 let buffer; 841 if (timeout > 0) { 842 let timer; 843 try { 844 buffer = await Promise.race([ 845 conversion, 846 new Promise((_, reject) => { 847 timer = setTimeout(() => { 848 reject( 849 new Error( 850 `$CONVERSION_TIMEOUT_ERROR_PREFIX} after $timeout}ms` 851 ) 852 ); 853 }, timeout); 854 }) 855 ]); 856 } catch (error) { 857 if (isConversionTimeoutError(error)) { 858 conversion.catch(() => { 859 }); 860 mod.cancelGifToVideoOperations(id).catch(() => { 861 }); 862 } 863 throw error; 864 } finally { 865 clearTimeout(timer); 866 } 867 } else { 868 buffer = await conversion; 869 } 870 const ext = outputMimeType === "video/webm" ? "webm" : "mp4"; 871 const fileName = `$getFileBasename(file.name)}.$ext}`; 872 return new File( 873 [new Blob([buffer], { type: outputMimeType })], 874 fileName, 875 { type: outputMimeType } 876 ); 877 } 878 async function cancelGifToVideoOperations(id) { 879 const mod = videoConversionModule ?? (videoConversionModulePromise ? await videoConversionModulePromise.catch(() => void 0) : void 0); 880 if (!mod) { 881 return false; 882 } 883 return mod.cancelGifToVideoOperations(id); 884 } 885 function terminateVideoConversionWorker() { 886 if (videoConversionModule) { 887 videoConversionModule.terminateVideoConversionWorker(); 888 return; 889 } 890 if (videoConversionModulePromise) { 891 void videoConversionModulePromise.then((mod) => mod.terminateVideoConversionWorker()).catch(() => { 892 }); 893 } 894 } 895 896 // packages/upload-media/build-module/store/utils/debug-logger.mjs 897 function isDebugEnabled() { 898 return true; 899 } 900 function debug(message, ...args) { 901 if (!isDebugEnabled()) { 902 return; 903 } 904 console.debug(`[upload-media] $message}`, ...args); 905 } 906 function measure(options) { 907 if (!isDebugEnabled()) { 908 return; 909 } 910 const { 911 measureName, 912 startTime, 913 endTime = performance.now(), 914 tooltipText, 915 properties 916 } = options; 917 const detail = { 918 devtools: { 919 dataType: "track-entry", 920 track: "Upload Media", 921 tooltipText, 922 properties: properties?.map(([key, value]) => ({ 923 key, 924 value 925 })) 926 } 927 }; 928 try { 929 performance.measure(measureName, { 930 start: startTime, 931 end: endTime, 932 detail 933 }); 934 } catch { 935 } 936 } 937 938 // packages/upload-media/build-module/upload-error.mjs 939 var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => { 940 ErrorCode2["EMPTY_FILE"] = "EMPTY_FILE"; 941 ErrorCode2["SIZE_ABOVE_LIMIT"] = "SIZE_ABOVE_LIMIT"; 942 ErrorCode2["MIME_TYPE_NOT_SUPPORTED"] = "MIME_TYPE_NOT_SUPPORTED"; 943 ErrorCode2["MIME_TYPE_NOT_ALLOWED_FOR_USER"] = "MIME_TYPE_NOT_ALLOWED_FOR_USER"; 944 ErrorCode2["HEIC_DECODE_ERROR"] = "HEIC_DECODE_ERROR"; 945 ErrorCode2["IMAGE_TRANSCODING_ERROR"] = "IMAGE_TRANSCODING_ERROR"; 946 ErrorCode2["IMAGE_ROTATION_ERROR"] = "IMAGE_ROTATION_ERROR"; 947 ErrorCode2["MEDIA_TRANSCODING_ERROR"] = "MEDIA_TRANSCODING_ERROR"; 948 ErrorCode2["GIF_TRANSCODING_ERROR"] = "GIF_TRANSCODING_ERROR"; 949 ErrorCode2["MEDIA_FINALIZE_ERROR"] = "MEDIA_FINALIZE_ERROR"; 950 ErrorCode2["GENERAL"] = "GENERAL"; 951 return ErrorCode2; 952 })(ErrorCode || {}); 953 var UploadError = class extends Error { 954 code; 955 file; 956 constructor({ code, message, file, cause }) { 957 super(message, { cause }); 958 Object.setPrototypeOf(this, new.target.prototype); 959 this.code = code; 960 this.file = file; 961 } 962 }; 963 964 // packages/upload-media/build-module/validate-mime-type.mjs 965 var import_i18n2 = __toESM(require_i18n(), 1); 966 function validateMimeType(file, allowedTypes) { 967 if (!allowedTypes) { 968 return; 969 } 970 const isAllowedType = allowedTypes.some((allowedType) => { 971 if (allowedType.includes("/")) { 972 return allowedType === file.type; 973 } 974 return file.type.startsWith(`$allowedType}/`); 975 }); 976 if (file.type && !isAllowedType) { 977 throw new UploadError({ 978 code: ErrorCode.MIME_TYPE_NOT_SUPPORTED, 979 message: (0, import_i18n2.sprintf)( 980 // translators: %s: file name. 981 (0, import_i18n2.__)("%s: Sorry, this file type is not supported here."), 982 file.name 983 ), 984 file 985 }); 986 } 987 } 988 989 // packages/upload-media/build-module/validate-mime-type-for-user.mjs 990 var import_i18n3 = __toESM(require_i18n(), 1); 991 992 // packages/upload-media/build-module/get-mime-types-array.mjs 993 function getMimeTypesArray(wpMimeTypesObject) { 994 if (!wpMimeTypesObject) { 995 return null; 996 } 997 return Object.entries(wpMimeTypesObject).flatMap( 998 ([extensionsString, mime]) => { 999 const [type] = mime.split("/"); 1000 const extensions = extensionsString.split("|"); 1001 return [ 1002 mime, 1003 ...extensions.map( 1004 (extension) => `$type}/$extension}` 1005 ) 1006 ]; 1007 } 1008 ); 1009 } 1010 1011 // packages/upload-media/build-module/validate-mime-type-for-user.mjs 1012 function validateMimeTypeForUser(file, wpAllowedMimeTypes) { 1013 const allowedMimeTypesForUser = getMimeTypesArray(wpAllowedMimeTypes); 1014 if (!allowedMimeTypesForUser) { 1015 return; 1016 } 1017 const isAllowedMimeTypeForUser = allowedMimeTypesForUser.includes( 1018 file.type 1019 ); 1020 if (file.type && !isAllowedMimeTypeForUser) { 1021 throw new UploadError({ 1022 code: ErrorCode.MIME_TYPE_NOT_ALLOWED_FOR_USER, 1023 message: (0, import_i18n3.sprintf)( 1024 // translators: %s: file name. 1025 (0, import_i18n3.__)( 1026 "%s: Sorry, you are not allowed to upload this file type." 1027 ), 1028 file.name 1029 ), 1030 file 1031 }); 1032 } 1033 } 1034 1035 // packages/upload-media/build-module/validate-file-size.mjs 1036 var import_i18n4 = __toESM(require_i18n(), 1); 1037 function validateFileSize(file, maxUploadFileSize) { 1038 if (file.size <= 0) { 1039 throw new UploadError({ 1040 code: ErrorCode.EMPTY_FILE, 1041 message: (0, import_i18n4.sprintf)( 1042 // translators: %s: file name. 1043 (0, import_i18n4.__)("%s: This file is empty."), 1044 file.name 1045 ), 1046 file 1047 }); 1048 } 1049 if (maxUploadFileSize && file.size > maxUploadFileSize) { 1050 throw new UploadError({ 1051 code: ErrorCode.SIZE_ABOVE_LIMIT, 1052 message: (0, import_i18n4.sprintf)( 1053 // translators: %s: file name. 1054 (0, import_i18n4.__)( 1055 "%s: This file exceeds the maximum upload size for this site." 1056 ), 1057 file.name 1058 ), 1059 file 1060 }); 1061 } 1062 } 1063 1064 // packages/upload-media/build-module/store/actions.mjs 1065 function addItems({ 1066 files, 1067 onChange, 1068 onSuccess, 1069 onError, 1070 onBatchSuccess, 1071 additionalData, 1072 allowedTypes 1073 }) { 1074 return async ({ select: select2, dispatch }) => { 1075 const batchId = v4_default(); 1076 for (const file of files) { 1077 try { 1078 validateMimeType(file, allowedTypes); 1079 validateMimeTypeForUser( 1080 file, 1081 select2.getSettings().allowedMimeTypes 1082 ); 1083 } catch (error) { 1084 onError?.(error); 1085 continue; 1086 } 1087 try { 1088 validateFileSize( 1089 file, 1090 select2.getSettings().maxUploadFileSize 1091 ); 1092 } catch (error) { 1093 onError?.(error); 1094 continue; 1095 } 1096 dispatch.addItem({ 1097 file, 1098 batchId, 1099 onChange, 1100 onSuccess, 1101 onBatchSuccess, 1102 onError, 1103 additionalData 1104 }); 1105 } 1106 }; 1107 } 1108 function cancelItem(id, error, silent = false) { 1109 return async ({ select: select2, dispatch }) => { 1110 const item = select2.getItem(id); 1111 if (!item) { 1112 return; 1113 } 1114 clearRetryTimer(id); 1115 if (!silent && error && !item.parentId && !item.attachment?.id) { 1116 const settings = select2.getSettings(); 1117 const retrySettings = settings.retry; 1118 if (retrySettings) { 1119 const retryCount = item.retryCount ?? 0; 1120 const maxRetries = retrySettings.maxRetryAttempts; 1121 if (shouldRetryError(error, retryCount, maxRetries)) { 1122 dispatch.scheduleRetry(id, error); 1123 return; 1124 } 1125 } 1126 } 1127 item.abortController?.abort(); 1128 vipsCancelOperations(id).catch(() => { 1129 }); 1130 cancelGifToVideoOperations(id).catch(() => { 1131 }); 1132 if (!silent) { 1133 const { onError } = item; 1134 onError?.(error ?? new Error("Upload cancelled")); 1135 if (!onError && error && !item.parentId) { 1136 console.error("Upload cancelled", error); 1137 } 1138 } else { 1139 debug( 1140 `Item cancelled: $item.file.name} (item $id}): $error instanceof Error ? error.message : error}` 1141 ); 1142 } 1143 const { currentOperation, parentId, batchId } = item; 1144 dispatch({ 1145 type: Type.Cancel, 1146 id, 1147 error 1148 }); 1149 dispatch.removeItem(id); 1150 dispatch.revokeBlobUrls(id); 1151 if (currentOperation === OperationType.ResizeCrop || currentOperation === OperationType.Rotate) { 1152 for (const pending of select2.getPendingImageProcessing()) { 1153 dispatch.processItem(pending.id); 1154 } 1155 } 1156 if (currentOperation === OperationType.Upload) { 1157 for (const pending of select2.getPendingUploads()) { 1158 dispatch.processItem(pending.id); 1159 } 1160 } 1161 if (currentOperation === OperationType.TranscodeGif) { 1162 for (const pending of select2.getPendingVideoProcessing()) { 1163 dispatch.processItem(pending.id); 1164 } 1165 } 1166 if (currentOperation === OperationType.ResizeCrop || currentOperation === OperationType.Rotate || currentOperation === OperationType.TranscodeImage) { 1167 maybeRecycleVipsWorker(select2.getActiveImageProcessingCount()); 1168 } 1169 if (parentId) { 1170 const parentItem = select2.getItem(parentId); 1171 if (parentItem) { 1172 const isOptionalCompanion = item.additionalData?.image_size === "animated_video" || item.additionalData?.image_size === "animated_video_poster"; 1173 if (select2.hasPendingItemsByParentId(parentId)) { 1174 if (parentItem.operations && parentItem.operations.length > 0) { 1175 dispatch.processItem(parentId); 1176 } 1177 } else if (parentItem.subSizes && parentItem.subSizes.length > 0 || isOptionalCompanion) { 1178 if (parentItem.operations && parentItem.operations.length > 0) { 1179 dispatch.processItem(parentId); 1180 } 1181 } else { 1182 const parentAttachmentId = parentItem.attachment?.id; 1183 const { mediaDelete } = select2.getSettings(); 1184 if (parentAttachmentId && mediaDelete) { 1185 mediaDelete(parentAttachmentId).catch(() => { 1186 }); 1187 } 1188 await dispatch.cancelItem( 1189 parentId, 1190 new UploadError({ 1191 code: error instanceof UploadError && error.code || ErrorCode.GENERAL, 1192 message: error?.message || (0, import_i18n5.__)("The image could not be uploaded."), 1193 file: parentItem.file, 1194 cause: error instanceof Error ? error : void 0 1195 }) 1196 ); 1197 } 1198 } 1199 } 1200 if (batchId && select2.isBatchUploaded(batchId)) { 1201 debug(`Batch completed: $batchId}`); 1202 item.onBatchSuccess?.(); 1203 } 1204 }; 1205 } 1206 function retryItem(id) { 1207 return async ({ select: select2, dispatch }) => { 1208 const item = select2.getItem(id); 1209 if (!item) { 1210 return; 1211 } 1212 if (!item.error) { 1213 return; 1214 } 1215 dispatch({ 1216 type: Type.RetryItem, 1217 id 1218 }); 1219 dispatch.processItem(id); 1220 }; 1221 } 1222 function scheduleRetry(id, error) { 1223 return async ({ select: select2, dispatch }) => { 1224 const item = select2.getItem(id); 1225 if (!item) { 1226 return; 1227 } 1228 const settings = select2.getSettings(); 1229 const retrySettings = settings.retry; 1230 if (!retrySettings) { 1231 return; 1232 } 1233 const currentRetryCount = item.retryCount ?? 0; 1234 const delay = calculateRetryDelay({ 1235 attempt: currentRetryCount + 1, 1236 initialDelay: retrySettings.initialRetryDelayMs, 1237 maxDelay: retrySettings.maxRetryDelayMs, 1238 multiplier: retrySettings.backoffMultiplier, 1239 jitter: retrySettings.retryJitter 1240 }); 1241 const timerId = setTimeout(() => { 1242 retryTimers.delete(id); 1243 dispatch.executeRetry(id); 1244 }, delay); 1245 retryTimers.set(id, timerId); 1246 dispatch({ 1247 type: Type.ScheduleRetry, 1248 id, 1249 error, 1250 retryCount: currentRetryCount, 1251 nextRetryTimestamp: Date.now() + delay 1252 }); 1253 }; 1254 } 1255 function executeRetry(id) { 1256 return async ({ select: select2, dispatch }) => { 1257 const item = select2.getItem(id); 1258 if (!item || item.status !== ItemStatus.PendingRetry) { 1259 return; 1260 } 1261 if (select2.isPaused()) { 1262 return; 1263 } 1264 dispatch({ 1265 type: Type.RetryItem, 1266 id 1267 }); 1268 dispatch.processItem(id); 1269 }; 1270 } 1271 1272 // packages/upload-media/build-module/store/private-actions.mjs 1273 var private_actions_exports = {}; 1274 __export(private_actions_exports, { 1275 addItem: () => addItem, 1276 addSideloadItem: () => addSideloadItem, 1277 detectUltraHdr: () => detectUltraHdr, 1278 finalizeItem: () => finalizeItem, 1279 finishOperation: () => finishOperation, 1280 generateThumbnails: () => generateThumbnails, 1281 getTranscodeImageOperation: () => getTranscodeImageOperation, 1282 pauseItem: () => pauseItem, 1283 pauseQueue: () => pauseQueue, 1284 prepareItem: () => prepareItem, 1285 processItem: () => processItem, 1286 removeItem: () => removeItem, 1287 resizeCropItem: () => resizeCropItem, 1288 resumeQueue: () => resumeQueue, 1289 revokeBlobUrls: () => revokeBlobUrls, 1290 rotateItem: () => rotateItem, 1291 sideloadItem: () => sideloadItem, 1292 transcodeGifItem: () => transcodeGifItem, 1293 transcodeImageItem: () => transcodeImageItem, 1294 updateItemProgress: () => updateItemProgress, 1295 updateSettings: () => updateSettings, 1296 uploadItem: () => uploadItem 1297 }); 1298 var import_blob = __toESM(require_blob(), 1); 1299 var import_i18n7 = __toESM(require_i18n(), 1); 1300 1301 // packages/upload-media/build-module/heic-parser.mjs 1302 var Reader = class { 1303 view; 1304 buffer; 1305 pos; 1306 constructor(buffer, offset = 0) { 1307 this.buffer = buffer; 1308 this.view = new DataView(buffer); 1309 this.pos = offset; 1310 } 1311 u8() { 1312 const v = this.view.getUint8(this.pos); 1313 this.pos += 1; 1314 return v; 1315 } 1316 u16() { 1317 const v = this.view.getUint16(this.pos); 1318 this.pos += 2; 1319 return v; 1320 } 1321 u32() { 1322 const v = this.view.getUint32(this.pos); 1323 this.pos += 4; 1324 return v; 1325 } 1326 u64() { 1327 const hi = this.view.getUint32(this.pos); 1328 const lo = this.view.getUint32(this.pos + 4); 1329 this.pos += 8; 1330 return hi * 4294967296 + lo; 1331 } 1332 /** 1333 * Read a variable-width unsigned integer (0, 4 or 8 bytes). 1334 * 1335 * @param size Byte width to read (0, 4, or 8). 1336 */ 1337 uN(size) { 1338 if (size === 0) { 1339 return 0; 1340 } 1341 if (size === 4) { 1342 return this.u32(); 1343 } 1344 if (size === 8) { 1345 return this.u64(); 1346 } 1347 throw new Error(`Unsupported uint size: $size}`); 1348 } 1349 str(len) { 1350 let s = ""; 1351 for (let i = 0; i < len; i++) { 1352 s += String.fromCharCode(this.view.getUint8(this.pos + i)); 1353 } 1354 this.pos += len; 1355 return s; 1356 } 1357 bytes(len) { 1358 const b = new Uint8Array(this.buffer, this.pos, len); 1359 this.pos += len; 1360 return new Uint8Array(b); 1361 } 1362 }; 1363 function readBox(r) { 1364 if (r.pos + 8 > r.view.byteLength) { 1365 return null; 1366 } 1367 const offset = r.pos; 1368 let size = r.u32(); 1369 const type = r.str(4); 1370 let headerSize = 8; 1371 if (size === 1) { 1372 size = r.u64(); 1373 headerSize = 16; 1374 } else if (size === 0) { 1375 size = r.view.byteLength - offset; 1376 } 1377 return { type, offset, size, headerSize }; 1378 } 1379 function findBoxes(r, start, end) { 1380 const boxes = []; 1381 r.pos = start; 1382 while (r.pos < end) { 1383 const box = readBox(r); 1384 if (!box || box.size < 8) { 1385 break; 1386 } 1387 boxes.push(box); 1388 r.pos = box.offset + box.size; 1389 } 1390 return boxes; 1391 } 1392 function findBox(r, start, end, type) { 1393 r.pos = start; 1394 while (r.pos < end) { 1395 const box = readBox(r); 1396 if (!box || box.size < 8) { 1397 break; 1398 } 1399 if (box.type === type) { 1400 return box; 1401 } 1402 r.pos = box.offset + box.size; 1403 } 1404 return void 0; 1405 } 1406 function parsePitm(r, box) { 1407 r.pos = box.offset + box.headerSize; 1408 const version = r.u8(); 1409 r.pos += 3; 1410 return version === 0 ? r.u16() : r.u32(); 1411 } 1412 function parseIloc(r, box) { 1413 r.pos = box.offset + box.headerSize; 1414 const version = r.u8(); 1415 r.pos += 3; 1416 const byte1 = r.u8(); 1417 const offsetSize = byte1 >> 4 & 15; 1418 const lengthSize = byte1 & 15; 1419 const byte2 = r.u8(); 1420 const baseOffsetSize = byte2 >> 4 & 15; 1421 const indexSize = version >= 1 ? byte2 & 15 : 0; 1422 const itemCount = version < 2 ? r.u16() : r.u32(); 1423 const items = /* @__PURE__ */ new Map(); 1424 for (let i = 0; i < itemCount; i++) { 1425 const itemId = version < 2 ? r.u16() : r.u32(); 1426 let constructionMethod = 0; 1427 if (version === 1 || version === 2) { 1428 const cm = r.u16(); 1429 constructionMethod = cm & 15; 1430 } 1431 r.u16(); 1432 const baseOffset = r.uN(baseOffsetSize); 1433 const extentCount = r.u16(); 1434 const extents = []; 1435 for (let j = 0; j < extentCount; j++) { 1436 if (version >= 1) { 1437 r.uN(indexSize); 1438 } 1439 const extOffset = r.uN(offsetSize); 1440 const extLength = r.uN(lengthSize); 1441 extents.push({ 1442 offset: baseOffset + extOffset, 1443 length: extLength 1444 }); 1445 } 1446 items.set(itemId, { constructionMethod, extents }); 1447 } 1448 return items; 1449 } 1450 function parseIpma(r, box) { 1451 r.pos = box.offset + box.headerSize; 1452 const vf = r.u32(); 1453 const version = vf >>> 24; 1454 const flags = vf & 16777215; 1455 const largeIndex = (flags & 1) !== 0; 1456 const entryCount = r.u32(); 1457 const associations = /* @__PURE__ */ new Map(); 1458 for (let i = 0; i < entryCount; i++) { 1459 const itemId = version < 1 ? r.u16() : r.u32(); 1460 const assocCount = r.u8(); 1461 const indices = []; 1462 for (let j = 0; j < assocCount; j++) { 1463 if (largeIndex) { 1464 indices.push(r.u16() & 32767); 1465 } else { 1466 indices.push(r.u8() & 127); 1467 } 1468 } 1469 associations.set(itemId, indices); 1470 } 1471 return associations; 1472 } 1473 function parseIspe(r, box) { 1474 r.pos = box.offset + box.headerSize + 4; 1475 return { width: r.u32(), height: r.u32() }; 1476 } 1477 function parseIrot(r, box) { 1478 r.pos = box.offset + box.headerSize; 1479 return (r.u8() & 3) * 90; 1480 } 1481 function parseIinf(r, box) { 1482 r.pos = box.offset + box.headerSize; 1483 const version = r.u8(); 1484 r.pos += 3; 1485 const entryCount = version === 0 ? r.u16() : r.u32(); 1486 const itemTypes = /* @__PURE__ */ new Map(); 1487 const entriesStart = r.pos; 1488 const boxEnd = box.offset + box.size; 1489 const infeBoxes = findBoxes(r, entriesStart, boxEnd); 1490 for (let i = 0; i < Math.min(entryCount, infeBoxes.length); i++) { 1491 const infe = infeBoxes[i]; 1492 if (infe.type !== "infe") { 1493 continue; 1494 } 1495 r.pos = infe.offset + infe.headerSize; 1496 const infeVersion = r.u8(); 1497 r.pos += 3; 1498 if (infeVersion >= 2) { 1499 const itemId = infeVersion === 2 ? r.u16() : r.u32(); 1500 r.u16(); 1501 const itemType = r.str(4); 1502 itemTypes.set(itemId, itemType); 1503 } 1504 } 1505 return itemTypes; 1506 } 1507 function parseIref(r, box, refType) { 1508 r.pos = box.offset + box.headerSize; 1509 const version = r.u8(); 1510 r.pos += 3; 1511 const refs = /* @__PURE__ */ new Map(); 1512 const boxEnd = box.offset + box.size; 1513 while (r.pos < boxEnd) { 1514 const refBox = readBox(r); 1515 if (!refBox || refBox.size < 8) { 1516 break; 1517 } 1518 r.pos = refBox.offset + refBox.headerSize; 1519 const fromId = version === 0 ? r.u16() : r.u32(); 1520 const refCount = r.u16(); 1521 const toIds = []; 1522 for (let i = 0; i < refCount; i++) { 1523 toIds.push(version === 0 ? r.u16() : r.u32()); 1524 } 1525 if (refBox.type === refType) { 1526 refs.set(fromId, toIds); 1527 } 1528 r.pos = refBox.offset + refBox.size; 1529 } 1530 return refs; 1531 } 1532 function reverseBits32(n) { 1533 n = n >>> 1 & 1431655765 | (n & 1431655765) << 1; 1534 n = n >>> 2 & 858993459 | (n & 858993459) << 2; 1535 n = n >>> 4 & 252645135 | (n & 252645135) << 4; 1536 n = n >>> 8 & 16711935 | (n & 16711935) << 8; 1537 n = n >>> 16 | n << 16; 1538 return n >>> 0; 1539 } 1540 function buildCodecString(r, recordOffset) { 1541 r.pos = recordOffset; 1542 r.u8(); 1543 const byte1 = r.u8(); 1544 const profileSpace = byte1 >> 6 & 3; 1545 const tierFlag = byte1 >> 5 & 1; 1546 const profileIdc = byte1 & 31; 1547 const compatFlags = r.u32(); 1548 const constraintBytes = r.bytes(6); 1549 const levelIdc = r.u8(); 1550 const spacePrefix = profileSpace > 0 ? String.fromCharCode(64 + profileSpace) : ""; 1551 const compatHex = reverseBits32(compatFlags).toString(16).toUpperCase(); 1552 const tierChar = tierFlag ? "H" : "L"; 1553 let lastNonZero = -1; 1554 for (let i = 5; i >= 0; i--) { 1555 if (constraintBytes[i] !== 0) { 1556 lastNonZero = i; 1557 break; 1558 } 1559 } 1560 let constraintStr = ""; 1561 if (lastNonZero >= 0) { 1562 const parts = []; 1563 for (let i = 0; i <= lastNonZero; i++) { 1564 parts.push(constraintBytes[i].toString(16).toUpperCase()); 1565 } 1566 constraintStr = "." + parts.join("."); 1567 } 1568 return `hvc1.$spacePrefix}$profileIdc}.$compatHex}.$tierChar}$levelIdc}$constraintStr}`; 1569 } 1570 function readItemData(buffer, loc, idatOffset) { 1571 const baseOffset = loc.constructionMethod === 1 ? idatOffset : 0; 1572 if (loc.extents.length === 1) { 1573 const ext = loc.extents[0]; 1574 const start = baseOffset + ext.offset; 1575 return new Uint8Array(buffer.slice(start, start + ext.length)); 1576 } 1577 let totalLength = 0; 1578 for (const ext of loc.extents) { 1579 totalLength += ext.length; 1580 } 1581 const data = new Uint8Array(totalLength); 1582 let pos = 0; 1583 for (const ext of loc.extents) { 1584 const start = baseOffset + ext.offset; 1585 data.set( 1586 new Uint8Array(buffer.slice(start, start + ext.length)), 1587 pos 1588 ); 1589 pos += ext.length; 1590 } 1591 return data; 1592 } 1593 function findHvcProperties(propIndices, properties) { 1594 let hvcCBox; 1595 let ispeBox; 1596 let irotBox; 1597 for (const idx of propIndices) { 1598 if (idx < 1 || idx > properties.length) { 1599 continue; 1600 } 1601 const prop = properties[idx - 1]; 1602 if (prop.type === "hvcC" && !hvcCBox) { 1603 hvcCBox = prop; 1604 } 1605 if (prop.type === "ispe" && !ispeBox) { 1606 ispeBox = prop; 1607 } 1608 if (prop.type === "irot" && !irotBox) { 1609 irotBox = prop; 1610 } 1611 } 1612 if (!hvcCBox) { 1613 throw new Error("No HEVC configuration (hvcC) found"); 1614 } 1615 if (!ispeBox) { 1616 throw new Error("No image dimensions (ispe) found"); 1617 } 1618 return { hvcCBox, ispeBox, irotBox }; 1619 } 1620 function parseHeic(buffer) { 1621 const r = new Reader(buffer); 1622 const fileEnd = buffer.byteLength; 1623 const metaBox = findBox(r, 0, fileEnd, "meta"); 1624 if (!metaBox) { 1625 throw new Error("No meta box found in HEIC file"); 1626 } 1627 const metaChildStart = metaBox.offset + metaBox.headerSize + 4; 1628 const metaEnd = metaBox.offset + metaBox.size; 1629 const children = findBoxes(r, metaChildStart, metaEnd); 1630 const pitmBox = children.find((b) => b.type === "pitm"); 1631 const ilocBox = children.find((b) => b.type === "iloc"); 1632 const iprpBox = children.find((b) => b.type === "iprp"); 1633 const iinfBox = children.find((b) => b.type === "iinf"); 1634 const irefBox = children.find((b) => b.type === "iref"); 1635 const idatBox = children.find((b) => b.type === "idat"); 1636 const idatOffset = idatBox ? idatBox.offset + idatBox.headerSize : 0; 1637 if (!pitmBox || !ilocBox || !iprpBox) { 1638 throw new Error("Missing required boxes (pitm, iloc, iprp) in HEIC"); 1639 } 1640 const primaryId = parsePitm(r, pitmBox); 1641 const locations = parseIloc(r, ilocBox); 1642 const iprpStart = iprpBox.offset + iprpBox.headerSize; 1643 const iprpEnd = iprpBox.offset + iprpBox.size; 1644 const iprpChildren = findBoxes(r, iprpStart, iprpEnd); 1645 const ipcoBox = iprpChildren.find((b) => b.type === "ipco"); 1646 const ipmaBox = iprpChildren.find((b) => b.type === "ipma"); 1647 if (!ipcoBox || !ipmaBox) { 1648 throw new Error("Missing ipco or ipma in HEIC properties"); 1649 } 1650 const allAssoc = parseIpma(r, ipmaBox); 1651 const ipcoStart = ipcoBox.offset + ipcoBox.headerSize; 1652 const ipcoEnd = ipcoBox.offset + ipcoBox.size; 1653 const properties = findBoxes(r, ipcoStart, ipcoEnd); 1654 let primaryItemType = "hvc1"; 1655 if (iinfBox) { 1656 const itemTypes = parseIinf(r, iinfBox); 1657 const t = itemTypes.get(primaryId); 1658 if (t) { 1659 primaryItemType = t; 1660 } 1661 } 1662 if (primaryItemType === "grid") { 1663 return parseGridImage( 1664 r, 1665 buffer, 1666 primaryId, 1667 locations, 1668 allAssoc, 1669 properties, 1670 irefBox, 1671 idatOffset 1672 ); 1673 } 1674 const primaryLoc = locations.get(primaryId); 1675 if (!primaryLoc || primaryLoc.extents.length === 0) { 1676 throw new Error(`No location data for primary item $primaryId}`); 1677 } 1678 const primaryPropIndices = allAssoc.get(primaryId); 1679 if (!primaryPropIndices || primaryPropIndices.length === 0) { 1680 throw new Error("No property associations for primary item"); 1681 } 1682 const { hvcCBox, ispeBox, irotBox } = findHvcProperties( 1683 primaryPropIndices, 1684 properties 1685 ); 1686 const hvcCDataStart = hvcCBox.offset + hvcCBox.headerSize; 1687 const hvcCDataSize = hvcCBox.size - hvcCBox.headerSize; 1688 const description = new Uint8Array( 1689 buffer.slice(hvcCDataStart, hvcCDataStart + hvcCDataSize) 1690 ); 1691 const codecString = buildCodecString(r, hvcCDataStart); 1692 const { width, height } = parseIspe(r, ispeBox); 1693 const rotation = irotBox ? parseIrot(r, irotBox) : 0; 1694 return { 1695 codecString, 1696 description, 1697 tiles: [ 1698 { 1699 data: readItemData(buffer, primaryLoc, idatOffset), 1700 x: 0, 1701 y: 0 1702 } 1703 ], 1704 tileWidth: width, 1705 tileHeight: height, 1706 outputWidth: width, 1707 outputHeight: height, 1708 rotation, 1709 exifOrientation: rotation === 0 ? getUnappliedExifOrientation(buffer) : 1 1710 }; 1711 } 1712 function parseGridImage(r, buffer, gridItemId, locations, allAssoc, properties, irefBox, idatOffset) { 1713 const gridLoc = locations.get(gridItemId); 1714 if (!gridLoc || gridLoc.extents.length === 0) { 1715 throw new Error("No location data for grid item"); 1716 } 1717 const gridData = readItemData(buffer, gridLoc, idatOffset); 1718 const largeFields = gridData.length > 1 && (gridData[1] & 1) !== 0; 1719 const minGridSize = largeFields ? 12 : 8; 1720 if (gridData.length < minGridSize) { 1721 throw new Error( 1722 `Grid descriptor too short: $gridData.length} bytes` 1723 ); 1724 } 1725 const rows = gridData[2] + 1; 1726 const columns = gridData[3] + 1; 1727 const gv = new DataView(gridData.buffer, gridData.byteOffset); 1728 let outputWidth; 1729 let outputHeight; 1730 if (largeFields) { 1731 outputWidth = gv.getUint32(4); 1732 outputHeight = gv.getUint32(8); 1733 } else { 1734 outputWidth = gv.getUint16(4); 1735 outputHeight = gv.getUint16(6); 1736 } 1737 if (!irefBox) { 1738 throw new Error("Grid image requires iref box"); 1739 } 1740 const dimgRefs = parseIref(r, irefBox, "dimg"); 1741 const tileItemIds = dimgRefs.get(gridItemId); 1742 if (!tileItemIds || tileItemIds.length === 0) { 1743 throw new Error("No tile references found for grid item"); 1744 } 1745 const expectedTiles = rows * columns; 1746 if (tileItemIds.length < expectedTiles) { 1747 throw new Error( 1748 `Grid expects $expectedTiles} tiles but found $tileItemIds.length}` 1749 ); 1750 } 1751 const firstTileProps = allAssoc.get(tileItemIds[0]); 1752 if (!firstTileProps || firstTileProps.length === 0) { 1753 throw new Error("No property associations for tile item"); 1754 } 1755 const { hvcCBox, ispeBox } = findHvcProperties( 1756 firstTileProps, 1757 properties 1758 ); 1759 const gridProps = allAssoc.get(gridItemId) || []; 1760 let irotBox; 1761 for (const idx of gridProps) { 1762 if (idx >= 1 && idx <= properties.length) { 1763 const prop = properties[idx - 1]; 1764 if (prop.type === "irot") { 1765 irotBox = prop; 1766 break; 1767 } 1768 } 1769 } 1770 const hvcCDataStart = hvcCBox.offset + hvcCBox.headerSize; 1771 const hvcCDataSize = hvcCBox.size - hvcCBox.headerSize; 1772 const description = new Uint8Array( 1773 buffer.slice(hvcCDataStart, hvcCDataStart + hvcCDataSize) 1774 ); 1775 const codecString = buildCodecString(r, hvcCDataStart); 1776 const { width: tileWidth, height: tileHeight } = parseIspe(r, ispeBox); 1777 const tiles = []; 1778 for (let row = 0; row < rows; row++) { 1779 for (let col = 0; col < columns; col++) { 1780 const tileIdx = row * columns + col; 1781 const tileId = tileItemIds[tileIdx]; 1782 const tileLoc = locations.get(tileId); 1783 if (!tileLoc || tileLoc.extents.length === 0) { 1784 throw new Error(`No location data for tile item $tileId}`); 1785 } 1786 tiles.push({ 1787 data: readItemData(buffer, tileLoc, idatOffset), 1788 x: col * tileWidth, 1789 y: row * tileHeight 1790 }); 1791 } 1792 } 1793 const rotation = irotBox ? parseIrot(r, irotBox) : 0; 1794 return { 1795 codecString, 1796 description, 1797 tiles, 1798 tileWidth, 1799 tileHeight, 1800 outputWidth, 1801 outputHeight, 1802 rotation, 1803 exifOrientation: rotation === 0 ? getUnappliedExifOrientation(buffer) : 1 1804 }; 1805 } 1806 function readTiffOrientation(payload) { 1807 if (payload.length < 8) { 1808 return 1; 1809 } 1810 const view = new DataView( 1811 payload.buffer, 1812 payload.byteOffset, 1813 payload.byteLength 1814 ); 1815 let tiffStart = 0; 1816 const firstWord = view.getUint16(0); 1817 if (firstWord !== 18761 && firstWord !== 19789) { 1818 tiffStart = view.getUint32(0) + 4; 1819 } 1820 if (tiffStart + 8 > payload.length) { 1821 return 1; 1822 } 1823 const byteOrder = view.getUint16(tiffStart); 1824 let little; 1825 if (byteOrder === 18761) { 1826 little = true; 1827 } else if (byteOrder === 19789) { 1828 little = false; 1829 } else { 1830 return 1; 1831 } 1832 const ifd0 = tiffStart + view.getUint32(tiffStart + 4, little); 1833 if (ifd0 + 2 > payload.length) { 1834 return 1; 1835 } 1836 const entryCount = view.getUint16(ifd0, little); 1837 for (let i = 0; i < entryCount; i++) { 1838 const entry = ifd0 + 2 + i * 12; 1839 if (entry + 12 > payload.length) { 1840 break; 1841 } 1842 if (view.getUint16(entry, little) === 274) { 1843 const value = view.getUint16(entry + 8, little); 1844 return value >= 1 && value <= 8 ? value : 1; 1845 } 1846 } 1847 return 1; 1848 } 1849 function findMeta(r) { 1850 const metaBox = findBox(r, 0, r.view.byteLength, "meta"); 1851 if (!metaBox) { 1852 return null; 1853 } 1854 const start = metaBox.offset + metaBox.headerSize + 4; 1855 const end = metaBox.offset + metaBox.size; 1856 return { box: metaBox, children: findBoxes(r, start, end) }; 1857 } 1858 function parseExifOrientation(buffer) { 1859 try { 1860 const r = new Reader(buffer); 1861 const meta = findMeta(r); 1862 if (!meta) { 1863 return 1; 1864 } 1865 const iinfBox = meta.children.find((b) => b.type === "iinf"); 1866 const ilocBox = meta.children.find((b) => b.type === "iloc"); 1867 if (!iinfBox || !ilocBox) { 1868 return 1; 1869 } 1870 const itemTypes = parseIinf(r, iinfBox); 1871 let exifItemId; 1872 for (const [id, type] of itemTypes) { 1873 if (type === "Exif") { 1874 exifItemId = id; 1875 break; 1876 } 1877 } 1878 if (exifItemId === void 0) { 1879 return 1; 1880 } 1881 const loc = parseIloc(r, ilocBox).get(exifItemId); 1882 if (!loc || loc.extents.length === 0) { 1883 return 1; 1884 } 1885 const idatBox = meta.children.find((b) => b.type === "idat"); 1886 const idatOffset = idatBox ? idatBox.offset + idatBox.headerSize : 0; 1887 return readTiffOrientation(readItemData(buffer, loc, idatOffset)); 1888 } catch { 1889 return 1; 1890 } 1891 } 1892 function hasNativeTransform(r) { 1893 const meta = findMeta(r); 1894 if (!meta) { 1895 return false; 1896 } 1897 const iprp = meta.children.find((b) => b.type === "iprp"); 1898 if (!iprp) { 1899 return false; 1900 } 1901 const ipco = findBox( 1902 r, 1903 iprp.offset + iprp.headerSize, 1904 iprp.offset + iprp.size, 1905 "ipco" 1906 ); 1907 if (!ipco) { 1908 return false; 1909 } 1910 const start = ipco.offset + ipco.headerSize; 1911 const end = ipco.offset + ipco.size; 1912 return Boolean( 1913 findBox(r, start, end, "irot") || findBox(r, start, end, "imir") 1914 ); 1915 } 1916 function getUnappliedExifOrientation(buffer) { 1917 try { 1918 if (hasNativeTransform(new Reader(buffer))) { 1919 return 1; 1920 } 1921 } catch { 1922 return 1; 1923 } 1924 return parseExifOrientation(buffer); 1925 } 1926 1927 // packages/upload-media/build-module/heic-support.mjs 1928 var import_i18n6 = __toESM(require_i18n(), 1); 1929 function detectBrowserFamily() { 1930 if (typeof navigator === "undefined") { 1931 return null; 1932 } 1933 const brands = navigator.userAgentData?.brands; 1934 if (brands?.length) { 1935 if (brands.some(({ brand }) => /Chromium/i.test(brand))) { 1936 return "chromium"; 1937 } 1938 } 1939 const userAgent = navigator.userAgent || ""; 1940 if (/Firefox|FxiOS/i.test(userAgent)) { 1941 return "firefox"; 1942 } 1943 if (/Chrome|Chromium|CriOS|Edg|OPR/i.test(userAgent)) { 1944 return "chromium"; 1945 } 1946 if (/Safari/i.test(userAgent)) { 1947 return "safari"; 1948 } 1949 return null; 1950 } 1951 function detectPlatform() { 1952 if (typeof navigator === "undefined") { 1953 return "other"; 1954 } 1955 const platform = navigator.userAgentData?.platform || navigator.userAgent || ""; 1956 if (/iPhone|iPad|iPod|iOS/i.test(platform)) { 1957 return "other"; 1958 } 1959 if (/macOS|Mac OS X|Macintosh/i.test(platform)) { 1960 return "macos"; 1961 } 1962 if (/Windows/i.test(platform)) { 1963 return "windows"; 1964 } 1965 if (/Android|CrOS|Chrome OS/i.test(platform)) { 1966 return "other"; 1967 } 1968 if (/Linux|X11/i.test(platform)) { 1969 return "linux"; 1970 } 1971 return "other"; 1972 } 1973 function getBrowserName() { 1974 if (detectBrowserFamily() === "chromium") { 1975 const brands = navigator.userAgentData?.brands ?? []; 1976 const userAgent = navigator.userAgent || ""; 1977 if (brands.some(({ brand }) => /Edge/i.test(brand)) || /Edg\//i.test(userAgent)) { 1978 return "Edge"; 1979 } 1980 if (brands.some(({ brand }) => /Opera/i.test(brand)) || /OPR\//i.test(userAgent)) { 1981 return "Opera"; 1982 } 1983 return "Chrome"; 1984 } 1985 switch (detectBrowserFamily()) { 1986 case "firefox": 1987 return "Firefox"; 1988 case "safari": 1989 return "Safari"; 1990 default: 1991 return null; 1992 } 1993 } 1994 function getHeicConversionAdvice() { 1995 const platform = detectPlatform(); 1996 const family = detectBrowserFamily(); 1997 if (platform === "macos") { 1998 if (family === "chromium") { 1999 return (0, import_i18n6.__)( 2000 "Safari usually can, or you can upload a JPEG instead." 2001 ); 2002 } 2003 if (family !== "safari") { 2004 return (0, import_i18n6.__)( 2005 "Safari or Chrome usually can, or you can upload a JPEG instead." 2006 ); 2007 } 2008 } 2009 if (platform === "windows" && family === "firefox") { 2010 return (0, import_i18n6.__)("Chrome or Edge might, or you can upload a JPEG instead."); 2011 } 2012 return (0, import_i18n6.__)("You can upload a JPEG instead."); 2013 } 2014 function getHeicUnsupportedMessage() { 2015 const platform = detectPlatform(); 2016 const family = detectBrowserFamily(); 2017 const browserName = getBrowserName(); 2018 let cause; 2019 if (platform === "linux") { 2020 cause = (0, import_i18n6.__)( 2021 "HEIC photos can't be decoded on Linux, so unfortunately we couldn't convert this one." 2022 ); 2023 } else if (family === "firefox") { 2024 cause = (0, import_i18n6.__)( 2025 "Firefox can't read HEIC photos, so we couldn't convert this one." 2026 ); 2027 } else if (browserName && platform === "windows") { 2028 cause = (0, import_i18n6.sprintf)( 2029 /* translators: %s: browser name, e.g. "Chrome". */ 2030 (0, import_i18n6.__)( 2031 "%s couldn't decode HEIC on this PC, so we couldn't convert this one." 2032 ), 2033 browserName 2034 ); 2035 } else if (browserName && platform === "macos") { 2036 cause = (0, import_i18n6.sprintf)( 2037 /* translators: %s: browser name, e.g. "Safari". */ 2038 (0, import_i18n6.__)( 2039 "%s couldn't decode HEIC on this Mac, so we couldn't convert this one." 2040 ), 2041 browserName 2042 ); 2043 } else if (browserName) { 2044 cause = (0, import_i18n6.sprintf)( 2045 /* translators: %s: browser name, e.g. "Chrome". */ 2046 (0, import_i18n6.__)( 2047 "%s couldn't decode HEIC on this device, so we couldn't convert this one." 2048 ), 2049 browserName 2050 ); 2051 } else { 2052 cause = (0, import_i18n6.__)( 2053 "This browser can't read HEIC photos, so we couldn't convert this one." 2054 ); 2055 } 2056 return `$cause} $getHeicConversionAdvice()}`; 2057 } 2058 2059 // packages/upload-media/build-module/canvas-utils.mjs 2060 async function canvasConvertToJpeg(file, quality = 0.82) { 2061 const baseName = getFileBasename(file.name); 2062 try { 2063 const bitmap = await createImageBitmap(file); 2064 try { 2065 const canvas = new OffscreenCanvas(bitmap.width, bitmap.height); 2066 const ctx = canvas.getContext("2d"); 2067 if (!ctx) { 2068 throw new Error("Could not get canvas 2d context"); 2069 } 2070 ctx.drawImage(bitmap, 0, 0); 2071 const jpegBlob = await canvas.convertToBlob({ 2072 type: "image/jpeg", 2073 quality 2074 }); 2075 return new File([jpegBlob], `$baseName}.jpg`, { 2076 type: "image/jpeg" 2077 }); 2078 } finally { 2079 bitmap.close(); 2080 } 2081 } catch { 2082 } 2083 if (typeof ImageDecoder !== "undefined") { 2084 const supported = await ImageDecoder.isTypeSupported(file.type); 2085 if (supported) { 2086 const decoder = new ImageDecoder({ 2087 type: file.type, 2088 data: file.stream() 2089 }); 2090 try { 2091 const { image: videoFrame } = await decoder.decode(); 2092 try { 2093 const canvas = new OffscreenCanvas( 2094 videoFrame.displayWidth, 2095 videoFrame.displayHeight 2096 ); 2097 const ctx = canvas.getContext("2d"); 2098 if (!ctx) { 2099 throw new Error("Could not get canvas 2d context"); 2100 } 2101 ctx.drawImage(videoFrame, 0, 0); 2102 const jpegBlob = await canvas.convertToBlob({ 2103 type: "image/jpeg", 2104 quality 2105 }); 2106 return new File([jpegBlob], `$baseName}.jpg`, { 2107 type: "image/jpeg" 2108 }); 2109 } finally { 2110 videoFrame.close(); 2111 } 2112 } finally { 2113 decoder.close(); 2114 } 2115 } 2116 } 2117 if (typeof VideoDecoder !== "undefined") { 2118 try { 2119 const heicData = parseHeic(await file.arrayBuffer()); 2120 const support = await VideoDecoder.isConfigSupported({ 2121 codec: heicData.codecString 2122 }); 2123 if (support.supported) { 2124 const canvas = new OffscreenCanvas( 2125 heicData.outputWidth, 2126 heicData.outputHeight 2127 ); 2128 const ctx = canvas.getContext("2d"); 2129 if (!ctx) { 2130 throw new Error("Could not get canvas 2d context"); 2131 } 2132 for (const tile of heicData.tiles) { 2133 const frame = await decodeHevcFrame( 2134 heicData.codecString, 2135 heicData.description, 2136 heicData.tileWidth, 2137 heicData.tileHeight, 2138 tile.data 2139 ); 2140 try { 2141 ctx.drawImage(frame, tile.x, tile.y); 2142 } finally { 2143 frame.close(); 2144 } 2145 } 2146 const outputCanvas = heicData.rotation !== 0 ? applyRotation(canvas, heicData.rotation) : applyExifOrientation( 2147 canvas, 2148 heicData.exifOrientation 2149 ); 2150 const jpegBlob = await outputCanvas.convertToBlob({ 2151 type: "image/jpeg", 2152 quality 2153 }); 2154 return new File([jpegBlob], `$baseName}.jpg`, { 2155 type: "image/jpeg" 2156 }); 2157 } 2158 } catch { 2159 } 2160 } 2161 throw new Error(getHeicUnsupportedMessage()); 2162 } 2163 function applyRotation(source, rotation) { 2164 if (rotation === 0) { 2165 return source; 2166 } 2167 const swap = rotation === 90 || rotation === 270; 2168 const w = swap ? source.height : source.width; 2169 const h = swap ? source.width : source.height; 2170 const rotated = new OffscreenCanvas(w, h); 2171 const ctx = rotated.getContext("2d"); 2172 if (!ctx) { 2173 return source; 2174 } 2175 ctx.translate(w / 2, h / 2); 2176 ctx.rotate(-rotation * Math.PI / 180); 2177 ctx.drawImage(source, -source.width / 2, -source.height / 2); 2178 return rotated; 2179 } 2180 function applyExifOrientation(source, orientation) { 2181 if (orientation <= 1 || orientation > 8) { 2182 return source; 2183 } 2184 const { width: sw, height: sh } = source; 2185 const swap = orientation >= 5; 2186 const out = new OffscreenCanvas(swap ? sh : sw, swap ? sw : sh); 2187 const ctx = out.getContext("2d"); 2188 if (!ctx) { 2189 return source; 2190 } 2191 switch (orientation) { 2192 case 2: 2193 ctx.transform(-1, 0, 0, 1, sw, 0); 2194 break; 2195 case 3: 2196 ctx.transform(-1, 0, 0, -1, sw, sh); 2197 break; 2198 case 4: 2199 ctx.transform(1, 0, 0, -1, 0, sh); 2200 break; 2201 case 5: 2202 ctx.transform(0, 1, 1, 0, 0, 0); 2203 break; 2204 case 6: 2205 ctx.transform(0, 1, -1, 0, sh, 0); 2206 break; 2207 case 7: 2208 ctx.transform(0, -1, -1, 0, sh, sw); 2209 break; 2210 case 8: 2211 ctx.transform(0, -1, 1, 0, 0, sw); 2212 break; 2213 } 2214 ctx.drawImage(source, 0, 0); 2215 return out; 2216 } 2217 function decodeHevcFrame(codec, description, width, height, data) { 2218 return new Promise((resolve, reject) => { 2219 const decoder = new VideoDecoder({ 2220 output: (frame) => { 2221 decoder.close(); 2222 resolve(frame); 2223 }, 2224 error: (e) => { 2225 if (decoder.state !== "closed") { 2226 decoder.close(); 2227 } 2228 reject(e); 2229 } 2230 }); 2231 decoder.configure({ 2232 codec, 2233 codedWidth: width, 2234 codedHeight: height, 2235 description 2236 }); 2237 decoder.decode( 2238 new EncodedVideoChunk({ 2239 type: "key", 2240 timestamp: 0, 2241 data 2242 }) 2243 ); 2244 decoder.flush().catch((e) => { 2245 if (decoder.state !== "closed") { 2246 decoder.close(); 2247 } 2248 reject(e); 2249 }); 2250 }); 2251 } 2252 2253 // packages/upload-media/build-module/feature-detection.mjs 2254 var cachedResult = null; 2255 function detectClientSideMediaSupport() { 2256 if (cachedResult !== null) { 2257 return cachedResult; 2258 } 2259 if (typeof WebAssembly === "undefined") { 2260 cachedResult = { 2261 supported: false, 2262 reason: "WebAssembly is not supported in this browser." 2263 }; 2264 return cachedResult; 2265 } 2266 if (typeof SharedArrayBuffer === "undefined") { 2267 cachedResult = { 2268 supported: false, 2269 reason: "SharedArrayBuffer is not available. This may be due to missing cross-origin isolation headers." 2270 }; 2271 return cachedResult; 2272 } 2273 if (typeof Worker === "undefined") { 2274 cachedResult = { 2275 supported: false, 2276 reason: "Web Workers are not supported in this browser." 2277 }; 2278 return cachedResult; 2279 } 2280 if (typeof navigator !== "undefined" && "deviceMemory" in navigator && navigator.deviceMemory <= 2) { 2281 cachedResult = { 2282 supported: false, 2283 reason: "Device has insufficient memory for client-side media processing." 2284 }; 2285 return cachedResult; 2286 } 2287 if (typeof navigator !== "undefined" && "hardwareConcurrency" in navigator && navigator.hardwareConcurrency < 2) { 2288 cachedResult = { 2289 supported: false, 2290 reason: "Device has insufficient CPU cores for client-side media processing." 2291 }; 2292 return cachedResult; 2293 } 2294 if (typeof navigator !== "undefined") { 2295 const connection = navigator.connection; 2296 if (connection) { 2297 if (connection.saveData) { 2298 cachedResult = { 2299 supported: false, 2300 reason: "Data saver mode is enabled." 2301 }; 2302 return cachedResult; 2303 } 2304 if (connection.effectiveType === "slow-2g" || connection.effectiveType === "2g") { 2305 cachedResult = { 2306 supported: false, 2307 reason: "Network connection is too slow for client-side media processing." 2308 }; 2309 return cachedResult; 2310 } 2311 } 2312 } 2313 if (typeof window !== "undefined") { 2314 try { 2315 const testBlob = new Blob([""], { 2316 type: "application/javascript" 2317 }); 2318 const testUrl = URL.createObjectURL(testBlob); 2319 try { 2320 const testWorker = new Worker(testUrl); 2321 testWorker.terminate(); 2322 } finally { 2323 URL.revokeObjectURL(testUrl); 2324 } 2325 } catch { 2326 cachedResult = { 2327 supported: false, 2328 reason: "The site's Content Security Policy (CSP) does not allow blob: workers. The worker-src directive must include blob: to enable client-side media processing." 2329 }; 2330 return cachedResult; 2331 } 2332 } 2333 cachedResult = { supported: true }; 2334 return cachedResult; 2335 } 2336 function isClientSideMediaSupported() { 2337 return detectClientSideMediaSupport().supported; 2338 } 2339 function isHeicCanvasSupported() { 2340 return typeof createImageBitmap !== "undefined" && typeof OffscreenCanvas !== "undefined"; 2341 } 2342 function clearFeatureDetectionCache() { 2343 cachedResult = null; 2344 } 2345 var BYTES_PER_PIXEL = 4; 2346 var INTERLACED_MEMORY_BUDGET = 0.5 * 1024 * 1024 * 1024; 2347 var BASELINE_MEMORY_BUDGET = 0.9 * 1024 * 1024 * 1024; 2348 function exceedsClientProcessingMemory(dimensions) { 2349 const { width, height, interlaced } = dimensions; 2350 const estimatedBytes = width * height * BYTES_PER_PIXEL; 2351 const budget = interlaced ? INTERLACED_MEMORY_BUDGET : BASELINE_MEMORY_BUDGET; 2352 return estimatedBytes > budget; 2353 } 2354 2355 // packages/upload-media/build-module/get-image-dimensions.mjs 2356 var MAX_HEADER_BYTES = 512 * 1024; 2357 function parseJpeg(view) { 2358 let offset = 2; 2359 while (offset < view.byteLength) { 2360 if (view.getUint8(offset) !== 255) { 2361 return null; 2362 } 2363 while (offset < view.byteLength && view.getUint8(offset) === 255) { 2364 offset++; 2365 } 2366 if (offset >= view.byteLength) { 2367 return null; 2368 } 2369 const marker = view.getUint8(offset); 2370 offset++; 2371 if (marker === 1 || marker >= 208 && marker <= 217) { 2372 continue; 2373 } 2374 if (marker === 218) { 2375 return null; 2376 } 2377 if (offset + 2 > view.byteLength) { 2378 return null; 2379 } 2380 const segmentLength = view.getUint16(offset); 2381 if (segmentLength < 2) { 2382 return null; 2383 } 2384 const isStartOfFrame = marker >= 192 && marker <= 207 && marker !== 196 && marker !== 200 && marker !== 204; 2385 if (isStartOfFrame) { 2386 if (offset + 7 > view.byteLength) { 2387 return null; 2388 } 2389 const height = view.getUint16(offset + 3); 2390 const width = view.getUint16(offset + 5); 2391 const interlaced = marker === 194 || marker === 198 || marker === 202 || marker === 206; 2392 return { width, height, interlaced }; 2393 } 2394 offset += segmentLength; 2395 } 2396 return null; 2397 } 2398 function parsePng(view) { 2399 if (view.byteLength < 29) { 2400 return null; 2401 } 2402 const isIhdr = view.getUint8(12) === 73 && // I 2403 view.getUint8(13) === 72 && // H 2404 view.getUint8(14) === 68 && // D 2405 view.getUint8(15) === 82; 2406 if (!isIhdr) { 2407 return null; 2408 } 2409 const width = view.getUint32(16); 2410 const height = view.getUint32(20); 2411 const interlaceMethod = view.getUint8(28); 2412 return { width, height, interlaced: interlaceMethod !== 0 }; 2413 } 2414 async function getImageDimensions(file) { 2415 try { 2416 const headerBytes = Math.min(file.size, MAX_HEADER_BYTES); 2417 const buffer = await file.slice(0, headerBytes).arrayBuffer(); 2418 const view = new DataView(buffer); 2419 if (view.byteLength >= 3 && view.getUint16(0) === 65496) { 2420 return parseJpeg(view); 2421 } 2422 if (view.byteLength >= 8 && view.getUint32(0) === 2303741511 && view.getUint32(4) === 218765834) { 2423 return parsePng(view); 2424 } 2425 return null; 2426 } catch { 2427 return null; 2428 } 2429 } 2430 2431 // packages/upload-media/build-module/stub-file.mjs 2432 var StubFile = class extends File { 2433 constructor(fileName = "stub-file") { 2434 super([], fileName); 2435 } 2436 }; 2437 2438 // packages/upload-media/build-module/store/private-actions.mjs 2439 var DEFAULT_OUTPUT_QUALITY = 0.82; 2440 var ultraHdrItems = /* @__PURE__ */ new Set(); 2441 function addItem({ 2442 file: fileOrBlob, 2443 batchId, 2444 onChange, 2445 onSuccess, 2446 onBatchSuccess, 2447 onError, 2448 additionalData = {}, 2449 sourceUrl, 2450 sourceAttachmentId, 2451 abortController, 2452 operations 2453 }) { 2454 return async ({ dispatch }) => { 2455 const itemId = v4_default(); 2456 const file = convertBlobToFile(fileOrBlob); 2457 let blobUrl; 2458 if (!(file instanceof StubFile)) { 2459 blobUrl = (0, import_blob.createBlobURL)(file); 2460 dispatch({ 2461 type: Type.CacheBlobUrl, 2462 id: itemId, 2463 blobUrl 2464 }); 2465 } 2466 dispatch({ 2467 type: Type.Add, 2468 item: { 2469 id: itemId, 2470 batchId, 2471 status: ItemStatus.Processing, 2472 sourceFile: cloneFile(file), 2473 file, 2474 attachment: { 2475 url: blobUrl 2476 }, 2477 additionalData: { 2478 generate_sub_sizes: false, 2479 ...additionalData 2480 }, 2481 onChange, 2482 onSuccess, 2483 onBatchSuccess, 2484 onError, 2485 sourceUrl, 2486 sourceAttachmentId, 2487 abortController: abortController || new AbortController(), 2488 operations: Array.isArray(operations) ? operations : [OperationType.Prepare] 2489 } 2490 }); 2491 dispatch.processItem(itemId); 2492 }; 2493 } 2494 function addSideloadItem({ 2495 file, 2496 onChange, 2497 additionalData, 2498 operations, 2499 batchId, 2500 parentId 2501 }) { 2502 return ({ dispatch }) => { 2503 const itemId = v4_default(); 2504 dispatch({ 2505 type: Type.Add, 2506 item: { 2507 id: itemId, 2508 batchId, 2509 status: ItemStatus.Processing, 2510 sourceFile: cloneFile(file), 2511 file, 2512 onChange, 2513 additionalData: { 2514 ...additionalData 2515 }, 2516 parentId, 2517 operations: Array.isArray(operations) ? operations : [OperationType.Prepare], 2518 abortController: new AbortController() 2519 } 2520 }); 2521 dispatch.processItem(itemId); 2522 }; 2523 } 2524 function processItem(id) { 2525 return async ({ select: select2, dispatch }) => { 2526 if (select2.isPaused()) { 2527 return; 2528 } 2529 const item = select2.getItem(id); 2530 if (!item) { 2531 return; 2532 } 2533 const { 2534 attachment, 2535 onChange, 2536 onSuccess, 2537 onBatchSuccess, 2538 batchId, 2539 parentId 2540 } = item; 2541 const operation = Array.isArray(item.operations?.[0]) ? item.operations[0][0] : item.operations?.[0]; 2542 const operationArgs = Array.isArray(item.operations?.[0]) ? item.operations[0][1] : void 0; 2543 if (operation === OperationType.Upload) { 2544 const settings = select2.getSettings(); 2545 const activeCount = select2.getActiveUploadCount(); 2546 if (activeCount >= settings.maxConcurrentUploads) { 2547 return; 2548 } 2549 } 2550 if (operation === OperationType.ResizeCrop || operation === OperationType.Rotate) { 2551 const settings = select2.getSettings(); 2552 const activeCount = select2.getActiveImageProcessingCount(); 2553 if (activeCount >= settings.maxConcurrentImageProcessing) { 2554 return; 2555 } 2556 } 2557 if (operation === OperationType.TranscodeGif) { 2558 const activeCount = select2.getActiveVideoProcessingCount(); 2559 if (activeCount >= 1) { 2560 return; 2561 } 2562 } 2563 if (attachment) { 2564 const isHeicUrl = attachment.url && /\.hei[cf]$/i.test(attachment.url); 2565 if (!isHeicUrl) { 2566 onChange?.([attachment]); 2567 } 2568 } 2569 if (!operation) { 2570 if (parentId || !parentId && !select2.hasPendingItemsByParentId(id)) { 2571 if (attachment) { 2572 onSuccess?.([attachment]); 2573 } 2574 dispatch.removeItem(id); 2575 dispatch.revokeBlobUrls(id); 2576 if (batchId && select2.isBatchUploaded(batchId)) { 2577 onBatchSuccess?.(); 2578 } 2579 } 2580 if (parentId && batchId && select2.isBatchUploaded(batchId)) { 2581 const parentItem = select2.getItem(parentId); 2582 if (!parentItem) { 2583 return; 2584 } 2585 if (parentItem.operations && parentItem.operations.length > 0) { 2586 dispatch.processItem(parentId); 2587 return; 2588 } 2589 if (attachment) { 2590 parentItem.onSuccess?.([attachment]); 2591 } 2592 dispatch.removeItem(parentId); 2593 dispatch.revokeBlobUrls(parentId); 2594 if (parentItem.batchId && select2.isBatchUploaded(parentItem.batchId)) { 2595 parentItem.onBatchSuccess?.(); 2596 } 2597 } 2598 return; 2599 } 2600 if (operation === OperationType.Finalize && select2.hasPendingItemsByParentId(id)) { 2601 return; 2602 } 2603 dispatch({ 2604 type: Type.OperationStart, 2605 id, 2606 operation 2607 }); 2608 debug( 2609 `Starting operation $operation} for $item.file.name} (item $item.id})` 2610 ); 2611 switch (operation) { 2612 case OperationType.Prepare: 2613 dispatch.prepareItem(item.id); 2614 break; 2615 case OperationType.ResizeCrop: 2616 dispatch.resizeCropItem( 2617 item.id, 2618 operationArgs 2619 ); 2620 break; 2621 case OperationType.Rotate: 2622 dispatch.rotateItem( 2623 item.id, 2624 operationArgs 2625 ); 2626 break; 2627 case OperationType.TranscodeImage: 2628 dispatch.transcodeImageItem( 2629 item.id, 2630 operationArgs 2631 ); 2632 break; 2633 case OperationType.TranscodeGif: 2634 dispatch.transcodeGifItem( 2635 item.id, 2636 operationArgs 2637 ); 2638 break; 2639 case OperationType.Upload: 2640 if (item.parentId) { 2641 dispatch.sideloadItem(id); 2642 } else { 2643 dispatch.uploadItem(id); 2644 } 2645 break; 2646 case OperationType.ThumbnailGeneration: 2647 dispatch.generateThumbnails(id); 2648 break; 2649 case OperationType.Finalize: 2650 dispatch.finalizeItem(id); 2651 break; 2652 case OperationType.DetectUltraHdr: 2653 dispatch.detectUltraHdr(id); 2654 break; 2655 } 2656 }; 2657 } 2658 function pauseQueue() { 2659 return { 2660 type: Type.PauseQueue 2661 }; 2662 } 2663 function resumeQueue() { 2664 return async ({ select: select2, dispatch }) => { 2665 dispatch({ 2666 type: Type.ResumeQueue 2667 }); 2668 for (const item of select2.getAllItems()) { 2669 if (item.status === ItemStatus.PendingRetry) { 2670 dispatch.executeRetry(item.id); 2671 } else { 2672 dispatch.processItem(item.id); 2673 } 2674 } 2675 }; 2676 } 2677 function pauseItem(id) { 2678 return async ({ dispatch }) => { 2679 dispatch({ 2680 type: Type.PauseItem, 2681 id 2682 }); 2683 }; 2684 } 2685 function removeItem(id) { 2686 return async ({ select: select2, dispatch }) => { 2687 const item = select2.getItem(id); 2688 if (!item) { 2689 return; 2690 } 2691 ultraHdrItems.delete(id); 2692 clearRetryTimer(id); 2693 dispatch({ 2694 type: Type.Remove, 2695 id 2696 }); 2697 if (select2.getAllItems().length === 0) { 2698 terminateVipsWorker(); 2699 terminateVideoConversionWorker(); 2700 } 2701 }; 2702 } 2703 function finishOperation(id, updates) { 2704 return async ({ select: select2, dispatch }) => { 2705 const item = select2.getItem(id); 2706 const previousOperation = item?.currentOperation; 2707 dispatch({ 2708 type: Type.OperationFinish, 2709 id, 2710 item: updates 2711 }); 2712 dispatch.processItem(id); 2713 if (previousOperation === OperationType.Upload) { 2714 const pendingUploads = select2.getPendingUploads(); 2715 for (const pendingItem of pendingUploads) { 2716 dispatch.processItem(pendingItem.id); 2717 } 2718 } 2719 if (previousOperation === OperationType.ResizeCrop || previousOperation === OperationType.Rotate) { 2720 const pendingItems = select2.getPendingImageProcessing(); 2721 for (const pendingItem of pendingItems) { 2722 dispatch.processItem(pendingItem.id); 2723 } 2724 } 2725 if (previousOperation === OperationType.TranscodeGif) { 2726 const pendingItems = select2.getPendingVideoProcessing(); 2727 for (const pendingItem of pendingItems) { 2728 dispatch.processItem(pendingItem.id); 2729 } 2730 } 2731 if (previousOperation === OperationType.ResizeCrop || previousOperation === OperationType.Rotate || previousOperation === OperationType.TranscodeImage) { 2732 maybeRecycleVipsWorker(select2.getActiveImageProcessingCount()); 2733 } 2734 }; 2735 } 2736 var VALID_IMAGE_FORMATS = ["jpeg", "webp", "avif", "png", "gif"]; 2737 function isValidImageFormat(format) { 2738 return VALID_IMAGE_FORMATS.includes(format); 2739 } 2740 async function getTranscodeImageOperation(file, outputMimeType, interlaced = false, quality = DEFAULT_OUTPUT_QUALITY) { 2741 if (file.type === "image/png" && outputMimeType === "image/jpeg") { 2742 const blobUrl = (0, import_blob.createBlobURL)(file); 2743 try { 2744 const hasAlpha = await vipsHasTransparency(blobUrl); 2745 if (hasAlpha) { 2746 return null; 2747 } 2748 } catch { 2749 return null; 2750 } finally { 2751 (0, import_blob.revokeBlobURL)(blobUrl); 2752 } 2753 } 2754 const formatPart = outputMimeType.split("/")[1]; 2755 if (!isValidImageFormat(formatPart)) { 2756 return null; 2757 } 2758 return [ 2759 OperationType.TranscodeImage, 2760 { 2761 outputFormat: formatPart, 2762 outputQuality: quality, 2763 interlaced 2764 } 2765 ]; 2766 } 2767 function prepareItem(id) { 2768 return async ({ select: select2, dispatch }) => { 2769 const item = select2.getItem(id); 2770 if (!item) { 2771 return; 2772 } 2773 const { file } = item; 2774 const operations = []; 2775 const settings = select2.getSettings(); 2776 if (file.type === "image/gif" && settings.gifConvert !== false && typeof ImageDecoder !== "undefined" && typeof VideoEncoder !== "undefined") { 2777 let isAnimated = false; 2778 try { 2779 isAnimated = isAnimatedGif(await file.arrayBuffer()); 2780 } catch { 2781 isAnimated = false; 2782 } 2783 if (isAnimated) { 2784 let hasTransparency = false; 2785 const blobUrl = (0, import_blob.createBlobURL)(file); 2786 try { 2787 hasTransparency = await vipsHasTransparency(blobUrl); 2788 } catch { 2789 hasTransparency = true; 2790 } finally { 2791 (0, import_blob.revokeBlobURL)(blobUrl); 2792 } 2793 if (!hasTransparency) { 2794 operations.push( 2795 OperationType.Upload, 2796 OperationType.ThumbnailGeneration, 2797 OperationType.Finalize 2798 ); 2799 dispatch({ 2800 type: Type.AddOperations, 2801 id, 2802 operations 2803 }); 2804 dispatch.finishOperation(id, { 2805 animatedGifFile: item.file 2806 }); 2807 return; 2808 } 2809 } 2810 } 2811 let heicJpeg = null; 2812 const isImage = file.type.startsWith("image/"); 2813 const isVipsSupported = CLIENT_SIDE_SUPPORTED_MIME_TYPES.includes( 2814 file.type 2815 ); 2816 const isHeic = HEIC_MIME_TYPES.includes(file.type); 2817 let tooLargeForClient = false; 2818 if (isImage && isVipsSupported) { 2819 const dimensions = await getImageDimensions(file); 2820 if (dimensions && exceedsClientProcessingMemory(dimensions)) { 2821 tooLargeForClient = true; 2822 } 2823 } 2824 if (file.type === "image/jpeg" && !tooLargeForClient) { 2825 operations.push(OperationType.DetectUltraHdr); 2826 } 2827 if (isImage && isVipsSupported && !tooLargeForClient) { 2828 operations.push( 2829 OperationType.Upload, 2830 OperationType.ThumbnailGeneration, 2831 OperationType.Finalize 2832 ); 2833 } else if (isImage && isHeic) { 2834 try { 2835 heicJpeg = await canvasConvertToJpeg( 2836 file, 2837 settings.imageQuality ?? DEFAULT_OUTPUT_QUALITY 2838 ); 2839 } catch { 2840 dispatch.cancelItem( 2841 id, 2842 new UploadError({ 2843 code: ErrorCode.HEIC_DECODE_ERROR, 2844 message: getHeicUnsupportedMessage(), 2845 file 2846 }) 2847 ); 2848 return; 2849 } 2850 operations.push( 2851 OperationType.Upload, 2852 OperationType.ThumbnailGeneration, 2853 OperationType.Finalize 2854 ); 2855 } else { 2856 operations.push(OperationType.Upload); 2857 } 2858 dispatch({ 2859 type: Type.AddOperations, 2860 id, 2861 operations 2862 }); 2863 let updates; 2864 if (isHeic && heicJpeg) { 2865 const vipsAvailable = isClientSideMediaSupported(); 2866 updates = { 2867 file: heicJpeg, 2868 sourceFile: heicJpeg, 2869 originalHeicFile: item.file, 2870 additionalData: { 2871 ...item.additionalData, 2872 generate_sub_sizes: !vipsAvailable, 2873 convert_format: true 2874 } 2875 }; 2876 } else if (!isVipsSupported || !isImage || tooLargeForClient) { 2877 updates = { 2878 additionalData: { 2879 ...item.additionalData, 2880 generate_sub_sizes: true, 2881 convert_format: true 2882 } 2883 }; 2884 } else { 2885 updates = { 2886 additionalData: { 2887 ...item.additionalData, 2888 generate_sub_sizes: false 2889 } 2890 }; 2891 } 2892 dispatch.finishOperation(id, updates); 2893 }; 2894 } 2895 function detectUltraHdr(id) { 2896 return async ({ select: select2, dispatch }) => { 2897 const item = select2.getItem(id); 2898 if (!item) { 2899 return; 2900 } 2901 let info; 2902 try { 2903 const buffer = await item.file.arrayBuffer(); 2904 info = await vipsGetUltraHdrInfo(buffer); 2905 } catch { 2906 } 2907 if (info) { 2908 ultraHdrItems.add(id); 2909 } 2910 dispatch.finishOperation(id, {}); 2911 }; 2912 } 2913 function uploadItem(id) { 2914 return async ({ select: select2, dispatch }) => { 2915 const item = select2.getItem(id); 2916 if (!item) { 2917 return; 2918 } 2919 const startTime = performance.now(); 2920 let finished = false; 2921 const finishUpload = (attachment) => { 2922 if (finished) { 2923 return; 2924 } 2925 finished = true; 2926 measure({ 2927 measureName: `Upload $item.file.name}`, 2928 startTime, 2929 tooltipText: item.file.name, 2930 properties: [ 2931 ["Item ID", item.id], 2932 ["File name", item.file.name] 2933 ] 2934 }); 2935 dispatch.finishOperation(id, { attachment }); 2936 }; 2937 select2.getSettings().mediaUpload({ 2938 filesList: [item.file], 2939 additionalData: item.additionalData, 2940 signal: item.abortController?.signal, 2941 // The queue's own items drive upload progress UI and save 2942 // locking; without this, consumers that track uploads themselves 2943 // (e.g. the editor's progress snackbar) would count this file a 2944 // second time. 2945 isTransportOnly: true, 2946 onFileChange: ([attachment]) => { 2947 if (attachment && !(0, import_blob.isBlobURL)(attachment.url)) { 2948 finishUpload(attachment); 2949 } 2950 }, 2951 onSuccess: ([attachment]) => { 2952 finishUpload(attachment); 2953 }, 2954 onError: (error) => { 2955 dispatch.cancelItem(id, error); 2956 } 2957 }); 2958 }; 2959 } 2960 function sideloadItem(id) { 2961 return async ({ select: select2, dispatch }) => { 2962 const item = select2.getItem(id); 2963 if (!item) { 2964 return; 2965 } 2966 const { post, ...additionalData } = item.additionalData; 2967 const mediaSideload = select2.getSettings().mediaSideload; 2968 if (!mediaSideload) { 2969 dispatch.finishOperation(id, {}); 2970 return; 2971 } 2972 const startTime = performance.now(); 2973 mediaSideload({ 2974 file: item.file, 2975 attachmentId: post, 2976 additionalData, 2977 signal: item.abortController?.signal, 2978 onSuccess: (subSize) => { 2979 measure({ 2980 measureName: `Sideload $item.file.name}`, 2981 startTime, 2982 tooltipText: item.file.name, 2983 properties: [ 2984 ["Item ID", item.id], 2985 ["File name", item.file.name] 2986 ] 2987 }); 2988 if (item.parentId) { 2989 dispatch({ 2990 type: Type.AccumulateSubSize, 2991 id: item.parentId, 2992 subSize 2993 }); 2994 } 2995 dispatch.finishOperation(id, {}); 2996 }, 2997 onError: (error) => { 2998 dispatch.cancelItem(id, error); 2999 } 3000 }); 3001 }; 3002 } 3003 function resizeCropItem(id, args) { 3004 return async ({ select: select2, dispatch }) => { 3005 const item = select2.getItem(id); 3006 if (!item) { 3007 return; 3008 } 3009 if (!args?.resize) { 3010 dispatch.finishOperation(id, { 3011 file: item.file 3012 }); 3013 return; 3014 } 3015 const startTime = performance.now(); 3016 const addSuffix = Boolean(item.parentId); 3017 const scaledSuffix = Boolean(args.isThresholdResize); 3018 const { imageStripMeta, imageMaxBitDepth } = select2.getSettings(); 3019 try { 3020 const file = await vipsResizeImage( 3021 item.id, 3022 item.file, 3023 args.resize, 3024 { 3025 smartCrop: false, 3026 addSuffix, 3027 signal: item.abortController?.signal, 3028 scaledSuffix, 3029 quality: args.quality, 3030 stripMeta: imageStripMeta, 3031 maxBitdepth: imageMaxBitDepth 3032 } 3033 ); 3034 measure({ 3035 measureName: `ResizeCrop $item.file.name}`, 3036 startTime, 3037 tooltipText: item.file.name, 3038 properties: [ 3039 ["Item ID", item.id], 3040 ["File name", item.file.name] 3041 ] 3042 }); 3043 const blobUrl = (0, import_blob.createBlobURL)(file); 3044 dispatch({ 3045 type: Type.CacheBlobUrl, 3046 id, 3047 blobUrl 3048 }); 3049 dispatch.finishOperation(id, { 3050 file, 3051 attachment: { 3052 url: blobUrl 3053 } 3054 }); 3055 } catch (error) { 3056 dispatch.cancelItem( 3057 id, 3058 new UploadError({ 3059 code: ErrorCode.IMAGE_TRANSCODING_ERROR, 3060 message: (0, import_i18n7.__)( 3061 "The web server cannot generate responsive image sizes for this image. Convert it to JPEG or PNG before uploading." 3062 ), 3063 file: item.file, 3064 cause: error instanceof Error ? error : void 0 3065 }) 3066 ); 3067 } 3068 }; 3069 } 3070 function rotateItem(id, args) { 3071 return async ({ select: select2, dispatch }) => { 3072 const item = select2.getItem(id); 3073 if (!item) { 3074 return; 3075 } 3076 if (!args?.orientation || args.orientation === 1) { 3077 dispatch.finishOperation(id, { 3078 file: item.file 3079 }); 3080 return; 3081 } 3082 const startTime = performance.now(); 3083 try { 3084 const file = await vipsRotateImage( 3085 item.id, 3086 item.file, 3087 args.orientation, 3088 item.abortController?.signal 3089 ); 3090 measure({ 3091 measureName: `Rotate $item.file.name}`, 3092 startTime, 3093 tooltipText: item.file.name, 3094 properties: [ 3095 ["Item ID", item.id], 3096 ["File name", item.file.name] 3097 ] 3098 }); 3099 const blobUrl = (0, import_blob.createBlobURL)(file); 3100 dispatch({ 3101 type: Type.CacheBlobUrl, 3102 id, 3103 blobUrl 3104 }); 3105 dispatch.finishOperation(id, { 3106 file, 3107 attachment: { 3108 url: blobUrl 3109 } 3110 }); 3111 } catch (error) { 3112 dispatch.cancelItem( 3113 id, 3114 new UploadError({ 3115 code: ErrorCode.IMAGE_ROTATION_ERROR, 3116 message: (0, import_i18n7.__)( 3117 "The web server cannot generate responsive image sizes for this image. Convert it to JPEG or PNG before uploading." 3118 ), 3119 file: item.file, 3120 cause: error instanceof Error ? error : void 0 3121 }) 3122 ); 3123 } 3124 }; 3125 } 3126 function transcodeImageItem(id, args) { 3127 return async ({ select: select2, dispatch }) => { 3128 const item = select2.getItem(id); 3129 if (!item) { 3130 return; 3131 } 3132 if (!args?.outputFormat) { 3133 dispatch.finishOperation(id, { 3134 file: item.file 3135 }); 3136 return; 3137 } 3138 const startTime = performance.now(); 3139 const outputMimeType = `image/$args.outputFormat}`; 3140 const quality = args.outputQuality ?? DEFAULT_OUTPUT_QUALITY; 3141 const interlaced = args.interlaced ?? false; 3142 const { imageStripMeta, imageMaxBitDepth } = select2.getSettings(); 3143 try { 3144 const file = await vipsConvertImageFormat( 3145 item.id, 3146 item.file, 3147 outputMimeType, 3148 { 3149 quality, 3150 interlaced, 3151 stripMeta: imageStripMeta, 3152 maxBitdepth: imageMaxBitDepth 3153 } 3154 ); 3155 measure({ 3156 measureName: `Transcode $item.file.name}`, 3157 startTime, 3158 tooltipText: item.file.name, 3159 properties: [ 3160 ["Item ID", item.id], 3161 ["File name", item.file.name] 3162 ] 3163 }); 3164 const blobUrl = (0, import_blob.createBlobURL)(file); 3165 dispatch({ 3166 type: Type.CacheBlobUrl, 3167 id, 3168 blobUrl 3169 }); 3170 dispatch.finishOperation(id, { 3171 file, 3172 attachment: { 3173 url: blobUrl 3174 } 3175 }); 3176 } catch (error) { 3177 dispatch.cancelItem( 3178 id, 3179 new UploadError({ 3180 code: ErrorCode.MEDIA_TRANSCODING_ERROR, 3181 message: "Image could not be transcoded to the target format", 3182 file: item.file, 3183 cause: error instanceof Error ? error : void 0 3184 }) 3185 ); 3186 } 3187 }; 3188 } 3189 function transcodeGifItem(id, args) { 3190 return async ({ select: select2, dispatch }) => { 3191 const item = select2.getItem(id); 3192 if (!item) { 3193 return; 3194 } 3195 const outputFormat = args?.outputFormat ?? "mp4"; 3196 const outputMimeType = `video/$outputFormat}`; 3197 const gifFile = item.file; 3198 try { 3199 const file = await convertGifToVideo( 3200 item.id, 3201 gifFile, 3202 outputMimeType, 3203 { 3204 timeout: args?.timeout, 3205 maxTotalPixels: args?.maxTotalPixels 3206 } 3207 ); 3208 dispatch.finishOperation(id, { file }); 3209 dispatch.addSideloadItem({ 3210 file: gifFile, 3211 batchId: v4_default(), 3212 parentId: item.parentId, 3213 additionalData: { 3214 post: item.additionalData?.post, 3215 image_size: "animated_video_poster", 3216 convert_format: false 3217 }, 3218 operations: [ 3219 [ 3220 OperationType.TranscodeImage, 3221 { 3222 outputFormat: "jpeg", 3223 outputQuality: DEFAULT_OUTPUT_QUALITY, 3224 interlaced: false 3225 } 3226 ], 3227 OperationType.Upload 3228 ] 3229 }); 3230 } catch (error) { 3231 if (isUnsupportedConversionError(error)) { 3232 if (isSizeLimitConversionError(error)) { 3233 debug( 3234 `Skipping GIF to video conversion: $error instanceof Error ? error.message : error}` 3235 ); 3236 } 3237 dispatch.cancelItem( 3238 id, 3239 new Error("Animated GIF conversion unsupported"), 3240 true 3241 ); 3242 return; 3243 } 3244 if (isConversionTimeoutError(error)) { 3245 debug( 3246 `GIF to video conversion timed out; keeping the original GIF only: $error instanceof Error ? error.message : error}` 3247 ); 3248 dispatch.cancelItem( 3249 id, 3250 new Error("Animated GIF conversion timed out"), 3251 true 3252 ); 3253 return; 3254 } 3255 console.error( 3256 "[video-conversion] GIF to video conversion failed:", 3257 error 3258 ); 3259 dispatch.cancelItem( 3260 id, 3261 new UploadError({ 3262 code: ErrorCode.GIF_TRANSCODING_ERROR, 3263 message: "Animated GIF could not be converted to video", 3264 file: item.file, 3265 cause: error instanceof Error ? error : void 0 3266 }), 3267 true 3268 ); 3269 } 3270 }; 3271 } 3272 function generateThumbnails(id) { 3273 return async ({ select: select2, dispatch }) => { 3274 const item = select2.getItem(id); 3275 if (!item) { 3276 return; 3277 } 3278 if (!item.attachment) { 3279 dispatch.finishOperation(id, {}); 3280 return; 3281 } 3282 const attachment = item.attachment; 3283 const settings = select2.getSettings(); 3284 if (item.originalHeicFile && attachment.id) { 3285 dispatch.addSideloadItem({ 3286 file: item.originalHeicFile, 3287 batchId: v4_default(), 3288 parentId: item.id, 3289 additionalData: { 3290 post: attachment.id, 3291 image_size: "source_original", 3292 convert_format: false 3293 }, 3294 operations: [OperationType.Upload] 3295 }); 3296 } 3297 if (item.animatedGifFile && attachment.id) { 3298 const outputFormat = settings.videoOutputFormat === "video/webm" ? "webm" : "mp4"; 3299 dispatch.addSideloadItem({ 3300 file: item.animatedGifFile, 3301 batchId: v4_default(), 3302 parentId: item.id, 3303 additionalData: { 3304 post: attachment.id, 3305 image_size: "animated_video", 3306 convert_format: false 3307 }, 3308 operations: [ 3309 [ 3310 OperationType.TranscodeGif, 3311 { 3312 outputFormat 3313 } 3314 ], 3315 OperationType.Upload 3316 ] 3317 }); 3318 } 3319 let exifOrientation = attachment.exif_orientation || 1; 3320 const sourceType = item.sourceFile.type; 3321 const isHeifFamily = sourceType === "image/avif" || sourceType === "image/heif"; 3322 let needsClientRotation = false; 3323 if (isHeifFamily) { 3324 exifOrientation = getUnappliedExifOrientation( 3325 await item.sourceFile.arrayBuffer() 3326 ); 3327 needsClientRotation = exifOrientation !== 1; 3328 } 3329 let rotatedSource; 3330 { 3331 const needsRotation = exifOrientation !== 1 && !item.file.name.includes("-scaled"); 3332 if ((needsRotation || needsClientRotation) && attachment.id) { 3333 try { 3334 rotatedSource = await vipsRotateImage( 3335 item.id, 3336 item.sourceFile, 3337 exifOrientation, 3338 item.abortController?.signal 3339 ); 3340 } catch { 3341 console.warn( 3342 "Failed to rotate image, continuing with thumbnails" 3343 ); 3344 } 3345 } 3346 if (needsRotation && rotatedSource && attachment.id) { 3347 dispatch.addSideloadItem({ 3348 file: rotatedSource, 3349 batchId: v4_default(), 3350 parentId: item.id, 3351 additionalData: { 3352 post: attachment.id, 3353 image_size: "original", 3354 convert_format: false 3355 }, 3356 operations: [OperationType.Upload] 3357 }); 3358 } 3359 } 3360 if (!item.parentId && attachment.missing_image_sizes && attachment.missing_image_sizes.length > 0) { 3361 const allImageSizes = settings.allImageSizes || {}; 3362 const sizesToGenerate = attachment.missing_image_sizes; 3363 const thumbnailSource = needsClientRotation && rotatedSource ? rotatedSource : item.sourceFile; 3364 const file = attachment.filename ? renameFile(thumbnailSource, attachment.filename) : thumbnailSource; 3365 const batchId = v4_default(); 3366 const isUltraHdr = ultraHdrItems.has(item.id); 3367 const outputMimeType = attachment.image_output_format; 3368 const interlaced = attachment.image_save_progressive ?? false; 3369 const imageQuality = attachment.image_quality; 3370 const fallbackQuality = settings.imageQuality ?? DEFAULT_OUTPUT_QUALITY; 3371 const defaultQuality = typeof imageQuality?.default === "number" ? imageQuality.default / 100 : fallbackQuality; 3372 const qualityForSize = (sizeName) => { 3373 const sized = imageQuality?.sizes?.[sizeName]; 3374 if (typeof sized === "number") { 3375 return sized / 100; 3376 } 3377 return defaultQuality; 3378 }; 3379 let thumbnailTranscodeOperation = null; 3380 if (!isUltraHdr && outputMimeType) { 3381 thumbnailTranscodeOperation = await getTranscodeImageOperation( 3382 thumbnailSource, 3383 outputMimeType, 3384 interlaced, 3385 defaultQuality 3386 ); 3387 } 3388 const dimensionGroups = /* @__PURE__ */ new Map(); 3389 for (const name of sizesToGenerate) { 3390 const imageSize = allImageSizes[name]; 3391 if (!imageSize) { 3392 console.warn( 3393 `Image size "$name}" not found in configuration` 3394 ); 3395 continue; 3396 } 3397 const key = `$imageSize.width}x$imageSize.height}x$imageSize.crop}`; 3398 const group = dimensionGroups.get(key); 3399 if (group) { 3400 group.push(name); 3401 } else { 3402 dimensionGroups.set(key, [name]); 3403 } 3404 } 3405 for (const [, names] of dimensionGroups) { 3406 const imageSize = allImageSizes[names[0]]; 3407 const sizeQuality = qualityForSize(names[0]); 3408 const thumbnailOperations = [ 3409 [ 3410 OperationType.ResizeCrop, 3411 { resize: imageSize, quality: sizeQuality } 3412 ] 3413 ]; 3414 if (!isUltraHdr && thumbnailTranscodeOperation) { 3415 thumbnailOperations.push([ 3416 thumbnailTranscodeOperation[0], 3417 { 3418 ...thumbnailTranscodeOperation[1], 3419 outputQuality: sizeQuality 3420 } 3421 ]); 3422 } 3423 thumbnailOperations.push(OperationType.Upload); 3424 const imageSizeParam = names.length === 1 ? names[0] : names; 3425 dispatch.addSideloadItem({ 3426 file, 3427 batchId, 3428 parentId: item.id, 3429 additionalData: { 3430 // Sideloading does not use the parent post ID but the 3431 // attachment ID as the image sizes need to be added to it. 3432 post: attachment.id, 3433 image_size: imageSizeParam, 3434 convert_format: false 3435 }, 3436 operations: thumbnailOperations 3437 }); 3438 } 3439 { 3440 const { bigImageSizeThreshold } = settings; 3441 if (bigImageSizeThreshold && attachment.id) { 3442 const bitmap = await createImageBitmap(thumbnailSource); 3443 const needsScaling = bitmap.width > bigImageSizeThreshold || bitmap.height > bigImageSizeThreshold; 3444 bitmap.close(); 3445 if (needsScaling) { 3446 const sourceForScaled = attachment.filename ? renameFile(thumbnailSource, attachment.filename) : thumbnailSource; 3447 const scaledOperations = [ 3448 [ 3449 OperationType.ResizeCrop, 3450 { 3451 resize: { 3452 width: bigImageSizeThreshold, 3453 height: bigImageSizeThreshold 3454 }, 3455 isThresholdResize: true, 3456 quality: defaultQuality 3457 } 3458 ] 3459 ]; 3460 if (!isUltraHdr && thumbnailTranscodeOperation) { 3461 scaledOperations.push( 3462 thumbnailTranscodeOperation 3463 ); 3464 } 3465 scaledOperations.push(OperationType.Upload); 3466 dispatch.addSideloadItem({ 3467 file: sourceForScaled, 3468 batchId, 3469 parentId: item.id, 3470 additionalData: { 3471 post: attachment.id, 3472 image_size: "scaled", 3473 convert_format: false 3474 }, 3475 operations: scaledOperations 3476 }); 3477 } 3478 } 3479 } 3480 } 3481 dispatch.finishOperation(id, {}); 3482 }; 3483 } 3484 function finalizeItem(id) { 3485 return async ({ select: select2, dispatch }) => { 3486 const item = select2.getItem(id); 3487 if (!item) { 3488 return; 3489 } 3490 const attachment = item.attachment; 3491 const { mediaFinalize } = select2.getSettings(); 3492 const updates = {}; 3493 if (attachment?.id && mediaFinalize) { 3494 try { 3495 const updatedAttachment = await mediaFinalize( 3496 attachment.id, 3497 item.subSizes || [] 3498 ); 3499 if (updatedAttachment) { 3500 updates.attachment = updatedAttachment; 3501 } 3502 } catch (error) { 3503 console.warn("Media finalization failed:", error); 3504 dispatch.cancelItem( 3505 id, 3506 new UploadError({ 3507 code: ErrorCode.MEDIA_FINALIZE_ERROR, 3508 message: (0, import_i18n7.__)("Could not finalize the upload."), 3509 file: item.file 3510 }) 3511 ); 3512 return; 3513 } 3514 } 3515 dispatch.finishOperation(id, updates); 3516 }; 3517 } 3518 function revokeBlobUrls(id) { 3519 return async ({ select: select2, dispatch }) => { 3520 const blobUrls = select2.getBlobUrls(id); 3521 for (const blobUrl of blobUrls) { 3522 (0, import_blob.revokeBlobURL)(blobUrl); 3523 } 3524 dispatch({ 3525 type: Type.RevokeBlobUrls, 3526 id 3527 }); 3528 }; 3529 } 3530 function updateItemProgress(id, progress) { 3531 return async ({ dispatch }) => { 3532 dispatch({ 3533 type: Type.UpdateProgress, 3534 id, 3535 progress 3536 }); 3537 }; 3538 } 3539 function updateSettings(settings) { 3540 return { 3541 type: Type.UpdateSettings, 3542 settings 3543 }; 3544 } 3545 3546 // packages/upload-media/build-module/lock-unlock.mjs 3547 var import_private_apis = __toESM(require_private_apis(), 1); 3548 var { lock, unlock } = (0, import_private_apis.__dangerousOptInToUnstableAPIsOnlyForCoreModules)( 3549 "I acknowledge private features are not for use in themes or plugins and doing so will break in the next version of WordPress.", 3550 "@wordpress/upload-media" 3551 ); 3552 3553 // packages/upload-media/build-module/store/index.mjs 3554 var storeConfig = { 3555 reducer: reducer_default, 3556 selectors: selectors_exports, 3557 actions: actions_exports 3558 }; 3559 var store = (0, import_data.createReduxStore)(STORE_NAME, { 3560 reducer: reducer_default, 3561 selectors: selectors_exports, 3562 actions: actions_exports 3563 }); 3564 if (!(0, import_data.select)(store)) { 3565 (0, import_data.register)(store); 3566 } 3567 unlock(store).registerPrivateActions(private_actions_exports); 3568 unlock(store).registerPrivateSelectors(private_selectors_exports); 3569 3570 // packages/upload-media/build-module/components/provider/index.mjs 3571 var import_element2 = __toESM(require_element(), 1); 3572 var import_data3 = __toESM(require_data(), 1); 3573 3574 // packages/upload-media/build-module/components/provider/with-registry-provider.mjs 3575 var import_element = __toESM(require_element(), 1); 3576 var import_data2 = __toESM(require_data(), 1); 3577 var import_compose = __toESM(require_compose(), 1); 3578 var import_jsx_runtime = __toESM(require_jsx_runtime(), 1); 3579 function getSubRegistry(subRegistries, registry, useSubRegistry) { 3580 if (!useSubRegistry) { 3581 return registry; 3582 } 3583 let subRegistry = subRegistries.get(registry); 3584 if (!subRegistry) { 3585 subRegistry = (0, import_data2.createRegistry)({}, registry); 3586 subRegistry.registerStore(STORE_NAME, storeConfig); 3587 subRegistries.set(registry, subRegistry); 3588 } 3589 return subRegistry; 3590 } 3591 var withRegistryProvider = (0, import_compose.createHigherOrderComponent)( 3592 (WrappedComponent) => ({ useSubRegistry = true, ...props }) => { 3593 const registry = (0, import_data2.useRegistry)(); 3594 const [subRegistries] = (0, import_element.useState)(() => /* @__PURE__ */ new WeakMap()); 3595 const subRegistry = getSubRegistry( 3596 subRegistries, 3597 registry, 3598 useSubRegistry 3599 ); 3600 if (subRegistry === registry) { 3601 return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(WrappedComponent, { registry, ...props }); 3602 } 3603 return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_data2.RegistryProvider, { value: subRegistry, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(WrappedComponent, { registry: subRegistry, ...props }) }); 3604 }, 3605 "withRegistryProvider" 3606 ); 3607 var with_registry_provider_default = withRegistryProvider; 3608 3609 // packages/upload-media/build-module/components/provider/index.mjs 3610 var import_jsx_runtime2 = __toESM(require_jsx_runtime(), 1); 3611 var MediaUploadProvider = with_registry_provider_default((props) => { 3612 const { children, settings } = props; 3613 const { updateSettings: updateSettings2 } = unlock((0, import_data3.useDispatch)(store)); 3614 (0, import_element2.useEffect)(() => { 3615 updateSettings2(settings); 3616 }, [settings, updateSettings2]); 3617 return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children }); 3618 }); 3619 var provider_default = MediaUploadProvider; 3620 3621 // packages/upload-media/build-module/error-messages.mjs 3622 var import_i18n8 = __toESM(require_i18n(), 1); 3623 function getErrorMessage(code, fileName) { 3624 const messages = { 3625 [ErrorCode.EMPTY_FILE]: { 3626 title: (0, import_i18n8.__)("Empty file"), 3627 description: (0, import_i18n8.sprintf)( 3628 /* translators: %s: file name */ 3629 (0, import_i18n8.__)('"%s" is empty.'), 3630 fileName 3631 ), 3632 action: (0, import_i18n8.__)("Please choose a different file.") 3633 }, 3634 [ErrorCode.SIZE_ABOVE_LIMIT]: { 3635 title: (0, import_i18n8.__)("File too large"), 3636 description: (0, import_i18n8.sprintf)( 3637 /* translators: %s: file name */ 3638 (0, import_i18n8.__)('"%s" exceeds the maximum upload size.'), 3639 fileName 3640 ), 3641 action: (0, import_i18n8.__)("Please reduce the file size and try again.") 3642 }, 3643 [ErrorCode.MIME_TYPE_NOT_SUPPORTED]: { 3644 title: (0, import_i18n8.__)("Unsupported file type"), 3645 description: (0, import_i18n8.sprintf)( 3646 /* translators: %s: file name */ 3647 (0, import_i18n8.__)('"%s" is not a supported file type.'), 3648 fileName 3649 ), 3650 action: (0, import_i18n8.__)("Please upload a different file format.") 3651 }, 3652 [ErrorCode.MIME_TYPE_NOT_ALLOWED_FOR_USER]: { 3653 title: (0, import_i18n8.__)("File type not allowed"), 3654 description: (0, import_i18n8.sprintf)( 3655 /* translators: %s: file name */ 3656 (0, import_i18n8.__)('You are not allowed to upload "%s".'), 3657 fileName 3658 ), 3659 action: (0, import_i18n8.__)("Please contact your site administrator.") 3660 }, 3661 [ErrorCode.HEIC_DECODE_ERROR]: { 3662 title: (0, import_i18n8.__)("HEIC decode failed"), 3663 description: (0, import_i18n8.sprintf)( 3664 /* translators: %s: file name */ 3665 (0, import_i18n8.__)('Failed to decode HEIC file "%s".'), 3666 fileName 3667 ), 3668 action: getHeicConversionAdvice() 3669 }, 3670 [ErrorCode.IMAGE_TRANSCODING_ERROR]: { 3671 title: (0, import_i18n8.__)("Image processing failed"), 3672 description: (0, import_i18n8.sprintf)( 3673 /* translators: %s: file name */ 3674 (0, import_i18n8.__)('Failed to process "%s".'), 3675 fileName 3676 ), 3677 action: (0, import_i18n8.__)("The image may be corrupted. Try a different file.") 3678 }, 3679 [ErrorCode.IMAGE_ROTATION_ERROR]: { 3680 title: (0, import_i18n8.__)("Image rotation failed"), 3681 description: (0, import_i18n8.sprintf)( 3682 /* translators: %s: file name */ 3683 (0, import_i18n8.__)('Failed to rotate "%s".'), 3684 fileName 3685 ), 3686 action: (0, import_i18n8.__)("The image may be corrupted. Try a different file.") 3687 }, 3688 [ErrorCode.MEDIA_TRANSCODING_ERROR]: { 3689 title: (0, import_i18n8.__)("Media processing failed"), 3690 description: (0, import_i18n8.sprintf)( 3691 /* translators: %s: file name */ 3692 (0, import_i18n8.__)('Failed to convert "%s" to the target format.'), 3693 fileName 3694 ), 3695 action: (0, import_i18n8.__)("The file may be corrupted. Try a different file.") 3696 }, 3697 [ErrorCode.MEDIA_FINALIZE_ERROR]: { 3698 title: (0, import_i18n8.__)("Upload failed"), 3699 description: (0, import_i18n8.sprintf)( 3700 /* translators: %s: file name */ 3701 (0, import_i18n8.__)('Could not finalize the upload of "%s".'), 3702 fileName 3703 ), 3704 action: (0, import_i18n8.__)("Please try again.") 3705 }, 3706 [ErrorCode.GENERAL]: { 3707 title: (0, import_i18n8.__)("Upload failed"), 3708 description: (0, import_i18n8.sprintf)( 3709 /* translators: %s: file name */ 3710 (0, import_i18n8.__)('Failed to upload "%s".'), 3711 fileName 3712 ), 3713 action: (0, import_i18n8.__)("Please try again.") 3714 } 3715 }; 3716 return messages[code] || { 3717 title: (0, import_i18n8.__)("Upload failed"), 3718 description: (0, import_i18n8.sprintf)( 3719 /* translators: %s: file name */ 3720 (0, import_i18n8.__)('Failed to upload "%s".'), 3721 fileName 3722 ), 3723 action: (0, import_i18n8.__)("Please try again.") 3724 }; 3725 } 3726 return __toCommonJS(index_exports); 3727 })(); 3728 (window.wp ||= {}).uploadMedia = wp.uploadMedia; 3729 })();
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated : Thu Aug 13 08:20:23 2026 | Cross-referenced by PHPXref |