@saooti/octopus-sdk 30.0.43 → 30.0.47

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/README.md CHANGED
@@ -539,4 +539,8 @@ See [Configuration Reference](https://cli.vuejs.org/config/).
539
539
  * 30.0.39 Listes inline taille item
540
540
  * 30.0.41 Inline list arrow
541
541
  * 30.0.42 Resize rubriqueList
542
- * 30.0.43 Resize rubriqueList
542
+ * 30.0.43 Resize rubriqueList
543
+ * 30.0.44 ProgressBar pour le soir
544
+ * 30.0.45 ProgressBar pour le soir
545
+ * 30.0.46 Param pour le soir
546
+ * 30.0.47 Live error
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saooti/octopus-sdk",
3
- "version": "30.0.43",
3
+ "version": "30.0.47",
4
4
  "private": false,
5
5
  "description": "Javascript SDK for using octopus",
6
6
  "author": "Saooti",
@@ -53,29 +53,32 @@
53
53
  class="border-top emission-item-border-color p-2 secondary-bg d-flex"
54
54
  >
55
55
  <div class="d-flex justify-content-between flex-grow-1">
56
- <router-link
57
- :to="{
58
- name: 'podcast',
59
- params: { podcastId: p.podcastId },
60
- query: { productor: $store.state.filter.organisationId },
61
- }"
62
- class="d-flex flex-column define-width text-dark"
63
- >
64
- <div class="fw-bold text-truncate">
65
- {{ p.title }}
66
- </div>
67
- <div
68
- :id="'description-podcast-container-' + p.podcastId"
69
- class="emission-description html-wysiwyg-content"
56
+ <div class="d-flex flex-column">
57
+ <router-link
58
+ :to="{
59
+ name: 'podcast',
60
+ params: { podcastId: p.podcastId },
61
+ query: { productor: $store.state.filter.organisationId },
62
+ }"
63
+ class="d-flex flex-column define-width text-dark"
70
64
  >
71
- <!-- eslint-disable vue/no-v-html -->
65
+ <div class="fw-bold text-truncate">
66
+ {{ p.title }}
67
+ </div>
72
68
  <div
73
- :id="'description-podcast-' + p.podcastId"
74
- v-html="urlify(p.description)"
75
- />
76
- <!-- eslint-enable -->
77
- </div>
78
- </router-link>
69
+ :id="'description-podcast-container-' + p.podcastId"
70
+ class="emission-description html-wysiwyg-content"
71
+ >
72
+ <!-- eslint-disable vue/no-v-html -->
73
+ <div
74
+ :id="'description-podcast-' + p.podcastId"
75
+ v-html="urlify(p.description)"
76
+ />
77
+ <!-- eslint-enable -->
78
+ </div>
79
+ </router-link>
80
+ <PodcastPlayBar :podcast="p" />
81
+ </div>
79
82
  <div
80
83
  v-if="
81
84
  $store.state.player.podcast !== p ||
@@ -125,10 +128,15 @@ import octopusApi from '@saooti/octopus-api';
125
128
  import { Emission } from '@/store/class/general/emission';
126
129
  import { Podcast } from '@/store/class/general/podcast';
127
130
  import { state } from '../../../store/paramStore';
131
+ import PodcastPlayBar from '../podcasts/PodcastPlayBar.vue';
128
132
  import { displayMethods } from '../../mixins/functions';
129
133
  import { defineComponent } from 'vue'
