Simplify playlist / history search and add video stats string for legacy videos

This commit is contained in:
Preston 2022-02-19 21:32:34 -05:00
parent 222c41c863
commit dbf69f242a
15 changed files with 154 additions and 125 deletions

View File

@ -36,8 +36,7 @@ const DBActions = {
}, },
HISTORY: { HISTORY: {
UPDATE_WATCH_PROGRESS: 'db-action-history-update-watch-progress', UPDATE_WATCH_PROGRESS: 'db-action-history-update-watch-progress'
SEARCH: 'db-action-history-search'
}, },
PLAYLISTS: { PLAYLISTS: {

View File

@ -38,11 +38,6 @@ class History {
return db.history.find({}).sort({ timeWatched: -1 }) return db.history.find({}).sort({ timeWatched: -1 })
} }
static search(query) {
const re = new RegExp(query, 'i')
return db.history.find({ $or: [{ author: { $regex: re } }, { title: { $regex: re } }] }).sort({ timeWatched: -1 })
}
static upsert(record) { static upsert(record) {
return db.history.update({ videoId: record.videoId }, record, { upsert: true }) return db.history.update({ videoId: record.videoId }, record, { upsert: true })
} }

View File

@ -25,13 +25,6 @@ class History {
) )
} }
static search(query) {
return ipcRenderer.invoke(
IpcChannels.DB_HISTORY,
{ action: DBActions.HISTORY.SEARCH, data: query }
)
}
static upsert(record) { static upsert(record) {
return ipcRenderer.invoke( return ipcRenderer.invoke(
IpcChannels.DB_HISTORY, IpcChannels.DB_HISTORY,

View File

@ -25,10 +25,6 @@ class History {
return baseHandlers.history.find() return baseHandlers.history.find()
} }
static search(query) {
return baseHandlers.history.search(query)
}
static upsert(record) { static upsert(record) {
return baseHandlers.history.upsert(record) return baseHandlers.history.upsert(record)
} }

View File

@ -18,7 +18,4 @@ db.profiles = Datastore.create({ filename: dbPath('profiles'), autoload: true })
db.playlists = Datastore.create({ filename: dbPath('playlists'), autoload: true }) db.playlists = Datastore.create({ filename: dbPath('playlists'), autoload: true })
db.history = Datastore.create({ filename: dbPath('history'), autoload: true }) db.history = Datastore.create({ filename: dbPath('history'), autoload: true })
db.history.ensureIndex({ fieldName: 'author' })
db.history.ensureIndex({ fieldName: 'title' })
export default db export default db

View File

@ -456,9 +456,6 @@ function runApp() {
) )
return null return null
case DBActions.HISTORY.SEARCH:
return await baseHandlers.history.search(data)
case DBActions.GENERAL.DELETE: case DBActions.GENERAL.DELETE:
await baseHandlers.history.delete(data) await baseHandlers.history.delete(data)
syncOtherWindows( syncOtherWindows(

View File

@ -208,12 +208,6 @@ export default Vue.extend({
return this.$store.getters.getSaveWatchedProgress return this.$store.getters.getSaveWatchedProgress
} }
}, },
watch: {
data: function () {
this.parseVideoData()
this.checkIfWatched()
}
},
mounted: function () { mounted: function () {
this.parseVideoData() this.parseVideoData()
this.checkIfWatched() this.checkIfWatched()

View File

@ -1414,7 +1414,7 @@ export default Vue.extend({
console.log(this.format) console.log(this.format)
if (this.format !== 'dash') { if (this.format !== 'dash') {
this.showToast({ this.showToast({
message: 'Video statistics are not available for legacy videos' message: this.$t('Video.Stats.Video statistics are not available for legacy videos')
}) })
} else { } else {
this.showStatsModal = !this.showStatsModal this.showStatsModal = !this.showStatsModal

View File

@ -1,16 +1,12 @@
import { DBHistoryHandlers } from '../../../datastores/handlers/index' import { DBHistoryHandlers } from '../../../datastores/handlers/index'
const state = { const state = {
historyCache: [], historyCache: []
searchHistoryCache: []
} }
const getters = { const getters = {
getHistoryCache: () => { getHistoryCache: () => {
return state.historyCache return state.historyCache
},
getSearchHistoryCache: () => {
return state.searchHistoryCache
} }
} }
@ -51,15 +47,6 @@ const actions = {
} }
}, },
async searchHistory({ commit }, query) {
try {
const results = await DBHistoryHandlers.search(query)
commit('setSearchHistoryCache', results)
} catch (errMessage) {
console.error(errMessage)
}
},
async updateWatchProgress({ commit }, { videoId, watchProgress }) { async updateWatchProgress({ commit }, { videoId, watchProgress }) {
try { try {
await DBHistoryHandlers.updateWatchProgress(videoId, watchProgress) await DBHistoryHandlers.updateWatchProgress(videoId, watchProgress)
@ -79,10 +66,6 @@ const mutations = {
state.historyCache = historyCache state.historyCache = historyCache
}, },
setSearchHistoryCache(state, result) {
state.searchHistoryCache = result
},
hoistEntryToTopOfHistoryCache(state, { currentIndex, updatedEntry }) { hoistEntryToTopOfHistoryCache(state, { currentIndex, updatedEntry }) {
state.historyCache.splice(currentIndex, 1) state.historyCache.splice(currentIndex, 1)
state.historyCache.unshift(updatedEntry) state.historyCache.unshift(updatedEntry)

View File

@ -13,20 +13,14 @@ const state = {
removeOnWatched: true, removeOnWatched: true,
videos: [] videos: []
} }
], ]
searchPlaylistCache: {
videos: []
}
} }
const getters = { const getters = {
getAllPlaylists: () => state.playlists, getAllPlaylists: () => state.playlists,
getFavorites: () => state.playlists[0], getFavorites: () => state.playlists[0],
getPlaylist: (playlistId) => state.playlists.find(playlist => playlist._id === playlistId), getPlaylist: (playlistId) => state.playlists.find(playlist => playlist._id === playlistId),
getWatchLater: () => state.playlists[1], getWatchLater: () => state.playlists[1]
getSearchPlaylistCache: () => {
return state.searchPlaylistCache
}
} }
const actions = { const actions = {
@ -136,25 +130,10 @@ const actions = {
} catch (errMessage) { } catch (errMessage) {
console.error(errMessage) console.error(errMessage)
} }
},
async searchFavoritePlaylist({ commit }, query) {
const re = new RegExp(query, 'i')
// filtering in the frontend because the documents are the playlists and not the videos
const results = state.playlists[0].videos.slice()
.filter((video) => {
return video.author.match(re) ||
video.title.match(re)
})
commit('setPlaylistCache', results)
} }
} }
const mutations = { const mutations = {
setPlaylistCache(state, result) {
state.searchPlaylistCache = {
videos: result
}
},
addPlaylist(state, payload) { addPlaylist(state, payload) {
state.playlists.push(payload) state.playlists.push(payload)
}, },

View File

@ -20,19 +20,19 @@ export default Vue.extend({
return { return {
isLoading: false, isLoading: false,
dataLimit: 100, dataLimit: 100,
hasQuery: false searchDataLimit: 100,
showLoadMoreButton: false,
hasQuery: false,
query: '',
activeData: []
} }
}, },
computed: { computed: {
historyCache: function () { historyCache: function () {
if (!this.hasQuery) { return this.$store.getters.getHistoryCache
return this.$store.getters.getHistoryCache
} else {
return this.$store.getters.getSearchHistoryCache
}
}, },
activeData: function () { fullData: function () {
if (this.historyCache.length < this.dataLimit) { if (this.historyCache.length < this.dataLimit) {
return this.historyCache return this.historyCache
} else { } else {
@ -40,30 +40,79 @@ export default Vue.extend({
} }
} }
}, },
watch: {
query() {
this.searchDataLimit = 100
this.filterHistory()
},
activeData() {
this.refreshPage()
},
fullData() {
this.activeData = this.fullData
this.filterHistory()
}
},
mounted: function () { mounted: function () {
console.log(this.historyCache)
const limit = sessionStorage.getItem('historyLimit') const limit = sessionStorage.getItem('historyLimit')
if (limit !== null) { if (limit !== null) {
this.dataLimit = limit this.dataLimit = limit
} }
this.activeData = this.fullData
if (this.activeData.length < this.historyCache.length) {
this.showLoadMoreButton = true
} else {
this.showLoadMoreButton = false
}
}, },
methods: { methods: {
increaseLimit: function () { increaseLimit: function () {
this.dataLimit += 100 if (this.query !== '') {
sessionStorage.setItem('historyLimit', this.dataLimit) this.searchDataLimit += 100
this.filterHistory()
} else {
this.dataLimit += 100
sessionStorage.setItem('historyLimit', this.dataLimit)
}
}, },
filterHistory: function(query) { filterHistory: function(query) {
this.hasQuery = query !== '' if (this.query === '') {
this.$store.dispatch('searchHistory', query) this.activeData = this.fullData
if (this.activeData.length < this.historyCache.length) {
this.showLoadMoreButton = true
} else {
this.showLoadMoreButton = false
}
} else {
const filteredQuery = this.historyCache.filter((video) => {
if (typeof (video.title) !== 'string' || typeof (video.author) !== 'string') {
return false
} else {
return video.title.toLowerCase().includes(this.query.toLowerCase()) || video.author.toLowerCase().includes(this.query.toLowerCase())
}
}).sort((a, b) => {
return b.timeWatched - a.timeWatched
})
if (filteredQuery.length <= this.searchDataLimit) {
this.showLoadMoreButton = false
} else {
this.showLoadMoreButton = true
}
this.activeData = filteredQuery.length < this.searchDataLimit ? filteredQuery : filteredQuery.slice(0, this.searchDataLimit)
}
}, },
load: function() { refreshPage: function() {
const scrollPos = window.scrollY || window.scrollTop || document.getElementsByTagName('html')[0].scrollTop
this.isLoading = true this.isLoading = true
setTimeout(() => { Vue.nextTick(() => {
this.isLoading = false this.isLoading = false
}, 100) Vue.nextTick(() => {
window.scrollTo(0, scrollPos)
})
})
} }
} }
}) })

View File

@ -1,11 +1,11 @@
<template> <template>
<div> <div>
<ft-loader <ft-loader
v-if="isLoading" v-show="isLoading"
:fullscreen="true" :fullscreen="true"
/> />
<ft-card <ft-card
v-else v-show="!isLoading"
class="card" class="card"
> >
<h3>{{ $t("History.History") }}</h3> <h3>{{ $t("History.History") }}</h3>
@ -14,21 +14,21 @@
:placeholder="$t('History.Search bar placeholder')" :placeholder="$t('History.Search bar placeholder')"
:show-clear-text-button="true" :show-clear-text-button="true"
:show-action-button="false" :show-action-button="false"
@input="filterHistory" @input="(input) => query = input"
/> />
<ft-flex-box <ft-flex-box
v-if="activeData.length === 0" v-show="activeData.length === 0"
> >
<p class="message"> <p class="message">
{{ $t("History['Your history list is currently empty.']") }} {{ $t("History['Your history list is currently empty.']") }}
</p> </p>
</ft-flex-box> </ft-flex-box>
<ft-element-list <ft-element-list
v-else v-if="activeData.length > 0 && !isLoading"
:data="activeData" :data="activeData"
/> />
<ft-flex-box <ft-flex-box
v-if="activeData.length < historyCache.length" v-if="showLoadMoreButton"
> >
<ft-button <ft-button
label="Load More" label="Load More"

View File

@ -22,19 +22,19 @@ export default Vue.extend({
return { return {
isLoading: false, isLoading: false,
dataLimit: 100, dataLimit: 100,
hasQuery: false searchDataLimit: 100,
showLoadMoreButton: false,
query: '',
hasQuery: false,
activeData: []
} }
}, },
computed: { computed: {
favoritesPlaylist: function () { favoritesPlaylist: function () {
if (!this.hasQuery) { return this.$store.getters.getFavorites
return this.$store.getters.getFavorites
} else {
return this.$store.getters.getSearchPlaylistCache
}
}, },
activeData: function () { fullData: function () {
const data = [].concat(this.favoritesPlaylist.videos).reverse() const data = [].concat(this.favoritesPlaylist.videos).reverse()
if (this.favoritesPlaylist.videos.length < this.dataLimit) { if (this.favoritesPlaylist.videos.length < this.dataLimit) {
return data return data
@ -44,7 +44,70 @@ export default Vue.extend({
} }
}, },
watch: { watch: {
query() {
this.searchDataLimit = 100
this.filterPlaylist()
},
activeData() { activeData() {
this.refreshPage()
},
fullData() {
this.activeData = this.fullData
this.filterPlaylist()
}
},
mounted: function () {
const limit = sessionStorage.getItem('favoritesLimit')
if (limit !== null) {
this.dataLimit = limit
}
if (this.activeData.length < this.favoritesPlaylist.videos.length) {
this.showLoadMoreButton = true
} else {
this.showLoadMoreButton = false
}
this.activeData = this.fullData
},
methods: {
increaseLimit: function () {
if (this.query !== '') {
this.searchDataLimit += 100
this.filterPlaylist()
} else {
this.dataLimit += 100
sessionStorage.setItem('favoritesLimit', this.dataLimit)
}
},
filterPlaylist: function() {
if (this.query === '') {
this.activeData = this.fullData
if (this.activeData.length < this.favoritesPlaylist.videos.length) {
this.showLoadMoreButton = true
} else {
this.showLoadMoreButton = false
}
} else {
const filteredQuery = this.favoritesPlaylist.videos.filter((video) => {
if (typeof (video.title) !== 'string' || typeof (video.author) !== 'string') {
return false
} else {
return video.title.toLowerCase().includes(this.query.toLowerCase()) || video.author.toLowerCase().includes(this.query.toLowerCase())
}
}).sort((a, b) => {
return b.timeAdded - a.timeAdded
})
if (filteredQuery.length <= this.searchDataLimit) {
this.showLoadMoreButton = false
} else {
this.showLoadMoreButton = true
}
this.activeData = filteredQuery.length < this.searchDataLimit ? filteredQuery : filteredQuery.slice(0, this.searchDataLimit)
}
},
refreshPage: function() {
const scrollPos = window.scrollY || window.scrollTop || document.getElementsByTagName('html')[0].scrollTop const scrollPos = window.scrollY || window.scrollTop || document.getElementsByTagName('html')[0].scrollTop
this.isLoading = true this.isLoading = true
Vue.nextTick(() => { Vue.nextTick(() => {
@ -54,22 +117,5 @@ export default Vue.extend({
}) })
}) })
} }
},
mounted: function () {
const limit = sessionStorage.getItem('favoritesLimit')
if (limit !== null) {
this.dataLimit = limit
}
},
methods: {
increaseLimit: function () {
this.dataLimit += 100
sessionStorage.setItem('favoritesLimit', this.dataLimit)
},
filterPlaylist: function(query) {
this.hasQuery = query !== ''
this.$store.dispatch('searchFavoritePlaylist', query)
}
} }
}) })

