@saooti/octopus-sdk 41.8.4 → 41.9.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 (60) hide show
  1. package/.claude/settings.local.json +2 -1
  2. package/CHANGELOG.md +41 -0
  3. package/eslint-config.d.ts +3 -0
  4. package/eslint-config.mjs +43 -0
  5. package/eslint.config.mjs +2 -43
  6. package/index.ts +15 -0
  7. package/package.json +14 -2
  8. package/src/api/transcriptionApi.ts +63 -3
  9. package/src/components/composable/player/usePlayerDisplayTime.ts +1 -0
  10. package/src/components/composable/player/usePlayerTranscript.ts +66 -17
  11. package/src/components/composable/share/useSharePath.ts +1 -1
  12. package/src/components/composable/share/useSharePlatforms.ts +16 -16
  13. package/src/components/composable/useTranslation.ts +174 -0
  14. package/src/components/display/comments/CommentName.vue +1 -0
  15. package/src/components/display/comments/modal/CheckIdentityModal.vue +1 -0
  16. package/src/components/display/comments/modal/ReportAbuseModal.vue +1 -0
  17. package/src/components/display/emission/EmissionInlineList.vue +7 -9
  18. package/src/components/display/filter/ProductorSearch.vue +1 -1
  19. package/src/components/display/list/SwiperList.vue +1 -0
  20. package/src/components/display/organisation/OrganisationChooser.vue +1 -1
  21. package/src/components/display/organisation/OrganisationChooserLight.vue +1 -1
  22. package/src/components/display/participant/ParticipantInlineList.vue +14 -13
  23. package/src/components/display/podcasts/PodcastItemInfo.vue +94 -58
  24. package/src/components/display/podcasts/PodcastModuleBox.vue +29 -3
  25. package/src/components/display/podcasts/PodcastRawTranscript.vue +155 -81
  26. package/src/components/display/sharing/SharePlayer.vue +1 -1
  27. package/src/components/form/ClassicDatePicker.vue +8 -3
  28. package/src/components/form/ClassicInputText.vue +1 -1
  29. package/src/components/form/ClassicLoading.vue +6 -2
  30. package/src/components/form/ClassicSelect.vue +2 -2
  31. package/src/components/misc/ClassicSpinner.vue +18 -4
  32. package/src/components/misc/FooterSection.vue +1 -1
  33. package/src/components/misc/player/PlayerComponent.vue +1 -1
  34. package/src/components/misc/player/PlayerLarge.vue +14 -0
  35. package/src/components/pages/EmissionPage.vue +16 -2
  36. package/src/components/pages/LivesPage.vue +1 -1
  37. package/src/helper/language.ts +38 -0
  38. package/src/locale/de.json +3 -1
  39. package/src/locale/en.json +3 -1
  40. package/src/locale/es.json +3 -1
  41. package/src/locale/fr.json +4 -1
  42. package/src/locale/it.json +3 -1
  43. package/src/locale/sl.json +3 -1
  44. package/src/main.ts +3 -29
  45. package/src/stores/AuthStore.ts +1 -1
  46. package/src/stores/ParamSdkStore.ts +10 -3
  47. package/src/stores/class/general/emission.ts +4 -1
  48. package/src/stores/class/general/organisation.ts +10 -1
  49. package/src/stores/class/general/podcast.ts +6 -1
  50. package/src/stores/class/transcript/transcriptParams.ts +25 -0
  51. package/tests/api/transcriptionApi.spec.ts +58 -0
  52. package/tests/components/composable/player/usePlayerTranscript.spec.ts +238 -0
  53. package/tests/components/composable/useTranslation.spec.ts +144 -0
  54. package/tests/components/display/podcasts/PodcastFilterList.spec.ts +4 -4
  55. package/tests/components/display/podcasts/PodcastItemInfo.spec.ts +65 -0
  56. package/tests/components/display/podcasts/PodcastModuleBox.spec.ts +64 -0
  57. package/tests/components/display/podcasts/PodcastRawTranscript.spec.ts +253 -0
  58. package/tests/components/misc/player/PlayerLarge.spec.ts +71 -0
  59. package/tests/components/pages/EmissionPage.spec.ts +31 -0
  60. package/tests/helper/language.spec.ts +45 -0
