IJPL-171506 Implement trial survey

ABT-32 IJ-MR-152914

(cherry picked from commit a5c47204f33b7736eaac962cd9c1b32855f7a25e)


(cherry picked from commit bfcf2844796b9bccefa7db3607a8f0cb73517e42)

IJ-CR-154529

GitOrigin-RevId: 9f5d59cfc83c084e294704c70fe63374fc783b02
This commit is contained in:
Alexey.Merkulov
2025-01-21 12:59:41 +01:00
committed by intellij-monorepo-bot
parent d65cff38d2
commit b3f3d0c3e3
6 changed files with 130 additions and 0 deletions

View File

@@ -15,6 +15,8 @@
implementationClass="com.intellij.platform.experiment.ab.impl.statistic.ABExperimentCountCollector"/>
<statistics.validation.customValidationRule
implementation="com.intellij.platform.experiment.ab.impl.statistic.ABExperimentOptionIdValidationRule"/>
<experiment.abExperimentOption implementation="com.intellij.platform.experiment.ab.temporary.ShowTrialSurveyOption"/>
</extensions>
<actions>

View File

@@ -0,0 +1,36 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.platform.experiment.ab.temporary
import com.intellij.openapi.application.ApplicationInfo
import com.intellij.platform.experiment.ab.impl.experiment.ABExperiment
import com.intellij.platform.experiment.ab.impl.experiment.ABExperimentOption
import com.intellij.platform.experiment.ab.impl.experiment.ABExperimentOptionId
import com.intellij.platform.experiment.ab.impl.option.ABExperimentOptionGroupSize
import com.intellij.util.PlatformUtils
import org.jetbrains.annotations.ApiStatus
@ApiStatus.Internal
class ShowTrialSurveyOption : ABExperimentOption {
override val id: ABExperimentOptionId = ABExperimentOptionId("showTrialSurvey")
override fun getGroupSizeForIde(isPopularIde: Boolean): ABExperimentOptionGroupSize {
return ABExperimentOptionGroupSize(128)
}
override fun checkIdeIsSuitable(): Boolean = PlatformUtils.isIdeaUltimate()
/**
* Experiment should be available only in 2024.3.3
*/
override fun checkIdeVersionIsSuitable(): Boolean {
val appInfo = ApplicationInfo.getInstance()
return appInfo.majorVersion == "2024" && appInfo.minorVersion == "3.3"
}
@Suppress("CompanionObjectInExtension")
companion object {
@JvmStatic
val isTrialSurveyEnabled: Boolean get() = System.getProperty("test.ide.trial.survey", "false").toBoolean() ||
ABExperiment.getABExperimentInstance().isExperimentOptionEnabled(ShowTrialSurveyOption::class.java)
}
}

View File

@@ -3144,3 +3144,11 @@ popup.text.non.commercial.usage=<b>Non-commercial use only</b><br><br>With your
<li>Switch to a trial or paid license at any time</li></ul><a href="https://www.jetbrains.com/legal/docs/toolbox/license_non-commercial/">Agreement for non-commercial use</a>\
<br><br><a href="{0}">Plans and pricing</a>
popup.license.button.non.commercial.usage=Manage Licenses\u2026
trial.survey.learn=I want to learn how to use a specific feature, language, or framework
trial.survey.check.for.daily=I am evaluating whether it will be useful for my daily tasks
trial.survey.check.new.features=I am evaluating new features introduced in the latest release
trial.survey.waiting.license=I am waiting for a license from my employer
trial.survey.no.goal=I do not have a specific goal
trial.survey.another.reason=My reason is not listed here

View File

@@ -0,0 +1,19 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.openapi.wm.impl.welcomeScreen.survey
import com.intellij.internal.statistic.eventLog.EventLogGroup
import com.intellij.internal.statistic.eventLog.events.EventFields
import com.intellij.internal.statistic.service.fus.collectors.CounterUsagesCollector
internal object IdeSurveyCollector : CounterUsagesCollector() {
private val GROUP = EventLogGroup("ide.survey", 1)
val trialSurveyAnswer = EventFields.Enum<TrialSurveyOptions>("answer")
val answerIndex = EventFields.Int("index")
private val trialSurveyAnsweredEvent = GROUP.registerEvent("trial.survey.answered", trialSurveyAnswer, answerIndex)
fun logTrialSurveyAnswered(answer: TrialSurveyOptions, index: Int) = trialSurveyAnsweredEvent.log(answer, index)
override fun getGroup(): EventLogGroup = GROUP
}

