refactor: offline roles (#2169)

This commit is contained in:
Mo
2023-01-19 21:46:21 -06:00
committed by GitHub
parent 391b2af4e1
commit 544a28d450
33 changed files with 282 additions and 266 deletions

View File

@@ -13,6 +13,7 @@ type Props = {
const UpgradeNow = ({ application, featuresController, subscriptionContoller }: Props) => {
const shouldShowCTA = !featuresController.hasFolders
const hasAccount = subscriptionContoller.hasAccount
const hasAccessToFeatures = subscriptionContoller.hasFirstPartySubscription
const onClick = useCallback(() => {
if (hasAccount && application.isNativeIOS()) {
@@ -22,16 +23,20 @@ const UpgradeNow = ({ application, featuresController, subscriptionContoller }:
}
}, [application, hasAccount])
return shouldShowCTA ? (
if (!shouldShowCTA || hasAccessToFeatures) {
return null
}
return (
<div className="flex h-full items-center px-2">
<button
className="rounded bg-info py-0.5 px-1.5 text-sm font-bold uppercase text-info-contrast hover:brightness-125 lg:text-xs"
onClick={onClick}
>
{hasAccount ? 'Unlock features' : 'Sign up to sync'}
{!hasAccount ? 'Sign up to sync' : 'Unlock features'}
</button>
</div>
) : null
)
}
export default observer(UpgradeNow)

View File

@@ -99,7 +99,7 @@ const Email: FunctionComponent<Props> = ({ application }: Props) => {
<Subtitle>Disable sign-in notification emails</Subtitle>
<Text>
Disables email notifications when a new sign-in occurs on your account. (Email notifications are
available to paid subscribers).
available only to paid subscribers).
</Text>
</div>
{isLoading ? (

View File

@@ -15,7 +15,7 @@ type Props = {
const Subscription: FunctionComponent<Props> = ({ application, viewControllerManager }: Props) => {
const subscriptionState = viewControllerManager.subscriptionController
const { userSubscription } = subscriptionState
const { onlineSubscription } = subscriptionState
const now = new Date().getTime()
@@ -25,7 +25,7 @@ const Subscription: FunctionComponent<Props> = ({ application, viewControllerMan
<div className="flex flex-row items-center">
<div className="flex flex-grow flex-col">
<Title>Subscription</Title>
{userSubscription && userSubscription.endsAt > now ? (
{onlineSubscription && onlineSubscription.endsAt > now ? (
<SubscriptionInformation subscriptionState={subscriptionState} application={application} />
) : (
<NoSubscription application={application} />

View File

@@ -17,7 +17,7 @@ import {
} from '@standardnotes/snjs'
import { WebApplication } from '@/Application/Application'
import Button from '@/Components/Button/Button'
import { isDev, openInNewTab } from '@/Utils'
import { openInNewTab } from '@/Utils'
import { Subtitle } from '@/Components/Preferences/PreferencesComponents/Content'
import { KeyboardKey } from '@standardnotes/ui-services'
@@ -61,7 +61,7 @@ const CloudBackupProvider: FunctionComponent<Props> = ({ application, providerNa
}
event.stopPropagation()
const authUrl = application.getCloudProviderIntegrationUrl(providerName, isDev)
const authUrl = application.getCloudProviderIntegrationUrl(providerName)
openInNewTab(authUrl)
setAuthBegan(true)
}

View File

@@ -7,7 +7,7 @@ export class PackageProvider {
static async load(application: WebApplication): Promise<PackageProvider | undefined> {
const response = await application.getAvailableSubscriptions()
if (response instanceof ClientDisplayableError) {
if (!response || response instanceof ClientDisplayableError) {
return undefined
}

View File

@@ -64,7 +64,10 @@ export const UpgradePrompt = ({
<div className="mb-2 font-bold">The Professional Plan costs $119.99/year and includes benefits like</div>
<ul className="list-inside list-[circle]">
<li>100GB encrypted file storage</li>
<li>Access to all note types, including markdown, rich text, authenticator, tasks, and spreadsheets</li>
<li>
Access to all note types, including Super, markdown, rich text, authenticator, tasks, and spreadsheets
</li>
<li>Access to Daily Notebooks and Moments journals</li>
<li>Note history going back indefinitely</li>
<li>Nested folders for your tags</li>
<li>Premium support</li>
@@ -79,7 +82,7 @@ export const UpgradePrompt = ({
className="no-border w-full cursor-pointer rounded bg-info py-2 font-bold text-info-contrast hover:brightness-125 focus:brightness-125"
ref={ctaRef}
>
Upgrade
{application.isNativeIOS() ? 'Start Free Trial' : 'Upgrade'}
</button>
</div>
</>

View File

@@ -65,6 +65,7 @@ export class FeaturesController extends AbstractViewController {
break
case ApplicationEvent.FeaturesUpdated:
case ApplicationEvent.Launched:
case ApplicationEvent.LocalDataLoaded:
runInAction(() => {
this.hasFolders = this.isEntitledToFolders()
this.hasSmartViews = this.isEntitledToSmartViews()

View File

@@ -75,7 +75,7 @@ export class LinkingController extends AbstractViewController {
}
get isEntitledToNoteLinking() {
return !!this.subscriptionController.userSubscription
return !!this.subscriptionController.onlineSubscription
}
setIsLinkingPanelOpen = (open: boolean) => {

View File

@@ -17,14 +17,15 @@ import { Subscription } from './SubscriptionType'
export class SubscriptionController extends AbstractViewController {
private readonly ALLOWED_SUBSCRIPTION_INVITATIONS = 5
userSubscription: Subscription | undefined = undefined
onlineSubscription: Subscription | undefined = undefined
availableSubscriptions: AvailableSubscriptions | undefined = undefined
subscriptionInvitations: Invitation[] | undefined = undefined
hasAccount: boolean
hasFirstPartySubscription: boolean
override deinit() {
super.deinit()
;(this.userSubscription as unknown) = undefined
;(this.onlineSubscription as unknown) = undefined
;(this.availableSubscriptions as unknown) = undefined
;(this.subscriptionInvitations as unknown) = undefined
@@ -38,12 +39,14 @@ export class SubscriptionController extends AbstractViewController {
) {
super(application, eventBus)
this.hasAccount = application.hasAccount()
this.hasFirstPartySubscription = application.features.hasFirstPartySubscription()
makeObservable(this, {
userSubscription: observable,
onlineSubscription: observable,
availableSubscriptions: observable,
subscriptionInvitations: observable,
hasAccount: observable,
hasFirstPartySubscription: observable,
userSubscriptionName: computed,
userSubscriptionExpirationDate: computed,
@@ -64,11 +67,20 @@ export class SubscriptionController extends AbstractViewController {
this.reloadSubscriptionInvitations().catch(console.error)
}
runInAction(() => {
this.hasFirstPartySubscription = application.features.hasFirstPartySubscription()
this.hasAccount = application.hasAccount()
})
}, ApplicationEvent.Launched),
)
this.disposers.push(
application.addEventObserver(async () => {
runInAction(() => {
this.hasFirstPartySubscription = application.features.hasFirstPartySubscription()
})
}, ApplicationEvent.LocalDataLoaded),
)
this.disposers.push(
application.addEventObserver(async () => {
this.getSubscriptionInfo().catch(console.error)
@@ -83,6 +95,9 @@ export class SubscriptionController extends AbstractViewController {
application.addEventObserver(async () => {
this.getSubscriptionInfo().catch(console.error)
this.reloadSubscriptionInvitations().catch(console.error)
runInAction(() => {
this.hasFirstPartySubscription = application.features.hasFirstPartySubscription()
})
}, ApplicationEvent.UserRolesChanged),
)
}
@@ -90,20 +105,20 @@ export class SubscriptionController extends AbstractViewController {
get userSubscriptionName(): string {
if (
this.availableSubscriptions &&
this.userSubscription &&
this.availableSubscriptions[this.userSubscription.planName]
this.onlineSubscription &&
this.availableSubscriptions[this.onlineSubscription.planName]
) {
return this.availableSubscriptions[this.userSubscription.planName].name
return this.availableSubscriptions[this.onlineSubscription.planName].name
}
return ''
}
get userSubscriptionExpirationDate(): Date | undefined {
if (!this.userSubscription) {
if (!this.onlineSubscription) {
return undefined
}
return new Date(convertTimestampToMilliseconds(this.userSubscription.endsAt))
return new Date(convertTimestampToMilliseconds(this.onlineSubscription.endsAt))
}
get isUserSubscriptionExpired(): boolean {
@@ -115,11 +130,11 @@ export class SubscriptionController extends AbstractViewController {
}
get isUserSubscriptionCanceled(): boolean {
return Boolean(this.userSubscription?.cancelled)
return Boolean(this.onlineSubscription?.cancelled)
}
hasValidSubscription(): boolean {
return this.userSubscription != undefined && !this.isUserSubscriptionExpired && !this.isUserSubscriptionCanceled
return this.onlineSubscription != undefined && !this.isUserSubscriptionExpired && !this.isUserSubscriptionCanceled
}
get usedInvitationsCount(): number {
@@ -139,7 +154,7 @@ export class SubscriptionController extends AbstractViewController {
}
public setUserSubscription(subscription: Subscription): void {
this.userSubscription = subscription
this.onlineSubscription = subscription
}
public setAvailableSubscriptions(subscriptions: AvailableSubscriptions): void {

View File

@@ -6,6 +6,7 @@ import {
ComponentArea,
FeatureDescription,
GetFeatures,
FindNativeFeature,
NoteType,
FeatureIdentifier,
} from '@standardnotes/snjs'
@@ -149,8 +150,7 @@ const createBaselineMap = (application: WebApplication): NoteTypeToEditorRowsMap
isEntitled: application.features.getFeatureStatus(FeatureIdentifier.SuperEditor) === FeatureStatus.Entitled,
noteType: NoteType.Super,
isLabs: true,
description:
'A new way to edit notes. Type / to bring up the block selection menu, or @ to embed images or link other tags and notes. Type - then space to start a list, or [] then space to start a checklist. Drag and drop an image or file to embed it in your note.',
description: FindNativeFeature(FeatureIdentifier.SuperEditor)?.description,
},
],
[NoteType.RichText]: [],