@@ -10,7 +10,8 @@
10
10
  "Bash(node --version:*)",
11
11
  "Bash(npm:*)",
12
12
  "Bash(npx vitest:*)",
13
- "Bash(./node_modules/.bin/vitest run:*)"
13
+ "Bash(./node_modules/.bin/vitest run:*)",
14
+ "Bash(npx eslint:*)"
14
15
  ]
15
16
  }
16
17
  }
package/CHANGELOG.md CHANGED
@@ -1,5 +1,46 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 41.9.0 (31/03/2026)
4
+
5
+ **Features**
6
+
7
+ - **12535** - Implémentation de la traduction des sous-titres
8
+ - Mise en place de l'api `transcriptionApi` pour simplifier les appels
9
+ - Ajout du composable `useTranslation` pour regrouper les opérations relatives
10
+ aux traductions
11
+ - `PodcastRawTranscript` permet maintenant de choisir la langue de la
12
+ transcription
13
+ - La langue la plus pertinente pour l'utilisateur est sélectionnée par
14
+ défaut
15
+ - La transcription affichée dans le player correspond à la langue la plus
16
+ pertinente disponible
17
+ - **14357** - Affichage des sous-titres et résumés d'épisodes, et des
18
+ sous-titres des émissions
19
+ - Ajout de nouveaux paramètres pour contrôler cet affichage :
20
+ - `hideSubtitle` dans `emissionPage` & `podcastPage`, pour cacher les
21
+ sous-titres
22
+ - `descriptionOrSummary` dans `emissionPage`, pour choisir quel élément
23
+ afficher
24
+ - **14387** - Affichage du numéro de saison et d'épisode, ainsi que du type
25
+ d'épisode dans les `PodcastItemInfo`
26
+ - La configuration eslint est maintenant exportée, elle peut donc être intégrée
27
+ telle quelle dans les projets se basant sur le SDK
28
+ - Ajout d'options de configuration pour `ClassicLoading` et `ClassicSpinner`
29
+
30
+ **Fix**
31
+
32
+ - **14404** - Correction affichage de la transcription dans le cas de preroll/
33
+ postrolls multiples
34
+ - Correction `z-index` des boutons de `SwiperList`
35
+ - La propriété `focus` de `ClassicInputText` est à `false` par défaut
36
+
37
+ **Misc**
38
+
39
+ - Correction warning avec les icônes de `useSharePlatforms`
40
+ - Ajustement composants pour les podcastmakers
41
+ - Mise à jour des dépendances
42
+ - Les exports d'organisation viennent du SDK et non plus du package parent
43
+
3
44
  ## 41.8.4 (24/03/2026)
4
45
 
5
46
  **Fix**
