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

Subscriptions: Add community tab #3973

Merged
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
a6b5988
Add subscription community tab
ChunkyProgrammer Aug 26, 2023
446688a
fix up community tab
ChunkyProgrammer Aug 29, 2023
91893ec
simplify if statement
ChunkyProgrammer Aug 30, 2023
5b4475d
use global.community for all references to community
ChunkyProgrammer Aug 30, 2023
0c985c1
Merge branch 'development' into add-subscription-community
ChunkyProgrammer Aug 30, 2023
05bbc12
dont show community when useRss is set
ChunkyProgrammer Aug 30, 2023
fe35848
check visibleTabs for showing the community tab
ChunkyProgrammer Aug 30, 2023
5ef6961
Merge branch 'development' into add-subscription-community
ChunkyProgrammer Sep 1, 2023
65eaffd
Merge branch 'development' into add-subscription-community
ChunkyProgrammer Sep 3, 2023
c184bc9
Merge branch 'development' into add-subscription-community
ChunkyProgrammer Sep 6, 2023
bcac51c
fix caching, decrease datalimit for community, add missing translations
ChunkyProgrammer Sep 6, 2023
eedc348
Merge branch 'development' into add-subscription-community
ChunkyProgrammer Sep 10, 2023
dd71681
Merge branch 'development' into add-subscription-community
ChunkyProgrammer Sep 14, 2023
2b7e639
L: Hide shared posts, IV: Don't show errors for empty community tab
ChunkyProgrammer Sep 18, 2023
951398d
Merge branch 'development' into add-subscription-community
ChunkyProgrammer Sep 18, 2023
29df968
add links to related issues
ChunkyProgrammer Sep 18, 2023
7d8c803
Merge branch 'development' into add-subscription-community
ChunkyProgrammer Sep 20, 2023
cd916e2
Merge branch 'development' into add-subscription-community
ChunkyProgrammer Sep 22, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ export default defineComponent({
hideSubscriptionsLive: function () {
return this.$store.getters.getHideSubscriptionsLive
},
hideSubscriptionsCommunity: function() {
return this.$store.getters.getHideSubscriptionsCommunity
},
showDistractionFreeTitles: function () {
return this.$store.getters.getShowDistractionFreeTitles
},
Expand Down Expand Up @@ -155,6 +158,7 @@ export default defineComponent({
'updateHideSubscriptionsVideos',
'updateHideSubscriptionsShorts',
'updateHideSubscriptionsLive',
'updateHideSubscriptionsCommunity',
'updateBlurThumbnails'
])
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@
:tooltip="hideLiveStreams ? hideSubscriptionsLiveTooltip : ''"
v-on="!hideLiveStreams ? { change: updateHideSubscriptionsLive } : {}"
/>
<ft-toggle-switch
:label="$t('Settings.Distraction Free Settings.Hide Subscriptions Community')"
:compact="true"
:default-value="hideSubscriptionsCommunity"
@change="updateHideSubscriptionsCommunity"
/>
</div>
</div>
<h4
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export default defineComponent({
commentCount: '',
isLoading: true,
author: '',
authorId: '',
}
},
computed: {
Expand Down Expand Up @@ -104,6 +105,7 @@ export default defineComponent({
this.commentCount = this.data.commentCount
this.type = (this.data.postContent !== null && this.data.postContent !== undefined) ? this.data.postContent.type : 'text'
this.author = this.data.author
this.authorId = this.data.authorId
this.isLoading = false
},

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
.outside {
margin: auto;
width: 40%;

@media screen and (max-width: 768px) {
width: 100%;
}
Expand Down Expand Up @@ -33,6 +34,11 @@
font-size: 15px;
font-weight: bold;
margin: 5px 6px 0 5px;

.authorNameLink {
color: inherit;
text-decoration: none;
}
}

.publishedText {
Expand Down
37 changes: 32 additions & 5 deletions src/renderer/components/ft-community-post/ft-community-post.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,43 @@
<div
class="author-div"
>
<img
<template
v-if="authorThumbnails.length > 0"
:src="getBestQualityImage(authorThumbnails)"
class="communityThumbnail"
alt=""
>
<router-link
v-if="authorId"
:to="`/channel/${authorId}`"
tabindex="-1"
aria-hidden="true"
>
<img
:src="getBestQualityImage(authorThumbnails)"
class="communityThumbnail"
alt=""
>
</router-link>
<img
v-else
:src="getBestQualityImage(authorThumbnails)"
class="communityThumbnail"
alt=""
>
</template>
<p
class="authorName"
>
{{ author }}
<router-link
v-if="authorId"
:to="`/channel/${authorId}`"
class="authorNameLink"
>
{{ author }}
</router-link>
<template
v-else
>
{{ author }}
</template>
</p>
<p
class="publishedText"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
import { defineComponent } from 'vue'
import { mapActions, mapMutations } from 'vuex'
import SubscriptionsTabUI from '../subscriptions-tab-ui/subscriptions-tab-ui.vue'

import { calculatePublishedDate, copyToClipboard, showToast } from '../../helpers/utils'
import { getLocalChannelCommunity } from '../../helpers/api/local'
import { invidiousGetCommunityPosts } from '../../helpers/api/invidious'

export default defineComponent({
name: 'SubscriptionsCommunity',
components: {
'subscriptions-tab-ui': SubscriptionsTabUI
},
data: function () {
return {
isLoading: false,
postList: [],
errorChannels: [],
attemptedFetch: false,
}
},
computed: {
backendPreference: function () {
return this.$store.getters.getBackendPreference
},

backendFallback: function () {
return this.$store.getters.getBackendFallback
},

currentInvidiousInstance: function () {
return this.$store.getters.getCurrentInvidiousInstance
},

activeProfile: function () {
return this.$store.getters.getActiveProfile
},
activeProfileId: function () {
return this.activeProfile._id
},

cacheEntriesForAllActiveProfileChannels() {
const entries = []
this.activeSubscriptionList.forEach((channel) => {
const cacheEntry = this.$store.getters.getPostsCacheByChannel(channel.id)
if (cacheEntry == null) { return }

entries.push(cacheEntry)
})
return entries
},
postCacheForAllActiveProfileChannelsPresent() {
if (this.cacheEntriesForAllActiveProfileChannels.length === 0) { return false }
if (this.cacheEntriesForAllActiveProfileChannels.length < this.activeSubscriptionList.length) { return false }

return this.cacheEntriesForAllActiveProfileChannels.every((cacheEntry) => {
return cacheEntry.posts != null
})
},

activeSubscriptionList: function () {
return this.activeProfile.subscriptions
},

fetchSubscriptionsAutomatically: function() {
return this.$store.getters.getFetchSubscriptionsAutomatically
},
},
watch: {
activeProfile: async function (_) {
this.isLoading = true
this.loadpostsFromCacheSometimes()
},
},
mounted: async function () {
this.isLoading = true

this.loadpostsFromCacheSometimes()
},
methods: {
loadpostsFromCacheSometimes() {
// This method is called on view visible
if (this.postCacheForAllActiveProfileChannelsPresent) {
this.loadPostsFromCacheForAllActiveProfileChannels()
return
}

this.maybeLoadPostsForSubscriptionsFromRemote()
},

async loadPostsFromCacheForAllActiveProfileChannels() {
const postList = []
this.activeSubscriptionList.forEach((channel) => {
const channelCacheEntry = this.$store.getters.getPostsCacheByChannel(channel.id)

postList.push(...channelCacheEntry.posts)
})

postList.sort((a, b) => {
return calculatePublishedDate(b.publishedText) - calculatePublishedDate(a.publishedText)
})

this.postList = postList
this.isLoading = false
},

loadPostsForSubscriptionsFromRemote: async function () {
if (this.activeSubscriptionList.length === 0) {
this.isLoading = false
this.postList = []
return
}

const channelsToLoadFromRemote = this.activeSubscriptionList
const postList = []
let channelCount = 0
this.isLoading = true

this.updateShowProgressBar(true)
this.setProgressBarPercentage(0)
this.attemptedFetch = true

this.errorChannels = []
const postListFromRemote = (await Promise.all(channelsToLoadFromRemote.map(async (channel) => {
let posts = []
if (!process.env.IS_ELECTRON || this.backendPreference === 'invidious') {
posts = await this.getChannelPostsInvidious(channel)
} else {
posts = await this.getChannelPostsLocal(channel)
}

channelCount++
const percentageComplete = (channelCount / channelsToLoadFromRemote.length) * 100
this.setProgressBarPercentage(percentageComplete)

this.updateSubscriptionPostsCacheByChannel({
channelId: channel.id,
posts: posts,
})
return posts
}))).flatMap((o) => o)
postList.push(...postListFromRemote)
postList.sort((a, b) => {
return calculatePublishedDate(b.publishedText) - calculatePublishedDate(a.publishedText)
})

this.postList = postList
this.isLoading = false
this.updateShowProgressBar(false)
},

maybeLoadPostsForSubscriptionsFromRemote: async function () {
if (this.fetchSubscriptionsAutomatically) {
// `this.isLoading = false` is called inside `loadPostsForSubscriptionsFromRemote` when needed
await this.loadPostsForSubscriptionsFromRemote()
} else {
this.postList = []
this.attemptedFetch = false
this.isLoading = false
}
},

getChannelPostsLocal: async function (channel) {
try {
const entries = await getLocalChannelCommunity(channel.id)

if (entries === null) {
this.errorChannels.push(channel)
return []
}
entries.forEach(post => {
post.authorId = channel.id
})
return entries
} catch (err) {
console.error(err)
const errorMessage = this.$t('Local API Error (Click to copy)')
showToast(`${errorMessage}: ${err}`, 10000, () => {
copyToClipboard(err)
})
if (this.backendPreference === 'local' && this.backendFallback) {
showToast(this.$t('Falling back to Invidious API'))
return await this.getChannelPostsInvidious(channel)
}
return []
}
},

getChannelPostsInvidious: function (channel) {
return new Promise((resolve, reject) => {
invidiousGetCommunityPosts(channel.id).then(result => {
result.posts.forEach(post => {
post.authorId = channel.id
})
resolve(result.posts)
}).catch((err) => {
console.error(err)
const errorMessage = this.$t('Invidious API Error (Click to copy)')
showToast(`${errorMessage}: ${err.responseText}`, 10000, () => {
copyToClipboard(err.responseText)
})
if (process.env.IS_ELECTRON && this.backendPreference === 'invidious' && this.backendFallback) {
showToast(this.$t('Falling back to the local API'))
resolve(this.getChannelPostsLocal(channel))
} else {
resolve([])
}
})
})
},

...mapActions([
'updateShowProgressBar',
'updateSubscriptionPostsCacheByChannel',
]),

...mapMutations([
'setProgressBarPercentage'
])
}
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<template>
<subscriptions-tab-ui
:is-loading="isLoading"
:video-list="postList"
:error-channels="errorChannels"
:attempted-fetch="attemptedFetch"
:display-list="true"
@refresh="loadPostsForSubscriptionsFromRemote"
/>
</template>

<script src="./subscriptions-community.js" />
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ export default defineComponent({
type: Array,
default: () => ([])
},
displayList: {
type: Boolean,
default: false
},
errorChannels: {
type: Array,
default: () => ([])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
v-if="!isLoading && activeVideoList.length > 0"
:data="activeVideoList"
:use-channels-hidden-preference="false"
:display="displayList ? 'list' : ''"
/>
<ft-flex-box
v-if="!isLoading && videoList.length > dataLimit"
Expand Down
Loading