mirror of
https://github.com/FreeTubeApp/FreeTube
synced 2024-11-26 19:59:56 +01:00
Allow Unsubscribing from Deleted Channels (#2283)
* unsub from deleted * reset error message on invidious channel load * fix error channels not showing * Use errorMessage instead of isErrorMessage Co-authored-by: absidue <48293849+absidue@users.noreply.github.com> * Change "Error Channels" to "Channels with Errors" Co-authored-by: absidue <48293849+absidue@users.noreply.github.com> * use find instead of find index Co-Authored-By: absidue <48293849+absidue@users.noreply.github.com> Co-Authored-By: PikachuEXE <pikachuexe@gmail.com> Co-authored-by: absidue <48293849+absidue@users.noreply.github.com> Co-authored-by: PikachuEXE <pikachuexe@gmail.com>
This commit is contained in:
parent
74dc309803
commit
da095adc8c
@ -4,7 +4,8 @@ const state = {
|
||||
allSubscriptionsList: [],
|
||||
profileSubscriptions: {
|
||||
activeProfile: MAIN_PROFILE_ID,
|
||||
videoList: []
|
||||
videoList: [],
|
||||
errorChannels: []
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,7 @@ export default Vue.extend({
|
||||
searchResults: [],
|
||||
shownElementList: [],
|
||||
apiUsed: '',
|
||||
errorMessage: '',
|
||||
videoSelectValues: [
|
||||
'newest',
|
||||
'oldest',
|
||||
@ -90,16 +91,14 @@ export default Vue.extend({
|
||||
return this.$store.getters.getActiveProfile
|
||||
},
|
||||
|
||||
isSubscribed: function () {
|
||||
const subIndex = this.activeProfile.subscriptions.findIndex((channel) => {
|
||||
subscriptionInfo: function () {
|
||||
return this.activeProfile.subscriptions.find((channel) => {
|
||||
return channel.id === this.id
|
||||
})
|
||||
}) ?? null
|
||||
},
|
||||
|
||||
if (subIndex === -1) {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
isSubscribed: function () {
|
||||
return this.subscriptionInfo !== null
|
||||
},
|
||||
|
||||
subscribedText: function () {
|
||||
@ -251,6 +250,11 @@ export default Vue.extend({
|
||||
this.apiUsed = 'local'
|
||||
const expectedId = this.id
|
||||
ytch.getChannelInfo({ channelId: expectedId }).then((response) => {
|
||||
if (response.alertMessage) {
|
||||
this.setErrorMessage(response.alertMessage)
|
||||
return
|
||||
}
|
||||
this.errorMessage = ''
|
||||
if (expectedId !== this.id) {
|
||||
return
|
||||
}
|
||||
@ -401,8 +405,10 @@ export default Vue.extend({
|
||||
this.bannerUrl = null
|
||||
}
|
||||
|
||||
this.errorMessage = ''
|
||||
this.isLoading = false
|
||||
}).catch((err) => {
|
||||
this.setErrorMessage(err.responseJSON.error)
|
||||
console.log(err)
|
||||
const errorMessage = this.$t('Invidious API Error (Click to copy)')
|
||||
this.showToast({
|
||||
@ -645,6 +651,16 @@ export default Vue.extend({
|
||||
}
|
||||
},
|
||||
|
||||
setErrorMessage: function (errorMessage) {
|
||||
this.isLoading = false
|
||||
this.errorMessage = errorMessage
|
||||
this.id = this.subscriptionInfo.id
|
||||
this.channelName = this.subscriptionInfo.name
|
||||
this.thumbnailUrl = this.subscriptionInfo.thumbnail
|
||||
this.bannerUrl = null
|
||||
this.subCount = null
|
||||
},
|
||||
|
||||
handleFetchMore: function () {
|
||||
switch (this.currentTab) {
|
||||
case 'videos':
|
||||
|
@ -3,7 +3,7 @@
|
||||
ref="search"
|
||||
>
|
||||
<ft-loader
|
||||
v-if="isLoading"
|
||||
v-if="isLoading && !errorMessage"
|
||||
:fullscreen="true"
|
||||
/>
|
||||
<ft-card
|
||||
@ -61,6 +61,7 @@
|
||||
</div>
|
||||
|
||||
<ft-flex-box
|
||||
v-if="!errorMessage"
|
||||
class="channelInfoTabs"
|
||||
>
|
||||
<div
|
||||
@ -112,7 +113,7 @@
|
||||
</div>
|
||||
</ft-card>
|
||||
<ft-card
|
||||
v-if="!isLoading"
|
||||
v-if="!isLoading && !errorMessage"
|
||||
class="card"
|
||||
>
|
||||
<div
|
||||
@ -194,6 +195,14 @@
|
||||
</div>
|
||||
</div>
|
||||
</ft-card>
|
||||
<ft-card
|
||||
v-if="errorMessage"
|
||||
class="card"
|
||||
>
|
||||
<p>
|
||||
{{ errorMessage }}
|
||||
</p>
|
||||
</ft-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -14,6 +14,10 @@
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
.channelBubble {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 350px) {
|
||||
.floatingTopButton {
|
||||
position: absolute
|
||||
|
@ -6,6 +6,7 @@ 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 FtChannelBubble from '../../components/ft-channel-bubble/ft-channel-bubble.vue'
|
||||
|
||||
import ytch from 'yt-channel-info'
|
||||
import Parser from 'rss-parser'
|
||||
@ -19,13 +20,15 @@ export default Vue.extend({
|
||||
'ft-button': FtButton,
|
||||
'ft-icon-button': FtIconButton,
|
||||
'ft-flex-box': FtFlexBox,
|
||||
'ft-element-list': FtElementList
|
||||
'ft-element-list': FtElementList,
|
||||
'ft-channel-bubble': FtChannelBubble
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
isLoading: false,
|
||||
dataLimit: 100,
|
||||
videoList: []
|
||||
videoList: [],
|
||||
errorChannels: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -110,6 +113,7 @@ export default Vue.extend({
|
||||
}))
|
||||
} else {
|
||||
this.videoList = subscriptionList.videoList
|
||||
this.errorChannels = subscriptionList.errorChannels
|
||||
}
|
||||
} else {
|
||||
this.getProfileSubscriptions()
|
||||
@ -123,6 +127,10 @@ export default Vue.extend({
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
goToChannel: function (id) {
|
||||
this.$router.push({ path: `/channel/${id}` })
|
||||
},
|
||||
|
||||
getSubscriptions: function () {
|
||||
if (this.activeSubscriptionList.length === 0) {
|
||||
this.isLoading = false
|
||||
@ -144,10 +152,9 @@ export default Vue.extend({
|
||||
|
||||
let videoList = []
|
||||
let channelCount = 0
|
||||
|
||||
this.errorChannels = []
|
||||
this.activeSubscriptionList.forEach(async (channel) => {
|
||||
let videos = []
|
||||
|
||||
if (!this.usingElectron || this.backendPreference === 'invidious') {
|
||||
if (useRss) {
|
||||
videos = await this.getChannelVideosInvidiousRSS(channel)
|
||||
@ -174,7 +181,8 @@ export default Vue.extend({
|
||||
|
||||
const profileSubscriptions = {
|
||||
activeProfile: this.activeProfile._id,
|
||||
videoList: videoList
|
||||
videoList: videoList,
|
||||
errorChannels: this.errorChannels
|
||||
}
|
||||
|
||||
this.videoList = await Promise.all(videoList.filter((video) => {
|
||||
@ -226,6 +234,11 @@ export default Vue.extend({
|
||||
getChannelVideosLocalScraper: function (channel, failedAttempts = 0) {
|
||||
return new Promise((resolve, reject) => {
|
||||
ytch.getChannelVideos({ channelId: channel.id, sortBy: 'latest' }).then(async (response) => {
|
||||
if (response.alertMessage) {
|
||||
this.errorChannels.push(channel)
|
||||
resolve([])
|
||||
return
|
||||
}
|
||||
const videos = await Promise.all(response.items.map(async (video) => {
|
||||
if (video.liveNow) {
|
||||
video.publishedDate = new Date().getTime()
|
||||
@ -297,33 +310,38 @@ export default Vue.extend({
|
||||
resolve(items)
|
||||
}).catch((err) => {
|
||||
console.log(err)
|
||||
const errorMessage = this.$t('Local API Error (Click to copy)')
|
||||
this.showToast({
|
||||
message: `${errorMessage}: ${err}`,
|
||||
time: 10000,
|
||||
action: () => {
|
||||
navigator.clipboard.writeText(err)
|
||||
}
|
||||
})
|
||||
switch (failedAttempts) {
|
||||
case 0:
|
||||
resolve(this.getChannelVideosLocalScraper(channel, failedAttempts + 1))
|
||||
break
|
||||
case 1:
|
||||
if (this.backendFallback) {
|
||||
this.showToast({
|
||||
message: this.$t('Falling back to Invidious API')
|
||||
})
|
||||
resolve(this.getChannelVideosInvidiousRSS(channel, failedAttempts + 1))
|
||||
} else {
|
||||
resolve([])
|
||||
if (err.toString().match(/404/)) {
|
||||
this.errorChannels.push(channel)
|
||||
resolve([])
|
||||
} else {
|
||||
const errorMessage = this.$t('Local API Error (Click to copy)')
|
||||
this.showToast({
|
||||
message: `${errorMessage}: ${err}`,
|
||||
time: 10000,
|
||||
action: () => {
|
||||
navigator.clipboard.writeText(err)
|
||||
}
|
||||
break
|
||||
case 2:
|
||||
resolve(this.getChannelVideosLocalScraper(channel, failedAttempts + 1))
|
||||
break
|
||||
default:
|
||||
resolve([])
|
||||
})
|
||||
switch (failedAttempts) {
|
||||
case 0:
|
||||
resolve(this.getChannelVideosLocalScraper(channel, failedAttempts + 1))
|
||||
break
|
||||
case 1:
|
||||
if (this.backendFallback) {
|
||||
this.showToast({
|
||||
message: this.$t('Falling back to Invidious API')
|
||||
})
|
||||
resolve(this.getChannelVideosInvidiousRSS(channel, failedAttempts + 1))
|
||||
} else {
|
||||
resolve([])
|
||||
}
|
||||
break
|
||||
case 2:
|
||||
resolve(this.getChannelVideosLocalScraper(channel, failedAttempts + 1))
|
||||
break
|
||||
default:
|
||||
resolve([])
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
@ -403,25 +421,30 @@ export default Vue.extend({
|
||||
navigator.clipboard.writeText(err)
|
||||
}
|
||||
})
|
||||
switch (failedAttempts) {
|
||||
case 0:
|
||||
resolve(this.getChannelVideosInvidiousScraper(channel, failedAttempts + 1))
|
||||
break
|
||||
case 1:
|
||||
if (this.backendFallback) {
|
||||
this.showToast({
|
||||
message: this.$t('Falling back to the local API')
|
||||
})
|
||||
resolve(this.getChannelVideosLocalRSS(channel, failedAttempts + 1))
|
||||
} else {
|
||||
if (err.toString().match(/500/)) {
|
||||
this.errorChannels.push(channel)
|
||||
resolve([])
|
||||
} else {
|
||||
switch (failedAttempts) {
|
||||
case 0:
|
||||
resolve(this.getChannelVideosInvidiousScraper(channel, failedAttempts + 1))
|
||||
break
|
||||
case 1:
|
||||
if (this.backendFallback) {
|
||||
this.showToast({
|
||||
message: this.$t('Falling back to the local API')
|
||||
})
|
||||
resolve(this.getChannelVideosLocalRSS(channel, failedAttempts + 1))
|
||||
} else {
|
||||
resolve([])
|
||||
}
|
||||
break
|
||||
case 2:
|
||||
resolve(this.getChannelVideosInvidiousScraper(channel, failedAttempts + 1))
|
||||
break
|
||||
default:
|
||||
resolve([])
|
||||
}
|
||||
break
|
||||
case 2:
|
||||
resolve(this.getChannelVideosInvidiousScraper(channel, failedAttempts + 1))
|
||||
break
|
||||
default:
|
||||
resolve([])
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -8,6 +8,22 @@
|
||||
v-else
|
||||
class="card"
|
||||
>
|
||||
<div
|
||||
v-if="errorChannels.length !== 0"
|
||||
>
|
||||
<h3> {{ $t("Subscriptions.Error Channels") }}</h3>
|
||||
<div>
|
||||
<ft-channel-bubble
|
||||
v-for="(channel, index) in errorChannels"
|
||||
:key="index"
|
||||
:channel-name="channel.name"
|
||||
:channel-id="channel.id"
|
||||
:channel-thumbnail="channel.thumbnail"
|
||||
class="channelBubble"
|
||||
@click="goToChannel(channel.id)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<h3>{{ $t("Subscriptions.Subscriptions") }}</h3>
|
||||
<ft-flex-box
|
||||
v-if="activeVideoList.length === 0"
|
||||
|
@ -78,6 +78,8 @@ Search Filters:
|
||||
Subscriptions:
|
||||
# On Subscriptions Page
|
||||
Subscriptions: Subscriptions
|
||||
# channels that were likely deleted
|
||||
Error Channels: Channels with Errors
|
||||
Latest Subscriptions: Latest Subscriptions
|
||||
This profile has a large number of subscriptions. Forcing RSS to avoid rate limiting: This
|
||||
profile has a large number of subscriptions. Forcing RSS to avoid rate limiting
|
||||
|
Loading…
Reference in New Issue
Block a user