@saooti/octopus-sdk 41.1.9 → 41.1.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.
- package/CHANGELOG.md +19 -0
- package/index.ts +1 -3
- package/package.json +1 -1
- package/src/api/podcastApi.ts +1 -1
- package/src/components/composable/player/usePlayerLive.ts +39 -16
- package/src/components/composable/player/usePlayerLogic.ts +7 -3
- package/src/components/display/podcasts/PodcastPresentationList.vue +23 -17
- package/src/components/pages/EmissionPage.vue +4 -2
- package/src/components/pages/PodcastPage.vue +3 -1
- package/src/stores/PlayerStore.ts +9 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 41.1.11 (16/12/2025)
|
|
4
|
+
|
|
5
|
+
**Misc**
|
|
6
|
+
|
|
7
|
+
- Export de `ClassicWysiwyg`
|
|
8
|
+
|
|
9
|
+
## 41.1.10 (15/12/2025)
|
|
10
|
+
|
|
11
|
+
**Misc**
|
|
12
|
+
|
|
13
|
+
- Les pages d'émissions et d'épisodes peuvent afficher le titre de l'émission
|
|
14
|
+
en header
|
|
15
|
+
- Ajustement pour assurer l'affichage d'épisodes d'émissions différentes dans
|
|
16
|
+
`PodcastPresentationList`.
|
|
17
|
+
|
|
18
|
+
**Fixes**
|
|
19
|
+
|
|
20
|
+
- Correction d'un problème de lecture des lives sous Firefox
|
|
21
|
+
|
|
3
22
|
## 41.1.9 (11/12/2025)
|
|
4
23
|
|
|
5
24
|
**Fixes**
|
package/index.ts
CHANGED
|
@@ -40,8 +40,6 @@ export const getContractPreviewModal = () => import("./src/components/misc/modal
|
|
|
40
40
|
export const getClassicModalInBody = () => import("./src/components/misc/modal/ClassicModalInBody.vue");
|
|
41
41
|
export const getClassicHelpButton = () => import("./src/components/misc/ClassicHelpButton.vue");
|
|
42
42
|
export const getClassicAlert = () => import("./src/components/misc/ClassicAlert.vue");
|
|
43
|
-
|
|
44
|
-
|
|
45
43
|
//Display
|
|
46
44
|
export const getCategoryChooser = () => import("./src/components/display/categories/CategoryChooser.vue");
|
|
47
45
|
export const getCategoryList = () => import("./src/components/display/categories/CategoryList.vue");
|
|
@@ -99,7 +97,7 @@ export const getClassicContentEditable = () => import("./src/components/form/Cla
|
|
|
99
97
|
export const getSwiperList = () => import("./src/components/display/list/SwiperList.vue");
|
|
100
98
|
export const getClassicCopyButton = () => import("./src/components/form/ClassicCopyButton.vue");
|
|
101
99
|
export const getClassicTagInput = () => import("./src/components/form/ClassicTagInput.vue");
|
|
102
|
-
|
|
100
|
+
export const getClassicWysiwyg = () => import("./src/components/form/ClassicWysiwyg.vue");
|
|
103
101
|
|
|
104
102
|
//Composable
|
|
105
103
|
import {useResizePhone} from "./src/components/composable/useResizePhone";
|
package/package.json
CHANGED
package/src/api/podcastApi.ts
CHANGED
|
@@ -70,7 +70,7 @@ export interface PodcastSearchOptions extends Paginable<PodcastSort> {
|
|
|
70
70
|
/** Filter by podcast having a video */
|
|
71
71
|
withVideo?: boolean;
|
|
72
72
|
/** Filter by tags */
|
|
73
|
-
tags
|
|
73
|
+
tags?: Array<string>;
|
|
74
74
|
/** Filter by beneficiaries/rights holder reference */
|
|
75
75
|
beneficiaries?: Array<string>;
|
|
76
76
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import stringHelper from "../../../helper/stringHelper";
|
|
2
2
|
import { usePlayerLogicProgress } from "./usePlayerLogicProgress";
|
|
3
3
|
import { computed, Ref, ref } from "vue";
|
|
4
|
-
import { usePlayerStore } from "../../../stores/PlayerStore";
|
|
4
|
+
import { usePlayerStore, PlayerStatus } from "../../../stores/PlayerStore";
|
|
5
5
|
import { useApiStore } from "../../../stores/ApiStore";
|
|
6
6
|
import dayjs from "dayjs";
|
|
7
7
|
import { useAuthStore } from "../../../stores/AuthStore";
|
|
@@ -28,11 +28,8 @@ export const usePlayerLive = (hlsReady: Ref<boolean>)=>{
|
|
|
28
28
|
return authStore.authParam.accessToken && ("SECURED" === playerStore.playerLive?.organisation?.privacy || playerStore.playerRadio?.secured);
|
|
29
29
|
});
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
function onPlay(): void {
|
|
35
|
-
playerStore.playerChangeStatus("PAUSED"===playerStore.playerStatus);
|
|
31
|
+
function onPlay(): void {
|
|
32
|
+
playerStore.playerChangeStatus(PlayerStatus.PAUSED ===playerStore.playerStatus);
|
|
36
33
|
}
|
|
37
34
|
|
|
38
35
|
function playRadio() {
|
|
@@ -87,7 +84,8 @@ export const usePlayerLive = (hlsReady: Ref<boolean>)=>{
|
|
|
87
84
|
} else {
|
|
88
85
|
await initHls();
|
|
89
86
|
}
|
|
90
|
-
} catch {
|
|
87
|
+
} catch(e) {
|
|
88
|
+
console.error(e);
|
|
91
89
|
onHlsError();
|
|
92
90
|
}
|
|
93
91
|
}
|
|
@@ -112,6 +110,11 @@ export const usePlayerLive = (hlsReady: Ref<boolean>)=>{
|
|
|
112
110
|
throw new Error("Hls is not supported ! ");
|
|
113
111
|
}
|
|
114
112
|
hls.value = new Hls({
|
|
113
|
+
autoStartLoad: true,
|
|
114
|
+
liveDurationInfinity:true,
|
|
115
|
+
backBufferLength:10,
|
|
116
|
+
maxBufferLength:60,
|
|
117
|
+
|
|
115
118
|
xhrSetup: (xhr: XMLHttpRequest) => {
|
|
116
119
|
if (needToAddToken.value) {
|
|
117
120
|
xhr.setRequestHeader("Authorization", "Bearer " +authStore.authParam.accessToken);
|
|
@@ -124,16 +127,36 @@ export const usePlayerLive = (hlsReady: Ref<boolean>)=>{
|
|
|
124
127
|
if(true===errorHls.value){
|
|
125
128
|
return;
|
|
126
129
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
playPromise.value
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
130
|
+
setTimeout(() => {
|
|
131
|
+
playPromise.value = (audioElement.value as HTMLAudioElement).play();
|
|
132
|
+
playPromise.value.then(() =>{
|
|
133
|
+
playPromise.value = undefined;
|
|
134
|
+
onPlay();
|
|
135
|
+
}).catch((e)=>{
|
|
136
|
+
console.error(e);
|
|
137
|
+
onHlsError();
|
|
138
|
+
playPromise.value = undefined;
|
|
139
|
+
});
|
|
140
|
+
}, 500);
|
|
135
141
|
});
|
|
136
|
-
hls.value.on(Hls.Events.ERROR, async (
|
|
142
|
+
hls.value.on(Hls.Events.ERROR, async (name: string, data:any) => {
|
|
143
|
+
// Stalling, we don't have enough data
|
|
144
|
+
if (data.details === 'bufferStalledError') {
|
|
145
|
+
// Some logs to be able to follow what's happening
|
|
146
|
+
console.warn('playback is stalling…');
|
|
147
|
+
playerStore.playerStatus = PlayerStatus.LOADING;
|
|
148
|
+
// Destroy current instance
|
|
149
|
+
hls.value.destroy();
|
|
150
|
+
// Wait a bit before restarting playback
|
|
151
|
+
setTimeout(initHls, 500);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
console.error('An error occured: ' + name + ' / ' + data.details);
|
|
155
|
+
console.error(data);
|
|
156
|
+
if (data.fatal && data.type === Hls.ErrorTypes.MEDIA_ERROR) {
|
|
157
|
+
console.warn('Trying to recover...');
|
|
158
|
+
hls.value.recoverMediaError();
|
|
159
|
+
}
|
|
137
160
|
errorHls.value = true;
|
|
138
161
|
if(undefined===playPromise.value && data.fatal){
|
|
139
162
|
onHlsError();
|
|
@@ -186,8 +186,12 @@ export const usePlayerLogic = (forceHide: Ref<boolean, boolean>) => {
|
|
|
186
186
|
let streamDuration = mediaTarget.duration;
|
|
187
187
|
if (Infinity === streamDuration) {
|
|
188
188
|
const seekable = mediaTarget.seekable;
|
|
189
|
-
if (seekable) {
|
|
190
|
-
|
|
189
|
+
if (seekable && seekable.length > 0) {
|
|
190
|
+
try {
|
|
191
|
+
streamDuration = seekable.end(seekable.length - 1);
|
|
192
|
+
} catch (e) {
|
|
193
|
+
console.error(e);
|
|
194
|
+
}
|
|
191
195
|
} else {
|
|
192
196
|
streamDuration = mediaTarget.currentTime;
|
|
193
197
|
}
|
|
@@ -272,4 +276,4 @@ export const usePlayerLogic = (forceHide: Ref<boolean, boolean>) => {
|
|
|
272
276
|
onFinished,
|
|
273
277
|
onPlay
|
|
274
278
|
}
|
|
275
|
-
}
|
|
279
|
+
}
|
|
@@ -43,15 +43,15 @@ import { Emission } from "@/stores/class/general/emission";
|
|
|
43
43
|
import { onMounted, Ref, ref } from "vue";
|
|
44
44
|
import { AxiosError } from "axios";
|
|
45
45
|
import {useResizePhone} from "../../composable/useResizePhone";
|
|
46
|
-
import { ListClassicReturn } from "
|
|
46
|
+
import { ListClassicReturn } from "../../../stores/class/general/listReturn";
|
|
47
47
|
|
|
48
48
|
import PresentationLayout from "../../layout/PresentationLayout.vue";
|
|
49
|
-
import { Podcast } from "
|
|
50
|
-
import { ModuleApi } from "../../../api/apiConnection";
|
|
49
|
+
import { Podcast, SimplifiedPodcast, simplifiedToFull } from "../../../stores/class/general/podcast";
|
|
51
50
|
|
|
52
51
|
import PresentationItem from "../../layout/PresentationItem.vue";
|
|
53
52
|
import PodcastPlayButton from "./PodcastPlayButton.vue";
|
|
54
53
|
import { RouteLocationRaw } from "vue-router";
|
|
54
|
+
import { podcastApi, PodcastSort } from "../../../api/podcastApi";
|
|
55
55
|
|
|
56
56
|
//Props
|
|
57
57
|
const props = defineProps({
|
|
@@ -92,23 +92,29 @@ async function fetchNext(): Promise<void> {
|
|
|
92
92
|
specialTreatement: true,
|
|
93
93
|
});
|
|
94
94
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
parameters: {
|
|
95
|
+
const promises: Array<Promise<SimplifiedPodcast>> = [];
|
|
96
|
+
|
|
97
|
+
for (let i = 0; i < emissions.result.length; i++) {
|
|
98
|
+
promises.push(podcastApi.search({
|
|
100
99
|
first: 0,
|
|
101
|
-
|
|
102
|
-
organisationId: props.organisationId,
|
|
103
|
-
emissionId: emissions.result.
|
|
104
|
-
sort:
|
|
100
|
+
pageSize: 1,
|
|
101
|
+
organisationId: [props.organisationId],
|
|
102
|
+
emissionId: [emissions.result[i].emissionId],
|
|
103
|
+
sort: PodcastSort.DATE,
|
|
105
104
|
rubriqueId: props.rubriquesId
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
105
|
+
}).then(r => r.result[0]));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Retrieve the podcasts for these emissions
|
|
109
|
+
const data = await Promise.all(promises);
|
|
110
|
+
|
|
110
111
|
podcasts.value = podcasts.value.concat(
|
|
111
|
-
data.
|
|
112
|
+
data.filter((em: SimplifiedPodcast | null) => null !== em).map(p => {
|
|
113
|
+
// Get emission from podcast
|
|
114
|
+
const emission = emissions.result.find(e => e.emissionId === p.emissionId);
|
|
115
|
+
// Create full podcast from simplified + emission
|
|
116
|
+
return simplifiedToFull(p, emission.orga, emission);
|
|
117
|
+
})
|
|
112
118
|
);
|
|
113
119
|
loading.value = false;
|
|
114
120
|
} catch (errorWs) {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<template v-if="loaded && !error && emission">
|
|
4
4
|
<PodcastmakerHeader
|
|
5
5
|
v-if="isPodcastmaker"
|
|
6
|
-
:page-title="t('Emission')"
|
|
6
|
+
:page-title="useEmissionTitle ? emission.name : t('Emission')"
|
|
7
7
|
:img-url="emission.imageUrl"
|
|
8
8
|
/>
|
|
9
9
|
<div
|
|
@@ -178,7 +178,9 @@ const props = defineProps({
|
|
|
178
178
|
pr: { default: 0, type: Number },
|
|
179
179
|
ps: { default: 30, type: Number },
|
|
180
180
|
routeQuery: { default: "", type: String },
|
|
181
|
-
|
|
181
|
+
/** When true, display emission title in podcastmaker header */
|
|
182
|
+
useEmissionTitle: { default: false, type: Boolean }
|
|
183
|
+
});
|
|
182
184
|
|
|
183
185
|
|
|
184
186
|
//Data
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<template v-if="loaded && !error && podcast">
|
|
4
4
|
<PodcastmakerHeader
|
|
5
5
|
v-if="isPodcastmaker"
|
|
6
|
-
:page-title="titlePage"
|
|
6
|
+
:page-title="useEmissionTitle ? podcast.emission.name : titlePage"
|
|
7
7
|
:img-url="podcast.imageUrl"
|
|
8
8
|
/>
|
|
9
9
|
<div
|
|
@@ -114,6 +114,8 @@ const props = defineProps({
|
|
|
114
114
|
updateStatus: { default: undefined, type: String },
|
|
115
115
|
playingPodcast: { default: undefined, type: Object as () => Podcast },
|
|
116
116
|
podcastId: { default: 0, type: Number },
|
|
117
|
+
/** When true, display emission title in podcastmaker header */
|
|
118
|
+
useEmissionTitle: { default: false, type: Boolean }
|
|
117
119
|
});
|
|
118
120
|
|
|
119
121
|
|
|
@@ -14,9 +14,17 @@ interface Transcript {
|
|
|
14
14
|
actualText: string;
|
|
15
15
|
value: Array<{ endTime: number; startTime: number; text: string }>;
|
|
16
16
|
}
|
|
17
|
+
|
|
18
|
+
export enum PlayerStatus {
|
|
19
|
+
STOPPED = "STOPPED",
|
|
20
|
+
LOADING = "LOADING",
|
|
21
|
+
PLAYING = "PLAYING",
|
|
22
|
+
PAUSED = "PAUSED"
|
|
23
|
+
}
|
|
24
|
+
|
|
17
25
|
interface PlayerState {
|
|
18
26
|
playerCurrentChange: number | null;
|
|
19
|
-
playerStatus:
|
|
27
|
+
playerStatus: PlayerStatus;
|
|
20
28
|
playerPodcast: Podcast | undefined;
|
|
21
29
|
playerVolume?: number; //From 0 to 1
|
|
22
30
|
playerElapsed: number; //From 0 to 1
|