@streamscloud/embeddable 6.3.4-1757324420366 → 6.3.5
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/media-center/data-provider/operations.generated.d.ts +3 -0
- package/dist/media-center/data-provider/operations.generated.js +5 -0
- package/dist/short-videos/short-video-viewer/cmp.attachments-inline.svelte +70 -6
- package/dist/short-videos/short-video-viewer/cmp.attachments-inline.svelte.d.ts +4 -0
- package/dist/short-videos/short-video-viewer/cmp.attachments.svelte +9 -2
- package/dist/short-videos/short-video-viewer/cmp.attachments.svelte.d.ts +1 -0
- package/dist/short-videos/short-video-viewer/cmp.short-video-product-card.svelte +26 -0
- package/dist/short-videos/short-video-viewer/cmp.short-video-product-card.svelte.d.ts +17 -0
- package/dist/short-videos/short-video-viewer/cmp.short-video-viewer.svelte +6 -1
- package/dist/short-videos/short-video-viewer/cmp.short-video-viewer.svelte.d.ts +2 -0
- package/dist/short-videos/short-video-viewer/mapper.js +1 -0
- package/dist/short-videos/short-video-viewer/operations.generated.d.ts +3 -0
- package/dist/short-videos/short-video-viewer/operations.generated.js +5 -0
- package/dist/short-videos/short-video-viewer/operations.graphql +3 -0
- package/dist/short-videos/short-video-viewer/types.d.ts +1 -0
- package/dist/short-videos/short-videos-player/cmp.short-videos-player.svelte +2 -1
- package/dist/short-videos/short-videos-player/controls.svelte +2 -1
- package/dist/short-videos/short-videos-player/controls.svelte.d.ts +1 -0
- package/dist/short-videos/short-videos-player/index.d.ts +2 -2
- package/dist/short-videos/short-videos-player/index.js +6 -0
- package/dist/short-videos/short-videos-player/internal-short-video-analytics-handler.d.ts +8 -0
- package/dist/short-videos/short-videos-player/internal-short-video-analytics-handler.js +21 -0
- package/dist/short-videos/short-videos-player/internal-short-video-player-provider.d.ts +0 -1
- package/dist/short-videos/short-videos-player/internal-short-video-player-provider.js +5 -15
- package/dist/short-videos/short-videos-player/operations.generated.d.ts +3 -0
- package/dist/short-videos/short-videos-player/operations.generated.js +5 -0
- package/dist/short-videos/short-videos-player/short-videos-player-view.svelte +19 -3
- package/dist/short-videos/short-videos-player/types.d.ts +8 -0
- package/dist/streams/cmp.stream-product-card.svelte +25 -0
- package/dist/streams/cmp.stream-product-card.svelte.d.ts +17 -0
- package/dist/streams/layout/cmp.slot-content.svelte +28 -2
- package/dist/streams/layout/cmp.slot-content.svelte.d.ts +1 -0
- package/dist/streams/layout/models/mapper.js +1 -0
- package/dist/streams/layout/models/stream-layout-short-video-model.d.ts +1 -0
- package/dist/streams/stream-page-viewer/cmp.stream-page-viewer.svelte.d.ts +1 -0
- package/dist/streams/stream-player/controls.svelte +2 -1
- package/dist/streams/stream-player/controls.svelte.d.ts +1 -0
- package/dist/streams/stream-player/internal-stream-analytics-handler.d.ts +5 -1
- package/dist/streams/stream-player/internal-stream-analytics-handler.js +5 -1
- package/dist/streams/stream-player/stream-player.svelte +19 -3
- package/dist/streams/stream-player/types.d.ts +4 -0
- package/package.json +2 -5
|
@@ -127,6 +127,11 @@ export const GetShortVideosDocument = {
|
|
|
127
127
|
selections: [
|
|
128
128
|
{ kind: 'Field', name: { kind: 'Name', value: 'id' } },
|
|
129
129
|
{ kind: 'Field', name: { kind: 'Name', value: 'enableSocialInteractions' } },
|
|
130
|
+
{
|
|
131
|
+
kind: 'Field',
|
|
132
|
+
name: { kind: 'Name', value: 'ownerProfile' },
|
|
133
|
+
selectionSet: { kind: 'SelectionSet', selections: [{ kind: 'Field', name: { kind: 'Name', value: 'id' } }] }
|
|
134
|
+
},
|
|
130
135
|
{
|
|
131
136
|
kind: 'Field',
|
|
132
137
|
name: { kind: 'Name', value: 'allProducts' },
|
|
@@ -1,18 +1,82 @@
|
|
|
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
|
-
|
|
4
|
+
import { onMount } from 'svelte';
|
|
5
|
+
let { model, on } = $props();
|
|
5
6
|
const attachmentsToShow = $derived.by(() => {
|
|
6
|
-
const products = model.products
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
const products = model.products
|
|
8
|
+
.filter((p) => !!p.image)
|
|
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
|
+
});
|
|
26
|
+
const result = [...products, ...ads];
|
|
27
|
+
return result;
|
|
28
|
+
});
|
|
29
|
+
const handleAttachmentClick = (attachment) => {
|
|
30
|
+
if (attachment.productId && (on === null || on === void 0 ? void 0 : on.productClick)) {
|
|
31
|
+
on.productClick(attachment.productId);
|
|
32
|
+
}
|
|
33
|
+
if (attachment.link) {
|
|
34
|
+
window.open(attachment.link, '_blank');
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
let attachmentElements = {};
|
|
38
|
+
let observer = null;
|
|
39
|
+
$effect(() => {
|
|
40
|
+
if ((on === null || on === void 0 ? void 0 : on.productImpression) && Object.keys(attachmentElements).length > 0) {
|
|
41
|
+
if (observer) {
|
|
42
|
+
observer.disconnect();
|
|
43
|
+
}
|
|
44
|
+
observer = new IntersectionObserver((entries) => {
|
|
45
|
+
entries.forEach((entry) => {
|
|
46
|
+
if (entry.isIntersecting && entry.intersectionRatio >= 0.1) {
|
|
47
|
+
const productId = entry.target.getAttribute('data-product-id');
|
|
48
|
+
if (productId) {
|
|
49
|
+
on.productImpression(productId, model.id);
|
|
50
|
+
observer === null || observer === void 0 ? void 0 : observer.unobserve(entry.target); // Only track once per session
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}, { threshold: 0.1 });
|
|
55
|
+
Object.entries(attachmentElements).forEach(([key, element]) => {
|
|
56
|
+
if (element && key.startsWith('product-')) {
|
|
57
|
+
observer === null || observer === void 0 ? void 0 : observer.observe(element);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return () => {
|
|
62
|
+
if (observer) {
|
|
63
|
+
observer.disconnect();
|
|
64
|
+
observer = null;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
9
67
|
});
|
|
10
68
|
</script>
|
|
11
69
|
|
|
12
70
|
<div class="attachments-inline-container">
|
|
13
71
|
<div class="attachments-inline">
|
|
14
|
-
{#each attachmentsToShow as attachment (attachment)}
|
|
15
|
-
<div
|
|
72
|
+
{#each attachmentsToShow as attachment, index (attachment)}
|
|
73
|
+
<div
|
|
74
|
+
class="attachments-inline__item"
|
|
75
|
+
onclick={() => handleAttachmentClick(attachment)}
|
|
76
|
+
onkeydown={() => {}}
|
|
77
|
+
role="none"
|
|
78
|
+
bind:this={attachmentElements[attachment.productId ? `product-${attachment.productId}` : `ad-${index}`]}
|
|
79
|
+
data-product-id={attachment.productId || undefined}>
|
|
16
80
|
<ImageRounded src={attachment.image} alt="" />
|
|
17
81
|
{#if attachment.isAd}
|
|
18
82
|
<div class="attachments-inline__item-icon">
|
|
@@ -1,6 +1,10 @@
|
|
|
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
|
+
};
|
|
4
8
|
};
|
|
5
9
|
declare const Cmp: import("svelte").Component<Props, {}, "">;
|
|
6
10
|
type Cmp = ReturnType<typeof Cmp>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts">import { AdCard } from '../../ads/ad-card';
|
|
2
|
-
import {
|
|
2
|
+
import { default as ShortVideoProductCard } from './cmp.short-video-product-card.svelte';
|
|
3
3
|
import { ShortVideoAttachmentsLocalization } from './short-video-attachments-localization';
|
|
4
4
|
import {} from './types';
|
|
5
5
|
let { shortVideo, localization: localizationInit = 'en', on } = $props();
|
|
@@ -14,7 +14,14 @@ const localization = $derived(new ShortVideoAttachmentsLocalization(localization
|
|
|
14
14
|
|
|
15
15
|
{#if shortVideo.products.length}
|
|
16
16
|
{#each shortVideo.products as product (product.id)}
|
|
17
|
-
<
|
|
17
|
+
<ShortVideoProductCard
|
|
18
|
+
product={product}
|
|
19
|
+
videoId={shortVideo.id}
|
|
20
|
+
localization={localization.productLocalization}
|
|
21
|
+
on={{
|
|
22
|
+
productClick: on?.productClick,
|
|
23
|
+
impression: on?.productImpression
|
|
24
|
+
}} />
|
|
18
25
|
{/each}
|
|
19
26
|
{/if}
|
|
20
27
|
</div>
|
|
@@ -6,6 +6,7 @@ type Props = {
|
|
|
6
6
|
localization?: IShortVideoAttachmentsLocalization | Locale;
|
|
7
7
|
on?: {
|
|
8
8
|
productClick?: (productId: string) => void;
|
|
9
|
+
productImpression?: (productId: string, videoId: string) => void;
|
|
9
10
|
};
|
|
10
11
|
};
|
|
11
12
|
declare const Cmp: import("svelte").Component<Props, {}, "">;
|
|
@@ -0,0 +1,26 @@
|
|
|
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>
|
|
@@ -0,0 +1,17 @@
|
|
|
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;
|
|
@@ -36,7 +36,12 @@ $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
|
|
39
|
+
<AttachmentsInline
|
|
40
|
+
model={model}
|
|
41
|
+
on={{
|
|
42
|
+
productClick: on?.productClick,
|
|
43
|
+
productImpression: on?.productImpression
|
|
44
|
+
}} />
|
|
40
45
|
{/if}
|
|
41
46
|
{#if uiManager.showControls}
|
|
42
47
|
<ShortVideoControls model={model} socialInteractionsHandler={socialInteractionsHandler} on={{ attachmentsClicked: uiManager.toggleEnableAttachments }} />
|
|
@@ -10,6 +10,8 @@ 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;
|
|
13
15
|
};
|
|
14
16
|
};
|
|
15
17
|
declare const Cmp: import("svelte").Component<Props, {}, "">;
|
|
@@ -3,6 +3,9 @@ import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-
|
|
|
3
3
|
export type ShortVideoViewerPayloadFragment = {
|
|
4
4
|
id: string;
|
|
5
5
|
enableSocialInteractions: boolean;
|
|
6
|
+
ownerProfile: {
|
|
7
|
+
id: string;
|
|
8
|
+
};
|
|
6
9
|
allProducts: Array<{
|
|
7
10
|
id: string;
|
|
8
11
|
title: string;
|
|
@@ -10,6 +10,11 @@ export const ShortVideoViewerPayloadFragmentDoc = {
|
|
|
10
10
|
selections: [
|
|
11
11
|
{ kind: 'Field', name: { kind: 'Name', value: 'id' } },
|
|
12
12
|
{ kind: 'Field', name: { kind: 'Name', value: 'enableSocialInteractions' } },
|
|
13
|
+
{
|
|
14
|
+
kind: 'Field',
|
|
15
|
+
name: { kind: 'Name', value: 'ownerProfile' },
|
|
16
|
+
selectionSet: { kind: 'SelectionSet', selections: [{ kind: 'Field', name: { kind: 'Name', value: 'id' } }] }
|
|
17
|
+
},
|
|
13
18
|
{
|
|
14
19
|
kind: 'Field',
|
|
15
20
|
name: { kind: 'Name', value: 'allProducts' },
|
|
@@ -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, on, mediaCenterDataProvider } = $props();
|
|
4
|
+
let { dataProvider, socialInteractionsHandler, localization, showStreamsCloudWatermark, disableBackground, analyticsHandler, on, mediaCenterDataProvider } = $props();
|
|
5
5
|
const initHost = (node) => {
|
|
6
6
|
const shadowRoot = createShadowRoot(node);
|
|
7
7
|
const mounted = mount(MediaCenter, {
|
|
@@ -16,6 +16,7 @@ const initHost = (node) => {
|
|
|
16
16
|
disableBackground,
|
|
17
17
|
localization,
|
|
18
18
|
showStreamsCloudWatermark,
|
|
19
|
+
analyticsHandler,
|
|
19
20
|
on
|
|
20
21
|
}
|
|
21
22
|
}
|
|
@@ -50,7 +50,8 @@ const changeShowAttachments = () => {
|
|
|
50
50
|
shortVideo={shortVideo}
|
|
51
51
|
localization={localization.shortVideoAttachmentsLocalization}
|
|
52
52
|
on={{
|
|
53
|
-
productClick: on.productClick
|
|
53
|
+
productClick: on.productClick,
|
|
54
|
+
productImpression: on.productImpression
|
|
54
55
|
}} />
|
|
55
56
|
</div>
|
|
56
57
|
{/if}
|
|
@@ -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 } from './types';
|
|
6
|
+
import { type PlayerSettings, type IShortVideoAnalyticsHandler } from './types';
|
|
7
7
|
export { ShortVideosPlayer };
|
|
8
|
-
export type { IShortVideosPlayerLocalization, IMediaCenterDataProvider, IPlayerItemsProvider };
|
|
8
|
+
export type { IShortVideosPlayerLocalization, IMediaCenterDataProvider, IPlayerItemsProvider, IShortVideoAnalyticsHandler };
|
|
9
9
|
/**
|
|
10
10
|
* Opens the short videos player modal.
|
|
11
11
|
*
|
|
@@ -3,6 +3,7 @@ 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';
|
|
6
7
|
import { InternalShortVideoPlayerProvider } from './internal-short-video-player-provider';
|
|
7
8
|
import {} from './types';
|
|
8
9
|
import { mount, unmount } from 'svelte';
|
|
@@ -21,6 +22,10 @@ export function openShortVideosPlayer(init) {
|
|
|
21
22
|
if (!mediaCenterDataProvider && init.mediaPageId) {
|
|
22
23
|
mediaCenterDataProvider = new InternalMediaCenterDataProvider(init.mediaPageId, graphqlOrigin);
|
|
23
24
|
}
|
|
25
|
+
let analyticsHandler = init.analyticsHandler;
|
|
26
|
+
if (!analyticsHandler && !init.shortVideosProvider && initiator) {
|
|
27
|
+
analyticsHandler = new InternalShortVideoAnalyticsHandler(graphqlOrigin);
|
|
28
|
+
}
|
|
24
29
|
const shadowHost = new ModalShadowHost();
|
|
25
30
|
const mounted = mount(MediaCenter, {
|
|
26
31
|
target: shadowHost.shadowRoot,
|
|
@@ -34,6 +39,7 @@ export function openShortVideosPlayer(init) {
|
|
|
34
39
|
disableBackground,
|
|
35
40
|
localization,
|
|
36
41
|
showStreamsCloudWatermark,
|
|
42
|
+
analyticsHandler,
|
|
37
43
|
on: {
|
|
38
44
|
playerClosed: async () => {
|
|
39
45
|
await unmount(mounted);
|
|
@@ -0,0 +1,8 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
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) => {
|
|
10
|
+
AppEventsTracker.setOrganizationId(organizationId);
|
|
11
|
+
};
|
|
12
|
+
trackShortVideoView = (videoId) => {
|
|
13
|
+
AppEventsTracker.trackShortVideoView(videoId);
|
|
14
|
+
};
|
|
15
|
+
trackShortVideoProductImpression = (productId, videoId) => {
|
|
16
|
+
AppEventsTracker.trackShortVideoProductImpression(productId, videoId);
|
|
17
|
+
};
|
|
18
|
+
trackShortVideoProductClicked = (productId, videoId) => {
|
|
19
|
+
AppEventsTracker.trackShortVideoProductClick(productId, videoId);
|
|
20
|
+
};
|
|
21
|
+
}
|
|
@@ -3,7 +3,6 @@ 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;
|
|
7
6
|
private initialId?;
|
|
8
7
|
private graphql;
|
|
9
8
|
private dataLoader;
|
|
@@ -4,25 +4,21 @@ 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;
|
|
8
7
|
export class InternalShortVideoPlayerProvider {
|
|
9
8
|
initialData;
|
|
10
9
|
ids;
|
|
11
|
-
idOrder = new Map();
|
|
12
10
|
initialId;
|
|
13
11
|
graphql;
|
|
14
12
|
dataLoader = new CursorDataLoader({
|
|
15
13
|
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);
|
|
19
14
|
try {
|
|
20
15
|
const payload = await this.graphql
|
|
21
16
|
.query(GetShortVideosDocument, {
|
|
22
17
|
input: {
|
|
23
|
-
limit:
|
|
18
|
+
limit: 20,
|
|
19
|
+
continuationToken,
|
|
24
20
|
filter: {
|
|
25
|
-
ids:
|
|
21
|
+
ids: this.ids
|
|
26
22
|
}
|
|
27
23
|
},
|
|
28
24
|
image_scale: ImageScale.OriginalEncoded
|
|
@@ -32,14 +28,9 @@ export class InternalShortVideoPlayerProvider {
|
|
|
32
28
|
if (!data) {
|
|
33
29
|
return null;
|
|
34
30
|
}
|
|
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
|
-
});
|
|
40
31
|
return {
|
|
41
|
-
items,
|
|
42
|
-
continuationToken: ContinuationToken.fromPayload(
|
|
32
|
+
items: data.items.map(mapToShortVideoViewerModel),
|
|
33
|
+
continuationToken: ContinuationToken.fromPayload(data.continuationToken)
|
|
43
34
|
};
|
|
44
35
|
}
|
|
45
36
|
catch {
|
|
@@ -51,7 +42,6 @@ export class InternalShortVideoPlayerProvider {
|
|
|
51
42
|
const { ids, graphqlOrigin, initiator, initialId } = input;
|
|
52
43
|
this.graphql = createLocalGQLClient(graphqlOrigin, initiator ? { 'x-initiator': initiator } : undefined);
|
|
53
44
|
this.ids = ids;
|
|
54
|
-
ids.forEach((id, idx) => this.idOrder.set(id, idx));
|
|
55
45
|
this.initialId = initialId;
|
|
56
46
|
this.initialData = { prefetchedItems: [], startIndex: 0 };
|
|
57
47
|
}
|
|
@@ -53,6 +53,11 @@ export const GetShortVideosDocument = {
|
|
|
53
53
|
selections: [
|
|
54
54
|
{ kind: 'Field', name: { kind: 'Name', value: 'id' } },
|
|
55
55
|
{ kind: 'Field', name: { kind: 'Name', value: 'enableSocialInteractions' } },
|
|
56
|
+
{
|
|
57
|
+
kind: 'Field',
|
|
58
|
+
name: { kind: 'Name', value: 'ownerProfile' },
|
|
59
|
+
selectionSet: { kind: 'SelectionSet', selections: [{ kind: 'Field', name: { kind: 'Name', value: 'id' } }] }
|
|
60
|
+
},
|
|
56
61
|
{
|
|
57
62
|
kind: 'Field',
|
|
58
63
|
name: { kind: 'Name', value: 'allProducts' },
|
|
@@ -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, on, categoriesSwitcher, playerLogo = null, fadeContent = false } = $props();
|
|
22
|
+
let { dataProvider, socialInteractionsHandler, localization: localizationInit = 'en', showStreamsCloudWatermark, disableBackground, analyticsHandler, 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,6 +56,8 @@ const onItemActivated = (id) => {
|
|
|
56
56
|
return;
|
|
57
57
|
}
|
|
58
58
|
background = resolveVideoCover(shortVideo);
|
|
59
|
+
analyticsHandler === null || analyticsHandler === void 0 ? void 0 : analyticsHandler.setOrganizationId(shortVideo.organizationId);
|
|
60
|
+
analyticsHandler === null || analyticsHandler === void 0 ? void 0 : analyticsHandler.trackShortVideoView(id);
|
|
59
61
|
(_a = on === null || on === void 0 ? void 0 : on.videoActivated) === null || _a === void 0 ? void 0 : _a.call(on, id);
|
|
60
62
|
};
|
|
61
63
|
const resolveVideoCover = (shortVideo) => {
|
|
@@ -87,6 +89,12 @@ const onPlayerClose = () => {
|
|
|
87
89
|
var _a;
|
|
88
90
|
(_a = on === null || on === void 0 ? void 0 : on.playerClosed) === null || _a === void 0 ? void 0 : _a.call(on);
|
|
89
91
|
};
|
|
92
|
+
const onShortVideoProductClick = (productId, videoId) => {
|
|
93
|
+
analyticsHandler === null || analyticsHandler === void 0 ? void 0 : analyticsHandler.trackShortVideoProductClicked(productId, videoId);
|
|
94
|
+
};
|
|
95
|
+
const onShortVideoProductImpression = (productId, videoId) => {
|
|
96
|
+
analyticsHandler === null || analyticsHandler === void 0 ? void 0 : analyticsHandler.trackShortVideoProductImpression(productId, videoId);
|
|
97
|
+
};
|
|
90
98
|
</script>
|
|
91
99
|
|
|
92
100
|
<svelte:document onkeydown={(e) => handleEsc(e, onPlayerClose)} />
|
|
@@ -127,7 +135,11 @@ const onPlayerClose = () => {
|
|
|
127
135
|
autoplay="on-appearance"
|
|
128
136
|
showAttachments={uiManager.showShortVideoOverlay}
|
|
129
137
|
showControls={uiManager.showShortVideoOverlay}
|
|
130
|
-
localization={localization.shortVideoViewerLocalization}
|
|
138
|
+
localization={localization.shortVideoViewerLocalization}
|
|
139
|
+
on={{
|
|
140
|
+
productClick: (productId: string) => onShortVideoProductClick(productId, item.id),
|
|
141
|
+
productImpression: (productId: string, videoId: string) => onShortVideoProductImpression(productId, videoId)
|
|
142
|
+
}} />
|
|
131
143
|
{/snippet}
|
|
132
144
|
</PlayerSlider>
|
|
133
145
|
{#if uiManager.isMobileView && buffer.loaded.length > 1 && !everTouched}
|
|
@@ -141,7 +153,11 @@ const onPlayerClose = () => {
|
|
|
141
153
|
localization={localization}
|
|
142
154
|
socialInteractionsHandler={socialInteractionsHandler}
|
|
143
155
|
playerLogo={playerLogo}
|
|
144
|
-
on={{
|
|
156
|
+
on={{
|
|
157
|
+
closePlayer: on?.playerClosed,
|
|
158
|
+
productClick: (productId: string) => onShortVideoProductClick(productId, buffer.current?.id || ''),
|
|
159
|
+
productImpression: onShortVideoProductImpression
|
|
160
|
+
}} />
|
|
145
161
|
{:else}
|
|
146
162
|
<Loading positionFixedCenter={true} timeout={1000} />
|
|
147
163
|
{/if}
|
|
@@ -2,14 +2,22 @@ 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
|
+
}
|
|
5
11
|
export type ShortVideoPlayerProps = PlayerSettings & {
|
|
6
12
|
dataProvider: IPlayerItemsProvider<ShortVideoViewerModel>;
|
|
13
|
+
analyticsHandler?: IShortVideoAnalyticsHandler;
|
|
7
14
|
};
|
|
8
15
|
export type PlayerSettings = {
|
|
9
16
|
socialInteractionsHandler?: IPostSocialInteractionsHandler;
|
|
10
17
|
disableBackground?: boolean;
|
|
11
18
|
localization?: IShortVideosPlayerLocalization | Locale;
|
|
12
19
|
showStreamsCloudWatermark?: boolean;
|
|
20
|
+
analyticsHandler?: IShortVideoAnalyticsHandler;
|
|
13
21
|
on?: {
|
|
14
22
|
playerClosed?: () => void;
|
|
15
23
|
videoActivated?: (id: string) => void;
|
|
@@ -0,0 +1,25 @@
|
|
|
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>
|
|
@@ -0,0 +1,17 @@
|
|
|
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;
|
|
@@ -1,6 +1,7 @@
|
|
|
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';
|
|
4
5
|
let { model, localization, on } = $props();
|
|
5
6
|
const component = $derived.by(() => {
|
|
6
7
|
return model.components.find((c) => (model.data ? c.dataType === model.data.type : c.dataType === StreamComponentDataType.NoData));
|
|
@@ -39,6 +40,23 @@ const handleProductClick = (e) => {
|
|
|
39
40
|
window.open(productModel.link, '_blank', 'noopener noreferrer');
|
|
40
41
|
}
|
|
41
42
|
};
|
|
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
|
+
});
|
|
42
60
|
</script>
|
|
43
61
|
|
|
44
62
|
{#snippet slotContent()}
|
|
@@ -49,11 +67,19 @@ const handleProductClick = (e) => {
|
|
|
49
67
|
{/if}
|
|
50
68
|
{/snippet}
|
|
51
69
|
{#if productModel?.link}
|
|
52
|
-
<a
|
|
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}>
|
|
53
77
|
{@render slotContent()}
|
|
54
78
|
</a>
|
|
55
79
|
{:else}
|
|
56
|
-
{
|
|
80
|
+
<div bind:this={productElement}>
|
|
81
|
+
{@render slotContent()}
|
|
82
|
+
</div>
|
|
57
83
|
{/if}
|
|
58
84
|
|
|
59
85
|
<style>@keyframes fadeIn {
|
|
@@ -3,6 +3,7 @@ import type { StreamLayoutMediaItemModel } from './stream-layout-media-item-mode
|
|
|
3
3
|
import type { StreamLayoutPostHeaderModel } from './stream-layout-post-header-model';
|
|
4
4
|
export type StreamLayoutShortVideoModel = {
|
|
5
5
|
id: string;
|
|
6
|
+
organizationId: string;
|
|
6
7
|
media: StreamLayoutMediaItemModel;
|
|
7
8
|
text: string | null;
|
|
8
9
|
header: StreamLayoutPostHeaderModel | null;
|
|
@@ -82,7 +82,8 @@ const changeShowShortVideoAttachments = () => {
|
|
|
82
82
|
shortVideo={shortVideo}
|
|
83
83
|
localization={localization.shortVideoAttachmentsLocalization}
|
|
84
84
|
on={{
|
|
85
|
-
productClick: on.productClick
|
|
85
|
+
productClick: on.productClick,
|
|
86
|
+
productImpression: on.productImpression
|
|
86
87
|
}} />
|
|
87
88
|
</div>
|
|
88
89
|
{/if}
|
|
@@ -4,9 +4,13 @@ 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;
|
|
8
7
|
trackStreamEngagementTime: (streamId: string, engagementTime: number) => void;
|
|
9
8
|
trackStreamScrollDepth: (streamId: string, scrollDepth: number) => void;
|
|
9
|
+
trackStreamProductImpression: (productId: string, streamId: string) => void;
|
|
10
|
+
trackStreamProductClicked: (productId: string, streamId: string) => void;
|
|
10
11
|
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;
|
|
11
15
|
trackShortVideoProgress: (pageId: string, videoId: string, progress: number, streamId: string) => void;
|
|
12
16
|
}
|
|
@@ -9,9 +9,13 @@ 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);
|
|
13
12
|
trackStreamEngagementTime = (streamId, engagementTime) => AppEventsTracker.trackStreamEngagementTime(streamId, engagementTime);
|
|
14
13
|
trackStreamScrollDepth = (streamId, scrollDepth) => AppEventsTracker.trackStreamScrollDepth(streamId, scrollDepth);
|
|
14
|
+
trackStreamProductImpression = (productId, streamId) => AppEventsTracker.trackStreamProductImpression(productId, streamId);
|
|
15
|
+
trackStreamProductClicked = (productId, streamId) => AppEventsTracker.trackStreamProductClicked(productId, streamId);
|
|
15
16
|
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);
|
|
16
20
|
trackShortVideoProgress = (pageId, videoId, progress, streamId) => AppEventsTracker.trackShortVideoProgress(pageId, videoId, progress, streamId);
|
|
17
21
|
}
|
|
@@ -134,6 +134,9 @@ 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
|
+
}
|
|
137
140
|
const currentIndex = buffer === null || buffer === void 0 ? void 0 : buffer.loaded.findIndex((p) => p.id === id);
|
|
138
141
|
if (currentIndex !== undefined && currentIndex > maxPageIndexViewed) {
|
|
139
142
|
maxPageIndexViewed = currentIndex;
|
|
@@ -143,6 +146,15 @@ const onPageActivated = (id) => {
|
|
|
143
146
|
const onProductCardClick = (productId) => {
|
|
144
147
|
analyticsHandler === null || analyticsHandler === void 0 ? void 0 : analyticsHandler.trackStreamProductClicked(productId, streamId);
|
|
145
148
|
};
|
|
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
|
+
};
|
|
146
158
|
const onPlayerClose = () => {
|
|
147
159
|
var _a;
|
|
148
160
|
stopActivityTracking();
|
|
@@ -191,13 +203,16 @@ const onProgress = (pageId, videoId, progress) => {
|
|
|
191
203
|
localization={localization.streamPageViewerLocalization}
|
|
192
204
|
on={{
|
|
193
205
|
progress: (videoId: String, progress: Number) => onProgress(item.id, videoId, progress),
|
|
194
|
-
productClick: (productId: String) => onProductCardClick(productId)
|
|
206
|
+
productClick: (productId: String) => onProductCardClick(productId),
|
|
207
|
+
productImpression: (productId: String) => onStreamProductImpression(productId)
|
|
195
208
|
}} />
|
|
196
209
|
{:else if item.type === 'short-video'}
|
|
197
210
|
<ShortVideoViewer
|
|
198
211
|
model={mapToShortVideoViewerModel(item.shortVideo)}
|
|
199
212
|
on={{
|
|
200
|
-
progress: (progress) => onProgress(item.id, item.shortVideo.id, progress)
|
|
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)
|
|
201
216
|
}}
|
|
202
217
|
autoplay="on-appearance"
|
|
203
218
|
socialInteractionsHandler={postSocialInteractionsHandler}
|
|
@@ -231,7 +246,8 @@ const onProgress = (pageId, videoId, progress) => {
|
|
|
231
246
|
postSocialInteractionsHandler={postSocialInteractionsHandler}
|
|
232
247
|
on={{
|
|
233
248
|
closePlayer: () => onPlayerClose(),
|
|
234
|
-
productClick: (productId: String) => onProductCardClick(productId)
|
|
249
|
+
productClick: (productId: String) => onProductCardClick(productId),
|
|
250
|
+
productImpression: (productId: String) => onStreamProductImpression(productId)
|
|
235
251
|
}} />
|
|
236
252
|
{/if}
|
|
237
253
|
</div>
|
|
@@ -44,9 +44,13 @@ 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;
|
|
47
48
|
trackStreamProductClicked: (productId: string, streamId: string) => void;
|
|
48
49
|
trackStreamEngagementTime: (streamId: string, engagementTime: number) => void;
|
|
49
50
|
trackStreamScrollDepth: (streamId: string, scrollDepth: number) => void;
|
|
50
51
|
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;
|
|
51
55
|
trackShortVideoProgress: (pageId: string, videoId: string, progress: number, streamId: string) => void;
|
|
52
56
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@streamscloud/embeddable",
|
|
3
|
-
"version": "6.3.
|
|
3
|
+
"version": "6.3.5",
|
|
4
4
|
"author": "StreamsCloud",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -11,9 +11,6 @@
|
|
|
11
11
|
"dev": "vite dev --port 3010",
|
|
12
12
|
"build": "svelte-package --tsconfig ./tsconfig.app.json && prettier --write --plugin prettier-plugin-svelte . && eslint --fix .",
|
|
13
13
|
"build-publish": "npm run build && npm publish --access public",
|
|
14
|
-
"publish:prod": "npm run build && npm publish --access public --tag latest",
|
|
15
|
-
"version:dev": "node -e \"const fs=require('fs');const pkg=require('./package.json');const base=(pkg.version.includes('-')?pkg.version.split('-')[0]:pkg.version);pkg.version=base+'-'+Date.now();fs.writeFileSync('package.json',JSON.stringify(pkg,null,2)+'\\n');\"",
|
|
16
|
-
"publish:dev": "npm run build && npm run version:dev && npm publish --tag next && git checkout -- package.json",
|
|
17
14
|
"pack": "npm run build && npm pack",
|
|
18
15
|
"preview": "vite preview",
|
|
19
16
|
"check": "svelte-check --tsconfig ./tsconfig.app.json && tsc -p tsconfig.node.json",
|
|
@@ -111,7 +108,7 @@
|
|
|
111
108
|
},
|
|
112
109
|
"peerDependencies": {
|
|
113
110
|
"@fluentui/svg-icons": "^1.1.292",
|
|
114
|
-
"@streamscloud/streams-analytics-collector": "^2.0.
|
|
111
|
+
"@streamscloud/streams-analytics-collector": "^2.0.9",
|
|
115
112
|
"@urql/core": "^5.1.1",
|
|
116
113
|
"dompurify": "^3.2.6",
|
|
117
114
|
"mobile-detect": "^1.4.5",
|