fix(ui): загрузка и общий контракт сравнения (refs #8 #7)
deploy-preland / deploy zoomstage.online (push) Successful in 32s

This commit is contained in:
Panfilov Konstantin committed 2026-10-20 01:41:30 +03:00
1 parent 7eaf1c12b0
commit f2e6877013
5 files changed
+38 -13

No files matched your search

+16
View File
@@ -5,6 +5,22 @@
const android = /Android/i.test(navigator.userAgent); const android = /Android/i.test(navigator.userAgent);
let uploadQueue = Promise.resolve(); let uploadQueue = Promise.resolve();
window.ZoomzillaUpload = { window.ZoomzillaUpload = {
// Резерв из пяти точек задаётся CSS: слово и соседняя иконка не двигаются.
renderLoadingLabel(label, dots, text) {
if (!label) return;
let output = label.querySelector('[data-upload-dots]');
if (!output) {
label.textContent = text + ' ';
const slot = document.createElement('span');
slot.className = 'upload-loading-dots';
slot.setAttribute('aria-hidden', 'true');
output = document.createElement('span');
output.dataset.uploadDots = '';
slot.append(output);
label.append(slot);
}
output.textContent = '.'.repeat(dots);
},
bindPicker(form, mainInput, fullAccept, onFiles) { bindPicker(form, mainInput, fullAccept, onFiles) {
const mobile = android || /iPhone|iPad|iPod/i.test(navigator.userAgent) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1); const mobile = android || /iPhone|iPad|iPod/i.test(navigator.userAgent) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1);
if (mobile) form.dataset.mobileUpload = '1'; if (mobile) form.dataset.mobileUpload = '1';
+2 -2
View File
@@ -105,7 +105,7 @@ $basePickerAccept = 'image/jpeg,image/png,image/gif,image/webp,image/bmp,image/a
const uploadButtonDefaultLabel = uploadButtonLabel?.textContent || ''; const uploadButtonDefaultLabel = uploadButtonLabel?.textContent || '';
function renderUploadButton() { function renderUploadButton() {
if (uploadButtonLabel) uploadButtonLabel.textContent = 'Загрузка' + '.'.repeat(uploadDots); window.ZoomzillaUpload.renderLoadingLabel(uploadButtonLabel, uploadDots, <?= json_encode(Yii::t('app', 'Загрузка'), JSON_UNESCAPED_UNICODE) ?>);
} }
function beginUploadPending() { function beginUploadPending() {
@@ -118,7 +118,7 @@ $basePickerAccept = 'image/jpeg,image/png,image/gif,image/webp,image/bmp,image/a
uploadButton.setAttribute('aria-busy', 'true'); uploadButton.setAttribute('aria-busy', 'true');
} }
uploadDotsTimer = window.setInterval(() => { uploadDotsTimer = window.setInterval(() => {
uploadDots = uploadDots === 5 ? 1 : uploadDots + 1; uploadDots = (uploadDots + 1) % 6;
renderUploadButton(); renderUploadButton();
}, 500); }, 500);
return true; return true;
+12 -5
View File
@@ -167,7 +167,7 @@ body {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
padding: 4px 10px; padding: 4px 10px;
font: 700 18px/26px Inter, sans-serif; font: 400 16px/26px Inter, sans-serif;
color: #fff; color: #fff;
backdrop-filter: none; backdrop-filter: none;
-webkit-backdrop-filter: none; -webkit-backdrop-filter: none;
@@ -621,11 +621,13 @@ body {
} }
.navbar-toggler .navbar-toggler-icon { .navbar-toggler .navbar-toggler-icon {
background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 1%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); background-position: center;
background-repeat: no-repeat;
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 1%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
} }
.navbar-toggler:not(.collapsed) .navbar-toggler-icon { .navbar-toggler:not(.collapsed) .navbar-toggler-icon {
background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 1%29' stroke-linecap='round' stroke-width='2' d='M6 6L24 23.9999M6 24L24 6.00015'/%3e%3c/svg%3e"); background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 1%29' stroke-linecap='round' stroke-width='2' d='M6 6L24 23.9999M6 24L24 6.00015'/%3e%3c/svg%3e");
} }
.theme-dark .link-icon { .theme-dark .link-icon {
@@ -1561,6 +1563,11 @@ body {
margin-top: 24px; margin-top: 24px;
} }
/* Пять мест сохраняются и в нулевом кадре анимации загрузки. */
.upload-loading-dots { display: inline-grid; text-align: left; }
.upload-loading-dots::before { content: '.....'; visibility: hidden; grid-area: 1 / 1; }
.upload-loading-dots > span { grid-area: 1 / 1; }
.dropzone-form-button { .dropzone-form-button {
display: inline-flex; display: inline-flex;
padding: 0 24px; padding: 0 24px;
@@ -2810,7 +2817,7 @@ body:not(.theme-dark) .theme-light-hidden {
.index-mobile-fit .image-examples-label { display: none; } .index-mobile-fit .image-examples-label { display: none; }
.index-mobile-fit .image-examples-list { gap: 8px; } .index-mobile-fit .image-examples-list { gap: 8px; }
.index-mobile-fit .image-examples-item { flex-basis: calc((100% - 32px) / 5); min-width: 0; } .index-mobile-fit .image-examples-item { flex-basis: calc((100% - 32px) / 5); min-width: 0; }
.index-mobile-fit #image-compare .icv__label { top: 4px; bottom: auto; margin: 0; font: 600 9px/1.3 Inter, sans-serif; padding: 2px 5px; border: 1px solid rgb(255 255 255 / 65%); border-radius: 5px; background: rgb(67 72 82 / 72%); color: #fff; box-shadow: 0 1px 3px rgb(0 0 0 / 20%); text-shadow: 0 1px 1px rgb(0 0 0 / 35%); white-space: nowrap; } .index-mobile-fit #image-compare .icv__label { top: 4px; bottom: auto; margin: 0; width: 48px; height: 20px; display: flex; align-items: center; justify-content: center; box-sizing: border-box; font: 600 9px/1.3 Inter, sans-serif; padding: 2px 5px; border: 1px solid rgb(255 255 255 / 65%); border-radius: 5px; background: rgb(67 72 82 / 72%); color: #fff; box-shadow: 0 1px 3px rgb(0 0 0 / 20%); text-shadow: 0 1px 1px rgb(0 0 0 / 35%); white-space: nowrap; }
.index-mobile-fit #image-compare .icv__label-before { left: 24px; } .index-mobile-fit #image-compare .icv__label-before { left: 24px; }
.index-mobile-fit #image-compare .icv__label-after { right: 24px; } .index-mobile-fit #image-compare .icv__label-after { right: 24px; }
} }
@@ -2824,7 +2831,7 @@ body:not(.theme-dark) .theme-light-hidden {
.footer-logo img{width:160px;height:auto;max-width:100%;} .footer-logo img{width:160px;height:auto;max-width:100%;}
.header .btn-header{min-height:44px;height:44px;font-size:14px;line-height:20px;padding:0 16px;border-radius:12px;white-space:nowrap;gap:6px;} .header .btn-header{min-height:44px;height:44px;font-size:14px;line-height:20px;padding:0 16px;border-radius:12px;white-space:nowrap;gap:6px;}
@media(max-width:767.98px){ @media(max-width:767.98px){
.header .navbar{height:68px;} .header .navbar-brand img{width:180px;} .header .navbar-toggler{width:30px;height:30px;border-radius:8px;padding:0;} .header .navbar-toggler-icon{width:20px;height:20px;background-size:20px;} .header .navbar{height:68px;} .header .navbar-brand img{width:180px;} .header .navbar-toggler{width:30px;height:30px;border-radius:8px;padding:0;display:inline-flex;align-items:center;justify-content:center;} .header .navbar-toggler-icon{width:20px;height:20px;background-size:20px;display:block;}
.header .navbar-brand{margin-right:8px;} .header .navbar-brand{margin-right:8px;}
.header .btn-header{height:30px;min-height:30px;font-size:12px;padding:0 12px;border-radius:11px;} .header .btn-header{height:30px;min-height:30px;font-size:12px;padding:0 12px;border-radius:11px;}
.header .btn-header svg{width:16px;height:16px;} .header .btn-header svg{width:16px;height:16px;}
+4 -3
View File
@@ -794,7 +794,7 @@ padding-top: 2svh !important;
.index-mobile-fit .image-examples-label { display: none; } .index-mobile-fit .image-examples-label { display: none; }
.index-mobile-fit .image-examples-list { gap: 8px; } .index-mobile-fit .image-examples-list { gap: 8px; }
.index-mobile-fit .image-examples-item { flex-basis: calc((100% - 32px) / 5); min-width: 0; } .index-mobile-fit .image-examples-item { flex-basis: calc((100% - 32px) / 5); min-width: 0; }
.index-mobile-fit #image-compare .icv__label { top: 4px; bottom: auto; margin: 0; font: 600 9px/1.3 Inter, sans-serif; padding: 2px 5px; border: 1px solid rgb(255 255 255 / 65%); border-radius: 5px; background: rgb(67 72 82 / 72%); color: #fff; box-shadow: 0 1px 3px rgb(0 0 0 / 20%); text-shadow: 0 1px 1px rgb(0 0 0 / 35%); white-space: nowrap; } .index-mobile-fit #image-compare .icv__label { top: 4px; bottom: auto; margin: 0; width: 48px; height: 20px; display: flex; align-items: center; justify-content: center; box-sizing: border-box; font: 600 9px/1.3 Inter, sans-serif; padding: 2px 5px; border: 1px solid rgb(255 255 255 / 65%); border-radius: 5px; background: rgb(67 72 82 / 72%); color: #fff; box-shadow: 0 1px 3px rgb(0 0 0 / 20%); text-shadow: 0 1px 1px rgb(0 0 0 / 35%); white-space: nowrap; }
.index-mobile-fit #image-compare .icv__label-before { left: 24px; } .index-mobile-fit #image-compare .icv__label-before { left: 24px; }
.index-mobile-fit #image-compare .icv__label-after { right: 24px; } .index-mobile-fit #image-compare .icv__label-after { right: 24px; }
} }
@@ -808,7 +808,7 @@ padding-top: 2svh !important;
.footer-logo img{width:160px;height:auto;max-width:100%;} .footer-logo img{width:160px;height:auto;max-width:100%;}
.header .btn-header{min-height:44px;height:44px;font-size:14px;line-height:20px;padding:0 16px;border-radius:12px;white-space:nowrap;gap:6px;} .header .btn-header{min-height:44px;height:44px;font-size:14px;line-height:20px;padding:0 16px;border-radius:12px;white-space:nowrap;gap:6px;}
@media(max-width:767.98px){ @media(max-width:767.98px){
.header .navbar{height:68px;} .header .navbar-brand img{width:180px;} .header .navbar-toggler{width:30px;height:30px;border-radius:8px;padding:0;} .header .navbar-toggler-icon{width:20px;height:20px;background-size:20px;} .header .navbar{height:68px;} .header .navbar-brand img{width:180px;} .header .navbar-toggler{width:30px;height:30px;border-radius:8px;padding:0;display:inline-flex;align-items:center;justify-content:center;} .header .navbar-toggler-icon{width:20px;height:20px;background-size:20px;display:block;}
.header .navbar-brand{margin-right:8px;} .header .navbar-brand{margin-right:8px;}
.header .btn-header{height:30px;min-height:30px;font-size:12px;padding:0 12px;border-radius:11px;} .header .btn-header{height:30px;min-height:30px;font-size:12px;padding:0 12px;border-radius:11px;}
.header .btn-header svg{width:16px;height:16px;} .header .btn-header svg{width:16px;height:16px;}
@@ -839,4 +839,5 @@ padding-top: 2svh !important;
.tour-processing #preview, .main-section:has(#process:not([style*="display: none"])) #preview{height:clamp(220px,calc(100svh - 335px),380px)!important;margin-top:16px;} .tour-processing #preview, .main-section:has(#process:not([style*="display: none"])) #preview{height:clamp(220px,calc(100svh - 335px),380px)!important;margin-top:16px;}
} }
@media(max-width:767.98px){.result-download-title{font-size:24px;line-height:1.2;}} @media(max-width:767.98px){.result-download-title{font-size:24px;line-height:1.2;}}
@media (min-width:768px){.image-compare .icv__label{top:10px;width:92px;height:36px;display:flex;align-items:center;justify-content:center;padding:4px 10px;font:700 18px/26px Inter,sans-serif;color:#fff;backdrop-filter:none;-webkit-backdrop-filter:none;background:rgb(0 0 0 / 25%);border:1px solid rgb(255 255 255 / 80%);box-shadow:none;text-shadow:none;}} @media (min-width:768px){.image-compare .icv__label{top:10px;width:92px;height:36px;display:flex;align-items:center;justify-content:center;padding:4px 10px;font:400 16px/26px Inter,sans-serif;color:#fff;backdrop-filter:none;-webkit-backdrop-filter:none;background:rgb(0 0 0 / 25%);border:1px solid rgb(255 255 255 / 80%);box-shadow:none;text-shadow:none;}}
.upload-loading-dots{display:inline-grid;text-align:left;}.upload-loading-dots::before{content:'.....';visibility:hidden;grid-area:1 / 1;}.upload-loading-dots > span{grid-area:1 / 1;}
+4 -3
View File
@@ -16,7 +16,7 @@
.index-mobile-fit .image-examples-label { display: none; } .index-mobile-fit .image-examples-label { display: none; }
.index-mobile-fit .image-examples-list { gap: 8px; } .index-mobile-fit .image-examples-list { gap: 8px; }
.index-mobile-fit .image-examples-item { flex-basis: calc((100% - 32px) / 5); min-width: 0; } .index-mobile-fit .image-examples-item { flex-basis: calc((100% - 32px) / 5); min-width: 0; }
.index-mobile-fit #image-compare .icv__label { top: 4px; bottom: auto; margin: 0; font: 600 9px/1.3 Inter, sans-serif; padding: 2px 5px; border: 1px solid rgb(255 255 255 / 65%); border-radius: 5px; background: rgb(67 72 82 / 72%); color: #fff; box-shadow: 0 1px 3px rgb(0 0 0 / 20%); text-shadow: 0 1px 1px rgb(0 0 0 / 35%); white-space: nowrap; } .index-mobile-fit #image-compare .icv__label { top: 4px; bottom: auto; margin: 0; width: 48px; height: 20px; display: flex; align-items: center; justify-content: center; box-sizing: border-box; font: 600 9px/1.3 Inter, sans-serif; padding: 2px 5px; border: 1px solid rgb(255 255 255 / 65%); border-radius: 5px; background: rgb(67 72 82 / 72%); color: #fff; box-shadow: 0 1px 3px rgb(0 0 0 / 20%); text-shadow: 0 1px 1px rgb(0 0 0 / 35%); white-space: nowrap; }
.index-mobile-fit #image-compare .icv__label-before { left: 24px; } .index-mobile-fit #image-compare .icv__label-before { left: 24px; }
.index-mobile-fit #image-compare .icv__label-after { right: 24px; } .index-mobile-fit #image-compare .icv__label-after { right: 24px; }
} }
@@ -30,7 +30,7 @@
.footer-logo img{width:160px;height:auto;max-width:100%;} .footer-logo img{width:160px;height:auto;max-width:100%;}
.header .btn-header{min-height:44px;height:44px;font-size:14px;line-height:20px;padding:0 16px;border-radius:12px;white-space:nowrap;gap:6px;} .header .btn-header{min-height:44px;height:44px;font-size:14px;line-height:20px;padding:0 16px;border-radius:12px;white-space:nowrap;gap:6px;}
@media(max-width:767.98px){ @media(max-width:767.98px){
.header .navbar{height:68px;} .header .navbar-brand img{width:180px;} .header .navbar-toggler{width:30px;height:30px;border-radius:8px;padding:0;} .header .navbar-toggler-icon{width:20px;height:20px;background-size:20px;} .header .navbar{height:68px;} .header .navbar-brand img{width:180px;} .header .navbar-toggler{width:30px;height:30px;border-radius:8px;padding:0;display:inline-flex;align-items:center;justify-content:center;} .header .navbar-toggler-icon{width:20px;height:20px;background-size:20px;display:block;}
.header .navbar-brand{margin-right:8px;} .header .navbar-brand{margin-right:8px;}
.header .btn-header{height:30px;min-height:30px;font-size:12px;padding:0 12px;border-radius:11px;} .header .btn-header{height:30px;min-height:30px;font-size:12px;padding:0 12px;border-radius:11px;}
.header .btn-header svg{width:16px;height:16px;} .header .btn-header svg{width:16px;height:16px;}
@@ -61,4 +61,5 @@
.tour-processing #preview, .main-section:has(#process:not([style*="display: none"])) #preview{height:clamp(220px,calc(100svh - 335px),380px)!important;margin-top:16px;} .tour-processing #preview, .main-section:has(#process:not([style*="display: none"])) #preview{height:clamp(220px,calc(100svh - 335px),380px)!important;margin-top:16px;}
} }
@media(max-width:767.98px){.result-download-title{font-size:24px;line-height:1.2;}} @media(max-width:767.98px){.result-download-title{font-size:24px;line-height:1.2;}}
@media (min-width:768px){.image-compare .icv__label{top:10px;width:92px;height:36px;display:flex;align-items:center;justify-content:center;padding:4px 10px;font:700 18px/26px Inter,sans-serif;color:#fff;backdrop-filter:none;-webkit-backdrop-filter:none;background:rgb(0 0 0 / 25%);border:1px solid rgb(255 255 255 / 80%);box-shadow:none;text-shadow:none;}} @media (min-width:768px){.image-compare .icv__label{top:10px;width:92px;height:36px;display:flex;align-items:center;justify-content:center;padding:4px 10px;font:400 16px/26px Inter,sans-serif;color:#fff;backdrop-filter:none;-webkit-backdrop-filter:none;background:rgb(0 0 0 / 25%);border:1px solid rgb(255 255 255 / 80%);box-shadow:none;text-shadow:none;}}
.upload-loading-dots{display:inline-grid;text-align:left;}.upload-loading-dots::before{content:'.....';visibility:hidden;grid-area:1 / 1;}.upload-loading-dots > span{grid-area:1 / 1;}