130
134
  export default defineComponent({
131
135
  name: 'EmissionPlayerItem',
136
+
137
+ components:{
138
+ PodcastPlayBar
139
+ },
132
140
  mixins: [displayMethods],
133
141
  props: {
134
142
  emission: { default: ()=>({}), type: Object as ()=>Emission },
@@ -238,6 +246,17 @@ export default defineComponent({
238
246
  height: min-content;
239
247
  border-radius: 0.8rem;
240
248
  overflow: hidden;
249
+ .progress{
250
+ height: 6px;
251
+ }
252
+ .progress-bar-cursor{
253
+ width: 10px;
254
+ height: 10px;
255
+ border-radius: 50%;
256
+ background: black;
257
+ align-self: center;
258
+ position: absolute;
259
+ }
241
260
  .emission-item-border-color {
242
261
  border-color: #ddd;
243
262
  }
@@ -106,6 +106,7 @@ export default defineComponent({
106
106
  rubriqueId: { default: () => [], type: Array as ()=> Array<number> },
107
107
  rubriquageId:{ default: () => [], type: Array as ()=> Array<number> },
108
108
  noRubriquageId: { default: () => [], type: Array as ()=> Array<number> },
109
+ query: { default: undefined, type: String},
109
110
  },
110
111
  emits: ['update:isArrow'],
111
112
 
@@ -170,7 +171,7 @@ export default defineComponent({
170
171
  return this.direction > 0 ? 'out-left' : 'out-right';
171
172
  },
172
173
  watchVariable():string{
173
- return `${this.emissionId}|${this.organisationId}|${this.filterOrga}|${this.iabId}|${this.rubriqueId}|${this.rubriquageId}`;
174
+ return `${this.emissionId}|${this.organisationId}|${this.filterOrga}|${this.iabId}|${this.rubriqueId}|${this.rubriquageId}|${this.query}`;
174
175
  }
175
176
  },
176
177
  watch: {
@@ -210,6 +211,7 @@ export default defineComponent({
210
211
  rubriquageId: this.rubriquageId.length ?this.rubriquageId : undefined,
211
212
  noRubriquageId: this.noRubriquageId.length ? this.noRubriquageId : undefined,
212
213
  sort: this.popularSort ? 'POPULARITY' : 'DATE',
214
+ query: this.query,
213
215
  });
214
216
  this.loading = false;
215
217
  this.loaded = true;
@@ -60,6 +60,10 @@
60
60
  {{ title }}
61
61
  </div>
62
62
  </router-link>
63
+ <PodcastPlayBar
64
+ :podcast="podcast"
65
+ class="mx-2"
66
+ />
63
67
  <div class="d-flex justify-content-between">
64
68
  <router-link
65
69
  v-if="!isPodcastmaker"
@@ -88,7 +92,7 @@ import { state } from '../../../store/paramStore';
88
92
  import moment from 'moment';
89
93
  // @ts-ignore
90
94
  import humanizeDuration from 'humanize-duration';
91
-
95
+ import PodcastPlayBar from '../podcasts/PodcastPlayBar.vue';
92
96
  import { Podcast } from '@/store/class/general/podcast';
93
97
  import { Category } from '@/store/class/general/category';
94
98
  import { defineComponent } from 'vue'
@@ -98,6 +102,7 @@ export default defineComponent({
98
102
  components: {
99
103
  AnimatorsItem,
100
104
  PodcastImage,
105
+ PodcastPlayBar
101
106
  },
102
107
 
103
108
  props: {
@@ -116,6 +116,9 @@
116
116
  :participants="podcast.guests"
117
117
  :is-guest="true"
118
118
  />
119
+ <PodcastPlayBar
120
+ :podcast="podcast"
121
+ />
119
122
  <div v-if="editRight && !isPodcastmaker">
120
123
  <div
121
124
  v-if="podcast.annotations && podcast.annotations.RSS"
@@ -152,6 +155,7 @@
152
155
  </template>
153
156
 
154
157
  <script lang="ts">
158
+ import PodcastPlayBar from './PodcastPlayBar.vue';
155
159
  import PodcastImage from './PodcastImage.vue';
156
160
  import ParticipantDescription from './ParticipantDescription.vue';
157
161
  import TagList from './TagList.vue';
@@ -174,6 +178,7 @@ export default defineComponent({
174
178
  ShareButtons,
175
179
  TagList,
176
180
  ErrorMessage,
181
+ PodcastPlayBar
177
182
  },
178
183
 
179
184
  mixins:[displayMethods],
@@ -0,0 +1,100 @@
1
+ <template>
2
+ <div
3
+ v-if="isProgressBar"
4
+ class="d-flex align-items-center podcast-play-bar"
5
+ >
6
+ <div class="me-2">
7
+ {{ playedTime }}
8
+ </div>
9
+ <div class="position-relative flex-grow-1">
10
+ <div
11
+ class="progress flex-grow-1 c-hand"
12
+ @mouseup="seekTo"
13
+ >
14
+ <div
15
+ class="progress-bar primary-bg"
16
+ role="progressbar"
17
+ aria-valuenow="0"
18
+ aria-valuemin="0"
19
+ aria-valuemax="100"
20
+ :style="'width: ' + percentProgress + '%'"
21
+ />
22
+ <div
23
+ class="progress-bar-cursor"
24
+ :style="'left:' + percentProgress + '%'"
25
+ />
26
+ </div>
27
+ </div>
28
+ <div class="ms-2">
29
+ {{ totalTime }}
30
+ </div>
31
+ </div>
32
+ </template>
33
+
34
+ <script lang="ts">
35
+ import { Podcast } from '@/store/class/general/podcast';
36
+ import DurationHelper from '../../../helper/duration';
37
+ import { displayMethods } from '../../mixins/functions';
38
+ import { state } from '../../../store/paramStore';
39
+ import { defineComponent } from 'vue'
40
+ export default defineComponent({
41
+ name: 'PodcastPlayBar',
42
+ mixins: [displayMethods],
43
+ props: {
44
+ podcast: { default: ()=>({}), type: Object as ()=>Podcast },
45
+ },
46
+ computed: {
47
+ isProgressBar(): boolean{
48
+ return (state.emissionsPage.progressBar as boolean);
49
+ },
50
+ percentProgress(): number{
51
+ if(this.podcast !== this.$store.state.player.podcast){
52
+ return 0;
53
+ }
54
+ if(!this.$store.state.player.elapsed){return 0;}
55
+ return this.$store.state.player.elapsed * 100;
56
+ },
57
+ playedTime(): string{
58
+ if(this.podcast === this.$store.state.player.podcast){
59
+ if (this.$store.state.player.elapsed && this.$store.state.player.elapsed > 0 && this.$store.state.player.total && this.$store.state.player.total > 0) {
60
+ return DurationHelper.formatDuration(
61
+ Math.round(this.$store.state.player.elapsed * this.$store.state.player.total)
62
+ );
63
+ }
64
+ }
65
+ return '00:00';
66
+ },
67
+ totalTime(): string {
68
+ return DurationHelper.formatDuration(Math.round(this.podcast.duration/1000));
69
+ },
70
+ },
71
+ methods: {
72
+ seekTo(event: MouseEvent): void {
73
+ if(this.podcast!== this.$store.state.player.podcast){return;}
74
+ const rect = (event.currentTarget as Element).getBoundingClientRect();
75
+ const barWidth = (event.currentTarget as Element).clientWidth;
76
+ const x = event.clientX - rect.left;
77
+ const percentPosition = x / barWidth;
78
+ if (percentPosition * 100 >= this.percentLiveProgress) return;
79
+ const seekTime = this.$store.state.player.total * percentPosition;
80
+ this.$store.commit("playerSeekTime", seekTime);
81
+ }
82
+ },
83
+ })
84
+ </script>
85
+
86
+ <style lang="scss">
87
+ .podcast-play-bar {
88
+ .progress{
89
+ height: 6px;
90
+ }
91
+ .progress-bar-cursor{
92
+ width: 10px;
93
+ height: 10px;
94
+ border-radius: 50%;
95
+ background: black;
96
+ align-self: center;
97
+ position: absolute;
98
+ }
99
+ }
100
+ </style>
@@ -28,7 +28,6 @@
28
28
  class="d-flex align-items-center flex-grow-1 px-5"
29
29
  >
30
30
  <audio
31
- v-if="!live"
32
31
  id="audio-player"
33
32
  :src="!live? audioUrl: undefined"
34
33
  autoplay
@@ -123,6 +122,7 @@ export default defineComponent({
123
122
  if(!state.player.elapsed){return 0;}
124
123
  return state.player.elapsed * 100;
125
124
  },
125
+ playerSeekTime: (state: StoreState) => state.player.seekTime,
126
126
  }),
127
127
  audioUrl(): string {
128
128
  if (this.media) return this.media.audioUrl? this.media.audioUrl:"";
@@ -150,6 +150,15 @@ export default defineComponent({
150
150
  },
151
151
 
152
152
  watch: {
153
+ playerSeekTime(){
154
+ if(!this.playerSeekTime){return;}
155
+ if (this.$store.state.player.podcast || this.$store.state.player.live) {
156
+ this.notListenTime = this.playerSeekTime - this.listenTime;
157
+ }
158
+ const audioPlayer: HTMLAudioElement | null = document.querySelector('#audio-player');
159
+ if (!audioPlayer) return;
160
+ audioPlayer.currentTime = this.playerSeekTime;
161
+ },
153
162
  live: {
154
163
  deep: true,
155
164
  async handler(){
@@ -184,6 +193,9 @@ export default defineComponent({
184
193
  commentsLoaded(): void {
185
194
  this.initComments(true);
186
195
  },
196
+ audioUrl(): void{
197
+ this.playerError = false;
198
+ }
187
199
  },
188
200
 
189
201
  mounted() {
@@ -332,47 +344,49 @@ export default defineComponent({
332
344
  this.listenTime = 0;
333
345
  },
334
346
  async initHls(hlsStreamUrl: string): Promise<void> {
335
- if(null === Hls){
336
- //TODO -> Version light min quand ce sera possible
337
- await import('hls.js/dist/hls.js').then((hlsLibrary) => {
338
- Hls = hlsLibrary.default;
339
- })
340
- await import('hls.js').then((hlsLibrary) => {
341
- Hls = hlsLibrary.default;
342
- })
343
- }
344
- if (!Hls.isSupported()) {
345
- throw 'Hls is not supported ! ';
346
- }
347
- const hls = new Hls();
348
- hls.on(Hls.Events.MANIFEST_PARSED, async () => {
349
- if(!this.live){ return; }
350
- let downloadId = null;
351
- try {
352
- downloadId = await octopusApi.requestLiveDownloadId(
353
- this.live.livePodcastId
354
- );
355
- await octopusApi.markPlayingLive(
356
- this.live.livePodcastId,
357
- downloadId,
358
- 'octopus',
359
- this.$store.state.authentication.organisationId
360
- );
361
- this.setDownloadId(downloadId);
362
- } catch (error) {
363
- console.log('ERROR downloadId');
347
+ return new Promise<void>(async(resolve, reject) => {
348
+ if(null === Hls){
349
+ //TODO -> Version light min quand ce sera possible
350
+ await import('hls.js/dist/hls.js').then((hlsLibrary) => {
351
+ Hls = hlsLibrary.default;
352
+ })
353
+ await import('hls.js').then((hlsLibrary) => {
354
+ Hls = hlsLibrary.default;
355
+ })
364
356
  }
365
- this.hlsReady = true;
366
- const audio: HTMLElement|null = document.getElementById('audio-player');
367
- hls.attachMedia((audio as HTMLAudioElement));
368
- await (audio as HTMLAudioElement).play();
369
- this.onPlay();
370
- throw 400;
371
- });
372
- hls.on(Hls.Events.ERROR, async () => {
373
- throw 'There is an error while reading media content';
357
+ if (!Hls.isSupported()) {
358
+ reject('Hls is not supported ! ');
359
+ }
360
+ const hls = new Hls();
361
+ hls.on(Hls.Events.MANIFEST_PARSED, async () => {
362
+ if(!this.live){ return; }
363
+ let downloadId = null;
364
+ try {
365
+ downloadId = await octopusApi.requestLiveDownloadId(
366
+ this.live.livePodcastId
367
+ );
368
+ await octopusApi.markPlayingLive(
369
+ this.live.livePodcastId,
370
+ downloadId,
371
+ 'octopus',
372
+ this.$store.state.authentication.organisationId
373
+ );
374
+ this.setDownloadId(downloadId);
375
+ } catch (error) {
376
+ console.log('ERROR downloadId');
377
+ }
378
+ this.hlsReady = true;
379
+ const audio: HTMLElement|null = document.getElementById('audio-player');
380
+ hls.attachMedia((audio as HTMLAudioElement));
381
+ await (audio as HTMLAudioElement).play();
382
+ this.onPlay();
383
+ resolve();
384
+ });
385
+ hls.on(Hls.Events.ERROR, async() => {
386
+ reject('There is an error while reading media content');
387
+ });
388
+ hls.loadSource(hlsStreamUrl);
374
389
  });
375
- hls.loadSource(hlsStreamUrl);
376
390
  },
377
391
  async playLive(): Promise<void> {
378
392
  if (!this.live) return;
@@ -19,6 +19,7 @@
19
19
  :class="{
20
20
  'saooti-play2-bounty': isPaused,
21
21
  'saooti-pause-bounty': isPlaying,
22
+ 'spinner-border':!isPaused&&!isPlaying
22
23
  }"
23
24
  />
24
25
  </div>
@@ -70,25 +70,27 @@
70
70
  :emission-id="emissionId"
71
71
  />
72
72
  </div>
73
- <LiveHorizontalList
74
- v-if="!isPodcastmaker"
75
- :emission-id="emissionId"
76
- />
77
- <PodcastFilterList
78
- v-if="!isOuestFrance"
79
- :emission-id="emissionId"
80
- :category-filter="false"
81
- :edit-right="editRight"
82
- :productor-id="emission.orga.id"
83
- @fetch="fetch"
84
- />
85
- <PodcastList
86
- v-else
87
- :first="0"
88
- :size="15"
89
- :emission-id="emissionId"
90
- @fetch="fetch"
91
- />
73
+ <template v-if="isDisplayPodcasts">
74
+ <LiveHorizontalList
75
+ v-if="!isPodcastmaker"
76
+ :emission-id="emissionId"
77
+ />
78
+ <PodcastFilterList
79
+ v-if="!isOuestFrance"
80
+ :emission-id="emissionId"
81
+ :category-filter="false"
82
+ :edit-right="editRight"
83
+ :productor-id="emission.orga.id"
84
+ @fetch="fetch"
85
+ />
86
+ <PodcastList
87
+ v-else
88
+ :first="0"
89
+ :size="15"
90
+ :emission-id="emissionId"
91
+ @fetch="fetch"
92
+ />
93
+ </template>
92
94
  </div>
93
95
  <ClassicLoading
94
96
  :loading-text="!loaded?$t('Loading content ...'):undefined"
@@ -172,6 +174,9 @@ export default defineComponent({
172
174
  isRssButton(): boolean {
173
175
  return (state.emissionPage.rssButton as boolean);
174
176
  },
177
+ isDisplayPodcasts(): boolean {
178
+ return (state.emissionPage.isDisplayPodcasts as boolean);
179
+ },
175
180
  isPodcastmaker(): boolean {
176
181
  return (state.generalParameters.podcastmaker as boolean);
177
182
  },
@@ -77,6 +77,9 @@ export default createStore({
77
77
  playerVolume(state, volume) {
78
78
  state.player.volume = volume;
79
79
  },
80
+ playerSeekTime(state, seekTime) {
81
+ state.player.seekTime = seekTime;
82
+ },
80
83
 
81
84
  filterOrga(state, filter) {
82
85
  state.filter.organisationId = filter.orgaId;
@@ -10,4 +10,5 @@ export interface Player{
10
10
  media: Media|undefined;
11
11
  live: Podcast|undefined;
12
12
  stop?: boolean;
13
+ seekTime?: number;
13
14
  }
@@ -50,10 +50,12 @@ const state:paramStore = {
50
50
  buttonMore: false,
51
51
  overflowScroll: false,
52
52
  titleInImage: false,
53
+ progressBar:false
53
54
  },
54
55
  emissionPage: {
55
56
  ouestFranceStyle: false,
56
57
  rssButton: false,
58
+ isDisplayPodcasts:true
57
59
  },
58
60
  intervenantPage: {
59
61
  lightStyle: false,
@@ -136,10 +138,12 @@ export interface EmissionsPage{
136
138
  buttonMore?: boolean,
137
139
  overflowScroll?: boolean,
138
140
  titleInImage?: boolean,
141
+ progressBar?:boolean
139
142
  }
140
143
  export interface EmissionPage{
141
144
  ouestFranceStyle?: boolean,
142
145
  rssButton?: boolean,
146
+ isDisplayPodcasts?:boolean
143
147
  }
144
148
  export interface IntervenantPage{
145
149
  lightStyle?: boolean,
@@ -199,6 +199,7 @@ export function emptyPodcastData(): Podcast{
199
199
  total: 0,
200
200
  media: undefined ,
201
201
  live: undefined ,
202
+ seekTime:0,
202
203
  },
203
204
 
204
205
  navigator: {