diff --git a/services/web/app/views/project/editor/editor.pug b/services/web/app/views/project/editor/editor.pug index 87beb0b2f8..b4d01693dc 100644 --- a/services/web/app/views/project/editor/editor.pug +++ b/services/web/app/views/project/editor/editor.pug @@ -12,6 +12,8 @@ div.full-size( custom-toggler-msg-when-open=hasFeature('custom-togglers') ? translate("tooltip_hide_pdf") : false custom-toggler-msg-when-closed=hasFeature('custom-togglers') ? translate("tooltip_show_pdf") : false ) + cm6-switch-away-survey() + include ./editor-pane .ui-layout-east diff --git a/services/web/frontend/js/features/source-editor/components/cm6-switch-away-survey.tsx b/services/web/frontend/js/features/source-editor/components/cm6-switch-away-survey.tsx new file mode 100644 index 0000000000..ebc3dc0771 --- /dev/null +++ b/services/web/frontend/js/features/source-editor/components/cm6-switch-away-survey.tsx @@ -0,0 +1,98 @@ +import { useCallback, useEffect, useRef, useState } from 'react' +import { Button } from 'react-bootstrap' +import customLocalStorage from '../../../infrastructure/local-storage' +import useScopeValue from '../../../shared/hooks/use-scope-value' + +type CM6SwitchAwaySurveyState = 'disabled' | 'enabled' | 'shown' + +export default function CM6SwitchAwaySurvey() { + const [state, setState] = useState('disabled') + const [newSourceEditor] = useScopeValue('editor.newSourceEditor') + const [richText] = useScopeValue('editor.showRichText') + const initialRichTextPreference = useRef(richText) + + useEffect(() => { + // If the user has previously seen the survey, then don't show it again + const hasSeenCM6SwitchAwaySurvey = customLocalStorage.getItem( + 'editor.has_seen_cm6_switch_away_survey' + ) + if (hasSeenCM6SwitchAwaySurvey) return + + if (initialRichTextPreference.current) { + if (!richText && newSourceEditor) { + // If user change from rich text to cm6, we remove the rich text preference + // so if user use rich text -> cm6 -> ace, we will show the survey + initialRichTextPreference.current = false + } + + // If the user loaded rich text initially, then don't show the survey + // (we are assuming that they will not have used CM6 as much) + return + } + + if (!newSourceEditor) { + setState('enabled') + } + }, [newSourceEditor, richText]) + + useEffect(() => { + if (state === 'enabled') { + const handleKeyDown = () => { + const TIME_FOR_SURVEY_TO_APPEAR = 3000 + + setTimeout(() => { + setState('shown') + customLocalStorage.setItem( + 'editor.has_seen_cm6_switch_away_survey', + true + ) + }, TIME_FOR_SURVEY_TO_APPEAR) + } + + // can't access the ace editor directly, so add the keydown event + // to window + window?.addEventListener('keydown', handleKeyDown, { once: true }) + } + }, [state]) + + const handleClose = useCallback(() => { + setState('disabled') + }, []) + + if (state !== 'shown') { + return null + } + + return ( +
+ +
+
+
+ We noticed that you're still using the{' '} + Source (legacy) editor. +
+
Could you let us know why?
+
+
+ + Take survey + +
+
+
+ ) +} diff --git a/services/web/frontend/js/features/source-editor/controllers/cm6-switch-away-survey-controller.js b/services/web/frontend/js/features/source-editor/controllers/cm6-switch-away-survey-controller.js new file mode 100644 index 0000000000..c4881f503d --- /dev/null +++ b/services/web/frontend/js/features/source-editor/controllers/cm6-switch-away-survey-controller.js @@ -0,0 +1,9 @@ +import App from '../../../base' +import { react2angular } from 'react2angular' +import { rootContext } from '../../../shared/context/root-context' +import CM6SwitchAwaySurvey from '../components/cm6-switch-away-survey' + +App.component( + 'cm6SwitchAwaySurvey', + react2angular(rootContext.use(CM6SwitchAwaySurvey)) +) diff --git a/services/web/frontend/js/ide.js b/services/web/frontend/js/ide.js index 8b3b84c9f1..6c3d84ffdc 100644 --- a/services/web/frontend/js/ide.js +++ b/services/web/frontend/js/ide.js @@ -64,6 +64,7 @@ import './features/editor-navigation-toolbar/controllers/editor-navigation-toolb import './features/pdf-preview/controllers/pdf-preview-controller' import './features/share-project-modal/controllers/react-share-project-modal-controller' import './features/source-editor/controllers/editor-switch-controller' +import './features/source-editor/controllers/cm6-switch-away-survey-controller' import { cleanupServiceWorker } from './utils/service-worker-cleanup' import { reportCM6Perf } from './infrastructure/cm6-performance' diff --git a/services/web/frontend/js/ide/editor/EditorManager.js b/services/web/frontend/js/ide/editor/EditorManager.js index 28dee0257c..9771960add 100644 --- a/services/web/frontend/js/ide/editor/EditorManager.js +++ b/services/web/frontend/js/ide/editor/EditorManager.js @@ -176,11 +176,20 @@ export default EditorManager = (function () { return false } - const sourceEditor = this.localStorage( - `editor.source_editor.${this.$scope.project_id}` + const hasSeenCM6SwitchAwaySurvey = this.localStorage( + 'editor.has_seen_cm6_switch_away_survey' ) - return sourceEditor === 'cm6' || sourceEditor == null + if (hasSeenCM6SwitchAwaySurvey) { + const sourceEditor = this.localStorage( + `editor.source_editor.${this.$scope.project_id}` + ) + + return sourceEditor === 'cm6' || sourceEditor == null + } else { + // force user to switch to cm6 if they haven't seen the switch away survey + return true + } } autoOpenDoc() { diff --git a/services/web/frontend/stylesheets/app/editor.less b/services/web/frontend/stylesheets/app/editor.less index f6ba46e4c8..2a296df545 100644 --- a/services/web/frontend/stylesheets/app/editor.less +++ b/services/web/frontend/stylesheets/app/editor.less @@ -799,3 +799,31 @@ CodeMirror } } } + +.cm6-switch-away-survey { + padding: @padding-sm; + box-shadow: 5px 5px 6px rgba(0, 0, 0, 0.3); + background-color: @ol-blue; + width: 530px; + position: absolute; + right: @margin-sm; + bottom: @margin-xl; + z-index: @zindex-popover; + + .btn.close { + background-color: @ol-blue; + } + + .warning-content { + display: flex; + align-items: center; + justify-content: space-between; + margin-right: 32px; + } + + .warning-text { + padding-right: @alert-padding; + display: inline-block; + font-size: @font-size-small; + } +}