@streamscloud/embeddable 6.3.3 → 6.3.4
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.attachments-inline.svelte +5 -63
- package/dist/short-videos/short-video-viewer/cmp.attachments-inline.svelte.d.ts +0 -4
- package/dist/short-videos/short-video-viewer/cmp.attachments.svelte +2 -9
- package/dist/short-videos/short-video-viewer/cmp.attachments.svelte.d.ts +0 -1
- package/dist/short-videos/short-video-viewer/cmp.short-video-viewer.svelte +1 -6
- package/dist/short-videos/short-video-viewer/cmp.short-video-viewer.svelte.d.ts +0 -2
- package/dist/short-videos/short-videos-player/cmp.short-videos-player.svelte +1 -2
- package/dist/short-videos/short-videos-player/index.d.ts +2 -2
- package/dist/short-videos/short-videos-player/index.js +0 -6
- package/dist/short-videos/short-videos-player/internal-short-video-player-provider.d.ts +1 -0
- package/dist/short-videos/short-videos-player/internal-short-video-player-provider.js +15 -5
- package/dist/short-videos/short-videos-player/short-videos-player-view.svelte +2 -13
- package/dist/short-videos/short-videos-player/types.d.ts +0 -8
- package/dist/streams/layout/cmp.slot-content.svelte +2 -28
- package/dist/streams/layout/cmp.slot-content.svelte.d.ts +0 -1
- package/dist/streams/stream-page-viewer/cmp.stream-page-viewer.svelte.d.ts +0 -1
- package/dist/streams/stream-player/controls.svelte +1 -2
- package/dist/streams/stream-player/controls.svelte.d.ts +0 -1
- package/dist/streams/stream-player/internal-stream-analytics-handler.d.ts +1 -5
- package/dist/streams/stream-player/internal-stream-analytics-handler.js +1 -5
- package/dist/streams/stream-player/stream-player.svelte +3 -19
- package/dist/streams/stream-player/types.d.ts +0 -4
- package/package.json +2 -2
- package/dist/short-videos/short-video-viewer/cmp.short-video-product-card.svelte +0 -26
- package/dist/short-videos/short-video-viewer/cmp.short-video-product-card.svelte.d.ts +0 -17
- package/dist/short-videos/short-videos-player/internal-short-video-analytics-handler.d.ts +0 -8
- package/dist/short-videos/short-videos-player/internal-short-video-analytics-handler.js +0 -13
- package/dist/streams/cmp.stream-product-card.svelte +0 -25
- package/dist/streams/cmp.stream-product-card.svelte.d.ts +0 -17
|
@@ -1,76 +1,18 @@
|
|
|
1
1
|
<script lang="ts">import { Icon, IconColor } from '../../ui/icon';
|
|
2
2
|
import { ImageRounded } from '../../ui/image';
|
|
3
3
|
import IconTargetArrow from '@fluentui/svg-icons/icons/target_arrow_20_regular.svg?raw';
|
|
4
|
-
|
|
5
|
-
let { model, on } = $props();
|
|
4
|
+
let { model } = $props();
|
|
6
5
|
const attachmentsToShow = $derived.by(() => {
|
|
7
|
-
const products = model.products
|
|
8
|
-
|
|
9
|
-
.map((p) => ({
|
|
10
|
-
isAd: false,
|
|
11
|
-
image: p.image,
|
|
12
|
-
link: p.link,
|
|
13
|
-
productId: p.id
|
|
14
|
-
}));
|
|
15
|
-
const ads = (model.ad ? [model.ad] : [])
|
|
16
|
-
.filter((a) => !!a.image)
|
|
17
|
-
.map((a) => {
|
|
18
|
-
var _a;
|
|
19
|
-
return ({
|
|
20
|
-
isAd: true,
|
|
21
|
-
image: a.image,
|
|
22
|
-
link: ((_a = a.ctaButton) === null || _a === void 0 ? void 0 : _a.url) || null,
|
|
23
|
-
productId: null
|
|
24
|
-
});
|
|
25
|
-
});
|
|
6
|
+
const products = model.products.filter((p) => !!p.image).map((p) => ({ isAd: false, image: p.image, link: p.link }));
|
|
7
|
+
const ads = (model.ad ? [model.ad] : []).filter((a) => !!a.image).map((a) => { var _a; return ({ isAd: true, image: a.image, link: ((_a = a.ctaButton) === null || _a === void 0 ? void 0 : _a.url) || null }); });
|
|
26
8
|
return [...products, ...ads];
|
|
27
9
|
});
|
|
28
|
-
const handleAttachmentClick = (attachment) => {
|
|
29
|
-
if (attachment.productId && (on === null || on === void 0 ? void 0 : on.productClick)) {
|
|
30
|
-
on.productClick(attachment.productId);
|
|
31
|
-
}
|
|
32
|
-
if (attachment.link) {
|
|
33
|
-
window.open(attachment.link, '_blank');
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
let attachmentElements = {};
|
|
37
|
-
onMount(() => {
|
|
38
|
-
if (on === null || on === void 0 ? void 0 : on.productImpression) {
|
|
39
|
-
// Track product impressions when they come into view
|
|
40
|
-
const observer = new IntersectionObserver((entries) => {
|
|
41
|
-
entries.forEach((entry) => {
|
|
42
|
-
if (entry.isIntersecting && entry.intersectionRatio >= 0.5) {
|
|
43
|
-
const productId = entry.target.getAttribute('data-product-id');
|
|
44
|
-
if (productId) {
|
|
45
|
-
on.productImpression(productId, model.id);
|
|
46
|
-
observer.unobserve(entry.target); // Only track once per session
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
}, { threshold: 0.5 });
|
|
51
|
-
// Observe all product elements
|
|
52
|
-
Object.entries(attachmentElements).forEach(([key, element]) => {
|
|
53
|
-
if (element && key.startsWith('product-')) {
|
|
54
|
-
observer.observe(element);
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
return () => {
|
|
58
|
-
observer.disconnect();
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
10
|
</script>
|
|
63
11
|
|
|
64
12
|
<div class="attachments-inline-container">
|
|
65
13
|
<div class="attachments-inline">
|
|
66
|
-
{#each attachmentsToShow as attachment
|
|
67
|
-
<div
|
|
68
|
-
class="attachments-inline__item"
|
|
69
|
-
onclick={() => handleAttachmentClick(attachment)}
|
|
70
|
-
onkeydown={() => {}}
|
|
71
|
-
role="none"
|
|
72
|
-
bind:this={attachmentElements[attachment.productId ? `product-${attachment.productId}` : `ad-${index}`]}
|
|
73
|
-
data-product-id={attachment.productId || undefined}>
|
|
14
|
+
{#each attachmentsToShow as attachment (attachment)}
|
|
15
|
+
<div class="attachments-inline__item" onclick={() => attachment.link && window.open(attachment.link, '_blank')} onkeydown={() => {}} role="none">
|
|
74
16
|
<ImageRounded src={attachment.image} alt="" />
|
|
75
17
|
{#if attachment.isAd}
|
|
76
18
|
<div class="attachments-inline__item-icon">
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import type { ShortVideoViewerModel } from './types';
|
|
2
2
|
type Props = {
|
|
3
3
|
model: ShortVideoViewerModel;
|
|
4
|
-
on?: {
|
|
5
|
-
productClick?: (productId: string) => void;
|
|
6
|
-
productImpression?: (productId: string, videoId: string) => void;
|
|
7
|
-
};
|
|
8
4
|
};
|
|
9
5
|
declare const Cmp: import("svelte").Component<Props, {}, "">;
|
|
10
6
|
type Cmp = ReturnType<typeof Cmp>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts">import { AdCard } from '../../ads/ad-card';
|
|
2
|
-
import {
|
|
2
|
+
import { ProductCard } from '../../products/product-card';
|
|
3
3
|
import { ShortVideoAttachmentsLocalization } from './short-video-attachments-localization';
|
|
4
4
|
import {} from './types';
|
|
5
5
|
let { shortVideo, localization: localizationInit = 'en', on } = $props();
|
|
@@ -14,14 +14,7 @@ const localization = $derived(new ShortVideoAttachmentsLocalization(localization
|
|
|
14
14
|
|
|
15
15
|
{#if shortVideo.products.length}
|
|
16
16
|
{#each shortVideo.products as product (product.id)}
|
|
17
|
-
<
|
|
18
|
-
product={product}
|
|
19
|
-
videoId={shortVideo.id}
|
|
20
|
-
localization={localization.productLocalization}
|
|
21
|
-
on={{
|
|
22
|
-
productClick: on?.productClick,
|
|
23
|
-
impression: on?.productImpression
|
|
24
|
-
}} />
|
|
17
|
+
<ProductCard product={product} localization={localization.productLocalization} on={on} />
|
|
25
18
|
{/each}
|
|
26
19
|
{/if}
|
|
27
20
|
</div>
|
|
@@ -6,7 +6,6 @@ type Props = {
|
|
|
6
6
|
localization?: IShortVideoAttachmentsLocalization | Locale;
|
|
7
7
|
on?: {
|
|
8
8
|
productClick?: (productId: string) => void;
|
|
9
|
-
productImpression?: (productId: string, videoId: string) => void;
|
|
10
9
|
};
|
|
11
10
|
};
|
|
12
11
|
declare const Cmp: import("svelte").Component<Props, {}, "">;
|
|
@@ -36,12 +36,7 @@ $effect(() => {
|
|
|
36
36
|
|
|
37
37
|
<div class="short-video-viewer__actions-panel" class:short-video-viewer__actions-panel--inside-frame={true}>
|
|
38
38
|
{#if uiManager.showAttachments}
|
|
39
|
-
<AttachmentsInline
|
|
40
|
-
model={model}
|
|
41
|
-
on={{
|
|
42
|
-
productClick: on?.productClick,
|
|
43
|
-
productImpression: on?.productImpression
|
|
44
|
-
}} />
|
|
39
|
+
<AttachmentsInline model={model} />
|
|
45
40
|
{/if}
|
|
46
41
|
{#if uiManager.showControls}
|
|
47
42
|
<ShortVideoControls model={model} socialInteractionsHandler={socialInteractionsHandler} on={{ attachmentsClicked: uiManager.toggleEnableAttachments }} />
|
|
@@ -10,8 +10,6 @@ type Props = {
|
|
|
10
10
|
localization?: IShortVideoViewerLocalization | Locale;
|
|
11
11
|
on?: {
|
|
12
12
|
progress?: (progress: number) => void;
|
|
13
|
-
productClick?: (productId: string) => void;
|
|
14
|
-
productImpression?: (productId: string, videoId: string) => void;
|
|
15
13
|
};
|
|
16
14
|
};
|
|
17
15
|
declare const Cmp: import("svelte").Component<Props, {}, "">;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">import { MediaCenter, MediaCenterMode } from '../../media-center/media-center';
|
|
2
2
|
import { createShadowRoot } from '../../ui/shadow-dom';
|
|
3
3
|
import { mount, unmount } from 'svelte';
|
|
4
|
-
let { dataProvider, socialInteractionsHandler, localization, showStreamsCloudWatermark, disableBackground,
|
|
4
|
+
let { dataProvider, socialInteractionsHandler, localization, showStreamsCloudWatermark, disableBackground, on, mediaCenterDataProvider } = $props();
|
|
5
5
|
const initHost = (node) => {
|
|
6
6
|
const shadowRoot = createShadowRoot(node);
|
|
7
7
|
const mounted = mount(MediaCenter, {
|
|
@@ -16,7 +16,6 @@ const initHost = (node) => {
|
|
|
16
16
|
disableBackground,
|
|
17
17
|
localization,
|
|
18
18
|
showStreamsCloudWatermark,
|
|
19
|
-
analyticsHandler,
|
|
20
19
|
on
|
|
21
20
|
}
|
|
22
21
|
}
|
|
@@ -3,9 +3,9 @@ import type { ShortVideoViewerModel } from '../short-video-viewer';
|
|
|
3
3
|
import type { IPlayerItemsProvider } from '../../ui/player';
|
|
4
4
|
import { default as ShortVideosPlayer } from './cmp.short-videos-player.svelte';
|
|
5
5
|
import type { IShortVideosPlayerLocalization } from './short-videos-player-localization';
|
|
6
|
-
import { type PlayerSettings
|
|
6
|
+
import { type PlayerSettings } from './types';
|
|
7
7
|
export { ShortVideosPlayer };
|
|
8
|
-
export type { IShortVideosPlayerLocalization, IMediaCenterDataProvider, IPlayerItemsProvider
|
|
8
|
+
export type { IShortVideosPlayerLocalization, IMediaCenterDataProvider, IPlayerItemsProvider };
|
|
9
9
|
/**
|
|
10
10
|
* Opens the short videos player modal.
|
|
11
11
|
*
|
|
@@ -3,7 +3,6 @@ import { InternalMediaCenterDataProvider } from '../../media-center/data-provide
|
|
|
3
3
|
import { MediaCenter, MediaCenterMode } from '../../media-center/media-center';
|
|
4
4
|
import { ModalShadowHost } from '../../ui/shadow-dom';
|
|
5
5
|
import { default as ShortVideosPlayer } from './cmp.short-videos-player.svelte';
|
|
6
|
-
import { InternalShortVideoAnalyticsHandler } from './internal-short-video-analytics-handler';
|
|
7
6
|
import { InternalShortVideoPlayerProvider } from './internal-short-video-player-provider';
|
|
8
7
|
import {} from './types';
|
|
9
8
|
import { mount, unmount } from 'svelte';
|
|
@@ -22,10 +21,6 @@ export function openShortVideosPlayer(init) {
|
|
|
22
21
|
if (!mediaCenterDataProvider && init.mediaPageId) {
|
|
23
22
|
mediaCenterDataProvider = new InternalMediaCenterDataProvider(init.mediaPageId, graphqlOrigin);
|
|
24
23
|
}
|
|
25
|
-
let analyticsHandler = init.analyticsHandler;
|
|
26
|
-
if (!analyticsHandler && !init.shortVideosProvider && initiator) {
|
|
27
|
-
analyticsHandler = new InternalShortVideoAnalyticsHandler(graphqlOrigin);
|
|
28
|
-
}
|
|
29
24
|
const shadowHost = new ModalShadowHost();
|
|
30
25
|
const mounted = mount(MediaCenter, {
|
|
31
26
|
target: shadowHost.shadowRoot,
|
|
@@ -39,7 +34,6 @@ export function openShortVideosPlayer(init) {
|
|
|
39
34
|
disableBackground,
|
|
40
35
|
localization,
|
|
41
36
|
showStreamsCloudWatermark,
|
|
42
|
-
analyticsHandler,
|
|
43
37
|
on: {
|
|
44
38
|
playerClosed: async () => {
|
|
45
39
|
await unmount(mounted);
|
|
@@ -3,6 +3,7 @@ import type { IPlayerItemsProvider } from '../../ui/player';
|
|
|
3
3
|
export declare class InternalShortVideoPlayerProvider implements IPlayerItemsProvider<ShortVideoViewerModel> {
|
|
4
4
|
initialData: IPlayerItemsProvider<ShortVideoViewerModel>['initialData'];
|
|
5
5
|
private ids;
|
|
6
|
+
private idOrder;
|
|
6
7
|
private initialId?;
|
|
7
8
|
private graphql;
|
|
8
9
|
private dataLoader;
|
|
@@ -4,21 +4,25 @@ import { CursorDataLoader } from '../../core/data-loaders';
|
|
|
4
4
|
import { createLocalGQLClient } from '../../core/graphql';
|
|
5
5
|
import { mapToShortVideoViewerModel } from '../short-video-viewer';
|
|
6
6
|
import { GetShortVideosDocument } from './operations.generated';
|
|
7
|
+
const CHUNK_SIZE = 20;
|
|
7
8
|
export class InternalShortVideoPlayerProvider {
|
|
8
9
|
initialData;
|
|
9
10
|
ids;
|
|
11
|
+
idOrder = new Map();
|
|
10
12
|
initialId;
|
|
11
13
|
graphql;
|
|
12
14
|
dataLoader = new CursorDataLoader({
|
|
13
15
|
loadPage: async (continuationToken) => {
|
|
16
|
+
const startIdIndex = continuationToken.value ? parseInt(continuationToken.value, 10) : 0;
|
|
17
|
+
const endIdIndex = Math.min(startIdIndex + CHUNK_SIZE, this.ids.length);
|
|
18
|
+
const idsChunk = this.ids.slice(startIdIndex, endIdIndex);
|
|
14
19
|
try {
|
|
15
20
|
const payload = await this.graphql
|
|
16
21
|
.query(GetShortVideosDocument, {
|
|
17
22
|
input: {
|
|
18
|
-
limit:
|
|
19
|
-
continuationToken,
|
|
23
|
+
limit: idsChunk.length,
|
|
20
24
|
filter: {
|
|
21
|
-
ids:
|
|
25
|
+
ids: idsChunk
|
|
22
26
|
}
|
|
23
27
|
},
|
|
24
28
|
image_scale: ImageScale.OriginalEncoded
|
|
@@ -28,9 +32,14 @@ export class InternalShortVideoPlayerProvider {
|
|
|
28
32
|
if (!data) {
|
|
29
33
|
return null;
|
|
30
34
|
}
|
|
35
|
+
const items = data.items.map(mapToShortVideoViewerModel).sort((a, b) => {
|
|
36
|
+
const ia = this.idOrder.get(a.id) ?? Number.MAX_SAFE_INTEGER;
|
|
37
|
+
const ib = this.idOrder.get(b.id) ?? Number.MAX_SAFE_INTEGER;
|
|
38
|
+
return ia - ib;
|
|
39
|
+
});
|
|
31
40
|
return {
|
|
32
|
-
items
|
|
33
|
-
continuationToken: ContinuationToken.fromPayload(
|
|
41
|
+
items,
|
|
42
|
+
continuationToken: ContinuationToken.fromPayload(endIdIndex < this.ids.length ? endIdIndex.toString() : null)
|
|
34
43
|
};
|
|
35
44
|
}
|
|
36
45
|
catch {
|
|
@@ -42,6 +51,7 @@ export class InternalShortVideoPlayerProvider {
|
|
|
42
51
|
const { ids, graphqlOrigin, initiator, initialId } = input;
|
|
43
52
|
this.graphql = createLocalGQLClient(graphqlOrigin, initiator ? { 'x-initiator': initiator } : undefined);
|
|
44
53
|
this.ids = ids;
|
|
54
|
+
ids.forEach((id, idx) => this.idOrder.set(id, idx));
|
|
45
55
|
this.initialId = initialId;
|
|
46
56
|
this.initialData = { prefetchedItems: [], startIndex: 0 };
|
|
47
57
|
}
|
|
@@ -19,7 +19,7 @@ import { InternalShortVideoPlayerProvider } from './internal-short-video-player-
|
|
|
19
19
|
import { ShortVideosPlayerLocalization } from './short-videos-player-localization';
|
|
20
20
|
import { ShortVideosPlayerUiManager } from './ui-manager.svelte';
|
|
21
21
|
import { untrack } from 'svelte';
|
|
22
|
-
let { dataProvider, socialInteractionsHandler, localization: localizationInit = 'en', showStreamsCloudWatermark, disableBackground,
|
|
22
|
+
let { dataProvider, socialInteractionsHandler, localization: localizationInit = 'en', showStreamsCloudWatermark, disableBackground, on, categoriesSwitcher, playerLogo = null, fadeContent = false } = $props();
|
|
23
23
|
const localization = $derived(new ShortVideosPlayerLocalization(localizationInit));
|
|
24
24
|
let everTouched = $state(false);
|
|
25
25
|
let background = $state(null);
|
|
@@ -56,7 +56,6 @@ const onItemActivated = (id) => {
|
|
|
56
56
|
return;
|
|
57
57
|
}
|
|
58
58
|
background = resolveVideoCover(shortVideo);
|
|
59
|
-
analyticsHandler === null || analyticsHandler === void 0 ? void 0 : analyticsHandler.trackShortVideoView(id);
|
|
60
59
|
(_a = on === null || on === void 0 ? void 0 : on.videoActivated) === null || _a === void 0 ? void 0 : _a.call(on, id);
|
|
61
60
|
};
|
|
62
61
|
const resolveVideoCover = (shortVideo) => {
|
|
@@ -88,12 +87,6 @@ const onPlayerClose = () => {
|
|
|
88
87
|
var _a;
|
|
89
88
|
(_a = on === null || on === void 0 ? void 0 : on.playerClosed) === null || _a === void 0 ? void 0 : _a.call(on);
|
|
90
89
|
};
|
|
91
|
-
const onShortVideoProductClick = (productId, videoId) => {
|
|
92
|
-
analyticsHandler === null || analyticsHandler === void 0 ? void 0 : analyticsHandler.trackShortVideoProductClicked(productId, videoId);
|
|
93
|
-
};
|
|
94
|
-
const onShortVideoProductImpression = (productId, videoId) => {
|
|
95
|
-
analyticsHandler === null || analyticsHandler === void 0 ? void 0 : analyticsHandler.trackShortVideoProductImpression(productId, videoId);
|
|
96
|
-
};
|
|
97
90
|
</script>
|
|
98
91
|
|
|
99
92
|
<svelte:document onkeydown={(e) => handleEsc(e, onPlayerClose)} />
|
|
@@ -134,11 +127,7 @@ const onShortVideoProductImpression = (productId, videoId) => {
|
|
|
134
127
|
autoplay="on-appearance"
|
|
135
128
|
showAttachments={uiManager.showShortVideoOverlay}
|
|
136
129
|
showControls={uiManager.showShortVideoOverlay}
|
|
137
|
-
localization={localization.shortVideoViewerLocalization}
|
|
138
|
-
on={{
|
|
139
|
-
productClick: (productId: string) => onShortVideoProductClick(productId, item.id),
|
|
140
|
-
productImpression: (productId: string, videoId: string) => onShortVideoProductImpression(productId, videoId)
|
|
141
|
-
}} />
|
|
130
|
+
localization={localization.shortVideoViewerLocalization} />
|
|
142
131
|
{/snippet}
|
|
143
132
|
</PlayerSlider>
|
|
144
133
|
{#if uiManager.isMobileView && buffer.loaded.length > 1 && !everTouched}
|
|
@@ -2,22 +2,14 @@ import type { Locale } from '../../core/locale';
|
|
|
2
2
|
import type { ShortVideoViewerModel, IPostSocialInteractionsHandler } from '../short-video-viewer';
|
|
3
3
|
import type { IPlayerItemsProvider } from '../../ui/player';
|
|
4
4
|
import type { IShortVideosPlayerLocalization } from './short-videos-player-localization';
|
|
5
|
-
export interface IShortVideoAnalyticsHandler {
|
|
6
|
-
setOrganizationId: (organizationId: string) => void;
|
|
7
|
-
trackShortVideoView: (videoId: string) => void;
|
|
8
|
-
trackShortVideoProductImpression: (productId: string, videoId: string) => void;
|
|
9
|
-
trackShortVideoProductClicked: (productId: string, videoId: string) => void;
|
|
10
|
-
}
|
|
11
5
|
export type ShortVideoPlayerProps = PlayerSettings & {
|
|
12
6
|
dataProvider: IPlayerItemsProvider<ShortVideoViewerModel>;
|
|
13
|
-
analyticsHandler?: IShortVideoAnalyticsHandler;
|
|
14
7
|
};
|
|
15
8
|
export type PlayerSettings = {
|
|
16
9
|
socialInteractionsHandler?: IPostSocialInteractionsHandler;
|
|
17
10
|
disableBackground?: boolean;
|
|
18
11
|
localization?: IShortVideosPlayerLocalization | Locale;
|
|
19
12
|
showStreamsCloudWatermark?: boolean;
|
|
20
|
-
analyticsHandler?: IShortVideoAnalyticsHandler;
|
|
21
13
|
on?: {
|
|
22
14
|
playerClosed?: () => void;
|
|
23
15
|
videoActivated?: (id: string) => void;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
<script lang="ts">import { Utils } from '../../core/utils';
|
|
2
2
|
import { StreamElementView } from './element-views';
|
|
3
3
|
import { StreamComponentDataType } from './enums';
|
|
4
|
-
import { onMount } from 'svelte';
|
|
5
4
|
let { model, localization, on } = $props();
|
|
6
5
|
const component = $derived.by(() => {
|
|
7
6
|
return model.components.find((c) => (model.data ? c.dataType === model.data.type : c.dataType === StreamComponentDataType.NoData));
|
|
@@ -40,23 +39,6 @@ const handleProductClick = (e) => {
|
|
|
40
39
|
window.open(productModel.link, '_blank', 'noopener noreferrer');
|
|
41
40
|
}
|
|
42
41
|
};
|
|
43
|
-
let productElement = $state();
|
|
44
|
-
onMount(() => {
|
|
45
|
-
if (productElement && (productModel === null || productModel === void 0 ? void 0 : productModel.id) && (on === null || on === void 0 ? void 0 : on.productImpression)) {
|
|
46
|
-
const observer = new IntersectionObserver((entries) => {
|
|
47
|
-
entries.forEach((entry) => {
|
|
48
|
-
if (entry.isIntersecting && entry.intersectionRatio >= 0.5) {
|
|
49
|
-
on.productImpression(productModel.id);
|
|
50
|
-
observer.unobserve(entry.target);
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
}, { threshold: 0.5 });
|
|
54
|
-
observer.observe(productElement);
|
|
55
|
-
return () => {
|
|
56
|
-
observer.disconnect();
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
42
|
</script>
|
|
61
43
|
|
|
62
44
|
{#snippet slotContent()}
|
|
@@ -67,19 +49,11 @@ onMount(() => {
|
|
|
67
49
|
{/if}
|
|
68
50
|
{/snippet}
|
|
69
51
|
{#if productModel?.link}
|
|
70
|
-
<a
|
|
71
|
-
class="stream-slot-content-product-link"
|
|
72
|
-
href={productModel.link}
|
|
73
|
-
onclick={handleProductClick}
|
|
74
|
-
target="_blank"
|
|
75
|
-
rel="noopener noreferrer"
|
|
76
|
-
bind:this={productElement}>
|
|
52
|
+
<a class="stream-slot-content-product-link" href={productModel.link} onclick={handleProductClick} target="_blank" rel="noopener noreferrer">
|
|
77
53
|
{@render slotContent()}
|
|
78
54
|
</a>
|
|
79
55
|
{:else}
|
|
80
|
-
|
|
81
|
-
{@render slotContent()}
|
|
82
|
-
</div>
|
|
56
|
+
{@render slotContent()}
|
|
83
57
|
{/if}
|
|
84
58
|
|
|
85
59
|
<style>@keyframes fadeIn {
|
|
@@ -82,8 +82,7 @@ const changeShowShortVideoAttachments = () => {
|
|
|
82
82
|
shortVideo={shortVideo}
|
|
83
83
|
localization={localization.shortVideoAttachmentsLocalization}
|
|
84
84
|
on={{
|
|
85
|
-
productClick: on.productClick
|
|
86
|
-
productImpression: on.productImpression
|
|
85
|
+
productClick: on.productClick
|
|
87
86
|
}} />
|
|
88
87
|
</div>
|
|
89
88
|
{/if}
|
|
@@ -4,13 +4,9 @@ export declare class InternalStreamAnalyticsHandler implements IStreamAnalyticsH
|
|
|
4
4
|
setOrganizationId: (organizationId: string) => void;
|
|
5
5
|
trackStreamView: (streamId: string) => void;
|
|
6
6
|
trackStreamPageView: (pageId: string, streamId: string) => void;
|
|
7
|
+
trackStreamProductClicked: (productId: string, streamId: string) => void;
|
|
7
8
|
trackStreamEngagementTime: (streamId: string, engagementTime: number) => void;
|
|
8
9
|
trackStreamScrollDepth: (streamId: string, scrollDepth: number) => void;
|
|
9
|
-
trackStreamProductImpression: (productId: string, streamId: string) => void;
|
|
10
|
-
trackStreamProductClicked: (productId: string, streamId: string) => void;
|
|
11
10
|
reportPageVideoViews: (videoId: string, streamId: string) => void;
|
|
12
|
-
trackShortVideoView: (videoId: string) => void;
|
|
13
|
-
trackShortVideoProductImpression: (productId: string, videoId: string) => void;
|
|
14
|
-
trackShortVideoProductClicked: (productId: string, videoId: string) => void;
|
|
15
11
|
trackShortVideoProgress: (pageId: string, videoId: string, progress: number, streamId: string) => void;
|
|
16
12
|
}
|
|
@@ -9,13 +9,9 @@ export class InternalStreamAnalyticsHandler {
|
|
|
9
9
|
setOrganizationId = (organizationId) => AppEventsTracker.setOrganizationId(organizationId);
|
|
10
10
|
trackStreamView = (streamId) => AppEventsTracker.trackStreamView(streamId);
|
|
11
11
|
trackStreamPageView = (pageId, streamId) => AppEventsTracker.trackStreamPageView(pageId, streamId);
|
|
12
|
+
trackStreamProductClicked = (productId, streamId) => AppEventsTracker.trackStreamProductClicked(productId, streamId);
|
|
12
13
|
trackStreamEngagementTime = (streamId, engagementTime) => AppEventsTracker.trackStreamEngagementTime(streamId, engagementTime);
|
|
13
14
|
trackStreamScrollDepth = (streamId, scrollDepth) => AppEventsTracker.trackStreamScrollDepth(streamId, scrollDepth);
|
|
14
|
-
trackStreamProductImpression = (productId, streamId) => AppEventsTracker.trackStreamProductImpression(productId, streamId);
|
|
15
|
-
trackStreamProductClicked = (productId, streamId) => AppEventsTracker.trackStreamProductClicked(productId, streamId);
|
|
16
15
|
reportPageVideoViews = (videoId, streamId) => AppEventsTracker.reportPageVideoViews(videoId, streamId);
|
|
17
|
-
trackShortVideoView = (videoId) => AppEventsTracker.trackShortVideoView(videoId);
|
|
18
|
-
trackShortVideoProductImpression = (productId, videoId) => AppEventsTracker.trackShortVideoProductImpression(productId, videoId);
|
|
19
|
-
trackShortVideoProductClicked = (productId, videoId) => AppEventsTracker.trackShortVideoProductClick(productId, videoId);
|
|
20
16
|
trackShortVideoProgress = (pageId, videoId, progress, streamId) => AppEventsTracker.trackShortVideoProgress(pageId, videoId, progress, streamId);
|
|
21
17
|
}
|
|
@@ -134,9 +134,6 @@ const onPageActivated = (id) => {
|
|
|
134
134
|
background = (page === null || page === void 0 ? void 0 : page.cover) || null;
|
|
135
135
|
if (page) {
|
|
136
136
|
analyticsHandler === null || analyticsHandler === void 0 ? void 0 : analyticsHandler.trackStreamPageView(id, streamId);
|
|
137
|
-
if (page.type === 'short-video' && page.shortVideo) {
|
|
138
|
-
analyticsHandler === null || analyticsHandler === void 0 ? void 0 : analyticsHandler.trackShortVideoView(page.shortVideo.id);
|
|
139
|
-
}
|
|
140
137
|
const currentIndex = buffer === null || buffer === void 0 ? void 0 : buffer.loaded.findIndex((p) => p.id === id);
|
|
141
138
|
if (currentIndex !== undefined && currentIndex > maxPageIndexViewed) {
|
|
142
139
|
maxPageIndexViewed = currentIndex;
|
|
@@ -146,15 +143,6 @@ const onPageActivated = (id) => {
|
|
|
146
143
|
const onProductCardClick = (productId) => {
|
|
147
144
|
analyticsHandler === null || analyticsHandler === void 0 ? void 0 : analyticsHandler.trackStreamProductClicked(productId, streamId);
|
|
148
145
|
};
|
|
149
|
-
const onShortVideoProductClick = (productId, videoId) => {
|
|
150
|
-
analyticsHandler === null || analyticsHandler === void 0 ? void 0 : analyticsHandler.trackShortVideoProductClicked(productId, videoId);
|
|
151
|
-
};
|
|
152
|
-
const onStreamProductImpression = (productId) => {
|
|
153
|
-
analyticsHandler === null || analyticsHandler === void 0 ? void 0 : analyticsHandler.trackStreamProductImpression(productId, streamId);
|
|
154
|
-
};
|
|
155
|
-
const onShortVideoProductImpression = (productId, videoId) => {
|
|
156
|
-
analyticsHandler === null || analyticsHandler === void 0 ? void 0 : analyticsHandler.trackShortVideoProductImpression(productId, videoId);
|
|
157
|
-
};
|
|
158
146
|
const onPlayerClose = () => {
|
|
159
147
|
var _a;
|
|
160
148
|
stopActivityTracking();
|
|
@@ -203,16 +191,13 @@ const onProgress = (pageId, videoId, progress) => {
|
|
|
203
191
|
localization={localization.streamPageViewerLocalization}
|
|
204
192
|
on={{
|
|
205
193
|
progress: (videoId: String, progress: Number) => onProgress(item.id, videoId, progress),
|
|
206
|
-
productClick: (productId: String) => onProductCardClick(productId)
|
|
207
|
-
productImpression: (productId: String) => onStreamProductImpression(productId)
|
|
194
|
+
productClick: (productId: String) => onProductCardClick(productId)
|
|
208
195
|
}} />
|
|
209
196
|
{:else if item.type === 'short-video'}
|
|
210
197
|
<ShortVideoViewer
|
|
211
198
|
model={mapToShortVideoViewerModel(item.shortVideo)}
|
|
212
199
|
on={{
|
|
213
|
-
progress: (progress) => onProgress(item.id, item.shortVideo.id, progress)
|
|
214
|
-
productClick: (productId: string) => onShortVideoProductClick(productId, item.shortVideo.id),
|
|
215
|
-
productImpression: (productId: string, videoId: string) => onShortVideoProductImpression(productId, videoId)
|
|
200
|
+
progress: (progress) => onProgress(item.id, item.shortVideo.id, progress)
|
|
216
201
|
}}
|
|
217
202
|
autoplay="on-appearance"
|
|
218
203
|
socialInteractionsHandler={postSocialInteractionsHandler}
|
|
@@ -246,8 +231,7 @@ const onProgress = (pageId, videoId, progress) => {
|
|
|
246
231
|
postSocialInteractionsHandler={postSocialInteractionsHandler}
|
|
247
232
|
on={{
|
|
248
233
|
closePlayer: () => onPlayerClose(),
|
|
249
|
-
productClick: (productId: String) => onProductCardClick(productId)
|
|
250
|
-
productImpression: (productId: String) => onStreamProductImpression(productId)
|
|
234
|
+
productClick: (productId: String) => onProductCardClick(productId)
|
|
251
235
|
}} />
|
|
252
236
|
{/if}
|
|
253
237
|
</div>
|
|
@@ -44,13 +44,9 @@ export interface IStreamAnalyticsHandler {
|
|
|
44
44
|
setOrganizationId: (organizationId: string) => void;
|
|
45
45
|
trackStreamView: (streamId: string) => void;
|
|
46
46
|
trackStreamPageView: (pageId: string, streamId: string) => void;
|
|
47
|
-
trackStreamProductImpression: (productId: string, streamId: string) => void;
|
|
48
47
|
trackStreamProductClicked: (productId: string, streamId: string) => void;
|
|
49
48
|
trackStreamEngagementTime: (streamId: string, engagementTime: number) => void;
|
|
50
49
|
trackStreamScrollDepth: (streamId: string, scrollDepth: number) => void;
|
|
51
50
|
reportPageVideoViews: (videoId: string, streamId: string) => void;
|
|
52
|
-
trackShortVideoView: (videoId: string) => void;
|
|
53
|
-
trackShortVideoProductImpression: (productId: string, videoId: string) => void;
|
|
54
|
-
trackShortVideoProductClicked: (productId: string, videoId: string) => void;
|
|
55
51
|
trackShortVideoProgress: (pageId: string, videoId: string, progress: number, streamId: string) => void;
|
|
56
52
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@streamscloud/embeddable",
|
|
3
|
-
"version": "6.3.
|
|
3
|
+
"version": "6.3.4",
|
|
4
4
|
"author": "StreamsCloud",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -108,7 +108,7 @@
|
|
|
108
108
|
},
|
|
109
109
|
"peerDependencies": {
|
|
110
110
|
"@fluentui/svg-icons": "^1.1.292",
|
|
111
|
-
"@streamscloud/streams-analytics-collector": "^2.0.
|
|
111
|
+
"@streamscloud/streams-analytics-collector": "^2.0.1",
|
|
112
112
|
"@urql/core": "^5.1.1",
|
|
113
113
|
"dompurify": "^3.2.6",
|
|
114
114
|
"mobile-detect": "^1.4.5",
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
<script lang="ts">import { ProductCard } from '../../products/product-card';
|
|
2
|
-
import { onMount } from 'svelte';
|
|
3
|
-
let { product, videoId, localization, includeBeforeNowPrefix, inert = false, on } = $props();
|
|
4
|
-
let productElement;
|
|
5
|
-
const productData = product;
|
|
6
|
-
onMount(() => {
|
|
7
|
-
if (productElement && (on === null || on === void 0 ? void 0 : on.impression)) {
|
|
8
|
-
const observer = new IntersectionObserver((entries) => {
|
|
9
|
-
entries.forEach((entry) => {
|
|
10
|
-
if (entry.isIntersecting && entry.intersectionRatio >= 0.5) {
|
|
11
|
-
on.impression(product.id, videoId);
|
|
12
|
-
observer.unobserve(entry.target);
|
|
13
|
-
}
|
|
14
|
-
});
|
|
15
|
-
}, { threshold: 0.5 });
|
|
16
|
-
observer.observe(productElement);
|
|
17
|
-
return () => {
|
|
18
|
-
observer.disconnect();
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
</script>
|
|
23
|
-
|
|
24
|
-
<div bind:this={productElement}>
|
|
25
|
-
<ProductCard product={productData} localization={localization} includeBeforeNowPrefix={includeBeforeNowPrefix} inert={inert} on={on} />
|
|
26
|
-
</div>
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { Locale } from '../../core/locale';
|
|
2
|
-
import type { IProductCardLocalization } from '../../products/product-card/product-card-localization';
|
|
3
|
-
import type { ShortVideoProductCardModel } from './types';
|
|
4
|
-
type Props = {
|
|
5
|
-
product: ShortVideoProductCardModel;
|
|
6
|
-
videoId: string;
|
|
7
|
-
localization?: IProductCardLocalization | Locale;
|
|
8
|
-
includeBeforeNowPrefix?: boolean;
|
|
9
|
-
inert?: boolean;
|
|
10
|
-
on?: {
|
|
11
|
-
productClick?: (id: string) => void;
|
|
12
|
-
impression?: (productId: string, videoId: string) => void;
|
|
13
|
-
};
|
|
14
|
-
};
|
|
15
|
-
declare const Cmp: import("svelte").Component<Props, {}, "">;
|
|
16
|
-
type Cmp = ReturnType<typeof Cmp>;
|
|
17
|
-
export default Cmp;
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { IShortVideoAnalyticsHandler } from './types';
|
|
2
|
-
export declare class InternalShortVideoAnalyticsHandler implements IShortVideoAnalyticsHandler {
|
|
3
|
-
constructor(graphqlOrigin: string | undefined);
|
|
4
|
-
setOrganizationId: (organizationId: string) => void;
|
|
5
|
-
trackShortVideoView: (videoId: string) => void;
|
|
6
|
-
trackShortVideoProductImpression: (productId: string, videoId: string) => void;
|
|
7
|
-
trackShortVideoProductClicked: (productId: string, videoId: string) => void;
|
|
8
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { getOrCreateProfileId } from '../../core/analytics.profile-id';
|
|
2
|
-
import { constructGraphQLUrl } from '../../core/graphql';
|
|
3
|
-
import { AppEventsTracker } from '@streamscloud/streams-analytics-collector';
|
|
4
|
-
export class InternalShortVideoAnalyticsHandler {
|
|
5
|
-
constructor(graphqlOrigin) {
|
|
6
|
-
AppEventsTracker.setEndpoint(constructGraphQLUrl(graphqlOrigin));
|
|
7
|
-
AppEventsTracker.setProfileId(getOrCreateProfileId());
|
|
8
|
-
}
|
|
9
|
-
setOrganizationId = (organizationId) => AppEventsTracker.setOrganizationId(organizationId);
|
|
10
|
-
trackShortVideoView = (videoId) => AppEventsTracker.trackShortVideoView(videoId);
|
|
11
|
-
trackShortVideoProductImpression = (productId, videoId) => AppEventsTracker.trackShortVideoProductImpression(productId, videoId);
|
|
12
|
-
trackShortVideoProductClicked = (productId, videoId) => AppEventsTracker.trackShortVideoProductClick(productId, videoId);
|
|
13
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
<script lang="ts">import { ProductCard } from '../products/product-card';
|
|
2
|
-
import { onMount } from 'svelte';
|
|
3
|
-
let { product, streamId, localization, includeBeforeNowPrefix, inert = false, on } = $props();
|
|
4
|
-
let productElement;
|
|
5
|
-
onMount(() => {
|
|
6
|
-
if (productElement && (on === null || on === void 0 ? void 0 : on.impression)) {
|
|
7
|
-
const observer = new IntersectionObserver((entries) => {
|
|
8
|
-
entries.forEach((entry) => {
|
|
9
|
-
if (entry.isIntersecting && entry.intersectionRatio >= 0.5) {
|
|
10
|
-
on.impression(product.id, streamId);
|
|
11
|
-
observer.unobserve(entry.target);
|
|
12
|
-
}
|
|
13
|
-
});
|
|
14
|
-
}, { threshold: 0.5 });
|
|
15
|
-
observer.observe(productElement);
|
|
16
|
-
return () => {
|
|
17
|
-
observer.disconnect();
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
</script>
|
|
22
|
-
|
|
23
|
-
<div bind:this={productElement}>
|
|
24
|
-
<ProductCard product={product} localization={localization} includeBeforeNowPrefix={includeBeforeNowPrefix} inert={inert} on={on} />
|
|
25
|
-
</div>
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { Locale } from '../core/locale';
|
|
2
|
-
import type { IProductCardLocalization } from '../products/product-card/product-card-localization';
|
|
3
|
-
import type { ProductCardModel } from '../products/product-card/types';
|
|
4
|
-
type Props = {
|
|
5
|
-
product: ProductCardModel;
|
|
6
|
-
streamId: string;
|
|
7
|
-
localization?: IProductCardLocalization | Locale;
|
|
8
|
-
includeBeforeNowPrefix?: boolean;
|
|
9
|
-
inert?: boolean;
|
|
10
|
-
on?: {
|
|
11
|
-
productClick?: (id: string) => void;
|
|
12
|
-
impression?: (productId: string, streamId: string) => void;
|
|
13
|
-
};
|
|
14
|
-
};
|
|
15
|
-
declare const Cmp: import("svelte").Component<Props, {}, "">;
|
|
16
|
-
type Cmp = ReturnType<typeof Cmp>;
|
|
17
|
-
export default Cmp;
|