Add Search Suggestions and Custom Invidious Instance
This commit is contained in:
parent
2b476f4dc6
commit
c8da6fec3d
|
@ -12940,6 +12940,11 @@
|
|||
"resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz",
|
||||
"integrity": "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU="
|
||||
},
|
||||
"lodash.debounce": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
|
||||
"integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168="
|
||||
},
|
||||
"lodash.defaults": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
|
||||
|
@ -16268,8 +16273,7 @@
|
|||
},
|
||||
"minimist": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
|
||||
"resolved": "",
|
||||
"dev": true
|
||||
},
|
||||
"schema-utils": {
|
||||
|
@ -18870,8 +18874,7 @@
|
|||
},
|
||||
"minimist": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
|
||||
"resolved": "",
|
||||
"dev": true
|
||||
},
|
||||
"string-width": {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
"dateformat": "^3.0.3",
|
||||
"electron-context-menu": "^2.0.1",
|
||||
"jquery": "^3.5.1",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"material-design-icons": "^3.0.1",
|
||||
"mediaelement": "^4.2.16",
|
||||
|
|
|
@ -22,27 +22,35 @@
|
|||
color: var(--tertiary-text-color);
|
||||
}
|
||||
|
||||
.search .ft-input {
|
||||
.forceTextColor .ft-input {
|
||||
color: var(--text-with-main-color);
|
||||
border-bottom: 1px solid var(--text-with-main-color);
|
||||
}
|
||||
|
||||
.search ::-webkit-input-placeholder {
|
||||
.forceTextColor ::-webkit-input-placeholder {
|
||||
color: var(--text-with-main-color);
|
||||
}
|
||||
|
||||
.inputAction {
|
||||
position: absolute;
|
||||
padding: 10px;
|
||||
top: 10px;
|
||||
top: 5px;
|
||||
right: 0px;
|
||||
cursor: pointer;
|
||||
border-radius: 200px 200px 200px 200px;
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
|
||||
.search ::-webkit-calendar-picker-indicator {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.search .inputAction {
|
||||
color: var(--text-with-main-color)
|
||||
top: 12px;
|
||||
}
|
||||
|
||||
.forceTextColor .inputAction {
|
||||
color: var(--text-with-main-color);
|
||||
}
|
||||
|
||||
.inputAction:hover {
|
||||
|
@ -52,7 +60,7 @@
|
|||
transition: background 0.2s ease-in;
|
||||
}
|
||||
|
||||
.search .inputAction:hover {
|
||||
.forceTextColor .inputAction:hover {
|
||||
background-color: var(--primary-color-hover);
|
||||
}
|
||||
|
||||
|
@ -63,6 +71,6 @@
|
|||
transition: background 0.2s ease-in;
|
||||
}
|
||||
|
||||
.search .inputAction:active {
|
||||
.forceTextColor .inputAction:active {
|
||||
background-color: var(--primary-color-active);
|
||||
}
|
||||
|
|
|
@ -7,14 +7,26 @@ export default Vue.extend({
|
|||
type: String,
|
||||
required: true
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
showArrow: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
showLabel: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
isSearch: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
dataList: {
|
||||
type: Array,
|
||||
default: () => { return [] }
|
||||
},
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
|
@ -29,6 +41,10 @@ export default Vue.extend({
|
|||
|
||||
forceTextColor: function () {
|
||||
return this.isSearch && this.barColor
|
||||
},
|
||||
|
||||
idDataList: function () {
|
||||
return `${this.id}_datalist`
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
|
@ -41,6 +57,11 @@ export default Vue.extend({
|
|||
this.$emit('click', this.inputData)
|
||||
},
|
||||
|
||||
handleInput: function (input) {
|
||||
this.inputData = input
|
||||
this.$emit('input', input)
|
||||
},
|
||||
|
||||
addListener: function () {
|
||||
const inputElement = document.getElementById(this.id)
|
||||
|
||||
|
|
|
@ -1,14 +1,25 @@
|
|||
<template>
|
||||
<div
|
||||
class="ft-input-component"
|
||||
:class="{ search: forceTextColor }"
|
||||
:class="{
|
||||
search: isSearch,
|
||||
forceTextColor: forceTextColor
|
||||
}"
|
||||
>
|
||||
<label
|
||||
v-if="showLabel"
|
||||
:for="id"
|
||||
>
|
||||
{{ placeholder }}
|
||||
</label>
|
||||
<input
|
||||
:id="id"
|
||||
:list="idDataList"
|
||||
:value="value"
|
||||
class="ft-input"
|
||||
type="text"
|
||||
:placeholder="placeholder"
|
||||
@input="e => inputData = e.target.value"
|
||||
@input="e => handleInput(e.target.value)"
|
||||
>
|
||||
<font-awesome-icon
|
||||
v-if="showArrow"
|
||||
|
@ -16,6 +27,16 @@
|
|||
class="inputAction"
|
||||
@click="handleClick"
|
||||
/>
|
||||
<datalist
|
||||
v-if="dataList.length > 0"
|
||||
:id="idDataList"
|
||||
>
|
||||
<option
|
||||
v-for="(list, index) in dataList"
|
||||
:key="index"
|
||||
:value="list"
|
||||
/>
|
||||
</datalist>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -3,14 +3,18 @@ import $ from 'jquery'
|
|||
import { mapActions } from 'vuex'
|
||||
import FtCard from '../ft-card/ft-card.vue'
|
||||
import FtSelect from '../ft-select/ft-select.vue'
|
||||
import FtInput from '../ft-input/ft-input.vue'
|
||||
import FtToggleSwitch from '../ft-toggle-switch/ft-toggle-switch.vue'
|
||||
import FtFlexBox from '../ft-flex-box/ft-flex-box.vue'
|
||||
|
||||
import debounce from 'lodash.debounce'
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'GeneralSettings',
|
||||
components: {
|
||||
'ft-card': FtCard,
|
||||
'ft-select': FtSelect,
|
||||
'ft-input': FtInput,
|
||||
'ft-toggle-switch': FtToggleSwitch,
|
||||
'ft-flex-box': FtFlexBox
|
||||
},
|
||||
|
@ -597,8 +601,20 @@ export default Vue.extend({
|
|||
console.log(requestUrl)
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
this.updateInvidiousInstanceBounce = debounce(this.updateInvidiousInstance, 500)
|
||||
},
|
||||
beforeDestroy: function () {
|
||||
if (this.invidiousInstance === '') {
|
||||
this.updateInvidiousInstance('https://invidio.us')
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleInvidiousInstanceInput: function (input) {
|
||||
const invidiousInstance = input.replace(/\/$/, '')
|
||||
this.updateInvidiousInstanceBounce(invidiousInstance)
|
||||
},
|
||||
|
||||
...mapActions([
|
||||
'updateBackendFallback',
|
||||
'updateCheckForUpdates',
|
||||
|
|
|
@ -57,15 +57,17 @@
|
|||
:select-values="thumbnailTypeValues"
|
||||
@change="updateThumbnailPreference"
|
||||
/>
|
||||
<ft-select
|
||||
v-if="showInvidiousInstances"
|
||||
placeholder="Invidious Instance"
|
||||
:value="invidiousInstance"
|
||||
:select-names="instanceNames"
|
||||
:select-values="instanceValues"
|
||||
@change="updateInvidiousInstance"
|
||||
/>
|
||||
</div>
|
||||
<ft-flex-box class="generalSettingsFlexBox">
|
||||
<ft-input
|
||||
placeholder="Invidious Instance (Default is https://invidio.us)"
|
||||
:show-arrow="false"
|
||||
:show-label="true"
|
||||
:value="invidiousInstance"
|
||||
:data-list="instanceValues"
|
||||
@input="handleInvidiousInstanceInput"
|
||||
/>
|
||||
</ft-flex-box>
|
||||
</ft-card>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@ import FtInput from '../ft-input/ft-input.vue'
|
|||
import FtSearchFilters from '../ft-search-filters/ft-search-filters.vue'
|
||||
import $ from 'jquery'
|
||||
import router from '../../router/index.js'
|
||||
import debounce from 'lodash.debounce'
|
||||
import ytSuggest from 'youtube-suggest'
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'TopNav',
|
||||
|
@ -14,7 +16,9 @@ export default Vue.extend({
|
|||
return {
|
||||
component: this,
|
||||
windowWidth: 0,
|
||||
showFilters: false
|
||||
showFilters: false,
|
||||
searchValue: '',
|
||||
searchSuggestionsDataList: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -28,7 +32,19 @@ export default Vue.extend({
|
|||
|
||||
barColor: function () {
|
||||
return this.$store.getters.getBarColor
|
||||
}
|
||||
},
|
||||
|
||||
invidiousInstance: function () {
|
||||
return this.$store.getters.getInvidiousInstance
|
||||
},
|
||||
|
||||
backendFallback: function () {
|
||||
return this.$store.getters.getBackendFallback
|
||||
},
|
||||
|
||||
backendPreference: function () {
|
||||
return this.$store.getters.getBackendPreference
|
||||
},
|
||||
},
|
||||
mounted: function () {
|
||||
const appWidth = $(window).width()
|
||||
|
@ -48,6 +64,8 @@ export default Vue.extend({
|
|||
searchContainer.style.display = 'none'
|
||||
}
|
||||
})
|
||||
|
||||
this.debounceSearchResults = debounce(this.getSearchSuggestions, 500)
|
||||
},
|
||||
methods: {
|
||||
goToSearch: function (query) {
|
||||
|
@ -84,6 +102,55 @@ export default Vue.extend({
|
|||
this.showFilters = false
|
||||
},
|
||||
|
||||
getSearchSuggestionsDebounce: function (query) {
|
||||
this.debounceSearchResults(query)
|
||||
},
|
||||
|
||||
getSearchSuggestions: function (query) {
|
||||
switch (this.backendPreference) {
|
||||
case 'local':
|
||||
this.getSearchSuggestionsLocal(query)
|
||||
break
|
||||
case 'invidious':
|
||||
this.getSearchSuggestionsInvidious(query)
|
||||
break
|
||||
}
|
||||
},
|
||||
|
||||
getSearchSuggestionsLocal: function (query) {
|
||||
if (query === '') {
|
||||
this.searchSuggestionsDataList = []
|
||||
this.searchValue = ''
|
||||
return
|
||||
}
|
||||
|
||||
ytSuggest(query).then((results) => {
|
||||
this.searchSuggestionsDataList = results
|
||||
this.searchValue = query
|
||||
})
|
||||
},
|
||||
|
||||
getSearchSuggestionsInvidious: function (query) {
|
||||
if (query === '') {
|
||||
this.searchSuggestionsDataList = []
|
||||
this.searchValue = ''
|
||||
return
|
||||
}
|
||||
|
||||
const searchPayload = {
|
||||
resource: 'search/suggestions',
|
||||
id: '',
|
||||
params: {
|
||||
q: query
|
||||
}
|
||||
}
|
||||
|
||||
this.$store.dispatch('invidiousAPICall', searchPayload).then((results) => {
|
||||
this.searchSuggestionsDataList = results.suggestions
|
||||
this.searchValue = query
|
||||
})
|
||||
},
|
||||
|
||||
toggleSearchContainer: function () {
|
||||
const searchContainer = $('.searchContainer').get(0)
|
||||
|
||||
|
|
|
@ -39,6 +39,9 @@
|
|||
placeholder="Search / Go to URL"
|
||||
class="searchInput"
|
||||
:is-search="true"
|
||||
:data-list="searchSuggestionsDataList"
|
||||
:value="searchValue"
|
||||
@input="getSearchSuggestionsDebounce"
|
||||
@click="goToSearch"
|
||||
/>
|
||||
<font-awesome-icon
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
.channelInformation {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
width: 300px;
|
||||
width: 350px;
|
||||
}
|
||||
|
||||
.channelThumbnail {
|
||||
|
|
|
@ -150,14 +150,18 @@ const getters = {
|
|||
}
|
||||
|
||||
const actions = {
|
||||
grabUserSettings ({ commit }) {
|
||||
grabUserSettings ({ dispatch, commit }) {
|
||||
settingsDb.find({}, (err, results) => {
|
||||
if (!err) {
|
||||
console.log(results)
|
||||
results.forEach((result) => {
|
||||
switch (result._id) {
|
||||
case 'invidiousInstance':
|
||||
if (result.value === '') {
|
||||
dispatch('updateInvidiousInstance', 'https://invidio.us')
|
||||
} else {
|
||||
commit('setInvidiousInstance', result.value)
|
||||
}
|
||||
break
|
||||
case 'backendFallback':
|
||||
commit('setBackendFallback', result.value)
|
||||
|
|
|
@ -137,6 +137,7 @@ export default Vue.extend({
|
|||
this.videoId = this.$route.params.id
|
||||
|
||||
this.firstLoad = true
|
||||
this.activeFormat = this.defaultVideoFormat
|
||||
|
||||
this.checkIfPlaylist()
|
||||
|
||||
|
@ -206,6 +207,16 @@ export default Vue.extend({
|
|||
this.videoDislikeCount = result.dislikes
|
||||
this.isLive = result.player_response.videoDetails.isLive
|
||||
|
||||
const subCount = result.author.subscriber_count
|
||||
|
||||
if (subCount >= 1000000) {
|
||||
this.channelSubscriptionCountText = `${subCount / 1000000}M`
|
||||
} else if (subCount >= 10000) {
|
||||
this.channelSubscriptionCountText = `${subCount / 1000}K`
|
||||
} else {
|
||||
this.channelSubscriptionCountText = subCount.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
|
||||
}
|
||||
|
||||
if (this.isLive) {
|
||||
this.showLegacyPlayer = true
|
||||
this.showDashPlayer = false
|
||||
|
|
Loading…
Reference in New Issue