ContentVideoPlayer.vue 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. <template>
  2. <div ref="videoPlayerWrapper"
  3. class="vPlayer">
  4. <video-player v-if="content.photo && content.isVideo() && content.hasVideoSource()"
  5. ref="videoPlayer"
  6. :key="playerKey"
  7. :source="content.getVideoSource()"
  8. :poster="content.photo"
  9. :over-player="hasTimepoint"
  10. :over-player-width="'250px'"
  11. :has-vast="canInitVAST && contentHasVast"
  12. :use-over-player="hasTimepoint"
  13. @adStarted="adStarted">
  14. <template #overPlayer>
  15. <div class="timepoint-list">
  16. <q-banner class="timepoint-list-title">
  17. زمان کوب ها
  18. ({{ currentContent.timepoints.list.length }})
  19. </q-banner>
  20. <q-list class="timepoint-list-items">
  21. <q-item v-for="timepoint in currentContent.timepoints.list"
  22. :key="timepoint.id"
  23. v-ripple
  24. clickable
  25. @click="goToTimpoint(timepoint)">
  26. <q-item-section avatar>
  27. <bookmark color="white"
  28. size="30"
  29. :is-favored="timepoint.is_favored"
  30. :loading="timepoint.loading"
  31. @clicked="handleTimepointBookmark(timepoint.id)" />
  32. </q-item-section>
  33. <q-item-section class="text-section">
  34. <span>{{ timepoint.title }}</span>
  35. <span v-if="currentContent.can_user_use_timepoint">
  36. {{ timepoint.formattedTime() }}
  37. </span>
  38. </q-item-section>
  39. </q-item>
  40. </q-list>
  41. </div>
  42. </template>
  43. </video-player>
  44. <div v-else>
  45. <q-card class="flex justify-center items-center">
  46. <q-img v-if="content.photo"
  47. :src="content.photo" />
  48. <div v-else
  49. class="flex justify-center items-center"
  50. style="height: 420px; justify-content: center">
  51. ویدیویی وجود ندارد!
  52. </div>
  53. </q-card>
  54. </div>
  55. </div>
  56. </template>
  57. <script>
  58. import { Content } from 'src/models/Content.js'
  59. import Bookmark from 'src/components/Bookmark.vue'
  60. import VideoPlayer from 'src/components/VideoPlayer.vue'
  61. import TimeElapsedSinceLastEvent from 'src/assets/js/TimeElapsedSinceLastEvent.js'
  62. export default {
  63. name: 'ContentVideoPlayer',
  64. components: { VideoPlayer, Bookmark },
  65. props: {
  66. content: {
  67. type: Content
  68. },
  69. showTimePoints: {
  70. type: Boolean,
  71. default: true
  72. },
  73. poster: {
  74. type: String,
  75. default () {
  76. return ''
  77. }
  78. },
  79. keepCalculating: {
  80. type: Boolean,
  81. default () {
  82. return true
  83. }
  84. },
  85. currentTimed: {
  86. type: Number
  87. }
  88. },
  89. emits: ['seeked'],
  90. data() {
  91. return {
  92. canInitVAST: false,
  93. playerKey: Date.now(),
  94. currentContent: new Content()
  95. }
  96. },
  97. computed: {
  98. contentHasVast () {
  99. return this.content.has_vast
  100. },
  101. hasTimepoint () {
  102. return this.content.timepoints.list.length > 0
  103. }
  104. },
  105. watch: {
  106. content: {
  107. handler (newVal) {
  108. this.playerKey = Date.now()
  109. this.currentContent = newVal
  110. if (!this.currentContent.can_user_use_timepoint) {
  111. this.currentContent.timepoints.removeAllTimes()
  112. }
  113. },
  114. immediate: true,
  115. deep: true
  116. }
  117. },
  118. beforeUnmount() {
  119. if (this.player) {
  120. this.player.dispose()
  121. }
  122. },
  123. beforeMount () {
  124. this.canInitVAST = TimeElapsedSinceLastEvent.canInitVAST()
  125. },
  126. methods: {
  127. adStarted () {
  128. TimeElapsedSinceLastEvent.setEventOccurrenceTime()
  129. },
  130. getCurrentContentTimepoint (timepointId) {
  131. return this.currentContent.timepoints.list.find(item => item.id === timepointId)
  132. },
  133. handleTimepointBookmark (timepointId) {
  134. const timepointIndex = this.currentContent.timepoints.list.findIndex(item => item.id === timepointId)
  135. const currentContentTimepoint = this.getCurrentContentTimepoint(timepointId)
  136. this.currentContent.timepoints.list[timepointIndex].loading = true
  137. const isFavoredStatus = currentContentTimepoint.is_favored ? 'unfavored' : 'favored'
  138. this.changeTimepointStatus({
  139. timepointId,
  140. isFavoredStatus,
  141. timepointIndex,
  142. currentContentTimepoint
  143. })
  144. },
  145. changeTimepointStatus (data) {
  146. this.$apiGateway.content.setBookmarkTimepointFavoredStatus({
  147. id: data.timepointId,
  148. status: data.isFavoredStatus
  149. })
  150. .then(() => {
  151. this.currentContent.timepoints.list[data.timepointIndex].is_favored = !data.currentContentTimepoint.is_favored
  152. this.toggleFavorite(this.content.id)
  153. this.currentContent.timepoints.list[data.timepointIndex].loading = false
  154. })
  155. .catch(() => {
  156. this.currentContent.timepoints.list[data.timepointIndex].loading = false
  157. })
  158. },
  159. goToTimpoint (timepoint) {
  160. if (!this.$refs.videoPlayer) {
  161. return
  162. }
  163. if (!this.currentContent.can_user_use_timepoint) {
  164. this.$refs.videoPlayer.toggleFullScreen()
  165. this.$q.dialog({
  166. title: 'استفاده از زمان کوب',
  167. message: 'جهت استفاده از زمان کوب می بایست اشتراک خریداری کنید.',
  168. cancel: true,
  169. persistent: true
  170. }).onOk(() => {
  171. this.$router.push({ name: 'Public.Landing.DynamicName', params: { landing_name: 'timepoint' } })
  172. }).onCancel(() => {
  173. // this.$router.push({ name: 'Public.Home' })
  174. })
  175. return
  176. }
  177. this.$refs.videoPlayer.changeCurrentTime(timepoint.time)
  178. },
  179. activate(time) {
  180. this.player.currentTime(time)
  181. this.player.play()
  182. const requiredElement = document.querySelector('.video-js')
  183. requiredElement.focus()
  184. },
  185. setSources() {
  186. this.options.sources = this.source
  187. },
  188. setPoster() {
  189. this.options.poster = this.poster
  190. },
  191. reInitVideo() {
  192. this.player.src(this.source)
  193. this.player.poster(this.poster)
  194. },
  195. toggleFavorite(id) {
  196. const that = this
  197. let count = -1
  198. // let currentTimepointIndex = null
  199. this.timePoints.forEach(function (item) {
  200. count++
  201. if (parseInt(item.id) === parseInt(id)) {
  202. // currentTimepointIndex = index
  203. item.loading = true
  204. item.is_favored = !item.is_favored
  205. that.postIsFavored = {
  206. id: item.id,
  207. isFavored: item.is_favored,
  208. numberOfTimestamp: count
  209. }
  210. }
  211. })
  212. const requiredElement = document.querySelector('.video-js')
  213. requiredElement.focus()
  214. this.$emit('toggleBookmark', this.postIsFavored)
  215. // setTimeout(function() { that.timePoints[currentTimepointIndex].loading = false }, 200) // vue/no-mutating-props
  216. },
  217. // postIsFavored(timeStampData){
  218. // var postStatus = 'unfavored'
  219. // if (timeStampData.isFavored){
  220. // postStatus = 'favored'
  221. // }
  222. // // /api/v2/timepoint/{timepoint_id}/favored
  223. // axios.post('/api/v2/c/timepoint/' + parseInt(timeStampData.id) + '/'+ postStatus)
  224. // .then(response => {
  225. // if (response.status === 200){
  226. // this.timePoints.forEach( function (item) {
  227. // if (parseInt(item.id) === parseInt(timeStampData.id)) {
  228. // item.loading = false
  229. // }
  230. // })
  231. // }
  232. // })
  233. // .catch(err => console.error(err));
  234. // },
  235. calcWatchedPercentage(currentTime, duration) {
  236. const watchedPercentage = ((currentTime / duration) * 100)
  237. const videoPlayerTimeData = {
  238. currentTime,
  239. duration,
  240. watchedPercentage
  241. }
  242. this.$emit('calcTimeData', videoPlayerTimeData)
  243. },
  244. videoStatus(val) {
  245. this.videoIsPlaying = val
  246. }
  247. }
  248. }
  249. </script>
  250. <style scoped lang="scss">
  251. .vPlayer {
  252. width: 100%;
  253. .timepoint-list {
  254. direction: ltr;
  255. width: 100%;
  256. color: white;
  257. height: 100%;
  258. padding-bottom: 30px;
  259. background: rgba(0,0,0,0.4);
  260. .timepoint-list-title {
  261. text-align: center;
  262. background: rgba(0,0,0,0.7);
  263. }
  264. .timepoint-list-items {
  265. .text-section {
  266. display: flex;
  267. flex-flow: row;
  268. font-size: 0.7rem;
  269. font-weight: bold;
  270. align-items: center;
  271. justify-content: space-between;
  272. }
  273. }
  274. :deep(.q-list) {
  275. height: calc(100% - 54px);
  276. overflow: auto;
  277. .bookmark-btn.q-btn {
  278. width: 26px;
  279. height: 26px;
  280. padding: 0;
  281. font-size: 10px;
  282. color: $primary !important;
  283. .q-btn__content {
  284. margin: 3px;
  285. svg {
  286. width: 20px;
  287. height: 20px;
  288. }
  289. }
  290. }
  291. }
  292. }
  293. }
  294. </style>