View File

@ -1,11 +1,11 @@
<template> <template>
<div> <div>
<ft-loader <ft-loader
v-if="isLoading" v-show="isLoading"
:fullscreen="true" :fullscreen="true"
/> />
<ft-card <ft-card
v-else v-show="!isLoading"
class="card" class="card"
> >
<h3> <h3>
@ -21,21 +21,21 @@
:placeholder="$t('User Playlists.Search bar placeholder')" :placeholder="$t('User Playlists.Search bar placeholder')"
:show-clear-text-button="true" :show-clear-text-button="true"
:show-action-button="false" :show-action-button="false"
@input="filterPlaylist" @input="(input) => query = input"
/> />
<ft-flex-box <ft-flex-box
v-if="activeData.length === 0" v-show="activeData.length === 0"
> >
<p class="message"> <p class="message">
{{ $t("User Playlists['Your saved videos are empty. Click on the save button on the corner of a video to have it listed here']") }} {{ $t("User Playlists['Your saved videos are empty. Click on the save button on the corner of a video to have it listed here']") }}
</p> </p>
</ft-flex-box> </ft-flex-box>
<ft-element-list <ft-element-list
v-else v-if="activeData.length > 0 && !isLoading"
:data="activeData" :data="activeData"
/> />
<ft-flex-box <ft-flex-box
v-if="activeData.length < favoritesPlaylist.videos.length" v-if="showLoadMoreButton"
> >
<ft-button <ft-button
label="Load More" label="Load More"

View File

@ -556,6 +556,7 @@ Video:
shuffling playlists: shuffling playlists shuffling playlists: shuffling playlists
looping playlists: looping playlists looping playlists: looping playlists
Stats: Stats:
Video statistics are not available for legacy videos: Video statistics are not available for legacy videos
Video ID: Video ID Video ID: Video ID
Resolution: Resolution Resolution: Resolution
Player Dimensions: Player Dimensions Player Dimensions: Player Dimensions