@streamscloud/embeddable 8.2.0 → 9.0.0

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.
Files changed (97) hide show
  1. package/dist/ads/ad-card/cmp.ad-card.svelte +8 -5
  2. package/dist/ads/ad-card/cmp.ad-card.svelte.d.ts +2 -0
  3. package/dist/content-player/cmp.content-player.svelte +1 -0
  4. package/dist/content-player/content-player-config.svelte.d.ts +8 -0
  5. package/dist/content-player/content-player-config.svelte.js +9 -1
  6. package/dist/content-player/controls-and-attachments.svelte +1 -0
  7. package/dist/core/enums.d.ts +5 -1
  8. package/dist/core/enums.js +4 -0
  9. package/dist/marketing-tracking/index.d.ts +2 -0
  10. package/dist/marketing-tracking/index.js +1 -0
  11. package/dist/marketing-tracking/service.d.ts +11 -0
  12. package/dist/marketing-tracking/service.js +35 -0
  13. package/dist/marketing-tracking/types.d.ts +5 -0
  14. package/dist/media-center/config/internal-media-center-analytics-handler.d.ts +3 -2
  15. package/dist/media-center/config/internal-media-center-analytics-handler.js +1 -0
  16. package/dist/media-center/config/internal-media-center-config.d.ts +1 -1
  17. package/dist/media-center/config/internal-media-center-config.js +11 -11
  18. package/dist/media-center/config/operations.generated.d.ts +4 -4
  19. package/dist/media-center/config/operations.generated.js +5 -8
  20. package/dist/media-center/config/operations.graphql +3 -3
  21. package/dist/media-center/config/types.d.ts +7 -5
  22. package/dist/media-center/config/types.js +1 -1
  23. package/dist/media-center/media-center/cmp.media-center.svelte +74 -17
  24. package/dist/media-center/media-center/cmp.media-center.svelte.d.ts +3 -3
  25. package/dist/media-center/media-center/discover-panel-handler.svelte.d.ts +5 -2
  26. package/dist/media-center/media-center/discover-panel-handler.svelte.js +8 -3
  27. package/dist/media-center/media-center/discover-panel.svelte +1 -1
  28. package/dist/media-center/media-center/discover-panel.svelte.d.ts +2 -2
  29. package/dist/media-center/media-center/post-player-provider-generator.d.ts +8 -0
  30. package/dist/media-center/media-center/{short-video-resources-generator.js → post-player-provider-generator.js} +8 -3
  31. package/dist/media-center/media-center/types.d.ts +1 -1
  32. package/dist/posts/attachments/cmp.attachments.svelte +14 -2
  33. package/dist/posts/attachments/cmp.attachments.svelte.d.ts +2 -0
  34. package/dist/posts/handlers/index.d.ts +1 -0
  35. package/dist/posts/handlers/index.js +1 -0
  36. package/dist/{short-videos/short-videos-player/internal-short-video-analytics-handler.d.ts → posts/handlers/internal-post-analytics-handler.d.ts} +3 -2
  37. package/dist/{short-videos/short-videos-player/internal-short-video-analytics-handler.js → posts/handlers/internal-post-analytics-handler.js} +2 -1
  38. package/dist/posts/model/post-model.d.ts +2 -0
  39. package/dist/posts/model/post-model.js +3 -0
  40. package/dist/posts/model/types.d.ts +2 -1
  41. package/dist/posts/model/types.js +1 -1
  42. package/dist/posts/post-viewer/attachments-horizontal.svelte +5 -4
  43. package/dist/posts/post-viewer/attachments-horizontal.svelte.d.ts +2 -0
  44. package/dist/posts/post-viewer/cmp.post-viewer.svelte +13 -2
  45. package/dist/posts/post-viewer/cmp.post-viewer.svelte.d.ts +2 -0
  46. package/dist/posts/post-viewer/mapper.js +18 -1
  47. package/dist/{short-videos/short-videos-player/cmp.short-videos-player.svelte → posts/posts-player/cmp.posts-player.svelte} +3 -3
  48. package/dist/posts/posts-player/cmp.posts-player.svelte.d.ts +4 -0
  49. package/dist/posts/posts-player/index.d.ts +31 -17
  50. package/dist/posts/posts-player/index.js +48 -31
  51. package/dist/posts/posts-player/mapper.d.ts +3 -0
  52. package/dist/{short-videos/short-videos-player → posts/posts-player}/mapper.js +2 -2
  53. package/dist/posts/posts-player/operations.generated.d.ts +80 -0
  54. package/dist/posts/posts-player/operations.generated.js +229 -0
  55. package/dist/posts/posts-player/operations.graphql +7 -0
  56. package/dist/posts/posts-player/posts-player-view.svelte +38 -4
  57. package/dist/posts/posts-player/posts-player-view.svelte.d.ts +5 -1
  58. package/dist/posts/posts-player/types.d.ts +7 -1
  59. package/dist/products/product-card/cmp.product-card.svelte +10 -7
  60. package/dist/products/product-card/cmp.product-card.svelte.d.ts +2 -0
  61. package/dist/products/product-card/mapper.d.ts +3 -1
  62. package/dist/products/product-card/mapper.js +2 -2
  63. package/dist/short-videos/data-providers/index.d.ts +1 -0
  64. package/dist/short-videos/data-providers/index.js +1 -0
  65. package/dist/short-videos/{short-videos-player/internal-short-video-player-provider.d.ts → data-providers/internal-short-video-player-items-provider.d.ts} +4 -4
  66. package/dist/short-videos/{short-videos-player/internal-short-video-player-provider.js → data-providers/internal-short-video-player-items-provider.js} +3 -3
  67. package/dist/short-videos/{short-videos-player → data-providers}/operations.generated.d.ts +0 -78
  68. package/dist/short-videos/{short-videos-player → data-providers}/operations.generated.js +2 -234
  69. package/dist/short-videos/{short-videos-player → data-providers}/operations.graphql +1 -9
  70. package/dist/short-videos/short-videos-player/index.d.ts +13 -62
  71. package/dist/short-videos/short-videos-player/index.js +76 -30
  72. package/dist/streams/layout/cmp.slot-content.svelte +14 -6
  73. package/dist/streams/layout/cmp.slot-content.svelte.d.ts +2 -0
  74. package/dist/streams/layout/element-views/cmp.container-stream-element.svelte +7 -2
  75. package/dist/streams/layout/element-views/cmp.container-stream-element.svelte.d.ts +2 -0
  76. package/dist/streams/layout/element-views/cmp.short-video-stream-element.svelte +8 -2
  77. package/dist/streams/layout/element-views/cmp.short-video-stream-element.svelte.d.ts +2 -0
  78. package/dist/streams/layout/element-views/cmp.stream-element.svelte +3 -2
  79. package/dist/streams/layout/element-views/cmp.stream-element.svelte.d.ts +2 -0
  80. package/dist/streams/layout/index.d.ts +1 -0
  81. package/dist/streams/layout/models/mapper.js +2 -1
  82. package/dist/streams/layout/serializer.svelte.js +0 -1
  83. package/dist/streams/layout/types.d.ts +4 -0
  84. package/dist/streams/layout/types.js +1 -0
  85. package/dist/streams/stream-page-viewer/cmp.stream-page-viewer.svelte +2 -2
  86. package/dist/streams/stream-page-viewer/cmp.stream-page-viewer.svelte.d.ts +2 -0
  87. package/dist/streams/stream-player/stream-player-view.svelte +15 -3
  88. package/dist/ui/player-slider/player-buffer.svelte.d.ts +1 -0
  89. package/dist/ui/swipe-indicator/cmp.swipe-indicator.svelte +7 -8
  90. package/package.json +1 -1
  91. package/dist/media-center/media-center/short-video-resources-generator.d.ts +0 -8
  92. package/dist/short-videos/short-videos-player/cmp.short-videos-player.svelte.d.ts +0 -4
  93. package/dist/short-videos/short-videos-player/mapper.d.ts +0 -3
  94. package/dist/short-videos/short-videos-player/short-videos-player-view.svelte +0 -82
  95. package/dist/short-videos/short-videos-player/short-videos-player-view.svelte.d.ts +0 -8
  96. package/dist/short-videos/short-videos-player/types.d.ts +0 -26
  97. /package/dist/{short-videos/short-videos-player → marketing-tracking}/types.js +0 -0