@@ -0,0 +1,3 @@
1
+ import type { ConfigArray } from 'typescript-eslint';
2
+ declare const config: ConfigArray;
3
+ export default config;
@@ -0,0 +1,43 @@
1
+ import eslint from '@eslint/js';
2
+ import eslintPluginVue from 'eslint-plugin-vue';
3
+ import globals from 'globals';
4
+ import typescriptEslint from 'typescript-eslint';
5
+
6
+ export default typescriptEslint.config(
7
+ { ignores: ['*.d.ts', '**/coverage', '**/dist'] },
8
+ {
9
+ extends: [
10
+ eslint.configs.recommended,
11
+ ...typescriptEslint.configs.recommended,
12
+ ...eslintPluginVue.configs['flat/recommended'],
13
+ ],
14
+ files: ['**/*.{ts,vue}'],
15
+ languageOptions: {
16
+ ecmaVersion: 'latest',
17
+ sourceType: 'module',
18
+ globals: globals.browser,
19
+ parserOptions: {
20
+ parser: typescriptEslint.parser,
21
+ },
22
+ },
23
+ rules: {
24
+ // your rules
25
+ "curly": ['error'],
26
+
27
+ // Please don't use console statements and duplicated imports, TODOs are marked
28
+ "no-console": ['warn', { allow: ['warn', 'error'] }],
29
+ "no-warning-comments": ['warn'],
30
+ "no-duplicate-imports": ['warn'],
31
+
32
+ // Prevent errors when testing on refs (instead of value of ref)
33
+ "vue/no-ref-as-operand": ['error'],
34
+
35
+ // Indentation
36
+ "vue/html-indent": ['warn', 4],
37
+ "vue/script-indent": ['warn', 4],
38
+
39
+ // Number of attributes per line (increase because sometimes two is not a lot)
40
+ "vue/max-attributes-per-line": ['warn', { singleline: 2 } ]
41
+ },
42
+ }
43
+ );
package/eslint.config.mjs CHANGED
@@ -1,43 +1,2 @@
1
- import eslint from '@eslint/js';
2
- import eslintPluginVue from 'eslint-plugin-vue';
3
- import globals from 'globals';
4
- import typescriptEslint from 'typescript-eslint';
5
-
6
- export default typescriptEslint.config(
7
- { ignores: ['*.d.ts', '**/coverage', '**/dist'] },
8
- {
9
- extends: [
10
- eslint.configs.recommended,
11
- ...typescriptEslint.configs.recommended,
12
- ...eslintPluginVue.configs['flat/recommended'],
13
- ],
14
- files: ['**/*.{ts,vue}'],
15
- languageOptions: {
16
- ecmaVersion: 'latest',
17
- sourceType: 'module',
18
- globals: globals.browser,
19
- parserOptions: {
20
- parser: typescriptEslint.parser,
21
- },
22
- },
23
- rules: {
24
- // your rules
25
- "curly": ['error'],
26
-
27
- // Please don't use console statements and duplicated imports, TODOs are marked
28
- "no-console": ['warn', { allow: ['warn', 'error'] }],
29
- "no-warning-comments": ['warn'],
30
- "no-duplicate-imports": ['warn'],
31
-
32
- // Prevent errors when testing on refs (instead of value of ref)
33
- "vue/no-ref-as-operand": ['error'],
34
-
35
- // Indentation
36
- "vue/html-indent": ['warn', 4],
37
- "vue/script-indent": ['warn', 4],
38
-
39
- // Number of attributes per line (increase because sometimes two is not a lot)
40
- "vue/max-attributes-per-line": ['warn', { singleline: 2 } ]
41
- },
42
- }
43
- );
1
+ import sdkConfig from './eslint-config.mjs';
2
+ export default sdkConfig;
package/index.ts CHANGED
@@ -161,6 +161,7 @@ import classicApi from "./src/api/classicApi.ts";
161
161
 
162
162
  // API
163
163
  export { emissionApi } from "./src/api/emissionApi.ts";
164
+ export { transcriptionApi } from "./src/api/transcriptionApi.ts";
164
165
  export * from "./src/api/groupsApi.ts";
165
166
  export { organisationApi } from "./src/api/organisationApi.ts";
166
167
  export { playlistApi } from "./src/api/playlistApi.ts";
@@ -168,9 +169,23 @@ export { podcastApi, PodcastSort, type PodcastSearchOptions } from "./src/api/po
168
169
 
169
170
  // Types
170
171
  export { type Emission, SeasonMode, emptyEmissionData } from "./src/stores/class/general/emission.ts";
172
+ export { type Organisation, type OrganisationAttributes, emptyOrganisationData, emptyOrgaData } from "./src/stores/class/general/organisation.ts";
171
173
  export { type Podcast, type PodcastAvailability, PodcastType } from "./src/stores/class/general/podcast.ts";
172
174
  export { type Playlist, type PlaylistRule } from "./src/stores/class/general/playlist.ts";
173
175
  export { type Annotations } from "./src/stores/class/general";
