@streamscloud/embeddable 8.0.1 → 8.1.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.
- package/dist/media-center/categories-following/mock-categories-following-handler.svelte.d.ts +8 -0
- package/dist/media-center/categories-following/mock-categories-following-handler.svelte.js +31 -0
- package/dist/media-center/config/internal-media-center-config.d.ts +1 -1
- package/dist/media-center/config/internal-media-center-config.js +6 -2
- package/dist/media-center/media-center/category-following-wrapper.svelte +70 -0
- package/dist/media-center/media-center/category-following-wrapper.svelte.d.ts +11 -0
- package/dist/media-center/media-center/cmp.media-center.svelte +5 -1
- package/dist/media-center/media-center/desktop-categories-selector.svelte +18 -13
- package/dist/media-center/media-center/desktop-categories-selector.svelte.d.ts +2 -0
- package/dist/media-center/media-center/mobile-controls-panel.svelte +20 -12
- package/dist/media-center/media-center/mobile-controls-panel.svelte.d.ts +2 -0
- package/dist/posts/social-interactions/mock-post-social-interactions-handler.svelte.d.ts +9 -0
- package/dist/posts/social-interactions/mock-post-social-interactions-handler.svelte.js +34 -0
- package/package.json +1 -1
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { IContentCategoryFollowingHandler } from './types';
|
|
2
|
+
export declare class MockCategoryFollowingProvider implements IContentCategoryFollowingHandler {
|
|
3
|
+
private categoriesMap;
|
|
4
|
+
getIsFollowed: (categoryId: string) => Promise<{
|
|
5
|
+
readonly isFollowed: boolean;
|
|
6
|
+
}>;
|
|
7
|
+
toggleFollow: (categoryId: string) => void;
|
|
8
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export class MockCategoryFollowingProvider {
|
|
2
|
+
categoriesMap = $state([]);
|
|
3
|
+
getIsFollowed = (categoryId) => {
|
|
4
|
+
const entry = this.categoriesMap.find((c) => c.id === categoryId);
|
|
5
|
+
if (entry) {
|
|
6
|
+
return Promise.resolve({
|
|
7
|
+
get isFollowed() {
|
|
8
|
+
return entry.isFollowed;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
const newEntry = { id: categoryId, isFollowed: Math.random() < 0.5 };
|
|
14
|
+
this.categoriesMap.push(newEntry);
|
|
15
|
+
return Promise.resolve({
|
|
16
|
+
get isFollowed() {
|
|
17
|
+
return newEntry.isFollowed;
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
toggleFollow = (categoryId) => {
|
|
23
|
+
const entry = this.categoriesMap.find((c) => c.id === categoryId);
|
|
24
|
+
if (entry) {
|
|
25
|
+
entry.isFollowed = !entry.isFollowed;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
this.categoriesMap.push({ id: categoryId, isFollowed: true });
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -5,6 +5,6 @@ export declare class InternalMediaCenterConfig implements IMediaCenterConfig {
|
|
|
5
5
|
streamPlayer: IMediaCenterConfig['streamPlayer'];
|
|
6
6
|
handlers: IMediaCenterConfig['handlers'];
|
|
7
7
|
private graphql;
|
|
8
|
-
constructor(mediaPageId: string, graphqlOrigin?: string);
|
|
8
|
+
constructor(mediaPageId: string, graphqlOrigin?: string, testingStuff?: boolean);
|
|
9
9
|
getConfig: IMediaCenterConfig['getConfig'];
|
|
10
10
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { PostType, Status, StreamStatus } from '../../core/enums';
|
|
2
2
|
import { createLocalGQLClient } from '../../core/graphql';
|
|
3
|
+
import { MockCategoryFollowingProvider } from '../categories-following/mock-categories-following-handler.svelte';
|
|
4
|
+
import { MockPostSocialInteractionsHandler } from '../../posts/social-interactions/mock-post-social-interactions-handler.svelte';
|
|
3
5
|
import { mapToShortVideoPlayerModel } from '../../short-videos/short-videos-player/mapper';
|
|
4
6
|
import { InternalStreamPlayerDataProvider } from '../../streams/stream-player/internal-stream-player-data-provider';
|
|
5
7
|
import { InternalMediaCenterAnalyticsHandler } from './internal-media-center-analytics-handler';
|
|
@@ -10,7 +12,7 @@ export class InternalMediaCenterConfig {
|
|
|
10
12
|
streamPlayer;
|
|
11
13
|
handlers;
|
|
12
14
|
graphql;
|
|
13
|
-
constructor(mediaPageId, graphqlOrigin) {
|
|
15
|
+
constructor(mediaPageId, graphqlOrigin, testingStuff) {
|
|
14
16
|
this.mediaPageId = mediaPageId;
|
|
15
17
|
this.graphql = createLocalGQLClient(graphqlOrigin);
|
|
16
18
|
this.shortVideosPlayer = {
|
|
@@ -63,7 +65,9 @@ export class InternalMediaCenterConfig {
|
|
|
63
65
|
streamPlayerDataProvider: new InternalStreamPlayerDataProvider({ graphql: this.graphql })
|
|
64
66
|
};
|
|
65
67
|
this.handlers = {
|
|
66
|
-
analyticsHandler: new InternalMediaCenterAnalyticsHandler(graphqlOrigin)
|
|
68
|
+
analyticsHandler: new InternalMediaCenterAnalyticsHandler(graphqlOrigin),
|
|
69
|
+
categoriesFollowingHandler: testingStuff ? new MockCategoryFollowingProvider() : undefined,
|
|
70
|
+
socialInteractionsHandler: testingStuff ? new MockPostSocialInteractionsHandler() : undefined
|
|
67
71
|
};
|
|
68
72
|
}
|
|
69
73
|
getConfig = async () => {
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<script lang="ts">var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { Icon } from '../../ui/icon';
|
|
11
|
+
import IconStarFilled from '@fluentui/svg-icons/icons/star_20_filled.svg?raw';
|
|
12
|
+
import IconStar from '@fluentui/svg-icons/icons/star_20_regular.svg?raw';
|
|
13
|
+
import { onMount } from 'svelte';
|
|
14
|
+
let { categoryId, followingHandler, children, invertedOrientation } = $props();
|
|
15
|
+
let isFollowedStore = $state.raw({
|
|
16
|
+
get isFollowed() {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
onMount(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
21
|
+
if (!followingHandler) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
isFollowedStore = yield followingHandler.getIsFollowed(categoryId);
|
|
25
|
+
}));
|
|
26
|
+
const handleToggleFollow = (e) => __awaiter(void 0, void 0, void 0, function* () {
|
|
27
|
+
e.stopPropagation();
|
|
28
|
+
if (!followingHandler) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
yield followingHandler.toggleFollow(categoryId);
|
|
32
|
+
});
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
{#if !followingHandler}
|
|
36
|
+
{@render children()}
|
|
37
|
+
{:else}
|
|
38
|
+
<div class="desktop-category-following-wrapper" class:desktop-category-following-wrapper--inverted-orientation={invertedOrientation}>
|
|
39
|
+
{@render children()}
|
|
40
|
+
<button type="button" class="desktop-category-following-wrapper__toggle-button" onclick={handleToggleFollow}>
|
|
41
|
+
<Icon src={isFollowedStore.isFollowed ? IconStarFilled : IconStar} />
|
|
42
|
+
</button>
|
|
43
|
+
</div>
|
|
44
|
+
{/if}
|
|
45
|
+
|
|
46
|
+
<style>@keyframes fadeIn {
|
|
47
|
+
0% {
|
|
48
|
+
opacity: 1;
|
|
49
|
+
}
|
|
50
|
+
50% {
|
|
51
|
+
opacity: 0.4;
|
|
52
|
+
}
|
|
53
|
+
100% {
|
|
54
|
+
opacity: 1;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
.desktop-category-following-wrapper {
|
|
58
|
+
display: flex;
|
|
59
|
+
align-items: center;
|
|
60
|
+
gap: 0.5rem;
|
|
61
|
+
}
|
|
62
|
+
.desktop-category-following-wrapper--inverted-orientation {
|
|
63
|
+
flex-direction: row-reverse;
|
|
64
|
+
}
|
|
65
|
+
.desktop-category-following-wrapper__toggle-button {
|
|
66
|
+
--icon--size: 1rem;
|
|
67
|
+
--icon--color: #00b8d8;
|
|
68
|
+
height: max-content;
|
|
69
|
+
line-height: 0;
|
|
70
|
+
}</style>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { IContentCategoryFollowingHandler } from '..';
|
|
2
|
+
import { type Snippet } from 'svelte';
|
|
3
|
+
type Props = {
|
|
4
|
+
categoryId: string;
|
|
5
|
+
followingHandler?: IContentCategoryFollowingHandler;
|
|
6
|
+
children: Snippet;
|
|
7
|
+
invertedOrientation?: boolean;
|
|
8
|
+
};
|
|
9
|
+
declare const CategoryFollowingWrapper: import("svelte").Component<Props, {}, "">;
|
|
10
|
+
type CategoryFollowingWrapper = ReturnType<typeof CategoryFollowingWrapper>;
|
|
11
|
+
export default CategoryFollowingWrapper;
|
|
@@ -169,7 +169,10 @@ const onWidthAnchorMounted = (node) => {
|
|
|
169
169
|
{#snippet controlsPanel()}
|
|
170
170
|
{#if !isMobileView}
|
|
171
171
|
<div class="media-center-controls-panel">
|
|
172
|
-
<DesktopCategoriesSelector
|
|
172
|
+
<DesktopCategoriesSelector
|
|
173
|
+
handler={handler}
|
|
174
|
+
followingHandler={config?.handlers?.categoriesFollowingHandler}
|
|
175
|
+
on={{ categorySelected: selectCategory }} />
|
|
173
176
|
<button
|
|
174
177
|
type="button"
|
|
175
178
|
class="media-center-controls-panel__button"
|
|
@@ -251,6 +254,7 @@ const onWidthAnchorMounted = (node) => {
|
|
|
251
254
|
<MobileControlsPanel
|
|
252
255
|
mediaCenterHandler={handler}
|
|
253
256
|
discoverHandler={discoverHandler}
|
|
257
|
+
followingHandler={config?.handlers?.categoriesFollowingHandler}
|
|
254
258
|
localization={localization}
|
|
255
259
|
extraActions={extraMobileControlsPanelActions}
|
|
256
260
|
on={{ categorySelected: selectCategory, toggleDiscover, externalActionExecuted: handleExternalActionExecuted }} />
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<script lang="ts">import { Dropdown } from '../../ui/dropdown';
|
|
2
2
|
import { Icon } from '../../ui/icon';
|
|
3
|
+
import { default as ButtonWrapper } from './category-following-wrapper.svelte';
|
|
3
4
|
import IconTextColumnThree from '@fluentui/svg-icons/icons/text_column_three_20_regular.svg?raw';
|
|
4
|
-
let { handler, on } = $props();
|
|
5
|
+
let { handler, followingHandler, on } = $props();
|
|
5
6
|
</script>
|
|
6
7
|
|
|
7
8
|
<Dropdown>
|
|
@@ -13,22 +14,26 @@ let { handler, on } = $props();
|
|
|
13
14
|
<div class="desktop-categories-selector">
|
|
14
15
|
{#each handler.categories as category (category.id)}
|
|
15
16
|
<div>
|
|
16
|
-
<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
<ButtonWrapper categoryId={category.id} followingHandler={followingHandler}>
|
|
18
|
+
<button
|
|
19
|
+
type="button"
|
|
20
|
+
class="desktop-categories-selector__category"
|
|
21
|
+
class:desktop-categories-selector__category--active={handler.selectedCategoryId === category.id}
|
|
22
|
+
title={category.name}
|
|
23
|
+
onclick={() => on.categorySelected(category.id)}>{category.name}</button>
|
|
24
|
+
</ButtonWrapper>
|
|
22
25
|
|
|
23
26
|
{#if category.children.length > 0}
|
|
24
27
|
<div class="desktop-categories-selector__sub-categories">
|
|
25
28
|
{#each category.children as subcategory (subcategory.id)}
|
|
26
|
-
<
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
<ButtonWrapper categoryId={subcategory.id} followingHandler={followingHandler}>
|
|
30
|
+
<button
|
|
31
|
+
type="button"
|
|
32
|
+
class="desktop-categories-selector__sub-category"
|
|
33
|
+
class:desktop-categories-selector__sub-category--active={handler.selectedCategoryId === subcategory.id}
|
|
34
|
+
title={subcategory.name}
|
|
35
|
+
onclick={() => on.categorySelected(subcategory.id)}>{subcategory.name}</button>
|
|
36
|
+
</ButtonWrapper>
|
|
32
37
|
{/each}
|
|
33
38
|
</div>
|
|
34
39
|
{/if}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import type { IContentCategoryFollowingHandler } from '..';
|
|
1
2
|
import type { MediaCenterHandler } from './media-center-handler.svelte';
|
|
2
3
|
type Props = {
|
|
3
4
|
handler: MediaCenterHandler;
|
|
5
|
+
followingHandler?: IContentCategoryFollowingHandler;
|
|
4
6
|
on: {
|
|
5
7
|
categorySelected: (categoryId: string) => void;
|
|
6
8
|
};
|
|
@@ -3,12 +3,13 @@ import { compactNumber } from '../../core/utils/compact-number';
|
|
|
3
3
|
import { Icon } from '../../ui/icon';
|
|
4
4
|
import { ImageRound } from '../../ui/image';
|
|
5
5
|
import { LineClamp } from '../../ui/line-clamp';
|
|
6
|
+
import { default as ButtonWrapper } from './category-following-wrapper.svelte';
|
|
6
7
|
import { DiscoverPanelHandler } from './discover-panel-handler.svelte';
|
|
7
8
|
import { MediaCenterLocalization } from './media-center-localization';
|
|
8
9
|
import IconChevronDown from '@fluentui/svg-icons/icons/chevron_down_20_regular.svg?raw';
|
|
9
10
|
import IconChevronRight from '@fluentui/svg-icons/icons/chevron_right_20_regular.svg?raw';
|
|
10
11
|
import { slide } from 'svelte/transition';
|
|
11
|
-
let { mediaCenterHandler, discoverHandler, localization, extraActions, on } = $props();
|
|
12
|
+
let { mediaCenterHandler, discoverHandler, followingHandler, localization, extraActions, on } = $props();
|
|
12
13
|
const target = $derived.by(() => mediaCenterHandler.targetData);
|
|
13
14
|
const generateCategoriesMap = () => {
|
|
14
15
|
const expanded = {};
|
|
@@ -83,17 +84,19 @@ const handleCategoryExpaned = (e, categoryId) => {
|
|
|
83
84
|
tabindex="0">
|
|
84
85
|
{category.name}
|
|
85
86
|
</div>
|
|
86
|
-
<
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
87
|
+
<ButtonWrapper categoryId={category.id} followingHandler={followingHandler} invertedOrientation={true}>
|
|
88
|
+
<button
|
|
89
|
+
type="button"
|
|
90
|
+
class="selector-item__collapser"
|
|
91
|
+
class:selector-item__collapser--hidden={!category.children.length}
|
|
92
|
+
onclick={(e) => handleCategoryExpaned(e, category.id)}>
|
|
93
|
+
{#if categoriesExpandedMap[category.id]}
|
|
94
|
+
<Icon src={IconChevronDown} />
|
|
95
|
+
{:else}
|
|
96
|
+
<Icon src={IconChevronRight} />
|
|
97
|
+
{/if}
|
|
98
|
+
</button>
|
|
99
|
+
</ButtonWrapper>
|
|
97
100
|
</div>
|
|
98
101
|
{#if categoriesExpandedMap[category.id]}
|
|
99
102
|
<div transition:slide|local>
|
|
@@ -108,6 +111,11 @@ const handleCategoryExpaned = (e, categoryId) => {
|
|
|
108
111
|
tabindex="0">
|
|
109
112
|
{subcategory.name}
|
|
110
113
|
</div>
|
|
114
|
+
<ButtonWrapper categoryId={subcategory.id} followingHandler={followingHandler} invertedOrientation={true}>
|
|
115
|
+
<button type="button" class="selector-item__collapser selector-item__collapser--hidden">
|
|
116
|
+
<Icon src={IconChevronRight} />
|
|
117
|
+
</button>
|
|
118
|
+
</ButtonWrapper>
|
|
111
119
|
</div>
|
|
112
120
|
{/each}
|
|
113
121
|
</div>
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { IContentCategoryFollowingHandler } from '..';
|
|
1
2
|
import type { ExtraActionDefinition } from '../model/types';
|
|
2
3
|
import { DiscoverPanelHandler } from './discover-panel-handler.svelte';
|
|
3
4
|
import type { MediaCenterHandler } from './media-center-handler.svelte';
|
|
@@ -5,6 +6,7 @@ import { MediaCenterLocalization } from './media-center-localization';
|
|
|
5
6
|
type Props = {
|
|
6
7
|
mediaCenterHandler: MediaCenterHandler;
|
|
7
8
|
discoverHandler: DiscoverPanelHandler;
|
|
9
|
+
followingHandler?: IContentCategoryFollowingHandler;
|
|
8
10
|
localization: MediaCenterLocalization;
|
|
9
11
|
extraActions: ExtraActionDefinition[];
|
|
10
12
|
on: {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { IPostSocialInteractionsHandler } from './types';
|
|
2
|
+
export declare class MockPostSocialInteractionsHandler implements IPostSocialInteractionsHandler {
|
|
3
|
+
private postsMap;
|
|
4
|
+
getIsLiked: (postId: string) => Promise<{
|
|
5
|
+
readonly isLiked: boolean;
|
|
6
|
+
}>;
|
|
7
|
+
toggleLike: (postId: string) => void;
|
|
8
|
+
share: (postId: string) => void;
|
|
9
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export class MockPostSocialInteractionsHandler {
|
|
2
|
+
postsMap = $state([]);
|
|
3
|
+
getIsLiked = (postId) => {
|
|
4
|
+
const entry = this.postsMap.find((c) => c.id === postId);
|
|
5
|
+
if (entry) {
|
|
6
|
+
return Promise.resolve({
|
|
7
|
+
get isLiked() {
|
|
8
|
+
return entry.isLiked;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
const newEntry = { id: postId, isLiked: Math.random() < 0.5 };
|
|
14
|
+
this.postsMap.push(newEntry);
|
|
15
|
+
return Promise.resolve({
|
|
16
|
+
get isLiked() {
|
|
17
|
+
return newEntry.isLiked;
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
toggleLike = (postId) => {
|
|
23
|
+
const entry = this.postsMap.find((c) => c.id === postId);
|
|
24
|
+
if (entry) {
|
|
25
|
+
entry.isLiked = !entry.isLiked;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
this.postsMap.push({ id: postId, isLiked: true });
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
share = (postId) => {
|
|
32
|
+
console.log('onShare', postId);
|
|
33
|
+
};
|
|
34
|
+
}
|