@@ -1,8 +1,10 @@
1
- <script lang="ts">import { toPriceRepresentation } from '../../products/price-helper';
1
+ <script lang="ts">var _a;
2
+ import { enrichAdLinkWithTracking } from '../../marketing-tracking';
3
+ import { toPriceRepresentation } from '../../products/price-helper';
2
4
  import { Button, ButtonSize } from '../../ui/button';
3
5
  import { Image } from '../../ui/image';
4
6
  import { LineClamp } from '../../ui/line-clamp';
5
- let { ad, inert = false, on } = $props();
7
+ let { ad, trackingParams, inert = false, on } = $props();
6
8
  const trackImpression = (node) => {
7
9
  if (on === null || on === void 0 ? void 0 : on.impression) {
8
10
  const observer = new IntersectionObserver((entries) => {
@@ -22,12 +24,13 @@ const trackImpression = (node) => {
22
24
  };
23
25
  }
24
26
  };
27
+ const enrichedLink = $derived(((_a = ad.ctaButton) === null || _a === void 0 ? void 0 : _a.url) ? enrichAdLinkWithTracking({ link: ad.ctaButton.url, adId: ad.id, trackingParams }) : null);
25
28
  const handleAdClick = () => {
26
29
  if (on === null || on === void 0 ? void 0 : on.click) {
27
30
  on.click(ad.id);
28
31
  }
29
- if (ad.ctaButton) {
30
- window.open(ad.ctaButton.url, '_blank');
32
+ if (enrichedLink) {
33
+ window.open(enrichedLink, '_blank', 'noopener noreferrer');
31
34
  }
32
35
  };
33
36
  </script>
@@ -60,7 +63,7 @@ const handleAdClick = () => {
60
63
  {/if}
61
64
  </div>
62
65
  <div class="ad-card__button-container">
63
- {#if ad.ctaButton && ad.ctaButton.url && ad.ctaButton.text}
66
+ {#if ad.ctaButton && enrichedLink && ad.ctaButton.text}
64
67
  <div class="ad-card__button">
65
68
  <Button
66
69
  size={ButtonSize.Standard}
@@ -1,6 +1,8 @@
1
+ import { type TrackingParams } from '../../marketing-tracking';
1
2
  import type { AdCardModel } from './types';
2
3
  type Props = {
3
4
  ad: AdCardModel;
5
+ trackingParams: TrackingParams;
4
6
  inert?: boolean;
5
7
  on?: {
6
8
  click?: (id: string) => void;
@@ -171,6 +171,7 @@ const variables = $derived.by(() => {
171
171
  {#if postModel}
172
172
  <PostViewer
173
173
  model={postModel}
174
+ trackingParams={config.trackingParams}
174
175
  socialInteractionsHandler={config.socialInteractionsHandler}
175
176
  enableAttachments={config.uiManager.showPostOverlayAttachments}
176
177
  enableControls={config.uiManager.showPostOverlayControls}
@@ -15,6 +15,7 @@ export declare class ContentPlayerConfig<T extends {
15
15
  readonly socialInteractionsHandler: IPostSocialInteractionsHandler | undefined;
16
16
  readonly uiManager: ContentPlayerUIManager;
17
17
  private _mediaCenterData;
18
+ private _trackingParams;
18
19
  private _mappers;
19
20
  private mappedPostsCache;
20
21
  constructor(init: {
@@ -25,16 +26,19 @@ export declare class ContentPlayerConfig<T extends {
25
26
  settings?: ContentPlayerSettings;
26
27
  callbacks?: ContentPlayerCallbacks;
27
28
  playerSliderCallbacks?: PlayerSliderCallbacks<T>;
29
+ trackingParams?: ContentPlayerTrackingParams | null;
28
30
  });
29
31
  get mediaCenterControlsPanel(): MediaCenterData['controlsPanel'] | null;
30
32
  get mediaCenterCallbacks(): MediaCenterData['callbacks'] | null;
31
33
  get playerLogo(): string | null;
32
34
  get fadeContent(): boolean;
35
+ get trackingParams(): ContentPlayerConfig<T>['_trackingParams'];
33
36
  itemAsPostViewerModel: (item: T & {
34
37
  mediaIndex?: number;
35
38
  }) => PostModel | null;
36
39
  setBackgroundImageUrl: (imageUrl: string | null) => void;
37
40
  updateMediaCenterData: (data: MediaCenterData | undefined) => void;
41
+ updateTrackingParams: (data: ContentPlayerTrackingParams | null) => void;
38
42
  }
39
43
  export type ContentPlayerMappers<T> = {
40
44
  postModelFromCurrentItem: (item: T) => IPostModel | null;
@@ -47,3 +51,7 @@ export type ContentPlayerCallbacks = {
47
51
  adClick?: (adId: string, postId: string) => void;
48
52
  adImpression?: (adId: string, postId: string) => void;
49
53
  };
54
+ export type ContentPlayerTrackingParams = {
55
+ streamId?: string;
56
+ campaignId?: string;
57
+ } | false;
@@ -9,11 +9,13 @@ export class ContentPlayerConfig {
9
9
  socialInteractionsHandler;
10
10
  uiManager = new ContentPlayerUIManager();
11
11
  _mediaCenterData = $state.raw(null);
12
+ _trackingParams = $state.raw(null);
12
13
  _mappers;
13
14
  mappedPostsCache = new Map();
14
15
  constructor(init) {
15
- const { playerBuffer, mappers, socialInteractionsHandler, mediaCenterData, settings, callbacks, playerSliderCallbacks } = init;
16
+ const { playerBuffer, trackingParams, mappers, socialInteractionsHandler, mediaCenterData, settings, callbacks, playerSliderCallbacks } = init;
16
17
  this.playerBuffer = playerBuffer;
18
+ this._trackingParams = trackingParams ?? null;
17
19
  this.settings = settings || new ContentPlayerSettings();
18
20
  this._mediaCenterData = mediaCenterData || null;
19
21
  this.callbacks = callbacks || null;
@@ -33,6 +35,9 @@ export class ContentPlayerConfig {
33
35
  get fadeContent() {
34
36
  return this._mediaCenterData?.overlayIsActive || false;
35
37
  }
38
+ get trackingParams() {
39
+ return this._trackingParams;
40
+ }
36
41
  itemAsPostViewerModel = (item) => {
37
42
  if (this.mappedPostsCache.has(item.id)) {
38
43
  return this.mappedPostsCache.get(item.id) || null;
@@ -52,4 +57,7 @@ export class ContentPlayerConfig {
52
57
  updateMediaCenterData = (data) => {
53
58
  this._mediaCenterData = data ?? null;
54
59
  };
60
+ updateTrackingParams = (data) => {
61
+ this._trackingParams = data ?? null;
62
+ };
55
63
  }
@@ -75,6 +75,7 @@ const variables = $derived.by(() => {
75
75
  <div class="controls-and-attachments__post-attachments" transition:slideHorizontally|local>
76
76
  <PostAttachments
77
77
  model={currentItemPostContainer}
78
+ trackingParams={config.trackingParams}
78
79
  locale={config.settings.locale}
79
80
  on={{
80
81
  productClick: (id) => config.callbacks?.productClick?.(id, currentItemPostContainer.id),
@@ -33,7 +33,11 @@ export declare enum ProfileType {
33
33
  Organization = "ORGANIZATION"
34
34
  }
35
35
  export declare enum PostType {
36
- ShortVideo = "SHORT_VIDEO"
36
+ Article = "ARTICLE",
37
+ Media = "MEDIA",
38
+ Moment = "MOMENT",
39
+ ShortVideo = "SHORT_VIDEO",
40
+ Video = "VIDEO"
37
41
  }
38
42
  export declare enum Status {
39
43
  Published = "PUBLISHED"
@@ -41,7 +41,11 @@ export var ProfileType;
41
41
  })(ProfileType || (ProfileType = {}));
42
42
  export var PostType;
43
43
  (function (PostType) {
44
+ PostType["Article"] = "ARTICLE";
45
+ PostType["Media"] = "MEDIA";
46
+ PostType["Moment"] = "MOMENT";
44
47
  PostType["ShortVideo"] = "SHORT_VIDEO";
48
+ PostType["Video"] = "VIDEO";
45
49
  })(PostType || (PostType = {}));
46
50
  export var Status;
47
51
  (function (Status) {
@@ -0,0 +1,2 @@
1
+ export type { TrackingParams } from './types';
2
+ export { enrichAdLinkWithTracking, enrichProductLinkWithTracking } from './service';
@@ -0,0 +1 @@
1
+ export { enrichAdLinkWithTracking, enrichProductLinkWithTracking } from './service';
@@ -0,0 +1,11 @@
1
+ import type { TrackingParams } from './types';
2
+ export declare const enrichProductLinkWithTracking: (data: {
3
+ link: string | URL;
4
+ productId: string;
5
+ trackingParams: TrackingParams | false | null | undefined;
6
+ }) => URL;
7
+ export declare const enrichAdLinkWithTracking: (data: {
8
+ link: string | URL;
9
+ adId: string;
10
+ trackingParams: TrackingParams | false | null | undefined;
11
+ }) => URL;
@@ -0,0 +1,35 @@
1
+ export const enrichProductLinkWithTracking = (data) => {
2
+ const { link, productId, trackingParams } = data;
3
+ const url = link instanceof URL ? link : new URL(link);
4
+ if (trackingParams === false) {
5
+ return url;
6
+ }
7
+ url.searchParams.set('utm_source', 'streams');
8
+ url.searchParams.set('streams_product_id', productId);
9
+ return addTrackingParamsToUrl(url, trackingParams);
10
+ };
11
+ export const enrichAdLinkWithTracking = (data) => {
12
+ const { link, adId, trackingParams } = data;
13
+ const url = link instanceof URL ? link : new URL(link);
14
+ if (trackingParams === false) {
15
+ return url;
16
+ }
17
+ url.searchParams.set('utm_source', 'streams');
18
+ url.searchParams.set('streams_ad_id', adId);
19
+ return addTrackingParamsToUrl(url, trackingParams);
20
+ };
21
+ const addTrackingParamsToUrl = (url, trackingParams) => {
22
+ if (!trackingParams) {
23
+ return url;
24
+ }
25
+ if (trackingParams.campaignId) {
26
+ url.searchParams.set('utm_id', trackingParams.campaignId);
27
+ }
28
+ if (trackingParams.shortVideoId) {
29
+ url.searchParams.set('streams_short_video_id', trackingParams.shortVideoId);
30
+ }
31
+ if (trackingParams.streamId) {
32
+ url.searchParams.set('streams_stream_id', trackingParams.streamId);
33
+ }
34
+ return url;
35
+ };
@@ -0,0 +1,5 @@
1
+ export type TrackingParams = {
2
+ streamId?: string;
3
+ shortVideoId?: string;
4
+ campaignId?: string;
5
+ } | false;
@@ -1,8 +1,9 @@
1
- import type { IShortVideoAnalyticsHandler } from '../../short-videos/short-videos-player/types';
1
+ import type { IPostAnalyticsHandler } from '../../posts/posts-player/types';
2
2
  import type { IStreamAnalyticsHandler } from '../../streams/stream-player/types';
3
- export declare class InternalMediaCenterAnalyticsHandler implements IShortVideoAnalyticsHandler, IStreamAnalyticsHandler {
3
+ export declare class InternalMediaCenterAnalyticsHandler implements IPostAnalyticsHandler, IStreamAnalyticsHandler {
4
4
  constructor(graphqlOrigin: string | undefined);
5
5
  setOrganizationId: (organizationId: string) => void;
6
+ trackPostOpened: (postId: string, ownerId: string) => void;
6
7
  trackStreamView: (streamId: string) => void;
7
8
  trackStreamPageView: (pageId: string, streamId: string) => void;
8
9
  trackStreamEngagementTime: (streamId: string, engagementTime: number) => void;
@@ -7,6 +7,7 @@ export class InternalMediaCenterAnalyticsHandler {
7
7
  AppEventsTracker.setProfileId(getOrCreateProfileId());
8
8
  }
9
9
  setOrganizationId = (organizationId) => AppEventsTracker.setOrganizationId(organizationId);
10
+ trackPostOpened = (postId, ownerId) => AppEventsTracker.trackPostOpened(postId, ownerId);
10
11
  trackStreamView = (streamId) => AppEventsTracker.trackStreamView(streamId);
11
12
  trackStreamPageView = (pageId, streamId) => AppEventsTracker.trackStreamPageView(pageId, streamId);
12
13
  trackStreamEngagementTime = (streamId, engagementTime) => AppEventsTracker.trackStreamEngagementTime(streamId, engagementTime);
@@ -1,7 +1,7 @@
1
1
  import type { IMediaCenterConfig } from './types';
2
2
  export declare class InternalMediaCenterConfig implements IMediaCenterConfig {
3
3
  private readonly mediaPageId;
4
- shortVideosPlayer: IMediaCenterConfig['shortVideosPlayer'];
4
+ postsPlayer: IMediaCenterConfig['postsPlayer'];
5
5
  streamPlayer: IMediaCenterConfig['streamPlayer'];
6
6
  handlers: IMediaCenterConfig['handlers'];
7
7
  private graphql;
@@ -1,28 +1,28 @@
1
- import { PostType, Status, StreamStatus } from '../../core/enums';
1
+ import { Status, StreamStatus } from '../../core/enums';
2
2
  import { createLocalGQLClient } from '../../core/graphql';
3
3
  import { MockCategoryFollowingProvider } from '../categories-following/mock-categories-following-handler.svelte';
4
+ import { mapToPostPlayerModel } from '../../posts/posts-player/mapper';
4
5
  import { MockPostSocialInteractionsHandler } from '../../posts/social-interactions/mock-post-social-interactions-handler.svelte';
5
- import { mapToShortVideoPlayerModel } from '../../short-videos/short-videos-player/mapper';
6
6
  import { InternalStreamPlayerDataProvider } from '../../streams/stream-player/internal-stream-player-data-provider';
7
7
  import { InternalMediaCenterAnalyticsHandler } from './internal-media-center-analytics-handler';
8
- import { GetMediaPageConfigDocument, GetShortVideosDocument, GetStreamsDocument } from './operations.generated';
8
+ import { GetMediaPageConfigDocument, GetPostsDocument, GetStreamsDocument } from './operations.generated';
9
9
  export class InternalMediaCenterConfig {
10
10
  mediaPageId;
11
- shortVideosPlayer;
11
+ postsPlayer;
12
12
  streamPlayer;
13
13
  handlers;
14
14
  graphql;
15
15
  constructor(mediaPageId, graphqlOrigin, testingStuff) {
16
16
  this.mediaPageId = mediaPageId;
17
17
  this.graphql = createLocalGQLClient(graphqlOrigin);
18
- this.shortVideosPlayer = {
19
- getShortVideosCursor: async ({ filter, limit, continuationToken }) => {
18
+ this.postsPlayer = {
19
+ getPostsCursor: async ({ filter, limit, continuationToken }) => {
20
20
  const payload = await this.graphql
21
- .query(GetShortVideosDocument, {
21
+ .query(GetPostsDocument, {
22
22
  input: {
23
23
  filter: {
24
24
  mediaPageId: this.mediaPageId,
25
- types: [PostType.ShortVideo],
25
+ types: filter.types,
26
26
  statuses: [Status.Published],
27
27
  categoryId: filter.categoryId,
28
28
  excludeIds: filter.excludeIds
@@ -32,10 +32,10 @@ export class InternalMediaCenterConfig {
32
32
  }
33
33
  })
34
34
  .toPromise();
35
- const posts = payload.data?.shortVideos?.items || [];
35
+ const posts = payload.data?.posts?.items || [];
36
36
  return {
37
- items: posts.map(mapToShortVideoPlayerModel),
38
- continuationToken: payload.data?.shortVideos?.continuationToken || null
37
+ items: posts.map(mapToPostPlayerModel),
38
+ continuationToken: payload.data?.posts?.continuationToken || null
39
39
  };
40
40
  }
41
41
  };
@@ -23,12 +23,12 @@ export type GetMediaPageConfigQuery = {
23
23
  } | null;
24
24
  } | null;
25
25
  };
26
- export type GetShortVideosQueryVariables = SchemaTypes.Exact<{
26
+ export type GetPostsQueryVariables = SchemaTypes.Exact<{
27
27
  input: SchemaTypes.EmbedPostsInput;
28
28
  image_scale?: SchemaTypes.InputMaybe<SchemaTypes.ImageScale>;
29
29
  }>;
30
- export type GetShortVideosQuery = {
31
- shortVideos: {
30
+ export type GetPostsQuery = {
31
+ posts: {
32
32
  continuationToken: string | null;
33
33
  items: Array<{
34
34
  id: string;
@@ -126,5 +126,5 @@ export type GetStreamsQuery = {
126
126
  };
127
127
  };
128
128
  export declare const GetMediaPageConfigDocument: DocumentNode<GetMediaPageConfigQuery, GetMediaPageConfigQueryVariables>;
129
- export declare const GetShortVideosDocument: DocumentNode<GetShortVideosQuery, GetShortVideosQueryVariables>;
129
+ export declare const GetPostsDocument: DocumentNode<GetPostsQuery, GetPostsQueryVariables>;
130
130
  export declare const GetStreamsDocument: DocumentNode<GetStreamsQuery, GetStreamsQueryVariables>;
@@ -84,13 +84,13 @@ export const GetMediaPageConfigDocument = {
84
84
  }
85
85
  ]
86
86
  };
87
- export const GetShortVideosDocument = {
87
+ export const GetPostsDocument = {
88
88
  kind: 'Document',
89
89
  definitions: [
90
90
  {
91
91
  kind: 'OperationDefinition',
92
92
  operation: 'query',
93
- name: { kind: 'Name', value: 'GetShortVideos' },
93
+ name: { kind: 'Name', value: 'GetPosts' },
94
94
  variableDefinitions: [
95
95
  {
96
96
  kind: 'VariableDefinition',
@@ -109,7 +109,7 @@ export const GetShortVideosDocument = {
109
109
  selections: [
110
110
  {
111
111
  kind: 'Field',
112
- alias: { kind: 'Name', value: 'shortVideos' },
112
+ alias: { kind: 'Name', value: 'posts' },
113
113
  name: { kind: 'Name', value: 'embedPosts' },
114
114
  arguments: [{ kind: 'Argument', name: { kind: 'Name', value: 'input' }, value: { kind: 'Variable', name: { kind: 'Name', value: 'input' } } }],
115
115
  selectionSet: {
@@ -118,10 +118,7 @@ export const GetShortVideosDocument = {
118
118
  {
119
119
  kind: 'Field',
120
120
  name: { kind: 'Name', value: 'items' },
121
- selectionSet: {
122
- kind: 'SelectionSet',
123
- selections: [{ kind: 'FragmentSpread', name: { kind: 'Name', value: 'ShortVideosPlayerPayloadFragment' } }]
124
- }
121
+ selectionSet: { kind: 'SelectionSet', selections: [{ kind: 'FragmentSpread', name: { kind: 'Name', value: 'PostsPlayerPayloadFragment' } }] }
125
122
  },
126
123
  { kind: 'Field', name: { kind: 'Name', value: 'continuationToken' } }
127
124
  ]
@@ -334,7 +331,7 @@ export const GetShortVideosDocument = {
334
331
  },
335
332
  {
336
333
  kind: 'FragmentDefinition',
337
- name: { kind: 'Name', value: 'ShortVideosPlayerPayloadFragment' },
334
+ name: { kind: 'Name', value: 'PostsPlayerPayloadFragment' },
338
335
  typeCondition: { kind: 'NamedType', name: { kind: 'Name', value: 'Post' } },
339
336
  selectionSet: {
340
337
  kind: 'SelectionSet',
@@ -20,10 +20,10 @@ query GetMediaPageConfig($mediaPageId: String!) {
20
20
  }
21
21
 
22
22
  # noinspection GraphQLSchemaValidation
23
- query GetShortVideos($input: EmbedPostsInput!, $image_scale: ImageScale = ORIGINAL_ENCODED) {
24
- shortVideos: embedPosts(input: $input) {
23
+ query GetPosts($input: EmbedPostsInput!, $image_scale: ImageScale = ORIGINAL_ENCODED) {
24
+ posts: embedPosts(input: $input) {
25
25
  items {
26
- ...ShortVideosPlayerPayloadFragment
26
+ ...PostsPlayerPayloadFragment
27
27
  }
28
28
  continuationToken
29
29
  }
@@ -1,24 +1,26 @@
1
+ import { PostType } from '../../core/enums';
1
2
  import type { IContentCategoryFollowingHandler } from '../categories-following';
3
+ import type { IPostAnalyticsHandler, PostPlayerModel } from '../../posts/posts-player/types';
2
4
  import type { IPostSocialInteractionsHandler } from '../../posts/social-interactions';
3
- import type { IShortVideoAnalyticsHandler, ShortVideoPlayerModel } from '../../short-videos/short-videos-player/types';
4
5
  import type { IStreamPlayerDataProvider, IStreamAnalyticsHandler } from '../../streams/stream-player/types';
5
6
  export interface IMediaCenterConfig {
6
7
  getConfig: () => Promise<MediaCenterConfigModel | null>;
7
8
  handlers?: {
8
- analyticsHandler?: IShortVideoAnalyticsHandler & IStreamAnalyticsHandler;
9
+ analyticsHandler?: IPostAnalyticsHandler & IStreamAnalyticsHandler;
9
10
  socialInteractionsHandler?: IPostSocialInteractionsHandler;
10
11
  categoriesFollowingHandler?: IContentCategoryFollowingHandler;
11
12
  };
12
- shortVideosPlayer: {
13
- getShortVideosCursor: (input: {
13
+ postsPlayer: {
14
+ getPostsCursor: (input: {
14
15
  filter: {
16
+ types: PostType[];
15
17
  categoryId?: string;
16
18
  excludeIds?: string[];
17
19
  };
18
20
  limit: number;
19
21
  continuationToken?: string | null;
20
22
  }) => Promise<{
21
- items: ShortVideoPlayerModel[];
23
+ items: PostPlayerModel[];
22
24
  continuationToken: string | null;
23
25
  }>;
24
26
  };
@@ -1 +1 @@
1
- export {};
1
+ import { PostType } from '../../core/enums';
@@ -9,7 +9,7 @@
9
9
  };
10
10
  import { horizontalWheelScroll } from '../../core/actions';
11
11
  import { Utils } from '../../core/utils';
12
- import { default as ShortVideosPlayerView } from '../../short-videos/short-videos-player/short-videos-player-view.svelte';
12
+ import { default as PostsPlayerView } from '../../posts/posts-player/posts-player-view.svelte';
13
13
  import { default as StreamPlayerView } from '../../streams/stream-player/stream-player-view.svelte';
14
14
  import { Icon } from '../../ui/icon';
15
15
  import { Loading } from '../../ui/loading';
@@ -20,12 +20,14 @@ import { default as DiscoverPanel } from './discover-panel.svelte';
20
20
  import { MediaCenterHandler } from './media-center-handler.svelte';
21
21
  import { MediaCenterLocalization } from './media-center-localization';
22
22
  import { default as MobileControlsPanel } from './mobile-controls-panel.svelte';
23
- import { makeShortVideosProvider } from './short-video-resources-generator';
23
+ import { makePostPlayerItemsProvider } from './post-player-provider-generator';
24
24
  import { StreamsInCategoryPanelHandler } from './streams-in-category-panel-handler.svelte';
25
25
  import { default as StreamsInCategoryPanel } from './streams-in-category-panel.svelte';
26
26
  import IconLineHorizontal3 from '@fluentui/svg-icons/icons/line_horizontal_3_20_regular.svg?raw';
27
27
  import IconScreenSearch from '@fluentui/svg-icons/icons/screen_search_20_regular.svg?raw';
28
+ import { tick } from 'svelte';
28
29
  import { fade } from 'svelte/transition';
30
+ const SCROLL_MASK_OFFSET = 32;
29
31
  let { config, playerProps, locale = 'en' } = $props();
30
32
  const localization = $derived(new MediaCenterLocalization(locale));
31
33
  const commonPlayerSettings = {
@@ -42,23 +44,24 @@ let isMobileView = $state(false);
42
44
  const overlayActivated = $derived(discoverHandler.activated || streamsInCategoryHandler.activated);
43
45
  let mobileControlsPanelActive = $state(false);
44
46
  let extraMobileControlsPanelActions = $state.raw([]);
47
+ let scrollAreaRef = $state(null);
45
48
  const selectCategory = (categoryId) => __awaiter(void 0, void 0, void 0, function* () {
46
- var _a, _b;
49
+ var _a, _b, _c;
47
50
  const selectedCategoryData = handler.getCategoryData(categoryId);
48
51
  if (!config || !selectedCategoryData) {
49
52
  return;
50
53
  }
51
54
  hideMobileControlsPanel();
52
55
  switch (mediaCenterMode) {
53
- case 'short-videos':
56
+ case 'posts':
54
57
  if (handler.selectedCategoryId === categoryId) {
55
58
  discoverHandler.deactivate();
56
59
  return;
57
60
  }
58
61
  handler.selectedCategoryId = categoryId;
59
62
  computedPlayerProps = {
60
- mode: 'short-videos',
61
- props: Object.assign({ dataProvider: makeShortVideosProvider({ config, categoryId }), socialInteractionsHandler: (_a = config.handlers) === null || _a === void 0 ? void 0 : _a.socialInteractionsHandler, analyticsHandler: (_b = config.handlers) === null || _b === void 0 ? void 0 : _b.analyticsHandler }, commonPlayerSettings)
63
+ mode: 'posts',
64
+ props: Object.assign({ dataProvider: makePostPlayerItemsProvider({ config, categoryId }), socialInteractionsHandler: (_a = config.handlers) === null || _a === void 0 ? void 0 : _a.socialInteractionsHandler, analyticsHandler: (_b = config.handlers) === null || _b === void 0 ? void 0 : _b.analyticsHandler }, commonPlayerSettings)
62
65
  };
63
66
  discoverHandler.deactivate();
64
67
  break;
@@ -76,16 +79,62 @@ const selectCategory = (categoryId) => __awaiter(void 0, void 0, void 0, functio
76
79
  default:
77
80
  Utils.assertUnreachable(mediaCenterMode);
78
81
  }
82
+ // Scroll to selected category if it's hidden
83
+ yield scrollToSelectedCategory((_c = selectedCategoryData.parentId) !== null && _c !== void 0 ? _c : selectedCategoryData.id);
84
+ });
85
+ /**
86
+ * Scrolls the scroll area to make the selected category button visible
87
+ * @param categoryId - ID of the selected category
88
+ */
89
+ const scrollToSelectedCategory = (categoryId) => __awaiter(void 0, void 0, void 0, function* () {
90
+ if (!scrollAreaRef) {
91
+ return;
92
+ }
93
+ // Wait for DOM to update with the new active state
94
+ yield tick();
95
+ // Find the selected category button element
96
+ const selectedButton = scrollAreaRef.querySelector(`[id="${categoryId}"]`);
97
+ if (!selectedButton) {
98
+ return;
99
+ }
100
+ // Get scroll area and button dimensions
101
+ const scrollAreaRect = scrollAreaRef.getBoundingClientRect();
102
+ const buttonRect = selectedButton.getBoundingClientRect();
103
+ // Calculate button position relative to scroll area
104
+ const buttonLeftRelative = buttonRect.left - scrollAreaRect.left + scrollAreaRef.scrollLeft;
105
+ const buttonRightRelative = buttonLeftRelative + buttonRect.width;
106
+ // Calculate visible area boundaries (accounting for mask gradients)
107
+ const hasLeftMask = scrollAreaRef.scrollLeft > 0;
108
+ const hasRightMask = scrollAreaRef.scrollLeft < scrollAreaRef.scrollWidth - scrollAreaRect.width - 1;
109
+ const visibleLeft = scrollAreaRef.scrollLeft + (hasLeftMask ? SCROLL_MASK_OFFSET : 0);
110
+ const visibleRight = scrollAreaRef.scrollLeft + scrollAreaRect.width - (hasRightMask ? SCROLL_MASK_OFFSET : 0);
111
+ // Check if button is hidden or partially hidden
112
+ const isHiddenLeft = buttonLeftRelative < visibleLeft;
113
+ const isHiddenRight = buttonRightRelative > visibleRight;
114
+ if (isHiddenLeft) {
115
+ const targetScroll = buttonLeftRelative - SCROLL_MASK_OFFSET;
116
+ scrollAreaRef.scrollTo({
117
+ left: targetScroll,
118
+ behavior: 'smooth'
119
+ });
120
+ }
121
+ else if (isHiddenRight) {
122
+ const targetScroll = buttonRightRelative - scrollAreaRect.width + SCROLL_MASK_OFFSET;
123
+ scrollAreaRef.scrollTo({
124
+ left: targetScroll,
125
+ behavior: 'smooth'
126
+ });
127
+ }
79
128
  });
80
129
  const activateSelectedShortVideoPlayer = (shortVideo) => {
81
130
  var _a, _b;
82
131
  if (!config) {
83
132
  return;
84
133
  }
85
- mediaCenterMode = 'short-videos';
134
+ mediaCenterMode = 'posts';
86
135
  computedPlayerProps = {
87
- mode: 'short-videos',
88
- props: Object.assign({ dataProvider: makeShortVideosProvider({ config, prefetchedItems: [shortVideo] }), socialInteractionsHandler: (_a = config.handlers) === null || _a === void 0 ? void 0 : _a.socialInteractionsHandler, analyticsHandler: (_b = config.handlers) === null || _b === void 0 ? void 0 : _b.analyticsHandler }, commonPlayerSettings)
136
+ mode: 'posts',
137
+ props: Object.assign({ dataProvider: makePostPlayerItemsProvider({ config, prefetchedItems: [shortVideo] }), socialInteractionsHandler: (_a = config.handlers) === null || _a === void 0 ? void 0 : _a.socialInteractionsHandler, analyticsHandler: (_b = config.handlers) === null || _b === void 0 ? void 0 : _b.analyticsHandler }, commonPlayerSettings)
89
138
  };
90
139
  handler.selectedCategoryId = null;
91
140
  discoverHandler.deactivate();
@@ -134,6 +183,8 @@ const updateScrollShadows = (scrollArea) => {
134
183
  scrollArea.classList.toggle('has-both-masks', scrollHasRight && scrollHasLeft);
135
184
  };
136
185
  const onScrollMounted = (node) => {
186
+ scrollAreaRef = node;
187
+ scrollAreaRef.style.setProperty('--scroll-area--mask-offset', `${SCROLL_MASK_OFFSET}px`);
137
188
  const scrollResizeObserver = new ResizeObserver(() => {
138
189
  updateScrollShadows(node);
139
190
  });
@@ -178,7 +229,7 @@ const onWidthAnchorMounted = (node) => {
178
229
  class="media-center-controls-panel__button"
179
230
  class:media-center-controls-panel__button--active={discoverHandler.activated}
180
231
  onclick={toggleDiscover}>
181
- <span class="media-center-controls-panel__button-icon">
232
+ <span class="media-center-controls-panel__button-icon" class:media-center-controls-panel__button-icon--active={discoverHandler.activated}>
182
233
  <Icon src={IconScreenSearch} />
183
234
  </span>
184
235
  <span class="media-center-controls-panel__button-value">
@@ -189,6 +240,7 @@ const onWidthAnchorMounted = (node) => {
189
240
  {#each handler.categories as category (category.id)}
190
241
  <button
191
242
  type="button"
243
+ id={category.id}
192
244
  class="media-center-controls-panel__button"
193
245
  class:media-center-controls-panel__button--active={!discoverHandler.activated && handler.controlsPanelSelectedCategory?.id === category.id}
194
246
  data-child-name={(!discoverHandler.activated &&
@@ -210,8 +262,8 @@ const onWidthAnchorMounted = (node) => {
210
262
  </div>
211
263
  {/if}
212
264
  {/snippet}
213
- {#if computedPlayerProps.mode === 'short-videos'}
214
- <ShortVideosPlayerView
265
+ {#if computedPlayerProps.mode === 'posts'}
266
+ <PostsPlayerView
215
267
  {...computedPlayerProps.props}
216
268
  mediaCenterData={{
217
269
  controlsPanel: handler.categories.length ? controlsPanel : undefined,
@@ -304,15 +356,17 @@ const onWidthAnchorMounted = (node) => {
304
356
  scrollbar-width: none;
305
357
  padding: 0.5rem 0.625rem;
306
358
  padding-left: 0;
359
+ --_scroll-area--mask-offset--left: var(--scroll-area--mask-offset);
360
+ --_scroll-area--mask-offset--right: calc(100% - var(--scroll-area--mask-offset));
307
361
  }
308
362
  :global(.media-center-controls-panel__scroll-area.has-left-mask) {
309
- mask-image: linear-gradient(to right, rgba(0, 0, 0, 0) 0, rgb(0, 0, 0) 32px, rgb(0, 0, 0) 100%);
363
+ mask-image: linear-gradient(to right, rgba(0, 0, 0, 0) 0, rgb(0, 0, 0) var(--_scroll-area--mask-offset--left), rgb(0, 0, 0) 100%);
310
364
  }
311
365
  :global(.media-center-controls-panel__scroll-area.has-right-mask) {
312
- mask-image: linear-gradient(to right, rgb(0, 0, 0) 0, rgb(0, 0, 0) calc(100% - 32px), rgba(0, 0, 0, 0) 100%);
366
+ mask-image: linear-gradient(to right, rgb(0, 0, 0) 0, rgb(0, 0, 0) var(--_scroll-area--mask-offset--right), rgba(0, 0, 0, 0) 100%);
313
367
  }
314
368
  :global(.media-center-controls-panel__scroll-area.has-both-masks) {
315
- mask-image: linear-gradient(to right, rgba(0, 0, 0, 0) 0, rgb(0, 0, 0) 32px, rgb(0, 0, 0) calc(100% - 32px), rgba(0, 0, 0, 0) 100%);
369
+ mask-image: linear-gradient(to right, rgba(0, 0, 0, 0) 0, rgb(0, 0, 0) var(--_scroll-area--mask-offset--left), rgb(0, 0, 0) var(--_scroll-area--mask-offset--right), rgba(0, 0, 0, 0) 100%);
316
370
  }
317
371
  .media-center-controls-panel__button {
318
372
  position: relative;
@@ -340,7 +394,6 @@ const onWidthAnchorMounted = (node) => {
340
394
  .media-center-controls-panel__button--active {
341
395
  background-color: rgba(255, 255, 255, 0.9);
342
396
  color: #000000;
343
- --icon--color: #000000;
344
397
  }
345
398
  .media-center-controls-panel__button:hover:not(.media-center-controls-panel__button--active) {
346
399
  background-color: rgba(0, 0, 0, 0.9);
@@ -364,8 +417,12 @@ const onWidthAnchorMounted = (node) => {
364
417
  pointer-events: none;
365
418
  }
366
419
  .media-center-controls-panel__button-icon {
367
- --icon--color: #ffffff;
368
420
  --icon--size: 1.0625rem;
421
+ --icon--color: #ffffff;
422
+ line-height: 0;
423
+ }
424
+ .media-center-controls-panel__button-icon--active {
425
+ --icon--color: #000000;
369
426
  }
370
427
  .media-center-controls-panel__button-value {
371
428
  font-size: 0.875rem;
@@ -1,10 +1,10 @@
1
1
  import type { Locale } from '../../core/locale';
2
2
  import type { IMediaCenterConfig } from '../config/types';
3
- import type { ShortVideoPlayerProps } from '../../short-videos/short-videos-player/types';
3
+ import type { PostPlayerProps } from '../../posts/posts-player/types';
4
4
  import type { StreamPlayerProps } from '../../streams/stream-player/types';
5
5
  type PlayerProps = {
6
- mode: 'short-videos';
7
- props: ShortVideoPlayerProps;
6
+ mode: 'posts';
7
+ props: PostPlayerProps;
8
8
  } | {
9
9
  mode: 'stream';
10
10
  props: StreamPlayerProps;