176
+ export {
177
+ CreateTranslation,
178
+ type TranslationConfiguration,
179
+ defaultTranslationConfig,
180
+ defaultModifyPodcastConfig,
181
+ defaultTtsParams,
182
+ type ModifyPodcastConfig,
183
+ ModifyPodcastEnum,
184
+ type TranscriptParams,
185
+ type TtsParams,
186
+ type ProviderTts,
187
+ type Voice
188
+ } from "./src/stores/class/transcript/transcriptParams.ts";
174
189
 
175
190
  //Icons
176
191
  export const getAmazonMusicIcon = () => import("./src/components/icons/AmazonMusicIcon.vue");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saooti/octopus-sdk",
3
- "version": "41.8.4",
3
+ "version": "41.9.0",
4
4
  "private": false,
5
5
  "description": "Javascript SDK for using octopus",
6
6
  "author": "Saooti",
@@ -12,7 +12,7 @@
12
12
  "bundle": "vite-bundle-visualizer",
13
13
  "proxy_authentifié": "node proxy.ts",
14
14
  "proxy_non_authentifié": "node proxy.ts false",
15
- "lint": "eslint --fix src",
15
+ "lint": "eslint --fix --max-warnings 0",
16
16
  "stylelint": "stylelint **/*.{scss,vue} --fix",
17
17
  "sonar": "sonar -Dsonar.host.url=http://localhost:9000"
18
18
  },
@@ -95,5 +95,17 @@
95
95
  },
96
96
  "peerDependencies": {
97
97
  "pinia": ">=2.3.0"
98
+ },
99
+ "exports": {
100
+ ".": {
101
+ "types": "./index.d.ts",
102
+ "default": "./index.ts"
103
+ },
104
+ "./src/*": "./src/*",
105
+ "./tests/*": "./tests/*",
106
+ "./eslint-config": {
107
+ "types": "./eslint-config.d.ts",
108
+ "default": "./eslint-config.mjs"
109
+ }
98
110
  }
99
111
  }
@@ -1,4 +1,5 @@
1
- import { classicApi, ModuleApi } from ".yalc/@saooti/octopus-sdk";
1
+ import { ModuleApi } from "./apiConnection";
2
+ import classicApi from "./classicApi";
2
3
 
3
4
  /** State of the translation */
4
5
  export enum TranslationState {
@@ -30,6 +31,11 @@ export interface PodcastTranslationData {
30
31
  translations: Array<TranslationData>;
31
32
  }
32
33
 
34
+ interface TranslationProgress {
35
+ started: boolean;
36
+ percent: number;
37
+ }
38
+
33
39
  /**
34
40
  * Returns the translations defined on the podcast
35
41
  * @param podcastId ID of the podcast
@@ -38,10 +44,64 @@ export interface PodcastTranslationData {
38
44
  async function getTranslations(podcastId: number): Promise<PodcastTranslationData> {
39
45
  return classicApi.fetchData<PodcastTranslationData>({
40
46
  api: ModuleApi.SPEECHTOTEXT,
41
- path: 'transcription/' + podcastId
47
+ path: `transcription/${podcastId}/languages`
48
+ });
49
+ }
50
+
51
+ /**
52
+ * Returns the translation in a given language for the podcast
53
+ * @param podcastId ID of the podcast
54
+ * @param language The target language
55
+ * @param mayCreate *(optional)* If set to true, request creation if not available
56
+ * @returns The transcription
57
+ */
58
+ async function getTranslation(podcastId: number, language: string, mayCreate?: boolean): Promise<string> {
59
+ let path = `transcription/${podcastId}/languages/${language}/srt`;
60
+ if (mayCreate !== undefined) {
61
+ path = `${path}?mayCreateIfNotExists=${mayCreate}`;
62
+ }
63
+
64
+ let found = false;
65
+ let timeout = 1000;
66
+ const timeoutStep = 100;
67
+ while (!found) {
68
+ const result = await classicApi.fetchData<string|TranslationProgress>({
69
+ api: ModuleApi.SPEECHTOTEXT,
70
+ path
71
+ });
72
+
73
+ // Stop when we get the proper result
74
+ if (typeof result === 'string') {
75
+ found = true;
76
+ return result;
77
+ }
78
+
79
+ // Wait some time before retrying
80
+ await new Promise((resolve) => setTimeout(resolve, timeout));
81
+ timeout += timeoutStep;
82
+
83
+ if (timeout >= 60 * 1000) {
84
+ break;
85
+ }
86
+ }
87
+
88
+ throw new Error('Timeout lors de la récupération de la transcription');
89
+ }
90
+
91
+ /**
92
+ * Get raw transcription for the given podcast
93
+ * @param podcastId ID of the podcast
94
+ * @returns The raw transcript
95
+ */
96
+ async function getRawTranscription(podcastId: number): Promise<string> {
97
+ return classicApi.fetchData({
98
+ api: ModuleApi.SPEECHTOTEXT,
99
+ path: `transcription/text/${podcastId}`,
42
100
  });
43
101
  }
44
102
 
45
103
  export const transcriptionApi = {
46
- getTranslations
104
+ getTranslations,
105
+ getTranslation,
106
+ getRawTranscription
47
107
  };
@@ -20,6 +20,7 @@ export const usePlayerDisplayTime = ()=>{
20
20
  }
21
21
  return playerStore.totalTime;
22
22
  });
