@saooti/octopus-sdk 31.0.18 → 31.0.21
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 +3 -0
- package/index.ts +1 -1
- package/package.json +1 -1
- package/src/assets/general.scss +3 -0
- package/src/components/misc/Footer.vue +2 -5
- package/src/components/misc/player/Player.vue +145 -0
- package/src/components/misc/player/PlayerCompact.vue +149 -0
- package/src/components/misc/player/PlayerLarge.vue +161 -0
- package/src/components/misc/player/PlayerProgressBar.vue +112 -0
- package/src/components/misc/{PlayerClockAndTimeline.vue → player/PlayerTimeline.vue} +3 -24
- package/src/components/mixins/player/playerComment.ts +97 -0
- package/src/components/mixins/player/playerDisplay.ts +113 -0
- package/src/components/mixins/player/playerLive.ts +113 -0
- package/src/components/mixins/player/playerLogic.ts +234 -0
- package/src/locale/de.ts +2 -0
- package/src/locale/en.ts +2 -0
- package/src/locale/es.ts +2 -0
- package/src/locale/fr.ts +2 -0
- package/src/locale/it.ts +2 -0
- package/src/locale/sl.ts +2 -0
- package/src/store/paramStore.ts +1 -5
- package/src/components/misc/Player.vue +0 -514
- package/src/components/misc/PlayerButtons.vue +0 -143
- package/src/components/misc/PlayerProgressBar.vue +0 -176
package/README.md
CHANGED
package/index.ts
CHANGED
|
@@ -15,7 +15,7 @@ import Rubrique from "./src/components/pages/Rubrique.vue";
|
|
|
15
15
|
//Misc
|
|
16
16
|
import Footer from "./src/components/misc/Footer.vue";
|
|
17
17
|
import LeftMenu from "./src/components/misc/LeftMenu.vue";
|
|
18
|
-
import Player from "./src/components/misc/Player.vue";
|
|
18
|
+
import Player from "./src/components/misc/player/Player.vue";
|
|
19
19
|
import Snackbar from "./src/components/misc/Snackbar.vue";
|
|
20
20
|
import TopBar from "./src/components/misc/TopBar.vue";
|
|
21
21
|
import HomeDropdown from "./src/components/misc/HomeDropdown.vue";
|
package/package.json
CHANGED
package/src/assets/general.scss
CHANGED
|
@@ -144,7 +144,7 @@
|
|
|
144
144
|
<script lang="ts">
|
|
145
145
|
import { cookies } from '../mixins/functions';
|
|
146
146
|
import ClassicSelect from '../form/ClassicSelect.vue';
|
|
147
|
-
import Player from './Player.vue';
|
|
147
|
+
import Player from './player/Player.vue';
|
|
148
148
|
import { state } from '../../store/paramStore';
|
|
149
149
|
import {loadLocaleMessages} from '@/i18n';
|
|
150
150
|
import octopusApi from '@saooti/octopus-api';
|
|
@@ -172,9 +172,6 @@ export default defineComponent({
|
|
|
172
172
|
isPodcastmaker(): boolean {
|
|
173
173
|
return (state.generalParameters.podcastmaker as boolean);
|
|
174
174
|
},
|
|
175
|
-
isBarTop(): boolean {
|
|
176
|
-
return (state.player.barTop as boolean);
|
|
177
|
-
},
|
|
178
175
|
isContactLink(): string|undefined {
|
|
179
176
|
return state.footer.contactLink;
|
|
180
177
|
},
|
|
@@ -198,7 +195,7 @@ export default defineComponent({
|
|
|
198
195
|
if(null===footerElement){return}
|
|
199
196
|
if (hide) {
|
|
200
197
|
footerElement.classList.remove('border-round');
|
|
201
|
-
} else
|
|
198
|
+
} else {
|
|
202
199
|
footerElement.className += ' border-round';
|
|
203
200
|
}
|
|
204
201
|
},
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
class="w-100 transition-height bg-dark"
|
|
4
|
+
:style="{ height: playerHeight }"
|
|
5
|
+
>
|
|
6
|
+
<div
|
|
7
|
+
class="player-container"
|
|
8
|
+
:style="{ height: playerHeight }"
|
|
9
|
+
@transitionend="onHidden"
|
|
10
|
+
>
|
|
11
|
+
<template v-if="display">
|
|
12
|
+
<audio
|
|
13
|
+
id="audio-player"
|
|
14
|
+
:src="!live? audioUrl: undefined"
|
|
15
|
+
autoplay
|
|
16
|
+
@timeupdate="onTimeUpdate"
|
|
17
|
+
@ended="onFinished"
|
|
18
|
+
@playing="onPlay"
|
|
19
|
+
@durationChange="onTimeUpdate"
|
|
20
|
+
@error="onError"
|
|
21
|
+
/>
|
|
22
|
+
<PlayerCompact
|
|
23
|
+
v-if="!largeVersion"
|
|
24
|
+
v-model:notListenTime="notListenTime"
|
|
25
|
+
:player-error="playerError"
|
|
26
|
+
:hls-ready="hlsReady"
|
|
27
|
+
:comments="comments"
|
|
28
|
+
:display-alert-bar="displayAlertBar"
|
|
29
|
+
:percent-live-progress="percentLiveProgress"
|
|
30
|
+
:duration-live-position="durationLivePosition"
|
|
31
|
+
:listen-time="listenTime"
|
|
32
|
+
@stopPlayer="stopPlayer"
|
|
33
|
+
@changePlayerLargeVersion="largeVersion = true"
|
|
34
|
+
/>
|
|
35
|
+
<PlayerLarge
|
|
36
|
+
v-else
|
|
37
|
+
v-model:notListenTime="notListenTime"
|
|
38
|
+
:player-error="playerError"
|
|
39
|
+
:hls-ready="hlsReady"
|
|
40
|
+
:comments="comments"
|
|
41
|
+
:display-alert-bar="displayAlertBar"
|
|
42
|
+
:percent-live-progress="percentLiveProgress"
|
|
43
|
+
:duration-live-position="durationLivePosition"
|
|
44
|
+
:listen-time="listenTime"
|
|
45
|
+
@stopPlayer="stopPlayer"
|
|
46
|
+
@changePlayerLargeVersion="largeVersion = false"
|
|
47
|
+
/>
|
|
48
|
+
</template>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
</template>
|
|
52
|
+
<script lang="ts">
|
|
53
|
+
import { mapState } from 'vuex';
|
|
54
|
+
import { CommentPodcast } from '@/store/class/general/comment';
|
|
55
|
+
import { playerLogic } from '../../mixins/player/playerLogic';
|
|
56
|
+
import { StoreState } from '@/store/typeAppStore';
|
|
57
|
+
import PlayerCompact from '../player/PlayerCompact.vue';
|
|
58
|
+
import PlayerLarge from '../player/PlayerLarge.vue';
|
|
59
|
+
import { defineComponent } from 'vue';
|
|
60
|
+
export default defineComponent({
|
|
61
|
+
name: 'Player',
|
|
62
|
+
|
|
63
|
+
components: {
|
|
64
|
+
PlayerCompact,
|
|
65
|
+
PlayerLarge
|
|
66
|
+
},
|
|
67
|
+
mixins:[playerLogic],
|
|
68
|
+
emits: ['hide'],
|
|
69
|
+
data() {
|
|
70
|
+
return {
|
|
71
|
+
forceHide: false as boolean,
|
|
72
|
+
listenTime: 0 as number,
|
|
73
|
+
notListenTime: 0 as number,
|
|
74
|
+
lastSend: 0 as number,
|
|
75
|
+
downloadId: null as string|null,
|
|
76
|
+
playerError: false as boolean,
|
|
77
|
+
listenError: false as boolean,
|
|
78
|
+
percentLiveProgress: 0 as number,
|
|
79
|
+
durationLivePosition: 0 as number,
|
|
80
|
+
displayAlertBar: false as boolean,
|
|
81
|
+
hlsReady: false as boolean,
|
|
82
|
+
comments: [] as Array<CommentPodcast>,
|
|
83
|
+
showTimeline: false as boolean,
|
|
84
|
+
largeVersion: false as boolean,
|
|
85
|
+
};
|
|
86
|
+
},
|
|
87
|
+
computed: {
|
|
88
|
+
...mapState({
|
|
89
|
+
display: (state: StoreState) => 'STOPPED' !== state.player.status,
|
|
90
|
+
playerHeight(state: StoreState) {
|
|
91
|
+
if ('STOPPED' === state.player.status || this.forceHide) return 0;
|
|
92
|
+
if (this.largeVersion) return '27rem';
|
|
93
|
+
if (window.innerWidth > 450 && !this.showTimeline) return '5rem';
|
|
94
|
+
if (window.innerWidth > 450 && this.showTimeline) return '6rem';
|
|
95
|
+
return '3.5rem';
|
|
96
|
+
},
|
|
97
|
+
}),
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
watch: {
|
|
101
|
+
playerHeight(): void {
|
|
102
|
+
this.$emit('hide', 0 === this.playerHeight ? true : false);
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
methods: {
|
|
107
|
+
onHidden(): void {
|
|
108
|
+
if (this.forceHide) {
|
|
109
|
+
this.$store.commit('playerPlayPodcast');
|
|
110
|
+
this.forceHide = false;
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
})
|
|
115
|
+
</script>
|
|
116
|
+
|
|
117
|
+
<style lang="scss">
|
|
118
|
+
.octopus-app{
|
|
119
|
+
.player-container {
|
|
120
|
+
max-height: 94%;
|
|
121
|
+
position: fixed;
|
|
122
|
+
overflow: hidden;
|
|
123
|
+
z-index: 12;
|
|
124
|
+
width: 100%;
|
|
125
|
+
bottom: 0;
|
|
126
|
+
display: flex;
|
|
127
|
+
flex-direction: column;
|
|
128
|
+
transition: height 1s;
|
|
129
|
+
background: #282828 !important;
|
|
130
|
+
font-size: 1rem;
|
|
131
|
+
|
|
132
|
+
.player-progress-border {
|
|
133
|
+
height: 10px;
|
|
134
|
+
width: 3px;
|
|
135
|
+
background: black;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
@media (max-width: 960px) {
|
|
139
|
+
.d-flex {
|
|
140
|
+
flex-wrap: nowrap !important;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
</style>
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
class="d-flex align-items-center flex-grow-1 ps-2"
|
|
4
|
+
>
|
|
5
|
+
<router-link
|
|
6
|
+
v-if="isImage && podcastImage"
|
|
7
|
+
:to="podcastShareUrl"
|
|
8
|
+
>
|
|
9
|
+
<img
|
|
10
|
+
v-lazy="podcastImage"
|
|
11
|
+
:alt="$t('Podcast image')"
|
|
12
|
+
class="player-image"
|
|
13
|
+
>
|
|
14
|
+
</router-link>
|
|
15
|
+
<button
|
|
16
|
+
v-if="!playerError"
|
|
17
|
+
:title="$t('Play')"
|
|
18
|
+
:class="{
|
|
19
|
+
'saooti-play2-bounty': isPaused,
|
|
20
|
+
'saooti-pause-bounty': isPlaying,
|
|
21
|
+
'spinner-border':!isPaused&&!isPlaying
|
|
22
|
+
}"
|
|
23
|
+
class="btn play-button-box text-light primary-bg"
|
|
24
|
+
@click="switchPausePlay"
|
|
25
|
+
/>
|
|
26
|
+
<div class="text-light player-grow-content">
|
|
27
|
+
<div class="d-flex mb-1">
|
|
28
|
+
<div
|
|
29
|
+
v-if="playerError"
|
|
30
|
+
class="text-warning mx-2"
|
|
31
|
+
>
|
|
32
|
+
{{ $t('Podcast play error') + ' - ' }}
|
|
33
|
+
</div>
|
|
34
|
+
<div class="flex-grow-1 text-truncate">
|
|
35
|
+
{{ podcastTitle }}
|
|
36
|
+
</div>
|
|
37
|
+
<div
|
|
38
|
+
v-if="!playerError"
|
|
39
|
+
class="hide-phone"
|
|
40
|
+
>
|
|
41
|
+
{{ playedTime }} / {{ totalTime }}
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
<PlayerProgressBar
|
|
45
|
+
:hls-ready="hlsReady"
|
|
46
|
+
:show-timeline="showTimeline"
|
|
47
|
+
:comments="comments"
|
|
48
|
+
:display-alert-bar="displayAlertBar"
|
|
49
|
+
:percent-live-progress="percentLiveProgress"
|
|
50
|
+
:duration-live-position="durationLivePosition"
|
|
51
|
+
:player-error="playerError"
|
|
52
|
+
:listen-time="listenTime"
|
|
53
|
+
@updateNotListenTime="$emit('update:notListenTime', $event)"
|
|
54
|
+
/>
|
|
55
|
+
</div>
|
|
56
|
+
<button
|
|
57
|
+
:title="$t('Enlarge')"
|
|
58
|
+
class="btn play-button-box primary-bg text-light saooti-up-bounty"
|
|
59
|
+
@click="changePlayerLargeVersion"
|
|
60
|
+
/>
|
|
61
|
+
<button
|
|
62
|
+
:title="$t('Close')"
|
|
63
|
+
class="btn play-button-box primary-bg text-light saooti-cross"
|
|
64
|
+
@click="stopPlayer"
|
|
65
|
+
/>
|
|
66
|
+
<PlayerTimeline
|
|
67
|
+
v-model:showTimeline="showTimeline"
|
|
68
|
+
:comments="comments"
|
|
69
|
+
/>
|
|
70
|
+
</div>
|
|
71
|
+
</template>
|
|
72
|
+
<script lang="ts">
|
|
73
|
+
import { CommentPodcast } from '@/store/class/general/comment';
|
|
74
|
+
import { playerDisplay } from '../../mixins/player/playerDisplay';
|
|
75
|
+
import PlayerProgressBar from './PlayerProgressBar.vue';
|
|
76
|
+
import PlayerTimeline from './PlayerTimeline.vue';
|
|
77
|
+
import { defineComponent } from 'vue';
|
|
78
|
+
export default defineComponent({
|
|
79
|
+
name: 'PlayerCompact',
|
|
80
|
+
|
|
81
|
+
components: {
|
|
82
|
+
PlayerProgressBar,
|
|
83
|
+
PlayerTimeline
|
|
84
|
+
},
|
|
85
|
+
mixins:[playerDisplay],
|
|
86
|
+
|
|
87
|
+
props: {
|
|
88
|
+
playerError: { default: false, type: Boolean},
|
|
89
|
+
notListenTime: { default: 0 , type: Number},
|
|
90
|
+
hlsReady: { default: false , type: Boolean},
|
|
91
|
+
comments: { default: ()=>[] , type: Array as ()=> Array<CommentPodcast> },
|
|
92
|
+
displayAlertBar: { default: false , type: Boolean},
|
|
93
|
+
percentLiveProgress: { default: 0 , type: Number},
|
|
94
|
+
durationLivePosition: { default: 0 , type: Number},
|
|
95
|
+
listenTime: { default: 0 , type: Number},
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
emits: ['stopPlayer', 'update:notListenTime', 'changePlayerLargeVersion'],
|
|
99
|
+
data() {
|
|
100
|
+
return {
|
|
101
|
+
showTimeline: false as boolean,
|
|
102
|
+
};
|
|
103
|
+
},
|
|
104
|
+
methods:{
|
|
105
|
+
stopPlayer(){
|
|
106
|
+
this.$emit('stopPlayer');
|
|
107
|
+
},
|
|
108
|
+
changePlayerLargeVersion(){
|
|
109
|
+
this.$emit('changePlayerLargeVersion');
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
})
|
|
113
|
+
</script>
|
|
114
|
+
|
|
115
|
+
<style lang="scss">
|
|
116
|
+
.octopus-app{
|
|
117
|
+
.player-grow-content {
|
|
118
|
+
display: flex;
|
|
119
|
+
flex-direction: column;
|
|
120
|
+
flex-grow: 1;
|
|
121
|
+
flex-shrink: 1;
|
|
122
|
+
overflow: hidden;
|
|
123
|
+
font-size: 0.8rem;
|
|
124
|
+
}
|
|
125
|
+
.player-image {
|
|
126
|
+
border-radius: 0.2rem;
|
|
127
|
+
height: 2.4rem;
|
|
128
|
+
width: 2.4rem;
|
|
129
|
+
cursor: pointer;
|
|
130
|
+
/** PHONES*/
|
|
131
|
+
@media (max-width: 450px) {
|
|
132
|
+
height: 1.8rem;
|
|
133
|
+
width: 1.8rem;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
.play-button-box {
|
|
137
|
+
height: 2.5rem;
|
|
138
|
+
width: 2.5rem;
|
|
139
|
+
display: flex;
|
|
140
|
+
align-items: center;
|
|
141
|
+
justify-content: center;
|
|
142
|
+
margin: 0 0.5rem;
|
|
143
|
+
border-radius: 50%;
|
|
144
|
+
font-size: 1.2rem !important;
|
|
145
|
+
flex-shrink: 0;
|
|
146
|
+
cursor: pointer;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
</style>
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
class="d-flex flex-column align-items-center my-2 flex-grow-1 text-light position-relative overflow-y-auto"
|
|
4
|
+
>
|
|
5
|
+
<button
|
|
6
|
+
:title="$t('Reduce')"
|
|
7
|
+
class="player-reduce-button btn bg-transparent text-light saooti-down-bounty"
|
|
8
|
+
@click="changePlayerLargeVersion"
|
|
9
|
+
/>
|
|
10
|
+
<router-link
|
|
11
|
+
v-if="isImage && podcastImage"
|
|
12
|
+
:to="podcastShareUrl"
|
|
13
|
+
>
|
|
14
|
+
<img
|
|
15
|
+
v-lazy="podcastImage"
|
|
16
|
+
:alt="$t('Podcast image')"
|
|
17
|
+
class="img-box"
|
|
18
|
+
>
|
|
19
|
+
</router-link>
|
|
20
|
+
<div class="d-flex w-100 px-2 mt-2 text-center">
|
|
21
|
+
<div
|
|
22
|
+
v-if="playerError"
|
|
23
|
+
class="text-warning mx-2"
|
|
24
|
+
>
|
|
25
|
+
{{ $t('Podcast play error') + ' - ' }}
|
|
26
|
+
</div>
|
|
27
|
+
<div class="flex-grow-1 text-truncate h3">
|
|
28
|
+
{{ podcastTitle }}
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
<div class="player-grow-large-content">
|
|
32
|
+
<PlayerProgressBar
|
|
33
|
+
ref="progressbar"
|
|
34
|
+
:hls-ready="hlsReady"
|
|
35
|
+
:show-timeline="showTimeline"
|
|
36
|
+
:comments="comments"
|
|
37
|
+
:display-alert-bar="displayAlertBar"
|
|
38
|
+
:percent-live-progress="percentLiveProgress"
|
|
39
|
+
:duration-live-position="durationLivePosition"
|
|
40
|
+
:player-error="playerError"
|
|
41
|
+
:listen-time="listenTime"
|
|
42
|
+
@updateNotListenTime="$emit('update:notListenTime', $event)"
|
|
43
|
+
/>
|
|
44
|
+
<div class="d-flex justify-content-between">
|
|
45
|
+
<div>{{ playedTime }}</div>
|
|
46
|
+
<div>{{ totalTime }}</div>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
<div class="d-flex align-items-center">
|
|
50
|
+
<button
|
|
51
|
+
class="btn fs-1 bg-transparent text-light saooti-backward"
|
|
52
|
+
@click="seekClick(-15)"
|
|
53
|
+
/>
|
|
54
|
+
<button
|
|
55
|
+
v-if="!playerError"
|
|
56
|
+
:title="$t('Play')"
|
|
57
|
+
:class="{
|
|
58
|
+
'saooti-play2-bounty': isPaused,
|
|
59
|
+
'saooti-pause-bounty': isPlaying,
|
|
60
|
+
'spinner-border':!isPaused&&!isPlaying
|
|
61
|
+
}"
|
|
62
|
+
class="btn play-big-button-box text-light primary-bg"
|
|
63
|
+
@click="switchPausePlay"
|
|
64
|
+
/>
|
|
65
|
+
<button
|
|
66
|
+
class="btn fs-1 bg-transparent text-light saooti-forward2"
|
|
67
|
+
@click="seekClick(15)"
|
|
68
|
+
/>
|
|
69
|
+
</div>
|
|
70
|
+
<PlayerTimeline
|
|
71
|
+
v-model:showTimeline="showTimeline"
|
|
72
|
+
:comments="comments"
|
|
73
|
+
/>
|
|
74
|
+
</div>
|
|
75
|
+
</template>
|
|
76
|
+
<script lang="ts">
|
|
77
|
+
import { playerDisplay } from '../../mixins/player/playerDisplay';
|
|
78
|
+
import PlayerProgressBar from './PlayerProgressBar.vue';
|
|
79
|
+
import PlayerTimeline from './PlayerTimeline.vue';
|
|
80
|
+
import { defineComponent } from 'vue';
|
|
81
|
+
import { CommentPodcast } from '@/store/class/general/comment';
|
|
82
|
+
export default defineComponent({
|
|
83
|
+
name: 'PlayerLarge',
|
|
84
|
+
|
|
85
|
+
components: {
|
|
86
|
+
PlayerProgressBar,
|
|
87
|
+
PlayerTimeline
|
|
88
|
+
},
|
|
89
|
+
mixins:[playerDisplay],
|
|
90
|
+
|
|
91
|
+
props: {
|
|
92
|
+
playerError: { default: false, type: Boolean},
|
|
93
|
+
notListenTime: { default: 0 , type: Number},
|
|
94
|
+
hlsReady: { default: false , type: Boolean},
|
|
95
|
+
comments: { default: ()=>[] , type: Array as ()=> Array<CommentPodcast> },
|
|
96
|
+
displayAlertBar: { default: false , type: Boolean},
|
|
97
|
+
percentLiveProgress: { default: 0 , type: Number},
|
|
98
|
+
durationLivePosition: { default: 0 , type: Number},
|
|
99
|
+
listenTime: { default: 0 , type: Number},
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
emits: ['stopPlayer', 'update:notListenTime', 'changePlayerLargeVersion'],
|
|
103
|
+
data() {
|
|
104
|
+
return {
|
|
105
|
+
showTimeline: false as boolean,
|
|
106
|
+
};
|
|
107
|
+
},
|
|
108
|
+
methods:{
|
|
109
|
+
stopPlayer(){
|
|
110
|
+
this.$emit('stopPlayer');
|
|
111
|
+
},
|
|
112
|
+
changePlayerLargeVersion(){
|
|
113
|
+
this.$emit('changePlayerLargeVersion');
|
|
114
|
+
},
|
|
115
|
+
seekClick(addTime: number):void{
|
|
116
|
+
const audioPlayer: HTMLAudioElement|null = document.querySelector('#audio-player');
|
|
117
|
+
if(!audioPlayer){return;}
|
|
118
|
+
const seekTo = audioPlayer.currentTime + addTime;
|
|
119
|
+
(this.$refs.progressbar as InstanceType<typeof PlayerProgressBar>).isSeekTo(audioPlayer, seekTo >0?seekTo: 0);
|
|
120
|
+
},
|
|
121
|
+
}
|
|
122
|
+
})
|
|
123
|
+
</script>
|
|
124
|
+
|
|
125
|
+
<style lang="scss">
|
|
126
|
+
.octopus-app{
|
|
127
|
+
.player-container .img-box{
|
|
128
|
+
@media (max-width: 960px) {
|
|
129
|
+
width: 10rem;
|
|
130
|
+
height: 10rem;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
.player-reduce-button{
|
|
134
|
+
position: absolute;
|
|
135
|
+
right: 0;
|
|
136
|
+
font-size: 1.2rem !important;
|
|
137
|
+
}
|
|
138
|
+
.player-grow-large-content{
|
|
139
|
+
width: 100%;
|
|
140
|
+
padding: 1rem 2rem;
|
|
141
|
+
@media (max-width: 960px) {
|
|
142
|
+
padding: 0.5rem;
|
|
143
|
+
}
|
|
144
|
+
.progress, .progress-bar{
|
|
145
|
+
height: 15px !important;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
.play-big-button-box {
|
|
149
|
+
height: 5rem;
|
|
150
|
+
width: 5rem;
|
|
151
|
+
display: flex;
|
|
152
|
+
align-items: center;
|
|
153
|
+
justify-content: center;
|
|
154
|
+
margin: 0 0.5rem;
|
|
155
|
+
border-radius: 50%;
|
|
156
|
+
font-size: 2.5rem !important;
|
|
157
|
+
flex-shrink: 0;
|
|
158
|
+
cursor: pointer;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
</style>
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
v-if="!playerError"
|
|
4
|
+
class="progress c-hand"
|
|
5
|
+
@mouseup="seekTo"
|
|
6
|
+
>
|
|
7
|
+
<div
|
|
8
|
+
class="progress-bar bg-light"
|
|
9
|
+
role="progressbar"
|
|
10
|
+
aria-valuenow="0"
|
|
11
|
+
aria-valuemin="0"
|
|
12
|
+
aria-valuemax="100"
|
|
13
|
+
:style="'width: ' + percentLiveProgress + '%'"
|
|
14
|
+
/>
|
|
15
|
+
<div
|
|
16
|
+
class="progress-bar primary-bg"
|
|
17
|
+
role="progressbar"
|
|
18
|
+
aria-valuenow="0"
|
|
19
|
+
aria-valuemin="0"
|
|
20
|
+
aria-valuemax="100"
|
|
21
|
+
:style="'width: ' + percentProgress + '%'"
|
|
22
|
+
/>
|
|
23
|
+
<div
|
|
24
|
+
v-if="displayAlertBar"
|
|
25
|
+
class="progress-bar progress-bar-duration bg-danger"
|
|
26
|
+
:style="'left: ' + durationLivePosition + '%'"
|
|
27
|
+
/>
|
|
28
|
+
</div>
|
|
29
|
+
<CommentPlayer
|
|
30
|
+
v-if="showTimeline"
|
|
31
|
+
:total-time="totalSecondes"
|
|
32
|
+
:comments="comments"
|
|
33
|
+
/>
|
|
34
|
+
</template>
|
|
35
|
+
|
|
36
|
+
<script lang="ts">
|
|
37
|
+
import { CommentPodcast } from '@/store/class/general/comment';
|
|
38
|
+
import { defineComponent, defineAsyncComponent } from 'vue';
|
|
39
|
+
const CommentPlayer = defineAsyncComponent(() => import('../../display/comments/CommentPlayer.vue'));
|
|
40
|
+
export default defineComponent({
|
|
41
|
+
name: 'PlayerProgressBar',
|
|
42
|
+
|
|
43
|
+
components: {
|
|
44
|
+
CommentPlayer,
|
|
45
|
+
},
|
|
46
|
+
props: {
|
|
47
|
+
hlsReady: { default: false, type: Boolean},
|
|
48
|
+
showTimeline: { default: false, type: Boolean},
|
|
49
|
+
comments: { default: ()=>[], type: Array as ()=>Array<CommentPodcast>},
|
|
50
|
+
displayAlertBar: { default: false, type: Boolean},
|
|
51
|
+
percentLiveProgress: { default: 0, type: Number},
|
|
52
|
+
durationLivePosition: { default: 0, type: Number},
|
|
53
|
+
playerError: { default: false, type: Boolean},
|
|
54
|
+
listenTime: { default: 0, type: Number},
|
|
55
|
+
},
|
|
56
|
+
emits: ['updateNotListenTime'],
|
|
57
|
+
|
|
58
|
+
computed: {
|
|
59
|
+
percentProgress(): number{
|
|
60
|
+
if(!this.$store.state.player.elapsed){return 0;}
|
|
61
|
+
return this.$store.state.player.elapsed * 100;
|
|
62
|
+
},
|
|
63
|
+
totalSecondes(): number{
|
|
64
|
+
return this.$store.state.player.total;
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
methods: {
|
|
70
|
+
seekTo(event: MouseEvent): void {
|
|
71
|
+
const audioPlayer: HTMLAudioElement|null = document.querySelector('#audio-player');
|
|
72
|
+
if(!audioPlayer || null===event.currentTarget){return;}
|
|
73
|
+
const rect = (event.currentTarget as Element).getBoundingClientRect();
|
|
74
|
+
const barWidth = (event.currentTarget as Element).clientWidth;
|
|
75
|
+
const x = event.clientX - rect.left;
|
|
76
|
+
const percentPosition = x / barWidth;
|
|
77
|
+
if (percentPosition * 100 >= this.percentLiveProgress) return;
|
|
78
|
+
const seekTime = this.$store.state.player.total * percentPosition;
|
|
79
|
+
this.isSeekTo(audioPlayer, seekTime);
|
|
80
|
+
},
|
|
81
|
+
isSeekTo(audioPlayer: HTMLAudioElement, seekTime: number): void {
|
|
82
|
+
if (this.$store.state.player.podcast || this.$store.state.player.live) {
|
|
83
|
+
this.$emit('updateNotListenTime',seekTime - this.listenTime);
|
|
84
|
+
}
|
|
85
|
+
audioPlayer.currentTime = seekTime;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
},
|
|
89
|
+
})
|
|
90
|
+
</script>
|
|
91
|
+
|
|
92
|
+
<style lang="scss">
|
|
93
|
+
.octopus-app{
|
|
94
|
+
.progress {
|
|
95
|
+
height: 4px;
|
|
96
|
+
position: relative;
|
|
97
|
+
@media (max-width: 960px) {
|
|
98
|
+
height: 8px;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
.progress-bar-duration {
|
|
102
|
+
width: 10px;
|
|
103
|
+
}
|
|
104
|
+
.progress-bar {
|
|
105
|
+
height: 4px;
|
|
106
|
+
position: absolute;
|
|
107
|
+
@media (max-width: 960px) {
|
|
108
|
+
height: 8px;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
</style>
|
|
@@ -10,22 +10,14 @@
|
|
|
10
10
|
/>
|
|
11
11
|
<div>Timeline</div>
|
|
12
12
|
</div>
|
|
13
|
-
<div
|
|
14
|
-
v-if="isClock"
|
|
15
|
-
class="d-flex text-light align-items-center hide-phone"
|
|
16
|
-
>
|
|
17
|
-
<div class="saooti-clock-stud m-2" />
|
|
18
|
-
<div>{{ actualTime }}</div>
|
|
19
|
-
</div>
|
|
20
13
|
</template>
|
|
21
14
|
|
|
22
15
|
<script lang="ts">
|
|
23
|
-
import
|
|
24
|
-
import { state } from '../../store/paramStore';
|
|
16
|
+
import { state } from '../../../store/paramStore';
|
|
25
17
|
import { defineComponent } from 'vue';
|
|
26
18
|
import { CommentPodcast } from '@/store/class/general/comment';
|
|
27
19
|
export default defineComponent({
|
|
28
|
-
name: '
|
|
20
|
+
name: 'PlayerTimeline',
|
|
29
21
|
|
|
30
22
|
props: {
|
|
31
23
|
showTimeline: { default: false, type: Boolean},
|
|
@@ -35,7 +27,6 @@ export default defineComponent({
|
|
|
35
27
|
|
|
36
28
|
data() {
|
|
37
29
|
return {
|
|
38
|
-
actualTime: '' as string,
|
|
39
30
|
};
|
|
40
31
|
},
|
|
41
32
|
|
|
@@ -43,24 +34,12 @@ export default defineComponent({
|
|
|
43
34
|
isPodcastmaker(): boolean {
|
|
44
35
|
return (state.generalParameters.podcastmaker as boolean);
|
|
45
36
|
},
|
|
46
|
-
isClock(): boolean {
|
|
47
|
-
return (state.player.clock as boolean);
|
|
48
|
-
},
|
|
49
|
-
|
|
50
|
-
},
|
|
51
|
-
|
|
52
|
-
mounted() {
|
|
53
|
-
if (this.isClock) {
|
|
54
|
-
setInterval(() => {
|
|
55
|
-
this.actualTime = moment(new Date()).format('HH:mm:ss');
|
|
56
|
-
}, 1000);
|
|
57
|
-
}
|
|
58
37
|
},
|
|
59
38
|
|
|
60
39
|
})
|
|
61
40
|
</script>
|
|
62
41
|
<style lang="scss">
|
|
63
|
-
@import '
|
|
42
|
+
@import '../../../sass/_variables.scss';
|
|
64
43
|
.octopus-app{
|
|
65
44
|
.player-container {
|
|
66
45
|
.timeline-button {
|