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