@saooti/octopus-sdk 36.0.9 → 36.0.11

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 (48) hide show
  1. package/package.json +1 -1
  2. package/public/img/tempRadio.jpg +0 -0
  3. package/src/assets/general.scss +9 -0
  4. package/src/assets/iframe.scss +11 -0
  5. package/src/assets/share.scss +38 -0
  6. package/src/assets/transition.scss +2 -3
  7. package/src/components/display/edit/EditBoxRadio.vue +11 -0
  8. package/src/components/display/list/SwiperList.vue +109 -0
  9. package/src/components/display/live/LiveItem.vue +26 -242
  10. package/src/components/display/live/LiveList.vue +111 -189
  11. package/src/components/display/live/RadioCurrently.vue +108 -0
  12. package/src/components/display/live/RadioImage.vue +84 -0
  13. package/src/components/display/live/RadioItem.vue +44 -0
  14. package/src/components/display/live/RadioList.vue +72 -0
  15. package/src/components/display/playlist/PlaylistList.vue +1 -0
  16. package/src/components/display/podcasts/PodcastImage.vue +15 -48
  17. package/src/components/display/podcasts/PodcastItem.vue +3 -0
  18. package/src/components/display/podcasts/PodcastSwiperList.vue +9 -80
  19. package/src/components/display/sharing/ShareButtons.vue +1 -0
  20. package/src/components/display/sharing/SharePlayer.vue +2 -10
  21. package/src/components/display/sharing/SharePlayerColors.vue +1 -1
  22. package/src/components/display/sharing/SharePlayerRadio.vue +102 -0
  23. package/src/components/misc/LeftMenu.vue +1 -1
  24. package/src/components/misc/ProgressBar.vue +4 -0
  25. package/src/components/misc/TopBar.vue +1 -1
  26. package/src/components/misc/modal/ShareModalPlayer.vue +2 -2
  27. package/src/components/misc/player/PlayerCompact.vue +1 -0
  28. package/src/components/mixins/player/playerDisplay.ts +27 -10
  29. package/src/components/mixins/radio/fetchRadioData.ts +47 -0
  30. package/src/components/pages/Lives.vue +22 -48
  31. package/src/components/pages/Playlist.vue +9 -2
  32. package/src/components/pages/Radio.vue +112 -0
  33. package/src/locale/de.ts +8 -3
  34. package/src/locale/en.ts +10 -5
  35. package/src/locale/es.ts +8 -3
  36. package/src/locale/fr.ts +10 -5
  37. package/src/locale/it.ts +8 -3
  38. package/src/locale/sl.ts +8 -3
  39. package/src/router/router.ts +10 -0
  40. package/src/stores/ParamSdkStore.ts +12 -12
  41. package/src/stores/PlayerStore.ts +8 -0
  42. package/src/stores/class/general/player.ts +9 -7
  43. package/src/stores/class/general/playlist.ts +2 -0
  44. package/src/stores/class/radio/canal.ts +9 -0
  45. package/src/stores/class/radio/live.ts +34 -0
  46. package/src/stores/class/radio/mix.ts +23 -0
  47. package/src/stores/class/radio/playlistMedia.ts +10 -0
  48. package/src/stores/class/radio/recurrence.ts +76 -0
@@ -33,7 +33,7 @@
33
33
  </div>
34
34
  <button
35
35
  v-if="hidePlay || recordingLive"
36
- class="podcast-image-play-button"
36
+ class="image-play-button"
37
37
  :class="classicPodcastPlay ? '' : 'transparent-background'"
38
38
  @click="play"
39
39
  >
@@ -65,7 +65,7 @@
65
65
  </div>
66
66
  <div
67
67
  v-else
68
- class="icon-container error-icon"
68
+ class="icon-container play-button-error-icon"
69
69
  >
70
70
  <div
71
71
  :title="textVisible"
@@ -75,7 +75,7 @@
75
75
  </div>
76
76
  <div
77
77
  v-if="!classicPodcastPlay"
78
- class="h6 mt-3 fw-bolder"
78
+ class="live-image-status bg-dark"
79
79
  >
80
80
  {{ textVisible }}
81
81
  </div>
