Skip to content

Commit 229f5d2

Browse files
committed
chore: chnage survey to notification instead of popup to not take user focus
1 parent 43270aa commit 229f5d2

File tree

4 files changed

+94
-52
lines changed

4 files changed

+94
-52
lines changed

src/extensionsIntegrated/Phoenix/guided-tour.js

Lines changed: 79 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ define(function (require, exports, module) {
3737
// All popup notifications will show immediately on boot, we don't want to interrupt user amidst his work
3838
// by showing it at a later point in time.
3939
const GENERAL_SURVEY_TIME = 1200000, // 20 min
40-
POWER_USER_SURVEY_TIME = 10000, // 10 seconds to allow the survey to preload, but not
40+
SURVEY_PRELOAD_DELAY = 10000, // 10 seconds to allow the survey to preload, but not
4141
// enough time to break user workflow
4242
ONE_MONTH_IN_DAYS = 30,
4343
POWER_USER_SURVEY_INTERVAL_DAYS = 35;
@@ -212,27 +212,23 @@ define(function (require, exports, module) {
212212
}
213213
}
214214

215-
function _showGeneralSurvey(surveyURL, delayOverride) {
215+
function _showFirstUseSurvey(surveyURL, delayOverride, title, useDialog) {
216216
let surveyVersion = 6; // increment this if you want to show this again
217217
if(userAlreadyDidAction.generalSurveyShownVersion === surveyVersion) {
218218
return;
219219
}
220-
const $surveyFrame = addSurveyIframe(surveyURL);
220+
let $surveyFrame;
221+
if(useDialog){
222+
$surveyFrame = addSurveyIframe(surveyURL);
223+
}
221224
setTimeout(()=>{
222-
const templateVars = {
223-
Strings: Strings
224-
};
225-
let positionObserver;
226-
Metrics.countEvent(Metrics.EVENT_TYPE.USER, "survey", "generalShown", 1);
227-
Dialogs.showModalDialogUsingTemplate(Mustache.render(SurveyTemplate, templateVars)).done(()=>{
228-
positionObserver && positionObserver.disconnect();
229-
$surveyFrame.remove();
230-
});
231-
setTimeout(()=>{
232-
const $surveyFrameContainer = $('#surveyFrameContainer');
233-
repositionIframe($surveyFrame, $surveyFrameContainer);
234-
positionObserver = observerPositionChanges($surveyFrame, $surveyFrameContainer);
235-
}, 200);
225+
if(useDialog){
226+
Metrics.countEvent(Metrics.EVENT_TYPE.USER, "survey", "firstDialog", 1);
227+
_showDialogSurvey($surveyFrame);
228+
} else {
229+
Metrics.countEvent(Metrics.EVENT_TYPE.USER, "survey", "firstNotification", 1);
230+
_showSurveyNotification(surveyURL, title);
231+
}
236232
userAlreadyDidAction.generalSurveyShownVersion = surveyVersion;
237233
PhStore.setItem(GUIDED_TOUR_LOCAL_STORAGE_KEY, JSON.stringify(userAlreadyDidAction));
238234
}, delayOverride || GENERAL_SURVEY_TIME);
@@ -275,38 +271,66 @@ define(function (require, exports, module) {
275271
return resizeObserver;
276272
}
277273

278-
function _showPowerUserSurvey(surveyURL, intervalOverride) {
279-
if(Metrics.isPowerUser()) {
280-
const intervalDays = intervalOverride || POWER_USER_SURVEY_INTERVAL_DAYS;
281-
Metrics.countEvent(Metrics.EVENT_TYPE.USER, "power", "user", 1);
282-
let lastShownDate = userAlreadyDidAction.lastShownPowerSurveyDate;
283-
let nextShowDate = new Date(lastShownDate);
284-
nextShowDate.setUTCDate(nextShowDate.getUTCDate() + intervalDays);
285-
let currentDate = new Date();
286-
if(currentDate < nextShowDate){
287-
return;
288-
}
274+
function _showDialogSurvey($surveyFrame) {
275+
const templateVars = {
276+
Strings: Strings
277+
};
278+
let positionObserver;
279+
Dialogs.showModalDialogUsingTemplate(Mustache.render(SurveyTemplate, templateVars))
280+
.done(()=>{
281+
positionObserver && positionObserver.disconnect();
282+
$surveyFrame.remove();
283+
});
284+
const $surveyFrameContainer = $('#surveyFrameContainer');
285+
setTimeout(()=>{
286+
repositionIframe($surveyFrame, $surveyFrameContainer);
287+
positionObserver = observerPositionChanges($surveyFrame, $surveyFrameContainer);
288+
}, 200);
289+
}
290+
291+
function _showSurveyNotification(surveyUrl, title) {
292+
NotificationUI.createToastFromTemplate(
293+
title || Strings.SURVEY_TITLE_VOTE_FOR_FEATURES_YOU_WANT,
294+
`<div class="survey-notification-popup">
295+
<iframe src="${surveyUrl}" style="width: 500px; height: 645px;" frameborder="0"></iframe></div>`, {
296+
toastStyle: `${NotificationUI.NOTIFICATION_STYLES_CSS_CLASS.INFO} survey-notification-big forced-hidden`,
297+
dismissOnClick: false
298+
});
299+
setTimeout(()=>{
300+
$('.survey-notification-big').removeClass('forced-hidden');
301+
}, SURVEY_PRELOAD_DELAY);
302+
}
303+
304+
function _showRepeatUserSurvey(surveyURL, intervalOverride, title, useDialog) {
305+
let nextPowerSurveyShowDate = userAlreadyDidAction.nextPowerSurveyShowDate;
306+
if(!nextPowerSurveyShowDate){
307+
// first boot, we schedule the power user survey to happen in two weeks
308+
let nextShowDate = new Date();
309+
nextShowDate.setUTCDate(nextShowDate.getUTCDate() + 14); // the first time repeat survey always shows up
310+
// always after 2 weeks.
311+
userAlreadyDidAction.nextPowerSurveyShowDate = nextShowDate.getTime();
312+
PhStore.setItem(GUIDED_TOUR_LOCAL_STORAGE_KEY, JSON.stringify(userAlreadyDidAction));
313+
return;
314+
}
315+
const intervalDays = intervalOverride || POWER_USER_SURVEY_INTERVAL_DAYS;
316+
let nextShowDate = new Date(nextPowerSurveyShowDate);
317+
let currentDate = new Date();
318+
if(currentDate < nextShowDate){
319+
return;
320+
}
321+
if(useDialog){
289322
const $surveyFrame = addSurveyIframe(surveyURL);
290323
setTimeout(()=>{
291-
Metrics.countEvent(Metrics.EVENT_TYPE.USER, "survey", "powerShown", 1);
292-
const templateVars = {
293-
Strings: Strings
294-
};
295-
let positionObserver;
296-
Dialogs.showModalDialogUsingTemplate(Mustache.render(SurveyTemplate, templateVars))
297-
.done(()=>{
298-
positionObserver && positionObserver.disconnect();
299-
$surveyFrame.remove();
300-
});
301-
const $surveyFrameContainer = $('#surveyFrameContainer');
302-
setTimeout(()=>{
303-
repositionIframe($surveyFrame, $surveyFrameContainer);
304-
positionObserver = observerPositionChanges($surveyFrame, $surveyFrameContainer);
305-
}, 200);
306-
userAlreadyDidAction.lastShownPowerSurveyDate = Date.now();
307-
PhStore.setItem(GUIDED_TOUR_LOCAL_STORAGE_KEY, JSON.stringify(userAlreadyDidAction));
308-
}, POWER_USER_SURVEY_TIME);
324+
Metrics.countEvent(Metrics.EVENT_TYPE.USER, "survey", "powerDialog", 1);
325+
_showDialogSurvey($surveyFrame);
326+
}, SURVEY_PRELOAD_DELAY);
327+
} else {
328+
Metrics.countEvent(Metrics.EVENT_TYPE.USER, "survey", "powerNotification", 1);
329+
_showSurveyNotification(surveyURL, title);
309330
}
331+
nextShowDate.setUTCDate(nextShowDate.getUTCDate() + intervalDays);
332+
userAlreadyDidAction.nextPowerSurveyShowDate = nextShowDate.getTime();
333+
PhStore.setItem(GUIDED_TOUR_LOCAL_STORAGE_KEY, JSON.stringify(userAlreadyDidAction));
310334
}
311335

312336
async function _showSurveys() {
@@ -319,14 +343,20 @@ define(function (require, exports, module) {
319343
if(!Phoenix.isNativeApp && surveyJSON.browser) {
320344
surveyJSON = {
321345
newUser: surveyJSON.browser.newUser || surveyJSON.newUser,
346+
newUserTitle: surveyJSON.browser.newUserTitle || surveyJSON.newUserTitle,
322347
newUserShowDelayMS: surveyJSON.browser.newUserShowDelayMS || surveyJSON.newUserShowDelayMS,
348+
newUserUseDialog: surveyJSON.browser.newUserUseDialog || surveyJSON.newUserUseDialog,
323349
powerUser: surveyJSON.browser.powerUser || surveyJSON.powerUser,
350+
powerUserTitle: surveyJSON.browser.powerUserTitle || surveyJSON.powerUserTitle,
324351
powerUserShowIntervalDays: surveyJSON.browser.powerUserShowIntervalDays
325-
|| surveyJSON.powerUserShowIntervalDays
352+
|| surveyJSON.powerUserShowIntervalDays,
353+
powerUserUseDialog: surveyJSON.browser.powerUserUseDialog || surveyJSON.powerUserUseDialog
326354
};
327355
}
328-
surveyJSON.newUser && _showGeneralSurvey(surveyJSON.newUser, surveyJSON.newUserShowDelayMS);
329-
surveyJSON.powerUser && _showPowerUserSurvey(surveyJSON.powerUser, surveyJSON.powerUserShowIntervalDays);
356+
surveyJSON.newUser && _showFirstUseSurvey(surveyJSON.newUser, surveyJSON.newUserShowDelayMS,
357+
surveyJSON.newUserTitle, surveyJSON.newUserUseDialog);
358+
surveyJSON.powerUser && _showRepeatUserSurvey(surveyJSON.powerUser, surveyJSON.powerUserShowIntervalDays,
359+
surveyJSON.powerUserTitle, surveyJSON.powerUserUseDialog);
330360
} catch (e) {
331361
console.error("Error fetching survey link", surveyLinksURL, e);
332362
Metrics.countEvent(Metrics.EVENT_TYPE.USER, "survey", "fetchError", 1);

src/nls/root/strings.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1528,5 +1528,8 @@ define({
15281528
"ERROR_PUSHING_OPERATION": "Pushing operation failed",
15291529
"ERROR_NO_REMOTE_SELECTED": "No remote has been selected for {0}!",
15301530
"ERROR_BRANCH_LIST": "Getting branch list failed",
1531-
"ERROR_FETCH_REMOTE": "Fetching remote information failed"
1531+
"ERROR_FETCH_REMOTE": "Fetching remote information failed",
1532+
1533+
// surveys
1534+
"SURVEY_TITLE_VOTE_FOR_FEATURES_YOU_WANT": "Vote for the features you want to see next!"
15321535
});

src/styles/brackets.less

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3267,7 +3267,7 @@ label input {
32673267
}
32683268

32693269
.notification-popup-close-button {
3270-
font-size: 16px;
3270+
font-size: 24px;
32713271
font-weight: 900;
32723272
position: absolute;
32733273
top: 0;
@@ -3557,3 +3557,11 @@ label input {
35573557
flex-direction: column;
35583558
justify-content: space-between
35593559
}
3560+
3561+
.notification-popup-container.survey-notification-big {
3562+
margin-left: -274px;
3563+
background-color: #f3f5f9; // match with survey planet
3564+
.notification-popup-close-button:hover {
3565+
color: @bc-primary-btn-border-focused-glow;
3566+
}
3567+
}

src/widgets/NotificationUI.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,10 +316,11 @@ define(function (require, exports, module) {
316316
* The message can either be a string or a jQuery object representing a DOM node that is *not* in the current DOM.
317317
*
318318
* Creating a toast notification popup
319+
*
320+
* ```js
319321
* // note that you can even provide an HTML Element node with
320322
* // custom event handlers directly here instead of HTML text.
321323
* let notification1 = NotificationUI.createToastFromTemplate( "Title here",
322-
* ```js
323324
* "<div>Click me to locate the file in file tree</div>", {
324325
* dismissOnClick: false,
325326
* autoCloseTimeS: 300 // auto close the popup after 5 minutes

0 commit comments

Comments
 (0)