refactor: make features state consistent with codebase (#988)
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import { Icon } from '@/Components/Icon'
|
||||
import { TAG_FOLDERS_FEATURE_NAME } from '@/Constants'
|
||||
import { usePremiumModal } from '@/Hooks/usePremiumModal'
|
||||
import { KeyboardKey } from '@/Services/IOService'
|
||||
import { FeaturesState, TAG_FOLDERS_FEATURE_NAME } from '@/UIModels/AppState/FeaturesState'
|
||||
import { FeaturesState } from '@/UIModels/AppState/FeaturesState'
|
||||
import { TagsState } from '@/UIModels/AppState/TagsState'
|
||||
import '@reach/tooltip/styles.css'
|
||||
import { SNTag } from '@standardnotes/snjs'
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import { TAG_FOLDERS_FEATURE_NAME, TAG_FOLDERS_FEATURE_TOOLTIP } from '@/Constants'
|
||||
import { usePremiumModal } from '@/Hooks/usePremiumModal'
|
||||
import {
|
||||
FeaturesState,
|
||||
TAG_FOLDERS_FEATURE_NAME,
|
||||
TAG_FOLDERS_FEATURE_TOOLTIP,
|
||||
} from '@/UIModels/AppState/FeaturesState'
|
||||
import { FeaturesState } from '@/UIModels/AppState/FeaturesState'
|
||||
import { Tooltip } from '@reach/tooltip'
|
||||
import { observer } from 'mobx-react-lite'
|
||||
import { FunctionComponent } from 'preact'
|
||||
|
||||
@@ -16,3 +16,7 @@ export const DAYS_IN_A_YEAR = 365
|
||||
|
||||
export const BYTES_IN_ONE_KILOBYTE = 1_000
|
||||
export const BYTES_IN_ONE_MEGABYTE = 1_000_000
|
||||
|
||||
export const TAG_FOLDERS_FEATURE_NAME = 'Tag folders'
|
||||
export const TAG_FOLDERS_FEATURE_TOOLTIP = 'A Plus or Pro plan is required to enable Tag folders.'
|
||||
export const SMART_TAGS_FEATURE_NAME = 'Smart Tags'
|
||||
|
||||
@@ -31,7 +31,7 @@ interface Props {
|
||||
|
||||
export const PremiumModalProvider: FunctionalComponent<Props> = observer(
|
||||
({ application, appState, children }) => {
|
||||
const featureName = appState.features._premiumAlertFeatureName
|
||||
const featureName = appState.features.premiumAlertFeatureName
|
||||
const activate = appState.features.showPremiumAlert
|
||||
const close = appState.features.closePremiumAlert
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ export class AppState {
|
||||
this.appEventObserverRemovers,
|
||||
)
|
||||
this.noteTags = new NoteTagsState(application, this, this.appEventObserverRemovers)
|
||||
this.features = new FeaturesState(application)
|
||||
this.features = new FeaturesState(application, this.appEventObserverRemovers)
|
||||
this.tags = new TagsState(application, this.appEventObserverRemovers, this.features)
|
||||
this.noAccountWarning = new NoAccountWarningState(application, this.appEventObserverRemovers)
|
||||
this.accountMenu = new AccountMenuState(application, this.appEventObserverRemovers)
|
||||
@@ -155,8 +155,6 @@ export class AppState {
|
||||
|
||||
this.appEventObserverRemovers.forEach((remover) => remover())
|
||||
this.appEventObserverRemovers.length = 0
|
||||
|
||||
this.features.deinit()
|
||||
;(this.features as unknown) = undefined
|
||||
|
||||
this.webAppEventDisposer?.()
|
||||
|
||||
@@ -1,38 +1,29 @@
|
||||
import { WebApplication } from '@/UIModels/Application'
|
||||
import { isDev } from '@/Utils'
|
||||
import { ApplicationEvent, FeatureIdentifier, FeatureStatus } from '@standardnotes/snjs'
|
||||
import { action, computed, makeObservable, observable, runInAction, when } from 'mobx'
|
||||
import { WebApplication } from '../Application'
|
||||
|
||||
export const TAG_FOLDERS_FEATURE_NAME = 'Tag folders'
|
||||
export const TAG_FOLDERS_FEATURE_TOOLTIP = 'A Plus or Pro plan is required to enable Tag folders.'
|
||||
|
||||
export const SMART_TAGS_FEATURE_NAME = 'Smart Tags'
|
||||
|
||||
/**
|
||||
* Holds state for premium/non premium features for the current user features,
|
||||
* and eventually for in-development features (feature flags).
|
||||
*/
|
||||
export class FeaturesState {
|
||||
readonly enableUnfinishedFeatures: boolean = window?.enabledUnfinishedFeatures
|
||||
hasFolders: boolean
|
||||
hasSmartViews: boolean
|
||||
hasFilesBeta: boolean
|
||||
premiumAlertFeatureName: string | undefined
|
||||
|
||||
_hasFolders = false
|
||||
_hasSmartViews = false
|
||||
_hasFilesBeta = false
|
||||
_premiumAlertFeatureName: string | undefined
|
||||
|
||||
private unsub: () => void
|
||||
|
||||
constructor(private application: WebApplication) {
|
||||
this._hasFolders = this.hasNativeFolders()
|
||||
this._hasSmartViews = this.hasNativeSmartViews()
|
||||
this._hasFilesBeta = this.isEntitledToFilesBeta()
|
||||
this._premiumAlertFeatureName = undefined
|
||||
constructor(private application: WebApplication, appObservers: (() => void)[]) {
|
||||
this.hasFolders = this.hasNativeFolders()
|
||||
this.hasSmartViews = this.hasNativeSmartViews()
|
||||
this.hasFilesBeta = this.isEntitledToFilesBeta()
|
||||
this.premiumAlertFeatureName = undefined
|
||||
|
||||
makeObservable(this, {
|
||||
_hasFolders: observable,
|
||||
_hasSmartViews: observable,
|
||||
hasFolders: computed,
|
||||
_premiumAlertFeatureName: observable,
|
||||
hasFolders: observable,
|
||||
hasSmartViews: observable,
|
||||
|
||||
hasFilesBeta: observable,
|
||||
isFilesEnabled: computed,
|
||||
isEntitledToFiles: computed,
|
||||
|
||||
premiumAlertFeatureName: observable,
|
||||
showPremiumAlert: action,
|
||||
closePremiumAlert: action,
|
||||
})
|
||||
@@ -40,49 +31,36 @@ export class FeaturesState {
|
||||
this.showPremiumAlert = this.showPremiumAlert.bind(this)
|
||||
this.closePremiumAlert = this.closePremiumAlert.bind(this)
|
||||
|
||||
this.unsub = this.application.addEventObserver(async (eventName) => {
|
||||
switch (eventName) {
|
||||
case ApplicationEvent.FeaturesUpdated:
|
||||
case ApplicationEvent.Launched:
|
||||
runInAction(() => {
|
||||
this._hasFolders = this.hasNativeFolders()
|
||||
this._hasSmartViews = this.hasNativeSmartViews()
|
||||
this._hasFilesBeta = this.isEntitledToFilesBeta()
|
||||
})
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
public deinit() {
|
||||
this.unsub()
|
||||
}
|
||||
|
||||
public get hasFolders(): boolean {
|
||||
return this._hasFolders
|
||||
}
|
||||
|
||||
public get hasSmartViews(): boolean {
|
||||
return this._hasSmartViews
|
||||
}
|
||||
|
||||
public get isFilesEnabled(): boolean {
|
||||
return this._hasFilesBeta || window.enabledUnfinishedFeatures || isDev
|
||||
}
|
||||
|
||||
public get isEntitledToFiles(): boolean {
|
||||
return this._hasFilesBeta
|
||||
appObservers.push(
|
||||
application.addEventObserver(async (event) => {
|
||||
switch (event) {
|
||||
case ApplicationEvent.FeaturesUpdated:
|
||||
case ApplicationEvent.Launched:
|
||||
runInAction(() => {
|
||||
this.hasFolders = this.hasNativeFolders()
|
||||
this.hasSmartViews = this.hasNativeSmartViews()
|
||||
this.hasFilesBeta = this.isEntitledToFilesBeta()
|
||||
})
|
||||
}
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
public async showPremiumAlert(featureName: string): Promise<void> {
|
||||
this._premiumAlertFeatureName = featureName
|
||||
return when(() => this._premiumAlertFeatureName === undefined)
|
||||
this.premiumAlertFeatureName = featureName
|
||||
return when(() => this.premiumAlertFeatureName === undefined)
|
||||
}
|
||||
|
||||
public async closePremiumAlert(): Promise<void> {
|
||||
this._premiumAlertFeatureName = undefined
|
||||
public closePremiumAlert() {
|
||||
this.premiumAlertFeatureName = undefined
|
||||
}
|
||||
|
||||
get isFilesEnabled(): boolean {
|
||||
return this.hasFilesBeta || window.enabledUnfinishedFeatures || isDev
|
||||
}
|
||||
|
||||
get isEntitledToFiles(): boolean {
|
||||
return this.hasFilesBeta
|
||||
}
|
||||
|
||||
private hasNativeFolders(): boolean {
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import { confirmDialog } from '@/Services/AlertService'
|
||||
import { STRING_DELETE_TAG } from '@/Strings'
|
||||
import { MAX_MENU_SIZE_MULTIPLIER, MENU_MARGIN_FROM_APP_BORDER } from '@/Constants'
|
||||
import {
|
||||
MAX_MENU_SIZE_MULTIPLIER,
|
||||
MENU_MARGIN_FROM_APP_BORDER,
|
||||
SMART_TAGS_FEATURE_NAME,
|
||||
} from '@/Constants'
|
||||
import {
|
||||
ComponentAction,
|
||||
ContentType,
|
||||
@@ -15,7 +19,7 @@ import {
|
||||
} from '@standardnotes/snjs'
|
||||
import { action, computed, makeAutoObservable, makeObservable, observable, runInAction } from 'mobx'
|
||||
import { WebApplication } from '../Application'
|
||||
import { FeaturesState, SMART_TAGS_FEATURE_NAME } from './FeaturesState'
|
||||
import { FeaturesState } from './FeaturesState'
|
||||
|
||||
type AnyTag = SNTag | SmartView
|
||||
|
||||
|
||||
Reference in New Issue
Block a user