23
+
23
24
  const transcriptText = computed(() => {
24
25
  return playerStore.transcriptText;
25
26
  });
@@ -2,45 +2,74 @@ import { usePlayerStore } from "../../../stores/PlayerStore";
2
2
  import { useVastStore } from "../../../stores/VastStore";
3
3
  import classicApi from "../../../api/classicApi";
4
4
  import { AdserverOtherEmission } from "@/stores/class/adserver/adserverOtherEmission";
5
+ import { useTranslation } from "../useTranslation";
6
+ import { transcriptionApi } from "../../../api/transcriptionApi";
7
+ import { ref } from "vue";
8
+
9
+ /** Contains the language of the transcript being generated */
10
+ const generatingTranscriptLanguage = ref<string|null>(null);
11
+
5
12
  export const usePlayerTranscript = ()=>{
6
13
 
7
14
  const playerStore = usePlayerStore();
8
15
  const vastStore = useVastStore();
16
+ const { getMostRelevantLanguage } = useTranslation();
9
17
 
10
18
  async function checkDelaytWithStitching(){
11
19
  playerStore.playerUpdateDelayStitching(0);
12
- if(vastStore.useVastPlayerPodcast){return;}
20
+ if(vastStore.useVastPlayerPodcast){
21
+ return;
22
+ }
23
+
13
24
  const audioPlayer = document.querySelector("#audio-player") as HTMLAudioElement;
14
25
  if (!playerStore.playerTranscript || !audioPlayer || !playerStore.playerPodcast ||
15
- audioPlayer.duration <= playerStore.playerPodcast.duration / 1000 + 5)
16
- {
26
+ audioPlayer.duration <= playerStore.playerPodcast.duration / 1000 + 5) {
17
27
  return;
18
28
  }
29
+
19
30
  const adserverConfig = await classicApi.fetchData<AdserverOtherEmission>({
20
31
  api:0,
21
32
  path:`ad/test/podcast/${playerStore.playerPodcast.podcastId}`,
22
33
  isNotAuth:true
23
34
  });
24
- const doubletsLength = adserverConfig.config.doublets.length;
25
- if(1=== doubletsLength && "pre" === adserverConfig.config.doublets[0].timing.insertion){
26
- playerStore.playerUpdateDelayStitching( audioPlayer.duration - (playerStore.playerPodcast.duration / 1000));
27
- }else if(0===doubletsLength || 1=== doubletsLength && "post" === adserverConfig.config.doublets[0].timing.insertion){
28
- return;
29
- }else{
35
+
36
+ // In case of midroll ads, we can't properly display transcription, so
37
+ // we disable it.
38
+ const hasOtherThanPreOrPost = adserverConfig.config.doublets
39
+ .filter(doublet => !(["pre", "post"].includes(doublet.timing.insertion)))
40
+ .length > 0;
41
+ if (hasOtherThanPreOrPost) {
42
+ console.warn("This episode's ad settings doesn't allow for transcription");
30
43
  playerStore.playerUpdateChaptering();
31
44
  playerStore.playerUpdateTranscript();
45
+ return;
46
+ }
47
+
48
+ // In case of preroll ads, delay start of transcription
49
+ const hasPre = adserverConfig.config.doublets
50
+ .filter(doublet => doublet.timing.insertion === "pre")
51
+ .length > 0;
52
+ if(hasPre) {
53
+ // Since we have the expected time (from playerStore) and effective time
54
+ // (from audioPlayer, which include ads), we just delay by the delta
55
+ playerStore.playerUpdateDelayStitching( audioPlayer.duration - (playerStore.playerPodcast.duration / 1000));
32
56
  }
33
57
  }
34
58
 
35
59
  async function getTranscription(): Promise<void> {
60
+ generatingTranscriptLanguage.value = null;
36
61
  if (!playerStore.playerPodcast) {
37
62
  playerStore.playerUpdateTranscript();
38
63
  return;
39
64
  }
40
- const result = await classicApi.fetchData<string>({
41
- api:11,
42
- path:`response/${playerStore.playerPodcast.podcastId}`,
43
- });
65
+
66
+ // Retrieve best language for transcription
67
+ const podcastId = playerStore.playerPodcast.podcastId;
68
+ const translationData = await transcriptionApi.getTranslations(podcastId);
69
+ const { ready, available } = await getMostRelevantLanguage(translationData);
70
+
71
+ // Retrieve transcription
72
+ const result = await transcriptionApi.getTranslation(podcastId, ready);
44
73
 
45
74
  const arrayTranscript = parseSrt(result);
46
75
  const actualText =
@@ -53,6 +82,26 @@ export const usePlayerTranscript = ()=>{
53
82
  actualText: actualText,
54
83
  value: arrayTranscript
55
84
  });
85
+
86
+ if (available !== undefined && ready !== available) {
87
+ generatingTranscriptLanguage.value = available;
88
+
89
+ // If there's a better language available, trigger its generation
90
+ const result = await transcriptionApi.getTranslation(podcastId, available, true);
91
+
92
+ const arrayTranscript = parseSrt(result);
93
+ const actualText =
94
+ arrayTranscript?.[0]?.startTime === 0 ? arrayTranscript[0].text : "";
95
+ if(!arrayTranscript){
96
+ return;
97
+ }
98
+ playerStore.playerUpdateTranscript({
99
+ actual: playerStore.playerTranscript?.actual,
100
+ actualText: actualText,
101
+ value: arrayTranscript
102
+ });
103
+ generatingTranscriptLanguage.value = null;
104
+ }
56
105
  }
57
106
 
58
107
  function parseSrt(transcript: string) {
@@ -110,11 +159,11 @@ export const usePlayerTranscript = ()=>{
110
159
  }
111
160
  }
112
161
 
113
-
114
- return {
162
+ return {
115
163
  checkDelaytWithStitching,
116
164
  getTranscription,
117
165
  onTimeUpdateTranscript,
118
- onSeekedTranscript
119
- }
166
+ onSeekedTranscript,
167
+ generatingTranscriptLanguage
168
+ }
120
169
  }
