X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;ds=sidebyside;f=client%2Fsrc%2Fapp%2Fshared%2Fuser-subscription%2Fsubscribe-button.component.ts;h=947f34c852236e215304c68c089ab35315a0a536;hb=d5692d4088cdd9fde3be6ff34be8ce2816dab0cf;hp=8f1754c7f31ececd86134531f0d391e31b1edf96;hpb=73471b1a52f242e86364ffb077ea6cadb3b07ae2;p=oweals%2Fpeertube.git diff --git a/client/src/app/shared/user-subscription/subscribe-button.component.ts b/client/src/app/shared/user-subscription/subscribe-button.component.ts index 8f1754c7f..947f34c85 100644 --- a/client/src/app/shared/user-subscription/subscribe-button.component.ts +++ b/client/src/app/shared/user-subscription/subscribe-button.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit } from '@angular/core' +import { Component, Input, OnInit, OnChanges } from '@angular/core' import { Router } from '@angular/router' import { AuthService, Notifier } from '@app/core' import { UserSubscriptionService } from '@app/shared/user-subscription/user-subscription.service' @@ -6,18 +6,27 @@ import { VideoChannel } from '@app/shared/video-channel/video-channel.model' import { I18n } from '@ngx-translate/i18n-polyfill' import { VideoService } from '@app/shared/video/video.service' import { FeedFormat } from '../../../../../shared/models/feeds' +import { Account } from '@app/shared/account/account.model' +import { concat, forkJoin, merge } from 'rxjs' @Component({ selector: 'my-subscribe-button', templateUrl: './subscribe-button.component.html', styleUrls: [ './subscribe-button.component.scss' ] }) -export class SubscribeButtonComponent implements OnInit { - @Input() videoChannel: VideoChannel +export class SubscribeButtonComponent implements OnInit, OnChanges { + /** + * SubscribeButtonComponent can be used with a single VideoChannel passed as [VideoChannel], + * or with an account and a full list of that account's videoChannels. The latter is intended + * to allow mass un/subscription from an account's page, while keeping the channel-centric + * subscription model. + */ + @Input() account: Account + @Input() videoChannels: VideoChannel[] @Input() displayFollowers = false @Input() size: 'small' | 'normal' = 'normal' - subscribed: boolean + subscribed = new Map() constructor ( private authService: AuthService, @@ -28,23 +37,56 @@ export class SubscribeButtonComponent implements OnInit { private videoService: VideoService ) { } + get handle () { + return this.account + ? this.account.nameWithHost + : this.videoChannel.name + '@' + this.videoChannel.host + } + + get channelHandle () { + return this.getChannelHandler(this.videoChannel) + } + get uri () { - return this.videoChannel.name + '@' + this.videoChannel.host + return this.account + ? this.account.url + : this.videoChannels[0].url + } + + get rssUri () { + const rssFeed = this.account + ? this.videoService + .getAccountFeedUrls(this.account.id) + .find(i => i.format === FeedFormat.RSS) + : this.videoService + .getVideoChannelFeedUrls(this.videoChannels[0].id) + .find(i => i.format === FeedFormat.RSS) + + return rssFeed.url + } + + get videoChannel () { + return this.videoChannels[0] } - get uriAccount () { - return this.videoChannel.ownerAccount.name + '@' + this.videoChannel.host + get isAllChannelsSubscribed () { + return this.subscribeStatus(true).length === this.videoChannels.length + } + + get isAtLeastOneChannelSubscribed () { + return this.subscribeStatus(true).length > 0 + } + + get isBigButton () { + return this.isUserLoggedIn() && this.videoChannels.length > 1 && this.isAtLeastOneChannelSubscribed } ngOnInit () { - if (this.isUserLoggedIn()) { - this.userSubscriptionService.isSubscriptionExists(this.uri) - .subscribe( - res => this.subscribed = res[this.uri], + this.loadSubscribedStatus() + } - err => this.notifier.error(err.message) - ) - } + ngOnChanges () { + this.ngOnInit() } subscribe () { @@ -56,13 +98,27 @@ export class SubscribeButtonComponent implements OnInit { } localSubscribe () { - this.userSubscriptionService.addSubscription(this.uri) + const subscribedStatus = this.subscribeStatus(false) + + const observableBatch = this.videoChannels + .map(videoChannel => this.getChannelHandler(videoChannel)) + .filter(handle => subscribedStatus.includes(handle)) + .map(handle => this.userSubscriptionService.addSubscription(handle)) + + forkJoin(observableBatch) .subscribe( () => { - this.subscribed = true - this.notifier.success( - this.i18n('Subscribed to {{nameWithHost}}', { nameWithHost: this.videoChannel.displayName }), + this.account + ? this.i18n( + 'Subscribed to all current channels of {{nameWithHost}}. You will be notified of all their new videos.', + { nameWithHost: this.account.displayName } + ) + : this.i18n( + 'Subscribed to {{nameWithHost}}. You will be notified of all their new videos.', + { nameWithHost: this.videoChannels[0].displayName } + ) + , this.i18n('Subscribed') ) }, @@ -78,19 +134,27 @@ export class SubscribeButtonComponent implements OnInit { } localUnsubscribe () { - this.userSubscriptionService.deleteSubscription(this.uri) - .subscribe( - () => { - this.subscribed = false + const subscribeStatus = this.subscribeStatus(true) - this.notifier.success( - this.i18n('Unsubscribed from {{nameWithHost}}', { nameWithHost: this.videoChannel.displayName }), - this.i18n('Unsubscribed') - ) - }, + const observableBatch = this.videoChannels + .map(videoChannel => this.getChannelHandler(videoChannel)) + .filter(handle => subscribeStatus.includes(handle)) + .map(handle => this.userSubscriptionService.deleteSubscription(handle)) - err => this.notifier.error(err.message) - ) + concat(...observableBatch) + .subscribe({ + complete: () => { + this.notifier.success( + this.account + ? this.i18n('Unsubscribed from all channels of {{nameWithHost}}', { nameWithHost: this.account.nameWithHost }) + : this.i18n('Unsubscribed from {{nameWithHost}}', { nameWithHost: this.videoChannels[ 0 ].nameWithHost }) + , + this.i18n('Unsubscribed') + ) + }, + + error: err => this.notifier.error(err.message) + }) } isUserLoggedIn () { @@ -101,11 +165,34 @@ export class SubscribeButtonComponent implements OnInit { this.router.navigate([ '/login' ]) } - rssOpen () { - const rssFeed = this.videoService - .getVideoChannelFeedUrls(this.videoChannel.id) - .find(i => i.format === FeedFormat.RSS) + subscribeStatus (subscribed: boolean) { + const accumulator: string[] = [] + for (const [key, value] of this.subscribed.entries()) { + if (value === subscribed) accumulator.push(key) + } - window.open(rssFeed.url) + return accumulator + } + + private getChannelHandler (videoChannel: VideoChannel) { + return videoChannel.name + '@' + videoChannel.host + } + + private loadSubscribedStatus () { + if (!this.isUserLoggedIn()) return + + for (const videoChannel of this.videoChannels) { + const handle = this.getChannelHandler(videoChannel) + this.subscribed.set(handle, false) + + merge( + this.userSubscriptionService.listenToSubscriptionCacheChange(handle), + this.userSubscriptionService.doesSubscriptionExist(handle) + ).subscribe( + res => this.subscribed.set(handle, res), + + err => this.notifier.error(err.message) + ) + } } }