feat: sharing subscriptions UI (#1567)
* feat(web): add ui for subscription sharing * fix(web): add missing triggers * fix(snjs): setting authorization token on http service * fix(web): add alert upon invite failure * fix(web): display invitations list * fix(web): canceling subscription invitations * fix(web): fonts * fix(web): linter issues * fix: click event handler * fix: styles * feat: update styles * feat: don't show bottom separator if all invites used * fix(web): references to alert service * fix(web): remove usebeforeunload Co-authored-by: Aman Harwara <amanharwara@protonmail.com>
This commit is contained in:
@@ -4,6 +4,10 @@ import {
|
||||
ClientDisplayableError,
|
||||
convertTimestampToMilliseconds,
|
||||
InternalEventBus,
|
||||
Invitation,
|
||||
InvitationStatus,
|
||||
SubscriptionClientInterface,
|
||||
Uuid,
|
||||
} from '@standardnotes/snjs'
|
||||
import { action, computed, makeObservable, observable } from 'mobx'
|
||||
import { WebApplication } from '../../Application/Application'
|
||||
@@ -12,28 +16,40 @@ import { AvailableSubscriptions } from './AvailableSubscriptionsType'
|
||||
import { Subscription } from './SubscriptionType'
|
||||
|
||||
export class SubscriptionController extends AbstractViewController {
|
||||
private readonly ALLOWED_SUBSCRIPTION_INVITATIONS = 5
|
||||
|
||||
userSubscription: Subscription | undefined = undefined
|
||||
availableSubscriptions: AvailableSubscriptions | undefined = undefined
|
||||
subscriptionInvitations: Invitation[] | undefined = undefined
|
||||
|
||||
override deinit() {
|
||||
super.deinit()
|
||||
;(this.userSubscription as unknown) = undefined
|
||||
;(this.availableSubscriptions as unknown) = undefined
|
||||
;(this.subscriptionInvitations as unknown) = undefined
|
||||
|
||||
destroyAllObjectProperties(this)
|
||||
}
|
||||
|
||||
constructor(application: WebApplication, eventBus: InternalEventBus) {
|
||||
constructor(
|
||||
application: WebApplication,
|
||||
eventBus: InternalEventBus,
|
||||
private subscriptionManager: SubscriptionClientInterface,
|
||||
) {
|
||||
super(application, eventBus)
|
||||
|
||||
makeObservable(this, {
|
||||
userSubscription: observable,
|
||||
availableSubscriptions: observable,
|
||||
subscriptionInvitations: observable,
|
||||
|
||||
userSubscriptionName: computed,
|
||||
userSubscriptionExpirationDate: computed,
|
||||
isUserSubscriptionExpired: computed,
|
||||
isUserSubscriptionCanceled: computed,
|
||||
usedInvitationsCount: computed,
|
||||
allowedInvitationsCount: computed,
|
||||
allInvitationsUsed: computed,
|
||||
|
||||
setUserSubscription: action,
|
||||
setAvailableSubscriptions: action,
|
||||
@@ -43,6 +59,7 @@ export class SubscriptionController extends AbstractViewController {
|
||||
application.addEventObserver(async () => {
|
||||
if (application.hasAccount()) {
|
||||
this.getSubscriptionInfo().catch(console.error)
|
||||
this.reloadSubscriptionInvitations().catch(console.error)
|
||||
}
|
||||
}, ApplicationEvent.Launched),
|
||||
)
|
||||
@@ -50,12 +67,14 @@ export class SubscriptionController extends AbstractViewController {
|
||||
this.disposers.push(
|
||||
application.addEventObserver(async () => {
|
||||
this.getSubscriptionInfo().catch(console.error)
|
||||
this.reloadSubscriptionInvitations().catch(console.error)
|
||||
}, ApplicationEvent.SignedIn),
|
||||
)
|
||||
|
||||
this.disposers.push(
|
||||
application.addEventObserver(async () => {
|
||||
this.getSubscriptionInfo().catch(console.error)
|
||||
this.reloadSubscriptionInvitations().catch(console.error)
|
||||
}, ApplicationEvent.UserRolesChanged),
|
||||
)
|
||||
}
|
||||
@@ -91,6 +110,22 @@ export class SubscriptionController extends AbstractViewController {
|
||||
return Boolean(this.userSubscription?.cancelled)
|
||||
}
|
||||
|
||||
get usedInvitationsCount(): number {
|
||||
return (
|
||||
this.subscriptionInvitations?.filter((invitation) =>
|
||||
[InvitationStatus.Accepted, InvitationStatus.Sent].includes(invitation.status),
|
||||
).length ?? 0
|
||||
)
|
||||
}
|
||||
|
||||
get allowedInvitationsCount(): number {
|
||||
return this.ALLOWED_SUBSCRIPTION_INVITATIONS
|
||||
}
|
||||
|
||||
get allInvitationsUsed(): boolean {
|
||||
return this.usedInvitationsCount === this.ALLOWED_SUBSCRIPTION_INVITATIONS
|
||||
}
|
||||
|
||||
public setUserSubscription(subscription: Subscription): void {
|
||||
this.userSubscription = subscription
|
||||
}
|
||||
@@ -99,6 +134,26 @@ export class SubscriptionController extends AbstractViewController {
|
||||
this.availableSubscriptions = subscriptions
|
||||
}
|
||||
|
||||
async sendSubscriptionInvitation(inviteeEmail: string): Promise<boolean> {
|
||||
const success = await this.subscriptionManager.inviteToSubscription(inviteeEmail)
|
||||
|
||||
if (success) {
|
||||
await this.reloadSubscriptionInvitations()
|
||||
}
|
||||
|
||||
return success
|
||||
}
|
||||
|
||||
async cancelSubscriptionInvitation(invitationUuid: Uuid): Promise<boolean> {
|
||||
const success = await this.subscriptionManager.cancelInvitation(invitationUuid)
|
||||
|
||||
if (success) {
|
||||
await this.reloadSubscriptionInvitations()
|
||||
}
|
||||
|
||||
return success
|
||||
}
|
||||
|
||||
private async getAvailableSubscriptions() {
|
||||
try {
|
||||
const subscriptions = await this.application.getAvailableSubscriptions()
|
||||
@@ -125,4 +180,8 @@ export class SubscriptionController extends AbstractViewController {
|
||||
await this.getSubscription()
|
||||
await this.getAvailableSubscriptions()
|
||||
}
|
||||
|
||||
private async reloadSubscriptionInvitations(): Promise<void> {
|
||||
this.subscriptionInvitations = await this.subscriptionManager.listSubscriptionInvitations()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user