Skip to content
Snippets Groups Projects
PlayButton.vue 8.96 KiB
Newer Older
  • Learn to ignore specific revisions
  • Georg Krause's avatar
    Georg Krause committed
      <span
        :title="title"
        :class="['ui', {'tiny': discrete}, {'icon': !discrete}, {'buttons': !dropdownOnly && !iconOnly}, 'play-button component-play-button']"
      >
    
          v-if="!dropdownOnly"
    
          :aria-label="labels.replacePlay"
    
    Georg Krause's avatar
    Georg Krause committed
          :class="buttonClasses.concat(['ui', {loading: isLoading}, {'mini': discrete}, {disabled: !playable}])"
          @click.stop.prevent="replacePlay"
        >
          <i
            v-if="playing"
            class="pause icon"
          />
          <i
            v-else
            :class="[playIconClass, 'icon']"
          />
    
          <template v-if="!discrete && !iconOnly">&nbsp;<slot><translate translate-context="*/Queue/Button.Label/Short, Verb">Play</translate></slot></template>
    
          v-if="!discrete && !iconOnly"
    
    Georg Krause's avatar
    Georg Krause committed
          :class="['ui', {disabled: !playable && !filterableArtist}, 'floating', 'dropdown', {'icon': !dropdownOnly}, {'button': !dropdownOnly}]"
    
          @click.stop.prevent="clicked = true"
    
    Georg Krause's avatar
    Georg Krause committed
        >
          <i
            :class="dropdownIconClasses.concat(['icon'])"
            :title="title"
          />
          <div
            v-if="clicked"
            class="menu"
          >
            <button
              ref="add"
              class="item basic"
              data-ref="add"
              :disabled="!playable"
              :title="labels.addToQueue"
              @click.stop.prevent="add"
            >
              <i class="plus icon" /><translate translate-context="*/Queue/Dropdown/Button/Label/Short">Add to queue</translate>
    
    Georg Krause's avatar
    Georg Krause committed
            <button
              ref="addNext"
              class="item basic"
              data-ref="addNext"
              :disabled="!playable"
              :title="labels.playNext"
              @click.stop.prevent="addNext()"
            >
              <i class="step forward icon" />{{ labels.playNext }}
    
    Georg Krause's avatar
    Georg Krause committed
            <button
              ref="playNow"
              class="item basic"
              data-ref="playNow"
              :disabled="!playable"
              :title="labels.playNow"
              @click.stop.prevent="addNext(true)"
            >
              <i class="play icon" />{{ labels.playNow }}
    
    Georg Krause's avatar
    Georg Krause committed
            <button
              v-if="track"
              class="item basic"
              :disabled="!playable"
              :title="labels.startRadio"
              @click.stop.prevent="$store.dispatch('radios/start', {type: 'similar', objectId: track.id})"
            >
              <i class="feed icon" /><translate translate-context="*/Queue/Button.Label/Short, Verb">Play radio</translate>
    
    Georg Krause's avatar
    Georg Krause committed
            <button
              v-if="track"
              class="item basic"
              :disabled="!playable"
              @click.stop="$store.commit('playlists/chooseTrack', track)"
            >
              <i class="list icon" />
    
    Ciarán Ainsworth's avatar
    Ciarán Ainsworth committed
              <translate translate-context="Sidebar/Player/Icon.Tooltip/Verb">Add to playlist…</translate>
            </button>
    
    Georg Krause's avatar
    Georg Krause committed
            <button
    
              v-if="track && !onTrackPage"
    
    Georg Krause's avatar
    Georg Krause committed
              class="item basic"
              @click.stop.prevent="$router.push(`/library/tracks/${track.id}/`)"
            >
              <i class="info icon" />
              <translate
                v-if="track.artist.content_category === 'podcast'"
                translate-context="*/Queue/Dropdown/Button/Label/Short"
              >Episode details</translate>
              <translate
                v-else
                translate-context="*/Queue/Dropdown/Button/Label/Short"
              >Track details</translate>
    
    Georg Krause's avatar
    Georg Krause committed
            <div class="divider" />
            <button
              v-if="filterableArtist"
              ref="filterArtist"
              data-ref="filterArtist"
              class="item basic"
              :disabled="!filterableArtist"
              :title="labels.hideArtist"
              @click.stop.prevent="filterArtist"
            >
              <i class="eye slash outline icon" /><translate translate-context="*/Queue/Dropdown/Button/Label/Short">Hide content from this artist</translate>
    
    Eliot Berriot's avatar
    Eliot Berriot committed
            <button
    
              v-for="obj in getReportableObjs({track, album, artist, playlist, account, channel})"
    
    Eliot Berriot's avatar
    Eliot Berriot committed
              :key="obj.target.type + obj.target.id"
    
    Georg Krause's avatar
    Georg Krause committed
              :ref="`report${obj.target.type}${obj.target.id}`"
    
    Eliot Berriot's avatar
    Eliot Berriot committed
              class="item basic"
    
    Georg Krause's avatar
    Georg Krause committed
              :data-ref="`report${obj.target.type}${obj.target.id}`"
              @click.stop.prevent="$store.dispatch('moderation/report', obj.target)"
            >
    
    Eliot Berriot's avatar
    Eliot Berriot committed
              <i class="share icon" /> {{ obj.label }}
            </button>
    
    Ciaran Ainsworth's avatar
    Ciaran Ainsworth committed
    import ReportMixin from '@/components/mixins/Report.vue'
    import PlayOptionsMixin from '@/components/mixins/PlayOptions.vue'
    
    Ciarán Ainsworth's avatar
    Ciarán Ainsworth committed
      mixins: [ReportMixin, PlayOptionsMixin],
    
      props: {
        // we can either have a single or multiple tracks to play when clicked
    
    Georg Krause's avatar
    Georg Krause committed
        tracks: { type: Array, required: false, default: () => { return null } },
        track: { type: Object, required: false, default: () => { return null } },
        account: { type: Object, required: false, default: () => { return null } },
    
    Georg Krause's avatar
    Georg Krause committed
        dropdownIconClasses: { type: Array, required: false, default: () => { return ['dropdown'] } },
        playIconClass: { type: String, required: false, default: 'play icon' },
        buttonClasses: { type: Array, required: false, default: () => { return ['button'] } },
    
    Georg Krause's avatar
    Georg Krause committed
        playlist: { type: Object, required: false, default: () => { return null } },
    
    Georg Krause's avatar
    Georg Krause committed
        discrete: { type: Boolean, default: false },
        dropdownOnly: { type: Boolean, default: false },
        iconOnly: { type: Boolean, default: false },
    
    Georg Krause's avatar
    Georg Krause committed
        artist: { type: Object, required: false, default: () => { return null } },
        album: { type: Object, required: false, default: () => { return null } },
        library: { type: Object, required: false, default: () => { return null } },
        channel: { type: Object, required: false, default: () => { return null } },
    
    Georg Krause's avatar
    Georg Krause committed
        isPlayable: { type: Boolean, required: false, default: null },
        playing: { type: Boolean, required: false, default: false },
        paused: { type: Boolean, required: false, default: false }
    
          isLoading: false,
    
    Eliot Berriot's avatar
    Eliot Berriot committed
        labels () {
    
    Agate's avatar
    Agate committed
          let replacePlay
          if (this.track) {
            replacePlay = this.$pgettext('*/Queue/Dropdown/Button/Title', 'Play track')
          } else if (this.album) {
            replacePlay = this.$pgettext('*/Queue/Dropdown/Button/Title', 'Play album')
          } else if (this.artist) {
            replacePlay = this.$pgettext('*/Queue/Dropdown/Button/Title', 'Play artist')
          } else if (this.playlist) {
            replacePlay = this.$pgettext('*/Queue/Dropdown/Button/Title', 'Play playlist')
          } else {
            replacePlay = this.$pgettext('*/Queue/Dropdown/Button/Title', 'Play tracks')
          }
    
    Eliot Berriot's avatar
    Eliot Berriot committed
          return {
    
            playNow: this.$pgettext('*/Queue/Dropdown/Button/Title', 'Play now'),
            addToQueue: this.$pgettext('*/Queue/Dropdown/Button/Title', 'Add to current queue'),
            playNext: this.$pgettext('*/Queue/Dropdown/Button/Title', 'Play next'),
    
            startRadio: this.$pgettext('*/Queue/Dropdown/Button/Title', 'Play similar songs'),
    
    Eliot Berriot's avatar
    Eliot Berriot committed
            report: this.$pgettext('*/Moderation/*/Button/Label,Verb', 'Report…'),
    
    Ciarán Ainsworth's avatar
    Ciarán Ainsworth committed
            addToPlaylist: this.$pgettext('Sidebar/Player/Icon.Tooltip/Verb', 'Add to playlist…'),
    
    Georg Krause's avatar
    Georg Krause committed
            replacePlay
    
            return this.$pgettext('*/*/Button.Label/Noun', 'More…')
    
              return this.$pgettext('*/Queue/Button/Title', 'This track is not available in any library you have access to')
    
    Georg Krause's avatar
    Georg Krause committed
          return null
    
        },
        onTrackPage () {
          return this.$router.currentRoute.name === 'library.tracks.detail'
    
    Georg Krause's avatar
    Georg Krause committed
          const self = this
    
          this.$nextTick(() => {
            jQuery(this.$el).find('.ui.dropdown').dropdown({
              selectOnKeydown: false,
              action: function (text, value, $el) {
    
                // used to ensure focusing the dropdown and clicking via keyboard
    
    Georg Krause's avatar
    Georg Krause committed
                const button = self.$refs[$el.data('ref')]
    
                if (Array.isArray(button)) {
                  button[0].click()
                } else {
                  button.click()
                }
    
                jQuery(self.$el).find('.ui.dropdown').dropdown('hide')
    
            })
            jQuery(this.$el).find('.ui.dropdown').dropdown('show', function () {
              // little magic to ensure the menu is always visible in the viewport
              // By default, try to diplay it on the right if there is enough room
    
    Georg Krause's avatar
    Georg Krause committed
              const menu = jQuery(self.$el).find('.ui.dropdown').find('.menu')
              const viewportOffset = menu.get(0).getBoundingClientRect()
              const viewportWidth = document.documentElement.clientWidth
              const rightOverflow = viewportOffset.right - viewportWidth
              const leftOverflow = -viewportOffset.left
    
              let offset = 0
              if (rightOverflow > 0) {
                offset = -rightOverflow - 5
    
    Georg Krause's avatar
    Georg Krause committed
                menu.css({ cssText: `left: ${offset}px !important;` })
              } else if (leftOverflow > 0) {
                offset = leftOverflow + 5
                menu.css({ cssText: `right: -${offset}px !important;` })