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