@@ -321,59 +321,26 @@ export default defineComponent({
321
321
  .transparent-background {
322
322
  background-color: rgba(255, 255, 255, 0.5);
323
323
  }
324
- .podcast-image-play-button{
325
- position: absolute;
326
- display: flex;
327
- justify-content: flex-end;
328
- top: 0;
329
- left: 0;
330
- right: 0;
331
- bottom: 0;
332
- cursor: pointer;
333
- flex-direction: column;
334
- background: transparent;
335
- border-width: 0;
336
- width: 100%;
337
- &:focus{
338
- background: rgba(0, 0, 0, 0.5);
339
- }
340
-
341
- .icon-container {
342
- background: $primaryColorLessTransparent !important;
343
- border-radius: 2rem;
344
- color: white;
345
- padding: 0.5rem;
346
- margin: 0.5rem;
347
- display: flex;
348
- align-items: center;
349
- justify-content: center;
350
- z-index: 2;
351
- &.error-icon {
352
- background: #00000050 !important;
353
- cursor: default !important;
354
- }
355
- &:hover {
356
- background: #00000030;
357
- }
358
- .saooti-play {
359
- font-size: 1.2rem;
360
- position: relative;
361
- color: white;
362
- }
363
- .big-icon-error {
364
- font-size: 1rem;
365
- position: relative;
366
- }
324
+
325
+ .play-button-error-icon {
326
+ background: #0000009d !important;
327
+ cursor: default !important;
328
+ align-self: center;
329
+ margin-bottom: calc(50% - 1rem);
330
+ .big-icon-error {
331
+ font-size: 2rem;
332
+ position: relative;
367
333
  }
368
334
  }
369
335
  .special-icon-play-button {
370
336
  width: 30px;
371
337
  height: 30px;
372
338
  background-color: #ffd663;
339
+ color: black;
373
340
  border-radius: 50%;
374
341
  position: absolute;
375
- left: 4.5rem;
376
- bottom: 4rem;
342
+ left: 4.4rem;
343
+ bottom: 2.2rem;
377
344
  font-size: 0.9rem;
378
345
  font-weight: bold;
379
346
  display: flex;
@@ -12,6 +12,7 @@
12
12
  :hide-play="!podcastItemDescription || (podcastItemDescription && (!hoverDesc || !description))"
13
13
  :display-description="0!==description.length && podcastItemDescription"
14
14
  :arrow-direction="arrowDirection"
15
+ :fetchConference="fetchConference"
15
16
  @hideDescription="hideDescription"
16
17
  @showDescription="showDescription"
17
18
  />
@@ -55,6 +56,7 @@ import { state } from '../../../stores/ParamSdkStore';
55
56
  import dayjs from 'dayjs';
56
57
  import { Podcast } from '@/stores/class/general/podcast';
57
58
  import { defineComponent } from 'vue'
59
+ import { Conference } from '@/stores/class/conference/conference';
58
60
  export default defineComponent({
59
61
  name: 'PodcastItem',
60
62
 
@@ -65,6 +67,7 @@ export default defineComponent({
65
67
 
66
68
  props: {
67
69
  podcast: { default: ()=>({}), type: Object as ()=> Podcast},
70
+ fetchConference: { default: undefined, type: Object as ()=>Conference},
68
71
  },
69
72
 
70
73
  data() {
@@ -18,24 +18,17 @@
18
18
  class="loading-size"
19
19
  :loading-text="loading?$t('Loading podcasts ...'):undefined"
20
20
  />
21
- <swiper
21
+ <SwiperList
22
22
  v-if="!loading"
23
- :slides-per-view="numberItem"
24
- :space-between="0"
25
- :loop="allPodcasts.length>=numberItem"
26
- :navigation="true"
27
- :modules="modules"
23
+ :listObject="allPodcasts"
28
24
  >
29
- <swiper-slide
30
- v-for="p in allPodcasts"
31
- :key="p.podcastId"
32
- >
25
+ <template #octopusSlide="{option}">
33
26
  <PodcastItem
34
27
  class="flex-shrink-0 item-phone-margin"
35
- :podcast="p"
28
+ :podcast="option"
36
29
  />
37
- </swiper-slide>
38
- </swiper>
30
+ </template>
31
+ </SwiperList>
39
32
  </template>
40
33
  </PodcastInlineListTemplate>
41
34
  </template>
@@ -43,14 +36,9 @@
43
36
  <script lang="ts">
44
37
  import PodcastInlineListTemplate from './PodcastInlineListTemplate.vue';
45
38
  import octopusApi from '@saooti/octopus-api';
46
- import domHelper from '../../../helper/dom';
47
39
  import PodcastItem from './PodcastItem.vue';
48
- import { state } from '../../../stores/ParamSdkStore';
49
40
  import ClassicLoading from '../../form/ClassicLoading.vue';
50
- import { Swiper, SwiperSlide } from "swiper/vue";
51
- import { Navigation } from "swiper";
52
- import "swiper/css";
53
- import "swiper/css/navigation";
41
+ import SwiperList from '../list/SwiperList.vue';
54
42
  import { useFilterStore } from '@/stores/FilterStore';
55
43
  import { mapState } from 'pinia';
56
44
  import { Podcast } from '@/stores/class/general/podcast';
@@ -62,8 +50,7 @@ export default defineComponent({
62
50
  PodcastInlineListTemplate,
63
51
  PodcastItem,
64
52
  ClassicLoading,
65
- Swiper,
66
- SwiperSlide,
53
+ SwiperList
67
54
  },
68
55
 
69
56
  props: {
@@ -88,8 +75,6 @@ export default defineComponent({
88
75
  loading: true as boolean,
89
76
  popularSort: false as boolean,
90
77
  allPodcasts: [] as Array<Podcast>,
91
- modules: [Navigation],
92
- numberItem: 5 as number
93
78
  };
94
79
  },
95
80
  computed: {
@@ -100,12 +85,6 @@ export default defineComponent({
100
85
  watchVariable():string{
101
86
  return `${this.emissionId}|${this.organisationId}|${this.filterOrgaId}|${this.iabId}|${this.rubriqueId}|${this.rubriquageId}|${this.query}`;
102
87
  },
103
- sizeItem(): number {
104
- if (window.innerWidth <= 450) {
105
- return 12.5;
106
- }
107
- return state.generalParameters.podcastItem ? state.generalParameters.podcastItem: 16.5;
108
- },
109
88
  },
110
89
  watch: {
111
90
  watchVariable(): void {
@@ -121,24 +100,11 @@ export default defineComponent({
121
100
  if (undefined !== this.isArrow) {
122
101
  this.$emit('update:isArrow', true);
123
102
  }
124
- window.addEventListener('resize', this.handleResize);
125
- },
126
- unmounted() {
127
- window.removeEventListener('resize', this.handleResize);
128
103
  },
129
-
130
-
131
104
  mounted() {
132
- this.handleResize();
133
105
  this.fetchNext();
134
106
  },
135
107
  methods: {
136
- handleResize(): void {
137
- if (!this.$el) return;
138
- const width = (this.$el as HTMLElement).offsetWidth - 95;
139
- const sixteen = domHelper.convertRemToPixels(this.sizeItem+ 0.5);
140
- this.numberItem = Math.max(1, Math.floor(width / sixteen));
141
- },
142
108
  async fetchNext(): Promise<void> {
143
109
  const data = await octopusApi.fetchDataWithParams<{count: number;result:Array<Podcast>;sort: string;}>(0, 'podcast/search',{
144
110
  first: 0,
@@ -176,41 +142,4 @@ export default defineComponent({
176
142
  },
177
143
  },
178
144
  })
179
- </script>
180
- <style lang="scss">
181
- @import '@scss/_variables.scss';
182
- .swiper {
183
- width: 100%;
184
- height: 100%;
185
- }
186
- .swiper-button-next, .swiper-button-prev{
187
- color: $octopus-primary-color !important;
188
- height: 100%;
189
- top: 0;
190
- bottom: 0;
191
- margin: 0;
192
- }
193
- .swiper-button-next{
194
- right: 0;
195
- }
196
- .swiper-button-prev{
197
- left: 0;
198
- }
199
- .swiper-slide-active{
200
- padding-left:27px;
201
- @media (max-width: 550px) {
202
- padding-left:0;
203
- }
204
- }
205
- .swiper-slide-next{
206
- padding-right:27px;
207
- }
208
- .swiper-button-lock{
209
- display: flex;
210
- }
211
- .swiper-slide {
212
- display: flex;
213
- justify-content: center;
214
- align-items: center;
215
- }
216
- </style>
145
+ </script>
@@ -41,6 +41,7 @@ import Popover from '../../misc/Popover.vue';
41
41
  import ShareButtonsIntern from './ShareButtonsIntern.vue';
42
42
  import { defineComponent } from 'vue';
43
43
  import { Playlist } from '@/stores/class/general/playlist';
44
+ import { Canal } from '@/stores/class/radio/canal';
44
45
  export default defineComponent({
45
46
  components: {
46
47
  ShareButtonsIntern,
@@ -32,6 +32,7 @@
32
32
  :organisation-id="organisationId"
33
33
  />
34
34
  <SharePlayerColors
35
+ class="mt-3"
35
36
  v-model:color="color"
36
37
  v-model:theme="theme"
37
38
  />
@@ -126,7 +127,6 @@ export default defineComponent({
126
127
  isVisible: false as boolean,
127
128
  displayArticle: true as boolean,
128
129
  displayTranscript: true as boolean,
129
- colors: ['#000000', '#ffffff'],
130
130
  orgaAttributes: undefined as{[key: string]:string|number|boolean|undefined}|undefined,
131
131
  };
132
132
  },
@@ -303,10 +303,8 @@ export default defineComponent({
303
303
 
304
304
  <style lang="scss">
305
305
  @import '@scss/_variables.scss';
306
+ @import '../../../assets/iframe.scss';
306
307
  .octopus-app{
307
- iframe{
308
- border:0;
309
- }
310
308
  .sticker {
311
309
  align-self: center;
312
310
  background: $octopus-primary-color;
@@ -324,11 +322,5 @@ export default defineComponent({
324
322
  color: $octopus-primary-color;
325
323
  }
326
324
  }
327
- .max-iframe {
328
- width: 500px;
329
- @media (max-width: 960px){
330
- width: calc(100% - 2rem);
331
- }
332
- }
333
325
  }
334
326
  </style>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="d-flex mt-3">
2
+ <div class="d-flex">
3
3
  <div class="d-flex flex-column align-items-center flex-shrink-0 me-4">
4
4
  <div class="h4 mb-2">
5
5
  {{ $t('Choose color') }}
@@ -0,0 +1,102 @@
1
+ <template>
2
+ <div class="module-box overflow-visible">
3
+ <h2 class="big-h2 mb-3 height-40">
4
+ {{ $t('Embed') }}
5
+ </h2>
6
+ <div class="d-flex">
7
+ <iframe
8
+ id="miniplayerIframeRadio"
9
+ title="miniplayer"
10
+ :src="iFrameSrc"
11
+ width="100%"
12
+ height="140px"
13
+ class="max-iframe mx-3 flex-grow-1"
14
+ />
15
+ <div class="d-flex flex-column flex-grow-1 align-items-center">
16
+ <SharePlayerColors
17
+ v-model:color="color"
18
+ v-model:theme="theme"
19
+ />
20
+ <ShareModalPlayer
21
+ v-if="isShareModal"
22
+ :embed-link="iFrame"
23
+ :embedly-link="iFrameSrc"
24
+ @close="isShareModal = false"
25
+ />
26
+ <button
27
+ class="btn btn-primary width-fit-content mt-3"
28
+ @click="isShareModal = true"
29
+ >
30
+ {{ $t('Share the player') }}
31
+ </button>
32
+ </div>
33
+ </div>
34
+ </div>
35
+ </template>
36
+
37
+ <script lang="ts">
38
+ import { orgaComputed } from '../../mixins/orgaComputed';
39
+ import { state } from '../../../stores/ParamSdkStore';
40
+ import octopusApi from '@saooti/octopus-api';
41
+ import { useAuthStore } from '@/stores/AuthStore';
42
+ import { mapState } from 'pinia';
43
+ import { defineComponent, defineAsyncComponent } from 'vue';
44
+ import { Canal } from '@/stores/class/radio/canal';
45
+ const ShareModalPlayer = defineAsyncComponent(() => import('../../misc/modal/ShareModalPlayer.vue'));
46
+ const SharePlayerColors = defineAsyncComponent(() => import('./SharePlayerColors.vue'));
47
+ export default defineComponent({
48
+ components: {
49
+ ShareModalPlayer,
50
+ SharePlayerColors
51
+ },
52
+ mixins:[orgaComputed],
53
+ props: {
54
+ canal: { default: undefined, type: Object as ()=> Canal},
55
+ organisationId: { default: undefined, type: String},
56
+ },
57
+
58
+ data() {
59
+ return {
60
+ isShareModal: false as boolean,
61
+ color: '#40a372' as string,
62
+ theme: '#000000' as string,
63
+ orgaAttributes: undefined as{[key: string]:string|number|boolean|undefined}|undefined,
64
+ };
65
+ },
66
+
67
+ computed: {
68
+ ...mapState(useAuthStore, ['authOrganisation']),
69
+ iFrameSrc(): string{
70
+ return `${state.podcastPage.MiniplayerUri}miniplayer/radio/${this.canal?.id}?distributorId=${this.organisationId}&color=${this.color.substring(1)}&theme=${this.theme.substring(1)}`;
71
+ },
72
+
73
+ iFrame(): string {
74
+ return `<iframe src="${this.iFrameSrc}" width="100%" height="140px" scrolling="no" frameborder="0"></iframe>`;
75
+ },
76
+
77
+ },
78
+ async created() {
79
+ await this.fetchOrgaAttributes();
80
+ this.initColor();
81
+ },
82
+ methods: {
83
+ async fetchOrgaAttributes(): Promise<void>{
84
+ if(""!==this.authOrganisation.id && this.authOrganisation.attributes && Object.keys(this.authOrganisation.attributes).length > 1){
85
+ this.orgaAttributes = this.authOrganisation.attributes;
86
+ }else{
87
+ this.orgaAttributes= await octopusApi.fetchData<{[key:string]:string}>(0, 'organisation/attributes/'+this.myOrganisationId);
88
+ }
89
+ },
90
+ initColor(): void {
91
+ if(!this.orgaAttributes){return;}
92
+ this.color = Object.prototype.hasOwnProperty.call(this.orgaAttributes,'COLOR') ? (this.orgaAttributes.COLOR as string) : '#40a372';
93
+ this.theme = Object.prototype.hasOwnProperty.call(this.orgaAttributes,'THEME') ? (this.orgaAttributes.THEME as string) : '#000000';
94
+ },
95
+ },
96
+ })
97
+ </script>
98
+
99
+ <style lang="scss">
100
+ @import '@scss/_variables.scss';
101
+ @import '../../../assets/iframe.scss';
102
+ </style>
@@ -78,7 +78,7 @@ export default defineComponent({
78
78
  routerLinkArray(){
79
79
  return [
80
80
  {title : this.$t('Home'), routeName: 'home', condition : true},
81
- {title : this.$t('Live'), routeName: 'lives', condition : state.generalParameters.isLiveTab &&((this.filterOrgaId && this.filterLive) || !this.filterOrgaId)},
81
+ {title : this.$t('Radio & Live'), routeName: 'lives', condition : state.generalParameters.isLiveTab &&((this.filterOrgaId && this.filterLive) || !this.filterOrgaId)},
82
82
  {title : this.$t('Podcasts'), routeName: 'podcasts', condition : true},
83
83
  {title : this.$t('Emissions'), routeName: 'emissions', condition : true},
84
84
  {title : this.$t('Productors'), routeName: 'productors', condition : !this.isPodcastmaker && (!this.filterOrgaId || this.isEducation)},
@@ -13,10 +13,12 @@
13
13
  />
14
14
  <template v-if="playerMedia">
15
15
  <div
16
+ v-if="mediaCueInPercent > 0"
16
17
  class="octopus-progress-bar bg-complementary"
17
18
  :style="{'width': + mediaCueInPercent + '%'}"
18
19
  />
19
20
  <div
21
+ v-if="mediaCueOutPercent < 100"
20
22
  class="octopus-progress-bar end-0 bg-complementary"
21
23
  :style="{'width': + 100- mediaCueOutPercent + '%'}"
22
24
  />
@@ -31,10 +33,12 @@
31
33
  />
32
34
  <template v-if="playerMedia">
33
35
  <div
36
+ v-if="mediaCueInPercent > 0"
34
37
  class="octopus-progress-bar octopus-progress-bar-duration bg-complementary"
35
38
  :style="{'left': + mediaCueInPercent + '%'}"
36
39
  />
37
40
  <div
41
+ v-if="mediaCueOutPercent < 100"
38
42
  class="octopus-progress-bar end-0 octopus-progress-bar-duration bg-complementary"
39
43
  :style="{'right': + 100- mediaCueOutPercent + '%'}"
40
44
  />
@@ -138,7 +138,7 @@ export default defineComponent({
138
138
  ...mapState(useFilterStore, ['filterLive', 'filterOrgaId', 'filterImgUrl', 'filterIab', 'filterRubrique', 'filterName']),
139
139
  routerLinkArray(){
140
140
  return [
141
- {title : this.$t('Live'), routeName: 'lives', condition : (state.generalParameters.isLiveTab as boolean) &&((this.filterOrgaId && this.filterLive) || !this.filterOrgaId)},
141
+ {title : this.$t('Radio & Live'), routeName: 'lives', condition : (state.generalParameters.isLiveTab as boolean) &&((this.filterOrgaId && this.filterLive) || !this.filterOrgaId)},
142
142
  {title : this.$t('Podcasts'), routeName: 'podcasts', condition : true},
143
143
  {title : this.$t('Emissions'), routeName: 'emissions', condition : true}
144
144
  ]
@@ -27,8 +27,8 @@
27
27
  <template
28
28
  #tab1
29
29
  >
30
- <div class="d-flex flex-column">
31
- <div class="d-flex">
30
+ <div class="d-flex flex-column flex-grow-1">
31
+ <div class="d-flex justify-content-between align-items-center">
32
32
  <p>{{ embedlyLink }}</p>
33
33
  <div
34
34
  class="saooti-copy"
@@ -143,6 +143,7 @@ export default defineComponent({
143
143
  border-radius: $octopus-borderradius;
144
144
  height: 2.4rem;
145
145
  width: 2.4rem;
146
+ margin-right: 0.5rem;
146
147
  cursor: pointer;
147
148
  /** PHONES*/
148
149
  @media (max-width: 450px) {
@@ -1,15 +1,19 @@
1
1
  import { state } from '../../../stores/ParamSdkStore';
2
2
  import { defineComponent } from 'vue';
3
3
  import { RouteLocationRaw } from 'vue-router';
4
- import { MetadataRadio } from '@/stores/class/general/player';
4
+ import {fetchRadioData} from '../../mixins/radio/fetchRadioData';
5
+ import { MediaRadio, MetadataRadio } from '@/stores/class/general/player';
5
6
  import { usePlayerStore } from '@/stores/PlayerStore';
6
7
  import { useFilterStore } from '@/stores/FilterStore';
7
8
  import { mapState, mapActions } from 'pinia';
8
9
  import octopusApi from '@saooti/octopus-api';
10
+ import dayjs from 'dayjs';
11
+ import { Podcast } from '@/stores/class/general/podcast';
9
12
  export const playerDisplay = defineComponent({
10
13
  props: {
11
14
  hlsReady: { default: false , type: Boolean},
12
15
  },
16
+ mixins: [fetchRadioData],
13
17
  data() {
14
18
  return {
15
19
  radioInterval: undefined as ReturnType<typeof setTimeout>|undefined,
@@ -35,6 +39,13 @@ export const playerDisplay = defineComponent({
35
39
  return (state.player.image as boolean);
36
40
  },
37
41
  podcastShareUrl(): RouteLocationRaw|string {
42
+ if(this.playerRadio?.podcast?.podcastId){
43
+ return {
44
+ name: 'podcast',
45
+ params: { podcastId: this.playerRadio?.podcast?.podcastId.toString() },
46
+ query: { productor: this.filterOrgaId },
47
+ };
48
+ }
38
49
  if (this.playerPodcast) {
39
50
  return {
40
51
  name: 'podcast',
@@ -49,7 +60,10 @@ export const playerDisplay = defineComponent({
49
60
  },
50
61
  podcastTitle(): string {
51
62
  if(this.playerRadio){
52
- return this.playerRadio.metadata.title + " " + this.playerRadio.metadata.artist;
63
+ if(this.playerRadio.podcast){
64
+ return this.playerRadio.podcast.title;
65
+ }
66
+ return this.displayTitle(this.playerRadio.metadata);
53
67
  }
54
68
  if (this.playerPodcast) {
55
69
  if (this.isEmissionName)
@@ -69,12 +83,13 @@ export const playerDisplay = defineComponent({
69
83
  playerRadio: {
70
84
  deep: true,
71
85
  immediate:true,
72
- handler(){
86
+ handler(newValue,oldValue){
87
+ if(oldValue && newValue && newValue.canalId === oldValue.canalId){return;}
73
88
  clearInterval((this.radioInterval as unknown as number));
74
89
  if(this.playerRadio){
75
- this.fetchRadioMetadata();
90
+ this.fetchCurrentlyPlaying();
76
91
  this.radioInterval = setInterval(() => {
77
- this.fetchRadioMetadata();
92
+ this.fetchCurrentlyPlaying();
78
93
  }, 2000);
79
94
  }
80
95
  }
@@ -85,13 +100,15 @@ export const playerDisplay = defineComponent({
85
100
  },
86
101
  beforeUnmount() {
87
102
  window.removeEventListener('keydown', this.addKeyboardControl);
88
- clearInterval((this.radioInterval as unknown as number));
89
103
  },
90
104
  methods: {
91
- ...mapActions(usePlayerStore, ['playerMetadata', 'playerChangeStatus']),
92
- async fetchRadioMetadata(): Promise<void>{
93
- const metadata = await octopusApi.fetchData<MetadataRadio>(14, 'player/playing/'+this.playerRadio?.canalId);
94
- this.playerMetadata(metadata.currently);
105
+ ...mapActions(usePlayerStore, ['playerMetadata', 'playerChangeStatus', 'playerRadioPodcast']),
106
+ async fetchCurrentlyPlaying(): Promise<void>{
107
+ this.fetchRadioMetadata(this.playerRadio?.canalId??0,this.playerRadio?.metadata.title??"", this.updateMetadata);
108
+ },
109
+ updateMetadata(metadata: MediaRadio, podcast?:Podcast): void{
110
+ this.playerMetadata(metadata);
111
+ this.playerRadioPodcast(podcast);
95
112
  },
96
113
  addKeyboardControl(event: KeyboardEvent): void{
97
114
  if(!event || null ===event){return;}
@@ -0,0 +1,47 @@
1
+ import { defineComponent } from 'vue';
2
+ import { MediaRadio, MetadataRadio } from '@/stores/class/general/player';
3
+ import octopusApi from '@saooti/octopus-api';
4
+ import dayjs from 'dayjs';
5
+ import { Podcast } from '@/stores/class/general/podcast';
6
+ export const fetchRadioData = defineComponent({
7
+ data() {
8
+ return {
9
+ radioInterval: undefined as ReturnType<typeof setTimeout>|undefined,
10
+ };
11
+ },
12
+ unmounted() {
13
+ clearInterval((this.radioInterval as unknown as number));
14
+ },
15
+ methods: {
16
+ async fetchRadioMetadata(canalId: number, previousTitle: string, callbackMetadata: (metadata: MediaRadio, podcast?:Podcast) => void): Promise<void>{
17
+ const metadata = await octopusApi.fetchData<MetadataRadio>(14, 'player/playing/'+canalId);
18
+ const arrayMetadata = metadata.previously;
19
+ arrayMetadata.unshift(metadata.currently);
20
+ for(let i = 0; i < arrayMetadata.length; i++){
21
+ if(dayjs().valueOf()-29000 > dayjs(arrayMetadata[i].startDate).valueOf()){
22
+ if(previousTitle !== arrayMetadata[i].title){
23
+ //todo
24
+ arrayMetadata[i].podcastId = 98619;
25
+ if(arrayMetadata[i].podcastId){
26
+ const data : Podcast = await octopusApi.fetchData<Podcast>(0, 'podcast/'+arrayMetadata[i].podcastId);
27
+ callbackMetadata(arrayMetadata[i], data);
28
+ }else{
29
+ callbackMetadata(arrayMetadata[i]);
30
+ }
31
+ }
32
+ return;
33
+ }
34
+ }
35
+ },
36
+ displayTitle(metadata: MediaRadio): string{
37
+ let title = "";
38
+ if(metadata.title){
39
+ title+=metadata.title;
40
+ }
41
+ if(metadata.artist){
42
+ title+=" - "+metadata.artist;
43
+ }
44
+ return title;
45
+ }
46
+ }
47
+ });