Compare commits

...

7 Commits

Author SHA1 Message Date
Jie Li
a0f1daf2ed
Merge 98fc5992fb into a70a5c6ab2 2024-11-21 16:49:58 +00:00
Jie Li
98fc5992fb removed buttons in edit mode 2024-11-21 16:49:46 +00:00
Jie Li
a2863d31d4 fixed empty playlist error 2024-11-15 11:48:52 +00:00
Jie Li
c5d2d3359a aligned buttons to the right for yt playlist 2024-11-12 16:14:47 +00:00
Jie Li
3f904e4b7d Merge branch 'development' into playlist-play-button 2024-11-12 15:53:12 +00:00
Jie Li
f1875d5f73 revert deletion of last updated on 2024-11-12 15:51:11 +00:00
Jie Li
0429121b8d added shuffle and play all buttons to playlists 2024-11-12 15:46:25 +00:00
8 changed files with 92 additions and 21 deletions

View File

@ -124,6 +124,29 @@ export default defineComponent({
}
},
computed: {
watchRandomVideo() {
if (!this.firstVideoIdExists) {
return ''
}
const randomVideo = this.videos[Math.floor(Math.random() * this.videos.length)]
return {
path: `/watch/${randomVideo.videoId}`,
query: this.watchPageLinkQuery(randomVideo.playlistItemId, true),
}
},
watchFirstVideo() {
if (!this.firstVideoIdExists) {
return ''
}
const firstVideo = this.videos[0]
return {
path: `/watch/${firstVideo.videoId}`,
query: this.watchPageLinkQuery(firstVideo.playlistItemId),
}
},
hideSharingActions: function () {
return this.$store.getters.getHideSharingActions
},
@ -353,6 +376,15 @@ export default defineComponent({
document.removeEventListener('keydown', this.keyboardShortcutHandler)
},
methods: {
watchPageLinkQuery(playlistItemId, shuffle = false) {
return {
playlistId: this.id,
playlistType: this.videoPlaylistType,
playlistItemId: playlistItemId,
playlistEnableShuffle: shuffle,
}
},
handlePlaylistNameInput(input) {
if (input.trim() === '') {
// Need to show message for blank input

View File

@ -73,6 +73,7 @@
grid-auto-flow: column;
column-gap: 8px;
justify-content: flex-end;
margin-block: 5px;
}
.searchInputsRow {
@ -111,7 +112,7 @@
margin-block-start: 8px;
}
.playlistOptionsAndSearch {
.playlistOptionsWrapper {
display: flex;
flex-direction: column;
justify-content: space-between;

View File

@ -129,7 +129,7 @@
</h3>
</div>
<div class="playlistOptionsAndSearch">
<div class="playlistOptionsWrapper">
<div class="playlistOptions">
<ft-icon-button
v-if="editMode"
@ -207,22 +207,6 @@
share-target-type="Playlist"
/>
</div>
<div
v-if="searchVideoModeAllowed"
class="searchInputsRow"
>
<ft-input
ref="searchInput"
class="inputElement"
:placeholder="$t('User Playlists.SinglePlaylistView.Search for Videos')"
:show-clear-text-button="true"
:show-action-button="false"
:value="query"
:maxlength="255"
@input="(input) => updateQueryDebounce(input)"
@clear="updateQueryDebounce('')"
/>
</div>
</div>
<ft-prompt
v-if="showDeletePlaylistPrompt"
@ -249,6 +233,48 @@
@click="handleRemoveDuplicateVideosPromptAnswer"
/>
</div>
<div class="playlistOptionsWrapper">
<div
v-if="firstVideoIdExists && !editMode"
class="playlistOptions"
>
<router-link
:to="watchFirstVideo"
>
<ft-button
class="playlistPlayButton"
:label="$t('Playlist.Play all')"
:icon="['fas', 'play']"
/>
</router-link>
<router-link
:to="watchRandomVideo"
>
<ft-button
class="playlistPlayButton"
:label="$t('Playlist.Shuffle')"
:icon="['fas', 'random']"
/>
</router-link>
</div>
<div
v-if="searchVideoModeAllowed"
class="searchInputsRow"
>
<ft-input
ref="searchInput"
class="inputElement"
:placeholder="$t('User Playlists.SinglePlaylistView.Search for Videos')"
:show-clear-text-button="true"
:show-action-button="false"
:value="query"
:maxlength="255"
@input="(input) => updateQueryDebounce(input)"
@clear="updateQueryDebounce('')"
/>
</div>
</div>
</div>
</template>

View File

@ -40,12 +40,16 @@ export default defineComponent({
type: Boolean,
required: true,
},
playlistEnableShuffle: {
type: Boolean,
default: false,
}
},
emits: ['pause-player'],
data: function () {
return {
isLoading: true,
shuffleEnabled: false,
shuffleEnabled: this.playlistEnableShuffle,
loopEnabled: false,
reversePlaylist: false,
pauseOnCurrentVideo: false,
@ -213,6 +217,10 @@ export default defineComponent({
this.getPlaylistInfoWithDelay()
}
if (this.shuffleEnabled) {
this.shufflePlaylistItems()
}
if ('mediaSession' in navigator) {
navigator.mediaSession.setActionHandler('previoustrack', this.playPreviousVideo)
navigator.mediaSession.setActionHandler('nexttrack', this.playNextVideo)
@ -529,7 +537,6 @@ export default defineComponent({
items.push(remainingItems[randomInt])
remainingItems.splice(randomInt, 1)
}
this.randomizedPlaylistItems = items
},

View File

@ -26,7 +26,7 @@
:last-updated="lastUpdated"
:description="playlistDescription"
:video-count="videoCount"
:videos="playlistItems"
:videos="sortedPlaylistItems"
:view-count="viewCount"
:info-source="infoSource"
:more-video-data-available="moreVideoDataAvailable"

View File

@ -114,6 +114,7 @@ export default defineComponent({
playlistId: '',
playlistType: '',
playlistItemId: null,
playlistEnableShuffle: false,
/** @type {number|null} */
timestamp: null,
playNextTimeout: null,
@ -1129,6 +1130,7 @@ export default defineComponent({
this.playlistId = this.$route.query.playlistId
this.playlistItemId = this.$route.query.playlistItemId
this.playlistEnableShuffle = this.$route.query.playlistEnableShuffle === 'true'
if (this.playlistId == null || this.playlistId.length === 0) {
this.playlistType = ''

View File

@ -196,6 +196,7 @@
:playlist-type="playlistType"
:video-id="videoId"
:playlist-item-id="playlistItemId"
:playlist-enable-shuffle="playlistEnableShuffle"
class="watchVideoSideBar watchVideoPlaylist"
:class="{ theatrePlaylist: useTheatreMode }"
@pause-player="pausePlayer"

View File

@ -892,6 +892,8 @@ Playlist:
Playlist: Playlist
View Full Playlist: View Full Playlist
Last Updated On: Last Updated On
Play all: Play all
Shuffle: Shuffle
Sort By:
Sort By: Sort By
DateAddedNewest: Latest added first