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