]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - client/src/app/shared/user-subscription/subscribe-button.component.ts
Fix OnInit for subscribe button
[github/Chocobozzz/PeerTube.git] / client / src / app / shared / user-subscription / subscribe-button.component.ts
index 25515f6ea31cd6367673c3720ad739edefb34323..947f34c852236e215304c68c089ab35315a0a536 100644 (file)
@@ -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<string, boolean>()
 
   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.videoChannel.name + '@' + this.videoChannel.host
+    return this.getChannelHandler(this.videoChannel)
+  }
+
+  get uri () {
+    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 channelUri () {
-    return this.videoChannel.url
+  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.doesSubscriptionExist(this.channelHandle)
-        .subscribe(
-          res => this.subscribed = res[this.channelHandle],
+    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.channelHandle)
+    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.channelHandle)
-        .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)
+      )
+    }
   }
 }