@emailmaker/filemanager 0.10.92 → 0.10.94
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/adapters/DataSourceProxyBase.d.ts +4 -0
- package/adapters/DataSourceProxyBase.rename.test.d.ts +1 -0
- package/adapters/DataSourceProxyBase.trash.test.d.ts +1 -0
- package/adapters/PathAwareStorageAdapter.d.ts +1 -0
- package/adapters/PathAwareStorageAdapter.trash.test.d.ts +1 -0
- package/adapters/TreeCache.d.ts +4 -19
- package/adapters/TreeCache.sortedView.test.d.ts +1 -0
- package/adapters/cacheViewStrategy.d.ts +31 -0
- package/adapters/cacheViewStrategy.test.d.ts +1 -0
- package/adapters/cacheViewTypes.d.ts +19 -0
- package/adapters/systemFolderPath.d.ts +27 -0
- package/adapters/systemFolderPath.test.d.ts +1 -0
- package/{file-manager-IconsTab-BMy0LDoU.js → file-manager-IconsTab-BOtfHzE7.js} +2 -2
- package/{file-manager-ImageCodeGenerator-CBdZ5eV3.js → file-manager-ImageCodeGenerator-D1ihYSGj.js} +2 -2
- package/{file-manager-JsBarcode-Bk9cl2mc.js → file-manager-JsBarcode-B-rE9quR.js} +2 -2
- package/{file-manager-browser-D-EORGqh.js → file-manager-browser-CBL2rGT5.js} +2 -2
- package/{file-manager-index-Z8TrA-pu.js → file-manager-index-CkVS948A.js} +3 -3
- package/file-manager.css +142 -142
- package/file-manager.esm.js +1 -1
- package/file-manager.js +595 -511
- package/index.d.ts +2 -0
- package/package.json +1 -1
- package/utils/mapWithConcurrency.d.ts +1 -0
package/file-manager.js
CHANGED
|
@@ -22726,8 +22726,8 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
22726
22726
|
|
|
22727
22727
|
// EXTERNAL MODULE: ./src/hooks/core/context.tsx
|
|
22728
22728
|
var context = __webpack_require__(8361);
|
|
22729
|
-
// EXTERNAL MODULE: ./src/hooks/core/files/index.ts +
|
|
22730
|
-
var core_files = __webpack_require__(
|
|
22729
|
+
// EXTERNAL MODULE: ./src/hooks/core/files/index.ts + 18 modules
|
|
22730
|
+
var core_files = __webpack_require__(8573);
|
|
22731
22731
|
;// ./src/hooks/core/useFiles.ts
|
|
22732
22732
|
|
|
22733
22733
|
|
|
@@ -27028,8 +27028,8 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
27028
27028
|
var core = __webpack_require__(4002);
|
|
27029
27029
|
// EXTERNAL MODULE: external {"root":"React","commonjs2":"react","commonjs":"react","amd":"react"}
|
|
27030
27030
|
var external_root_React_commonjs2_react_commonjs_react_amd_react_ = __webpack_require__(5442);
|
|
27031
|
-
// EXTERNAL MODULE: ./src/hooks/core/files/index.ts +
|
|
27032
|
-
var core_files = __webpack_require__(
|
|
27031
|
+
// EXTERNAL MODULE: ./src/hooks/core/files/index.ts + 18 modules
|
|
27032
|
+
var core_files = __webpack_require__(8573);
|
|
27033
27033
|
;// ./src/hooks/useFileActions.ts
|
|
27034
27034
|
|
|
27035
27035
|
|
|
@@ -28282,314 +28282,7 @@ const FileManagerProvider = ({ children, options }) => {
|
|
|
28282
28282
|
|
|
28283
28283
|
/***/ }),
|
|
28284
28284
|
|
|
28285
|
-
/***/
|
|
28286
|
-
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
28287
|
-
|
|
28288
|
-
"use strict";
|
|
28289
|
-
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
28290
|
-
/* harmony export */ $5: () => (/* binding */ getUniqueFileName),
|
|
28291
|
-
/* harmony export */ mF: () => (/* binding */ encodeUrlForImageSrc),
|
|
28292
|
-
/* harmony export */ nF: () => (/* binding */ formatFileSizeDisplay),
|
|
28293
|
-
/* harmony export */ v7: () => (/* binding */ formatFileSize),
|
|
28294
|
-
/* harmony export */ w3: () => (/* binding */ MAX_FILE_SIZE)
|
|
28295
|
-
/* harmony export */ });
|
|
28296
|
-
/* unused harmony exports MIN_FILE_SIZE, ALLOWED_FILE_TYPES, ALL_ALLOWED_TYPES, validateFile, validateFiles, validateFileUrl, getFileCategory, formatFileSizeShort, sanitizeFileName */
|
|
28297
|
-
/* harmony import */ var antd__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(550);
|
|
28298
|
-
/* harmony import */ var antd__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(antd__WEBPACK_IMPORTED_MODULE_0__);
|
|
28299
|
-
/* harmony import */ var _i18n__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3829);
|
|
28300
|
-
|
|
28301
|
-
|
|
28302
|
-
const MAX_FILE_SIZE = 50 * 1024 * 1024;
|
|
28303
|
-
const MIN_FILE_SIZE = 1;
|
|
28304
|
-
const ALLOWED_FILE_TYPES = {
|
|
28305
|
-
images: ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml', 'image/bmp', 'image/tiff'],
|
|
28306
|
-
documents: [
|
|
28307
|
-
'application/pdf',
|
|
28308
|
-
'text/plain',
|
|
28309
|
-
'application/msword',
|
|
28310
|
-
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
28311
|
-
],
|
|
28312
|
-
archives: ['application/zip', 'application/x-rar-compressed', 'application/x-7z-compressed'],
|
|
28313
|
-
videos: ['video/mp4', 'video/avi', 'video/quicktime', 'video/x-msvideo'],
|
|
28314
|
-
audio: ['audio/mpeg', 'audio/wav', 'audio/ogg'],
|
|
28315
|
-
};
|
|
28316
|
-
const ALL_ALLOWED_TYPES = Object.values(ALLOWED_FILE_TYPES).flat();
|
|
28317
|
-
const validateFile = (file, options = {}) => {
|
|
28318
|
-
const { maxSize = MAX_FILE_SIZE, minSize = MIN_FILE_SIZE, allowedTypes = ALL_ALLOWED_TYPES, allowAllTypes = false, maxFileNameLength = 255, } = options;
|
|
28319
|
-
const errors = [];
|
|
28320
|
-
const warnings = [];
|
|
28321
|
-
if (file.size > maxSize) {
|
|
28322
|
-
errors.push(i18n.t('File too large. Maximum size: {{size}}', { size: formatFileSize(maxSize) }));
|
|
28323
|
-
}
|
|
28324
|
-
if (file.size < minSize) {
|
|
28325
|
-
errors.push(i18n.t('File too small. Minimum size: {{size}}', { size: formatFileSize(minSize) }));
|
|
28326
|
-
}
|
|
28327
|
-
if (!allowAllTypes && !allowedTypes.includes(file.type)) {
|
|
28328
|
-
errors.push(i18n.t('Unsupported file type: {{type}}', { type: file.type || i18n.t('unknown') }));
|
|
28329
|
-
}
|
|
28330
|
-
if (file.name.length > maxFileNameLength) {
|
|
28331
|
-
errors.push(i18n.t('File name is too long. Maximum {{max}} characters', { max: maxFileNameLength }));
|
|
28332
|
-
}
|
|
28333
|
-
const invalidChars = /[<>:"/\\|?*()#]/;
|
|
28334
|
-
const hasControlChars = file.name.split('').some(char => {
|
|
28335
|
-
const code = char.charCodeAt(0);
|
|
28336
|
-
return code >= 0 && code <= 31;
|
|
28337
|
-
});
|
|
28338
|
-
if (invalidChars.test(file.name) || hasControlChars) {
|
|
28339
|
-
errors.push(i18n.t('File name contains invalid characters'));
|
|
28340
|
-
}
|
|
28341
|
-
if (file.size > 10 * 1024 * 1024) {
|
|
28342
|
-
warnings.push(i18n.t('Large file may take a long time to upload'));
|
|
28343
|
-
}
|
|
28344
|
-
return {
|
|
28345
|
-
isValid: errors.length === 0,
|
|
28346
|
-
errors,
|
|
28347
|
-
warnings,
|
|
28348
|
-
};
|
|
28349
|
-
};
|
|
28350
|
-
const validateFiles = (files, options = {}) => {
|
|
28351
|
-
const valid = [];
|
|
28352
|
-
const invalid = [];
|
|
28353
|
-
files.forEach(file => {
|
|
28354
|
-
const result = validateFile(file, options);
|
|
28355
|
-
if (result.isValid) {
|
|
28356
|
-
valid.push(file);
|
|
28357
|
-
}
|
|
28358
|
-
else {
|
|
28359
|
-
invalid.push({ file, result });
|
|
28360
|
-
}
|
|
28361
|
-
});
|
|
28362
|
-
return { valid, invalid };
|
|
28363
|
-
};
|
|
28364
|
-
const validateFileUrl = async (url) => {
|
|
28365
|
-
const errors = [];
|
|
28366
|
-
let notified = false;
|
|
28367
|
-
let lastError = undefined;
|
|
28368
|
-
const notifyError = (message) => {
|
|
28369
|
-
notified = true;
|
|
28370
|
-
notification.error({
|
|
28371
|
-
key: 'FILE_URL_VALIDATION_FAILED',
|
|
28372
|
-
title: message,
|
|
28373
|
-
placement: 'bottomRight',
|
|
28374
|
-
description: url,
|
|
28375
|
-
});
|
|
28376
|
-
};
|
|
28377
|
-
try {
|
|
28378
|
-
new URL(url);
|
|
28379
|
-
}
|
|
28380
|
-
catch (error) {
|
|
28381
|
-
console.error('Invalid URL:', error);
|
|
28382
|
-
lastError = error;
|
|
28383
|
-
const message = i18n.t('Invalid file URL');
|
|
28384
|
-
errors.push(message);
|
|
28385
|
-
notifyError(message);
|
|
28386
|
-
return { isValid: false, errors };
|
|
28387
|
-
}
|
|
28388
|
-
try {
|
|
28389
|
-
const response = await fetch(url, { method: 'HEAD' });
|
|
28390
|
-
if (!response.ok) {
|
|
28391
|
-
errors.push(i18n.t('File unavailable: {{status}} {{statusText}}', {
|
|
28392
|
-
status: response.status,
|
|
28393
|
-
statusText: response.statusText,
|
|
28394
|
-
}));
|
|
28395
|
-
}
|
|
28396
|
-
const contentLength = response.headers.get('content-length');
|
|
28397
|
-
if (contentLength && parseInt(contentLength) > MAX_FILE_SIZE) {
|
|
28398
|
-
errors.push(i18n.t('File too large: {{size}}', { size: formatFileSize(parseInt(contentLength)) }));
|
|
28399
|
-
}
|
|
28400
|
-
const contentType = response.headers.get('content-type');
|
|
28401
|
-
if (contentType && !ALL_ALLOWED_TYPES.includes(contentType)) {
|
|
28402
|
-
errors.push(i18n.t('Unsupported file type: {{contentType}}', { contentType }));
|
|
28403
|
-
}
|
|
28404
|
-
}
|
|
28405
|
-
catch (error) {
|
|
28406
|
-
console.error('Failed to validate file URL:', error);
|
|
28407
|
-
lastError = error;
|
|
28408
|
-
const message = i18n.t('Unable to validate file URL');
|
|
28409
|
-
errors.push(message);
|
|
28410
|
-
notifyError(message);
|
|
28411
|
-
}
|
|
28412
|
-
if (errors.length > 0 && !notified) {
|
|
28413
|
-
notifyError(i18n.t('Unable to validate file URL'));
|
|
28414
|
-
}
|
|
28415
|
-
return {
|
|
28416
|
-
isValid: errors.length === 0,
|
|
28417
|
-
errors,
|
|
28418
|
-
};
|
|
28419
|
-
};
|
|
28420
|
-
const getFileCategory = (file) => {
|
|
28421
|
-
const type = file.type;
|
|
28422
|
-
if (ALLOWED_FILE_TYPES.images.includes(type))
|
|
28423
|
-
return 'image';
|
|
28424
|
-
if (ALLOWED_FILE_TYPES.documents.includes(type))
|
|
28425
|
-
return 'document';
|
|
28426
|
-
if (ALLOWED_FILE_TYPES.archives.includes(type))
|
|
28427
|
-
return 'archive';
|
|
28428
|
-
if (ALLOWED_FILE_TYPES.videos.includes(type))
|
|
28429
|
-
return 'video';
|
|
28430
|
-
if (ALLOWED_FILE_TYPES.audio.includes(type))
|
|
28431
|
-
return 'audio';
|
|
28432
|
-
return 'other';
|
|
28433
|
-
};
|
|
28434
|
-
const formatFileSize = (bytes) => {
|
|
28435
|
-
if (bytes === 0)
|
|
28436
|
-
return '0 Bytes';
|
|
28437
|
-
const k = 1024;
|
|
28438
|
-
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
|
28439
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
28440
|
-
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
28441
|
-
};
|
|
28442
|
-
const formatFileSizeShort = (bytes) => {
|
|
28443
|
-
if (!bytes || bytes <= 0)
|
|
28444
|
-
return '';
|
|
28445
|
-
const KILOBYTE = 1024;
|
|
28446
|
-
const MEGABYTE = KILOBYTE * 1024;
|
|
28447
|
-
if (bytes < MEGABYTE) {
|
|
28448
|
-
const kb = Math.round(bytes / KILOBYTE);
|
|
28449
|
-
return `${kb} Kb`;
|
|
28450
|
-
}
|
|
28451
|
-
const mb = bytes / MEGABYTE;
|
|
28452
|
-
return `${mb.toFixed(2)} Mb`;
|
|
28453
|
-
};
|
|
28454
|
-
const formatFileSizeDisplay = (value) => {
|
|
28455
|
-
if (value === undefined || value === null)
|
|
28456
|
-
return '';
|
|
28457
|
-
if (typeof value === 'number') {
|
|
28458
|
-
return formatFileSizeShort(value);
|
|
28459
|
-
}
|
|
28460
|
-
const normalized = String(value).trim();
|
|
28461
|
-
if (!normalized)
|
|
28462
|
-
return '';
|
|
28463
|
-
const parsed = Number(normalized);
|
|
28464
|
-
if (!Number.isNaN(parsed)) {
|
|
28465
|
-
return formatFileSizeShort(parsed);
|
|
28466
|
-
}
|
|
28467
|
-
return normalized;
|
|
28468
|
-
};
|
|
28469
|
-
/**
|
|
28470
|
-
* Генерирует уникальное имя файла: если name уже есть в existingNames, добавляет _1 (или _2, _3 и т.д.).
|
|
28471
|
-
* @param name — исходное имя файла (с расширением)
|
|
28472
|
-
* @param existingNames — массив имён файлов/папок в целевой директории
|
|
28473
|
-
*/
|
|
28474
|
-
const getUniqueFileName = (name, existingNames) => {
|
|
28475
|
-
const safeNames = existingNames.filter((n) => typeof n === 'string');
|
|
28476
|
-
const set = new Set(safeNames.map(n => n.toLowerCase()));
|
|
28477
|
-
const safeName = typeof name === 'string' ? name : String(name !== null && name !== void 0 ? name : '');
|
|
28478
|
-
if (!set.has(safeName.toLowerCase()))
|
|
28479
|
-
return safeName;
|
|
28480
|
-
const lastDot = safeName.lastIndexOf('.');
|
|
28481
|
-
const baseName = lastDot > 0 ? safeName.slice(0, lastDot) : safeName;
|
|
28482
|
-
const ext = lastDot > 0 ? safeName.slice(lastDot) : '';
|
|
28483
|
-
let suffix = 1;
|
|
28484
|
-
let candidate;
|
|
28485
|
-
do {
|
|
28486
|
-
candidate = `${baseName}_${suffix}${ext}`;
|
|
28487
|
-
suffix++;
|
|
28488
|
-
} while (set.has(candidate.toLowerCase()));
|
|
28489
|
-
return candidate;
|
|
28490
|
-
};
|
|
28491
|
-
/**
|
|
28492
|
-
* Кодирует URL для безопасного использования в img src. Решает проблему с кириллицей и другими
|
|
28493
|
-
* не-ASCII символами в пути (например, emcdn.ru/.../Снимок_экрана.png).
|
|
28494
|
-
* data: и blob: URLs возвращаются без изменений.
|
|
28495
|
-
*/
|
|
28496
|
-
const encodeUrlForImageSrc = (url) => {
|
|
28497
|
-
if (!url || typeof url !== 'string')
|
|
28498
|
-
return undefined;
|
|
28499
|
-
if (url.startsWith('data:') || url.startsWith('blob:'))
|
|
28500
|
-
return url;
|
|
28501
|
-
try {
|
|
28502
|
-
if (url.startsWith('http://') || url.startsWith('https://') || url.startsWith('/')) {
|
|
28503
|
-
const parsed = new URL(url.startsWith('/') ? `https://x${url}` : url);
|
|
28504
|
-
const origin = url.startsWith('/') ? '' : `${parsed.protocol}//${parsed.host}`;
|
|
28505
|
-
const pathEncoded = parsed.pathname
|
|
28506
|
-
.split('/')
|
|
28507
|
-
.map(seg => {
|
|
28508
|
-
if (!seg)
|
|
28509
|
-
return '';
|
|
28510
|
-
try {
|
|
28511
|
-
return encodeURIComponent(decodeURIComponent(seg));
|
|
28512
|
-
}
|
|
28513
|
-
catch (_a) {
|
|
28514
|
-
return encodeURIComponent(seg);
|
|
28515
|
-
}
|
|
28516
|
-
})
|
|
28517
|
-
.join('/');
|
|
28518
|
-
const result = url.startsWith('/') ? pathEncoded + (parsed.search || '') + (parsed.hash || '') : `${origin}${pathEncoded}${parsed.search}${parsed.hash}`;
|
|
28519
|
-
return result;
|
|
28520
|
-
}
|
|
28521
|
-
}
|
|
28522
|
-
catch (_a) {
|
|
28523
|
-
// если парсинг не удался, возвращаем как есть
|
|
28524
|
-
}
|
|
28525
|
-
return url;
|
|
28526
|
-
};
|
|
28527
|
-
/**
|
|
28528
|
-
* @deprecated Эта функция оставлена только для обратной совместимости.
|
|
28529
|
-
* Используйте {@link normalizeFileName} из `nameNormalization.ts` для настраиваемой нормализации имен файлов.
|
|
28530
|
-
*
|
|
28531
|
-
* Упрощенная санитизация имени файла:
|
|
28532
|
-
* - Заменяет запрещенные символы на `_`
|
|
28533
|
-
* - Заменяет пробелы на `_`
|
|
28534
|
-
* - Удаляет множественные подчеркивания
|
|
28535
|
-
* - Ограничивает длину до 255 символов
|
|
28536
|
-
*/
|
|
28537
|
-
const sanitizeFileName = (fileName) => {
|
|
28538
|
-
return fileName
|
|
28539
|
-
.replace(/[<>:"/\\|?*()#]/g, '_')
|
|
28540
|
-
.split('')
|
|
28541
|
-
.map(char => {
|
|
28542
|
-
const code = char.charCodeAt(0);
|
|
28543
|
-
return code >= 0 && code <= 31 ? '_' : char;
|
|
28544
|
-
})
|
|
28545
|
-
.join('')
|
|
28546
|
-
.replace(/\s+/g, '_')
|
|
28547
|
-
.replace(/_{2,}/g, '_')
|
|
28548
|
-
.substring(0, 255);
|
|
28549
|
-
};
|
|
28550
|
-
|
|
28551
|
-
|
|
28552
|
-
/***/ }),
|
|
28553
|
-
|
|
28554
|
-
/***/ 9287:
|
|
28555
|
-
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
28556
|
-
|
|
28557
|
-
// Imports
|
|
28558
|
-
var ___CSS_LOADER_API_SOURCEMAP_IMPORT___ = __webpack_require__(1354);
|
|
28559
|
-
var ___CSS_LOADER_API_IMPORT___ = __webpack_require__(6314);
|
|
28560
|
-
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);
|
|
28561
|
-
// Module
|
|
28562
|
-
___CSS_LOADER_EXPORT___.push([module.id, `.FolderSidebar-module__button__Yf2rX.ant-btn.ant-btn-icon-only{padding:calc(var(--paddingXXS)*1px) calc(var(--paddingSM)*1px);cursor:pointer;color:var(--colorTextSecondary);display:flex;gap:calc(var(--marginXS)*1px);align-items:center;justify-content:center;border-radius:calc(var(--borderRadiusSM)*1px);transition:all var(--motionDurationFast);box-shadow:none;border:none;width:32px;height:32px}.FolderSidebar-module__button__Yf2rX.ant-btn.ant-btn-icon-only:hover{background-color:var(--colorBgLayout);color:inherit}.FolderSidebar-module__button__Yf2rX:hover{background-color:var(--colorBgContainer);color:var(--colorPrimary)}.FolderSidebar-module__foldersTitle__Uh6u7{display:flex;align-items:center;flex:1;cursor:pointer}.FolderSidebar-module__folderActions__qA2Bk{position:absolute;top:4px;right:4px;display:flex;align-items:center;gap:4px;z-index:10}.FolderSidebar-module__folderActions__qA2Bk .FolderSidebar-module__button__Yf2rX.FolderSidebar-module__ant-btn__LXAXm.FolderSidebar-module__ant-btn-icon-only__j_wVF{padding:calc(var(--paddingXXS)*1px) calc(var(--paddingSM)*1px);cursor:pointer;color:var(--colorTextSecondary);display:flex;gap:calc(var(--marginXS)*1px);align-items:center;justify-content:center;border-radius:calc(var(--borderRadiusSM)*1px);transition:all var(--motionDurationFast);box-shadow:none;border:none;width:32px;height:32px}.FolderSidebar-module__folderActions__qA2Bk .FolderSidebar-module__button__Yf2rX.FolderSidebar-module__ant-btn__LXAXm.FolderSidebar-module__ant-btn-icon-only__j_wVF:hover{background-color:var(--colorBgLayout);color:inherit}.FolderSidebar-module__customExpandIcon__IhZJl{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;margin-right:8px;cursor:pointer;color:#666;font-size:10px;transition:transform .2s ease}.FolderSidebar-module__customExpandIcon__IhZJl:hover{color:var(--colorPrimary)}.FolderSidebar-module__fileCount__bD9DD{display:inline-flex;align-items:center;justify-content:center;min-width:20px;height:100%;padding:0 6px;margin-left:8px;color:#8d8d8d;font-size:14px;font-weight:500;transition:all .2s ease;white-space:nowrap;cursor:default;flex-shrink:0;margin-right:10px}.ant-tree .ant-tree-node-content-wrapper.ant-tree-node-selected{background-color:rgba(0,0,0,0) !important}.FolderSidebar-module__folderMenu__JCzLF .ant-tree-treenode-selected .folder-label span,.FolderSidebar-module__folderMenu__JCzLF .ant-tree .ant-tree-node-content-wrapper.ant-tree-node-selected .folderLabelItem,.FolderSidebar-module__folderMenu__JCzLF .ant-tree-treenode-selected .folderLabelItem,.FolderSidebar-module__folderMenu__JCzLF .ant-tree-node-selected .folderLabelItem{font-weight:600 !important}.FolderSidebar-module__uploadButton__QQUid{width:100%;justify-content:flex-start}.FolderSidebar-module__uploadButton__QQUid button:hover{background-color:var(--colorPrimaryHover) !important}.FolderSidebar-module__folderMenu__JCzLF{padding-left:0;padding-right:0}.FolderSidebar-module__folderMenu__JCzLF .ant-tree-treenode{display:flex;align-items:center;justify-content:space-between;padding:4px 0;border-radius:4px;transition:background-color .2s ease;width:100%;margin-bottom:0}.FolderSidebar-module__folderMenu__JCzLF .ant-tree-node-content-wrapper{flex:1;align-items:center;padding:0;transition:background-color .2s ease}.FolderSidebar-module__folderMenu__JCzLF .ant-tree-node-content-wrapper:hover{background-color:rgba(0,0,0,0)}.FolderSidebar-module__folderMenu__JCzLF .ant-tree-switcher{height:24px;width:24px;margin-top:5px;display:flex !important;align-items:center;justify-content:center;transition:color .2s ease;flex-shrink:0}.FolderSidebar-module__folderMenu__JCzLF .ant-tree-switcher-noop{width:24px}.FolderSidebar-module__folderMenu__JCzLF .ant-tree-switcher-line-icon{color:#d9d9d9}.FolderSidebar-module__folderMenu__JCzLF .FolderSidebar-module__folderItemContainer__byl5b{width:100%;display:flex;align-items:center;justify-content:space-between;padding:2px 0;min-width:0}.FolderSidebar-module__folderMenu__JCzLF .folder-label{display:flex;align-items:center;flex:1;color:#595959;font-size:14px;min-width:0;overflow:hidden}.FolderSidebar-module__folderMenu__JCzLF .ant-tree-treenode[data-key="folders"]{border-bottom:1px solid var(--colorBorderSecondary);margin-bottom:8px;padding-bottom:8px}.FolderSidebar-module__folderMenu__JCzLF .ant-tree-treenode[data-key="folders"].ant-tree-treenode-selected{background-color:rgba(0,0,0,0) !important}.FolderSidebar-module__folderMenu__JCzLF .ant-tree-treenode[data-key="folders"] .ant-tree-node-content-wrapper{padding:0}.FolderSidebar-module__folderMenu__JCzLF .ant-tree-treenode[data-key="folders"] .ant-tree-node-content-wrapper:hover{background-color:rgba(0,0,0,0) !important}.FolderSidebar-module__folderMenu__JCzLF .ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0}.FolderSidebar-module__folderMenu__JCzLF .FolderSidebar-module__emptyFolderContainer__WK6tx{padding:20px;text-align:center}.FolderSidebar-module__folderMenu__JCzLF .ant-tree > .ant-tree-treenode{padding-left:0 !important}.FolderSidebar-module__folderIcon__UoZzH{margin-right:8px;font-size:18px;flex-shrink:0}.FolderSidebar-module__folderLabelItem__uJ062{font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1;min-width:0;user-select:none}.FolderSidebar-module__foldersTitleItem__gapOI{display:flex;align-items:center;flex:1;cursor:pointer;min-width:0;overflow:hidden}.FolderSidebar-module__folderLabel__fHWMp{display:flex;align-items:center;flex:1;min-width:0;overflow:hidden}.FolderSidebar-module__foldersContainer__zdBVU{position:relative;width:100%}.FolderSidebar-module__uploadButton__QQUid .FolderSidebar-module__ant-btn__LXAXm,.FolderSidebar-module__uploadButton__QQUid .ant-btn{display:flex;align-items:center;justify-content:center;gap:3px}.FolderSidebar-module__buttonWrapper__a9Qi5{margin-bottom:24px;display:flex;gap:4px}.FolderSidebar-module__buttonWrapper__a9Qi5>:first-child{flex:1;height:40px;padding-left:10px}.FolderSidebar-module__buttonWrapper__a9Qi5>:last-child{width:40px;height:40px;flex-shrink:0}.FolderSidebar-module__uploadButtonIcon__mWQmq{font-size:20px}.FolderSidebar-module__uploadButtonTitle__wk_o6{line-height:1em}.FolderSidebar-module__emptyFolderContainer__WK6tx{user-select:none;cursor:default;color:var(--colorTextTertiary)}.FolderSidebar-module__folderItemContainer__byl5b{width:100%;display:flex;align-items:center;justify-content:space-between;padding:2px 0;min-width:0}`, "",{"version":3,"sources":["webpack://./src/components/FolderSidebar/FolderSidebar.module.scss"],"names":[],"mappings":"AAAA,+DACI,8DAAA,CACA,cAAA,CACA,+BAAA,CACA,YAAA,CACA,6BAAA,CACA,kBAAA,CACA,sBAAA,CACA,6CAAA,CACA,wCAAA,CACA,eAAA,CAEA,WAAA,CACA,UAAA,CACA,WAAA,CAEA,qEACI,qCAAA,CACA,aAAA,CAIR,2CACI,wCAAA,CACA,yBAAA,CAGJ,2CACE,YAAA,CACA,kBAAA,CACA,MAAA,CACA,cAAA,CAGF,4CACI,iBAAA,CACA,OAAA,CACA,SAAA,CACA,YAAA,CACA,kBAAA,CACA,OAAA,CACA,UAAA,CAEA,qKACE,8DAAA,CACA,cAAA,CACA,+BAAA,CACA,YAAA,CACA,6BAAA,CACA,kBAAA,CACA,sBAAA,CACA,6CAAA,CACA,wCAAA,CACA,eAAA,CAEA,WAAA,CACA,UAAA,CACA,WAAA,CAEA,2KACI,qCAAA,CACA,aAAA,CAKV,+CACE,mBAAA,CACA,kBAAA,CACA,sBAAA,CACA,UAAA,CACA,WAAA,CACA,gBAAA,CACA,cAAA,CACA,UAAA,CACA,cAAA,CACA,6BAAA,CAGF,qDACI,yBAAA,CAGJ,wCACE,mBAAA,CACA,kBAAA,CACA,sBAAA,CACA,cAAA,CACE,WAAA,CACF,aAAA,CACA,eAAA,CACE,aAAA,CACA,cAAA,CACF,eAAA,CACA,uBAAA,CACA,kBAAA,CACA,cAAA,CACA,aAAA,CACA,iBAAA,CAQF,gEACE,yCAAA,CAQF,0XAIE,0BAAA,CAWF,2CACI,UAAA,CACA,0BAAA,CAEA,wDACE,oDAAA,CAIN,yCACE,cAAA,CACA,eAAA,CAGF,4DACE,YAAA,CACA,kBAAA,CACA,6BAAA,CACA,aAAA,CACA,iBAAA,CACA,oCAAA,CACA,UAAA,CACA,eAAA,CAGF,wEACE,MAAA,CAEA,kBAAA,CACA,SAAA,CAEA,oCAAA,CAGF,8EACE,8BAAA,CAGF,4DACE,WAAA,CACA,UAAA,CACA,cAAA,CACA,uBAAA,CACA,kBAAA,CACA,sBAAA,CACA,yBAAA,CACA,aAAA,CAGF,iEACE,UAAA,CAIF,sEACE,aAAA,CAIF,2FACE,UAAA,CACA,YAAA,CACA,kBAAA,CACA,6BAAA,CACA,aAAA,CACA,WAAA,CAGF,uDACE,YAAA,CACA,kBAAA,CACA,MAAA,CACA,aAAA,CACA,cAAA,CACA,WAAA,CACA,eAAA,CAIF,gFACI,mDAAA,CACF,iBAAA,CACA,kBAAA,CAGF,2GACE,yCAAA,CAGF,+GACE,SAAA,CAGF,qHACE,yCAAA,CAIF,mDACE,eAAA,CACA,sBAAA,CACA,kBAAA,CACA,MAAA,CACA,WAAA,CAIF,4FACE,YAAA,CACA,iBAAA,CAIF,wEACE,yBAAA,CAEF,yCACE,gBAAA,CACE,cAAA,CACF,aAAA,CAGF,8CACE,cAAA,CACA,kBAAA,CACA,eAAA,CACA,sBAAA,CACA,MAAA,CACA,WAAA,CACA,gBAAA,CAGF,+CACE,YAAA,CACA,kBAAA,CACA,MAAA,CACA,cAAA,CACA,WAAA,CACA,eAAA,CASF,0CACE,YAAA,CACA,kBAAA,CACA,MAAA,CACA,WAAA,CACA,eAAA,CAGF,+CACE,iBAAA,CACA,UAAA,CAWF,qIAEE,YAAA,CACA,kBAAA,CACA,sBAAA,CACA,OAAA,CAaF,4CAEI,kBAAA,CACA,YAAA,CACA,OAAA,CAIA,yDACI,MAAA,CACA,WAAA,CACA,iBAAA,CAIJ,wDACI,UAAA,CACA,WAAA,CACA,aAAA,CAIR,+CACI,cAAA,CAGJ,gDACI,eAAA,CAGJ,mDACI,gBAAA,CACA,cAAA,CACA,8BAAA,CAGJ,kDACI,UAAA,CACA,YAAA,CACA,kBAAA,CACA,6BAAA,CACA,aAAA,CACA,WAAA","sourcesContent":[".button:global(.ant-btn.ant-btn-icon-only) {\r\n padding: calc(var(--paddingXXS) * 1px) calc(var(--paddingSM) * 1px);\r\n cursor: pointer;\r\n color: var(--colorTextSecondary);\r\n display: flex;\r\n gap: calc(var(--marginXS) * 1px);\r\n align-items: center;\r\n justify-content: center;\r\n border-radius: calc(var(--borderRadiusSM) * 1px);\r\n transition: all var(--motionDurationFast);\r\n box-shadow: none;\r\n\r\n border: none;\r\n width: 32px;\r\n height: 32px;\r\n\r\n &:hover {\r\n background-color: var(--colorBgLayout);\r\n color: inherit;\r\n }\r\n}\r\n\r\n.button:hover {\r\n background-color: var(--colorBgContainer);\r\n color: var(--colorPrimary);\r\n}\r\n\r\n.foldersTitle {\r\n display: flex;\r\n align-items: center;\r\n flex: 1;\r\n cursor: pointer;\r\n}\r\n\r\n.folderActions {\r\n position: absolute;\r\n top: 4px; /* Выравниваем по заголовку Folders */\r\n right: 4px;\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n z-index: 10;\r\n\r\n .button.ant-btn.ant-btn-icon-only {\r\n padding: calc(var(--paddingXXS) * 1px) calc(var(--paddingSM) * 1px);\r\n cursor: pointer;\r\n color: var(--colorTextSecondary);\r\n display: flex;\r\n gap: calc(var(--marginXS) * 1px);\r\n align-items: center;\r\n justify-content: center;\r\n border-radius: calc(var(--borderRadiusSM) * 1px);\r\n transition: all var(--motionDurationFast);\r\n box-shadow: none;\r\n\r\n border: none;\r\n width: 32px;\r\n height: 32px;\r\n\r\n &:hover {\r\n background-color: var(--colorBgLayout);\r\n color: inherit;\r\n }\r\n }\r\n}\r\n\r\n.customExpandIcon {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 16px;\r\n height: 16px;\r\n margin-right: 8px;\r\n cursor: pointer;\r\n color: #666;\r\n font-size: 10px;\r\n transition: transform 0.2s ease;\r\n}\r\n\r\n.customExpandIcon:hover {\r\n color: var(--colorPrimary);\r\n}\r\n\r\n.fileCount {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n min-width: 20px;\r\n height: 100%;\r\n padding: 0 6px;\r\n margin-left: 8px;\r\n color: #8D8D8D;\r\n font-size: 14px;\r\n font-weight: 500;\r\n transition: all 0.2s ease;\r\n white-space: nowrap;\r\n cursor: default;\r\n flex-shrink: 0; /* Запрещаем сжатие счетчика */\r\n margin-right: 10px;\r\n}\r\n\r\n// .fileCount:hover {\r\n// border-color: var(--colorPrimary);\r\n// color: var(--colorPrimary);\r\n// }\r\n\r\n:global(.ant-tree .ant-tree-node-content-wrapper.ant-tree-node-selected) {\r\n background-color: transparent !important;\r\n}\r\n\r\n/* :global(.ant-tree .ant-tree-node-content-wrapper.ant-tree-node-selected):hover {\r\n color: red !important;\r\n} */\r\n\r\n/* Стили для выделения текста в выбранной папке */\r\n.folderMenu :global(.ant-tree-treenode-selected .folder-label span),\r\n.folderMenu :global(.ant-tree .ant-tree-node-content-wrapper.ant-tree-node-selected .folderLabelItem),\r\n.folderMenu :global(.ant-tree-treenode-selected .folderLabelItem),\r\n.folderMenu :global(.ant-tree-node-selected .folderLabelItem) {\r\n font-weight: 600 !important;\r\n}\r\n\r\n/* Стили для иконки в выбранной папке */\r\n/* .folderMenu :global(.ant-tree-treenode-selected .folderIcon),\r\n.folderMenu :global(.ant-tree-node-selected .folderIcon) {\r\n color: red !important;\r\n} */\r\n\r\n/* CSS переменные для упрощения расчетов */\r\n\r\n.uploadButton {\r\n width: 100%;\r\n justify-content: flex-start;\r\n\r\n & button:hover {\r\n background-color: var(--colorPrimaryHover) !important;\r\n }\r\n}\r\n\r\n.folderMenu {\r\n padding-left: 0;\r\n padding-right: 0; /* Место для кнопки справа */\r\n}\r\n\r\n.folderMenu :global(.ant-tree-treenode) {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 4px 0;\r\n border-radius: 4px;\r\n transition: background-color 0.2s ease;\r\n width: 100%;\r\n margin-bottom: 0;\r\n}\r\n\r\n.folderMenu :global(.ant-tree-node-content-wrapper) {\r\n flex: 1;\r\n /* display: flex; */\r\n align-items: center;\r\n padding: 0;\r\n /* border-radius: 4px; */\r\n transition: background-color 0.2s ease;\r\n}\r\n\r\n.folderMenu :global(.ant-tree-node-content-wrapper:hover) {\r\n background-color: transparent;\r\n}\r\n\r\n.folderMenu :global(.ant-tree-switcher) {\r\n height: 24px;\r\n width: 24px;\r\n margin-top: 5px;\r\n display: flex !important;\r\n align-items: center;\r\n justify-content: center;\r\n transition: color 0.2s ease;\r\n flex-shrink: 0; /* Запрещаем сжатие переключателя */\r\n}\r\n\r\n.folderMenu :global(.ant-tree-switcher-noop) {\r\n width: 24px;\r\n}\r\n\r\n/* Стили для линий дерева */\r\n.folderMenu :global(.ant-tree-switcher-line-icon) {\r\n color: #d9d9d9;\r\n}\r\n\r\n/* Улучшение отображения folder-item-container */\r\n.folderMenu .folderItemContainer {\r\n width: 100%;\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 2px 0;\r\n min-width: 0; /* Позволяет flex-элементам сжиматься */\r\n}\r\n\r\n.folderMenu :global(.folder-label) {\r\n display: flex;\r\n align-items: center;\r\n flex: 1;\r\n color: #595959;\r\n font-size: 14px;\r\n min-width: 0;\r\n overflow: hidden;\r\n}\r\n\r\n/* Стили для корневого элемента Folders */\r\n.folderMenu :global(.ant-tree-treenode[data-key='folders']) {\r\n border-bottom: 1px solid var(--colorBorderSecondary);\r\n margin-bottom: 8px;\r\n padding-bottom: 8px;\r\n}\r\n\r\n.folderMenu :global(.ant-tree-treenode[data-key='folders'].ant-tree-treenode-selected) {\r\n background-color: transparent !important;\r\n}\r\n\r\n.folderMenu :global(.ant-tree-treenode[data-key='folders'] .ant-tree-node-content-wrapper) {\r\n padding: 0;\r\n}\r\n\r\n.folderMenu :global(.ant-tree-treenode[data-key='folders'] .ant-tree-node-content-wrapper:hover) {\r\n background-color: transparent !important;\r\n}\r\n\r\n/* Стили для ellipsis - удаляем max-width для гибкости */\r\n.folderMenu :global(.ellipsis) {\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n flex: 1;\r\n min-width: 0;\r\n}\r\n\r\n/* Стили для пустого состояния */\r\n.folderMenu .emptyFolderContainer {\r\n padding: 20px;\r\n text-align: center;\r\n}\r\n\r\n/* Убираем отступы у корневого узла */\r\n.folderMenu :global(.ant-tree > .ant-tree-treenode) {\r\n padding-left: 0 !important;\r\n}\r\n.folderIcon {\r\n margin-right: 8px;\r\n font-size: 18px;\r\n flex-shrink: 0; /* Запрещаем сжатие иконки */\r\n}\r\n\r\n.folderLabelItem {\r\n font-size: 14px;\r\n white-space: nowrap; /* Запрещаем перенос строк */\r\n overflow: hidden; /* Скрываем переполнение */\r\n text-overflow: ellipsis; /* Показываем троеточие */\r\n flex: 1; /* Занимает доступное место */\r\n min-width: 0; /* Позволяет сжиматься */\r\n user-select: none;\r\n}\r\n\r\n.foldersTitleItem {\r\n display: flex;\r\n align-items: center;\r\n flex: 1;\r\n cursor: pointer;\r\n min-width: 0; /* Позволяет сжиматься */\r\n overflow: hidden; /* Скрываем переполнение */\r\n}\r\n\r\n/* .foldersTitleItem .folderLabelItem {\r\n font-weight: 500;\r\n color: #262626;\r\n} */\r\n\r\n/* Класс для заголовка папок */\r\n.folderLabel {\r\n display: flex;\r\n align-items: center;\r\n flex: 1;\r\n min-width: 0;\r\n overflow: hidden;\r\n}\r\n\r\n.foldersContainer {\r\n position: relative;\r\n width: 100%;\r\n}\r\n\r\n/* Дополнительные стили для улучшения визуала */\r\n/* .folderMenu :global(.ant-tree-treenode:hover .folder-label span) {\r\n color: #1890ff;\r\n} */\r\n\r\n/* Стили для дивайдера между папками */\r\n\r\n\r\n.uploadButton .ant-btn,\r\n.uploadButton :global(.ant-btn) {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 3px;\r\n}\r\n/* .folderMenu :global(.ant-tree-treenode-selected) .folderLabelItem {\r\n color: #1890ff !important;\r\n} */\r\n\r\n// .folderMenu :global(.ant-tree-treenode-selected) .folderLabel .folderLabelItem,\r\n// .folderMenu :global(.ant-tree-treenode-selected) .folderLabel .folderIcon,\r\n// .folderMenu :global(.ant-tree-treenode-selected) .folderLabelItem {\r\n// color: var(--colorLink);\r\n// }\r\n\r\n\r\n.buttonWrapper {\r\n // overflow: hidden;\r\n margin-bottom: 24px;\r\n display: flex;\r\n gap: 4px;\r\n // border-radius: calc(var(--borderRadius) * 1px);\r\n \r\n // Левая кнопка занимает всю доступную ширину\r\n > :first-child {\r\n flex: 1;\r\n height: 40px;\r\n padding-left: 10px;\r\n }\r\n \r\n // Правая кнопка строго 40px\r\n > :last-child {\r\n width: 40px;\r\n height: 40px;\r\n flex-shrink: 0;\r\n }\r\n}\r\n\r\n.uploadButtonIcon {\r\n font-size: 20px;\r\n}\r\n\r\n.uploadButtonTitle {\r\n line-height: 1em;\r\n}\r\n\r\n.emptyFolderContainer {\r\n user-select: none;\r\n cursor: default;\r\n color: var(--colorTextTertiary);\r\n}\r\n\r\n.folderItemContainer {\r\n width: 100%;\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 2px 0;\r\n min-width: 0; /* Позволяет flex-элементам сжиматься */\r\n}\r\n"],"sourceRoot":""}]);
|
|
28563
|
-
// Exports
|
|
28564
|
-
___CSS_LOADER_EXPORT___.locals = {
|
|
28565
|
-
"button": `FolderSidebar-module__button__Yf2rX`,
|
|
28566
|
-
"foldersTitle": `FolderSidebar-module__foldersTitle__Uh6u7`,
|
|
28567
|
-
"folderActions": `FolderSidebar-module__folderActions__qA2Bk`,
|
|
28568
|
-
"ant-btn": `FolderSidebar-module__ant-btn__LXAXm`,
|
|
28569
|
-
"antBtn": `FolderSidebar-module__ant-btn__LXAXm`,
|
|
28570
|
-
"ant-btn-icon-only": `FolderSidebar-module__ant-btn-icon-only__j_wVF`,
|
|
28571
|
-
"antBtnIconOnly": `FolderSidebar-module__ant-btn-icon-only__j_wVF`,
|
|
28572
|
-
"customExpandIcon": `FolderSidebar-module__customExpandIcon__IhZJl`,
|
|
28573
|
-
"fileCount": `FolderSidebar-module__fileCount__bD9DD`,
|
|
28574
|
-
"folderMenu": `FolderSidebar-module__folderMenu__JCzLF`,
|
|
28575
|
-
"uploadButton": `FolderSidebar-module__uploadButton__QQUid`,
|
|
28576
|
-
"folderItemContainer": `FolderSidebar-module__folderItemContainer__byl5b`,
|
|
28577
|
-
"emptyFolderContainer": `FolderSidebar-module__emptyFolderContainer__WK6tx`,
|
|
28578
|
-
"folderIcon": `FolderSidebar-module__folderIcon__UoZzH`,
|
|
28579
|
-
"folderLabelItem": `FolderSidebar-module__folderLabelItem__uJ062`,
|
|
28580
|
-
"foldersTitleItem": `FolderSidebar-module__foldersTitleItem__gapOI`,
|
|
28581
|
-
"folderLabel": `FolderSidebar-module__folderLabel__fHWMp`,
|
|
28582
|
-
"foldersContainer": `FolderSidebar-module__foldersContainer__zdBVU`,
|
|
28583
|
-
"buttonWrapper": `FolderSidebar-module__buttonWrapper__a9Qi5`,
|
|
28584
|
-
"uploadButtonIcon": `FolderSidebar-module__uploadButtonIcon__mWQmq`,
|
|
28585
|
-
"uploadButtonTitle": `FolderSidebar-module__uploadButtonTitle__wk_o6`
|
|
28586
|
-
};
|
|
28587
|
-
module.exports = ___CSS_LOADER_EXPORT___;
|
|
28588
|
-
|
|
28589
|
-
|
|
28590
|
-
/***/ }),
|
|
28591
|
-
|
|
28592
|
-
/***/ 9557:
|
|
28285
|
+
/***/ 8573:
|
|
28593
28286
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
28594
28287
|
|
|
28595
28288
|
"use strict";
|
|
@@ -28735,6 +28428,27 @@ var dedupeUploadNamesOnClient = __webpack_require__(3795);
|
|
|
28735
28428
|
var utils_resolveUniqueUploadName = __webpack_require__(7742);
|
|
28736
28429
|
// EXTERNAL MODULE: ./src/utils/fileFormatUtils.ts
|
|
28737
28430
|
var fileFormatUtils = __webpack_require__(6825);
|
|
28431
|
+
;// ./src/utils/mapWithConcurrency.ts
|
|
28432
|
+
async function mapWithConcurrency(items, limit, fn) {
|
|
28433
|
+
if (items.length === 0) {
|
|
28434
|
+
return [];
|
|
28435
|
+
}
|
|
28436
|
+
const results = new Array(items.length);
|
|
28437
|
+
let nextIndex = 0;
|
|
28438
|
+
const poolSize = Math.max(1, Math.min(limit, items.length));
|
|
28439
|
+
const worker = async () => {
|
|
28440
|
+
while (true) {
|
|
28441
|
+
const currentIndex = nextIndex++;
|
|
28442
|
+
if (currentIndex >= items.length) {
|
|
28443
|
+
return;
|
|
28444
|
+
}
|
|
28445
|
+
results[currentIndex] = await fn(items[currentIndex], currentIndex);
|
|
28446
|
+
}
|
|
28447
|
+
};
|
|
28448
|
+
await Promise.all(Array.from({ length: poolSize }, () => worker()));
|
|
28449
|
+
return results;
|
|
28450
|
+
}
|
|
28451
|
+
|
|
28738
28452
|
// EXTERNAL MODULE: ./src/hooks/core/context.tsx
|
|
28739
28453
|
var context = __webpack_require__(8361);
|
|
28740
28454
|
// EXTERNAL MODULE: ./src/constants/index.tsx
|
|
@@ -28766,6 +28480,8 @@ var fileManagerApiError = __webpack_require__(7036);
|
|
|
28766
28480
|
|
|
28767
28481
|
|
|
28768
28482
|
|
|
28483
|
+
|
|
28484
|
+
const UPLOAD_IMAGE_PREPARE_CONCURRENCY = 4;
|
|
28769
28485
|
/**
|
|
28770
28486
|
* Проверяет, нужно ли сжимать изображение
|
|
28771
28487
|
*/
|
|
@@ -29674,7 +29390,7 @@ const useFilesAPI = () => {
|
|
|
29674
29390
|
}
|
|
29675
29391
|
}, [resolveTargetFolderId]);
|
|
29676
29392
|
const uploadFilesBatch = (0,external_root_React_commonjs2_react_commonjs_react_amd_react_.useCallback)(async (filesToUpload, progressCallbacks) => {
|
|
29677
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0
|
|
29393
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0;
|
|
29678
29394
|
if (filesToUpload.length === 0) {
|
|
29679
29395
|
return { successCount: 0, failCount: 0, successes: [], errors: [], totalCount: 0 };
|
|
29680
29396
|
}
|
|
@@ -29684,9 +29400,8 @@ const useFilesAPI = () => {
|
|
|
29684
29400
|
const filtered = names.filter(Boolean);
|
|
29685
29401
|
return filtered.length > 0 && filtered.length <= MAX_NAMES_PREVIEW ? filtered.join(', ') : null;
|
|
29686
29402
|
};
|
|
29687
|
-
const
|
|
29688
|
-
|
|
29689
|
-
const file = filesToUpload[index];
|
|
29403
|
+
const preparedResults = await mapWithConcurrency(filesToUpload, UPLOAD_IMAGE_PREPARE_CONCURRENCY, async (file, index) => {
|
|
29404
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
29690
29405
|
if (!(0,mimeUtils/* isAllowedImageUploadFile */.rc)(file)) {
|
|
29691
29406
|
const payload = await notification.warning({
|
|
29692
29407
|
id: 'FILES_UPLOAD_UNSUPPORTED_TYPE',
|
|
@@ -29698,8 +29413,8 @@ const useFilesAPI = () => {
|
|
|
29698
29413
|
folderId: selectedFolder || null,
|
|
29699
29414
|
},
|
|
29700
29415
|
});
|
|
29701
|
-
(
|
|
29702
|
-
|
|
29416
|
+
(_a = progressCallbacks === null || progressCallbacks === void 0 ? void 0 : progressCallbacks.onError) === null || _a === void 0 ? void 0 : _a.call(progressCallbacks, file.name, payload.message);
|
|
29417
|
+
return null;
|
|
29703
29418
|
}
|
|
29704
29419
|
// Нормализуем имя файла заранее для подготовки изображения и fallback
|
|
29705
29420
|
const normalizedFileName = (0,nameNormalization/* normalizeFileName */.Px)(file.name, options === null || options === void 0 ? void 0 : options.config);
|
|
@@ -29707,24 +29422,19 @@ const useFilesAPI = () => {
|
|
|
29707
29422
|
// eslint-disable-next-line sonarjs/no-dead-store
|
|
29708
29423
|
let fileToUpload = file;
|
|
29709
29424
|
try {
|
|
29710
|
-
|
|
29711
|
-
|
|
29712
|
-
|
|
29713
|
-
|
|
29714
|
-
|
|
29715
|
-
|
|
29716
|
-
|
|
29717
|
-
|
|
29718
|
-
|
|
29719
|
-
|
|
29720
|
-
|
|
29721
|
-
|
|
29722
|
-
|
|
29723
|
-
});
|
|
29724
|
-
}
|
|
29725
|
-
else {
|
|
29726
|
-
fileToUpload = createNormalizedFile(file, normalizedFileName);
|
|
29727
|
-
}
|
|
29425
|
+
const maxSizeMB = (_c = (_b = options === null || options === void 0 ? void 0 : options.config) === null || _b === void 0 ? void 0 : _b.compressMaxSize) !== null && _c !== void 0 ? _c : fileFormatUtils/* IMAGE_COMPRESSION_DEFAULTS */.a9.MAX_SIZE_MB;
|
|
29426
|
+
const maxWidthOrHeight = (_e = (_d = options === null || options === void 0 ? void 0 : options.config) === null || _d === void 0 ? void 0 : _d.compressMaxWidthOrHeight) !== null && _e !== void 0 ? _e : 2000;
|
|
29427
|
+
const compressorUrl = (_g = (_f = options === null || options === void 0 ? void 0 : options.config) === null || _f === void 0 ? void 0 : _f.compessorUrl) !== null && _g !== void 0 ? _g : (_h = options === null || options === void 0 ? void 0 : options.config) === null || _h === void 0 ? void 0 : _h.compressorUrl;
|
|
29428
|
+
const effectiveMime = ((_j = file.type) === null || _j === void 0 ? void 0 : _j.trim()) || (0,mimeUtils/* inferImageMimeFromFileName */.xU)(file.name) || file.type;
|
|
29429
|
+
fileToUpload = await (0,imageCompression/* prepareImageForUpload */.j)(file, {
|
|
29430
|
+
maxSizeMB,
|
|
29431
|
+
maxWidthOrHeight,
|
|
29432
|
+
mimeType: effectiveMime,
|
|
29433
|
+
fileName: normalizedFileName,
|
|
29434
|
+
libURL: compressorUrl,
|
|
29435
|
+
enableCompression: shouldCompressImage(effectiveMime),
|
|
29436
|
+
convertSvgToPng: true,
|
|
29437
|
+
});
|
|
29728
29438
|
}
|
|
29729
29439
|
catch (e) {
|
|
29730
29440
|
console.warn('Image preparation failed, uploading original file', e);
|
|
@@ -29735,15 +29445,16 @@ const useFilesAPI = () => {
|
|
|
29735
29445
|
// тогда результат будет сопоставлен по индексу массива.
|
|
29736
29446
|
const requestId = `${Date.now()}-${index}-${Math.random().toString(36).slice(2, 8)}`;
|
|
29737
29447
|
const targetFolderId = await resolveTargetFolderId(fileToUpload, selectedFolder);
|
|
29738
|
-
(
|
|
29739
|
-
|
|
29448
|
+
(_k = progressCallbacks === null || progressCallbacks === void 0 ? void 0 : progressCallbacks.onStart) === null || _k === void 0 ? void 0 : _k.call(progressCallbacks, fileToUpload);
|
|
29449
|
+
return {
|
|
29740
29450
|
file: fileToUpload,
|
|
29741
29451
|
targetFolderId,
|
|
29742
29452
|
requestId,
|
|
29743
29453
|
originalFileName: file.name,
|
|
29744
29454
|
originalIndex: index,
|
|
29745
|
-
}
|
|
29746
|
-
}
|
|
29455
|
+
};
|
|
29456
|
+
});
|
|
29457
|
+
const preparedItems = preparedResults.filter((item) => item !== null);
|
|
29747
29458
|
const totalCount = preparedItems.length;
|
|
29748
29459
|
if (totalCount === 0) {
|
|
29749
29460
|
return { successCount: 0, failCount: 0, successes: [], errors: [], totalCount: 0 };
|
|
@@ -29825,7 +29536,7 @@ const useFilesAPI = () => {
|
|
|
29825
29536
|
},
|
|
29826
29537
|
}, silent || !shouldEmitAnyNotifications);
|
|
29827
29538
|
};
|
|
29828
|
-
const maxFileSize = (
|
|
29539
|
+
const maxFileSize = (_c = (_b = options === null || options === void 0 ? void 0 : options.config) === null || _b === void 0 ? void 0 : _b.maxFileSize) !== null && _c !== void 0 ? _c : fileValidation/* MAX_FILE_SIZE */.w3;
|
|
29829
29540
|
const emitErrorNotification = (fileName, folderId, innerException, silent, context) => {
|
|
29830
29541
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
29831
29542
|
const apiError = (0,errorMessages/* asFileManagerApiError */.sj)(innerException);
|
|
@@ -29929,17 +29640,17 @@ const useFilesAPI = () => {
|
|
|
29929
29640
|
});
|
|
29930
29641
|
progressIntervals.forEach(id => window.clearInterval(id));
|
|
29931
29642
|
progressIntervals.length = 0;
|
|
29932
|
-
const detailedList = (
|
|
29643
|
+
const detailedList = (_d = batchResult.detailed) !== null && _d !== void 0 ? _d : [];
|
|
29933
29644
|
const detailedMap = new Map(detailedList.filter(detail => detail.requestId).map(detail => [detail.requestId, detail]));
|
|
29934
29645
|
if (detailedList.length > 0) {
|
|
29935
29646
|
for (let index = 0; index < uploadItems.length; index++) {
|
|
29936
29647
|
const item = uploadItems[index];
|
|
29937
29648
|
// Пытаемся сопоставить по requestId, а при его отсутствии — по порядку.
|
|
29938
|
-
const detail = (
|
|
29649
|
+
const detail = (_e = (item.requestId ? detailedMap.get(item.requestId) : undefined)) !== null && _e !== void 0 ? _e : detailedList[index];
|
|
29939
29650
|
if (detail && detail.success) {
|
|
29940
29651
|
const data = detail.data;
|
|
29941
|
-
const normalizedFileName = (
|
|
29942
|
-
const folderId = (
|
|
29652
|
+
const normalizedFileName = (_f = data === null || data === void 0 ? void 0 : data.name) !== null && _f !== void 0 ? _f : item.resolvedUploadName;
|
|
29653
|
+
const folderId = (_j = (_h = (_g = data === null || data === void 0 ? void 0 : data.folderId) !== null && _g !== void 0 ? _g : item.targetFolderId) !== null && _h !== void 0 ? _h : selectedFolder) !== null && _j !== void 0 ? _j : null;
|
|
29943
29654
|
const fileId = data === null || data === void 0 ? void 0 : data.id;
|
|
29944
29655
|
// Сохраняем информацию о загруженном файле (включая size для корректного отображения в попапе)
|
|
29945
29656
|
uploadedFilesMap.set(normalizedFileName, {
|
|
@@ -29956,9 +29667,9 @@ const useFilesAPI = () => {
|
|
|
29956
29667
|
}
|
|
29957
29668
|
else {
|
|
29958
29669
|
const data = detail === null || detail === void 0 ? void 0 : detail.data;
|
|
29959
|
-
const normalizedFileName = (
|
|
29960
|
-
const folderId = (
|
|
29961
|
-
await handleFailure(normalizedFileName, folderId, (
|
|
29670
|
+
const normalizedFileName = (_k = data === null || data === void 0 ? void 0 : data.name) !== null && _k !== void 0 ? _k : item.resolvedUploadName;
|
|
29671
|
+
const folderId = (_o = (_m = (_l = data === null || data === void 0 ? void 0 : data.folderId) !== null && _l !== void 0 ? _l : item.targetFolderId) !== null && _m !== void 0 ? _m : selectedFolder) !== null && _o !== void 0 ? _o : null;
|
|
29672
|
+
await handleFailure(normalizedFileName, folderId, (_p = detail === null || detail === void 0 ? void 0 : detail.error) !== null && _p !== void 0 ? _p : new Error(t('Error uploading file')), {
|
|
29962
29673
|
emitNotification: shouldEmitPerItemNotifications,
|
|
29963
29674
|
fileSize: item.file.size,
|
|
29964
29675
|
progressCallbackName: item.originalFileName,
|
|
@@ -29970,17 +29681,17 @@ const useFilesAPI = () => {
|
|
|
29970
29681
|
else if (batchResult.success) {
|
|
29971
29682
|
for (const item of uploadItems) {
|
|
29972
29683
|
const normalizedFileName = item.resolvedUploadName;
|
|
29973
|
-
const folderId = (
|
|
29684
|
+
const folderId = (_r = (_q = item.targetFolderId) !== null && _q !== void 0 ? _q : selectedFolder) !== null && _r !== void 0 ? _r : null;
|
|
29974
29685
|
await handleSuccess(normalizedFileName, folderId, undefined, {
|
|
29975
29686
|
emitNotification: shouldEmitPerItemNotifications,
|
|
29976
29687
|
});
|
|
29977
29688
|
}
|
|
29978
29689
|
}
|
|
29979
29690
|
else {
|
|
29980
|
-
const batchError = (
|
|
29691
|
+
const batchError = (_s = batchResult.error) !== null && _s !== void 0 ? _s : new Error(t('Error uploading file'));
|
|
29981
29692
|
for (const item of uploadItems) {
|
|
29982
29693
|
const normalizedFileName = item.resolvedUploadName;
|
|
29983
|
-
const folderId = (
|
|
29694
|
+
const folderId = (_u = (_t = item.targetFolderId) !== null && _t !== void 0 ? _t : selectedFolder) !== null && _u !== void 0 ? _u : null;
|
|
29984
29695
|
await handleFailure(normalizedFileName, folderId, batchError, {
|
|
29985
29696
|
emitNotification: shouldEmitPerItemNotifications,
|
|
29986
29697
|
fileSize: item.file.size,
|
|
@@ -29993,7 +29704,7 @@ const useFilesAPI = () => {
|
|
|
29993
29704
|
catch (error) {
|
|
29994
29705
|
for (const item of uploadItems) {
|
|
29995
29706
|
const normalizedFileName = item.resolvedUploadName;
|
|
29996
|
-
const folderId = (
|
|
29707
|
+
const folderId = (_w = (_v = item.targetFolderId) !== null && _v !== void 0 ? _v : selectedFolder) !== null && _w !== void 0 ? _w : null;
|
|
29997
29708
|
await handleFailure(normalizedFileName, folderId, error !== null && error !== void 0 ? error : new Error(t('Error uploading file')), {
|
|
29998
29709
|
emitNotification: shouldEmitPerItemNotifications,
|
|
29999
29710
|
fileSize: item.file.size,
|
|
@@ -30061,10 +29772,10 @@ const useFilesAPI = () => {
|
|
|
30061
29772
|
},
|
|
30062
29773
|
});
|
|
30063
29774
|
}
|
|
30064
|
-
else if (totalCount === 1 && errorDetails.length > 0 && ((
|
|
29775
|
+
else if (totalCount === 1 && errorDetails.length > 0 && ((_x = errorDetails[0].error) === null || _x === void 0 ? void 0 : _x.code)) {
|
|
30065
29776
|
// Для одного файла используем конкретное сообщение об ошибке
|
|
30066
|
-
const codeMessage = (0,errorMessages/* getErrorMessageFromCode */.j2)((
|
|
30067
|
-
const failedFileName = (
|
|
29777
|
+
const codeMessage = (0,errorMessages/* getErrorMessageFromCode */.j2)((_y = errorDetails[0].error) === null || _y === void 0 ? void 0 : _y.code, t);
|
|
29778
|
+
const failedFileName = (_0 = (_z = errors[0]) === null || _z === void 0 ? void 0 : _z.fileName) !== null && _0 !== void 0 ? _0 : '';
|
|
30068
29779
|
const failureMessage = codeMessage !== null && codeMessage !== void 0 ? codeMessage : (failedFileName ? `${t('Failed to upload files')}: ${failedFileName}` : t('Failed to upload files'));
|
|
30069
29780
|
notification.error({
|
|
30070
29781
|
id: 'FILES_UPLOAD_BATCH_FAILED',
|
|
@@ -31995,29 +31706,336 @@ const useFilesDeleteModal = (fetchFiles) => {
|
|
|
31995
31706
|
},
|
|
31996
31707
|
};
|
|
31997
31708
|
};
|
|
31998
|
-
|
|
31999
|
-
;// ./src/hooks/core/files/useFilesModals.ts
|
|
32000
|
-
|
|
32001
|
-
|
|
32002
|
-
|
|
32003
|
-
|
|
32004
|
-
const useFilesModals = (fetchFiles) => {
|
|
32005
|
-
const renameModal = useFilesRenameModal(fetchFiles);
|
|
32006
|
-
const moveModal = useFilesMoveModal(fetchFiles);
|
|
32007
|
-
const copyModal = useFilesCopyModal(fetchFiles);
|
|
32008
|
-
const deleteModal = useFilesDeleteModal(fetchFiles);
|
|
32009
|
-
return {
|
|
32010
|
-
state: renameModal.state,
|
|
32011
|
-
actions: Object.assign(Object.assign(Object.assign(Object.assign({}, renameModal.actions), moveModal.actions), copyModal.actions), deleteModal.actions),
|
|
32012
|
-
};
|
|
31709
|
+
|
|
31710
|
+
;// ./src/hooks/core/files/useFilesModals.ts
|
|
31711
|
+
|
|
31712
|
+
|
|
31713
|
+
|
|
31714
|
+
|
|
31715
|
+
const useFilesModals = (fetchFiles) => {
|
|
31716
|
+
const renameModal = useFilesRenameModal(fetchFiles);
|
|
31717
|
+
const moveModal = useFilesMoveModal(fetchFiles);
|
|
31718
|
+
const copyModal = useFilesCopyModal(fetchFiles);
|
|
31719
|
+
const deleteModal = useFilesDeleteModal(fetchFiles);
|
|
31720
|
+
return {
|
|
31721
|
+
state: renameModal.state,
|
|
31722
|
+
actions: Object.assign(Object.assign(Object.assign(Object.assign({}, renameModal.actions), moveModal.actions), copyModal.actions), deleteModal.actions),
|
|
31723
|
+
};
|
|
31724
|
+
};
|
|
31725
|
+
|
|
31726
|
+
;// ./src/hooks/core/files/index.ts
|
|
31727
|
+
|
|
31728
|
+
|
|
31729
|
+
|
|
31730
|
+
|
|
31731
|
+
|
|
31732
|
+
|
|
31733
|
+
|
|
31734
|
+
/***/ }),
|
|
31735
|
+
|
|
31736
|
+
/***/ 9142:
|
|
31737
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
31738
|
+
|
|
31739
|
+
"use strict";
|
|
31740
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
31741
|
+
/* harmony export */ $5: () => (/* binding */ getUniqueFileName),
|
|
31742
|
+
/* harmony export */ mF: () => (/* binding */ encodeUrlForImageSrc),
|
|
31743
|
+
/* harmony export */ nF: () => (/* binding */ formatFileSizeDisplay),
|
|
31744
|
+
/* harmony export */ v7: () => (/* binding */ formatFileSize),
|
|
31745
|
+
/* harmony export */ w3: () => (/* binding */ MAX_FILE_SIZE)
|
|
31746
|
+
/* harmony export */ });
|
|
31747
|
+
/* unused harmony exports MIN_FILE_SIZE, ALLOWED_FILE_TYPES, ALL_ALLOWED_TYPES, validateFile, validateFiles, validateFileUrl, getFileCategory, formatFileSizeShort, sanitizeFileName */
|
|
31748
|
+
/* harmony import */ var antd__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(550);
|
|
31749
|
+
/* harmony import */ var antd__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(antd__WEBPACK_IMPORTED_MODULE_0__);
|
|
31750
|
+
/* harmony import */ var _i18n__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3829);
|
|
31751
|
+
|
|
31752
|
+
|
|
31753
|
+
const MAX_FILE_SIZE = 50 * 1024 * 1024;
|
|
31754
|
+
const MIN_FILE_SIZE = 1;
|
|
31755
|
+
const ALLOWED_FILE_TYPES = {
|
|
31756
|
+
images: ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml', 'image/bmp', 'image/tiff'],
|
|
31757
|
+
documents: [
|
|
31758
|
+
'application/pdf',
|
|
31759
|
+
'text/plain',
|
|
31760
|
+
'application/msword',
|
|
31761
|
+
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
31762
|
+
],
|
|
31763
|
+
archives: ['application/zip', 'application/x-rar-compressed', 'application/x-7z-compressed'],
|
|
31764
|
+
videos: ['video/mp4', 'video/avi', 'video/quicktime', 'video/x-msvideo'],
|
|
31765
|
+
audio: ['audio/mpeg', 'audio/wav', 'audio/ogg'],
|
|
31766
|
+
};
|
|
31767
|
+
const ALL_ALLOWED_TYPES = Object.values(ALLOWED_FILE_TYPES).flat();
|
|
31768
|
+
const validateFile = (file, options = {}) => {
|
|
31769
|
+
const { maxSize = MAX_FILE_SIZE, minSize = MIN_FILE_SIZE, allowedTypes = ALL_ALLOWED_TYPES, allowAllTypes = false, maxFileNameLength = 255, } = options;
|
|
31770
|
+
const errors = [];
|
|
31771
|
+
const warnings = [];
|
|
31772
|
+
if (file.size > maxSize) {
|
|
31773
|
+
errors.push(i18n.t('File too large. Maximum size: {{size}}', { size: formatFileSize(maxSize) }));
|
|
31774
|
+
}
|
|
31775
|
+
if (file.size < minSize) {
|
|
31776
|
+
errors.push(i18n.t('File too small. Minimum size: {{size}}', { size: formatFileSize(minSize) }));
|
|
31777
|
+
}
|
|
31778
|
+
if (!allowAllTypes && !allowedTypes.includes(file.type)) {
|
|
31779
|
+
errors.push(i18n.t('Unsupported file type: {{type}}', { type: file.type || i18n.t('unknown') }));
|
|
31780
|
+
}
|
|
31781
|
+
if (file.name.length > maxFileNameLength) {
|
|
31782
|
+
errors.push(i18n.t('File name is too long. Maximum {{max}} characters', { max: maxFileNameLength }));
|
|
31783
|
+
}
|
|
31784
|
+
const invalidChars = /[<>:"/\\|?*()#]/;
|
|
31785
|
+
const hasControlChars = file.name.split('').some(char => {
|
|
31786
|
+
const code = char.charCodeAt(0);
|
|
31787
|
+
return code >= 0 && code <= 31;
|
|
31788
|
+
});
|
|
31789
|
+
if (invalidChars.test(file.name) || hasControlChars) {
|
|
31790
|
+
errors.push(i18n.t('File name contains invalid characters'));
|
|
31791
|
+
}
|
|
31792
|
+
if (file.size > 10 * 1024 * 1024) {
|
|
31793
|
+
warnings.push(i18n.t('Large file may take a long time to upload'));
|
|
31794
|
+
}
|
|
31795
|
+
return {
|
|
31796
|
+
isValid: errors.length === 0,
|
|
31797
|
+
errors,
|
|
31798
|
+
warnings,
|
|
31799
|
+
};
|
|
31800
|
+
};
|
|
31801
|
+
const validateFiles = (files, options = {}) => {
|
|
31802
|
+
const valid = [];
|
|
31803
|
+
const invalid = [];
|
|
31804
|
+
files.forEach(file => {
|
|
31805
|
+
const result = validateFile(file, options);
|
|
31806
|
+
if (result.isValid) {
|
|
31807
|
+
valid.push(file);
|
|
31808
|
+
}
|
|
31809
|
+
else {
|
|
31810
|
+
invalid.push({ file, result });
|
|
31811
|
+
}
|
|
31812
|
+
});
|
|
31813
|
+
return { valid, invalid };
|
|
31814
|
+
};
|
|
31815
|
+
const validateFileUrl = async (url) => {
|
|
31816
|
+
const errors = [];
|
|
31817
|
+
let notified = false;
|
|
31818
|
+
let lastError = undefined;
|
|
31819
|
+
const notifyError = (message) => {
|
|
31820
|
+
notified = true;
|
|
31821
|
+
notification.error({
|
|
31822
|
+
key: 'FILE_URL_VALIDATION_FAILED',
|
|
31823
|
+
title: message,
|
|
31824
|
+
placement: 'bottomRight',
|
|
31825
|
+
description: url,
|
|
31826
|
+
});
|
|
31827
|
+
};
|
|
31828
|
+
try {
|
|
31829
|
+
new URL(url);
|
|
31830
|
+
}
|
|
31831
|
+
catch (error) {
|
|
31832
|
+
console.error('Invalid URL:', error);
|
|
31833
|
+
lastError = error;
|
|
31834
|
+
const message = i18n.t('Invalid file URL');
|
|
31835
|
+
errors.push(message);
|
|
31836
|
+
notifyError(message);
|
|
31837
|
+
return { isValid: false, errors };
|
|
31838
|
+
}
|
|
31839
|
+
try {
|
|
31840
|
+
const response = await fetch(url, { method: 'HEAD' });
|
|
31841
|
+
if (!response.ok) {
|
|
31842
|
+
errors.push(i18n.t('File unavailable: {{status}} {{statusText}}', {
|
|
31843
|
+
status: response.status,
|
|
31844
|
+
statusText: response.statusText,
|
|
31845
|
+
}));
|
|
31846
|
+
}
|
|
31847
|
+
const contentLength = response.headers.get('content-length');
|
|
31848
|
+
if (contentLength && parseInt(contentLength) > MAX_FILE_SIZE) {
|
|
31849
|
+
errors.push(i18n.t('File too large: {{size}}', { size: formatFileSize(parseInt(contentLength)) }));
|
|
31850
|
+
}
|
|
31851
|
+
const contentType = response.headers.get('content-type');
|
|
31852
|
+
if (contentType && !ALL_ALLOWED_TYPES.includes(contentType)) {
|
|
31853
|
+
errors.push(i18n.t('Unsupported file type: {{contentType}}', { contentType }));
|
|
31854
|
+
}
|
|
31855
|
+
}
|
|
31856
|
+
catch (error) {
|
|
31857
|
+
console.error('Failed to validate file URL:', error);
|
|
31858
|
+
lastError = error;
|
|
31859
|
+
const message = i18n.t('Unable to validate file URL');
|
|
31860
|
+
errors.push(message);
|
|
31861
|
+
notifyError(message);
|
|
31862
|
+
}
|
|
31863
|
+
if (errors.length > 0 && !notified) {
|
|
31864
|
+
notifyError(i18n.t('Unable to validate file URL'));
|
|
31865
|
+
}
|
|
31866
|
+
return {
|
|
31867
|
+
isValid: errors.length === 0,
|
|
31868
|
+
errors,
|
|
31869
|
+
};
|
|
31870
|
+
};
|
|
31871
|
+
const getFileCategory = (file) => {
|
|
31872
|
+
const type = file.type;
|
|
31873
|
+
if (ALLOWED_FILE_TYPES.images.includes(type))
|
|
31874
|
+
return 'image';
|
|
31875
|
+
if (ALLOWED_FILE_TYPES.documents.includes(type))
|
|
31876
|
+
return 'document';
|
|
31877
|
+
if (ALLOWED_FILE_TYPES.archives.includes(type))
|
|
31878
|
+
return 'archive';
|
|
31879
|
+
if (ALLOWED_FILE_TYPES.videos.includes(type))
|
|
31880
|
+
return 'video';
|
|
31881
|
+
if (ALLOWED_FILE_TYPES.audio.includes(type))
|
|
31882
|
+
return 'audio';
|
|
31883
|
+
return 'other';
|
|
31884
|
+
};
|
|
31885
|
+
const formatFileSize = (bytes) => {
|
|
31886
|
+
if (bytes === 0)
|
|
31887
|
+
return '0 Bytes';
|
|
31888
|
+
const k = 1024;
|
|
31889
|
+
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
|
31890
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
31891
|
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
31892
|
+
};
|
|
31893
|
+
const formatFileSizeShort = (bytes) => {
|
|
31894
|
+
if (!bytes || bytes <= 0)
|
|
31895
|
+
return '';
|
|
31896
|
+
const KILOBYTE = 1024;
|
|
31897
|
+
const MEGABYTE = KILOBYTE * 1024;
|
|
31898
|
+
if (bytes < MEGABYTE) {
|
|
31899
|
+
const kb = Math.round(bytes / KILOBYTE);
|
|
31900
|
+
return `${kb} Kb`;
|
|
31901
|
+
}
|
|
31902
|
+
const mb = bytes / MEGABYTE;
|
|
31903
|
+
return `${mb.toFixed(2)} Mb`;
|
|
31904
|
+
};
|
|
31905
|
+
const formatFileSizeDisplay = (value) => {
|
|
31906
|
+
if (value === undefined || value === null)
|
|
31907
|
+
return '';
|
|
31908
|
+
if (typeof value === 'number') {
|
|
31909
|
+
return formatFileSizeShort(value);
|
|
31910
|
+
}
|
|
31911
|
+
const normalized = String(value).trim();
|
|
31912
|
+
if (!normalized)
|
|
31913
|
+
return '';
|
|
31914
|
+
const parsed = Number(normalized);
|
|
31915
|
+
if (!Number.isNaN(parsed)) {
|
|
31916
|
+
return formatFileSizeShort(parsed);
|
|
31917
|
+
}
|
|
31918
|
+
return normalized;
|
|
31919
|
+
};
|
|
31920
|
+
/**
|
|
31921
|
+
* Генерирует уникальное имя файла: если name уже есть в existingNames, добавляет _1 (или _2, _3 и т.д.).
|
|
31922
|
+
* @param name — исходное имя файла (с расширением)
|
|
31923
|
+
* @param existingNames — массив имён файлов/папок в целевой директории
|
|
31924
|
+
*/
|
|
31925
|
+
const getUniqueFileName = (name, existingNames) => {
|
|
31926
|
+
const safeNames = existingNames.filter((n) => typeof n === 'string');
|
|
31927
|
+
const set = new Set(safeNames.map(n => n.toLowerCase()));
|
|
31928
|
+
const safeName = typeof name === 'string' ? name : String(name !== null && name !== void 0 ? name : '');
|
|
31929
|
+
if (!set.has(safeName.toLowerCase()))
|
|
31930
|
+
return safeName;
|
|
31931
|
+
const lastDot = safeName.lastIndexOf('.');
|
|
31932
|
+
const baseName = lastDot > 0 ? safeName.slice(0, lastDot) : safeName;
|
|
31933
|
+
const ext = lastDot > 0 ? safeName.slice(lastDot) : '';
|
|
31934
|
+
let suffix = 1;
|
|
31935
|
+
let candidate;
|
|
31936
|
+
do {
|
|
31937
|
+
candidate = `${baseName}_${suffix}${ext}`;
|
|
31938
|
+
suffix++;
|
|
31939
|
+
} while (set.has(candidate.toLowerCase()));
|
|
31940
|
+
return candidate;
|
|
31941
|
+
};
|
|
31942
|
+
/**
|
|
31943
|
+
* Кодирует URL для безопасного использования в img src. Решает проблему с кириллицей и другими
|
|
31944
|
+
* не-ASCII символами в пути (например, emcdn.ru/.../Снимок_экрана.png).
|
|
31945
|
+
* data: и blob: URLs возвращаются без изменений.
|
|
31946
|
+
*/
|
|
31947
|
+
const encodeUrlForImageSrc = (url) => {
|
|
31948
|
+
if (!url || typeof url !== 'string')
|
|
31949
|
+
return undefined;
|
|
31950
|
+
if (url.startsWith('data:') || url.startsWith('blob:'))
|
|
31951
|
+
return url;
|
|
31952
|
+
try {
|
|
31953
|
+
if (url.startsWith('http://') || url.startsWith('https://') || url.startsWith('/')) {
|
|
31954
|
+
const parsed = new URL(url.startsWith('/') ? `https://x${url}` : url);
|
|
31955
|
+
const origin = url.startsWith('/') ? '' : `${parsed.protocol}//${parsed.host}`;
|
|
31956
|
+
const pathEncoded = parsed.pathname
|
|
31957
|
+
.split('/')
|
|
31958
|
+
.map(seg => {
|
|
31959
|
+
if (!seg)
|
|
31960
|
+
return '';
|
|
31961
|
+
try {
|
|
31962
|
+
return encodeURIComponent(decodeURIComponent(seg));
|
|
31963
|
+
}
|
|
31964
|
+
catch (_a) {
|
|
31965
|
+
return encodeURIComponent(seg);
|
|
31966
|
+
}
|
|
31967
|
+
})
|
|
31968
|
+
.join('/');
|
|
31969
|
+
const result = url.startsWith('/') ? pathEncoded + (parsed.search || '') + (parsed.hash || '') : `${origin}${pathEncoded}${parsed.search}${parsed.hash}`;
|
|
31970
|
+
return result;
|
|
31971
|
+
}
|
|
31972
|
+
}
|
|
31973
|
+
catch (_a) {
|
|
31974
|
+
// если парсинг не удался, возвращаем как есть
|
|
31975
|
+
}
|
|
31976
|
+
return url;
|
|
31977
|
+
};
|
|
31978
|
+
/**
|
|
31979
|
+
* @deprecated Эта функция оставлена только для обратной совместимости.
|
|
31980
|
+
* Используйте {@link normalizeFileName} из `nameNormalization.ts` для настраиваемой нормализации имен файлов.
|
|
31981
|
+
*
|
|
31982
|
+
* Упрощенная санитизация имени файла:
|
|
31983
|
+
* - Заменяет запрещенные символы на `_`
|
|
31984
|
+
* - Заменяет пробелы на `_`
|
|
31985
|
+
* - Удаляет множественные подчеркивания
|
|
31986
|
+
* - Ограничивает длину до 255 символов
|
|
31987
|
+
*/
|
|
31988
|
+
const sanitizeFileName = (fileName) => {
|
|
31989
|
+
return fileName
|
|
31990
|
+
.replace(/[<>:"/\\|?*()#]/g, '_')
|
|
31991
|
+
.split('')
|
|
31992
|
+
.map(char => {
|
|
31993
|
+
const code = char.charCodeAt(0);
|
|
31994
|
+
return code >= 0 && code <= 31 ? '_' : char;
|
|
31995
|
+
})
|
|
31996
|
+
.join('')
|
|
31997
|
+
.replace(/\s+/g, '_')
|
|
31998
|
+
.replace(/_{2,}/g, '_')
|
|
31999
|
+
.substring(0, 255);
|
|
32013
32000
|
};
|
|
32014
32001
|
|
|
32015
|
-
;// ./src/hooks/core/files/index.ts
|
|
32016
|
-
|
|
32017
|
-
|
|
32018
32002
|
|
|
32003
|
+
/***/ }),
|
|
32019
32004
|
|
|
32005
|
+
/***/ 9287:
|
|
32006
|
+
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
32020
32007
|
|
|
32008
|
+
// Imports
|
|
32009
|
+
var ___CSS_LOADER_API_SOURCEMAP_IMPORT___ = __webpack_require__(1354);
|
|
32010
|
+
var ___CSS_LOADER_API_IMPORT___ = __webpack_require__(6314);
|
|
32011
|
+
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);
|
|
32012
|
+
// Module
|
|
32013
|
+
___CSS_LOADER_EXPORT___.push([module.id, `.FolderSidebar-module__button__Yf2rX.ant-btn.ant-btn-icon-only{padding:calc(var(--paddingXXS)*1px) calc(var(--paddingSM)*1px);cursor:pointer;color:var(--colorTextSecondary);display:flex;gap:calc(var(--marginXS)*1px);align-items:center;justify-content:center;border-radius:calc(var(--borderRadiusSM)*1px);transition:all var(--motionDurationFast);box-shadow:none;border:none;width:32px;height:32px}.FolderSidebar-module__button__Yf2rX.ant-btn.ant-btn-icon-only:hover{background-color:var(--colorBgLayout);color:inherit}.FolderSidebar-module__button__Yf2rX:hover{background-color:var(--colorBgContainer);color:var(--colorPrimary)}.FolderSidebar-module__foldersTitle__Uh6u7{display:flex;align-items:center;flex:1;cursor:pointer}.FolderSidebar-module__folderActions__qA2Bk{position:absolute;top:4px;right:4px;display:flex;align-items:center;gap:4px;z-index:10}.FolderSidebar-module__folderActions__qA2Bk .FolderSidebar-module__button__Yf2rX.FolderSidebar-module__ant-btn__LXAXm.FolderSidebar-module__ant-btn-icon-only__j_wVF{padding:calc(var(--paddingXXS)*1px) calc(var(--paddingSM)*1px);cursor:pointer;color:var(--colorTextSecondary);display:flex;gap:calc(var(--marginXS)*1px);align-items:center;justify-content:center;border-radius:calc(var(--borderRadiusSM)*1px);transition:all var(--motionDurationFast);box-shadow:none;border:none;width:32px;height:32px}.FolderSidebar-module__folderActions__qA2Bk .FolderSidebar-module__button__Yf2rX.FolderSidebar-module__ant-btn__LXAXm.FolderSidebar-module__ant-btn-icon-only__j_wVF:hover{background-color:var(--colorBgLayout);color:inherit}.FolderSidebar-module__customExpandIcon__IhZJl{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;margin-right:8px;cursor:pointer;color:#666;font-size:10px;transition:transform .2s ease}.FolderSidebar-module__customExpandIcon__IhZJl:hover{color:var(--colorPrimary)}.FolderSidebar-module__fileCount__bD9DD{display:inline-flex;align-items:center;justify-content:center;min-width:20px;height:100%;padding:0 6px;margin-left:8px;color:#8d8d8d;font-size:14px;font-weight:500;transition:all .2s ease;white-space:nowrap;cursor:default;flex-shrink:0;margin-right:10px}.ant-tree .ant-tree-node-content-wrapper.ant-tree-node-selected{background-color:rgba(0,0,0,0) !important}.FolderSidebar-module__folderMenu__JCzLF .ant-tree-treenode-selected .folder-label span,.FolderSidebar-module__folderMenu__JCzLF .ant-tree .ant-tree-node-content-wrapper.ant-tree-node-selected .folderLabelItem,.FolderSidebar-module__folderMenu__JCzLF .ant-tree-treenode-selected .folderLabelItem,.FolderSidebar-module__folderMenu__JCzLF .ant-tree-node-selected .folderLabelItem{font-weight:600 !important}.FolderSidebar-module__uploadButton__QQUid{width:100%;justify-content:flex-start}.FolderSidebar-module__uploadButton__QQUid button:hover{background-color:var(--colorPrimaryHover) !important}.FolderSidebar-module__folderMenu__JCzLF{padding-left:0;padding-right:0}.FolderSidebar-module__folderMenu__JCzLF .ant-tree-treenode{display:flex;align-items:center;justify-content:space-between;padding:4px 0;border-radius:4px;transition:background-color .2s ease;width:100%;margin-bottom:0}.FolderSidebar-module__folderMenu__JCzLF .ant-tree-node-content-wrapper{flex:1;align-items:center;padding:0;transition:background-color .2s ease}.FolderSidebar-module__folderMenu__JCzLF .ant-tree-node-content-wrapper:hover{background-color:rgba(0,0,0,0)}.FolderSidebar-module__folderMenu__JCzLF .ant-tree-switcher{height:24px;width:24px;margin-top:5px;display:flex !important;align-items:center;justify-content:center;transition:color .2s ease;flex-shrink:0}.FolderSidebar-module__folderMenu__JCzLF .ant-tree-switcher-noop{width:24px}.FolderSidebar-module__folderMenu__JCzLF .ant-tree-switcher-line-icon{color:#d9d9d9}.FolderSidebar-module__folderMenu__JCzLF .FolderSidebar-module__folderItemContainer__byl5b{width:100%;display:flex;align-items:center;justify-content:space-between;padding:2px 0;min-width:0}.FolderSidebar-module__folderMenu__JCzLF .folder-label{display:flex;align-items:center;flex:1;color:#595959;font-size:14px;min-width:0;overflow:hidden}.FolderSidebar-module__folderMenu__JCzLF .ant-tree-treenode[data-key="folders"]{border-bottom:1px solid var(--colorBorderSecondary);margin-bottom:8px;padding-bottom:8px}.FolderSidebar-module__folderMenu__JCzLF .ant-tree-treenode[data-key="folders"].ant-tree-treenode-selected{background-color:rgba(0,0,0,0) !important}.FolderSidebar-module__folderMenu__JCzLF .ant-tree-treenode[data-key="folders"] .ant-tree-node-content-wrapper{padding:0}.FolderSidebar-module__folderMenu__JCzLF .ant-tree-treenode[data-key="folders"] .ant-tree-node-content-wrapper:hover{background-color:rgba(0,0,0,0) !important}.FolderSidebar-module__folderMenu__JCzLF .ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0}.FolderSidebar-module__folderMenu__JCzLF .FolderSidebar-module__emptyFolderContainer__WK6tx{padding:20px;text-align:center}.FolderSidebar-module__folderMenu__JCzLF .ant-tree > .ant-tree-treenode{padding-left:0 !important}.FolderSidebar-module__folderIcon__UoZzH{margin-right:8px;font-size:18px;flex-shrink:0}.FolderSidebar-module__folderLabelItem__uJ062{font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1;min-width:0;user-select:none}.FolderSidebar-module__foldersTitleItem__gapOI{display:flex;align-items:center;flex:1;cursor:pointer;min-width:0;overflow:hidden}.FolderSidebar-module__folderLabel__fHWMp{display:flex;align-items:center;flex:1;min-width:0;overflow:hidden}.FolderSidebar-module__foldersContainer__zdBVU{position:relative;width:100%}.FolderSidebar-module__uploadButton__QQUid .FolderSidebar-module__ant-btn__LXAXm,.FolderSidebar-module__uploadButton__QQUid .ant-btn{display:flex;align-items:center;justify-content:center;gap:3px}.FolderSidebar-module__buttonWrapper__a9Qi5{margin-bottom:24px;display:flex;gap:4px}.FolderSidebar-module__buttonWrapper__a9Qi5>:first-child{flex:1;height:40px;padding-left:10px}.FolderSidebar-module__buttonWrapper__a9Qi5>:last-child{width:40px;height:40px;flex-shrink:0}.FolderSidebar-module__uploadButtonIcon__mWQmq{font-size:20px}.FolderSidebar-module__uploadButtonTitle__wk_o6{line-height:1em}.FolderSidebar-module__emptyFolderContainer__WK6tx{user-select:none;cursor:default;color:var(--colorTextTertiary)}.FolderSidebar-module__folderItemContainer__byl5b{width:100%;display:flex;align-items:center;justify-content:space-between;padding:2px 0;min-width:0}`, "",{"version":3,"sources":["webpack://./src/components/FolderSidebar/FolderSidebar.module.scss"],"names":[],"mappings":"AAAA,+DACI,8DAAA,CACA,cAAA,CACA,+BAAA,CACA,YAAA,CACA,6BAAA,CACA,kBAAA,CACA,sBAAA,CACA,6CAAA,CACA,wCAAA,CACA,eAAA,CAEA,WAAA,CACA,UAAA,CACA,WAAA,CAEA,qEACI,qCAAA,CACA,aAAA,CAIR,2CACI,wCAAA,CACA,yBAAA,CAGJ,2CACE,YAAA,CACA,kBAAA,CACA,MAAA,CACA,cAAA,CAGF,4CACI,iBAAA,CACA,OAAA,CACA,SAAA,CACA,YAAA,CACA,kBAAA,CACA,OAAA,CACA,UAAA,CAEA,qKACE,8DAAA,CACA,cAAA,CACA,+BAAA,CACA,YAAA,CACA,6BAAA,CACA,kBAAA,CACA,sBAAA,CACA,6CAAA,CACA,wCAAA,CACA,eAAA,CAEA,WAAA,CACA,UAAA,CACA,WAAA,CAEA,2KACI,qCAAA,CACA,aAAA,CAKV,+CACE,mBAAA,CACA,kBAAA,CACA,sBAAA,CACA,UAAA,CACA,WAAA,CACA,gBAAA,CACA,cAAA,CACA,UAAA,CACA,cAAA,CACA,6BAAA,CAGF,qDACI,yBAAA,CAGJ,wCACE,mBAAA,CACA,kBAAA,CACA,sBAAA,CACA,cAAA,CACE,WAAA,CACF,aAAA,CACA,eAAA,CACE,aAAA,CACA,cAAA,CACF,eAAA,CACA,uBAAA,CACA,kBAAA,CACA,cAAA,CACA,aAAA,CACA,iBAAA,CAQF,gEACE,yCAAA,CAQF,0XAIE,0BAAA,CAWF,2CACI,UAAA,CACA,0BAAA,CAEA,wDACE,oDAAA,CAIN,yCACE,cAAA,CACA,eAAA,CAGF,4DACE,YAAA,CACA,kBAAA,CACA,6BAAA,CACA,aAAA,CACA,iBAAA,CACA,oCAAA,CACA,UAAA,CACA,eAAA,CAGF,wEACE,MAAA,CAEA,kBAAA,CACA,SAAA,CAEA,oCAAA,CAGF,8EACE,8BAAA,CAGF,4DACE,WAAA,CACA,UAAA,CACA,cAAA,CACA,uBAAA,CACA,kBAAA,CACA,sBAAA,CACA,yBAAA,CACA,aAAA,CAGF,iEACE,UAAA,CAIF,sEACE,aAAA,CAIF,2FACE,UAAA,CACA,YAAA,CACA,kBAAA,CACA,6BAAA,CACA,aAAA,CACA,WAAA,CAGF,uDACE,YAAA,CACA,kBAAA,CACA,MAAA,CACA,aAAA,CACA,cAAA,CACA,WAAA,CACA,eAAA,CAIF,gFACI,mDAAA,CACF,iBAAA,CACA,kBAAA,CAGF,2GACE,yCAAA,CAGF,+GACE,SAAA,CAGF,qHACE,yCAAA,CAIF,mDACE,eAAA,CACA,sBAAA,CACA,kBAAA,CACA,MAAA,CACA,WAAA,CAIF,4FACE,YAAA,CACA,iBAAA,CAIF,wEACE,yBAAA,CAEF,yCACE,gBAAA,CACE,cAAA,CACF,aAAA,CAGF,8CACE,cAAA,CACA,kBAAA,CACA,eAAA,CACA,sBAAA,CACA,MAAA,CACA,WAAA,CACA,gBAAA,CAGF,+CACE,YAAA,CACA,kBAAA,CACA,MAAA,CACA,cAAA,CACA,WAAA,CACA,eAAA,CASF,0CACE,YAAA,CACA,kBAAA,CACA,MAAA,CACA,WAAA,CACA,eAAA,CAGF,+CACE,iBAAA,CACA,UAAA,CAWF,qIAEE,YAAA,CACA,kBAAA,CACA,sBAAA,CACA,OAAA,CAaF,4CAEI,kBAAA,CACA,YAAA,CACA,OAAA,CAIA,yDACI,MAAA,CACA,WAAA,CACA,iBAAA,CAIJ,wDACI,UAAA,CACA,WAAA,CACA,aAAA,CAIR,+CACI,cAAA,CAGJ,gDACI,eAAA,CAGJ,mDACI,gBAAA,CACA,cAAA,CACA,8BAAA,CAGJ,kDACI,UAAA,CACA,YAAA,CACA,kBAAA,CACA,6BAAA,CACA,aAAA,CACA,WAAA","sourcesContent":[".button:global(.ant-btn.ant-btn-icon-only) {\r\n padding: calc(var(--paddingXXS) * 1px) calc(var(--paddingSM) * 1px);\r\n cursor: pointer;\r\n color: var(--colorTextSecondary);\r\n display: flex;\r\n gap: calc(var(--marginXS) * 1px);\r\n align-items: center;\r\n justify-content: center;\r\n border-radius: calc(var(--borderRadiusSM) * 1px);\r\n transition: all var(--motionDurationFast);\r\n box-shadow: none;\r\n\r\n border: none;\r\n width: 32px;\r\n height: 32px;\r\n\r\n &:hover {\r\n background-color: var(--colorBgLayout);\r\n color: inherit;\r\n }\r\n}\r\n\r\n.button:hover {\r\n background-color: var(--colorBgContainer);\r\n color: var(--colorPrimary);\r\n}\r\n\r\n.foldersTitle {\r\n display: flex;\r\n align-items: center;\r\n flex: 1;\r\n cursor: pointer;\r\n}\r\n\r\n.folderActions {\r\n position: absolute;\r\n top: 4px; /* Выравниваем по заголовку Folders */\r\n right: 4px;\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n z-index: 10;\r\n\r\n .button.ant-btn.ant-btn-icon-only {\r\n padding: calc(var(--paddingXXS) * 1px) calc(var(--paddingSM) * 1px);\r\n cursor: pointer;\r\n color: var(--colorTextSecondary);\r\n display: flex;\r\n gap: calc(var(--marginXS) * 1px);\r\n align-items: center;\r\n justify-content: center;\r\n border-radius: calc(var(--borderRadiusSM) * 1px);\r\n transition: all var(--motionDurationFast);\r\n box-shadow: none;\r\n\r\n border: none;\r\n width: 32px;\r\n height: 32px;\r\n\r\n &:hover {\r\n background-color: var(--colorBgLayout);\r\n color: inherit;\r\n }\r\n }\r\n}\r\n\r\n.customExpandIcon {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 16px;\r\n height: 16px;\r\n margin-right: 8px;\r\n cursor: pointer;\r\n color: #666;\r\n font-size: 10px;\r\n transition: transform 0.2s ease;\r\n}\r\n\r\n.customExpandIcon:hover {\r\n color: var(--colorPrimary);\r\n}\r\n\r\n.fileCount {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n min-width: 20px;\r\n height: 100%;\r\n padding: 0 6px;\r\n margin-left: 8px;\r\n color: #8D8D8D;\r\n font-size: 14px;\r\n font-weight: 500;\r\n transition: all 0.2s ease;\r\n white-space: nowrap;\r\n cursor: default;\r\n flex-shrink: 0; /* Запрещаем сжатие счетчика */\r\n margin-right: 10px;\r\n}\r\n\r\n// .fileCount:hover {\r\n// border-color: var(--colorPrimary);\r\n// color: var(--colorPrimary);\r\n// }\r\n\r\n:global(.ant-tree .ant-tree-node-content-wrapper.ant-tree-node-selected) {\r\n background-color: transparent !important;\r\n}\r\n\r\n/* :global(.ant-tree .ant-tree-node-content-wrapper.ant-tree-node-selected):hover {\r\n color: red !important;\r\n} */\r\n\r\n/* Стили для выделения текста в выбранной папке */\r\n.folderMenu :global(.ant-tree-treenode-selected .folder-label span),\r\n.folderMenu :global(.ant-tree .ant-tree-node-content-wrapper.ant-tree-node-selected .folderLabelItem),\r\n.folderMenu :global(.ant-tree-treenode-selected .folderLabelItem),\r\n.folderMenu :global(.ant-tree-node-selected .folderLabelItem) {\r\n font-weight: 600 !important;\r\n}\r\n\r\n/* Стили для иконки в выбранной папке */\r\n/* .folderMenu :global(.ant-tree-treenode-selected .folderIcon),\r\n.folderMenu :global(.ant-tree-node-selected .folderIcon) {\r\n color: red !important;\r\n} */\r\n\r\n/* CSS переменные для упрощения расчетов */\r\n\r\n.uploadButton {\r\n width: 100%;\r\n justify-content: flex-start;\r\n\r\n & button:hover {\r\n background-color: var(--colorPrimaryHover) !important;\r\n }\r\n}\r\n\r\n.folderMenu {\r\n padding-left: 0;\r\n padding-right: 0; /* Место для кнопки справа */\r\n}\r\n\r\n.folderMenu :global(.ant-tree-treenode) {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 4px 0;\r\n border-radius: 4px;\r\n transition: background-color 0.2s ease;\r\n width: 100%;\r\n margin-bottom: 0;\r\n}\r\n\r\n.folderMenu :global(.ant-tree-node-content-wrapper) {\r\n flex: 1;\r\n /* display: flex; */\r\n align-items: center;\r\n padding: 0;\r\n /* border-radius: 4px; */\r\n transition: background-color 0.2s ease;\r\n}\r\n\r\n.folderMenu :global(.ant-tree-node-content-wrapper:hover) {\r\n background-color: transparent;\r\n}\r\n\r\n.folderMenu :global(.ant-tree-switcher) {\r\n height: 24px;\r\n width: 24px;\r\n margin-top: 5px;\r\n display: flex !important;\r\n align-items: center;\r\n justify-content: center;\r\n transition: color 0.2s ease;\r\n flex-shrink: 0; /* Запрещаем сжатие переключателя */\r\n}\r\n\r\n.folderMenu :global(.ant-tree-switcher-noop) {\r\n width: 24px;\r\n}\r\n\r\n/* Стили для линий дерева */\r\n.folderMenu :global(.ant-tree-switcher-line-icon) {\r\n color: #d9d9d9;\r\n}\r\n\r\n/* Улучшение отображения folder-item-container */\r\n.folderMenu .folderItemContainer {\r\n width: 100%;\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 2px 0;\r\n min-width: 0; /* Позволяет flex-элементам сжиматься */\r\n}\r\n\r\n.folderMenu :global(.folder-label) {\r\n display: flex;\r\n align-items: center;\r\n flex: 1;\r\n color: #595959;\r\n font-size: 14px;\r\n min-width: 0;\r\n overflow: hidden;\r\n}\r\n\r\n/* Стили для корневого элемента Folders */\r\n.folderMenu :global(.ant-tree-treenode[data-key='folders']) {\r\n border-bottom: 1px solid var(--colorBorderSecondary);\r\n margin-bottom: 8px;\r\n padding-bottom: 8px;\r\n}\r\n\r\n.folderMenu :global(.ant-tree-treenode[data-key='folders'].ant-tree-treenode-selected) {\r\n background-color: transparent !important;\r\n}\r\n\r\n.folderMenu :global(.ant-tree-treenode[data-key='folders'] .ant-tree-node-content-wrapper) {\r\n padding: 0;\r\n}\r\n\r\n.folderMenu :global(.ant-tree-treenode[data-key='folders'] .ant-tree-node-content-wrapper:hover) {\r\n background-color: transparent !important;\r\n}\r\n\r\n/* Стили для ellipsis - удаляем max-width для гибкости */\r\n.folderMenu :global(.ellipsis) {\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n flex: 1;\r\n min-width: 0;\r\n}\r\n\r\n/* Стили для пустого состояния */\r\n.folderMenu .emptyFolderContainer {\r\n padding: 20px;\r\n text-align: center;\r\n}\r\n\r\n/* Убираем отступы у корневого узла */\r\n.folderMenu :global(.ant-tree > .ant-tree-treenode) {\r\n padding-left: 0 !important;\r\n}\r\n.folderIcon {\r\n margin-right: 8px;\r\n font-size: 18px;\r\n flex-shrink: 0; /* Запрещаем сжатие иконки */\r\n}\r\n\r\n.folderLabelItem {\r\n font-size: 14px;\r\n white-space: nowrap; /* Запрещаем перенос строк */\r\n overflow: hidden; /* Скрываем переполнение */\r\n text-overflow: ellipsis; /* Показываем троеточие */\r\n flex: 1; /* Занимает доступное место */\r\n min-width: 0; /* Позволяет сжиматься */\r\n user-select: none;\r\n}\r\n\r\n.foldersTitleItem {\r\n display: flex;\r\n align-items: center;\r\n flex: 1;\r\n cursor: pointer;\r\n min-width: 0; /* Позволяет сжиматься */\r\n overflow: hidden; /* Скрываем переполнение */\r\n}\r\n\r\n/* .foldersTitleItem .folderLabelItem {\r\n font-weight: 500;\r\n color: #262626;\r\n} */\r\n\r\n/* Класс для заголовка папок */\r\n.folderLabel {\r\n display: flex;\r\n align-items: center;\r\n flex: 1;\r\n min-width: 0;\r\n overflow: hidden;\r\n}\r\n\r\n.foldersContainer {\r\n position: relative;\r\n width: 100%;\r\n}\r\n\r\n/* Дополнительные стили для улучшения визуала */\r\n/* .folderMenu :global(.ant-tree-treenode:hover .folder-label span) {\r\n color: #1890ff;\r\n} */\r\n\r\n/* Стили для дивайдера между папками */\r\n\r\n\r\n.uploadButton .ant-btn,\r\n.uploadButton :global(.ant-btn) {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 3px;\r\n}\r\n/* .folderMenu :global(.ant-tree-treenode-selected) .folderLabelItem {\r\n color: #1890ff !important;\r\n} */\r\n\r\n// .folderMenu :global(.ant-tree-treenode-selected) .folderLabel .folderLabelItem,\r\n// .folderMenu :global(.ant-tree-treenode-selected) .folderLabel .folderIcon,\r\n// .folderMenu :global(.ant-tree-treenode-selected) .folderLabelItem {\r\n// color: var(--colorLink);\r\n// }\r\n\r\n\r\n.buttonWrapper {\r\n // overflow: hidden;\r\n margin-bottom: 24px;\r\n display: flex;\r\n gap: 4px;\r\n // border-radius: calc(var(--borderRadius) * 1px);\r\n \r\n // Левая кнопка занимает всю доступную ширину\r\n > :first-child {\r\n flex: 1;\r\n height: 40px;\r\n padding-left: 10px;\r\n }\r\n \r\n // Правая кнопка строго 40px\r\n > :last-child {\r\n width: 40px;\r\n height: 40px;\r\n flex-shrink: 0;\r\n }\r\n}\r\n\r\n.uploadButtonIcon {\r\n font-size: 20px;\r\n}\r\n\r\n.uploadButtonTitle {\r\n line-height: 1em;\r\n}\r\n\r\n.emptyFolderContainer {\r\n user-select: none;\r\n cursor: default;\r\n color: var(--colorTextTertiary);\r\n}\r\n\r\n.folderItemContainer {\r\n width: 100%;\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: 2px 0;\r\n min-width: 0; /* Позволяет flex-элементам сжиматься */\r\n}\r\n"],"sourceRoot":""}]);
|
|
32014
|
+
// Exports
|
|
32015
|
+
___CSS_LOADER_EXPORT___.locals = {
|
|
32016
|
+
"button": `FolderSidebar-module__button__Yf2rX`,
|
|
32017
|
+
"foldersTitle": `FolderSidebar-module__foldersTitle__Uh6u7`,
|
|
32018
|
+
"folderActions": `FolderSidebar-module__folderActions__qA2Bk`,
|
|
32019
|
+
"ant-btn": `FolderSidebar-module__ant-btn__LXAXm`,
|
|
32020
|
+
"antBtn": `FolderSidebar-module__ant-btn__LXAXm`,
|
|
32021
|
+
"ant-btn-icon-only": `FolderSidebar-module__ant-btn-icon-only__j_wVF`,
|
|
32022
|
+
"antBtnIconOnly": `FolderSidebar-module__ant-btn-icon-only__j_wVF`,
|
|
32023
|
+
"customExpandIcon": `FolderSidebar-module__customExpandIcon__IhZJl`,
|
|
32024
|
+
"fileCount": `FolderSidebar-module__fileCount__bD9DD`,
|
|
32025
|
+
"folderMenu": `FolderSidebar-module__folderMenu__JCzLF`,
|
|
32026
|
+
"uploadButton": `FolderSidebar-module__uploadButton__QQUid`,
|
|
32027
|
+
"folderItemContainer": `FolderSidebar-module__folderItemContainer__byl5b`,
|
|
32028
|
+
"emptyFolderContainer": `FolderSidebar-module__emptyFolderContainer__WK6tx`,
|
|
32029
|
+
"folderIcon": `FolderSidebar-module__folderIcon__UoZzH`,
|
|
32030
|
+
"folderLabelItem": `FolderSidebar-module__folderLabelItem__uJ062`,
|
|
32031
|
+
"foldersTitleItem": `FolderSidebar-module__foldersTitleItem__gapOI`,
|
|
32032
|
+
"folderLabel": `FolderSidebar-module__folderLabel__fHWMp`,
|
|
32033
|
+
"foldersContainer": `FolderSidebar-module__foldersContainer__zdBVU`,
|
|
32034
|
+
"buttonWrapper": `FolderSidebar-module__buttonWrapper__a9Qi5`,
|
|
32035
|
+
"uploadButtonIcon": `FolderSidebar-module__uploadButtonIcon__mWQmq`,
|
|
32036
|
+
"uploadButtonTitle": `FolderSidebar-module__uploadButtonTitle__wk_o6`
|
|
32037
|
+
};
|
|
32038
|
+
module.exports = ___CSS_LOADER_EXPORT___;
|
|
32021
32039
|
|
|
32022
32040
|
|
|
32023
32041
|
/***/ }),
|
|
@@ -32433,7 +32451,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
32433
32451
|
"default": () => (/* binding */ src)
|
|
32434
32452
|
});
|
|
32435
32453
|
|
|
32436
|
-
// UNUSED EXPORTS: DEFAULT_FILE_MANAGER_CACHE_TTL_MS, DataSourceProxyBase, FailedRequestCache, FileContent, FileManagerApiError, FileManagerApp, FileManagerAppWithContext, FileModals, FolderSidebar, MutationRegistry, PathAwareStorageAdapter, PixieOnlyApp, TreeCache, ViewCacheManager, buildAssetsPath, defaultIsFolderNotFoundError, fetchRemoteImageBlobByUrl, getAssetsBase, init, initFileManager, initPixieEditor, installResizeObserverErrorHandler, joinUrls, mapHttpStatusToErrorCode, uninstallResizeObserverErrorHandler, unmount, unmountPixieEditor
|
|
32454
|
+
// UNUSED EXPORTS: DEFAULT_FILE_MANAGER_CACHE_TTL_MS, DataSourceProxyBase, FailedRequestCache, FileContent, FileManagerApiError, FileManagerApp, FileManagerAppWithContext, FileModals, FolderSidebar, MutationRegistry, PathAwareStorageAdapter, PixieOnlyApp, TRASH_FOLDER_ID, TreeCache, ViewCacheManager, buildAssetsPath, compareFileSystemItems, createSystemFolderByPathResolver, defaultChildrenViewFilterMatch, defaultFileSystemItemComparator, defaultIsFolderNotFoundError, fetchRemoteImageBlobByUrl, getAssetsBase, getTrashFolderLookupCandidates, init, initFileManager, initPixieEditor, installResizeObserverErrorHandler, joinUrls, mapHttpStatusToErrorCode, matchesChildrenViewFilter, normalizeSystemFolderPath, resolveSortParams, resolveViewStrategyOptions, uninstallResizeObserverErrorHandler, unmount, unmountPixieEditor
|
|
32437
32455
|
|
|
32438
32456
|
// EXTERNAL MODULE: ./node_modules/react/jsx-runtime.js
|
|
32439
32457
|
var jsx_runtime = __webpack_require__(4848);
|
|
@@ -33361,8 +33379,8 @@ const SearchInput = ({ onSearch, placeholder, className }) => {
|
|
|
33361
33379
|
;// ./src/components/SearchInput/index.ts
|
|
33362
33380
|
|
|
33363
33381
|
|
|
33364
|
-
// EXTERNAL MODULE: ./src/hooks/core/files/index.ts +
|
|
33365
|
-
var core_files = __webpack_require__(
|
|
33382
|
+
// EXTERNAL MODULE: ./src/hooks/core/files/index.ts + 18 modules
|
|
33383
|
+
var core_files = __webpack_require__(8573);
|
|
33366
33384
|
;// ./src/hooks/core/types.ts
|
|
33367
33385
|
/** Полный список опций сортировки в дропдауне (порядок отображения). */
|
|
33368
33386
|
const ALL_SORT_OPTIONS = [
|
|
@@ -39870,6 +39888,7 @@ var TreeCache_rest = (undefined && undefined.__rest) || function (s, e) {
|
|
|
39870
39888
|
return t;
|
|
39871
39889
|
};
|
|
39872
39890
|
|
|
39891
|
+
|
|
39873
39892
|
const ROOT_KEY = '';
|
|
39874
39893
|
/** When `fileManager.cacheStrategy.ttl` is unset: success/error cache and notification dedupe fallback (30 min). */
|
|
39875
39894
|
const DEFAULT_FILE_MANAGER_CACHE_TTL_MS = (/* unused pure expression or super */ null && (30 * 60 * 1000));
|
|
@@ -40326,14 +40345,15 @@ class ViewCacheManager {
|
|
|
40326
40345
|
this.views = new Map();
|
|
40327
40346
|
// Защита от переполнения
|
|
40328
40347
|
this.maxViewsPerParent = 50;
|
|
40348
|
+
const resolved = resolveViewStrategyOptions(options);
|
|
40329
40349
|
this.strategy = {
|
|
40330
|
-
allowSortedInsert: (_a =
|
|
40331
|
-
allowSearchInsert: (_b =
|
|
40332
|
-
invalidateOnPaginationFull: (_c =
|
|
40333
|
-
preloadPagesBefore: (_d =
|
|
40334
|
-
preloadPagesAfter: (_e =
|
|
40335
|
-
comparator:
|
|
40336
|
-
filterMatch:
|
|
40350
|
+
allowSortedInsert: (_a = resolved.allowSortedInsert) !== null && _a !== void 0 ? _a : true,
|
|
40351
|
+
allowSearchInsert: (_b = resolved.allowSearchInsert) !== null && _b !== void 0 ? _b : true,
|
|
40352
|
+
invalidateOnPaginationFull: (_c = resolved.invalidateOnPaginationFull) !== null && _c !== void 0 ? _c : true,
|
|
40353
|
+
preloadPagesBefore: (_d = resolved.preloadPagesBefore) !== null && _d !== void 0 ? _d : 0,
|
|
40354
|
+
preloadPagesAfter: (_e = resolved.preloadPagesAfter) !== null && _e !== void 0 ? _e : 1,
|
|
40355
|
+
comparator: resolved.comparator,
|
|
40356
|
+
filterMatch: resolved.filterMatch,
|
|
40337
40357
|
};
|
|
40338
40358
|
this.ttl = ttl;
|
|
40339
40359
|
this.errorTtl = errorTtl !== null && errorTtl !== void 0 ? errorTtl : ttl;
|
|
@@ -40375,6 +40395,17 @@ class ViewCacheManager {
|
|
|
40375
40395
|
return true;
|
|
40376
40396
|
return false;
|
|
40377
40397
|
}
|
|
40398
|
+
/** Mark cached view as stale and cancel any in-flight load for this record. */
|
|
40399
|
+
markViewStaleForReload(rec) {
|
|
40400
|
+
var _a;
|
|
40401
|
+
rec.view.meta = Object.assign(Object.assign({}, ((_a = rec.view.meta) !== null && _a !== void 0 ? _a : {})), { stale: true });
|
|
40402
|
+
rec.view.updatedAt = this.now();
|
|
40403
|
+
rec.view.loadId = generateId();
|
|
40404
|
+
if (rec.view.abortController) {
|
|
40405
|
+
rec.view.abortController.abort();
|
|
40406
|
+
rec.view.abortController = undefined;
|
|
40407
|
+
}
|
|
40408
|
+
}
|
|
40378
40409
|
cleanupOldViews(bucket) {
|
|
40379
40410
|
if (bucket.size <= this.maxViewsPerParent)
|
|
40380
40411
|
return;
|
|
@@ -40651,14 +40682,6 @@ class ViewCacheManager {
|
|
|
40651
40682
|
}
|
|
40652
40683
|
}
|
|
40653
40684
|
}
|
|
40654
|
-
// Если задан comparator — считаем клиентскую сортировку авторитетной
|
|
40655
|
-
canSafelyModifySortedView(baseParams) {
|
|
40656
|
-
if (!baseParams.sortBy && !baseParams.sortOrder)
|
|
40657
|
-
return true;
|
|
40658
|
-
if (this.strategy.comparator)
|
|
40659
|
-
return true;
|
|
40660
|
-
return false;
|
|
40661
|
-
}
|
|
40662
40685
|
cascadeShiftPages(bucket, startPageRec, startPageNum, pageSize, totalPages, entitiesManager, baseParams) {
|
|
40663
40686
|
var _a, _b, _c;
|
|
40664
40687
|
let currentPageRec = startPageRec;
|
|
@@ -40775,7 +40798,7 @@ class ViewCacheManager {
|
|
|
40775
40798
|
return wasNewPageCreated;
|
|
40776
40799
|
}
|
|
40777
40800
|
tryInsertSorted(rec, entity, entitiesManager) {
|
|
40778
|
-
var _a;
|
|
40801
|
+
var _a, _b;
|
|
40779
40802
|
const comparator = this.strategy.comparator;
|
|
40780
40803
|
if (!comparator)
|
|
40781
40804
|
return false;
|
|
@@ -40787,6 +40810,21 @@ class ViewCacheManager {
|
|
|
40787
40810
|
const currentEntities = rec.view.value.map((id) => entitiesManager.getEntity(id));
|
|
40788
40811
|
if (currentEntities.some((e) => !e))
|
|
40789
40812
|
return false;
|
|
40813
|
+
if (currentEntities.length === 0) {
|
|
40814
|
+
const params = (_b = rec.params) !== null && _b !== void 0 ? _b : {};
|
|
40815
|
+
if (params.sortBy || params.sortOrder) {
|
|
40816
|
+
const probe = comparator(entity, entity, rec.params);
|
|
40817
|
+
if (typeof probe !== 'number' || Number.isNaN(probe))
|
|
40818
|
+
return false;
|
|
40819
|
+
}
|
|
40820
|
+
if (rec.view.value.includes(entity.id)) {
|
|
40821
|
+
rec.view.updatedAt = this.now();
|
|
40822
|
+
return true;
|
|
40823
|
+
}
|
|
40824
|
+
rec.view.value = [entity.id];
|
|
40825
|
+
rec.view.updatedAt = this.now();
|
|
40826
|
+
return true;
|
|
40827
|
+
}
|
|
40790
40828
|
let lo = 0;
|
|
40791
40829
|
let hi = currentEntities.length;
|
|
40792
40830
|
while (lo < hi) {
|
|
@@ -40805,9 +40843,6 @@ class ViewCacheManager {
|
|
|
40805
40843
|
}
|
|
40806
40844
|
rec.view.value = [...rec.view.value.slice(0, lo), entity.id, ...rec.view.value.slice(lo)];
|
|
40807
40845
|
rec.view.updatedAt = this.now();
|
|
40808
|
-
if (rec.view.meta && typeof rec.view.meta.total === 'number') {
|
|
40809
|
-
rec.view.meta.total = Number(rec.view.meta.total) + 1;
|
|
40810
|
-
}
|
|
40811
40846
|
return true;
|
|
40812
40847
|
}
|
|
40813
40848
|
updateChildrenCountForOperation(operation, entity, prevParentId, entitiesManager) {
|
|
@@ -40842,7 +40877,7 @@ class ViewCacheManager {
|
|
|
40842
40877
|
}
|
|
40843
40878
|
// Разделили smartInvalidate на хелперы
|
|
40844
40879
|
smartInvalidateChildrenViews(parentId, entity, operation, entitiesManager, prevParentId, prevEntity) {
|
|
40845
|
-
var _a, _b, _c
|
|
40880
|
+
var _a, _b, _c;
|
|
40846
40881
|
if (!entity)
|
|
40847
40882
|
return;
|
|
40848
40883
|
// Всегда обновляем childrenCount (entitiesManager обязателен)
|
|
@@ -40867,7 +40902,7 @@ class ViewCacheManager {
|
|
|
40867
40902
|
if (rec.view.meta && typeof rec.view.meta.total === 'number') {
|
|
40868
40903
|
rec.view.meta.total = Math.max(0, rec.view.meta.total - 1);
|
|
40869
40904
|
}
|
|
40870
|
-
|
|
40905
|
+
this.markViewStaleForReload(rec);
|
|
40871
40906
|
}
|
|
40872
40907
|
continue;
|
|
40873
40908
|
}
|
|
@@ -40885,13 +40920,7 @@ class ViewCacheManager {
|
|
|
40885
40920
|
const entityInView = rec.view.value.includes(entity.id);
|
|
40886
40921
|
const shouldInvalidateCompletely = this.shouldInvalidateCompletely(rec, operation, entity, hasSort, isPaginated, page);
|
|
40887
40922
|
if (shouldInvalidateCompletely) {
|
|
40888
|
-
|
|
40889
|
-
rec.view.loadId = generateId();
|
|
40890
|
-
// Отменяем старый AbortController если был
|
|
40891
|
-
if (rec.view.abortController) {
|
|
40892
|
-
rec.view.abortController.abort();
|
|
40893
|
-
rec.view.abortController = undefined;
|
|
40894
|
-
}
|
|
40923
|
+
this.markViewStaleForReload(rec);
|
|
40895
40924
|
continue;
|
|
40896
40925
|
}
|
|
40897
40926
|
switch (operation) {
|
|
@@ -40911,13 +40940,10 @@ class ViewCacheManager {
|
|
|
40911
40940
|
}
|
|
40912
40941
|
}
|
|
40913
40942
|
}
|
|
40914
|
-
shouldInvalidateCompletely(rec, operation,
|
|
40943
|
+
shouldInvalidateCompletely(rec, operation, _entity, _hasSort, isPaginated, page) {
|
|
40915
40944
|
if (isPaginated && page > 1 && (operation === 'insert' || operation === 'delete' || operation === 'move')) {
|
|
40916
40945
|
return true;
|
|
40917
40946
|
}
|
|
40918
|
-
if (hasSort && !this.strategy.comparator && (operation === 'insert' || operation === 'move')) {
|
|
40919
|
-
return true;
|
|
40920
|
-
}
|
|
40921
40947
|
if (this.isExpired(rec.view.updatedAt)) {
|
|
40922
40948
|
return true;
|
|
40923
40949
|
}
|
|
@@ -40928,16 +40954,13 @@ class ViewCacheManager {
|
|
|
40928
40954
|
const itemType = ((_a = rec.params) === null || _a === void 0 ? void 0 : _a.itemType) || 'all';
|
|
40929
40955
|
if (!this.isEntityTypeCompatible(entity, itemType))
|
|
40930
40956
|
return false;
|
|
40931
|
-
if (this.strategy.comparator && this.strategy.filterMatch) {
|
|
40932
|
-
if (!this.strategy.filterMatch(entity, rec.params))
|
|
40933
|
-
return false;
|
|
40934
|
-
const inserted = this.tryInsertSorted(rec, entity, entitiesManager);
|
|
40935
|
-
if (inserted)
|
|
40936
|
-
return true;
|
|
40937
|
-
}
|
|
40938
40957
|
const params = (_b = rec.params) !== null && _b !== void 0 ? _b : {};
|
|
40939
|
-
|
|
40940
|
-
|
|
40958
|
+
if (!this.strategy.filterMatch(entity, params))
|
|
40959
|
+
return false;
|
|
40960
|
+
const inserted = this.tryInsertSorted(rec, entity, entitiesManager);
|
|
40961
|
+
if (inserted)
|
|
40962
|
+
return true;
|
|
40963
|
+
if (params.sortBy || params.sortOrder)
|
|
40941
40964
|
return false;
|
|
40942
40965
|
if (!isPaginated || rec.view.value.length < pageSize) {
|
|
40943
40966
|
rec.view.value.push(entity.id);
|
|
@@ -40982,31 +41005,37 @@ class ViewCacheManager {
|
|
|
40982
41005
|
}
|
|
40983
41006
|
// helper: вставка
|
|
40984
41007
|
handleInsert(bucket, rec, page, pageSize, isPaginated, hasSort, entity, entitiesManager) {
|
|
40985
|
-
var _a, _b, _c
|
|
41008
|
+
var _a, _b, _c;
|
|
40986
41009
|
if (rec.view.value.includes(entity.id))
|
|
40987
41010
|
return;
|
|
40988
41011
|
if (hasSort && this.strategy.allowSortedInsert && this.strategy.comparator && entitiesManager) {
|
|
40989
41012
|
const inserted = this.tryInsertSorted(rec, entity, entitiesManager);
|
|
40990
|
-
if (inserted
|
|
40991
|
-
rec.view.meta.total
|
|
40992
|
-
|
|
40993
|
-
|
|
40994
|
-
|
|
40995
|
-
|
|
41013
|
+
if (inserted) {
|
|
41014
|
+
if (rec.view.meta && typeof rec.view.meta.total === 'number') {
|
|
41015
|
+
rec.view.meta.total += 1;
|
|
41016
|
+
if (isPaginated && Number.isFinite(pageSize)) {
|
|
41017
|
+
const finitePageSize = pageSize;
|
|
41018
|
+
if (finitePageSize > 0) {
|
|
41019
|
+
rec.view.meta.totalPages = Math.max(1, Math.ceil(rec.view.meta.total / finitePageSize));
|
|
41020
|
+
}
|
|
40996
41021
|
}
|
|
41022
|
+
this.syncTotalsInSameViews(bucket, rec);
|
|
40997
41023
|
}
|
|
40998
|
-
|
|
40999
|
-
|
|
41000
|
-
|
|
41001
|
-
|
|
41002
|
-
|
|
41003
|
-
|
|
41004
|
-
|
|
41005
|
-
|
|
41006
|
-
|
|
41007
|
-
|
|
41024
|
+
rec.view.updatedAt = Date.now();
|
|
41025
|
+
if (isPaginated && ((_b = (_a = rec.view.value) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > pageSize && entitiesManager) {
|
|
41026
|
+
const meta = rec.view.meta;
|
|
41027
|
+
const totalPages = meta && typeof meta.totalPages === 'number' ? meta.totalPages : 1;
|
|
41028
|
+
const wasNewPageCreated = this.cascadeShiftToNextPage(bucket, rec, page, pageSize, totalPages, entitiesManager, (_c = rec.params) !== null && _c !== void 0 ? _c : {});
|
|
41029
|
+
if (wasNewPageCreated && rec.view.meta && typeof rec.view.meta.totalPages === 'number') {
|
|
41030
|
+
const newTotalPages = rec.view.meta.totalPages + 1;
|
|
41031
|
+
rec.view.meta.totalPages = newTotalPages;
|
|
41032
|
+
this.updateTotalPagesForAllViews(bucket, newTotalPages);
|
|
41033
|
+
}
|
|
41008
41034
|
}
|
|
41009
41035
|
}
|
|
41036
|
+
else {
|
|
41037
|
+
this.markViewStaleForReload(rec);
|
|
41038
|
+
}
|
|
41010
41039
|
}
|
|
41011
41040
|
else {
|
|
41012
41041
|
if (!isPaginated || rec.view.value.length < pageSize) {
|
|
@@ -41024,7 +41053,7 @@ class ViewCacheManager {
|
|
|
41024
41053
|
rec.view.updatedAt = Date.now();
|
|
41025
41054
|
}
|
|
41026
41055
|
else {
|
|
41027
|
-
|
|
41056
|
+
this.markViewStaleForReload(rec);
|
|
41028
41057
|
}
|
|
41029
41058
|
}
|
|
41030
41059
|
rec.view.loadId = generateId();
|
|
@@ -41036,7 +41065,7 @@ class ViewCacheManager {
|
|
|
41036
41065
|
}
|
|
41037
41066
|
// helper: update
|
|
41038
41067
|
handleUpdate(bucket, rec, page, pageSize, isPaginated, hasSort, hasSearch, entity, entitiesManager) {
|
|
41039
|
-
var _a, _b
|
|
41068
|
+
var _a, _b;
|
|
41040
41069
|
const entityInView = rec.view.value.includes(entity.id);
|
|
41041
41070
|
const stillCompatible = this.isEntityTypeCompatible(entity, ((_a = rec.params) === null || _a === void 0 ? void 0 : _a.itemType) || 'all');
|
|
41042
41071
|
if (entityInView && !stillCompatible) {
|
|
@@ -41073,46 +41102,16 @@ class ViewCacheManager {
|
|
|
41073
41102
|
rec.view.value = rec.view.value.filter((id) => id !== entity.id);
|
|
41074
41103
|
const reinserted = this.tryReinsertEntity(rec, entity, entitiesManager, isPaginated, pageSize);
|
|
41075
41104
|
if (!reinserted) {
|
|
41076
|
-
|
|
41077
|
-
rec.view.meta.total = Math.max(0, rec.view.meta.total - 1);
|
|
41078
|
-
if (isPaginated && Number.isFinite(pageSize) && typeof rec.view.meta.total === 'number') {
|
|
41079
|
-
const finitePageSize = pageSize;
|
|
41080
|
-
if (finitePageSize > 0) {
|
|
41081
|
-
rec.view.meta.totalPages = Math.max(1, Math.ceil(rec.view.meta.total / finitePageSize));
|
|
41082
|
-
}
|
|
41083
|
-
}
|
|
41084
|
-
this.syncTotalsInSameViews(bucket, rec);
|
|
41085
|
-
}
|
|
41086
|
-
if (isPaginated && rec.view.value.length < pageSize && entitiesManager) {
|
|
41087
|
-
const meta = rec.view.meta;
|
|
41088
|
-
const totalPages = meta && typeof meta.totalPages === 'number' ? meta.totalPages : 1;
|
|
41089
|
-
const wasEmptyPageRemoved = this.cascadeShiftPages(bucket, rec, page, pageSize, totalPages, entitiesManager, (_c = rec.params) !== null && _c !== void 0 ? _c : {});
|
|
41090
|
-
if (wasEmptyPageRemoved && rec.view.meta && typeof rec.view.meta.totalPages === 'number') {
|
|
41091
|
-
const newTotalPages = Math.max(1, rec.view.meta.totalPages - 1);
|
|
41092
|
-
rec.view.meta.totalPages = newTotalPages;
|
|
41093
|
-
this.updateTotalPagesForAllViews(bucket, newTotalPages);
|
|
41094
|
-
}
|
|
41095
|
-
}
|
|
41105
|
+
this.markViewStaleForReload(rec);
|
|
41096
41106
|
}
|
|
41097
41107
|
else {
|
|
41098
|
-
|
|
41099
|
-
|
|
41100
|
-
|
|
41101
|
-
|
|
41102
|
-
|
|
41103
|
-
rec.view.meta.totalPages = Math.max(1, Math.ceil(rec.view.meta.total / finitePageSize));
|
|
41104
|
-
}
|
|
41105
|
-
}
|
|
41106
|
-
this.syncTotalsInSameViews(bucket, rec);
|
|
41108
|
+
rec.view.updatedAt = Date.now();
|
|
41109
|
+
rec.view.loadId = generateId();
|
|
41110
|
+
if (rec.view.abortController) {
|
|
41111
|
+
rec.view.abortController.abort();
|
|
41112
|
+
rec.view.abortController = undefined;
|
|
41107
41113
|
}
|
|
41108
41114
|
}
|
|
41109
|
-
rec.view.updatedAt = Date.now();
|
|
41110
|
-
rec.view.loadId = generateId();
|
|
41111
|
-
// Отменяем старый AbortController если был
|
|
41112
|
-
if (rec.view.abortController) {
|
|
41113
|
-
rec.view.abortController.abort();
|
|
41114
|
-
rec.view.abortController = undefined;
|
|
41115
|
-
}
|
|
41116
41115
|
return;
|
|
41117
41116
|
}
|
|
41118
41117
|
if (entityInView) {
|
|
@@ -41128,15 +41127,21 @@ class ViewCacheManager {
|
|
|
41128
41127
|
if (stillCompatible && !hasSearch) {
|
|
41129
41128
|
if (hasSort && this.strategy.allowSortedInsert && this.strategy.comparator && entitiesManager) {
|
|
41130
41129
|
const inserted = this.tryInsertSorted(rec, entity, entitiesManager);
|
|
41131
|
-
if (inserted
|
|
41132
|
-
rec.view.meta.total
|
|
41133
|
-
|
|
41134
|
-
|
|
41135
|
-
|
|
41136
|
-
|
|
41130
|
+
if (inserted) {
|
|
41131
|
+
if (rec.view.meta && typeof rec.view.meta.total === 'number') {
|
|
41132
|
+
rec.view.meta.total += 1;
|
|
41133
|
+
if (isPaginated && Number.isFinite(pageSize)) {
|
|
41134
|
+
const finitePageSize = pageSize;
|
|
41135
|
+
if (finitePageSize > 0) {
|
|
41136
|
+
rec.view.meta.totalPages = Math.max(1, Math.ceil(rec.view.meta.total / finitePageSize));
|
|
41137
|
+
}
|
|
41137
41138
|
}
|
|
41139
|
+
this.syncTotalsInSameViews(bucket, rec);
|
|
41138
41140
|
}
|
|
41139
|
-
|
|
41141
|
+
rec.view.updatedAt = Date.now();
|
|
41142
|
+
}
|
|
41143
|
+
else {
|
|
41144
|
+
this.markViewStaleForReload(rec);
|
|
41140
41145
|
}
|
|
41141
41146
|
}
|
|
41142
41147
|
else if (!isPaginated || rec.view.value.length < pageSize) {
|
|
@@ -41154,7 +41159,7 @@ class ViewCacheManager {
|
|
|
41154
41159
|
rec.view.updatedAt = Date.now();
|
|
41155
41160
|
}
|
|
41156
41161
|
else {
|
|
41157
|
-
|
|
41162
|
+
this.markViewStaleForReload(rec);
|
|
41158
41163
|
}
|
|
41159
41164
|
rec.view.loadId = generateId();
|
|
41160
41165
|
// Отменяем старый AbortController если был
|
|
@@ -41560,14 +41565,15 @@ class TreeCache_TreeCache {
|
|
|
41560
41565
|
});
|
|
41561
41566
|
// Применяем viewOptions к ViewCacheManager после создания
|
|
41562
41567
|
if (viewOptions) {
|
|
41568
|
+
const resolved = resolveViewStrategyOptions(viewOptions);
|
|
41563
41569
|
v.strategy = {
|
|
41564
|
-
allowSortedInsert: (_g =
|
|
41565
|
-
allowSearchInsert: (_h =
|
|
41566
|
-
invalidateOnPaginationFull: (_j =
|
|
41567
|
-
preloadPagesBefore: (_k =
|
|
41568
|
-
preloadPagesAfter: (_l =
|
|
41569
|
-
comparator:
|
|
41570
|
-
filterMatch:
|
|
41570
|
+
allowSortedInsert: (_g = resolved.allowSortedInsert) !== null && _g !== void 0 ? _g : true,
|
|
41571
|
+
allowSearchInsert: (_h = resolved.allowSearchInsert) !== null && _h !== void 0 ? _h : true,
|
|
41572
|
+
invalidateOnPaginationFull: (_j = resolved.invalidateOnPaginationFull) !== null && _j !== void 0 ? _j : true,
|
|
41573
|
+
preloadPagesBefore: (_k = resolved.preloadPagesBefore) !== null && _k !== void 0 ? _k : 0,
|
|
41574
|
+
preloadPagesAfter: (_l = resolved.preloadPagesAfter) !== null && _l !== void 0 ? _l : 1,
|
|
41575
|
+
comparator: resolved.comparator,
|
|
41576
|
+
filterMatch: resolved.filterMatch,
|
|
41571
41577
|
};
|
|
41572
41578
|
}
|
|
41573
41579
|
tc.entities = ent;
|
|
@@ -41617,6 +41623,8 @@ var DataSourceProxyBase_rest = (undefined && undefined.__rest) || function (s, e
|
|
|
41617
41623
|
|
|
41618
41624
|
|
|
41619
41625
|
|
|
41626
|
+
|
|
41627
|
+
|
|
41620
41628
|
// Константы для стандартных идентификаторов
|
|
41621
41629
|
const DEFAULT_ROOT_ID = '';
|
|
41622
41630
|
const DEFAULT_TRASH_PATH = 'Trash';
|
|
@@ -41672,12 +41680,62 @@ function parseFilePath(filePath) {
|
|
|
41672
41680
|
* Extend this class in a consumer app to add backend-specific logic.
|
|
41673
41681
|
*/
|
|
41674
41682
|
class DataSourceProxyBase {
|
|
41683
|
+
_getTrashPath() {
|
|
41684
|
+
return this._pathOptions.trashPath || DEFAULT_TRASH_PATH;
|
|
41685
|
+
}
|
|
41686
|
+
_getPathLookupCandidates(path) {
|
|
41687
|
+
return getTrashFolderLookupCandidates(path, this._getTrashPath(), TRASH_FOLDER_ID);
|
|
41688
|
+
}
|
|
41689
|
+
_folderFromResolvedPath(resolved, lookupPath) {
|
|
41690
|
+
var _a;
|
|
41691
|
+
if (resolved.isFolder !== true) {
|
|
41692
|
+
const message = resolved.isFolder === false ?
|
|
41693
|
+
"Path '%s' resolves to a file, not a folder".replace('%s', lookupPath)
|
|
41694
|
+
: "Path '%s' resolved to an item that is not marked as a folder".replace('%s', lookupPath);
|
|
41695
|
+
throw new FileManagerApiError(message, 'ValidationError');
|
|
41696
|
+
}
|
|
41697
|
+
if (!resolved.id) {
|
|
41698
|
+
const message = "Path '%s' resolved to a folder without id".replace('%s', lookupPath);
|
|
41699
|
+
throw new FileManagerApiError(message, 'ValidationError');
|
|
41700
|
+
}
|
|
41701
|
+
const folder = {
|
|
41702
|
+
id: resolved.id,
|
|
41703
|
+
name: resolved.name || resolved.id,
|
|
41704
|
+
parentId: resolved.folderId,
|
|
41705
|
+
};
|
|
41706
|
+
// Synthetic system folders (e.g. backend-managed trash) must exist in the entity
|
|
41707
|
+
// graph so forceInvalidate(trash.id) can invalidate children views.
|
|
41708
|
+
this._cache.upsertEntity(normalizeFileSystemItem({
|
|
41709
|
+
id: folder.id,
|
|
41710
|
+
name: folder.name,
|
|
41711
|
+
folderId: (_a = folder.parentId) !== null && _a !== void 0 ? _a : null,
|
|
41712
|
+
isFolder: true,
|
|
41713
|
+
}));
|
|
41714
|
+
return folder;
|
|
41715
|
+
}
|
|
41716
|
+
async _resolveFolderByPath(path) {
|
|
41717
|
+
if (typeof this._dataProvider.findItemByPath !== 'function') {
|
|
41718
|
+
return undefined;
|
|
41719
|
+
}
|
|
41720
|
+
for (const lookupPath of this._getPathLookupCandidates(path)) {
|
|
41721
|
+
const resolved = await this._dataProvider.findItemByPath(lookupPath);
|
|
41722
|
+
if (!resolved) {
|
|
41723
|
+
continue;
|
|
41724
|
+
}
|
|
41725
|
+
return this._folderFromResolvedPath(resolved, lookupPath);
|
|
41726
|
+
}
|
|
41727
|
+
return undefined;
|
|
41728
|
+
}
|
|
41675
41729
|
async _findOrCreateFolderByPath(path) {
|
|
41676
41730
|
const parts = parseFilePath(path);
|
|
41677
41731
|
if (parts.length > MAX_PATH_DEPTH) {
|
|
41678
41732
|
const message = 'Path depth exceeds maximum limit of %s'.replace('%s', String(MAX_PATH_DEPTH));
|
|
41679
41733
|
throw new FileManagerApiError(message, 'ValidationError');
|
|
41680
41734
|
}
|
|
41735
|
+
const resolvedFolder = await this._resolveFolderByPath(path);
|
|
41736
|
+
if (resolvedFolder) {
|
|
41737
|
+
return resolvedFolder;
|
|
41738
|
+
}
|
|
41681
41739
|
let current = undefined;
|
|
41682
41740
|
for (const part of parts) {
|
|
41683
41741
|
const { files } = await this.getFiles({ folderId: (current === null || current === void 0 ? void 0 : current.id) || '', itemType: 'folder' });
|
|
@@ -41698,8 +41756,13 @@ class DataSourceProxyBase {
|
|
|
41698
41756
|
}
|
|
41699
41757
|
return current;
|
|
41700
41758
|
}
|
|
41701
|
-
getTrashFolder() {
|
|
41702
|
-
|
|
41759
|
+
async getTrashFolder() {
|
|
41760
|
+
const folder = await this._findOrCreateFolderByPath(this._getTrashPath());
|
|
41761
|
+
if (!folder) {
|
|
41762
|
+
const message = "Trash folder path '%s' could not be resolved".replace('%s', this._getTrashPath());
|
|
41763
|
+
throw new FileManagerApiError(message, 'FolderNotFound');
|
|
41764
|
+
}
|
|
41765
|
+
return folder;
|
|
41703
41766
|
}
|
|
41704
41767
|
async getTempFolder() {
|
|
41705
41768
|
var _a;
|
|
@@ -41747,7 +41810,7 @@ class DataSourceProxyBase {
|
|
|
41747
41810
|
this._rootId = this._pathOptions.rootId || DEFAULT_ROOT_ID;
|
|
41748
41811
|
this._enableTrash = this._options.enableTrash === undefined ? true : this._options.enableTrash;
|
|
41749
41812
|
this._validateDuplicates = this._dataProvider.validateDuplicates;
|
|
41750
|
-
//
|
|
41813
|
+
// ViewCacheManager applies resolveViewStrategyOptions in its constructor.
|
|
41751
41814
|
this._cache = new TreeCache(_options.cacheStrategy || {}, (_a = _options.cacheStrategy) === null || _a === void 0 ? void 0 : _a.ttl, (_b = _options.cacheStrategy) === null || _b === void 0 ? void 0 : _b.errorTtl);
|
|
41752
41815
|
// if (!this._dataProvider.deleteItems) {
|
|
41753
41816
|
// this.deleteItems = undefined;
|
|
@@ -42163,23 +42226,7 @@ class DataSourceProxyBase {
|
|
|
42163
42226
|
* Стандартная клиентская сортировка файлов
|
|
42164
42227
|
*/
|
|
42165
42228
|
_defaultClientSideSort(files, sortBy, sortOrder) {
|
|
42166
|
-
return files.sort((a, b) => {
|
|
42167
|
-
let compareResult = 0;
|
|
42168
|
-
switch (sortBy) {
|
|
42169
|
-
case 'name':
|
|
42170
|
-
compareResult = (a.name || '').localeCompare(b.name || '');
|
|
42171
|
-
break;
|
|
42172
|
-
case 'date':
|
|
42173
|
-
compareResult = new Date(a.date || 0).getTime() - new Date(b.date || 0).getTime();
|
|
42174
|
-
break;
|
|
42175
|
-
case 'size':
|
|
42176
|
-
compareResult = (Number(a.size) || 0) - (Number(b.size) || 0);
|
|
42177
|
-
break;
|
|
42178
|
-
default:
|
|
42179
|
-
compareResult = (a.name || '').localeCompare(b.name || '');
|
|
42180
|
-
}
|
|
42181
|
-
return sortOrder === 'desc' ? -compareResult : compareResult;
|
|
42182
|
-
});
|
|
42229
|
+
return files.sort((a, b) => compareFileSystemItems(a, b, { sortBy, sortOrder }));
|
|
42183
42230
|
}
|
|
42184
42231
|
async getFileData(fileOrId, options) {
|
|
42185
42232
|
var _a;
|
|
@@ -43004,11 +43051,11 @@ var PathAwareStorageAdapter_rest = (undefined && undefined.__rest) || function (
|
|
|
43004
43051
|
// @ts-nocheck
|
|
43005
43052
|
|
|
43006
43053
|
|
|
43054
|
+
|
|
43007
43055
|
const PathAwareStorageAdapter_DEFAULT_ROOT_ID = '';
|
|
43008
43056
|
const PathAwareStorageAdapter_DEFAULT_TRASH_PATH = 'Trash';
|
|
43009
|
-
const DEFAULT_TRASH_ID = 'Trash';
|
|
43010
43057
|
class PathAwareStorageAdapter {
|
|
43011
|
-
constructor(_inner, rootPath = PathAwareStorageAdapter_DEFAULT_ROOT_ID, trashId =
|
|
43058
|
+
constructor(_inner, rootPath = PathAwareStorageAdapter_DEFAULT_ROOT_ID, trashId = TRASH_FOLDER_ID, trashPath = PathAwareStorageAdapter_DEFAULT_TRASH_PATH, ensureFolderTrailingSlash = true) {
|
|
43012
43059
|
var _a;
|
|
43013
43060
|
this._inner = _inner;
|
|
43014
43061
|
this.rootPath = rootPath;
|
|
@@ -43082,11 +43129,46 @@ class PathAwareStorageAdapter {
|
|
|
43082
43129
|
return;
|
|
43083
43130
|
return this._inner.clearCache(pathFolder);
|
|
43084
43131
|
}
|
|
43132
|
+
findItemByPath(path) {
|
|
43133
|
+
if (typeof this._inner.findItemByPath !== 'function') {
|
|
43134
|
+
return undefined;
|
|
43135
|
+
}
|
|
43136
|
+
const mapResolved = (resolved, lookupPath, requestPath) => {
|
|
43137
|
+
if (!resolved) {
|
|
43138
|
+
return undefined;
|
|
43139
|
+
}
|
|
43140
|
+
if (resolved.isFolder !== true) {
|
|
43141
|
+
return resolved;
|
|
43142
|
+
}
|
|
43143
|
+
const requestPathClean = normalizeSystemFolderPath(requestPath);
|
|
43144
|
+
const trashPathClean = normalizeSystemFolderPath(this.trashPath);
|
|
43145
|
+
const idPath = requestPathClean === trashPathClean ? this.trashPath : lookupPath;
|
|
43146
|
+
const cleanedIdPath = normalizeSystemFolderPath(idPath);
|
|
43147
|
+
const parentPath = resolved.folderId != null && resolved.folderId !== '' ?
|
|
43148
|
+
normalizeSystemFolderPath(resolved.folderId)
|
|
43149
|
+
: this.rootPath;
|
|
43150
|
+
return Object.assign(Object.assign({}, resolved), { id: this._getOrGenerateId(cleanedIdPath), name: resolved.name, folderId: parentPath === normalizeSystemFolderPath(this.rootPath) ?
|
|
43151
|
+
this.rootPath || ''
|
|
43152
|
+
: this._getOrGenerateId(parentPath), isFolder: true });
|
|
43153
|
+
};
|
|
43154
|
+
const lookupPaths = getTrashFolderLookupCandidates(path, this.trashPath, this.trashId);
|
|
43155
|
+
const resolveCandidates = async () => {
|
|
43156
|
+
for (const lookupPath of lookupPaths) {
|
|
43157
|
+
const resolved = await Promise.resolve(this._inner.findItemByPath(lookupPath));
|
|
43158
|
+
const mapped = mapResolved(resolved, lookupPath, path);
|
|
43159
|
+
if (mapped) {
|
|
43160
|
+
return mapped;
|
|
43161
|
+
}
|
|
43162
|
+
}
|
|
43163
|
+
return undefined;
|
|
43164
|
+
};
|
|
43165
|
+
return resolveCandidates();
|
|
43166
|
+
}
|
|
43085
43167
|
_getOrGenerateId(path) {
|
|
43086
43168
|
if (path === this.rootPath)
|
|
43087
43169
|
return '';
|
|
43088
|
-
const cleanedPath = path
|
|
43089
|
-
if (cleanedPath === this.trashPath
|
|
43170
|
+
const cleanedPath = normalizeSystemFolderPath(path);
|
|
43171
|
+
if (cleanedPath === normalizeSystemFolderPath(this.trashPath))
|
|
43090
43172
|
return this.trashId;
|
|
43091
43173
|
if (this._pathToId.has(cleanedPath))
|
|
43092
43174
|
return this._pathToId.get(cleanedPath);
|
|
@@ -43566,6 +43648,8 @@ var remoteFileFetchPipeline = __webpack_require__(5597);
|
|
|
43566
43648
|
|
|
43567
43649
|
|
|
43568
43650
|
|
|
43651
|
+
|
|
43652
|
+
|
|
43569
43653
|
})();
|
|
43570
43654
|
|
|
43571
43655
|
__webpack_exports__ = __webpack_exports__["default"];
|