Finish Core Subscriptions logic and add more locales to profiles page
This commit is contained in:
parent
1e035105d1
commit
8f35f95a5b
|
@ -11136,6 +11136,14 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"javascript-time-ago": {
|
||||
"version": "2.0.13",
|
||||
"resolved": "https://registry.npmjs.org/javascript-time-ago/-/javascript-time-ago-2.0.13.tgz",
|
||||
"integrity": "sha512-zH+obXUQ4vlc9UlERFe637rNJQaVYLizwODUfGzYN/cNW/owkk5wzb327gAfEXFpI4yhFcStEaoqoJtMGAmrAg==",
|
||||
"requires": {
|
||||
"relative-time-format": "^0.1.3"
|
||||
}
|
||||
},
|
||||
"jest": {
|
||||
"version": "26.4.2",
|
||||
"resolved": "https://registry.npmjs.org/jest/-/jest-26.4.2.tgz",
|
||||
|
@ -16240,6 +16248,11 @@
|
|||
"integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=",
|
||||
"dev": true
|
||||
},
|
||||
"relative-time-format": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/relative-time-format/-/relative-time-format-0.1.3.tgz",
|
||||
"integrity": "sha512-0O6i4fKjsx8qhz57zorG+LrIDnF9pSvP5s7H9R1Nb5nSqih5dvRyKzNKs6MxhL3bv4iwsz4DuDwAyw+c47QFIA=="
|
||||
},
|
||||
"remove-trailing-separator": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
|
||||
|
@ -16522,6 +16535,31 @@
|
|||
"sprintf-js": "^1.1.2"
|
||||
}
|
||||
},
|
||||
"rss-parser": {
|
||||
"version": "3.9.0",
|
||||
"resolved": "https://registry.npmjs.org/rss-parser/-/rss-parser-3.9.0.tgz",
|
||||
"integrity": "sha512-wlRSfGrotOXuWo19Dtl2KmQt7o9i5zzCExUrxpechE0O54BAx7JD+xhWyGumPPqiJj771ndflV3sE3bTHen0HQ==",
|
||||
"requires": {
|
||||
"entities": "^2.0.3",
|
||||
"xml2js": "^0.4.19"
|
||||
},
|
||||
"dependencies": {
|
||||
"entities": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz",
|
||||
"integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"rss-to-json": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/rss-to-json/-/rss-to-json-1.1.1.tgz",
|
||||
"integrity": "sha512-d+TwrFI5wAHbZ/fTd3Pvty14tadBjKHAjfMcUam9FWoWrC9g5rHJN9Slw10OZwk6Mey+hqdXwdmymO7d8ebVmw==",
|
||||
"requires": {
|
||||
"axios": "^0.19.2",
|
||||
"xml2json": "^0.12.0"
|
||||
}
|
||||
},
|
||||
"rsvp": {
|
||||
"version": "4.8.5",
|
||||
"resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz",
|
||||
|
@ -20249,6 +20287,15 @@
|
|||
"integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==",
|
||||
"dev": true
|
||||
},
|
||||
"xml2js": {
|
||||
"version": "0.4.23",
|
||||
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz",
|
||||
"integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==",
|
||||
"requires": {
|
||||
"sax": ">=0.6.0",
|
||||
"xmlbuilder": "~11.0.0"
|
||||
}
|
||||
},
|
||||
"xml2json": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/xml2json/-/xml2json-0.12.0.tgz",
|
||||
|
@ -20259,6 +20306,11 @@
|
|||
"node-expat": "^2.3.18"
|
||||
}
|
||||
},
|
||||
"xmlbuilder": {
|
||||
"version": "11.0.1",
|
||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
|
||||
"integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="
|
||||
},
|
||||
"xmlchars": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
"mediaelement": "^4.2.16",
|
||||
"nedb": "^1.8.0",
|
||||
"opml-to-json": "0.0.3",
|
||||
"rss-parser": "^3.9.0",
|
||||
"video.js": "7.6.6",
|
||||
"videojs-abloop": "^1.1.2",
|
||||
"videojs-contrib-quality-levels": "^2.0.9",
|
||||
|
|
|
@ -255,7 +255,8 @@ export default Vue.extend({
|
|||
liveStreamString: this.$t('Video.Watching'),
|
||||
upcomingString: this.$t('Video.Published.Upcoming'),
|
||||
isLive: this.isLive,
|
||||
isUpcoming: this.data.isUpcoming
|
||||
isUpcoming: this.data.isUpcoming,
|
||||
isRSS: this.data.isRSS
|
||||
}).then((data) => {
|
||||
this.uploadedTime = data
|
||||
}).catch((error) => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.colorOption {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin: 10px;
|
||||
cursor: pointer;
|
||||
border-radius: 200px 200px 200px 200px;
|
||||
|
@ -8,10 +8,10 @@
|
|||
}
|
||||
|
||||
.initial {
|
||||
font-size: 25px;
|
||||
font-size: 20px;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
bottom: 27px;
|
||||
bottom: 30px;
|
||||
}
|
||||
|
||||
#profileList {
|
||||
|
@ -39,10 +39,18 @@
|
|||
|
||||
.profile {
|
||||
cursor: pointer;
|
||||
height: 50px;
|
||||
-webkit-transition: background 0.2s ease-out;
|
||||
-moz-transition: background 0.2s ease-out;
|
||||
-o-transition: background 0.2s ease-out;
|
||||
transition: background 0.2s ease-out;
|
||||
}
|
||||
|
||||
.profile:hover {
|
||||
background-color: var(--side-nav-hover-color);
|
||||
-moz-transition: background 0.2s ease-in;
|
||||
-o-transition: background 0.2s ease-in;
|
||||
transition: background 0.2s ease-in;
|
||||
}
|
||||
|
||||
.profile .colorOption {
|
||||
|
@ -51,6 +59,10 @@
|
|||
bottom: 5px;
|
||||
}
|
||||
|
||||
.profileName {
|
||||
line-height: 50px;
|
||||
}
|
||||
|
||||
.profileListTitle {
|
||||
position: absolute;
|
||||
top: -15px;
|
||||
|
|
|
@ -36,6 +36,16 @@ export default Vue.extend({
|
|||
}
|
||||
},
|
||||
mounted: function () {
|
||||
setTimeout(() => {
|
||||
const profileIndex = this.profileList.findIndex((profile) => {
|
||||
return profile._id === this.defaultProfile
|
||||
})
|
||||
|
||||
if (profileIndex !== -1) {
|
||||
this.updateActiveProfile(profileIndex)
|
||||
}
|
||||
}, 100)
|
||||
|
||||
$('#profileList').focusout(() => {
|
||||
$('#profileList')[0].style.display = 'none'
|
||||
})
|
||||
|
@ -65,8 +75,9 @@ export default Vue.extend({
|
|||
return
|
||||
}
|
||||
this.updateActiveProfile(index)
|
||||
const message = this.$t('Profile.$ is now the active profile').replace('$', profile.name)
|
||||
this.showToast({
|
||||
message: `${profile.name} is now the active profile`
|
||||
message: message
|
||||
})
|
||||
$('#profileList').focusout()
|
||||
},
|
||||
|
|
|
@ -44,7 +44,9 @@
|
|||
{{ profileInitials[index] }}
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
<p
|
||||
class="profileName"
|
||||
>
|
||||
{{ profile.name }}
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import Vue from 'vue'
|
||||
import { mapActions } from 'vuex'
|
||||
import FtCard from '../ft-card/ft-card.vue'
|
||||
import FtToggleSwitch from '../ft-toggle-switch/ft-toggle-switch.vue'
|
||||
import FtButton from '../ft-button/ft-button.vue'
|
||||
|
@ -27,9 +28,18 @@ export default Vue.extend({
|
|||
]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
goToChannel: function () {
|
||||
console.log('TODO: Handle goToChannel')
|
||||
computed: {
|
||||
hideWatchedSubs: function () {
|
||||
return this.$store.getters.getHideWatchedSubs
|
||||
},
|
||||
useRssFeeds: function () {
|
||||
return this.$store.getters.getUseRssFeeds
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions([
|
||||
'updateHideWatchedSubs',
|
||||
'updateUseRssFeeds'
|
||||
])
|
||||
}
|
||||
})
|
||||
|
|
|
@ -5,16 +5,24 @@
|
|||
<h3
|
||||
class="videoTitle"
|
||||
>
|
||||
{{ title }}
|
||||
{{ $t("Settings.Subscription Settings.Subscription Settings") }}
|
||||
</h3>
|
||||
<ft-flex-box class="subscriptionSettingsFlexBox">
|
||||
<ft-toggle-switch
|
||||
label="Hide Videos When Watched"
|
||||
:label="$t('Settings.Subscription Settings.Hide Videos on Watch')"
|
||||
:default-value="hideWatchedSubs"
|
||||
@change="updateHideWatchedSubs"
|
||||
/>
|
||||
<ft-toggle-switch
|
||||
:label="$t('Settings.Subscription Settings.Fetch Feeds from RSS')"
|
||||
:default-value="useRssFeeds"
|
||||
@change="updateUseRssFeeds"
|
||||
/>
|
||||
</ft-flex-box>
|
||||
<br>
|
||||
<ft-flex-box>
|
||||
<ft-select
|
||||
v-if="false"
|
||||
placeholder="Subscription View Type"
|
||||
:value="viewValues[0]"
|
||||
:select-names="viewNames"
|
||||
|
@ -24,6 +32,7 @@
|
|||
<br>
|
||||
<ft-flex-box>
|
||||
<ft-button
|
||||
v-if="false"
|
||||
label="Manage My Subscriptions"
|
||||
/>
|
||||
</ft-flex-box>
|
||||
|
|
|
@ -57,6 +57,7 @@ const state = {
|
|||
debugMode: false,
|
||||
disctractionFreeMode: false,
|
||||
hideWatchedSubs: false,
|
||||
useRssFeeds: false,
|
||||
usingElectron: true
|
||||
}
|
||||
|
||||
|
@ -157,13 +158,21 @@ const getters = {
|
|||
return state.defaultQuality
|
||||
},
|
||||
|
||||
getHideWatchedSubs: () => {
|
||||
return state.hideWatchedSubs
|
||||
},
|
||||
|
||||
getUseRssFeeds: () => {
|
||||
return state.useRssFeeds
|
||||
},
|
||||
|
||||
getUsingElectron: () => {
|
||||
return state.usingElectron
|
||||
}
|
||||
}
|
||||
|
||||
const actions = {
|
||||
grabUserSettings ({ dispatch, commit }) {
|
||||
grabUserSettings ({ dispatch, commit, rootState }) {
|
||||
settingsDb.find({}, (err, results) => {
|
||||
if (!err) {
|
||||
console.log(results)
|
||||
|
@ -206,6 +215,12 @@ const actions = {
|
|||
case 'barColor':
|
||||
commit('setBarColor', result.value)
|
||||
break
|
||||
case 'hideWatchedSubs':
|
||||
commit('setHideWatchedSubs', result.value)
|
||||
break
|
||||
case 'useRssFeeds':
|
||||
commit('setUseRssFeeds', result.value)
|
||||
break
|
||||
case 'rememberHistory':
|
||||
commit('setRememberHistory', result.value)
|
||||
break
|
||||
|
@ -341,6 +356,22 @@ const actions = {
|
|||
})
|
||||
},
|
||||
|
||||
updateHideWatchedSubs ({ commit }, hideWatchedSubs) {
|
||||
settingsDb.update({ _id: 'hideWatchedSubs' }, { _id: 'hideWatchedSubs', value: hideWatchedSubs }, { upsert: true }, (err, numReplaced) => {
|
||||
if (!err) {
|
||||
commit('setHideWatchedSubs', hideWatchedSubs)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
updateUseRssFeeds ({ commit }, useRssFeeds) {
|
||||
settingsDb.update({ _id: 'useRssFeeds' }, { _id: 'useRssFeeds', value: useRssFeeds }, { upsert: true }, (err, numReplaced) => {
|
||||
if (!err) {
|
||||
commit('setUseRssFeeds', useRssFeeds)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
updateRememberHistory ({ commit }, history) {
|
||||
settingsDb.update({ _id: 'rememberHistory' }, { _id: 'rememberHistory', value: history }, { upsert: true }, (err, numReplaced) => {
|
||||
if (!err) {
|
||||
|
@ -546,6 +577,9 @@ const mutations = {
|
|||
setHideWatchedSubs (state, hideWatchedSubs) {
|
||||
state.hideWatchedSubs = hideWatchedSubs
|
||||
},
|
||||
setUseRssFeeds (state, useRssFeeds) {
|
||||
state.useRssFeeds = useRssFeeds
|
||||
},
|
||||
setUsingElectron (state, usingElectron) {
|
||||
state.usingElectron = usingElectron
|
||||
},
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import ytch from 'yt-channel-info'
|
||||
|
||||
const state = {
|
||||
subscriptions: [],
|
||||
allSubscriptionsList: [],
|
||||
profileSubscriptions: {
|
||||
activeProfile: 0,
|
||||
videoList: []
|
||||
|
@ -9,8 +7,8 @@ const state = {
|
|||
}
|
||||
|
||||
const getters = {
|
||||
getSubscriptions: () => {
|
||||
return state.subscriptions
|
||||
getAllSubscriptionsList: () => {
|
||||
return state.allSubscriptionsList
|
||||
},
|
||||
getProfileSubscriptions: () => {
|
||||
return state.profileSubscriptions
|
||||
|
@ -18,8 +16,8 @@ const getters = {
|
|||
}
|
||||
|
||||
const actions = {
|
||||
updateSubscriptions ({ commit }, subscriptions) {
|
||||
commit('setSubscriptions', subscriptions)
|
||||
updateAllSubscriptionsList ({ commit }, subscriptions) {
|
||||
commit('setAllSubscriptionsList', subscriptions)
|
||||
},
|
||||
updateProfileSubscriptions ({ commit }, subscriptions) {
|
||||
commit('setProfileSubscriptions', subscriptions)
|
||||
|
@ -27,8 +25,8 @@ const actions = {
|
|||
}
|
||||
|
||||
const mutations = {
|
||||
setSubscriptions (state, subscriptions) {
|
||||
state.subscriptions = subscriptions
|
||||
setAllSubscriptionsList (state, allSubscriptionsList) {
|
||||
state.allSubscriptionsList = allSubscriptionsList
|
||||
},
|
||||
setProfileSubscriptions (state, profileSubscriptions) {
|
||||
state.profileSubscriptions = profileSubscriptions
|
||||
|
|
|
@ -265,6 +265,8 @@ const actions = {
|
|||
} else if (payload.isUpcoming || payload.publishText === null) {
|
||||
// the check for null is currently just an inferring of knowledge, because there is no other possibility left
|
||||
return payload.upcomingString
|
||||
} else if (payload.isRSS) {
|
||||
return payload.publishText
|
||||
}
|
||||
const strings = payload.publishText.split(' ')
|
||||
const singular = (strings[0] === '1')
|
||||
|
|
|
@ -63,7 +63,7 @@ export default Vue.extend({
|
|||
this.isLoading = true
|
||||
const profileType = this.$route.name
|
||||
|
||||
this.deletePromptLabel = 'Are you sure you want to delete this profile? All subscriptions in this profile will also be deleted.'
|
||||
this.deletePromptLabel = `${this.$t('Profile.Are you sure you want to delete this profile?')} ${this.$t('Profile["All subscriptions will also be deleted."]')}`
|
||||
|
||||
if (profileType === 'newProfile') {
|
||||
this.isNew = true
|
||||
|
@ -78,7 +78,7 @@ export default Vue.extend({
|
|||
this.grabProfileInfo(this.profileId).then((profile) => {
|
||||
if (profile === null) {
|
||||
this.showToast({
|
||||
message: 'Profile could not be found'
|
||||
message: this.$t('Profile.Profile could not be found')
|
||||
})
|
||||
this.$router.push({
|
||||
path: '/settings/profile/'
|
||||
|
@ -108,7 +108,7 @@ export default Vue.extend({
|
|||
saveProfile: function () {
|
||||
if (this.profileName === '') {
|
||||
this.showToast({
|
||||
message: 'Your profile name cannot be empty'
|
||||
message: this.$t('Profile.Your profile name cannot be empty')
|
||||
})
|
||||
return
|
||||
}
|
||||
|
@ -129,34 +129,36 @@ export default Vue.extend({
|
|||
|
||||
if (this.isNew) {
|
||||
this.showToast({
|
||||
message: 'Profile has been created'
|
||||
message: this.$t('Profile.Profile has been created')
|
||||
})
|
||||
this.$router.push({
|
||||
path: '/settings/profile/'
|
||||
})
|
||||
} else {
|
||||
this.showToast({
|
||||
message: 'Profile has been updated'
|
||||
message: this.$t('Profile.Profile has been updated')
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
setDefaultProfile: function () {
|
||||
this.updateDefaultProfile(this.profileId)
|
||||
const message = this.$t('Profile.Your default profile has been set to $').replace('$', this.profileName)
|
||||
this.showToast({
|
||||
message: `Your default profile has been set to ${this.profileName}`
|
||||
message: message
|
||||
})
|
||||
},
|
||||
|
||||
deleteProfile: function () {
|
||||
this.removeProfile(this.profileId)
|
||||
const message = this.$t('Profile.Removed $ from your profiles').replace('$', this.profileName)
|
||||
this.showToast({
|
||||
message: `Removed ${this.profileName} from your profiles`
|
||||
message: message
|
||||
})
|
||||
if (this.defaultProfile === this.profileId) {
|
||||
this.updateDefaultProfile('allChannels')
|
||||
this.showToast({
|
||||
message: 'Your default profile has been set your Primary profile'
|
||||
message: this.$t('Profile.Your default profile has been changed to your primary profile')
|
||||
})
|
||||
}
|
||||
if (this.activeProfile._id === this.profileId) {
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
</ft-flex-box>
|
||||
<ft-flex-box>
|
||||
<ft-button
|
||||
label="Create New Profile"
|
||||
:label="$t('Profile.Create New Profile')"
|
||||
@click="newProfile"
|
||||
/>
|
||||
</ft-flex-box>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<general-settings />
|
||||
<theme-settings />
|
||||
<player-settings />
|
||||
<subscription-settings />
|
||||
<privacy-settings />
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -8,6 +8,12 @@
|
|||
color: var(--tertiary-text-color);
|
||||
}
|
||||
|
||||
.floatingTopButton {
|
||||
position: absolute;
|
||||
top: 70px;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 680px) {
|
||||
.card {
|
||||
width: 90%;
|
||||
|
|
|
@ -2,16 +2,21 @@ import Vue from 'vue'
|
|||
import { mapActions, mapMutations } from 'vuex'
|
||||
import FtLoader from '../../components/ft-loader/ft-loader.vue'
|
||||
import FtCard from '../../components/ft-card/ft-card.vue'
|
||||
import FtButton from '../../components/ft-button/ft-button.vue'
|
||||
import FtIconButton from '../../components/ft-icon-button/ft-icon-button.vue'
|
||||
import FtFlexBox from '../../components/ft-flex-box/ft-flex-box.vue'
|
||||
import FtElementList from '../../components/ft-element-list/ft-element-list.vue'
|
||||
|
||||
import ytch from 'yt-channel-info'
|
||||
import Parser from 'rss-parser'
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'Subscriptions',
|
||||
components: {
|
||||
'ft-loader': FtLoader,
|
||||
'ft-card': FtCard,
|
||||
'ft-button': FtButton,
|
||||
'ft-icon-button': FtIconButton,
|
||||
'ft-flex-box': FtFlexBox,
|
||||
'ft-element-list': FtElementList
|
||||
},
|
||||
|
@ -23,6 +28,10 @@ export default Vue.extend({
|
|||
}
|
||||
},
|
||||
computed: {
|
||||
usingElectron: function () {
|
||||
return this.$store.getters.getUsingElectron
|
||||
},
|
||||
|
||||
backendPreference: function () {
|
||||
return this.$store.getters.getBackendPreference
|
||||
},
|
||||
|
@ -31,10 +40,30 @@ export default Vue.extend({
|
|||
return this.$store.getters.getBackendFallback
|
||||
},
|
||||
|
||||
invidiousInstance: function () {
|
||||
return this.$store.getters.getInvidiousInstance
|
||||
},
|
||||
|
||||
hideWatchedSubs: function () {
|
||||
return this.$store.getters.getHideWatchedSubs
|
||||
},
|
||||
|
||||
useRssFeeds: function () {
|
||||
return this.$store.getters.getUseRssFeeds
|
||||
},
|
||||
|
||||
profileList: function () {
|
||||
return this.$store.getters.getProfileList
|
||||
},
|
||||
|
||||
activeVideoList: function () {
|
||||
if (this.videoList.length < this.dataLimit) {
|
||||
return this.videoList
|
||||
} else {
|
||||
return this.videoList.slice(0, this.dataLimit)
|
||||
}
|
||||
},
|
||||
|
||||
activeProfile: function () {
|
||||
return this.$store.getters.getActiveProfile
|
||||
},
|
||||
|
@ -43,50 +72,99 @@ export default Vue.extend({
|
|||
return this.$store.getters.getProfileSubscriptions
|
||||
},
|
||||
|
||||
allSubscriptionsList: function () {
|
||||
return this.$store.getters.getAllSubscriptionsList
|
||||
},
|
||||
|
||||
historyCache: function () {
|
||||
return this.$store.getters.getHistoryCache
|
||||
},
|
||||
|
||||
activeSubscriptionList: function () {
|
||||
return this.profileList[this.activeProfile].subscriptions
|
||||
},
|
||||
|
||||
allSubscriptionsList: function () {
|
||||
return this.profileList[0].subscriptions
|
||||
},
|
||||
|
||||
sortedVideoList: function () {
|
||||
const profileSubscriptions = JSON.parse(JSON.stringify(this.profileSubscriptions))
|
||||
return profileSubscriptions.videoList.sort((a, b) => {
|
||||
if (a.title.toLowerCase() > b.title.toLowerCase()) {
|
||||
return -1
|
||||
}
|
||||
|
||||
if (a.title.toLowerCase() < b.title.toLowerCase()) {
|
||||
return 1
|
||||
}
|
||||
|
||||
console.log(a.title)
|
||||
|
||||
return 0
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
setTimeout(() => {
|
||||
this.fetchActiveSubscriptionsLocal()
|
||||
}, 1000)
|
||||
watch: {
|
||||
activeProfile: async function (val) {
|
||||
if (this.allSubscriptionsList.length !== 0) {
|
||||
this.isLoading = true
|
||||
this.videoList = await Promise.all(this.allSubscriptionsList.filter((video) => {
|
||||
const channelIndex = this.activeSubscriptionList.findIndex((x) => {
|
||||
return x.id === video.authorId
|
||||
})
|
||||
|
||||
const historyIndex = this.historyCache.findIndex((x) => {
|
||||
return x.videoId === video.videoId
|
||||
})
|
||||
|
||||
if (this.hideWatchedSubs) {
|
||||
return channelIndex !== -1 && historyIndex === -1
|
||||
} else {
|
||||
return channelIndex !== -1
|
||||
}
|
||||
}))
|
||||
this.isLoading = false
|
||||
} else {
|
||||
this.getSubscriptions()
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted: async function () {
|
||||
this.isLoading = true
|
||||
const dataLimit = sessionStorage.getItem('subscriptionLimit')
|
||||
if (dataLimit !== null) {
|
||||
this.dataLimit = dataLimit
|
||||
}
|
||||
setTimeout(async () => {
|
||||
if (this.profileSubscriptions.videoList.length === 0) {
|
||||
this.getSubscriptions()
|
||||
} else {
|
||||
const subscriptionList = JSON.parse(JSON.stringify(this.profileSubscriptions))
|
||||
if (this.hideWatchedSubs) {
|
||||
this.videoList = await Promise.all(subscriptionList.videoList.filter((video) => {
|
||||
const historyIndex = this.historyCache.findIndex((x) => {
|
||||
return x.videoId === video.videoId
|
||||
})
|
||||
|
||||
return historyIndex === -1
|
||||
}))
|
||||
} else {
|
||||
this.videoList = subscriptionList.videoList
|
||||
}
|
||||
this.isLoading = false
|
||||
}
|
||||
}, 200)
|
||||
},
|
||||
methods: {
|
||||
fetchActiveSubscriptionsLocal: function () {
|
||||
getSubscriptions: function () {
|
||||
if (this.activeSubscriptionList.length === 0) {
|
||||
this.isLoading = false
|
||||
this.videoList = []
|
||||
return
|
||||
}
|
||||
this.isLoading = true
|
||||
this.updateShowProgressBar(true)
|
||||
this.setProgressBarPercentage(0)
|
||||
|
||||
let videoList = []
|
||||
let channelCount = 0
|
||||
|
||||
this.activeSubscriptionList.forEach(async (channel) => {
|
||||
const videos = await this.getChannelVideosLocalScraper(channel.id)
|
||||
console.log(videos)
|
||||
let videos = []
|
||||
|
||||
if (!this.usingElectron || this.backendPreference === 'invidious') {
|
||||
if (this.useRssFeeds) {
|
||||
videos = await this.getChannelVideosInvidiousRSS(channel.id)
|
||||
} else {
|
||||
videos = await this.getChannelVideosInvidiousScraper(channel.id)
|
||||
}
|
||||
} else {
|
||||
if (this.useRssFeeds) {
|
||||
videos = await this.getChannelVideosLocalRSS(channel.id)
|
||||
} else {
|
||||
videos = await this.getChannelVideosLocalScraper(channel.id)
|
||||
}
|
||||
}
|
||||
|
||||
videoList = videoList.concat(videos)
|
||||
channelCount++
|
||||
|
@ -103,9 +181,24 @@ export default Vue.extend({
|
|||
videoList: videoList
|
||||
}
|
||||
|
||||
this.videoList = await Promise.all(videoList.filter((video) => {
|
||||
if (this.hideWatchedSubs) {
|
||||
const historyIndex = this.historyCache.findIndex((x) => {
|
||||
return x.videoId === video.videoId
|
||||
})
|
||||
|
||||
return historyIndex === -1
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}))
|
||||
this.updateProfileSubscriptions(profileSubscriptions)
|
||||
this.isLoading = false
|
||||
this.updateShowProgressBar(false)
|
||||
|
||||
if (this.activeProfile === 0) {
|
||||
this.updateAllSubscriptionsList(profileSubscriptions.videoList)
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
|
@ -135,25 +228,75 @@ export default Vue.extend({
|
|||
},
|
||||
|
||||
getChannelVideosLocalRSS: function (channelId) {
|
||||
console.log('TODO')
|
||||
},
|
||||
return new Promise((resolve, reject) => {
|
||||
const parser = new Parser()
|
||||
const feedUrl = `https://www.youtube.com/feeds/videos.xml?channel_id=${channelId}`
|
||||
|
||||
fetchActiveSubscriptionsInvidious: function () {
|
||||
console.log('TODO')
|
||||
parser.parseURL(feedUrl).then(async (feed) => {
|
||||
resolve(await Promise.all(feed.items.map((video) => {
|
||||
video.authorId = channelId
|
||||
video.videoId = video.id.replace('yt:video:', '')
|
||||
video.type = 'video'
|
||||
video.publishedDate = new Date(video.pubDate)
|
||||
video.publishedText = video.publishedDate.toLocaleString()
|
||||
video.lengthSeconds = '0:00'
|
||||
video.isRSS = true
|
||||
|
||||
return video
|
||||
})))
|
||||
}).catch((err) => {
|
||||
console.log(err)
|
||||
resolve([])
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
getChannelVideosInvidiousScraper: function (channelId) {
|
||||
console.log('TODO')
|
||||
return new Promise((resolve, reject) => {
|
||||
const subscriptionsPayload = {
|
||||
resource: 'channels/latest',
|
||||
id: channelId,
|
||||
params: {}
|
||||
}
|
||||
|
||||
this.invidiousAPICall(subscriptionsPayload).then((result) => {
|
||||
resolve(result)
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
getChannelVideosInvidiousRSS: function (channelId) {
|
||||
console.log('TODO')
|
||||
return new Promise((resolve, reject) => {
|
||||
const parser = new Parser()
|
||||
const feedUrl = `${this.invidiousInstance}/feed/channel/${channelId}`
|
||||
|
||||
parser.parseURL(feedUrl).then(async (feed) => {
|
||||
resolve(await Promise.all(feed.items.map((video) => {
|
||||
video.authorId = channelId
|
||||
video.videoId = video.id.replace('yt:video:', '')
|
||||
video.type = 'video'
|
||||
video.publishedDate = new Date(video.pubDate)
|
||||
video.publishedText = video.publishedDate.toLocaleString()
|
||||
video.lengthSeconds = '0:00'
|
||||
video.isRSS = true
|
||||
|
||||
return video
|
||||
})))
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
increaseLimit: function () {
|
||||
this.dataLimit += 100
|
||||
sessionStorage.setItem('subscriptionLimit', this.dataLimit)
|
||||
},
|
||||
|
||||
...mapActions([
|
||||
'showToast',
|
||||
'invidiousAPICall',
|
||||
'updateShowProgressBar',
|
||||
'updateProfileSubscriptions',
|
||||
'updateAllSubscriptionsList',
|
||||
'calculatePublishedDate'
|
||||
]),
|
||||
|
||||
|
|
|
@ -10,20 +10,20 @@
|
|||
>
|
||||
<h3>{{ $t("Subscriptions.Subscriptions") }}</h3>
|
||||
<ft-flex-box
|
||||
v-if="profileSubscriptions.videoList.length === 0"
|
||||
v-if="activeVideoList.length === 0"
|
||||
>
|
||||
<p class="message">
|
||||
{{ $t("History['Your history list is currently empty.']") }}
|
||||
{{ $t("Subscriptions['Your Subscription list is currently empty. Start adding subscriptions to see them here.']") }}
|
||||
</p>
|
||||
</ft-flex-box>
|
||||
<ft-element-list
|
||||
v-else
|
||||
:data="profileSubscriptions.videoList"
|
||||
:data="activeVideoList"
|
||||
/>
|
||||
<ft-flex-box
|
||||
v-if="false"
|
||||
>
|
||||
<ft-button
|
||||
v-if="videoList.length > dataLimit"
|
||||
label="Load More"
|
||||
background-color="var(--primary-color)"
|
||||
text-color="var(--text-with-main-color)"
|
||||
|
@ -31,6 +31,15 @@
|
|||
/>
|
||||
</ft-flex-box>
|
||||
</ft-card>
|
||||
<ft-icon-button
|
||||
v-if="!isLoading"
|
||||
icon="sync"
|
||||
class="floatingTopButton"
|
||||
:title="$t('Subscriptions.Refresh Subscriptions')"
|
||||
:size="12"
|
||||
theme="primary"
|
||||
@click="getSubscriptions"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -70,7 +70,8 @@ Subscriptions:
|
|||
Latest Subscriptions: Latest Subscriptions
|
||||
'Your Subscription list is currently empty. Start adding subscriptions to see them here.': Your
|
||||
Subscription list is currently empty. Start adding subscriptions to see them here.
|
||||
'Getting Subscriptions. Please wait.': Getting Subscriptions. Please wait.
|
||||
'Getting Subscriptions. Please wait.': Getting Subscriptions. Please wait.
|
||||
Refresh Subscriptions: Refresh Subscriptions
|
||||
Trending: Trending
|
||||
Most Popular: Most Popular
|
||||
Playlists: Playlists
|
||||
|
@ -180,6 +181,7 @@ Settings:
|
|||
Subscription Settings:
|
||||
Subscription Settings: Subscription Settings
|
||||
Hide Videos on Watch: Hide Videos on Watch
|
||||
Fetch Feeds from RSS: Fetch Feeds from RSS
|
||||
Subscriptions Export Format:
|
||||
Subscriptions Export Format: Subscriptions Export Format
|
||||
#& Freetube
|
||||
|
@ -260,6 +262,14 @@ Profile:
|
|||
Delete Profile: Delete Profile
|
||||
Are you sure you want to delete this profile?: Are you sure you want to delete this profile?
|
||||
All subscriptions will also be deleted.: All subscriptions will also be deleted.
|
||||
Profile could not be found: Profile could not be found
|
||||
Your profile name cannot be empty: Your profile name cannot be empty
|
||||
Profile has been created: Profile has been created
|
||||
Profile has been updated: Profile has been updated
|
||||
Your default profile has been set to $: Your default profile has been set to $
|
||||
Removed $ from your profiles: Removed $ from your profiles
|
||||
Your default profile has been changed to your primary profile: Your default profile has been changed to your primary profile
|
||||
$ is now the active profile: $ is now the active profile
|
||||
#On Channel Page
|
||||
Channel:
|
||||
Subscriber: Subscriber
|
||||
|
|
Loading…
Reference in New Issue