@@ -1,4 +1,4 @@
1
- import { OrganisationAttributes } from "@/stores/class/general/organisation";
1
+ import { OrganisationAttributes } from "../../../stores/class/general/organisation";
2
2
  import { RouteLocationAsRelativeTyped, useRouter } from "vue-router";
3
3
  import { useSeoTitleUrl } from "../route/useSeoTitleUrl";
4
4
 
@@ -14,7 +14,7 @@ import RadioFranceIcon from "../../icons/RadioFranceIcon.vue";
14
14
  import YoutubeIcon from "vue-material-design-icons/Youtube.vue";
15
15
  import SpotifyIcon from "vue-material-design-icons/Spotify.vue";
16
16
  import { Annotations } from "@/stores/class/general";
17
- import { computed, type Component } from "vue";
17
+ import { computed, markRaw, type Component } from "vue";
18
18
 
19
19
  export enum SharePlatformName {
20
20
  APPLE = "applePodcast",
@@ -55,77 +55,77 @@ export const useSharePlatforms = () => {
55
55
  const platforms = computed((): Array<SharePlatform> => {
56
56
  return [{
57
57
  name: SharePlatformName.APPLE,
58
- icon: ApplePodcastIcon,
58
+ icon: markRaw(ApplePodcastIcon),
59
59
  title: "Apple Podcast | iTunes",
60
60
  color:"#aa1dd3"
61
61
  }, {
62
62
  name: SharePlatformName.DEEZER,
63
- icon: DeezerIcon,
63
+ icon: markRaw(DeezerIcon),
64
64
  title: "Deezer",
65
65
  color:"#a238ff",
66
66
  }, {
67
67
  name: SharePlatformName.SPOTIFY,
68
- icon: SpotifyIcon,
68
+ icon: markRaw(SpotifyIcon),
69
69
  title: "Spotify",
70
70
  color: "#1ed760",
71
71
  }, {
72
72
  name: SharePlatformName.AMAZON,
73
- icon: AmazonMusicIcon,
73
+ icon: markRaw(AmazonMusicIcon),
74
74
  title: "Amazon Music",
75
75
  color: "#0c6cb3",
76
76
  }, {
77
77
  name: SharePlatformName.I_HEART,
78
- icon: IHeartIcon,
78
+ icon: markRaw(IHeartIcon),
79
79
  title: "iHeart",
80
80
  color:"#e11b22"
81
81
  }, {
82
82
  name: SharePlatformName.PLAYER_FM,
83
- icon: PlayerFmIcon,
83
+ icon: markRaw(PlayerFmIcon),
84
84
  title: "Player FM",
85
85
  color:"#bb202a"
86
86
  }, {
87
87
  name: SharePlatformName.POCKET_CASTS,
88
- icon: PocketCastIcon,
88
+ icon: markRaw(PocketCastIcon),
89
89
  title: "Pocket Casts",
90
90
  color:"#f43e37"
91
91
  }, {
92
92
  name: SharePlatformName.PODCAST_ADDICT,
93
- icon: PodcastAddictIcon,
93
+ icon: markRaw(PodcastAddictIcon),
94
94
  title: "Podcast Addict",
95
95
  color:"#f4842d"
96
96
  }, {
97
97
  name: SharePlatformName.RADIOLINE,
98
- icon: RadiolineIcon,
98
+ icon: markRaw(RadiolineIcon),
99
99
  title: "Radioline",
100
100
  color:"#1678bd"
101
101
  }, {
102
102
  name: SharePlatformName.TUNE_IN,
103
- icon: TuninIcon,
103
+ icon: markRaw(TuninIcon),
104
104
  title: "TuneIn",
105
105
  color:"#36b4a7"
106
106
  }, {
107
107
  name: SharePlatformName.YOUTUBE,
108
- icon: YoutubeIcon,
108
+ icon: markRaw(YoutubeIcon),
109
109
  title: "YouTube Music",
110
110
  color: "#fe0000",
111
111
  }, {
112
112
  name: SharePlatformName.CASTBOX,
113
- icon: CastboxIcon,
113
+ icon: markRaw(CastboxIcon),
114
114
  title: "Castbox",
115
115
  color: "#fe6222",
116
116
  }, {
117
117
  name: SharePlatformName.PODBEAN,
118
- icon: PodbeanIcon,
118
+ icon: markRaw(PodbeanIcon),
119
119
  title: "PodBean",
120
120
  color: "#428200",
121
121
  }, {
122
122
  name: SharePlatformName.PODCAST_REPUBLIC,
123
- icon: PodcastRepublicIcon,
123
+ icon: markRaw(PodcastRepublicIcon),
124
124
  title: "Podcast Republic",
125
125
  color: "#5c85dd",
126
126
  }, {
127
127
  name: SharePlatformName.RADIO_FRANCE,
128
- icon: RadioFranceIcon,
128
+ icon: markRaw(RadioFranceIcon),
129
129
  title: "Radio France",
130
130
  color: "#a90041",
131
131
  }];