itube-specs 0.0.892 → 0.0.895
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/assets/scss/themes/dark/_theme.scss +18 -1
- package/assets/scss/themes/light/_theme.scss +18 -1
- package/components/card/dropdown/trigger.vue +9 -5
- package/components/card/history.vue +4 -3
- package/components/card/video/index.vue +21 -8
- package/components/library/feed.vue +340 -0
- package/components/library/follows.vue +147 -0
- package/components/ui/expand-row.vue +21 -2
- package/components/ui/video-preview.vue +62 -0
- package/package.json +1 -1
- package/pages/library/categories.vue +61 -0
- package/pages/library/channels.vue +62 -0
- package/pages/library/index.vue +366 -0
- package/pages/library/models.vue +63 -0
- package/pages/library.vue +1 -361
- package/stubs/history.ts +17 -14
- package/stubs/library-follows.ts +135 -0
- package/stubs/videos.ts +29 -0
- package/types/index.d.ts +1 -0
- package/types/library-feed.d.ts +34 -0
- package/components/card/preview.vue +0 -139
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
<!-- Видео-предпросмотр (автоплей) поверх постера карточки видео + индикатор загрузки -->
|
|
2
|
-
<template>
|
|
3
|
-
<span class="card-preview">
|
|
4
|
-
<video
|
|
5
|
-
ref="videoRef"
|
|
6
|
-
:src="url"
|
|
7
|
-
:class="{'--playing': isPlaying}"
|
|
8
|
-
class="card-preview__video"
|
|
9
|
-
loop
|
|
10
|
-
muted
|
|
11
|
-
autoplay
|
|
12
|
-
playsinline
|
|
13
|
-
@loadedmetadata="updateProgress"
|
|
14
|
-
@progress="updateProgress"
|
|
15
|
-
@playing="onPlaying"
|
|
16
|
-
@waiting="onWaiting"
|
|
17
|
-
@pause="isPlaying = false"
|
|
18
|
-
/>
|
|
19
|
-
<span
|
|
20
|
-
:class="{'--done': isLoaded}"
|
|
21
|
-
:style="{'--preview-progress': isLoaded ? 1 : progress}"
|
|
22
|
-
class="card-preview__loader"
|
|
23
|
-
/>
|
|
24
|
-
</span>
|
|
25
|
-
</template>
|
|
26
|
-
|
|
27
|
-
<script setup lang="ts">
|
|
28
|
-
defineProps<{
|
|
29
|
-
url: string
|
|
30
|
-
}>();
|
|
31
|
-
|
|
32
|
-
/** Стартовая ширина полосы: видна сразу по ховеру/касанию, не дожидаясь первого скачанного куска файла. */
|
|
33
|
-
const MIN_PROGRESS = 0.05;
|
|
34
|
-
/** Докуда полоса подползает сама, пока нет данных о реальной загрузке. */
|
|
35
|
-
const CREEP_LIMIT = 0.45;
|
|
36
|
-
const CREEP_INTERVAL = 150;
|
|
37
|
-
const CREEP_STEP = 0.18;
|
|
38
|
-
|
|
39
|
-
const videoRef = ref<HTMLVideoElement | null>(null);
|
|
40
|
-
const isPlaying = ref(false);
|
|
41
|
-
const isLoaded = ref(false);
|
|
42
|
-
const progress = ref(MIN_PROGRESS);
|
|
43
|
-
|
|
44
|
-
let creepTimer: ReturnType<typeof setInterval> | null = null;
|
|
45
|
-
|
|
46
|
-
function stopCreep() {
|
|
47
|
-
if (creepTimer) clearInterval(creepTimer);
|
|
48
|
-
creepTimer = null;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/** Имитация ожидания: пока идёт коннект к CDN и реального прогресса нет, полоса замедляясь подползает к CREEP_LIMIT. */
|
|
52
|
-
function startCreep() {
|
|
53
|
-
creepTimer = setInterval(() => {
|
|
54
|
-
const next = progress.value + (CREEP_LIMIT - progress.value) * CREEP_STEP;
|
|
55
|
-
|
|
56
|
-
if (CREEP_LIMIT - next < CREEP_STEP / 100) {
|
|
57
|
-
stopCreep();
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
progress.value = next;
|
|
62
|
-
}, CREEP_INTERVAL);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/** Доля скачанного файла превью: правый край последнего буферизованного отрезка к общей длительности. */
|
|
66
|
-
function updateProgress() {
|
|
67
|
-
const video = videoRef.value;
|
|
68
|
-
if (!video || !video.buffered.length || !Number.isFinite(video.duration)) return;
|
|
69
|
-
|
|
70
|
-
const loaded = video.buffered.end(video.buffered.length - 1) / video.duration;
|
|
71
|
-
if (loaded > 0) stopCreep();
|
|
72
|
-
|
|
73
|
-
progress.value = Math.max(loaded, progress.value);
|
|
74
|
-
if (loaded >= 1) isLoaded.value = true;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function onPlaying() {
|
|
78
|
-
stopCreep();
|
|
79
|
-
isPlaying.value = true;
|
|
80
|
-
isLoaded.value = true;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/** Буферизация на середине: возвращаем постер и полосу, она продолжит с реально скачанного места. */
|
|
84
|
-
function onWaiting() {
|
|
85
|
-
isPlaying.value = false;
|
|
86
|
-
isLoaded.value = false;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
onMounted(() => {
|
|
90
|
-
startCreep();
|
|
91
|
-
|
|
92
|
-
const video = videoRef.value;
|
|
93
|
-
if (!video) return;
|
|
94
|
-
|
|
95
|
-
video.muted = true;
|
|
96
|
-
video.play().catch(() => {
|
|
97
|
-
isPlaying.value = false;
|
|
98
|
-
});
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
onBeforeUnmount(stopCreep);
|
|
102
|
-
</script>
|
|
103
|
-
|
|
104
|
-
<style lang="scss">
|
|
105
|
-
$loader-height: 4px;
|
|
106
|
-
|
|
107
|
-
.card-preview {
|
|
108
|
-
position: absolute;
|
|
109
|
-
inset: 0;
|
|
110
|
-
z-index: $z-index-plus;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
.card-preview__video {
|
|
114
|
-
width: 100%;
|
|
115
|
-
height: 100%;
|
|
116
|
-
object-fit: cover;
|
|
117
|
-
opacity: 0;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/* Пока автоплей не стартовал, браузер рисует поверх видео нативную кнопку плей — держим элемент невидимым */
|
|
121
|
-
.card-preview__video.--playing {
|
|
122
|
-
opacity: 1;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
.card-preview__loader {
|
|
126
|
-
position: absolute;
|
|
127
|
-
inset: 0 0 auto;
|
|
128
|
-
height: $loader-height;
|
|
129
|
-
background: $card-preview-loader-bg;
|
|
130
|
-
transform: scaleX(var(--preview-progress, 0));
|
|
131
|
-
transform-origin: left center;
|
|
132
|
-
transition: var(--transition) transform, var(--transition) var(--default-transition-duration) opacity;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/* Догрузилось или пошло воспроизведение — полоса доезжает до конца и только потом гаснет */
|
|
136
|
-
.card-preview__loader.--done {
|
|
137
|
-
opacity: 0;
|
|
138
|
-
}
|
|
139
|
-
</style>
|