itube-specs 0.0.1059 → 0.0.1061
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/SITE_UPDATES.md +23 -0
- package/assets/icons/common/arrow-up.svg +1 -0
- package/assets/icons/common/link.svg +1 -0
- package/assets/icons/common/loader.svg +1 -0
- package/assets/icons/common/upload-arrow.svg +1 -0
- package/assets/scss/themes/dark/_theme.scss +58 -2
- package/assets/scss/themes/light/_theme.scss +56 -0
- package/assets/scss/vars/_palette.scss +1 -0
- package/components/layout/burger.vue +16 -8
- package/components/layout/footer-language.vue +4 -1
- package/components/layout/header.vue +129 -112
- package/components/ui/confirm.vue +2 -1
- package/components/ui/link.vue +1 -1
- package/components/upload/combobox.vue +380 -0
- package/components/upload/details.vue +239 -0
- package/components/upload/main.vue +195 -0
- package/components/upload/models.vue +162 -0
- package/components/upload/picker.vue +319 -0
- package/components/upload/progress.vue +477 -0
- package/components/upload/publish.vue +153 -0
- package/components/upload/requirements.vue +179 -0
- package/components/upload/rules.vue +144 -0
- package/components/upload/section.vue +55 -0
- package/components/upload/sent.vue +299 -0
- package/components/upload/spinner.vue +35 -0
- package/components/upload/tags.vue +81 -0
- package/components/view/video.vue +7 -2
- package/composables/use-upload-suggest.ts +40 -0
- package/composables/use-upload.ts +165 -0
- package/i18n/locales/en-US.json +207 -0
- package/package.json +1 -1
- package/pages/upload.vue +19 -0
- package/runtime/constants/upload.ts +61 -0
- package/runtime/index.ts +2 -0
- package/runtime/utils/__tests__/video-data-mark-top-categories.test.ts +19 -0
- package/runtime/utils/video-data-mark-top-categories.ts +21 -0
- package/server/api/videos/get-video-by-id/[id].get.ts +4 -3
- package/server/api/videos/get-video-by-url/[url].get.ts +4 -3
- package/server/utils/top-category-names.ts +14 -0
- package/types/index.d.ts +1 -0
- package/types/raw/raw-video-data.d.ts +3 -1
- package/types/upload.d.ts +40 -0
- package/types/video-data.d.ts +2 -0
- package/utils/upload/__tests__/check-upload-file.test.ts +34 -0
- package/utils/upload/__tests__/format-file-size.test.ts +16 -0
- package/utils/upload/__tests__/format-video-quality.test.ts +19 -0
- package/utils/upload/__tests__/strip-html-tags.test.ts +12 -0
- package/utils/upload/check-upload-file.ts +123 -0
- package/utils/upload/create-idle-upload-checks.ts +11 -0
- package/utils/upload/format-file-size.ts +8 -0
- package/utils/upload/format-video-quality.ts +13 -0
- package/utils/upload/strip-html-tags.ts +3 -0
package/SITE_UPDATES.md
CHANGED
|
@@ -11,6 +11,29 @@
|
|
|
11
11
|
коммиты до бампа); `npm run patch` сам проставит ей номер версии. Формат пункта: что сделать и где,
|
|
12
12
|
кому именно (всем / сайтам с N), что будет, если не сделать.
|
|
13
13
|
|
|
14
|
+
## 0.0.1061 — 2026-11-02
|
|
15
|
+
|
|
16
|
+
- **Всем — решить флаг:** новая страница загрузки видео `/upload` (выбор файла с проверкой в браузере → детали
|
|
17
|
+
во время загрузки → «отправлено» со статусом обработки) и кнопка Upload в шапке (десктоп) — за флагом
|
|
18
|
+
`FeatureUploadEnabled`. API загрузки ещё нет: прогресс и обработка имитируются таймерами. Хотите страницу —
|
|
19
|
+
добавьте `FeatureUploadEnabled: true` в `config/feature-flags.config.ts` (gay-cool-new включил). Без флага
|
|
20
|
+
`/upload` отдаёт 404, кнопки нет, а мёртвая кнопка Upload из бургера (была без действия) пропадает — делать
|
|
21
|
+
ничего не надо.
|
|
22
|
+
- **Всем — к сведению:** новая группа общих ключей `upload_page` (пока только en-US, остальные локали — через CSV
|
|
23
|
+
слоя). У `UiConfirm` необязательный проп `cancelText` (по умолчанию «Cancel», как было).
|
|
24
|
+
|
|
25
|
+
## 0.0.1060 — 2026-11-02
|
|
26
|
+
|
|
27
|
+
- **Сайтам со своими `assets/scss/vars` (hdsex-remaster и др.), срочно:** с 0.0.1059 (лоадер, `0d412182`) без новых
|
|
28
|
+
токенов сборка падает на `Undefined variable`. В `_vars.scss`: `$blur-loading: 4px;` и
|
|
29
|
+
`$blur-loading-spill: $blur-loading * 3;`. В теме: `$loading-bg` (тёмная — `transparent`, светлая —
|
|
30
|
+
`$color-white-75`) и `$video-preview-loading-bg: transparent;`. Образец — hdsex-remaster.
|
|
31
|
+
|
|
32
|
+
- **Всем — к сведению:** в строке чипсов над плеером — только топ-категории ролика (`categories[].isTop`, ставит BFF
|
|
33
|
+
видео по закешированному `/v1/categories/top`, к бекенду — раз в 10 минут на домен/язык/нишу). Нетоповые остаются в
|
|
34
|
+
блоке под описанием и не возвращаются в строку тегом. Топ-список не пришёл — как раньше, все категории. Делать ничего
|
|
35
|
+
не надо.
|
|
36
|
+
|
|
14
37
|
## 0.0.1059 — 2026-10-30
|
|
15
38
|
|
|
16
39
|
- **Всем, срочно к сведению:** с 0.0.1056 блок Live Cams и врезки вебкамов пропали из сеток видео на страницах, которые
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.75" viewBox="0 0 24 24"><path d="m5 12 7-7 7 7M12 19V5"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24"><path d="M9 17H7A5 5 0 0 1 7 7h2M15 7h2a5 5 0 1 1 0 10h-2M8 12h8"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24"><path d="M21 12a9 9 0 1 1-6.219-8.56"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="none" viewBox="0 0 18 18"><path fill="currentColor" d="M9 2.25 4.5 6.75h2.75V12h3.5V6.75h2.75z"/><path stroke="currentColor" stroke-linecap="round" stroke-width="1.5" d="M2.5 14v1.25c0 .97.78 1.75 1.75 1.75h9.5c.97 0 1.75-.78 1.75-1.75V14"/></svg>
|
|
@@ -424,6 +424,8 @@ $niche-switch-text--checked: $color-white;
|
|
|
424
424
|
$footer-language-bg: $color-zinc-800-50;
|
|
425
425
|
$footer-language-bg--hover: $color-zinc-700;
|
|
426
426
|
$footer-language-text: $color-zinc-400;
|
|
427
|
+
$footer-language-text--hover: $color-white;
|
|
428
|
+
$footer-language-badge: $color-zinc-200;
|
|
427
429
|
$footer-language-menu-bg: $color-night;
|
|
428
430
|
$footer-language-menu-border: $color-zinc-800;
|
|
429
431
|
$footer-language-menu-shadow: 0 20px 25px -5px #{$mono-black-25}, 0 8px 10px -6px #{$mono-black-25};
|
|
@@ -456,8 +458,9 @@ $header-burger-icon: $color-zinc-200;
|
|
|
456
458
|
$header-user-icon: $color-zinc-500;
|
|
457
459
|
$header-language-trigger: $color-zinc-400;
|
|
458
460
|
$header-language-trigger--hover: $color-white;
|
|
459
|
-
$header-language-trigger-bg:
|
|
460
|
-
$header-language-trigger-bg--hover:
|
|
461
|
+
$header-language-trigger-bg: $color-zinc-800-50;
|
|
462
|
+
$header-language-trigger-bg--hover: $color-zinc-700;
|
|
463
|
+
$header-language-badge: $color-zinc-200;
|
|
461
464
|
$header-language-menu-bg: $color-night;
|
|
462
465
|
$header-language-menu-border: $color-zinc-800;
|
|
463
466
|
$header-language-menu-shadow: 0 20px 25px -5px #{$mono-black-25}, 0 8px 10px -6px #{$mono-black-25};
|
|
@@ -1214,3 +1217,56 @@ $player-tags-chip-bg: $color-zinc-800;
|
|
|
1214
1217
|
$player-tags-tag-bg: $color-zinc-800-50;
|
|
1215
1218
|
$player-tags-more-text: $color-zinc-400;
|
|
1216
1219
|
$player-tags-more-text--hover: $color-white;
|
|
1220
|
+
|
|
1221
|
+
// ─── Header upload button ───
|
|
1222
|
+
$header-upload-bg: $color-indigo-600-20;
|
|
1223
|
+
$header-upload-border: $color-indigo-500-50;
|
|
1224
|
+
$header-upload-border--hover: $color-indigo-500;
|
|
1225
|
+
$header-upload-text: $color-white;
|
|
1226
|
+
|
|
1227
|
+
// ─── Upload page ───
|
|
1228
|
+
$upload-title: $color-white;
|
|
1229
|
+
$upload-text: $color-zinc-450;
|
|
1230
|
+
$upload-card-bg: $color-zinc-925;
|
|
1231
|
+
$upload-accent: $color-indigo-600;
|
|
1232
|
+
$upload-accent-text: $color-indigo-500;
|
|
1233
|
+
$upload-success: $color-emerald-500;
|
|
1234
|
+
$upload-error: $color-red-500;
|
|
1235
|
+
$upload-icon-bg: $color-zinc-850;
|
|
1236
|
+
$upload-dot: $color-zinc-550;
|
|
1237
|
+
$upload-check-icon: $color-zinc-550;
|
|
1238
|
+
$upload-dropzone-border: $color-zinc-800;
|
|
1239
|
+
$upload-dropzone-border--error: $color-red-500-50;
|
|
1240
|
+
$upload-dropzone-bg--active: $color-zinc-925;
|
|
1241
|
+
$upload-field-bg: $color-zinc-850;
|
|
1242
|
+
$upload-field-text: $color-white;
|
|
1243
|
+
$upload-field-placeholder: $color-zinc-450;
|
|
1244
|
+
$upload-field-border: transparent;
|
|
1245
|
+
$upload-field-border--hover: $color-zinc-800;
|
|
1246
|
+
$upload-field-bg--hover: $color-zinc-800;
|
|
1247
|
+
$upload-chip-bg: $color-zinc-850;
|
|
1248
|
+
$upload-chip-text: $color-white;
|
|
1249
|
+
$upload-chip-icon: $color-zinc-450;
|
|
1250
|
+
$upload-chip-icon--hover: $color-white;
|
|
1251
|
+
$upload-avatar-bg: $color-zinc-925;
|
|
1252
|
+
$upload-avatar-text: $color-zinc-450;
|
|
1253
|
+
$upload-listbox-bg: $color-zinc-850;
|
|
1254
|
+
$upload-listbox-border: $color-zinc-800;
|
|
1255
|
+
$upload-listbox-shadow: 0 12px 32px #{$mono-black-50}, 0 2px 8px #{$mono-black-42};
|
|
1256
|
+
$upload-option-bg--active: $color-zinc-800;
|
|
1257
|
+
$upload-poster-bg: $color-zinc-850;
|
|
1258
|
+
$upload-overlay-bg: $color-black-50;
|
|
1259
|
+
$upload-overlay-text: $color-white;
|
|
1260
|
+
$upload-overlay-subtext: $color-white-75;
|
|
1261
|
+
$upload-badge-bg: $color-black-75;
|
|
1262
|
+
$upload-badge-text: $color-white;
|
|
1263
|
+
$upload-track-bg: $color-black-50;
|
|
1264
|
+
$upload-stripes-from: $color-indigo-600;
|
|
1265
|
+
$upload-stripes-to: $color-indigo-800;
|
|
1266
|
+
$upload-step-line: $color-zinc-700;
|
|
1267
|
+
$upload-step-time: $color-zinc-500;
|
|
1268
|
+
$upload-step-icon: $color-white;
|
|
1269
|
+
$upload-radio-ring: $color-zinc-700;
|
|
1270
|
+
$upload-radio-dot: $color-white;
|
|
1271
|
+
$upload-rules-text: $color-zinc-400;
|
|
1272
|
+
$upload-rules-dot: $color-zinc-600;
|
|
@@ -482,6 +482,8 @@ $niche-switch-text--checked: $color-white;
|
|
|
482
482
|
$footer-language-bg: $color-slate-750;
|
|
483
483
|
$footer-language-bg--hover: $color-slate-700;
|
|
484
484
|
$footer-language-text: $color-white;
|
|
485
|
+
$footer-language-text--hover: $color-white;
|
|
486
|
+
$footer-language-badge: $color-gray-200;
|
|
485
487
|
$footer-language-menu-bg: $color-slate-850;
|
|
486
488
|
$footer-language-menu-border: $color-white-10;
|
|
487
489
|
$footer-language-menu-shadow: 0 20px 25px -5px #{$mono-black-25}, 0 8px 10px -6px #{$mono-black-25};
|
|
@@ -516,6 +518,7 @@ $header-language-trigger: $color-white;
|
|
|
516
518
|
$header-language-trigger--hover: $color-white;
|
|
517
519
|
$header-language-trigger-bg: $color-slate-750;
|
|
518
520
|
$header-language-trigger-bg--hover: $color-slate-700;
|
|
521
|
+
$header-language-badge: $color-gray-200;
|
|
519
522
|
$header-language-menu-bg: $color-slate-850;
|
|
520
523
|
$header-language-menu-border: $color-white-10;
|
|
521
524
|
$header-language-menu-shadow: 0 20px 25px -5px #{$mono-black-25}, 0 8px 10px -6px #{$mono-black-25};
|
|
@@ -1243,3 +1246,56 @@ $player-tags-chip-bg: $color-gray-200;
|
|
|
1243
1246
|
$player-tags-tag-bg: $color-gray-100;
|
|
1244
1247
|
$player-tags-more-text: $color-gray-700;
|
|
1245
1248
|
$player-tags-more-text--hover: $color-gray-900;
|
|
1249
|
+
|
|
1250
|
+
// ─── Header upload button ───
|
|
1251
|
+
$header-upload-bg: $color-indigo-600-20;
|
|
1252
|
+
$header-upload-border: $color-indigo-500-50;
|
|
1253
|
+
$header-upload-border--hover: $color-indigo-500;
|
|
1254
|
+
$header-upload-text: $color-white;
|
|
1255
|
+
|
|
1256
|
+
// ─── Upload page ───
|
|
1257
|
+
$upload-title: $color-gray-900;
|
|
1258
|
+
$upload-text: $color-gray-500;
|
|
1259
|
+
$upload-card-bg: $color-gray-100;
|
|
1260
|
+
$upload-accent: $color-indigo-600;
|
|
1261
|
+
$upload-accent-text: $color-indigo-600;
|
|
1262
|
+
$upload-success: $color-emerald-600;
|
|
1263
|
+
$upload-error: $color-red-500;
|
|
1264
|
+
$upload-icon-bg: $color-gray-200;
|
|
1265
|
+
$upload-dot: $color-gray-400;
|
|
1266
|
+
$upload-check-icon: $color-gray-400;
|
|
1267
|
+
$upload-dropzone-border: $color-gray-300;
|
|
1268
|
+
$upload-dropzone-border--error: $color-red-300;
|
|
1269
|
+
$upload-dropzone-bg--active: $color-gray-100;
|
|
1270
|
+
$upload-field-bg: $color-white;
|
|
1271
|
+
$upload-field-text: $color-gray-900;
|
|
1272
|
+
$upload-field-placeholder: $color-gray-400;
|
|
1273
|
+
$upload-field-border: $color-gray-200;
|
|
1274
|
+
$upload-field-border--hover: $color-gray-300;
|
|
1275
|
+
$upload-field-bg--hover: $color-gray-200;
|
|
1276
|
+
$upload-chip-bg: $color-gray-200;
|
|
1277
|
+
$upload-chip-text: $color-gray-900;
|
|
1278
|
+
$upload-chip-icon: $color-gray-500;
|
|
1279
|
+
$upload-chip-icon--hover: $color-gray-900;
|
|
1280
|
+
$upload-avatar-bg: $color-gray-100;
|
|
1281
|
+
$upload-avatar-text: $color-gray-500;
|
|
1282
|
+
$upload-listbox-bg: $color-white;
|
|
1283
|
+
$upload-listbox-border: $color-gray-200;
|
|
1284
|
+
$upload-listbox-shadow: 0 12px 32px #{$mono-black-15}, 0 2px 8px #{$mono-black-10};
|
|
1285
|
+
$upload-option-bg--active: $color-gray-100;
|
|
1286
|
+
$upload-poster-bg: $color-gray-200;
|
|
1287
|
+
$upload-overlay-bg: $color-black-50;
|
|
1288
|
+
$upload-overlay-text: $color-white;
|
|
1289
|
+
$upload-overlay-subtext: $color-white-75;
|
|
1290
|
+
$upload-badge-bg: $color-black-75;
|
|
1291
|
+
$upload-badge-text: $color-white;
|
|
1292
|
+
$upload-track-bg: $color-black-50;
|
|
1293
|
+
$upload-stripes-from: $color-indigo-600;
|
|
1294
|
+
$upload-stripes-to: $color-indigo-800;
|
|
1295
|
+
$upload-step-line: $color-gray-200;
|
|
1296
|
+
$upload-step-time: $color-gray-400;
|
|
1297
|
+
$upload-step-icon: $color-white;
|
|
1298
|
+
$upload-radio-ring: $color-gray-300;
|
|
1299
|
+
$upload-radio-dot: $color-white;
|
|
1300
|
+
$upload-rules-text: $color-gray-300;
|
|
1301
|
+
$upload-rules-dot: $color-gray-500;
|
|
@@ -133,6 +133,7 @@ $color-red-400: lab(63.7053% 60.745 31.3109);
|
|
|
133
133
|
$color-red-500: lab(55.4814% 75.0732 48.8528);
|
|
134
134
|
$color-red-500-10: color-mix(in oklab, #{$color-red-500} 10%, transparent);
|
|
135
135
|
$color-red-500-20: color-mix(in oklab, #{$color-red-500} 20%, transparent);
|
|
136
|
+
$color-red-500-50: color-mix(in oklab, #{$color-red-500} 50%, transparent);
|
|
136
137
|
$color-red-600: lab(48.4493% 77.4328 61.5452);
|
|
137
138
|
$color-red-600-20: color-mix(in oklab, #{$color-red-600} 20%, transparent);
|
|
138
139
|
$color-red-600-30: color-mix(in oklab, #{$color-red-600} 30%, transparent);
|
|
@@ -33,11 +33,13 @@
|
|
|
33
33
|
<UiAvatar :size="40"/>
|
|
34
34
|
<span class="layout-burger__button-text">{{ data.username }}</span>
|
|
35
35
|
</NuxtLink>
|
|
36
|
-
<
|
|
36
|
+
<component
|
|
37
37
|
v-for="(btn, index) in burgerButtons"
|
|
38
|
+
:is="btn.link ? NuxtLink : 'button'"
|
|
38
39
|
:key="`burger-btn-${index}`"
|
|
40
|
+
:to="btn.link"
|
|
41
|
+
:type="btn.link ? undefined : 'button'"
|
|
39
42
|
class="layout-burger__button"
|
|
40
|
-
type="button"
|
|
41
43
|
@click="btn.action?.(); close()"
|
|
42
44
|
>
|
|
43
45
|
<span class="layout-burger__button-icon">
|
|
@@ -47,7 +49,7 @@
|
|
|
47
49
|
/>
|
|
48
50
|
</span>
|
|
49
51
|
{{ t(btn.label) }}
|
|
50
|
-
</
|
|
52
|
+
</component>
|
|
51
53
|
</div>
|
|
52
54
|
|
|
53
55
|
<nav class="layout-burger__nav">
|
|
@@ -84,6 +86,7 @@
|
|
|
84
86
|
</template>
|
|
85
87
|
|
|
86
88
|
<script setup lang="ts">
|
|
89
|
+
import { NuxtLink } from '#components';
|
|
87
90
|
import { AuthSteps, onBackdropClick, checkDeviceWidth } from '../../runtime';
|
|
88
91
|
import type { IProfileData } from '../../types';
|
|
89
92
|
import { CSS_BREAKPOINTS } from '../../config/css-breakpoints';
|
|
@@ -158,7 +161,9 @@ function logOut() {
|
|
|
158
161
|
useUser(AuthorizationApiService).signOut();
|
|
159
162
|
}
|
|
160
163
|
|
|
161
|
-
const
|
|
164
|
+
const featureFlags = useRuntimeConfig().public.featureFlags;
|
|
165
|
+
|
|
166
|
+
const burgerButtons = computed<{ icon: string, label: string, action?: () => void, link?: string }[]>(() => [
|
|
162
167
|
...isAuthorized.value ? [
|
|
163
168
|
{
|
|
164
169
|
icon: 'logout',
|
|
@@ -178,10 +183,13 @@ const burgerButtons = computed(() => [
|
|
|
178
183
|
action: () => openAuthPopup(AuthSteps.Login),
|
|
179
184
|
},
|
|
180
185
|
],
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
186
|
+
...featureFlags.FeatureUploadEnabled ? [
|
|
187
|
+
{
|
|
188
|
+
icon: 'upload',
|
|
189
|
+
label: 'upload',
|
|
190
|
+
link: generateLink('/upload'),
|
|
191
|
+
}
|
|
192
|
+
] : [],
|
|
185
193
|
]);
|
|
186
194
|
|
|
187
195
|
const router = useRouter();
|
|
@@ -82,13 +82,16 @@ function handler() {
|
|
|
82
82
|
background-color: $footer-language-bg;
|
|
83
83
|
color: $footer-language-text;
|
|
84
84
|
|
|
85
|
-
@include hover(background-color) {
|
|
85
|
+
@include hover(background-color, color) {
|
|
86
|
+
color: $footer-language-text--hover;
|
|
86
87
|
background-color: $footer-language-bg--hover;
|
|
87
88
|
}
|
|
88
89
|
}
|
|
89
90
|
|
|
90
91
|
.layout-footer-language__badge {
|
|
91
92
|
@include locale-badge;
|
|
93
|
+
|
|
94
|
+
color: $footer-language-badge;
|
|
92
95
|
}
|
|
93
96
|
|
|
94
97
|
.layout-footer-language__angle {
|
|
@@ -1,73 +1,95 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<header
|
|
3
|
-
:class="{
|
|
3
|
+
:class="{
|
|
4
|
+
'--burger-open': burgerShow,
|
|
5
|
+
'--no-notifications': !featureFlags.FeatureFollowEnabled,
|
|
6
|
+
}"
|
|
4
7
|
class="layout-header"
|
|
5
8
|
>
|
|
6
9
|
|
|
7
10
|
<SearchMain class="layout-header__search"/>
|
|
8
11
|
|
|
9
|
-
<
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
<div class="layout-header__left">
|
|
13
|
+
<LayoutLogo
|
|
14
|
+
glow
|
|
15
|
+
class="layout-header__logo"
|
|
16
|
+
/>
|
|
13
17
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
v-if="featureFlags.FeatureFollowEnabled"
|
|
20
|
-
class="layout-header__notifications"
|
|
21
|
-
/>
|
|
18
|
+
<LayoutNiche
|
|
19
|
+
class="layout-header__niche _from-sd"
|
|
20
|
+
icon-size="20"
|
|
21
|
+
/>
|
|
22
|
+
</div>
|
|
22
23
|
|
|
23
|
-
<div
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
24
|
+
<div class="layout-header__right">
|
|
25
|
+
<LayoutNotifications
|
|
26
|
+
v-if="featureFlags.FeatureFollowEnabled"
|
|
27
|
+
class="layout-header__notifications"
|
|
28
|
+
/>
|
|
29
|
+
<NuxtLink
|
|
30
|
+
v-if="featureFlags.FeatureUploadEnabled"
|
|
31
|
+
:to="uploadLink"
|
|
32
|
+
:aria-current="isUploadPage ? 'page' : undefined"
|
|
33
|
+
:tabindex="isUploadPage ? -1 : undefined"
|
|
34
|
+
:class="{'--current': isUploadPage}"
|
|
35
|
+
class="layout-header__upload _from-sd"
|
|
33
36
|
>
|
|
34
37
|
<UiIcon
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
name="upload-arrow"
|
|
39
|
+
size="18"
|
|
40
|
+
aria-hidden="true"
|
|
38
41
|
/>
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
42
|
+
{{ $t('upload') }}
|
|
43
|
+
</NuxtLink>
|
|
44
|
+
<div
|
|
45
|
+
ref="languageRef"
|
|
46
|
+
class="layout-header__language _from-sd"
|
|
47
|
+
>
|
|
48
|
+
<button
|
|
49
|
+
:class="{'--open': showLanguage}"
|
|
50
|
+
:aria-label="$t('language')"
|
|
51
|
+
class="layout-header__language-trigger"
|
|
52
|
+
type="button"
|
|
53
|
+
@click="showLanguageMenu"
|
|
54
|
+
>
|
|
55
|
+
<UiIcon
|
|
56
|
+
class="layout-header__language-icon"
|
|
57
|
+
name="earth"
|
|
58
|
+
size="16"
|
|
53
59
|
/>
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
<span class="layout-header__language-badge">{{ locale }}</span>
|
|
61
|
+
<UiIcon
|
|
62
|
+
class="layout-header__language-angle"
|
|
63
|
+
name="angle-down"
|
|
64
|
+
size="12"
|
|
65
|
+
/>
|
|
66
|
+
</button>
|
|
67
|
+
<transition mode="out-in">
|
|
68
|
+
<KeepAlive>
|
|
69
|
+
<LazyLayoutLanguage
|
|
70
|
+
v-if="showLanguage"
|
|
71
|
+
class="layout-header__language-menu"
|
|
72
|
+
icon-size="20"
|
|
73
|
+
@change="closeLanguage"
|
|
74
|
+
/>
|
|
75
|
+
</KeepAlive>
|
|
76
|
+
</transition>
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
<LazyLayoutHeaderUser
|
|
80
|
+
v-if="isAuthorized"
|
|
81
|
+
class="layout-header__user _from-sd"
|
|
82
|
+
/>
|
|
62
83
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
84
|
+
<template v-else>
|
|
85
|
+
<UiBtn
|
|
86
|
+
class="layout-header__sign-up _from-sd"
|
|
87
|
+
theme="primary"
|
|
88
|
+
@click="openAuthPopup(AuthSteps.Registration)"
|
|
89
|
+
>{{ $t('sign_up_button') }}
|
|
90
|
+
</UiBtn>
|
|
91
|
+
</template>
|
|
92
|
+
</div>
|
|
71
93
|
|
|
72
94
|
<button
|
|
73
95
|
:aria-label="$t('show_menu')"
|
|
@@ -95,6 +117,11 @@ import { AuthorizationApiService } from '../../services/api/authorization.servic
|
|
|
95
117
|
|
|
96
118
|
const { locale } = useI18n();
|
|
97
119
|
const featureFlags = useRuntimeConfig().public.featureFlags;
|
|
120
|
+
const route = useRoute();
|
|
121
|
+
const { generateLink } = useGenerateLink();
|
|
122
|
+
|
|
123
|
+
const uploadLink = computed(() => generateLink('/upload'));
|
|
124
|
+
const isUploadPage = computed(() => route.path === uploadLink.value);
|
|
98
125
|
|
|
99
126
|
const burgerShow = ref(false);
|
|
100
127
|
const showLanguage = ref(false);
|
|
@@ -127,7 +154,12 @@ function closeLanguage() {
|
|
|
127
154
|
width: 100%;
|
|
128
155
|
|
|
129
156
|
@include from-br($brkpnt-burger) {
|
|
130
|
-
grid-template-columns:
|
|
157
|
+
grid-template-columns: minmax(max-content, 1fr) minmax(0, $search-max-width) minmax(max-content, 1fr);
|
|
158
|
+
justify-content: stretch;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
@include from-br(md) {
|
|
162
|
+
grid-template-columns: minmax(max-content, 1fr) minmax(0, $search-max-width-md) minmax(max-content, 1fr);
|
|
131
163
|
}
|
|
132
164
|
|
|
133
165
|
/* поиск | лого | колокольчик | бургер — 1fr держит лого по центру */
|
|
@@ -138,34 +170,38 @@ function closeLanguage() {
|
|
|
138
170
|
}
|
|
139
171
|
|
|
140
172
|
.layout-header.--no-notifications {
|
|
141
|
-
@include from-br($brkpnt-burger) {
|
|
142
|
-
grid-template-columns: auto auto minmax(0, 1fr) auto auto;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
173
|
@include to-br($brkpnt-burger) {
|
|
146
174
|
grid-template-columns: auto 1fr auto;
|
|
147
175
|
}
|
|
148
176
|
}
|
|
149
177
|
|
|
150
|
-
.layout-
|
|
178
|
+
.layout-header__left,
|
|
179
|
+
.layout-header__right {
|
|
180
|
+
display: contents;
|
|
181
|
+
|
|
151
182
|
@include from-br($brkpnt-burger) {
|
|
152
|
-
|
|
183
|
+
display: flex;
|
|
184
|
+
align-items: center;
|
|
185
|
+
gap: 12px;
|
|
186
|
+
grid-row: 1;
|
|
153
187
|
}
|
|
154
188
|
}
|
|
155
189
|
|
|
156
|
-
.layout-
|
|
157
|
-
.layout-header.--no-notifications .layout-header__sign-up {
|
|
190
|
+
.layout-header__left {
|
|
158
191
|
@include from-br($brkpnt-burger) {
|
|
159
|
-
grid-column:
|
|
192
|
+
grid-column: 1;
|
|
193
|
+
justify-self: start;
|
|
160
194
|
}
|
|
161
195
|
}
|
|
162
196
|
|
|
163
|
-
.layout-
|
|
197
|
+
.layout-header__right {
|
|
164
198
|
@include from-br($brkpnt-burger) {
|
|
165
|
-
grid-column:
|
|
166
|
-
|
|
199
|
+
grid-column: 3;
|
|
200
|
+
justify-self: end;
|
|
167
201
|
}
|
|
202
|
+
}
|
|
168
203
|
|
|
204
|
+
.layout-header__logo {
|
|
169
205
|
@include to-br($brkpnt-burger) {
|
|
170
206
|
justify-self: center;
|
|
171
207
|
}
|
|
@@ -189,58 +225,46 @@ function closeLanguage() {
|
|
|
189
225
|
}
|
|
190
226
|
}
|
|
191
227
|
|
|
192
|
-
/* Поиск живёт в своей колонке (свободный 1fr между лого и правым блоком), а не оверлеем
|
|
193
|
-
поверх всей строки: так он сжимается вместе с ней и на него ничто не наезжает */
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* Поиск стоит строго по центру ШАПКИ, а не по центру свободного места: он растянут
|
|
197
|
-
* на всю строку сетки и центрирован `justify-self`. Иначе центр уезжал бы к более
|
|
198
|
-
* узкой группе: левая (лого + ниша) и правая (колокольчик, язык, вход) разной ширины.
|
|
199
|
-
*
|
|
200
|
-
* Наезжать при этом не на что: по обе стороны резервируется `--header-side-space`
|
|
201
|
-
* — ширина более широкой группы (сейчас левая: лого + ниша ~340, правая ~290).
|
|
202
|
-
* Считается БЕЗ бокового паддинга шапки, потому что `100%` у поиска — это уже
|
|
203
|
-
* контентная ширина. Не хватило места — поиск сужается, а боковые группы остаются
|
|
204
|
-
* на своих местах. Значение вынесено в переменную: у сайта без переключателя ниш
|
|
205
|
-
* левая группа уже, и он может его уменьшить.
|
|
206
|
-
*/
|
|
207
228
|
.layout-header__search {
|
|
208
|
-
--header-side-space: 358px;
|
|
209
|
-
|
|
210
229
|
@include from-br($brkpnt-burger) {
|
|
211
|
-
grid-column:
|
|
230
|
+
grid-column: 2;
|
|
212
231
|
grid-row: 1;
|
|
213
|
-
justify-self: center;
|
|
214
232
|
width: 100%;
|
|
215
233
|
min-width: 0;
|
|
216
|
-
|
|
217
|
-
// 24px — два column-gap шапки по бокам от поиска
|
|
218
|
-
max-width: min($search-max-width, calc(100% - 2 * var(--header-side-space) - 24px));
|
|
219
234
|
}
|
|
235
|
+
}
|
|
220
236
|
|
|
221
|
-
|
|
222
|
-
|
|
237
|
+
.layout-header__upload {
|
|
238
|
+
@include font-sm;
|
|
239
|
+
|
|
240
|
+
display: flex;
|
|
241
|
+
align-items: center;
|
|
242
|
+
gap: 8px;
|
|
243
|
+
height: 36px;
|
|
244
|
+
padding-inline: 12px;
|
|
245
|
+
color: $header-upload-text;
|
|
246
|
+
background-color: $header-upload-bg;
|
|
247
|
+
border: 1px solid $header-upload-border;
|
|
248
|
+
border-radius: $radius-md;
|
|
249
|
+
|
|
250
|
+
@include hover(border-color) {
|
|
251
|
+
border-color: $header-upload-border--hover;
|
|
223
252
|
}
|
|
224
253
|
}
|
|
225
254
|
|
|
255
|
+
.layout-header__upload.--current {
|
|
256
|
+
cursor: default;
|
|
257
|
+
pointer-events: none;
|
|
258
|
+
}
|
|
259
|
+
|
|
226
260
|
.layout-header__user {
|
|
227
261
|
display: grid;
|
|
228
262
|
place-content: center;
|
|
229
263
|
color: $header-user-icon;
|
|
230
264
|
}
|
|
231
265
|
|
|
232
|
-
.layout-header__user,
|
|
233
|
-
.layout-header__sign-up {
|
|
234
|
-
@include from-br($brkpnt-burger) {
|
|
235
|
-
grid-column: 6;
|
|
236
|
-
grid-row: 1;
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
|
|
240
266
|
.layout-header__niche {
|
|
241
267
|
@include from-br($brkpnt-burger) {
|
|
242
|
-
grid-column: 2;
|
|
243
|
-
grid-row: 1;
|
|
244
268
|
margin-left: 4px;
|
|
245
269
|
}
|
|
246
270
|
}
|
|
@@ -251,18 +275,9 @@ function closeLanguage() {
|
|
|
251
275
|
margin: 0 16px;
|
|
252
276
|
}
|
|
253
277
|
|
|
254
|
-
.layout-header__notifications {
|
|
255
|
-
@include from-br($brkpnt-burger) {
|
|
256
|
-
grid-column: 4;
|
|
257
|
-
grid-row: 1;
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
278
|
.layout-header__language {
|
|
262
279
|
@include from-br($brkpnt-burger) {
|
|
263
280
|
position: relative;
|
|
264
|
-
grid-column: 5;
|
|
265
|
-
grid-row: 1;
|
|
266
281
|
}
|
|
267
282
|
}
|
|
268
283
|
|
|
@@ -287,6 +302,8 @@ function closeLanguage() {
|
|
|
287
302
|
|
|
288
303
|
.layout-header__language-badge {
|
|
289
304
|
@include locale-badge;
|
|
305
|
+
|
|
306
|
+
color: $header-language-badge;
|
|
290
307
|
}
|
|
291
308
|
|
|
292
309
|
.layout-header__language-angle {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
size="l"
|
|
24
24
|
theme="secondary"
|
|
25
25
|
@click="emit('update:modelValue', false)"
|
|
26
|
-
>{{ $t('cancel') }}
|
|
26
|
+
>{{ cancelText || $t('cancel') }}
|
|
27
27
|
</UiBtn>
|
|
28
28
|
<UiBtn
|
|
29
29
|
:disabled="loading"
|
|
@@ -44,6 +44,7 @@ defineProps<{
|
|
|
44
44
|
modelValue: boolean
|
|
45
45
|
title: string
|
|
46
46
|
confirmText: string
|
|
47
|
+
cancelText?: string
|
|
47
48
|
loading?: boolean
|
|
48
49
|
transparentBackdrop?: boolean
|
|
49
50
|
}>();
|