@streamscloud/embeddable 5.1.3 → 6.0.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/ads/ad-card/mapper.js +1 -1
- package/dist/core/browser.d.ts +1 -0
- package/dist/core/browser.js +1 -0
- package/dist/core/continuation-token.d.ts +1 -0
- package/dist/core/continuation-token.js +3 -0
- package/dist/core/locale.d.ts +0 -1
- package/dist/core/locale.js +0 -12
- package/dist/core/media/media-item-url.service.d.ts +1 -1
- package/dist/core/media/media-item-url.service.js +1 -6
- package/dist/media-center/data-provider/index.d.ts +2 -0
- package/dist/media-center/data-provider/index.js +1 -0
- package/dist/media-center/data-provider/internal-media-center-data-provider.svelte.d.ts +8 -0
- package/dist/media-center/data-provider/internal-media-center-data-provider.svelte.js +44 -0
- package/dist/media-center/data-provider/operations.generated.d.ts +89 -0
- package/dist/media-center/data-provider/operations.generated.js +275 -0
- package/dist/media-center/data-provider/operations.graphql +25 -0
- package/dist/media-center/data-provider/types.d.ts +24 -0
- package/dist/media-center/data-provider/types.js +1 -0
- package/dist/media-center/index.d.ts +1 -0
- package/dist/media-center/index.js +1 -0
- package/dist/media-center/media-center/cmp.media-center.svelte +433 -0
- package/dist/media-center/media-center/cmp.media-center.svelte.d.ts +20 -0
- package/dist/media-center/media-center/index.d.ts +3 -0
- package/dist/media-center/media-center/index.js +2 -0
- package/dist/media-center/media-center/media-center-localization.d.ts +13 -0
- package/dist/media-center/media-center/media-center-localization.js +21 -0
- package/dist/media-center/media-center/overview.svelte +151 -0
- package/dist/media-center/media-center/overview.svelte.d.ts +13 -0
- package/dist/media-center/media-center/short-video-resources-generator.d.ts +8 -0
- package/dist/media-center/media-center/short-video-resources-generator.js +26 -0
- package/dist/media-center/media-center/types.d.ts +10 -0
- package/dist/media-center/media-center/types.js +5 -0
- package/dist/products/product-card/cmp.product-card.svelte +11 -6
- package/dist/products/product-card/mapper.js +3 -3
- package/dist/short-videos/short-video-card/cmp.short-video-card.svelte +118 -0
- package/dist/short-videos/short-video-card/cmp.short-video-card.svelte.d.ts +11 -0
- package/dist/short-videos/short-video-card/index.d.ts +2 -0
- package/dist/short-videos/short-video-card/index.js +1 -0
- package/dist/short-videos/short-video-card/types.d.ts +5 -0
- package/dist/short-videos/short-video-card/types.js +1 -0
- package/dist/short-videos/short-video-viewer/cmp.short-video-controls.svelte +3 -3
- package/dist/short-videos/short-video-viewer/cmp.short-video-controls.svelte.d.ts +2 -2
- package/dist/short-videos/short-video-viewer/cmp.short-video-viewer.svelte +8 -26
- package/dist/short-videos/short-video-viewer/cmp.short-video-viewer.svelte.d.ts +2 -3
- package/dist/short-videos/short-video-viewer/index.d.ts +1 -1
- package/dist/short-videos/short-video-viewer/mapper.js +6 -3
- package/dist/short-videos/short-video-viewer/types.d.ts +8 -6
- package/dist/short-videos/short-video-viewer/ui-manager.svelte.d.ts +0 -5
- package/dist/short-videos/short-video-viewer/ui-manager.svelte.js +0 -11
- package/dist/short-videos/short-videos-player/cmp.short-videos-player.svelte +16 -12
- package/dist/short-videos/short-videos-player/cmp.short-videos-player.svelte.d.ts +5 -15
- package/dist/short-videos/short-videos-player/controls.svelte +39 -4
- package/dist/short-videos/short-videos-player/controls.svelte.d.ts +3 -2
- package/dist/short-videos/short-videos-player/fade-mixins.scss +12 -0
- package/dist/short-videos/short-videos-player/index.d.ts +66 -36
- package/dist/short-videos/short-videos-player/index.js +40 -104
- package/dist/short-videos/short-videos-player/internal-short-video-player-provider.d.ts +17 -0
- package/dist/short-videos/short-videos-player/internal-short-video-player-provider.js +59 -0
- package/dist/short-videos/short-videos-player/operations.generated.d.ts +1 -0
- package/dist/short-videos/short-videos-player/operations.generated.js +2 -1
- package/dist/short-videos/short-videos-player/operations.graphql +1 -0
- package/dist/short-videos/short-videos-player/short-videos-player-view.svelte +36 -55
- package/dist/short-videos/short-videos-player/short-videos-player-view.svelte.d.ts +12 -15
- package/dist/short-videos/short-videos-player/types.d.ts +8 -29
- package/dist/short-videos/short-videos-player/types.js +1 -6
- package/dist/short-videos/short-videos-player/ui-manager.svelte.d.ts +6 -6
- package/dist/short-videos/short-videos-player/ui-manager.svelte.js +28 -16
- package/dist/streams/layout/element-views/cmp.short-video-stream-element.svelte +6 -1
- package/dist/streams/stream-page-viewer/index.d.ts +1 -0
- package/dist/streams/stream-page-viewer/index.js +1 -0
- package/dist/streams/stream-player/controls.svelte +2 -2
- package/dist/streams/stream-player/controls.svelte.d.ts +2 -2
- package/dist/streams/stream-player/index.d.ts +84 -27
- package/dist/streams/stream-player/index.js +46 -48
- package/dist/streams/stream-player/internal-stream-analytics-handler.d.ts +12 -0
- package/dist/streams/stream-player/internal-stream-analytics-handler.js +17 -0
- package/dist/streams/stream-player/internal-stream-player-data-provider.d.ts +10 -0
- package/dist/streams/stream-player/internal-stream-player-data-provider.js +48 -0
- package/dist/streams/stream-player/mapper.js +2 -0
- package/dist/streams/stream-player/operations.generated.d.ts +0 -2
- package/dist/streams/stream-player/operations.generated.js +2 -4
- package/dist/streams/stream-player/operations.graphql +0 -1
- package/dist/streams/stream-player/stream-player-buffer.svelte.d.ts +5 -5
- package/dist/streams/stream-player/stream-player-buffer.svelte.js +12 -27
- package/dist/streams/stream-player/{cmp.stream-player.svelte → stream-player.svelte} +19 -37
- package/dist/streams/stream-player/stream-player.svelte.d.ts +4 -0
- package/dist/streams/stream-player/types.d.ts +40 -0
- package/dist/ui/dropdown/cmp.dropdown.svelte +187 -0
- package/dist/ui/dropdown/cmp.dropdown.svelte.d.ts +23 -0
- package/dist/ui/dropdown/dropdown-ignore.d.ts +6 -0
- package/dist/ui/dropdown/dropdown-ignore.js +11 -0
- package/dist/ui/dropdown/index.d.ts +3 -0
- package/dist/ui/dropdown/index.js +2 -0
- package/dist/ui/player/index.d.ts +1 -1
- package/dist/ui/player/player-buffer.svelte.d.ts +3 -3
- package/package.json +8 -1
- package/dist/streams/stream-player/cmp.stream-player.svelte.d.ts +0 -22
|
@@ -0,0 +1,17 @@
|
|
|
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 InternalStreamAnalyticsHandler {
|
|
5
|
+
constructor(graphqlOrigin) {
|
|
6
|
+
AppEventsTracker.setEndpoint(constructGraphQLUrl(graphqlOrigin));
|
|
7
|
+
AppEventsTracker.setProfileId(getOrCreateProfileId());
|
|
8
|
+
}
|
|
9
|
+
setOrganizationId = (organizationId) => AppEventsTracker.setOrganizationId(organizationId);
|
|
10
|
+
trackStreamView = (streamId) => AppEventsTracker.trackStreamView(streamId);
|
|
11
|
+
trackStreamPageView = (pageId, streamId) => AppEventsTracker.trackStreamPageView(pageId, streamId);
|
|
12
|
+
trackStreamProductClicked = (productId, streamId) => AppEventsTracker.trackStreamProductClicked(productId, streamId);
|
|
13
|
+
trackStreamEngagementTime = (streamId, engagementTime) => AppEventsTracker.trackStreamEngagementTime(streamId, engagementTime);
|
|
14
|
+
trackStreamScrollDepth = (streamId, scrollDepth) => AppEventsTracker.trackStreamScrollDepth(streamId, scrollDepth);
|
|
15
|
+
reportPageVideoViews = (videoId, streamId) => AppEventsTracker.reportPageVideoViews(videoId, streamId);
|
|
16
|
+
trackShortVideoProgress = (pageId, videoId, progress, streamId) => AppEventsTracker.trackShortVideoProgress(pageId, videoId, progress, streamId);
|
|
17
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { IStreamPlayerDataProvider } from './types';
|
|
2
|
+
export declare class InternalStreamPlayerDataProvider implements IStreamPlayerDataProvider {
|
|
3
|
+
private graphql;
|
|
4
|
+
constructor(input: {
|
|
5
|
+
initiator?: string;
|
|
6
|
+
graphqlOrigin?: string;
|
|
7
|
+
});
|
|
8
|
+
getStream: IStreamPlayerDataProvider['getStream'];
|
|
9
|
+
getStreamPages: IStreamPlayerDataProvider['getStreamPages'];
|
|
10
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { ImageScale } from '../..';
|
|
2
|
+
import { createLocalGQLClient } from '../../core/graphql';
|
|
3
|
+
import { mapToStreamPageViewerModel } from '../stream-page-viewer';
|
|
4
|
+
import { mapToStreamPlayerModel } from './mapper';
|
|
5
|
+
import { GetStreamDocument, GetStreamPagesDocument } from './operations.generated';
|
|
6
|
+
export class InternalStreamPlayerDataProvider {
|
|
7
|
+
graphql;
|
|
8
|
+
constructor(input) {
|
|
9
|
+
const { graphqlOrigin, initiator } = input;
|
|
10
|
+
this.graphql = createLocalGQLClient(graphqlOrigin, initiator ? { 'x-initiator': initiator } : undefined);
|
|
11
|
+
}
|
|
12
|
+
getStream = async (id) => {
|
|
13
|
+
const streamPayload = await this.graphql.query(GetStreamDocument, { id }).toPromise();
|
|
14
|
+
if (!streamPayload.data?.stream) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
return mapToStreamPlayerModel(streamPayload.data.stream);
|
|
18
|
+
};
|
|
19
|
+
getStreamPages = async (streamId, continuationToken) => {
|
|
20
|
+
const emptyResult = { items: [], continuationToken: null };
|
|
21
|
+
if (continuationToken === null) {
|
|
22
|
+
return emptyResult;
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
const payload = await this.graphql
|
|
26
|
+
.query(GetStreamPagesDocument, {
|
|
27
|
+
input: {
|
|
28
|
+
limit: 10,
|
|
29
|
+
continuationToken,
|
|
30
|
+
filter: { streamId }
|
|
31
|
+
},
|
|
32
|
+
image_scale: ImageScale.OriginalEncoded
|
|
33
|
+
})
|
|
34
|
+
.toPromise();
|
|
35
|
+
const data = payload.data?.streamPages;
|
|
36
|
+
if (!data) {
|
|
37
|
+
return emptyResult;
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
items: data.items.map(mapToStreamPageViewerModel),
|
|
41
|
+
continuationToken: data.continuationToken
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return emptyResult;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
@@ -4,8 +4,10 @@ export const mapToStreamPlayerModel = (payload) => {
|
|
|
4
4
|
id: payload.id,
|
|
5
5
|
title: payload.title,
|
|
6
6
|
subTitle: payload.subTitle || null,
|
|
7
|
+
cover: payload.cover?.url || null,
|
|
7
8
|
createdAt: payload.createdAt,
|
|
8
9
|
publishedAt: payload.publishedAt,
|
|
10
|
+
organizationId: payload.ownerProfile.id,
|
|
9
11
|
header: {
|
|
10
12
|
name: headerDataProvider.name,
|
|
11
13
|
image: headerDataProvider.image
|
|
@@ -18,7 +18,6 @@ export type GetStreamQuery = {
|
|
|
18
18
|
image: string | null;
|
|
19
19
|
name: string;
|
|
20
20
|
id: string;
|
|
21
|
-
type: SchemaTypes.ProfileType;
|
|
22
21
|
};
|
|
23
22
|
availableFrom: {
|
|
24
23
|
image: string;
|
|
@@ -57,7 +56,6 @@ export type StreamPlayerPayloadFragment = {
|
|
|
57
56
|
image: string | null;
|
|
58
57
|
name: string;
|
|
59
58
|
id: string;
|
|
60
|
-
type: SchemaTypes.ProfileType;
|
|
61
59
|
};
|
|
62
60
|
availableFrom: {
|
|
63
61
|
image: string;
|
|
@@ -26,8 +26,7 @@ export const StreamPlayerPayloadFragmentDoc = {
|
|
|
26
26
|
selections: [
|
|
27
27
|
{ kind: 'Field', name: { kind: 'Name', value: 'image' } },
|
|
28
28
|
{ kind: 'Field', name: { kind: 'Name', value: 'name' } },
|
|
29
|
-
{ kind: 'Field', name: { kind: 'Name', value: 'id' } }
|
|
30
|
-
{ kind: 'Field', name: { kind: 'Name', value: 'type' } }
|
|
29
|
+
{ kind: 'Field', name: { kind: 'Name', value: 'id' } }
|
|
31
30
|
]
|
|
32
31
|
}
|
|
33
32
|
},
|
|
@@ -109,8 +108,7 @@ export const GetStreamDocument = {
|
|
|
109
108
|
selections: [
|
|
110
109
|
{ kind: 'Field', name: { kind: 'Name', value: 'image' } },
|
|
111
110
|
{ kind: 'Field', name: { kind: 'Name', value: 'name' } },
|
|
112
|
-
{ kind: 'Field', name: { kind: 'Name', value: 'id' } }
|
|
113
|
-
{ kind: 'Field', name: { kind: 'Name', value: 'type' } }
|
|
111
|
+
{ kind: 'Field', name: { kind: 'Name', value: 'id' } }
|
|
114
112
|
]
|
|
115
113
|
}
|
|
116
114
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type StreamPageViewerModel } from '../stream-page-viewer';
|
|
2
2
|
import type { IPlayerBuffer } from '../../ui/player';
|
|
3
|
-
import type {
|
|
3
|
+
import type { IStreamPlayerDataProvider } from './types';
|
|
4
4
|
export declare class StreamPlayerBuffer implements IPlayerBuffer<StreamPageViewerModel> {
|
|
5
5
|
readonly loaded: StreamPageViewerModel[];
|
|
6
6
|
readonly currentIndex: number;
|
|
@@ -9,17 +9,17 @@ export declare class StreamPlayerBuffer implements IPlayerBuffer<StreamPageViewe
|
|
|
9
9
|
readonly canLoadPrevious: boolean;
|
|
10
10
|
readonly navigationDisabled: boolean;
|
|
11
11
|
readonly animationDuration = 300;
|
|
12
|
-
private _pagesLoader;
|
|
13
12
|
private _currentIndex;
|
|
14
13
|
private _loaded;
|
|
15
|
-
|
|
14
|
+
private _pagesLoader;
|
|
15
|
+
constructor(init: {
|
|
16
16
|
streamId: string;
|
|
17
|
-
|
|
17
|
+
dataProvider: IStreamPlayerDataProvider;
|
|
18
18
|
});
|
|
19
19
|
loadMore: () => Promise<StreamPageViewerModel[]>;
|
|
20
20
|
loadNext: () => Promise<void>;
|
|
21
21
|
loadPrevious: () => Promise<void>;
|
|
22
22
|
setIndex: (index: number) => void;
|
|
23
|
-
reset: () => void
|
|
23
|
+
reset: () => Promise<void>;
|
|
24
24
|
private warmUpBuffer;
|
|
25
25
|
}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { ContinuationToken } from '../../core/continuation-token';
|
|
2
2
|
import { CursorDataLoader } from '../../core/data-loaders';
|
|
3
|
-
import { ImageScale } from '../../core/enums';
|
|
4
3
|
import { Utils } from '../../core/utils';
|
|
5
4
|
import {} from '../stream-page-viewer';
|
|
6
|
-
import { mapToStreamPageViewerModel } from '../stream-page-viewer/mapper';
|
|
7
|
-
import { GetStreamPagesDocument } from './operations.generated';
|
|
8
5
|
export class StreamPlayerBuffer {
|
|
9
6
|
loaded = $derived.by(() => this._loaded);
|
|
10
7
|
currentIndex = $derived.by(() => this._currentIndex);
|
|
@@ -13,34 +10,19 @@ export class StreamPlayerBuffer {
|
|
|
13
10
|
canLoadPrevious = $derived(this.currentIndex > 0);
|
|
14
11
|
navigationDisabled = $derived(!this.canLoadNext && !this.canLoadPrevious);
|
|
15
12
|
animationDuration = 300;
|
|
16
|
-
_pagesLoader;
|
|
17
13
|
_currentIndex = $state(-1);
|
|
18
14
|
_loaded = $state.raw([]);
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
_pagesLoader;
|
|
16
|
+
constructor(init) {
|
|
17
|
+
const { streamId, dataProvider } = init;
|
|
21
18
|
this._pagesLoader = new CursorDataLoader({
|
|
22
19
|
loadPage: async (continuationToken) => {
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
input: {
|
|
26
|
-
limit: 10,
|
|
27
|
-
continuationToken,
|
|
28
|
-
filter: {
|
|
29
|
-
streamId
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
image_scale: ImageScale.OriginalEncoded
|
|
33
|
-
})
|
|
34
|
-
.toPromise();
|
|
35
|
-
const data = payload.data?.streamPages;
|
|
36
|
-
if (!data) {
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
39
|
-
const items = data.items.map(mapToStreamPageViewerModel);
|
|
20
|
+
const result = await dataProvider.getStreamPages(streamId, continuationToken.toRawFormat());
|
|
21
|
+
const items = result.items;
|
|
40
22
|
this._loaded = [...this._loaded, ...items];
|
|
41
23
|
return {
|
|
42
24
|
items: items,
|
|
43
|
-
continuationToken: ContinuationToken.fromPayload(
|
|
25
|
+
continuationToken: ContinuationToken.fromPayload(result.continuationToken)
|
|
44
26
|
};
|
|
45
27
|
}
|
|
46
28
|
});
|
|
@@ -66,15 +48,18 @@ export class StreamPlayerBuffer {
|
|
|
66
48
|
this._currentIndex = index;
|
|
67
49
|
this.warmUpBuffer();
|
|
68
50
|
};
|
|
69
|
-
reset = () => {
|
|
70
|
-
this.
|
|
51
|
+
reset = async () => {
|
|
52
|
+
this._loaded = [];
|
|
53
|
+
this._currentIndex = -1;
|
|
54
|
+
await this._pagesLoader.reset();
|
|
55
|
+
this.warmUpBuffer();
|
|
71
56
|
};
|
|
72
57
|
warmUpBuffer = async () => {
|
|
73
58
|
const bufferSize = 2;
|
|
74
59
|
if (this.loaded.length >= this.currentIndex + bufferSize) {
|
|
75
60
|
return;
|
|
76
61
|
}
|
|
77
|
-
await this.
|
|
62
|
+
await this.loadMore();
|
|
78
63
|
if (this._currentIndex < 0) {
|
|
79
64
|
if (this.loaded.length > 0) {
|
|
80
65
|
this._currentIndex = 0;
|
|
@@ -7,9 +7,7 @@
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import { getOrCreateProfileId } from '../../core/analytics.profile-id';
|
|
11
10
|
import { handleEsc } from '../../core/document.event-handlers';
|
|
12
|
-
import { constructGraphQLUrl, createLocalGQLClient } from '../../core/graphql';
|
|
13
11
|
import { toastrWarning } from '../../core/toastr';
|
|
14
12
|
import { ShortVideoViewer } from '../../short-videos/short-video-viewer';
|
|
15
13
|
import { mapToShortVideoViewerModel } from '../layout/models';
|
|
@@ -19,15 +17,12 @@ import { PlayerSlider } from '../../ui/player';
|
|
|
19
17
|
import { SpotlightLayout } from '../../ui/spotlight-layout';
|
|
20
18
|
import { SwipeIndicator } from '../../ui/swipe-indicator';
|
|
21
19
|
import { default as Controls } from './controls.svelte';
|
|
22
|
-
import { mapToStreamPlayerModel } from './mapper';
|
|
23
|
-
import { GetStreamDocument } from './operations.generated';
|
|
24
20
|
import { default as Overview } from './stream-overview.svelte';
|
|
25
21
|
import { StreamPlayerBuffer } from './stream-player-buffer.svelte';
|
|
26
22
|
import { StreamPlayerLocalization } from './stream-player-localization';
|
|
27
23
|
import { StreamPlayerUiManager } from './ui-manager.svelte';
|
|
28
|
-
import { AppEventsTracker } from '@streamscloud/streams-analytics-collector';
|
|
29
24
|
import { onMount } from 'svelte';
|
|
30
|
-
let { streamId,
|
|
25
|
+
let { streamId, dataProvider, analyticsHandler, localization: localizationInit = 'en', showStreamsCloudWatermark, postSocialInteractionsHandler, on } = $props();
|
|
31
26
|
const localization = $derived(new StreamPlayerLocalization(localizationInit));
|
|
32
27
|
let model = $state(null);
|
|
33
28
|
let buffer = $state.raw(null);
|
|
@@ -54,27 +49,21 @@ const resetInactivityTimer = () => {
|
|
|
54
49
|
}, inactiveTimeSeconds * 1000);
|
|
55
50
|
};
|
|
56
51
|
onMount(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
57
|
-
var _a, _b
|
|
52
|
+
var _a, _b;
|
|
58
53
|
uiManager.overviewCollapsed = window && window.innerWidth < window.innerHeight;
|
|
59
54
|
try {
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
if (!((_a = streamPayload.data) === null || _a === void 0 ? void 0 : _a.stream)) {
|
|
55
|
+
const stream = yield dataProvider.getStream(streamId);
|
|
56
|
+
if (!stream) {
|
|
63
57
|
toastrWarning(localization.streamNotFound);
|
|
64
|
-
(
|
|
58
|
+
(_a = on === null || on === void 0 ? void 0 : on.playerClosed) === null || _a === void 0 ? void 0 : _a.call(on);
|
|
65
59
|
return;
|
|
66
60
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
(_c = on === null || on === void 0 ? void 0 : on.streamActivated) === null || _c === void 0 ? void 0 : _c.call(on, {
|
|
70
|
-
ownerId: streamPayload.data.stream.ownerProfile.id,
|
|
71
|
-
title: streamPayload.data.stream.title,
|
|
72
|
-
image: ((_d = streamPayload.data.stream.cover) === null || _d === void 0 ? void 0 : _d.url) || null
|
|
73
|
-
});
|
|
61
|
+
analyticsHandler === null || analyticsHandler === void 0 ? void 0 : analyticsHandler.setOrganizationId(stream.organizationId);
|
|
62
|
+
(_b = on === null || on === void 0 ? void 0 : on.streamActivated) === null || _b === void 0 ? void 0 : _b.call(on, { title: stream.title, image: stream.cover });
|
|
74
63
|
// start tracking the stream
|
|
75
|
-
model =
|
|
76
|
-
buffer = new StreamPlayerBuffer({
|
|
77
|
-
|
|
64
|
+
model = stream;
|
|
65
|
+
buffer = new StreamPlayerBuffer({ streamId, dataProvider: dataProvider });
|
|
66
|
+
analyticsHandler === null || analyticsHandler === void 0 ? void 0 : analyticsHandler.trackStreamView(stream.id);
|
|
78
67
|
startActivityTracking();
|
|
79
68
|
}
|
|
80
69
|
finally {
|
|
@@ -144,7 +133,7 @@ const onPageActivated = (id) => {
|
|
|
144
133
|
const page = buffer === null || buffer === void 0 ? void 0 : buffer.loaded.find((x) => x.id === id);
|
|
145
134
|
background = (page === null || page === void 0 ? void 0 : page.cover) || null;
|
|
146
135
|
if (page) {
|
|
147
|
-
|
|
136
|
+
analyticsHandler === null || analyticsHandler === void 0 ? void 0 : analyticsHandler.trackStreamPageView(id, streamId);
|
|
148
137
|
const currentIndex = buffer === null || buffer === void 0 ? void 0 : buffer.loaded.findIndex((p) => p.id === id);
|
|
149
138
|
if (currentIndex !== undefined && currentIndex > maxPageIndexViewed) {
|
|
150
139
|
maxPageIndexViewed = currentIndex;
|
|
@@ -152,23 +141,23 @@ const onPageActivated = (id) => {
|
|
|
152
141
|
}
|
|
153
142
|
};
|
|
154
143
|
const onProductCardClick = (productId) => {
|
|
155
|
-
|
|
144
|
+
analyticsHandler === null || analyticsHandler === void 0 ? void 0 : analyticsHandler.trackStreamProductClicked(productId, streamId);
|
|
156
145
|
};
|
|
157
146
|
const onPlayerClose = () => {
|
|
158
147
|
var _a;
|
|
159
148
|
stopActivityTracking();
|
|
160
|
-
|
|
149
|
+
analyticsHandler === null || analyticsHandler === void 0 ? void 0 : analyticsHandler.trackStreamEngagementTime(streamId, totalEngagementTimeSeconds);
|
|
161
150
|
if (buffer && buffer.loaded.length > 0) {
|
|
162
151
|
let scrollDepth = Math.round(((maxPageIndexViewed + 1) / buffer.loaded.length) * 100);
|
|
163
|
-
|
|
152
|
+
analyticsHandler === null || analyticsHandler === void 0 ? void 0 : analyticsHandler.trackStreamScrollDepth(streamId, scrollDepth);
|
|
164
153
|
}
|
|
165
|
-
(_a = on === null || on === void 0 ? void 0 : on.
|
|
154
|
+
(_a = on === null || on === void 0 ? void 0 : on.playerClosed) === null || _a === void 0 ? void 0 : _a.call(on);
|
|
166
155
|
};
|
|
167
156
|
const onPageDeactivated = (itemId) => {
|
|
168
|
-
|
|
157
|
+
analyticsHandler === null || analyticsHandler === void 0 ? void 0 : analyticsHandler.reportPageVideoViews(itemId, streamId);
|
|
169
158
|
};
|
|
170
159
|
const onProgress = (pageId, videoId, progress) => {
|
|
171
|
-
|
|
160
|
+
analyticsHandler === null || analyticsHandler === void 0 ? void 0 : analyticsHandler.trackShortVideoProgress(pageId, videoId, progress, streamId);
|
|
172
161
|
};
|
|
173
162
|
</script>
|
|
174
163
|
|
|
@@ -211,7 +200,7 @@ const onProgress = (pageId, videoId, progress) => {
|
|
|
211
200
|
progress: (progress) => onProgress(item.id, item.shortVideo.id, progress)
|
|
212
201
|
}}
|
|
213
202
|
autoplay="on-appearance"
|
|
214
|
-
socialInteractionsHandler={
|
|
203
|
+
socialInteractionsHandler={postSocialInteractionsHandler}
|
|
215
204
|
localization={localization.shortVideoViewerLocalization}
|
|
216
205
|
showAttachments={uiManager.showShortVideoOverlay}
|
|
217
206
|
showControls={uiManager.showShortVideoOverlay} />
|
|
@@ -239,7 +228,7 @@ const onProgress = (pageId, videoId, progress) => {
|
|
|
239
228
|
buffer={buffer}
|
|
240
229
|
uiManager={uiManager}
|
|
241
230
|
localization={localization}
|
|
242
|
-
|
|
231
|
+
postSocialInteractionsHandler={postSocialInteractionsHandler}
|
|
243
232
|
on={{
|
|
244
233
|
closePlayer: () => onPlayerClose(),
|
|
245
234
|
productClick: (productId: String) => onProductCardClick(productId)
|
|
@@ -296,11 +285,4 @@ const onProgress = (pageId, videoId, progress) => {
|
|
|
296
285
|
.stream-player__content {
|
|
297
286
|
width: 100%;
|
|
298
287
|
height: 100%;
|
|
299
|
-
--short-video-viewer--actions-panel--bottom: 5rem;
|
|
300
|
-
/* Set 'container-type: inline-size;' to reference container*/
|
|
301
|
-
}
|
|
302
|
-
@container (width < 576px) {
|
|
303
|
-
.stream-player__content {
|
|
304
|
-
--short-video-viewer--actions-panel--top: 5rem;
|
|
305
|
-
}
|
|
306
288
|
}</style>
|
|
@@ -1,12 +1,52 @@
|
|
|
1
|
+
import type { Locale } from '../../core/locale';
|
|
2
|
+
import type { IPostSocialInteractionsHandler } from '../../short-videos/short-video-viewer';
|
|
3
|
+
import type { StreamPageViewerModel } from '../stream-page-viewer';
|
|
4
|
+
import type { IStreamPlayerLocalization } from './stream-player-localization';
|
|
1
5
|
export type StreamPlayerModel = {
|
|
2
6
|
id: string;
|
|
3
7
|
title: string;
|
|
8
|
+
cover: string | null;
|
|
4
9
|
subTitle: string | null;
|
|
5
10
|
createdAt: string;
|
|
6
11
|
publishedAt: string | null;
|
|
12
|
+
organizationId: string;
|
|
7
13
|
header: {
|
|
8
14
|
image: string | null;
|
|
9
15
|
name: string;
|
|
10
16
|
};
|
|
11
17
|
pagesCount: number;
|
|
12
18
|
};
|
|
19
|
+
export type StreamPlayerProps = PlayerSettings & {
|
|
20
|
+
dataProvider: IStreamPlayerDataProvider;
|
|
21
|
+
analyticsHandler?: IStreamAnalyticsHandler;
|
|
22
|
+
};
|
|
23
|
+
export type PlayerSettings = {
|
|
24
|
+
streamId: string;
|
|
25
|
+
localization?: IStreamPlayerLocalization | Locale;
|
|
26
|
+
showStreamsCloudWatermark?: boolean;
|
|
27
|
+
postSocialInteractionsHandler?: IPostSocialInteractionsHandler;
|
|
28
|
+
on?: {
|
|
29
|
+
streamActivated?: (data: {
|
|
30
|
+
title: string;
|
|
31
|
+
image: string | null;
|
|
32
|
+
}) => void;
|
|
33
|
+
playerClosed?: () => void;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
export interface IStreamPlayerDataProvider {
|
|
37
|
+
getStream: (streamId: string) => Promise<StreamPlayerModel | null>;
|
|
38
|
+
getStreamPages: (streamId: string, continuationToken: string | null | undefined) => Promise<{
|
|
39
|
+
items: StreamPageViewerModel[];
|
|
40
|
+
continuationToken: string | null;
|
|
41
|
+
}>;
|
|
42
|
+
}
|
|
43
|
+
export interface IStreamAnalyticsHandler {
|
|
44
|
+
setOrganizationId: (organizationId: string) => void;
|
|
45
|
+
trackStreamView: (streamId: string) => void;
|
|
46
|
+
trackStreamPageView: (pageId: string, streamId: string) => void;
|
|
47
|
+
trackStreamProductClicked: (productId: string, streamId: string) => void;
|
|
48
|
+
trackStreamEngagementTime: (streamId: string, engagementTime: number) => void;
|
|
49
|
+
trackStreamScrollDepth: (streamId: string, scrollDepth: number) => void;
|
|
50
|
+
reportPageVideoViews: (videoId: string, streamId: string) => void;
|
|
51
|
+
trackShortVideoProgress: (pageId: string, videoId: string, progress: number, streamId: string) => void;
|
|
52
|
+
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
<script lang="ts">import { runningInBrowser } from '../../core/browser';
|
|
2
|
+
import { isIgnored } from './dropdown-ignore';
|
|
3
|
+
import { Icon } from '../icon';
|
|
4
|
+
import IconChevronDown from '@fluentui/svg-icons/icons/chevron_down_20_regular.svg?raw';
|
|
5
|
+
import { createPopper } from '@popperjs/core';
|
|
6
|
+
import { onDestroy } from 'svelte';
|
|
7
|
+
let { position = 'bottom-start', disabled = false, keepDropdownOpen = false, fixedPosition = false, offset = 8, boundaryMargin = 8, on, children, trigger, isOpenRequested } = $props();
|
|
8
|
+
$effect(() => {
|
|
9
|
+
var _a;
|
|
10
|
+
(_a = on === null || on === void 0 ? void 0 : on.mounted) === null || _a === void 0 ? void 0 : _a.call(on, {
|
|
11
|
+
toggleOpen: (value) => {
|
|
12
|
+
if (value === undefined) {
|
|
13
|
+
if (opened) {
|
|
14
|
+
close();
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
open();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
if (!value) {
|
|
22
|
+
close();
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
open();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
const id = Math.random();
|
|
32
|
+
let opened = $state(false);
|
|
33
|
+
$effect(() => {
|
|
34
|
+
var _a, _b;
|
|
35
|
+
if (opened) {
|
|
36
|
+
(_a = on === null || on === void 0 ? void 0 : on.opened) === null || _a === void 0 ? void 0 : _a.call(on);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
(_b = on === null || on === void 0 ? void 0 : on.closed) === null || _b === void 0 ? void 0 : _b.call(on);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
$effect(() => {
|
|
43
|
+
popper === null || popper === void 0 ? void 0 : popper.setOptions({ placement: position });
|
|
44
|
+
});
|
|
45
|
+
$effect(() => {
|
|
46
|
+
if (isOpenRequested) {
|
|
47
|
+
open();
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
let triggerRef = $state(null);
|
|
51
|
+
let dropdownRef;
|
|
52
|
+
let popper;
|
|
53
|
+
onDestroy(() => {
|
|
54
|
+
removeWindowClickListener();
|
|
55
|
+
});
|
|
56
|
+
const open = () => {
|
|
57
|
+
opened = true;
|
|
58
|
+
window.addEventListener('click', close);
|
|
59
|
+
};
|
|
60
|
+
const close = () => {
|
|
61
|
+
opened = false;
|
|
62
|
+
removeWindowClickListener();
|
|
63
|
+
};
|
|
64
|
+
const removeWindowClickListener = () => {
|
|
65
|
+
if (runningInBrowser()) {
|
|
66
|
+
window.removeEventListener('click', close);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
const handleClick = (event) => {
|
|
70
|
+
event.stopPropagation();
|
|
71
|
+
if (disabled) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (!opened) {
|
|
75
|
+
open();
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const checkCanClose = (node) => {
|
|
79
|
+
if (keepDropdownOpen) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
while (node && node !== dropdownRef) {
|
|
83
|
+
if (isIgnored(node) || node.classList.contains('flatpickr-calendar')) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
node = node.parentElement;
|
|
87
|
+
}
|
|
88
|
+
return true;
|
|
89
|
+
};
|
|
90
|
+
if (checkCanClose(event.target)) {
|
|
91
|
+
close();
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
const initPopper = (node, _triggerEl) => {
|
|
95
|
+
popper = createPopper(_triggerEl, node, {
|
|
96
|
+
placement: position,
|
|
97
|
+
strategy: fixedPosition ? 'fixed' : 'absolute',
|
|
98
|
+
modifiers: [
|
|
99
|
+
{
|
|
100
|
+
name: 'offset',
|
|
101
|
+
options: {
|
|
102
|
+
offset: () => {
|
|
103
|
+
return [0, offset];
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
{ name: 'eventListeners', enabled: opened },
|
|
108
|
+
{ name: 'flip' },
|
|
109
|
+
{
|
|
110
|
+
name: 'preventOverflow',
|
|
111
|
+
options: {
|
|
112
|
+
boundary: document.body,
|
|
113
|
+
padding: boundaryMargin
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
]
|
|
117
|
+
});
|
|
118
|
+
return {
|
|
119
|
+
update(_triggerEl) {
|
|
120
|
+
popper.state.elements.reference = _triggerEl;
|
|
121
|
+
popper.update();
|
|
122
|
+
},
|
|
123
|
+
destroy() {
|
|
124
|
+
popper.destroy();
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
};
|
|
128
|
+
</script>
|
|
129
|
+
|
|
130
|
+
<div class="dropdown" class:dropdown--disabled={disabled} onclick={handleClick} onkeydown={() => ({})} bind:this={dropdownRef} role="none">
|
|
131
|
+
<button type="button" class="dropdown__trigger" bind:this={triggerRef}>
|
|
132
|
+
{#if trigger}
|
|
133
|
+
{@render trigger()}
|
|
134
|
+
{:else}
|
|
135
|
+
<Icon src={IconChevronDown} />
|
|
136
|
+
{/if}
|
|
137
|
+
</button>
|
|
138
|
+
{#if opened}
|
|
139
|
+
<div use:initPopper={triggerRef} class="dropdown__content" role="tooltip" tabindex="-1">
|
|
140
|
+
{@render children()}
|
|
141
|
+
</div>
|
|
142
|
+
{/if}
|
|
143
|
+
</div>
|
|
144
|
+
|
|
145
|
+
<style>@keyframes fadeIn {
|
|
146
|
+
0% {
|
|
147
|
+
opacity: 1;
|
|
148
|
+
}
|
|
149
|
+
50% {
|
|
150
|
+
opacity: 0.4;
|
|
151
|
+
}
|
|
152
|
+
100% {
|
|
153
|
+
opacity: 1;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
.dropdown {
|
|
157
|
+
--_dropdown--width: var(--dropdown--width, auto);
|
|
158
|
+
--_dropdown--content--background-color: var(--dropdown--content--background-color, transparent);
|
|
159
|
+
--_dropdown--content--box-shadow: var(--dropdown--content--box-shadow, none);
|
|
160
|
+
height: 100%;
|
|
161
|
+
width: var(--_dropdown--width);
|
|
162
|
+
-webkit-user-drag: none;
|
|
163
|
+
user-select: none;
|
|
164
|
+
}
|
|
165
|
+
.dropdown :global([contenteditable]) {
|
|
166
|
+
user-select: text;
|
|
167
|
+
}
|
|
168
|
+
.dropdown__trigger {
|
|
169
|
+
height: 100%;
|
|
170
|
+
width: 100%;
|
|
171
|
+
display: flex;
|
|
172
|
+
align-items: center;
|
|
173
|
+
line-height: 1;
|
|
174
|
+
}
|
|
175
|
+
.dropdown--disabled {
|
|
176
|
+
opacity: 0.5;
|
|
177
|
+
pointer-events: none;
|
|
178
|
+
}
|
|
179
|
+
.dropdown__content {
|
|
180
|
+
box-shadow: var(--_dropdown--content--box-shadow);
|
|
181
|
+
background: var(--_dropdown--content--background-color);
|
|
182
|
+
width: max-content;
|
|
183
|
+
z-index: 999;
|
|
184
|
+
}
|
|
185
|
+
.dropdown :global([data-popper-escaped]) {
|
|
186
|
+
visibility: hidden !important;
|
|
187
|
+
}</style>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { DropdownPosition } from './index';
|
|
2
|
+
import { type Snippet } from 'svelte';
|
|
3
|
+
type Props = {
|
|
4
|
+
position?: DropdownPosition;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
keepDropdownOpen?: boolean;
|
|
7
|
+
fixedPosition?: boolean;
|
|
8
|
+
offset?: number;
|
|
9
|
+
boundaryMargin?: number;
|
|
10
|
+
on?: {
|
|
11
|
+
opened?: () => void;
|
|
12
|
+
closed?: () => void;
|
|
13
|
+
mounted?: (callbacks: {
|
|
14
|
+
toggleOpen: (value?: boolean) => void;
|
|
15
|
+
}) => void;
|
|
16
|
+
};
|
|
17
|
+
children: Snippet;
|
|
18
|
+
trigger?: Snippet;
|
|
19
|
+
isOpenRequested?: boolean;
|
|
20
|
+
};
|
|
21
|
+
declare const Cmp: import("svelte").Component<Props, {}, "">;
|
|
22
|
+
type Cmp = ReturnType<typeof Cmp>;
|
|
23
|
+
export default Cmp;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** @type {import('svelte/action').Action} */
|
|
2
|
+
export declare const dropdownIgnore: (node: HTMLElement, value?: boolean) => {
|
|
3
|
+
destroy(): void;
|
|
4
|
+
};
|
|
5
|
+
export declare const ignoreAttribute = "dropdownIgnore";
|
|
6
|
+
export declare const isIgnored: (node: HTMLElement) => boolean;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** @type {import('svelte/action').Action} */
|
|
2
|
+
export const dropdownIgnore = (node, value = true) => {
|
|
3
|
+
node.dataset[ignoreAttribute] = value.toString();
|
|
4
|
+
return {
|
|
5
|
+
destroy() {
|
|
6
|
+
// the node has been removed from the DOM
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
export const ignoreAttribute = 'dropdownIgnore';
|
|
11
|
+
export const isIgnored = (node) => node.dataset[ignoreAttribute] === 'true';
|