Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add back favorites shortcut #4517

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/datastores/handlers/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ class Playlists {
static deleteVideoIdsByPlaylistId(_id, videoIds) {
return db.playlists.updateAsync(
{ _id },
{ $pull: { videos: { $in: videoIds } } },
{ $pull: { videos: { videoId: { $in: videoIds } } } },
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a fix?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is. But this function is not in use in your PR, it seems. You can add this fix as well.

{ upsert: true }
)
}
Expand Down
69 changes: 69 additions & 0 deletions src/renderer/components/ft-list-video/ft-list-video.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,24 @@ export default defineComponent({
return this.$route.name === 'history'
},

favoritesPlaylist: function () {
return this.$store.getters.getFavorites
},

inFavoritesPlaylist: function () {
return this.favoritesPlaylist.videos.some((video) =>
video.videoId === this.id
)
},

favoriteIconTheme: function () {
return this.inFavoritesPlaylist ? 'base favorite' : 'base'
},

favoritesText: function () {
return this.inFavoritesPlaylist ? this.$t('User Playlists.Unsave from Favorites') : this.$t('User Playlists.Save to Favorites')
},

inUserPlaylist: function () {
return this.playlistTypeFinal === 'user' || this.selectedUserPlaylist != null
},
Expand Down Expand Up @@ -729,8 +747,59 @@ export default defineComponent({
showToast(this.$t('Channel Unhidden', { channel: channelName }))
},

toggleSaveToFavorites: function () {
if (this.inFavoritesPlaylist) {
this.removeFromFavorites()
} else {
this.addToFavorites()
}
},

addToFavorites: function () {
const videoData = {
videoId: this.id,
title: this.title,
author: this.channelName,
authorId: this.channelId,
description: this.description,
viewCount: this.viewCount,
lengthSeconds: this.data.lengthSeconds,
}

const payload = {
_id: 'favorites',
videoData: videoData
}

this.addVideo(payload)
// Update playlist's `lastUpdatedAt`
this.updatePlaylist({ _id: 'favorites' })

showToast(this.$t('Video.Video has been saved'))
},

removeFromFavorites: function () {
const payload = {
_id: 'favorites',
videoIds: [this.id]
}

try {
this.removeVideos(payload)
// Update playlist's `lastUpdatedAt`
this.updatePlaylist({ _id: 'favorites' })
showToast(this.$t('Video.Video has been removed from your saved list'))
} catch (e) {
showToast(this.$t('User Playlists.SinglePlaylistView.Toast.There was a problem with removing this video'))
console.error(e)
}
},

...mapActions([
'openInExternalPlayer',
'addVideo',
'removeVideos',
'updatePlaylist',
'updateHistory',
'removeFromHistory',
'updateChannelsHidden',
Expand Down
22 changes: 20 additions & 2 deletions src/renderer/components/ft-list-video/ft-list-video.vue
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,32 @@
:size="appearance === `watchPlaylistItem` ? 12 : 16"
@click="handleExternalPlayer"
/>
<span class="playlistIcons">
<span
class="playlistIcons"
:class="{ inUserPlaylist }"
>
<ft-icon-button
v-if="!isUpcoming && playlistId !== 'favorites'"
:title="favoritesText"
:icon="['fas', 'star']"
class="favoritesIcon"
:class="{
alwaysVisible: alwaysShowAddToPlaylistButton || favoriteIconTheme === 'base favorite'
}"
:theme="favoriteIconTheme"
:padding="appearance === `watchPlaylistItem` ? 5 : 6"
:size="appearance === `watchPlaylistItem` ? 14 : 18"
@click="toggleSaveToFavorites"
/>
<ft-icon-button
v-if="showPlaylists"
ref="addToPlaylistIcon"
:title="$t('User Playlists.Add to Playlist')"
:icon="['fas', 'plus']"
class="addToPlaylistIcon"
:class="alwaysShowAddToPlaylistButton ? 'alwaysVisible' : ''"
:class="{
alwaysVisible: alwaysShowAddToPlaylistButton || favoriteIconTheme === 'base favorite'
}"
:padding="appearance === `watchPlaylistItem` ? 5 : 6"
:size="appearance === `watchPlaylistItem` ? 14 : 18"
@click="togglePlaylistPrompt"
Expand Down
75 changes: 74 additions & 1 deletion src/renderer/components/watch-video-info/watch-video-info.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import FtCard from '../ft-card/ft-card.vue'
import FtIconButton from '../ft-icon-button/ft-icon-button.vue'
import FtShareButton from '../ft-share-button/ft-share-button.vue'
import FtSubscribeButton from '../ft-subscribe-button/ft-subscribe-button.vue'
import { formatNumber, openExternalLink } from '../../helpers/utils'
import { formatNumber, openExternalLink, showToast } from '../../helpers/utils'

export default defineComponent({
name: 'WatchVideoInfo',
Expand Down Expand Up @@ -125,6 +125,28 @@ export default defineComponent({
return this.$store.getters.getHideVideoViews
},

favoritesPlaylist: function () {
return this.$store.getters.getFavorites
},

inFavoritesPlaylist: function () {
return this.favoritesPlaylist.videos.some((video) =>
video.videoId === this.id
)
},

favoriteIconTheme: function () {
return this.inFavoritesPlaylist ? 'base favorite' : 'base'
},

favoritesText: function () {
return this.inFavoritesPlaylist ? this.$t('User Playlists.Unsave from Favorites') : this.$t('User Playlists.Save to Favorites')
},

inUserPlaylist: function () {
return this.playlistTypeFinal === 'user' || this.selectedUserPlaylist != null
},

showPlaylists: function () {
return !this.$store.getters.getHidePlaylists
},
Expand Down Expand Up @@ -311,7 +333,58 @@ export default defineComponent({
this.showAddToPlaylistPromptForManyVideos({ videos: [videoData] })
},

toggleSaveToFavorites: function () {
if (this.inFavoritesPlaylist) {
this.removeFromFavorites()
} else {
this.addToFavorites()
}
},

addToFavorites: function () {
const videoData = {
videoId: this.id,
title: this.title,
author: this.channelName,
authorId: this.channelId,
description: this.description,
viewCount: this.viewCount,
lengthSeconds: this.lengthSeconds,
}

const payload = {
_id: 'favorites',
videoData: videoData
}

this.addVideo(payload)
// Update playlist's `lastUpdatedAt`
this.updatePlaylist({ _id: 'favorites' })

showToast(this.$t('Video.Video has been saved'))
},

removeFromFavorites: function () {
const payload = {
_id: 'favorites',
videoIds: [this.id]
}

try {
this.removeVideos(payload)
// Update playlist's `lastUpdatedAt`
this.updatePlaylist({ _id: 'favorites' })
showToast(this.$t('Video.Video has been removed from your saved list'))
} catch (e) {
showToast(this.$t('User Playlists.SinglePlaylistView.Toast.There was a problem with removing this video'))
console.error(e)
}
},

...mapActions([
'addVideo',
'removeVideos',
'updatePlaylist',
'openInExternalPlayer',
'downloadMedia',
'showAddToPlaylistPromptForManyVideos',
Expand Down
8 changes: 8 additions & 0 deletions src/renderer/components/watch-video-info/watch-video-info.vue
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,14 @@
</div>
-->
<div class="videoOptions">
<ft-icon-button
v-if="!isUpcoming"
:title="favoritesText"
:icon="['fas', 'star']"
class="option"
:theme="favoriteIconTheme"
@click="toggleSaveToFavorites"
/>
<ft-icon-button
v-if="showPlaylists && !isUpcoming"
:title="$t('User Playlists.Add to Playlist')"
Expand Down
19 changes: 16 additions & 3 deletions src/renderer/scss-partials/_ft-list-item.scss
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,15 @@ $watched-transition-duration: 0.5s;
justify-content: flex-end;
block-size: fit-content;
}

.playlistIcons:not(.inUserPlaylist) {
grid-auto-flow: row;
justify-content: flex-start;
align-content: flex-start;
gap: 3px;
}

.favoritesIcon,
.addToPlaylistIcon,
.trashIcon,
.upArrowIcon,
Expand Down Expand Up @@ -353,24 +362,28 @@ $watched-transition-duration: 0.5s;
}

.playlistIcons,
.favoritesIcon,
.externalPlayerIcon {
opacity: $thumbnail-overlay-opacity;
}

@media (hover: hover) {
&:hover .addToPlaylistIcon:not(.alwaysVisible),
&:hover .favoritesIcon:not(.alwaysVisible),
&:hover .externalPlayerIcon,
&:focus-within .addToPlaylistIcon:not(.alwaysVisible),
&:focus-within .externalPlayerIcon {
&:has(:focus-visible) .addToPlaylistIcon:not(.alwaysVisible),
&:has(:focus-visible) .favoritesIcon:not(.alwaysVisible),
&:has(:focus-visible) .externalPlayerIcon {
opacity: $thumbnail-overlay-opacity;
}

&:hover .optionsButton,
&:focus-within .optionsButton {
&:has(:focus-visible) .optionsButton {
opacity: 1;
}

.addToPlaylistIcon:not(.alwaysVisible),
.favoritesIcon:not(.alwaysVisible),
.externalPlayerIcon,
.optionsButton {
opacity: 0;
Expand Down
39 changes: 5 additions & 34 deletions src/renderer/store/modules/playlists.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,18 @@ const state = {
defaultPlaylists: [
{
playlistName: 'Favorites',
protected: false,
protected: true,
description: 'Your favorite videos',
videos: [],
_id: 'favorites',
},
{
playlistName: 'Watch Later',
protected: false,
description: 'Videos to watch later',
videos: [],
_id: 'watchLater',
},
}
],
}

const getters = {
getPlaylistsReady: () => state.playlistsReady,
getAllPlaylists: () => state.playlists,
getFavorites: () => state.playlists.find(playlist => playlist._id === 'favorites'),
getPlaylist: (state) => (playlistId) => {
return state.playlists.find(playlist => playlist._id === playlistId)
},
Expand Down Expand Up @@ -253,9 +247,6 @@ const actions = {
const favoritesPlaylist = payload.find((playlist) => {
return playlist.playlistName === 'Favorites' || playlist._id === 'favorites'
})
const watchLaterPlaylist = payload.find((playlist) => {
return playlist.playlistName === 'Watch Later' || playlist._id === 'watchLater'
})

const defaultFavoritesPlaylist = state.defaultPlaylists.find((e) => e._id === 'favorites')
if (favoritesPlaylist != null) {
Expand All @@ -277,26 +268,6 @@ const actions = {
}
}

const defaultWatchLaterPlaylist = state.defaultPlaylists.find((e) => e._id === 'watchLater')
if (watchLaterPlaylist != null) {
// Update existing matching playlist only if it exists
if (watchLaterPlaylist._id !== defaultWatchLaterPlaylist._id || watchLaterPlaylist.protected !== defaultWatchLaterPlaylist.protected) {
const oldId = watchLaterPlaylist._id
watchLaterPlaylist._id = defaultWatchLaterPlaylist._id
watchLaterPlaylist.protected = defaultWatchLaterPlaylist.protected
if (oldId === defaultWatchLaterPlaylist._id) {
// Update playlist if ID already the same
DBPlaylistHandlers.upsert(watchLaterPlaylist)
} else {
dispatch('removePlaylist', oldId)
// DO NOT use dispatch('addPlaylist', ...)
// Which causes duplicate displayed playlist in window (But DB is fine)
// Due to the object is already in `payload`
DBPlaylistHandlers.create(watchLaterPlaylist)
}
}
}

commit('setAllPlaylists', payload)
}
commit('setPlaylistsReady', true)
Expand Down Expand Up @@ -417,9 +388,9 @@ const mutations = {
},

removeVideos(state, payload) {
const playlist = state.playlists.find(playlist => playlist._id === payload.playlistId)
const playlist = state.playlists.find(playlist => playlist._id === payload._id)
if (playlist) {
playlist.videos = playlist.videos.filter(video => payload.videoId.indexOf(video) === -1)
playlist.videos = playlist.videos.filter(video => !payload.videoIds.includes(video.videoId))
}
},

Expand Down
3 changes: 2 additions & 1 deletion static/locales/en-US.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ User Playlists:
Create New Playlist: Create New Playlist

Add to Playlist: Add to Playlist
Save to Favorites: Save to Favorites
Unsave from Favorites: Unsave from Favorites
Move Video Up: Move Video Up
Move Video Down: Move Video Down
Remove from Playlist: Remove from Playlist
Expand Down Expand Up @@ -707,7 +709,6 @@ Video:
Remove From History: Remove From History
Video has been marked as watched: Video has been marked as watched
Video has been removed from your history: Video has been removed from your history
Save Video: Save Video
Video has been saved: Video has been saved
Video has been removed from your saved list: Video has been removed from your saved list
Open in YouTube: Open in YouTube
Expand Down
Loading