]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - client/src/app/shared/shared-user-subscription/subscribe-button.component.ts
Move to sass module
[github/Chocobozzz/PeerTube.git] / client / src / app / shared / shared-user-subscription / subscribe-button.component.ts
1 import { concat, forkJoin, merge } from 'rxjs'
2 import { Component, Input, OnChanges, OnInit } from '@angular/core'
3 import { Router } from '@angular/router'
4 import { AuthService, Notifier } from '@app/core'
5 import { Account, VideoChannel, VideoService } from '@app/shared/shared-main'
6 import { FeedFormat } from '@shared/models'
7 import { UserSubscriptionService } from './user-subscription.service'
8
9 @Component({
10 selector: 'my-subscribe-button',
11 templateUrl: './subscribe-button.component.html',
12 styleUrls: [ './subscribe-button.component.scss' ]
13 })
14 export class SubscribeButtonComponent implements OnInit, OnChanges {
15 /**
16 * SubscribeButtonComponent can be used with a single VideoChannel passed as [VideoChannel],
17 * or with an account and a full list of that account's videoChannels. The latter is intended
18 * to allow mass un/subscription from an account's page, while keeping the channel-centric
19 * subscription model.
20 */
21 @Input() account: Account
22 @Input() videoChannels: VideoChannel[]
23 @Input() displayFollowers = false
24 @Input() size: 'small' | 'normal' = 'normal'
25
26 subscribed = new Map<string, boolean>()
27
28 constructor (
29 private authService: AuthService,
30 private router: Router,
31 private notifier: Notifier,
32 private userSubscriptionService: UserSubscriptionService,
33 private videoService: VideoService
34 ) { }
35
36 get handle () {
37 return this.account
38 ? this.account.nameWithHost
39 : this.videoChannel.name + '@' + this.videoChannel.host
40 }
41
42 get channelHandle () {
43 return this.getChannelHandler(this.videoChannel)
44 }
45
46 get uri () {
47 return this.account
48 ? this.account.url
49 : this.videoChannels[0].url
50 }
51
52 get rssUri () {
53 const rssFeed = this.account
54 ? this.videoService
55 .getAccountFeedUrls(this.account.id)
56 .find(i => i.format === FeedFormat.RSS)
57 : this.videoService
58 .getVideoChannelFeedUrls(this.videoChannels[0].id)
59 .find(i => i.format === FeedFormat.RSS)
60
61 return rssFeed.url
62 }
63
64 get videoChannel () {
65 return this.videoChannels[0]
66 }
67
68 get isAllChannelsSubscribed () {
69 return this.subscribeStatus(true).length === this.videoChannels.length
70 }
71
72 get isAtLeastOneChannelSubscribed () {
73 return this.subscribeStatus(true).length > 0
74 }
75
76 get isBigButton () {
77 return this.isUserLoggedIn() && this.videoChannels.length > 1 && this.isAtLeastOneChannelSubscribed
78 }
79
80 ngOnInit () {
81 this.loadSubscribedStatus()
82 }
83
84 ngOnChanges () {
85 this.ngOnInit()
86 }
87
88 subscribe () {
89 if (this.isUserLoggedIn()) {
90 return this.localSubscribe()
91 }
92
93 return this.gotoLogin()
94 }
95
96 localSubscribe () {
97 const subscribedStatus = this.subscribeStatus(false)
98
99 const observableBatch = this.videoChannels
100 .map(videoChannel => this.getChannelHandler(videoChannel))
101 .filter(handle => subscribedStatus.includes(handle))
102 .map(handle => this.userSubscriptionService.addSubscription(handle))
103
104 forkJoin(observableBatch)
105 .subscribe(
106 () => {
107 this.notifier.success(
108 this.account
109 ? $localize`Subscribed to all current channels of ${this.account.displayName}. You will be notified of all their new videos.`
110 : $localize`Subscribed to ${this.videoChannels[0].displayName}. You will be notified of all their new videos.`,
111
112 $localize`Subscribed`
113 )
114 },
115
116 err => this.notifier.error(err.message)
117 )
118 }
119
120 unsubscribe () {
121 if (this.isUserLoggedIn()) {
122 this.localUnsubscribe()
123 }
124 }
125
126 localUnsubscribe () {
127 const subscribeStatus = this.subscribeStatus(true)
128
129 const observableBatch = this.videoChannels
130 .map(videoChannel => this.getChannelHandler(videoChannel))
131 .filter(handle => subscribeStatus.includes(handle))
132 .map(handle => this.userSubscriptionService.deleteSubscription(handle))
133
134 concat(...observableBatch)
135 .subscribe({
136 complete: () => {
137 this.notifier.success(
138 this.account
139 ? $localize`Unsubscribed from all channels of ${this.account.nameWithHost}`
140 : $localize`Unsubscribed from ${this.videoChannels[ 0 ].nameWithHost}`,
141
142 $localize`Unsubscribed`
143 )
144 },
145
146 error: err => this.notifier.error(err.message)
147 })
148 }
149
150 isUserLoggedIn () {
151 return this.authService.isLoggedIn()
152 }
153
154 gotoLogin () {
155 this.router.navigate([ '/login' ])
156 }
157
158 subscribeStatus (subscribed: boolean) {
159 const accumulator: string[] = []
160 for (const [key, value] of this.subscribed.entries()) {
161 if (value === subscribed) accumulator.push(key)
162 }
163
164 return accumulator
165 }
166
167 private getChannelHandler (videoChannel: VideoChannel) {
168 return videoChannel.name + '@' + videoChannel.host
169 }
170
171 private loadSubscribedStatus () {
172 if (!this.isUserLoggedIn()) return
173
174 for (const videoChannel of this.videoChannels) {
175 const handle = this.getChannelHandler(videoChannel)
176 this.subscribed.set(handle, false)
177
178 merge(
179 this.userSubscriptionService.listenToSubscriptionCacheChange(handle),
180 this.userSubscriptionService.doesSubscriptionExist(handle)
181 ).subscribe(
182 res => this.subscribed.set(handle, res),
183
184 err => this.notifier.error(err.message)
185 )
186 }
187 }
188 }