diff --git a/services/web/app/src/models/User.mjs b/services/web/app/src/models/User.mjs index a9d3c2a900..2555e748c8 100644 --- a/services/web/app/src/models/User.mjs +++ b/services/web/app/src/models/User.mjs @@ -154,6 +154,10 @@ export const UserSchema = new Schema( default: Settings.defaultFeatures.symbolPalette, }, aiUsageQuota: { type: String, default: 'basic' }, + offlineMode: { + type: Boolean, + default: Settings.defaultFeatures.offlineMode, + }, }, featuresOverrides: [ { @@ -181,6 +185,7 @@ export const UserSchema = new Schema( zotero: { type: Boolean }, referencesSearch: { type: Boolean }, symbolPalette: { type: Boolean }, + offlineMode: { type: Boolean }, }, }, ], diff --git a/services/web/config/settings.defaults.js b/services/web/config/settings.defaults.js index 219ff1c5a1..8ca78ce6f4 100644 --- a/services/web/config/settings.defaults.js +++ b/services/web/config/settings.defaults.js @@ -435,6 +435,7 @@ module.exports = { compileGroup: 'standard', references: true, trackChanges: true, + offlineMode: false, }), // featuresEpoch: 'YYYY-MM-DD', diff --git a/services/web/frontend/js/features/ide-react/context/unsaved-docs-context.tsx b/services/web/frontend/js/features/ide-react/context/unsaved-docs-context.tsx index ad9bcb9a7b..5050d0505e 100644 --- a/services/web/frontend/js/features/ide-react/context/unsaved-docs-context.tsx +++ b/services/web/frontend/js/features/ide-react/context/unsaved-docs-context.tsx @@ -34,7 +34,7 @@ export const UnsavedDocsProvider: FC = ({ const { permissionsLevel, setPermissionsLevel } = useIdeReactContext() const [isLocked, setIsLocked] = useState(false) const [unsavedDocs, setUnsavedDocs] = useState(new Map()) - const isPremiumUser = Boolean(getMeta('ol-user')?.features?.versioning) + const isPremiumUser = Boolean(getMeta('ol-user')?.features?.offlineMode) const intermittentConnectionImprovementsEnabled = useFeatureFlag( 'intermittent-connection-improvements' ) diff --git a/services/web/test/acceptance/config/settings.test.defaults.js b/services/web/test/acceptance/config/settings.test.defaults.js index f2a72335db..8f32bb9b08 100644 --- a/services/web/test/acceptance/config/settings.test.defaults.js +++ b/services/web/test/acceptance/config/settings.test.defaults.js @@ -116,6 +116,7 @@ module.exports = { trackChanges: false, symbolPalette: false, aiUsageQuota: 'basic', + offlineMode: false, }, personal: { collaborators: 1, @@ -133,6 +134,7 @@ module.exports = { trackChanges: false, symbolPalette: false, aiUsageQuota: 'basic', + offlineMode: false, }, collaborator: { collaborators: 10, @@ -150,6 +152,7 @@ module.exports = { trackChanges: true, symbolPalette: true, aiUsageQuota: 'basic', + offlineMode: true, }, professional: { collaborators: -1, @@ -167,6 +170,7 @@ module.exports = { trackChanges: true, symbolPalette: true, aiUsageQuota: 'basic', + offlineMode: true, }, }), diff --git a/services/web/test/frontend/features/ide-react/context/unsaved-docs-context.spec.tsx b/services/web/test/frontend/features/ide-react/context/unsaved-docs-context.spec.tsx index 43f4d7e9ee..325ffa0eb3 100644 --- a/services/web/test/frontend/features/ide-react/context/unsaved-docs-context.spec.tsx +++ b/services/web/test/frontend/features/ide-react/context/unsaved-docs-context.spec.tsx @@ -44,10 +44,9 @@ function mount( intermittentConnectionImprovementsEnabled?: boolean } = {} ) { - // the provider reads getMeta('ol-user') to decide the lock threshold; the - // `versioning` feature marks a premium user + // the provider reads getMeta('ol-user') to decide the lock threshold window.metaAttributesCache.set('ol-user', { - features: isPremiumUser ? { versioning: true } : {}, + features: isPremiumUser ? { offlineMode: true } : {}, }) // the provider reads the split test variant via useFeatureFlag window.metaAttributesCache.set('ol-splitTestVariants', { diff --git a/services/web/test/frontend/features/subscription/fixtures/plans.ts b/services/web/test/frontend/features/subscription/fixtures/plans.ts index aed10f6782..a204147af1 100644 --- a/services/web/test/frontend/features/subscription/fixtures/plans.ts +++ b/services/web/test/frontend/features/subscription/fixtures/plans.ts @@ -18,6 +18,7 @@ const features = { compileGroup: 'priority', trackChanges: true, symbolPalette: true, + offlineMode: true, }, personal: { aiUsageQuota: 'basic', @@ -35,6 +36,7 @@ const features = { compileGroup: 'priority', trackChanges: false, symbolPalette: true, + offlineMode: true, }, collaborator: { aiUsageQuota: 'standard', @@ -52,6 +54,7 @@ const features = { compileGroup: 'priority', trackChanges: true, symbolPalette: true, + offlineMode: true, }, professional: { aiUsageQuota: 'unlimited', @@ -69,6 +72,7 @@ const features = { compileGroup: 'priority', trackChanges: true, symbolPalette: true, + offlineMode: true, }, } satisfies Record diff --git a/services/web/test/unit/src/Subscription/UserFeaturesUpdater.test.mjs b/services/web/test/unit/src/Subscription/UserFeaturesUpdater.test.mjs index a0167f9c42..87a1af72d2 100644 --- a/services/web/test/unit/src/Subscription/UserFeaturesUpdater.test.mjs +++ b/services/web/test/unit/src/Subscription/UserFeaturesUpdater.test.mjs @@ -20,6 +20,7 @@ describe('UserFeaturesUpdater', function () { zotero: true, mendeley: true, symbolPalette: true, + offlineMode: true, } ctx.User = { findByIdAndUpdate: sinon.stub().returns({ diff --git a/services/web/types/subscription/plan.ts b/services/web/types/subscription/plan.ts index 062ef725f2..82b16cc541 100644 --- a/services/web/types/subscription/plan.ts +++ b/services/web/types/subscription/plan.ts @@ -9,6 +9,7 @@ export type Features = { gitBridge: boolean github: boolean mendeley: boolean + offlineMode: boolean references: boolean referencesSearch: boolean symbolPalette: boolean diff --git a/services/web/types/user.ts b/services/web/types/user.ts index 036ae15783..91c923b207 100644 --- a/services/web/types/user.ts +++ b/services/web/types/user.ts @@ -18,6 +18,7 @@ export type Features = { gitBridge?: boolean github?: boolean mendeley?: boolean + offlineMode?: boolean papers?: boolean references?: boolean referencesSearch?: boolean