diff --git a/.yarn/cache/@standardnotes-domain-core-npm-1.25.0-51a2ed924b-f99196f620.zip b/.yarn/cache/@standardnotes-domain-core-npm-1.28.0-e07c009747-9ee58eea35.zip similarity index 77% rename from .yarn/cache/@standardnotes-domain-core-npm-1.25.0-51a2ed924b-f99196f620.zip rename to .yarn/cache/@standardnotes-domain-core-npm-1.28.0-e07c009747-9ee58eea35.zip index aa20e6ae0..8de0cca17 100644 Binary files a/.yarn/cache/@standardnotes-domain-core-npm-1.25.0-51a2ed924b-f99196f620.zip and b/.yarn/cache/@standardnotes-domain-core-npm-1.28.0-e07c009747-9ee58eea35.zip differ diff --git a/packages/api/package.json b/packages/api/package.json index 222b3aa41..1c7900ca8 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -36,7 +36,7 @@ }, "dependencies": { "@standardnotes/common": "^1.50.0", - "@standardnotes/domain-core": "^1.25.0", + "@standardnotes/domain-core": "^1.28.0", "@standardnotes/models": "workspace:*", "@standardnotes/responses": "workspace:*", "@standardnotes/utils": "workspace:*", diff --git a/packages/desktop/package.json b/packages/desktop/package.json index d837d60d9..5dac3aefc 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -35,7 +35,7 @@ }, "dependencies": { "@electron/remote": "^2.0.9", - "@standardnotes/domain-core": "^1.25.0", + "@standardnotes/domain-core": "^1.28.0", "@standardnotes/electron-clear-data": "1.1.1", "@standardnotes/web": "workspace:*", "axios": "^1.1.3", diff --git a/packages/encryption/package.json b/packages/encryption/package.json index 2b65d1dad..52376e056 100644 --- a/packages/encryption/package.json +++ b/packages/encryption/package.json @@ -29,7 +29,7 @@ }, "dependencies": { "@standardnotes/common": "^1.50.0", - "@standardnotes/domain-core": "^1.25.0", + "@standardnotes/domain-core": "^1.28.0", "@standardnotes/models": "workspace:*", "@standardnotes/responses": "workspace:*", "@standardnotes/sncrypto-common": "workspace:*", diff --git a/packages/features/package.json b/packages/features/package.json index 8437d86cd..61458cc4d 100644 --- a/packages/features/package.json +++ b/packages/features/package.json @@ -26,7 +26,7 @@ }, "dependencies": { "@standardnotes/common": "^1.50.0", - "@standardnotes/domain-core": "^1.25.0", + "@standardnotes/domain-core": "^1.28.0", "reflect-metadata": "^0.1.13" }, "devDependencies": { diff --git a/packages/features/src/Domain/Feature/NativeFeatureIdentifier.ts b/packages/features/src/Domain/Feature/NativeFeatureIdentifier.ts index f4897d03d..b28385901 100644 --- a/packages/features/src/Domain/Feature/NativeFeatureIdentifier.ts +++ b/packages/features/src/Domain/Feature/NativeFeatureIdentifier.ts @@ -41,6 +41,8 @@ export class NativeFeatureIdentifier extends ValueObject(Web_TYPES.FilesController), this.get(Web_TYPES.SubscriptionController), this.get(Web_TYPES.NavigationController), + this.get(Web_TYPES.FeaturesController), this.get(Web_TYPES.ItemGroupController), this.get(Web_TYPES.VaultDisplayService), application.preferences, diff --git a/packages/web/src/javascripts/Components/ContentListView/ListItemVaultInfo.tsx b/packages/web/src/javascripts/Components/ContentListView/ListItemVaultInfo.tsx index 953cb25af..a5402281a 100644 --- a/packages/web/src/javascripts/Components/ContentListView/ListItemVaultInfo.tsx +++ b/packages/web/src/javascripts/Components/ContentListView/ListItemVaultInfo.tsx @@ -3,7 +3,6 @@ import { useApplication } from '../ApplicationProvider' import Icon from '../Icon/Icon' import { DecryptedItemInterface, classNames } from '@standardnotes/snjs' import VaultNameBadge from '../Vaults/VaultNameBadge' -import { featureTrunkVaultsEnabled } from '@/FeatureTrunk' type Props = { item: DecryptedItemInterface @@ -13,7 +12,7 @@ type Props = { const ListItemVaultInfo: FunctionComponent = ({ item, className }) => { const application = useApplication() - if (!featureTrunkVaultsEnabled()) { + if (!application.featuresController.isEntitledToVaults()) { return null } diff --git a/packages/web/src/javascripts/Components/FileContextMenu/FileMenuOptions.tsx b/packages/web/src/javascripts/Components/FileContextMenu/FileMenuOptions.tsx index 5cfc99053..23b59caba 100644 --- a/packages/web/src/javascripts/Components/FileContextMenu/FileMenuOptions.tsx +++ b/packages/web/src/javascripts/Components/FileContextMenu/FileMenuOptions.tsx @@ -14,7 +14,6 @@ import AddTagOption from '../NotesOptions/AddTagOption' import { MenuItemIconSize } from '@/Constants/TailwindClassNames' import AddToVaultMenuOption from '../Vaults/AddToVaultMenuOption' import { iconClass } from '../NotesOptions/ClassNames' -import { featureTrunkVaultsEnabled } from '@/FeatureTrunk' import { useApplication } from '../ApplicationProvider' type Props = { @@ -87,7 +86,9 @@ const FileMenuOptions: FunctionComponent = ({ ) : null} )} - {featureTrunkVaultsEnabled() && } + {application.featuresController.isEntitledToVaults() && ( + + )} { @@ -16,7 +15,7 @@ const VaultSelectionButton = ({ isMobileNavigation = false }: { isMobileNavigati const [isOpen, setIsOpen] = useState(false) const toggleMenu = () => setIsOpen(!isOpen) - if (!featureTrunkVaultsEnabled()) { + if (!application.featuresController.isEntitledToVaults()) { return null } diff --git a/packages/web/src/javascripts/Components/NoteView/CollaborationInfoHUD.tsx b/packages/web/src/javascripts/Components/NoteView/CollaborationInfoHUD.tsx index c59d0ec0b..57df63d86 100644 --- a/packages/web/src/javascripts/Components/NoteView/CollaborationInfoHUD.tsx +++ b/packages/web/src/javascripts/Components/NoteView/CollaborationInfoHUD.tsx @@ -2,7 +2,6 @@ import { FunctionComponent } from 'react' import Icon from '../Icon/Icon' import { useApplication } from '../ApplicationProvider' import { DecryptedItemInterface } from '@standardnotes/snjs' -import { featureTrunkVaultsEnabled } from '@/FeatureTrunk' import VaultNameBadge from '../Vaults/VaultNameBadge' type Props = { @@ -12,7 +11,7 @@ type Props = { const CollaborationInfoHUD: FunctionComponent = ({ item }) => { const application = useApplication() - if (!featureTrunkVaultsEnabled()) { + if (!application.featuresController.isEntitledToVaults()) { return null } @@ -32,7 +31,7 @@ const CollaborationInfoHUD: FunctionComponent = ({ item }) => { {lastEditedBy && ( -
+
{lastEditedBy?.name}
diff --git a/packages/web/src/javascripts/Components/NotesOptions/NotesOptions.tsx b/packages/web/src/javascripts/Components/NotesOptions/NotesOptions.tsx index f3dddd96b..04f4d5e7c 100644 --- a/packages/web/src/javascripts/Components/NotesOptions/NotesOptions.tsx +++ b/packages/web/src/javascripts/Components/NotesOptions/NotesOptions.tsx @@ -41,7 +41,6 @@ import SuperExportModal from './SuperExportModal' import { useApplication } from '../ApplicationProvider' import { MutuallyExclusiveMediaQueryBreakpoints } from '@/Hooks/useMediaQuery' import AddToVaultMenuOption from '../Vaults/AddToVaultMenuOption' -import { featureTrunkVaultsEnabled } from '@/FeatureTrunk' import Menu from '../Menu/Menu' import Popover from '../Popover/Popover' @@ -267,7 +266,9 @@ const NotesOptions = ({ notes, closeMenu }: NotesOptionsProps) => { )} - {featureTrunkVaultsEnabled() && } + {application.featuresController.isEntitledToVaults() && ( + + )} {application.navigationController.tagsCount > 0 && ( { continueTitle: DEFAULT_CONTINUE_TITLE, } - if (featureTrunkVaultsEnabled()) { + if (props.application.featuresController.isEntitledToVaults()) { this.state = { ...baseState, lockContinue: true, diff --git a/packages/web/src/javascripts/Components/Preferences/Controller/PreferencesSessionController.ts b/packages/web/src/javascripts/Components/Preferences/Controller/PreferencesSessionController.ts index e53b4863d..3b0f43fc7 100644 --- a/packages/web/src/javascripts/Components/Preferences/Controller/PreferencesSessionController.ts +++ b/packages/web/src/javascripts/Components/Preferences/Controller/PreferencesSessionController.ts @@ -4,7 +4,7 @@ import { PackageProvider } from '../Panes/General/Advanced/Packages/Provider/Pac import { securityPrefsHasBubble } from '../Panes/Security/securityPrefsHasBubble' import { PreferencePaneId, StatusServiceEvent } from '@standardnotes/services' import { isDesktopApplication } from '@/Utils' -import { featureTrunkHomeServerEnabled, featureTrunkVaultsEnabled } from '@/FeatureTrunk' +import { featureTrunkHomeServerEnabled } from '@/FeatureTrunk' import { PreferencesMenuItem } from './PreferencesMenuItem' import { SelectableMenuItem } from './SelectableMenuItem' import { PREFERENCES_MENU_ITEMS, READY_PREFERENCES_MENU_ITEMS } from './MenuItems' @@ -26,7 +26,7 @@ export class PreferencesSessionController { ? PREFERENCES_MENU_ITEMS.slice() : READY_PREFERENCES_MENU_ITEMS.slice() - if (featureTrunkVaultsEnabled()) { + if (application.featuresController.isEntitledToVaults()) { menuItems.push({ id: 'vaults', label: 'Vaults', icon: 'safe-square', order: 5 }) } diff --git a/packages/web/src/javascripts/Components/Tags/Navigation.tsx b/packages/web/src/javascripts/Components/Tags/Navigation.tsx index 922b61cc7..fbb79ccb5 100644 --- a/packages/web/src/javascripts/Components/Tags/Navigation.tsx +++ b/packages/web/src/javascripts/Components/Tags/Navigation.tsx @@ -14,7 +14,6 @@ import { PaneLayout } from '@/Controllers/PaneController/PaneLayout' import { usePaneSwipeGesture } from '../Panes/usePaneGesture' import { mergeRefs } from '@/Hooks/mergeRefs' import { useAvailableSafeAreaPadding } from '@/Hooks/useSafeAreaPadding' -import { featureTrunkVaultsEnabled } from '@/FeatureTrunk' import QuickSettingsButton from '../Footer/QuickSettingsButton' import VaultSelectionButton from '../Footer/VaultSelectionButton' @@ -131,7 +130,7 @@ const Navigation = forwardRef(({ application, className, icon="tune" /> - {featureTrunkVaultsEnabled() && } + {application.featuresController.isEntitledToVaults() && }
{children} diff --git a/packages/web/src/javascripts/Components/Tags/TagContextMenu.tsx b/packages/web/src/javascripts/Components/Tags/TagContextMenu.tsx index 872346a4b..b045aacc7 100644 --- a/packages/web/src/javascripts/Components/Tags/TagContextMenu.tsx +++ b/packages/web/src/javascripts/Components/Tags/TagContextMenu.tsx @@ -12,7 +12,6 @@ import { PremiumFeatureIconClass, PremiumFeatureIconName } from '../Icon/Premium import Popover from '../Popover/Popover' import IconPicker from '../Icon/IconPicker' import AddToVaultMenuOption from '../Vaults/AddToVaultMenuOption' -import { featureTrunkVaultsEnabled } from '@/FeatureTrunk' import { useApplication } from '../ApplicationProvider' type ContextMenuProps = { @@ -82,7 +81,7 @@ const TagContextMenu = ({ navigationController, isEntitledToFolders, selectedTag iconGridClassName="max-h-30" /> - {featureTrunkVaultsEnabled() && ( + {application.featuresController.isEntitledToVaults() && ( )} diff --git a/packages/web/src/javascripts/Components/Vaults/AddToVaultMenuOption.tsx b/packages/web/src/javascripts/Components/Vaults/AddToVaultMenuOption.tsx index 9a911188a..a6284808d 100644 --- a/packages/web/src/javascripts/Components/Vaults/AddToVaultMenuOption.tsx +++ b/packages/web/src/javascripts/Components/Vaults/AddToVaultMenuOption.tsx @@ -7,7 +7,6 @@ import { classNames, DecryptedItemInterface, VaultListingInterface } from '@stan import { useApplication } from '../ApplicationProvider' import MenuItem from '../Menu/MenuItem' import Menu from '../Menu/Menu' -import { featureTrunkVaultsEnabled } from '@/FeatureTrunk' const VaultMenu = observer(({ items }: { items: DecryptedItemInterface[] }) => { const application = useApplication() @@ -107,6 +106,7 @@ const VaultMenu = observer(({ items }: { items: DecryptedItemInterface[] }) => { }) const AddToVaultMenuOption = ({ iconClassName, items }: { iconClassName: string; items: DecryptedItemInterface[] }) => { + const application = useApplication() const buttonRef = useRef(null) const [isSubMenuOpen, setIsSubMenuOpen] = useState(false) @@ -115,7 +115,7 @@ const AddToVaultMenuOption = ({ iconClassName, items }: { iconClassName: string; setIsSubMenuOpen((isOpen) => !isOpen) }, []) - if (!featureTrunkVaultsEnabled()) { + if (!application.featuresController.isEntitledToVaults()) { return null } diff --git a/packages/web/src/javascripts/Controllers/FeaturesController.ts b/packages/web/src/javascripts/Controllers/FeaturesController.ts index 6675bb040..8b23759b8 100644 --- a/packages/web/src/javascripts/Controllers/FeaturesController.ts +++ b/packages/web/src/javascripts/Controllers/FeaturesController.ts @@ -12,6 +12,7 @@ import { import { action, makeObservable, observable, runInAction, when } from 'mobx' import { AbstractViewController } from './Abstract/AbstractViewController' import { CrossControllerEvent } from './CrossControllerEvent' +import { featureTrunkVaultsEnabled } from '@/FeatureTrunk' export class FeaturesController extends AbstractViewController implements InternalEventHandlerInterface { hasFolders: boolean @@ -128,4 +129,13 @@ export class FeaturesController extends AbstractViewController implements Intern return status === FeatureStatus.Entitled } + + isEntitledToVaults(): boolean { + const status = this.features.getFeatureStatus( + NativeFeatureIdentifier.create(NativeFeatureIdentifier.TYPES.SharedVaults).getValue(), + ) + const isEntitledToFeature = status === FeatureStatus.Entitled + + return featureTrunkVaultsEnabled() || isEntitledToFeature + } } diff --git a/packages/web/src/javascripts/Controllers/LinkingController.spec.ts b/packages/web/src/javascripts/Controllers/LinkingController.spec.ts index a4b339761..6d2c5ddbf 100644 --- a/packages/web/src/javascripts/Controllers/LinkingController.spec.ts +++ b/packages/web/src/javascripts/Controllers/LinkingController.spec.ts @@ -22,6 +22,7 @@ import { LinkingController } from './LinkingController' import { NavigationController } from './Navigation/NavigationController' import { SubscriptionController } from './Subscription/SubscriptionController' import { getLinkingSearchResults } from '@/Utils/Items/Search/getSearchResults' +import { FeaturesController } from './FeaturesController' const createNote = (name: string, options?: Partial) => { return { @@ -63,11 +64,13 @@ describe('LinkingController', () => { itemListController: {} as jest.Mocked, filesController: {} as jest.Mocked, subscriptionController: {} as jest.Mocked, + featuresController: {} as jest.Mocked, } as unknown as jest.Mocked application.getPreference = jest.fn() application.addSingleEventObserver = jest.fn() application.sync.sync = jest.fn() + application.featuresController.isEntitledToVaults = jest.fn().mockReturnValue(true) Object.defineProperty(application, 'items', { value: {} as jest.Mocked }) @@ -81,6 +84,7 @@ describe('LinkingController', () => { application.filesController, application.subscriptionController, application.navigationController, + application.featuresController, application.itemControllerGroup, application.vaultDisplayService, application.preferences, diff --git a/packages/web/src/javascripts/Controllers/LinkingController.tsx b/packages/web/src/javascripts/Controllers/LinkingController.tsx index 2ca063e91..7eba1d9d7 100644 --- a/packages/web/src/javascripts/Controllers/LinkingController.tsx +++ b/packages/web/src/javascripts/Controllers/LinkingController.tsx @@ -32,9 +32,9 @@ import { FilesController } from './FilesController' import { ItemListController } from './ItemList/ItemListController' import { NavigationController } from './Navigation/NavigationController' import { SubscriptionController } from './Subscription/SubscriptionController' -import { featureTrunkVaultsEnabled } from '@/FeatureTrunk' import { ItemGroupController } from '@/Components/NoteView/Controller/ItemGroupController' import { VaultDisplayServiceInterface } from '@standardnotes/ui-services' +import { FeaturesController } from './FeaturesController' export class LinkingController extends AbstractViewController implements InternalEventHandlerInterface { shouldLinkToParentFolders: boolean @@ -45,6 +45,7 @@ export class LinkingController extends AbstractViewController implements Interna private filesController: FilesController, private subscriptionController: SubscriptionController, private navigationController: NavigationController, + private featuresController: FeaturesController, private itemControllerGroup: ItemGroupController, private vaultDisplayService: VaultDisplayServiceInterface, private preferences: PreferenceServiceInterface, @@ -207,7 +208,7 @@ export class LinkingController extends AbstractViewController implements Interna const linkNoteAndFile = async (note: SNNote, file: FileItem) => { const updatedFile = await this.mutator.associateFileWithNote(file, note) - if (featureTrunkVaultsEnabled()) { + if (this.featuresController.isEntitledToVaults()) { if (updatedFile) { const noteVault = this.vaults.getItemVault(note) const fileVault = this.vaults.getItemVault(updatedFile) diff --git a/yarn.lock b/yarn.lock index 6f2bd5b12..7a5c81b13 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4138,7 +4138,7 @@ __metadata: resolution: "@standardnotes/api@workspace:packages/api" dependencies: "@standardnotes/common": ^1.50.0 - "@standardnotes/domain-core": ^1.25.0 + "@standardnotes/domain-core": ^1.28.0 "@standardnotes/models": "workspace:*" "@standardnotes/responses": "workspace:*" "@standardnotes/utils": "workspace:*" @@ -4288,7 +4288,7 @@ __metadata: "@babel/core": "*" "@babel/preset-env": "*" "@electron/remote": ^2.0.9 - "@standardnotes/domain-core": ^1.25.0 + "@standardnotes/domain-core": ^1.28.0 "@standardnotes/electron-clear-data": 1.1.1 "@standardnotes/web": "workspace:*" "@types/fs-extra": ^11.0.1 @@ -4340,12 +4340,12 @@ __metadata: languageName: node linkType: hard -"@standardnotes/domain-core@npm:^1.25.0": - version: 1.25.0 - resolution: "@standardnotes/domain-core@npm:1.25.0" +"@standardnotes/domain-core@npm:^1.28.0": + version: 1.28.0 + resolution: "@standardnotes/domain-core@npm:1.28.0" dependencies: uuid: ^9.0.0 - checksum: f99196f6209a05a50e84371d3a59cf870937a5589f4ba4caab0f2eb17c2cfa733142b18ca8788016c81ca609d1f5a0461e51bcf159a67d631e249a04a5568244 + checksum: 9ee58eea35ed5d988513c5a24f751b9c3a2be2a324c30684db54ecbd16f0c8e19a80b8e464bde46e86905590085923c7e1abbe1b792a4ef0a19c1171e8f3b6c2 languageName: node linkType: hard @@ -4392,7 +4392,7 @@ __metadata: dependencies: "@standardnotes/common": ^1.50.0 "@standardnotes/config": 2.4.3 - "@standardnotes/domain-core": ^1.25.0 + "@standardnotes/domain-core": ^1.28.0 "@standardnotes/models": "workspace:*" "@standardnotes/responses": "workspace:*" "@standardnotes/sncrypto-common": "workspace:*" @@ -4427,7 +4427,7 @@ __metadata: resolution: "@standardnotes/features@workspace:packages/features" dependencies: "@standardnotes/common": ^1.50.0 - "@standardnotes/domain-core": ^1.25.0 + "@standardnotes/domain-core": ^1.28.0 "@types/jest": ^29.2.3 "@typescript-eslint/eslint-plugin": "*" eslint: "*" @@ -4633,7 +4633,7 @@ __metadata: resolution: "@standardnotes/models@workspace:packages/models" dependencies: "@standardnotes/common": ^1.50.0 - "@standardnotes/domain-core": ^1.25.0 + "@standardnotes/domain-core": ^1.28.0 "@standardnotes/features": "workspace:*" "@standardnotes/responses": "workspace:*" "@standardnotes/sncrypto-common": "workspace:^" @@ -4729,7 +4729,7 @@ __metadata: dependencies: "@standardnotes/api": "workspace:^" "@standardnotes/common": ^1.50.0 - "@standardnotes/domain-core": ^1.25.0 + "@standardnotes/domain-core": ^1.28.0 "@standardnotes/encryption": "workspace:^" "@standardnotes/features": "workspace:^" "@standardnotes/files": "workspace:^" @@ -4828,7 +4828,7 @@ __metadata: "@babel/preset-env": "*" "@standardnotes/api": "workspace:*" "@standardnotes/common": ^1.50.0 - "@standardnotes/domain-core": ^1.25.0 + "@standardnotes/domain-core": ^1.28.0 "@standardnotes/domain-events": ^2.122.0 "@standardnotes/encryption": "workspace:*" "@standardnotes/features": "workspace:*" @@ -4953,7 +4953,7 @@ __metadata: resolution: "@standardnotes/ui-services@workspace:packages/ui-services" dependencies: "@standardnotes/common": ^1.50.0 - "@standardnotes/domain-core": ^1.25.0 + "@standardnotes/domain-core": ^1.28.0 "@standardnotes/features": "workspace:^" "@standardnotes/filepicker": "workspace:^" "@standardnotes/models": "workspace:^"