@streamscloud/embeddable 3.3.0 → 3.4.1
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/dist/short-videos/short-video-viewer/cmp.social-interactions.svelte +69 -0
- package/dist/short-videos/short-video-viewer/cmp.social-interactions.svelte.d.ts +10 -0
- package/dist/short-videos/short-video-viewer/index.d.ts +1 -0
- package/dist/short-videos/short-video-viewer/index.js +1 -0
- package/dist/streams/stream-player/cmp.stream-player.svelte +9 -2
- package/dist/streams/stream-player/controls.svelte +53 -94
- package/dist/streams/stream-player/stream-overview.svelte +32 -22
- package/dist/streams/stream-player/ui-manager.svelte.d.ts +3 -2
- package/dist/streams/stream-player/ui-manager.svelte.js +8 -7
- package/dist/ui/player/cmp.player-slider.svelte +34 -16
- package/dist/ui/player/cmp.player-slider.svelte.d.ts +6 -1
- package/package.json +1 -1
- package/dist/streams/stream-player/action-button.svelte +0 -38
- package/dist/streams/stream-player/action-button.svelte.d.ts +0 -10
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
<script lang="ts">import { Icon } from '../../ui/icon';
|
|
2
|
+
import { MediaVolumeManager } from '../../ui/media-playback';
|
|
3
|
+
import IconShoppingBag from '@fluentui/svg-icons/icons/shopping_bag_28_regular.svg?raw';
|
|
4
|
+
import IconSpeaker2 from '@fluentui/svg-icons/icons/speaker_2_28_regular.svg?raw';
|
|
5
|
+
import IconSpeakerMute from '@fluentui/svg-icons/icons/speaker_mute_28_regular.svg?raw';
|
|
6
|
+
let { model, on } = $props();
|
|
7
|
+
const onAttachmentsClicked = () => {
|
|
8
|
+
var _a;
|
|
9
|
+
(_a = on === null || on === void 0 ? void 0 : on.attachmentsClicked) === null || _a === void 0 ? void 0 : _a.call(on);
|
|
10
|
+
};
|
|
11
|
+
const onMuteClicked = () => {
|
|
12
|
+
MediaVolumeManager.isMuted = !MediaVolumeManager.isMuted;
|
|
13
|
+
};
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<div class="short-video-social-interactions" class:short-video-social-interactions--single-action={!(model.products.length || model.ad)}>
|
|
17
|
+
{#if model.products.length || model.ad}
|
|
18
|
+
<button type="button" class="short-video-social-interactions__action" onclick={onAttachmentsClicked}>
|
|
19
|
+
<Icon src={IconShoppingBag} />
|
|
20
|
+
</button>
|
|
21
|
+
{/if}
|
|
22
|
+
|
|
23
|
+
<button type="button" class="short-video-social-interactions__action" onclick={onMuteClicked}>
|
|
24
|
+
{#if MediaVolumeManager.isMuted}
|
|
25
|
+
<Icon src={IconSpeakerMute} />
|
|
26
|
+
{:else}
|
|
27
|
+
<Icon src={IconSpeaker2} />
|
|
28
|
+
{/if}
|
|
29
|
+
</button>
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
<style>@keyframes fadeIn {
|
|
33
|
+
0% {
|
|
34
|
+
opacity: 1;
|
|
35
|
+
}
|
|
36
|
+
50% {
|
|
37
|
+
opacity: 0.4;
|
|
38
|
+
}
|
|
39
|
+
100% {
|
|
40
|
+
opacity: 1;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
.short-video-social-interactions {
|
|
44
|
+
cursor: pointer;
|
|
45
|
+
display: flex;
|
|
46
|
+
flex-direction: column;
|
|
47
|
+
justify-content: center;
|
|
48
|
+
gap: 1.125rem;
|
|
49
|
+
border-radius: 1.25rem;
|
|
50
|
+
border: 0.0625rem solid #1c1c1e;
|
|
51
|
+
background: rgba(0, 0, 0, 0.6);
|
|
52
|
+
padding: 1rem 0.625rem;
|
|
53
|
+
}
|
|
54
|
+
.short-video-social-interactions--single-action {
|
|
55
|
+
width: var(--stream-player--button--size);
|
|
56
|
+
min-width: var(--stream-player--button--size);
|
|
57
|
+
max-width: var(--stream-player--button--size);
|
|
58
|
+
height: var(--stream-player--button--size);
|
|
59
|
+
min-height: var(--stream-player--button--size);
|
|
60
|
+
max-height: var(--stream-player--button--size);
|
|
61
|
+
border-radius: 50%;
|
|
62
|
+
}
|
|
63
|
+
.short-video-social-interactions__action {
|
|
64
|
+
--icon--size: var(--stream-player--icon--size);
|
|
65
|
+
--icon--color: #ffffff;
|
|
66
|
+
display: flex;
|
|
67
|
+
justify-content: center;
|
|
68
|
+
align-items: center;
|
|
69
|
+
}</style>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ShortVideoViewerModel } from '../..';
|
|
2
|
+
type Props = {
|
|
3
|
+
model: ShortVideoViewerModel;
|
|
4
|
+
on?: {
|
|
5
|
+
attachmentsClicked?: () => void;
|
|
6
|
+
};
|
|
7
|
+
};
|
|
8
|
+
declare const Cmp: import("svelte").Component<Props, {}, "">;
|
|
9
|
+
type Cmp = ReturnType<typeof Cmp>;
|
|
10
|
+
export default Cmp;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { default as ShortVideoViewer } from './cmp.short-video-viewer.svelte';
|
|
2
2
|
export { default as ShortVideoAdViewer } from './cmp.ad.svelte';
|
|
3
3
|
export { default as ShortVideoProductViewer } from './cmp.product.svelte';
|
|
4
|
+
export { default as ShortVideoSocialInteractions } from './cmp.social-interactions.svelte';
|
|
4
5
|
export { default as ShortVideoViewerAttachments } from './cmp.attachments.svelte';
|
|
5
6
|
export { default as ShortVideoViewerAttachmentsInline } from './cmp.attachments-inline.svelte';
|
|
6
7
|
export { default as ShortVideoDetails } from './cmp.short-video-details.svelte';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { default as ShortVideoViewer } from './cmp.short-video-viewer.svelte';
|
|
2
2
|
export { default as ShortVideoAdViewer } from './cmp.ad.svelte';
|
|
3
3
|
export { default as ShortVideoProductViewer } from './cmp.product.svelte';
|
|
4
|
+
export { default as ShortVideoSocialInteractions } from './cmp.social-interactions.svelte';
|
|
4
5
|
export { default as ShortVideoViewerAttachments } from './cmp.attachments.svelte';
|
|
5
6
|
export { default as ShortVideoViewerAttachmentsInline } from './cmp.attachments-inline.svelte';
|
|
6
7
|
export { default as ShortVideoDetails } from './cmp.short-video-details.svelte';
|
|
@@ -40,6 +40,7 @@ let isActive = true;
|
|
|
40
40
|
let activityTimeout = null;
|
|
41
41
|
let trackingInterval = null;
|
|
42
42
|
let maxPageIndexViewed = 0;
|
|
43
|
+
let background = $state(null);
|
|
43
44
|
const uiManager = new StreamPlayerUiManager();
|
|
44
45
|
const resetInactivityTimer = () => {
|
|
45
46
|
if (!isActive) {
|
|
@@ -138,6 +139,7 @@ const contentMounted = (node) => {
|
|
|
138
139
|
};
|
|
139
140
|
const onPageActivated = (id) => {
|
|
140
141
|
const page = buffer === null || buffer === void 0 ? void 0 : buffer.loaded.find((x) => x.id === id);
|
|
142
|
+
background = (page === null || page === void 0 ? void 0 : page.cover) || null;
|
|
141
143
|
if (page) {
|
|
142
144
|
AppEventsTracker.trackStreamPageView(id, streamId);
|
|
143
145
|
const currentIndex = buffer === null || buffer === void 0 ? void 0 : buffer.loaded.findIndex((p) => p.id === id);
|
|
@@ -169,7 +171,7 @@ const onProgress = (pageId, videoId, progress) => {
|
|
|
169
171
|
|
|
170
172
|
<svelte:document onkeydown={(e) => handleEsc(e, onPlayerClose)} />
|
|
171
173
|
|
|
172
|
-
<div class="stream-player-container">
|
|
174
|
+
<div class="stream-player-container" style="--background-image: url({background})">
|
|
173
175
|
{#if loading}
|
|
174
176
|
<Loading positionAbsoluteCenter={true} timeout={600} />
|
|
175
177
|
{/if}
|
|
@@ -258,13 +260,18 @@ const onProgress = (pageId, videoId, progress) => {
|
|
|
258
260
|
container-type: inline-size;
|
|
259
261
|
display: flex;
|
|
260
262
|
position: relative;
|
|
261
|
-
background:
|
|
263
|
+
background-color: rgba(0, 0, 0, 0.75);
|
|
264
|
+
background-image: var(--background-image);
|
|
265
|
+
background-size: cover;
|
|
266
|
+
background-blend-mode: multiply;
|
|
262
267
|
}
|
|
263
268
|
|
|
264
269
|
.stream-player {
|
|
265
270
|
display: flex;
|
|
266
271
|
flex: 1;
|
|
267
272
|
padding: 0.625rem 0;
|
|
273
|
+
backdrop-filter: blur(30px);
|
|
274
|
+
position: relative;
|
|
268
275
|
/* Set 'container-type: inline-size;' to reference container*/
|
|
269
276
|
}
|
|
270
277
|
@container (width < 576px) {
|
|
@@ -1,22 +1,14 @@
|
|
|
1
1
|
<script lang="ts">var _a, _b;
|
|
2
|
-
import {
|
|
2
|
+
import { ShortVideoViewerAttachmentsInline, ShortVideoViewerAttachments } from '../../short-videos/short-video-viewer';
|
|
3
|
+
import { ShortVideoSocialInteractions } from '../../short-videos/short-video-viewer/index.js';
|
|
3
4
|
import { StreamElementType } from '../layout/enums';
|
|
4
5
|
import { mapToShortVideoViewerModel } from '../layout/models';
|
|
5
6
|
import { Icon } from '../../ui/icon';
|
|
6
|
-
import { MediaVolumeManager } from '../../ui/media-playback';
|
|
7
|
-
import { default as ActionButton } from './action-button.svelte';
|
|
8
7
|
import { StreamPlayerLocalization } from './stream-player-localization';
|
|
9
|
-
import IconChevronDown from '@fluentui/svg-icons/icons/
|
|
10
|
-
import IconChevronUp from '@fluentui/svg-icons/icons/
|
|
11
|
-
import IconDismiss from '@fluentui/svg-icons/icons/
|
|
12
|
-
import IconFullScreenMaximize from '@fluentui/svg-icons/icons/full_screen_maximize_20_regular.svg?raw';
|
|
13
|
-
import IconPanelRightGallery from '@fluentui/svg-icons/icons/panel_right_gallery_20_regular.svg?raw';
|
|
14
|
-
import IconSpeaker2 from '@fluentui/svg-icons/icons/speaker_2_20_regular.svg?raw';
|
|
15
|
-
import IconSpeakerMute from '@fluentui/svg-icons/icons/speaker_mute_20_regular.svg?raw';
|
|
8
|
+
import IconChevronDown from '@fluentui/svg-icons/icons/chevron_down_28_regular.svg?raw';
|
|
9
|
+
import IconChevronUp from '@fluentui/svg-icons/icons/chevron_up_28_regular.svg?raw';
|
|
10
|
+
import IconDismiss from '@fluentui/svg-icons/icons/dismiss_28_regular.svg?raw';
|
|
16
11
|
let { buffer, uiManager, localization, on } = $props();
|
|
17
|
-
const toggleMuted = () => {
|
|
18
|
-
MediaVolumeManager.isMuted = !MediaVolumeManager.isMuted;
|
|
19
|
-
};
|
|
20
12
|
const shortVideo = $derived(((_a = buffer.current) === null || _a === void 0 ? void 0 : _a.type) === 'short-video' && ((_b = buffer.current) === null || _b === void 0 ? void 0 : _b.shortVideo) ? mapToShortVideoViewerModel(buffer.current.shortVideo) : null);
|
|
21
13
|
const singleWebViewPage = $derived.by(() => {
|
|
22
14
|
var _a;
|
|
@@ -48,15 +40,21 @@ const singleWebViewPage = $derived.by(() => {
|
|
|
48
40
|
}
|
|
49
41
|
return allRenderableElements.length === 1 && allRenderableElements[0].type === StreamElementType.WebView;
|
|
50
42
|
});
|
|
43
|
+
const changeShowShortVideoAttachments = () => {
|
|
44
|
+
uiManager.showShortVideoAttachments = !uiManager.showShortVideoAttachments;
|
|
45
|
+
};
|
|
51
46
|
</script>
|
|
52
47
|
|
|
53
48
|
<div class="stream-player-controls">
|
|
54
49
|
<div class="stream-player-controls__left">
|
|
55
50
|
{#if shortVideo && uiManager.shortVideoDetailsCollapsed && !uiManager.showShortVideoOverlay}
|
|
56
51
|
<div class="stream-player-controls__short-video-overlay">
|
|
57
|
-
|
|
58
|
-
<
|
|
59
|
-
|
|
52
|
+
{#if uiManager.showShortVideoAttachments}
|
|
53
|
+
<div class="stream-player-controls__short-video-attachments-inline">
|
|
54
|
+
<ShortVideoViewerAttachmentsInline model={shortVideo} />
|
|
55
|
+
</div>
|
|
56
|
+
{/if}
|
|
57
|
+
<ShortVideoSocialInteractions model={shortVideo} on={{ attachmentsClicked: changeShowShortVideoAttachments }} />
|
|
60
58
|
</div>
|
|
61
59
|
{/if}
|
|
62
60
|
<div class="stream-player-controls__navigation-buttons" class:stream-player-controls__navigation-buttons--single-web-view-page={singleWebViewPage}>
|
|
@@ -69,7 +67,7 @@ const singleWebViewPage = $derived.by(() => {
|
|
|
69
67
|
</div>
|
|
70
68
|
</div>
|
|
71
69
|
<div class="stream-player-controls__right">
|
|
72
|
-
{#if shortVideo && shortVideo.products}
|
|
70
|
+
{#if shortVideo && shortVideo.products && uiManager.showShortVideoAttachments}
|
|
73
71
|
<div class="stream-player-controls__short-video-attachments">
|
|
74
72
|
<ShortVideoViewerAttachments
|
|
75
73
|
shortVideo={shortVideo}
|
|
@@ -79,40 +77,10 @@ const singleWebViewPage = $derived.by(() => {
|
|
|
79
77
|
}} />
|
|
80
78
|
</div>
|
|
81
79
|
{/if}
|
|
82
|
-
<div class="stream-player-controls__controls">
|
|
83
|
-
{#if shortVideo}
|
|
84
|
-
<ActionButton on={{ click: toggleMuted }}>
|
|
85
|
-
{#if MediaVolumeManager.isMuted}
|
|
86
|
-
<Icon src={IconSpeakerMute} />
|
|
87
|
-
{:else}
|
|
88
|
-
<Icon src={IconSpeaker2} />
|
|
89
|
-
{/if}
|
|
90
|
-
</ActionButton>
|
|
91
|
-
{/if}
|
|
92
|
-
{#if !uiManager.overviewCollapsed}
|
|
93
|
-
<ActionButton on={{ click: () => (uiManager.overviewCollapsed = true) }}>
|
|
94
|
-
<Icon src={IconFullScreenMaximize} />
|
|
95
|
-
</ActionButton>
|
|
96
|
-
{/if}
|
|
97
|
-
</div>
|
|
98
80
|
</div>
|
|
99
81
|
</div>
|
|
100
82
|
|
|
101
|
-
|
|
102
|
-
<ShortVideoDetails
|
|
103
|
-
shortVideo={shortVideo}
|
|
104
|
-
collapsed={uiManager.shortVideoDetailsCollapsed}
|
|
105
|
-
localization={localization.shortVideoDetailsLocalization}
|
|
106
|
-
on={{
|
|
107
|
-
productClick: on.productClick
|
|
108
|
-
}} />
|
|
109
|
-
<div class="toggle-collapsed-button">
|
|
110
|
-
<ActionButton on={{ click: () => (uiManager.shortVideoDetailsCollapsed = !uiManager.shortVideoDetailsCollapsed) }}>
|
|
111
|
-
<Icon src={IconPanelRightGallery} />
|
|
112
|
-
</ActionButton>
|
|
113
|
-
</div>
|
|
114
|
-
{/if}
|
|
115
|
-
<button type="button" class="close-button navigation-button" onclick={on.closePlayer}>
|
|
83
|
+
<button type="button" class="close-button" onclick={on.closePlayer} class:close-button--left={uiManager.overviewCollapsed}>
|
|
116
84
|
<Icon src={IconDismiss} />
|
|
117
85
|
</button>
|
|
118
86
|
|
|
@@ -129,16 +97,30 @@ const singleWebViewPage = $derived.by(() => {
|
|
|
129
97
|
}
|
|
130
98
|
.close-button {
|
|
131
99
|
position: absolute;
|
|
132
|
-
top:
|
|
133
|
-
|
|
100
|
+
top: 0.9375rem;
|
|
101
|
+
left: 15.1875rem;
|
|
134
102
|
z-index: 1;
|
|
103
|
+
width: var(--stream-player--button--size);
|
|
104
|
+
min-width: var(--stream-player--button--size);
|
|
105
|
+
max-width: var(--stream-player--button--size);
|
|
106
|
+
height: var(--stream-player--button--size);
|
|
107
|
+
min-height: var(--stream-player--button--size);
|
|
108
|
+
max-height: var(--stream-player--button--size);
|
|
109
|
+
background-color: rgba(0, 0, 0, 0.6);
|
|
110
|
+
border: 0.0625rem solid #1c1c1e;
|
|
111
|
+
border-radius: 50%;
|
|
112
|
+
text-align: center;
|
|
113
|
+
--icon--color: #ffffff;
|
|
114
|
+
/* Set 'container-type: inline-size;' to reference container*/
|
|
135
115
|
}
|
|
136
|
-
|
|
137
|
-
.
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
116
|
+
.close-button--left {
|
|
117
|
+
left: 0.625rem;
|
|
118
|
+
}
|
|
119
|
+
@container (width < 576px) {
|
|
120
|
+
.close-button {
|
|
121
|
+
left: unset;
|
|
122
|
+
right: 0.625rem;
|
|
123
|
+
}
|
|
142
124
|
}
|
|
143
125
|
|
|
144
126
|
.stream-player-controls {
|
|
@@ -156,8 +138,9 @@ const singleWebViewPage = $derived.by(() => {
|
|
|
156
138
|
.stream-player-controls__left {
|
|
157
139
|
display: flex;
|
|
158
140
|
flex-direction: column;
|
|
159
|
-
gap: 2.
|
|
141
|
+
gap: 2.3125rem;
|
|
160
142
|
justify-content: flex-end;
|
|
143
|
+
align-items: center;
|
|
161
144
|
}
|
|
162
145
|
.stream-player-controls__right {
|
|
163
146
|
flex: 1;
|
|
@@ -165,7 +148,6 @@ const singleWebViewPage = $derived.by(() => {
|
|
|
165
148
|
justify-content: space-between;
|
|
166
149
|
align-items: flex-end;
|
|
167
150
|
flex-direction: column;
|
|
168
|
-
padding-top: 3.75rem;
|
|
169
151
|
/* Set 'container-type: inline-size;' to reference container*/
|
|
170
152
|
}
|
|
171
153
|
@container (width < 9.375rem) {
|
|
@@ -181,16 +163,12 @@ const singleWebViewPage = $derived.by(() => {
|
|
|
181
163
|
flex-direction: column;
|
|
182
164
|
align-items: flex-start;
|
|
183
165
|
justify-content: flex-end;
|
|
184
|
-
--short-video-viewer--interactions--icon--size: var(--stream-player--navigation-button--size);
|
|
185
|
-
--short-video-viewer--interactions--background--color: #1c1c1c;
|
|
186
|
-
--short-video-viewer--interactions--counter--color: #f3f4f6;
|
|
187
|
-
--short-video-viewer--interactions--icon--font-color: #f3f4f6;
|
|
188
166
|
}
|
|
189
167
|
.stream-player-controls__short-video-attachments-inline {
|
|
190
168
|
display: none;
|
|
191
169
|
/* Set 'container-type: inline-size;' to reference container*/
|
|
192
170
|
}
|
|
193
|
-
@container (width < calc(
|
|
171
|
+
@container (width < calc(11rem + 3.75rem)) {
|
|
194
172
|
.stream-player-controls__short-video-attachments-inline {
|
|
195
173
|
display: contents;
|
|
196
174
|
}
|
|
@@ -201,8 +179,8 @@ const singleWebViewPage = $derived.by(() => {
|
|
|
201
179
|
overflow-y: auto;
|
|
202
180
|
scrollbar-color: transparent transparent;
|
|
203
181
|
scrollbar-width: thin;
|
|
204
|
-
width:
|
|
205
|
-
max-width:
|
|
182
|
+
width: 11rem;
|
|
183
|
+
max-width: 11rem;
|
|
206
184
|
/* Set 'container-type: inline-size;' to reference container*/
|
|
207
185
|
}
|
|
208
186
|
.stream-player-controls__short-video-attachments::-webkit-scrollbar {
|
|
@@ -227,7 +205,7 @@ const singleWebViewPage = $derived.by(() => {
|
|
|
227
205
|
.stream-player-controls__short-video-attachments:hover::-webkit-scrollbar-thumb {
|
|
228
206
|
background: var(--custom-scrollbar-color, #7d7d7d);
|
|
229
207
|
}
|
|
230
|
-
@container (width < calc(
|
|
208
|
+
@container (width < calc(11rem + 3.75rem)) {
|
|
231
209
|
.stream-player-controls__short-video-attachments {
|
|
232
210
|
display: none;
|
|
233
211
|
}
|
|
@@ -236,7 +214,6 @@ const singleWebViewPage = $derived.by(() => {
|
|
|
236
214
|
display: flex;
|
|
237
215
|
flex-direction: column;
|
|
238
216
|
gap: 1rem;
|
|
239
|
-
margin-bottom: 0.625rem;
|
|
240
217
|
z-index: 1;
|
|
241
218
|
/* Set 'container-type: inline-size;' to reference container*/
|
|
242
219
|
}
|
|
@@ -245,38 +222,20 @@ const singleWebViewPage = $derived.by(() => {
|
|
|
245
222
|
visibility: hidden;
|
|
246
223
|
}
|
|
247
224
|
}
|
|
248
|
-
.stream-player-controls__navigation-buttons--single-web-view-page {
|
|
249
|
-
/* Set 'container-type: inline-size;' to reference container*/
|
|
250
|
-
}
|
|
251
|
-
@container (width < 6.25rem) {
|
|
252
|
-
.stream-player-controls__navigation-buttons--single-web-view-page {
|
|
253
|
-
visibility: visible;
|
|
254
|
-
position: absolute;
|
|
255
|
-
bottom: var(--stream-player--controls--offset-vertical);
|
|
256
|
-
right: var(--stream-player--controls--offset-horizontal);
|
|
257
|
-
z-index: 1;
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
.stream-player-controls__controls {
|
|
261
|
-
display: flex;
|
|
262
|
-
margin-top: auto;
|
|
263
|
-
gap: 1rem;
|
|
264
|
-
align-self: flex-start;
|
|
265
|
-
}
|
|
266
225
|
|
|
267
226
|
.navigation-button {
|
|
268
|
-
width: var(--stream-player--
|
|
269
|
-
min-width: var(--stream-player--
|
|
270
|
-
max-width: var(--stream-player--
|
|
271
|
-
height: var(--stream-player--
|
|
272
|
-
min-height: var(--stream-player--
|
|
273
|
-
max-height: var(--stream-player--
|
|
274
|
-
background-color:
|
|
275
|
-
border:
|
|
227
|
+
width: var(--stream-player--button--size);
|
|
228
|
+
min-width: var(--stream-player--button--size);
|
|
229
|
+
max-width: var(--stream-player--button--size);
|
|
230
|
+
height: var(--stream-player--button--size);
|
|
231
|
+
min-height: var(--stream-player--button--size);
|
|
232
|
+
max-height: var(--stream-player--button--size);
|
|
233
|
+
background-color: rgba(0, 0, 0, 0.6);
|
|
234
|
+
border: 0.0625rem solid #1c1c1e;
|
|
276
235
|
border-radius: 50%;
|
|
277
236
|
text-align: center;
|
|
278
237
|
--icon--color: #ffffff;
|
|
279
|
-
--icon--
|
|
238
|
+
--icon--size: var(--stream-player--icon--size);
|
|
280
239
|
}
|
|
281
240
|
.navigation-button:disabled {
|
|
282
241
|
opacity: 0.5;
|
|
@@ -5,7 +5,6 @@ import { InfiniteScrolling } from '../../ui/infinite-scrolling';
|
|
|
5
5
|
import { LineClamp } from '../../ui/line-clamp';
|
|
6
6
|
import { ProportionalContainer } from '../../ui/proportional-container';
|
|
7
7
|
import { TimeAgo } from '../../ui/time-ago';
|
|
8
|
-
import { default as ActionButton } from './action-button.svelte';
|
|
9
8
|
import { StreamPlayerLocalization } from './stream-player-localization';
|
|
10
9
|
import IconPanelLeftText from '@fluentui/svg-icons/icons/panel_left_text_20_regular.svg?raw';
|
|
11
10
|
let { model, buffer, activePageId, on, uiManager, localization } = $props();
|
|
@@ -67,11 +66,13 @@ let { model, buffer, activePageId, on, uiManager, localization } = $props();
|
|
|
67
66
|
</div>
|
|
68
67
|
{/if}
|
|
69
68
|
|
|
70
|
-
<
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
69
|
+
<button
|
|
70
|
+
class="toggle-collapsed-button"
|
|
71
|
+
class:toggle-collapsed-button--left={uiManager.overviewCollapsed}
|
|
72
|
+
type="button"
|
|
73
|
+
onclick={() => (uiManager.overviewCollapsed = !uiManager.overviewCollapsed)}>
|
|
74
|
+
<Icon src={IconPanelLeftText} />
|
|
75
|
+
</button>
|
|
75
76
|
|
|
76
77
|
<style>@keyframes fadeIn {
|
|
77
78
|
0% {
|
|
@@ -114,9 +115,21 @@ let { model, buffer, activePageId, on, uiManager, localization } = $props();
|
|
|
114
115
|
|
|
115
116
|
.toggle-collapsed-button {
|
|
116
117
|
position: absolute;
|
|
117
|
-
bottom:
|
|
118
|
-
left:
|
|
118
|
+
bottom: 0.625rem;
|
|
119
|
+
left: 12rem;
|
|
119
120
|
z-index: 1;
|
|
121
|
+
--icon--color: #ffffff;
|
|
122
|
+
--icon--size: 1.25rem;
|
|
123
|
+
/* Set 'container-type: inline-size;' to reference container*/
|
|
124
|
+
}
|
|
125
|
+
.toggle-collapsed-button--left {
|
|
126
|
+
left: 0.625rem;
|
|
127
|
+
}
|
|
128
|
+
@container (width < 576px) {
|
|
129
|
+
.toggle-collapsed-button {
|
|
130
|
+
left: unset;
|
|
131
|
+
right: 0.625rem;
|
|
132
|
+
}
|
|
120
133
|
}
|
|
121
134
|
|
|
122
135
|
.stream-overview-info {
|
|
@@ -124,21 +137,19 @@ let { model, buffer, activePageId, on, uiManager, localization } = $props();
|
|
|
124
137
|
}
|
|
125
138
|
.stream-overview-info__title {
|
|
126
139
|
font-size: 1.125rem;
|
|
127
|
-
line-height: 1.
|
|
128
|
-
font-weight:
|
|
140
|
+
line-height: 1.55;
|
|
141
|
+
font-weight: 600;
|
|
129
142
|
color: #ffffff;
|
|
130
143
|
}
|
|
131
144
|
.stream-overview-info__subtitle {
|
|
132
|
-
font-size: 0.
|
|
133
|
-
line-height: 1.6;
|
|
134
|
-
font-weight: 500;
|
|
135
|
-
letter-spacing: 0.75px;
|
|
145
|
+
font-size: 0.875rem;
|
|
136
146
|
color: #ffffff;
|
|
137
147
|
}
|
|
138
148
|
.stream-overview-info__pages {
|
|
139
149
|
font-size: 0.625rem;
|
|
140
150
|
line-height: 1;
|
|
141
|
-
font-weight:
|
|
151
|
+
font-weight: 400;
|
|
152
|
+
letter-spacing: -0.0125rem;
|
|
142
153
|
color: #999999;
|
|
143
154
|
}
|
|
144
155
|
|
|
@@ -179,7 +190,7 @@ let { model, buffer, activePageId, on, uiManager, localization } = $props();
|
|
|
179
190
|
display: flex;
|
|
180
191
|
flex-direction: column;
|
|
181
192
|
align-items: center;
|
|
182
|
-
gap:
|
|
193
|
+
gap: 1rem;
|
|
183
194
|
/* Set 'container-type: inline-size;' to reference container*/
|
|
184
195
|
}
|
|
185
196
|
@container (width < 576px) {
|
|
@@ -217,9 +228,9 @@ let { model, buffer, activePageId, on, uiManager, localization } = $props();
|
|
|
217
228
|
height: 2rem;
|
|
218
229
|
min-height: 2rem;
|
|
219
230
|
max-height: 2rem;
|
|
220
|
-
--image--rounded--inner--border-
|
|
221
|
-
--image--rounded--outer--border-color: #
|
|
222
|
-
--image--rounded--outer--border-width: 0.
|
|
231
|
+
--image--rounded--inner--border-width: 0;
|
|
232
|
+
--image--rounded--outer--border-color: #f2f2f3;
|
|
233
|
+
--image--rounded--outer--border-width: 0.04325rem;
|
|
223
234
|
}
|
|
224
235
|
.stream-overview-owner__body {
|
|
225
236
|
display: flex;
|
|
@@ -229,11 +240,10 @@ let { model, buffer, activePageId, on, uiManager, localization } = $props();
|
|
|
229
240
|
}
|
|
230
241
|
.stream-overview-owner__name {
|
|
231
242
|
font-size: 0.75rem;
|
|
232
|
-
line-height: 1.2;
|
|
233
243
|
font-weight: 500;
|
|
244
|
+
letter-spacing: -0.015625rem;
|
|
234
245
|
}
|
|
235
246
|
.stream-overview-owner__meta {
|
|
236
247
|
font-size: 0.625rem;
|
|
237
|
-
|
|
238
|
-
font-weight: 500;
|
|
248
|
+
letter-spacing: -0.0125rem;
|
|
239
249
|
}</style>
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
export declare class StreamPlayerUiManager {
|
|
2
2
|
overviewCollapsed: boolean;
|
|
3
3
|
shortVideoDetailsCollapsed: boolean;
|
|
4
|
+
showShortVideoAttachments: boolean;
|
|
4
5
|
globalCssVariables: string;
|
|
5
6
|
isMobileView: boolean;
|
|
6
7
|
showShortVideoOverlay: boolean;
|
|
7
|
-
private readonly
|
|
8
|
-
private readonly navigationButtonSize;
|
|
8
|
+
private readonly buttonSize;
|
|
9
9
|
private readonly controlsOffsetHorizontal;
|
|
10
10
|
private readonly controlsOffsetVertical;
|
|
11
|
+
private readonly iconSize;
|
|
11
12
|
private viewTotalWidth;
|
|
12
13
|
private mainViewColumnWidth;
|
|
13
14
|
updateDimensions: (dimensions: {
|
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
export class StreamPlayerUiManager {
|
|
2
2
|
overviewCollapsed = $state(false);
|
|
3
3
|
shortVideoDetailsCollapsed = $state(true);
|
|
4
|
+
showShortVideoAttachments = $state(true);
|
|
4
5
|
globalCssVariables = $derived.by(() => {
|
|
5
6
|
const values = [
|
|
6
|
-
`--stream-player--
|
|
7
|
-
`--stream-player--navigation-button--size: ${this.navigationButtonSize}px`,
|
|
7
|
+
`--stream-player--button--size: ${this.buttonSize}px`,
|
|
8
8
|
`--stream-player--controls--offset-horizontal: ${this.controlsOffsetHorizontal}px`,
|
|
9
9
|
`--stream-player--controls--offset-vertical: ${this.controlsOffsetVertical}px`,
|
|
10
|
-
`--stream-player--sidebar--available-space: ${(this.viewTotalWidth - this.mainViewColumnWidth) / 2}px
|
|
10
|
+
`--stream-player--sidebar--available-space: ${(this.viewTotalWidth - this.mainViewColumnWidth) / 2}px`,
|
|
11
|
+
`--stream-player--icon--size: ${this.iconSize}px`
|
|
11
12
|
];
|
|
12
13
|
return values.join(';');
|
|
13
14
|
});
|
|
14
15
|
isMobileView = $derived.by(() => this.viewTotalWidth <= 576);
|
|
15
16
|
showShortVideoOverlay = $derived.by(() => (this.viewTotalWidth - this.mainViewColumnWidth) / 2 <= 70);
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
buttonSize = 48;
|
|
18
|
+
controlsOffsetHorizontal = 28;
|
|
19
|
+
controlsOffsetVertical = 28;
|
|
20
|
+
iconSize = 23;
|
|
20
21
|
viewTotalWidth = $state(0);
|
|
21
22
|
mainViewColumnWidth = $state(0);
|
|
22
23
|
updateDimensions = (dimensions) => {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<script lang="ts">import { Utils } from '../../core/utils';
|
|
2
2
|
import { isScrollingPrevented } from './prevent-slider-scroll';
|
|
3
|
-
import { onDestroy, onMount } from 'svelte';
|
|
4
|
-
let { buffer,
|
|
3
|
+
import { onDestroy, onMount, untrack } from 'svelte';
|
|
4
|
+
let { buffer, on, children } = $props();
|
|
5
5
|
let slidesRef;
|
|
6
6
|
let sliderHeight = $state(0);
|
|
7
7
|
let swipeTransition = $state(0);
|
|
8
|
-
let cssAnimationDuration = $state(buffer.animationDuration);
|
|
8
|
+
let cssAnimationDuration = $state(buffer.animationDuration * 0.55);
|
|
9
9
|
let resizeObserver;
|
|
10
10
|
let activeIndex = $state.raw(buffer.currentIndex);
|
|
11
11
|
const actualTransition = $derived(-sliderHeight * activeIndex);
|
|
@@ -17,14 +17,41 @@ const onKeyPress = (e) => {
|
|
|
17
17
|
buffer.loadNext();
|
|
18
18
|
}
|
|
19
19
|
};
|
|
20
|
-
// Notify the parent component that the active item is about to change.
|
|
21
|
-
let active = null;
|
|
22
20
|
$effect(() => {
|
|
23
21
|
if (buffer.currentIndex >= 0 && activeIndex >= 0 && Math.abs(activeIndex - buffer.currentIndex) === 1) {
|
|
24
22
|
slidesRef.classList.toggle('animate', true);
|
|
25
23
|
}
|
|
24
|
+
else if (buffer.currentIndex >= 0 && (Math.abs(activeIndex - buffer.currentIndex) !== 0 || !active)) {
|
|
25
|
+
untrack(() => notifyOnItemChanged());
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
// Notify the parent component that the active item is about to change.
|
|
29
|
+
let active = null;
|
|
30
|
+
$effect(() => {
|
|
31
|
+
if (buffer.currentIndex >= 0 && activeIndex >= 0 && activeIndex !== buffer.currentIndex && on) {
|
|
32
|
+
untrack(() => {
|
|
33
|
+
var _a, _b, _c;
|
|
34
|
+
if (active && ((_a = buffer.current) === null || _a === void 0 ? void 0 : _a.id) !== active.id) {
|
|
35
|
+
(_b = on === null || on === void 0 ? void 0 : on.itemPreDeactivated) === null || _b === void 0 ? void 0 : _b.call(on, { itemId: active.id, loadingNext: buffer.currentIndex > activeIndex });
|
|
36
|
+
}
|
|
37
|
+
const nextItem = buffer.loaded[buffer.currentIndex];
|
|
38
|
+
if (nextItem) {
|
|
39
|
+
(_c = on === null || on === void 0 ? void 0 : on.itemPreActivated) === null || _c === void 0 ? void 0 : _c.call(on, nextItem);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
26
43
|
activeIndex = buffer.currentIndex;
|
|
27
44
|
});
|
|
45
|
+
const notifyOnItemChanged = () => {
|
|
46
|
+
var _a, _b, _c;
|
|
47
|
+
if (active && ((_a = buffer.current) === null || _a === void 0 ? void 0 : _a.id) !== active.id) {
|
|
48
|
+
(_b = on === null || on === void 0 ? void 0 : on.itemDeactivated) === null || _b === void 0 ? void 0 : _b.call(on, active.id);
|
|
49
|
+
}
|
|
50
|
+
active = buffer.current;
|
|
51
|
+
if (active) {
|
|
52
|
+
(_c = on === null || on === void 0 ? void 0 : on.itemActivated) === null || _c === void 0 ? void 0 : _c.call(on, active.id);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
28
55
|
onMount(() => {
|
|
29
56
|
let touchStartY = 0;
|
|
30
57
|
let touchMoveY = 0;
|
|
@@ -37,6 +64,7 @@ onMount(() => {
|
|
|
37
64
|
touchStartTime = Date.now();
|
|
38
65
|
});
|
|
39
66
|
slidesRef.addEventListener('touchmove', (e) => {
|
|
67
|
+
e.preventDefault();
|
|
40
68
|
const newPosition = e.changedTouches[0].screenY;
|
|
41
69
|
const diff = newPosition - touchStartY;
|
|
42
70
|
if ((diff > 0 && buffer.canLoadPrevious) || (diff < 0 && buffer.canLoadNext)) {
|
|
@@ -81,7 +109,7 @@ onMount(() => {
|
|
|
81
109
|
if (e.deltaY < 0 && buffer.canLoadPrevious) {
|
|
82
110
|
buffer.loadPrevious();
|
|
83
111
|
}
|
|
84
|
-
}, buffer.animationDuration));
|
|
112
|
+
}, buffer.animationDuration + 250));
|
|
85
113
|
slidesRef.addEventListener('transitionend', (e) => {
|
|
86
114
|
if (e.target !== slidesRef) {
|
|
87
115
|
return;
|
|
@@ -95,16 +123,6 @@ onMount(() => {
|
|
|
95
123
|
});
|
|
96
124
|
resizeObserver.observe(slidesRef);
|
|
97
125
|
});
|
|
98
|
-
const notifyOnItemChanged = () => {
|
|
99
|
-
var _a, _b, _c;
|
|
100
|
-
if (active && ((_a = buffer.current) === null || _a === void 0 ? void 0 : _a.id) !== active.id) {
|
|
101
|
-
(_b = on === null || on === void 0 ? void 0 : on.itemDeactivated) === null || _b === void 0 ? void 0 : _b.call(on, active.id);
|
|
102
|
-
}
|
|
103
|
-
active = buffer.current;
|
|
104
|
-
if (active) {
|
|
105
|
-
(_c = on === null || on === void 0 ? void 0 : on.itemActivated) === null || _c === void 0 ? void 0 : _c.call(on, active.id);
|
|
106
|
-
}
|
|
107
|
-
};
|
|
108
126
|
onDestroy(() => {
|
|
109
127
|
if (resizeObserver) {
|
|
110
128
|
resizeObserver.disconnect();
|
|
@@ -6,8 +6,13 @@ declare class __sveltets_Render<T extends {
|
|
|
6
6
|
props(): {
|
|
7
7
|
buffer: IPlayerBuffer<T>;
|
|
8
8
|
on?: {
|
|
9
|
-
|
|
9
|
+
itemPreActivated?: ((e: T) => void) | undefined;
|
|
10
|
+
itemPreDeactivated?: ((e: {
|
|
11
|
+
itemId: string;
|
|
12
|
+
loadingNext: boolean;
|
|
13
|
+
}) => void) | undefined;
|
|
10
14
|
itemActivated?: ((e: string) => void) | undefined;
|
|
15
|
+
itemDeactivated?: ((e: string) => void) | undefined;
|
|
11
16
|
} | undefined;
|
|
12
17
|
children: Snippet<[{
|
|
13
18
|
item: T;
|
package/package.json
CHANGED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
<script lang="ts">let { children, on } = $props();
|
|
2
|
-
export {};
|
|
3
|
-
</script>
|
|
4
|
-
|
|
5
|
-
<button type="button" class="action-button" onclick={() => on.click()}>
|
|
6
|
-
{@render children()}
|
|
7
|
-
</button>
|
|
8
|
-
|
|
9
|
-
<style>@keyframes fadeIn {
|
|
10
|
-
0% {
|
|
11
|
-
opacity: 1;
|
|
12
|
-
}
|
|
13
|
-
50% {
|
|
14
|
-
opacity: 0.4;
|
|
15
|
-
}
|
|
16
|
-
100% {
|
|
17
|
-
opacity: 1;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
.action-button {
|
|
21
|
-
--_stream-player--action-button--size: var(--stream-player--action-button--size);
|
|
22
|
-
--_stream-player--action-button--background: var(--action-button-background, #1c1c1c);
|
|
23
|
-
width: var(--_stream-player--action-button--size);
|
|
24
|
-
min-width: var(--_stream-player--action-button--size);
|
|
25
|
-
max-width: var(--_stream-player--action-button--size);
|
|
26
|
-
height: var(--_stream-player--action-button--size);
|
|
27
|
-
min-height: var(--_stream-player--action-button--size);
|
|
28
|
-
max-height: var(--_stream-player--action-button--size);
|
|
29
|
-
display: flex;
|
|
30
|
-
justify-content: center;
|
|
31
|
-
align-items: center;
|
|
32
|
-
line-height: 0;
|
|
33
|
-
background: var(--_stream-player--action-button--background);
|
|
34
|
-
border-radius: 50%;
|
|
35
|
-
--icon--size: 1.25rem;
|
|
36
|
-
z-index: 1;
|
|
37
|
-
color: #ffffff;
|
|
38
|
-
}</style>
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { Snippet } from 'svelte';
|
|
2
|
-
type Props = {
|
|
3
|
-
on: {
|
|
4
|
-
click: () => void;
|
|
5
|
-
};
|
|
6
|
-
children: Snippet;
|
|
7
|
-
};
|
|
8
|
-
declare const ActionButton: import("svelte").Component<Props, {}, "">;
|
|
9
|
-
type ActionButton = ReturnType<typeof ActionButton>;
|
|
10
|
-
export default ActionButton;
|