@@ -32,7 +32,8 @@ define(function (require, exports, module) {
3232
3333 const EventDispatcher = require ( "utils/EventDispatcher" ) ,
3434 AIControl = require ( "./ai-control" ) ,
35- Strings = require ( "strings" ) ;
35+ Strings = require ( "strings" ) ,
36+ StringUtils = require ( "utils/StringUtils" ) ;
3637
3738 const MS_IN_DAY = 24 * 60 * 60 * 1000 ;
3839 const FREE_PLAN_VALIDITY_DAYS = 10000 ;
@@ -169,6 +170,117 @@ define(function (require, exports, module) {
169170 } ;
170171 }
171172
173+ /**
174+ * Get AI is enabled for user, based on his logged in pro-user/trial status.
175+ *
176+ * @returns {Promise<Object> } AI entitlement object with the following shape:
177+ * @returns {Promise<boolean> } entitlement.activated - If true, enable AI features. If false, check upsellDialog.
178+ * @returns {Promise<boolean> } [entitlement.needsLogin] - If true, user needs to login first.
179+ * @returns {Promise<string> } [entitlement.aiBrandName] - The brand name used for AI. Eg: `Phoenix AI`
180+ * @returns {Promise<string> } [entitlement.buyURL] - URL to subscribe/purchase if not activated. Can be null if AI
181+ * is not purchasable.
182+ * @returns {Promise<string> } [entitlement.upgradeToPlan] - Plan name that includes AI entitlement
183+ * @returns {Promise<number> } [entitlement.validTill] - Timestamp when entitlement expires (if from server)
184+ * @returns {Promise<Object> } [entitlement.upsellDialog] - Dialog configuration if user needs to be shown an upsell.
185+ * Only present when activated is false.
186+ * @returns {Promise<string> } [entitlement.upsellDialog.title] - Dialog title
187+ * @returns {Promise<string> } [entitlement.upsellDialog.message] - Dialog message
188+ * @returns {Promise<string> } [entitlement.upsellDialog.buyURL] - Purchase URL. If present, dialog shows
189+ * "Get AI Access" button. If absent, shows only OK button.
190+ *
191+ * @example
192+ * const aiEntitlement = await EntitlementsManager.getAIEntitlement();
193+ * if (aiEntitlement.activated) {
194+ * // Enable AI features
195+ * enableAIFeature();
196+ * } else if (aiEntitlement.upsellDialog) {
197+ * // Show upsell dialog when user tries to use AI
198+ * promotions.showAIUpsellDialog(aiEntitlement);
199+ * }
200+ */
201+ async function getAIEntitlement ( ) {
202+ if ( ! isLoggedIn ( ) ) {
203+ return {
204+ needsLogin : true ,
205+ activated : false ,
206+ upsellDialog : {
207+ title : Strings . AI_LOGIN_DIALOG_TITLE ,
208+ message : Strings . AI_LOGIN_DIALOG_MESSAGE
209+ // no buy url as it is a sign in hint. only ok button will be there in this dialog.
210+ }
211+ } ;
212+ }
213+ const aiControlStatus = await EntitlementsManager . getAIControlStatus ( ) ;
214+ if ( ! aiControlStatus . aiEnabled ) {
215+ return {
216+ activated : false ,
217+ upsellDialog : {
218+ title : Strings . AI_DISABLED_DIALOG_TITLE ,
219+ // Eg. AI is disabled by school admin/root user.
220+ // no buyURL as ai is disabled explicitly. only ok button will be there in this dialog.
221+ message : aiControlStatus . message || Strings . AI_CONTROL_ADMIN_DISABLED
222+ }
223+ } ;
224+ }
225+ const defaultAIBrandName = brackets . config . ai_brand_name ,
226+ defaultPurchaseURL = brackets . config . purchase_url ,
227+ defaultUpsellTitle = StringUtils . format ( Strings . AI_UPSELL_DIALOG_TITLE , defaultAIBrandName ) ;
228+ const entitlements = await _getEffectiveEntitlements ( ) ;
229+ if ( ! entitlements || ! entitlements . entitlements || ! entitlements . entitlements . aiAgent ) {
230+ return {
231+ activated : false ,
232+ aiBrandName : defaultAIBrandName ,
233+ buyURL : defaultPurchaseURL ,
234+ upgradeToPlan : defaultAIBrandName ,
235+ upsellDialog : {
236+ title : defaultUpsellTitle ,
237+ message : Strings . AI_UPSELL_DIALOG_MESSAGE ,
238+ buyURL : defaultPurchaseURL
239+ }
240+ } ;
241+ }
242+ const aiEntitlement = entitlements . entitlements . aiAgent ;
243+ // entitlements.entitlements.aiAgent: {
244+ // activated: boolean,
245+ // aiBrandName: string,
246+ // subscribeURL: string,
247+ // upgradeToPlan: string,
248+ // validTill: number,
249+ // upsellDialog: {
250+ // title: "if activated is false, server can send a custom upsell dialog to show",
251+ // message: "this is the message to show",
252+ // buyURL: "if this url is present from server, this will be shown to as buy link"
253+ // }
254+ // }
255+
256+ if ( aiEntitlement . activated ) {
257+ return {
258+ activated : true ,
259+ aiBrandName : aiEntitlement . aiBrandName ,
260+ buyURL : aiEntitlement . subscribeURL ,
261+ upgradeToPlan : aiEntitlement . upgradeToPlan ,
262+ validTill : aiEntitlement . validTill
263+ // no upsellDialog, as it need not be shown.
264+ } ;
265+ }
266+
267+ const upsellTitle = StringUtils . format ( Strings . AI_UPSELL_DIALOG_TITLE ,
268+ aiEntitlement . aiBrandName || defaultAIBrandName ) ;
269+ const upsellDialog = aiEntitlement . upsellDialog || { } ;
270+ return {
271+ activated : false ,
272+ aiBrandName : aiEntitlement . aiBrandName ,
273+ buyURL : aiEntitlement . subscribeURL || defaultPurchaseURL ,
274+ upgradeToPlan : aiEntitlement . upgradeToPlan ,
275+ validTill : aiEntitlement . validTill ,
276+ upsellDialog : {
277+ title : upsellDialog . title || upsellTitle ,
278+ message : upsellDialog . message || Strings . AI_UPSELL_DIALOG_MESSAGE ,
279+ buyURL : upsellDialog . buyURL || aiEntitlement . subscribeURL || defaultPurchaseURL
280+ }
281+ } ;
282+ }
283+
172284 let inited = false ;
173285 function init ( ) {
174286 if ( inited ) {
@@ -209,5 +321,6 @@ define(function (require, exports, module) {
209321 EntitlementsManager . getTrialRemainingDays = getTrialRemainingDays ;
210322 EntitlementsManager . getRawEntitlements = getRawEntitlements ;
211323 EntitlementsManager . getLiveEditEntitlement = getLiveEditEntitlement ;
324+ EntitlementsManager . getAIEntitlement = getAIEntitlement ;
212325 EntitlementsManager . EVENT_ENTITLEMENTS_CHANGED = EVENT_ENTITLEMENTS_CHANGED ;
213326} ) ;
0 commit comments