View File

@@ -0,0 +1,63 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.openapi.wm.impl.welcomeScreen.survey
import com.intellij.ide.IdeBundle
import com.intellij.openapi.ui.DialogPanel
import com.intellij.openapi.util.NlsContexts
import com.intellij.ui.dsl.builder.TopGap
import com.intellij.ui.dsl.builder.bind
import com.intellij.ui.dsl.builder.panel
import com.intellij.util.ui.JBInsets
import com.intellij.util.ui.JBUI
import org.jetbrains.annotations.ApiStatus
import javax.swing.JButton
import javax.swing.JComponent
internal enum class TrialSurveyOptions(@NlsContexts.RadioButton val text: String) {
Unselected(""),
Learn(IdeBundle.message("trial.survey.learn")),
CheckForDaily(IdeBundle.message("trial.survey.check.for.daily")),
CheckNewFeatures(IdeBundle.message("trial.survey.check.new.features")),
WaitingLicense(IdeBundle.message("trial.survey.waiting.license")),
NoGoal(IdeBundle.message("trial.survey.no.goal")),
AnotherReason(IdeBundle.message("trial.survey.another.reason")),
}
@ApiStatus.Internal
fun trialSurveyPanel(createButtonsPanel: (JButton) -> JComponent, activateTrialButtonFn: (() -> Unit) -> JButton): DialogPanel {
var chosenOption: Pair<TrialSurveyOptions, Int> = TrialSurveyOptions.Unselected to -1
lateinit var panel: DialogPanel
val activateTrialButton = activateTrialButtonFn {
reportSurveyAnswer(chosenOption)
panel.apply()
}
//LicenseDialogComponents.adjustStartTrialButtonText(model, activateTrialButton)
activateTrialButton.isEnabled = false
val options = (TrialSurveyOptions.entries - TrialSurveyOptions.Unselected - TrialSurveyOptions.AnotherReason).shuffled() +
TrialSurveyOptions.AnotherReason
panel = panel {
buttonsGroup {
for ((index, value) in options.withIndex()) {
row {
val option = value to index
radioButton(value.text, option).onChanged { activateTrialButton.isEnabled = true }
}
}
}.bind({ chosenOption }, { chosenOption = it })
row {
cell(createButtonsPanel(activateTrialButton))
}.topGap(TopGap.MEDIUM)
}
panel.border = JBUI.Borders.empty(JBInsets(0, 36, 0, 36))
return panel
}
private fun reportSurveyAnswer(chosenOption: Pair<TrialSurveyOptions, Int>) {
val (value, order) = chosenOption
IdeSurveyCollector.logTrialSurveyAnswered(value, order)
}

View File

@@ -631,6 +631,8 @@
<welcomeFrameProvider implementation="com.intellij.openapi.wm.impl.welcomeScreen.FlatWelcomeFrameProvider"/>
<welcomeTabFactory id="ProjectsWelcomeTab" implementation="com.intellij.openapi.wm.impl.welcomeScreen.ProjectsTabFactory"/>
<registryKey defaultValue="3" description="Number of primary buttons on welcome screen (other go to 'more actions')" key="welcome.screen.primaryButtonsCount" restartRequired="true"/>
<statistics.counterUsagesCollector
implementationClass="com.intellij.openapi.wm.impl.welcomeScreen.survey.IdeSurveyCollector"/>
<statistics.counterUsagesCollector
implementationClass="com.intellij.openapi.wm.impl.welcomeScreen.statistics.WelcomeScreenCounterUsageCollector"/>
<welcomeTabFactory id="CustomizeWelcomeTab" implementation="com.intellij.openapi.wm.impl.welcomeScreen.CustomizeTabFactory"