116 lines
3.7 KiB
TypeScript
116 lines
3.7 KiB
TypeScript
import { AnyFeatureDescription, FeatureIdentifier, FindNativeFeature } from '@standardnotes/features'
|
|
import { DecryptedItemInterface } from '@standardnotes/models'
|
|
import { Subscription } from '@standardnotes/responses'
|
|
import { FeatureStatus, ItemManagerInterface } from '@standardnotes/services'
|
|
import { convertTimestampToMilliseconds } from '@standardnotes/utils'
|
|
|
|
export class GetFeatureStatusUseCase {
|
|
constructor(private items: ItemManagerInterface) {}
|
|
|
|
execute(dto: {
|
|
featureId: FeatureIdentifier | string
|
|
firstPartyOnlineSubscription: Subscription | undefined
|
|
firstPartyRoles: { online: string[] } | { offline: string[] } | undefined
|
|
hasPaidAnyPartyOnlineOrOfflineSubscription: boolean
|
|
inContextOfItem?: DecryptedItemInterface
|
|
}): FeatureStatus {
|
|
if (this.isFreeFeature(dto.featureId as FeatureIdentifier)) {
|
|
return FeatureStatus.Entitled
|
|
}
|
|
|
|
const nativeFeature = FindNativeFeature(dto.featureId as FeatureIdentifier)
|
|
|
|
if (!nativeFeature) {
|
|
return this.getThirdPartyFeatureStatus(dto.featureId as string)
|
|
}
|
|
|
|
if (nativeFeature.deprecated) {
|
|
return this.getDeprecatedNativeFeatureStatus({
|
|
nativeFeature,
|
|
hasPaidAnyPartyOnlineOrOfflineSubscription: dto.hasPaidAnyPartyOnlineOrOfflineSubscription,
|
|
})
|
|
}
|
|
|
|
return this.getNativeFeatureFeatureStatus({
|
|
nativeFeature,
|
|
firstPartyOnlineSubscription: dto.firstPartyOnlineSubscription,
|
|
firstPartyRoles: dto.firstPartyRoles,
|
|
inContextOfItem: dto.inContextOfItem,
|
|
})
|
|
}
|
|
|
|
private getDeprecatedNativeFeatureStatus(dto: {
|
|
hasPaidAnyPartyOnlineOrOfflineSubscription: boolean
|
|
nativeFeature: AnyFeatureDescription
|
|
}): FeatureStatus {
|
|
if (dto.hasPaidAnyPartyOnlineOrOfflineSubscription) {
|
|
return FeatureStatus.Entitled
|
|
} else {
|
|
return FeatureStatus.NoUserSubscription
|
|
}
|
|
}
|
|
|
|
private getNativeFeatureFeatureStatus(dto: {
|
|
nativeFeature: AnyFeatureDescription
|
|
firstPartyOnlineSubscription: Subscription | undefined
|
|
firstPartyRoles: { online: string[] } | { offline: string[] } | undefined
|
|
inContextOfItem?: DecryptedItemInterface
|
|
}): FeatureStatus {
|
|
if (dto.inContextOfItem) {
|
|
const isSharedVaultItem = dto.inContextOfItem.shared_vault_uuid !== undefined
|
|
if (isSharedVaultItem) {
|
|
return FeatureStatus.Entitled
|
|
}
|
|
}
|
|
|
|
if (!dto.firstPartyOnlineSubscription && !dto.firstPartyRoles) {
|
|
return FeatureStatus.NoUserSubscription
|
|
}
|
|
|
|
const roles = !dto.firstPartyRoles
|
|
? undefined
|
|
: 'online' in dto.firstPartyRoles
|
|
? dto.firstPartyRoles.online
|
|
: dto.firstPartyRoles.offline
|
|
|
|
if (dto.nativeFeature.availableInRoles && roles) {
|
|
const hasRole = roles.some((role) => {
|
|
return dto.nativeFeature.availableInRoles?.includes(role)
|
|
})
|
|
|
|
if (!hasRole) {
|
|
return FeatureStatus.NotInCurrentPlan
|
|
}
|
|
}
|
|
|
|
if (dto.firstPartyOnlineSubscription) {
|
|
const isSubscriptionExpired =
|
|
new Date(convertTimestampToMilliseconds(dto.firstPartyOnlineSubscription.endsAt)) < new Date()
|
|
|
|
if (isSubscriptionExpired) {
|
|
return FeatureStatus.InCurrentPlanButExpired
|
|
}
|
|
}
|
|
|
|
return FeatureStatus.Entitled
|
|
}
|
|
|
|
private getThirdPartyFeatureStatus(featureId: string): FeatureStatus {
|
|
const component = this.items.getDisplayableComponents().find((candidate) => candidate.identifier === featureId)
|
|
|
|
if (!component) {
|
|
return FeatureStatus.NoUserSubscription
|
|
}
|
|
|
|
if (component.isExpired) {
|
|
return FeatureStatus.InCurrentPlanButExpired
|
|
}
|
|
|
|
return FeatureStatus.Entitled
|
|
}
|
|
|
|
private isFreeFeature(featureId: FeatureIdentifier) {
|
|
return [FeatureIdentifier.DarkTheme, FeatureIdentifier.PlainEditor].includes(featureId)
|
|
}
|
|
}
|