[feedback] IJPL-177421 Permanent CSAT survey in IDEs

Fix hashes computation for show condition

(cherry picked from commit b07545e8cb52c438bc26c487fb9672624c3c1217)


(cherry picked from commit b34b16e13a124ec955924fa613ce72f9e06cfa9e)

IJ-MR-155667

GitOrigin-RevId: 136aa670b8a125c4c41dcb69a9047258ad8d73b8
This commit is contained in:
Yuriy Artamonov
2025-02-11 19:56:21 +01:00
committed by intellij-monorepo-bot
parent e41d4d19bb
commit f0b1bb4c47
4 changed files with 21 additions and 7 deletions

View File

@@ -34,6 +34,12 @@ interface FeedbackSurveyConfig {
*/
val requireIdeEAP: Boolean
/**
* Whether the survey is allowed to be shown indefinite times. Must only be used by product and not plugins.
*/
val isIndefinite: Boolean
get() = false
/**
* Checks whether the IDE is suitable for the feedback survey.
*

View File

@@ -19,6 +19,7 @@ import kotlinx.datetime.LocalDate
import kotlinx.datetime.Month
import java.time.format.DateTimeFormatter
import java.time.temporal.ChronoUnit
import kotlin.math.abs
internal const val USER_CONSIDERED_NEW_DAYS = 30
internal const val NEW_USER_SURVEY_PERIOD = 29
@@ -71,8 +72,8 @@ internal class CsatFeedbackSurveyConfig : InIdeFeedbackSurveyConfig {
val surveyPeriod = if (isNewUser) NEW_USER_SURVEY_PERIOD else EXISTING_USER_SURVEY_PERIOD
val productHash = (ApplicationInfo.getInstance().versionName + MachineIdManager.getAnonymizedMachineId("CSAT Survey")).hashCode() % surveyPeriod
val daysHash = ChronoUnit.DAYS.between(java.time.LocalDate.of(1970, 1, 1), today).hashCode() % surveyPeriod
val productHash = abs((ApplicationInfo.getInstance().versionName + MachineIdManager.getAnonymizedMachineId("CSAT Survey")).hashCode()) % surveyPeriod
val daysHash = abs(ChronoUnit.DAYS.between(java.time.LocalDate.of(1970, 1, 1), today).toInt()) % surveyPeriod
if (productHash != daysHash) {
LOG.debug("Periods do not match: $productHash / $daysHash, is not yet suitable date for the survey")

View File

@@ -14,7 +14,6 @@ import kotlinx.datetime.Clock
import kotlinx.datetime.TimeZone
import kotlinx.datetime.todayIn
internal const val MAX_FEEDBACK_SURVEY_NUMBER_SHOWS: Int = 2
internal fun FeedbackSurveyConfig.checkIsFeedbackCollectionDeadlineNotPast(): Boolean {
@@ -61,7 +60,7 @@ internal fun isSuitableToShow(feedbackSurveyConfig: FeedbackSurveyConfig, projec
true
}
else {
!CommonFeedbackSurveyService.checkIsFeedbackSurveyAnswerSent(feedbackSurveyConfig.surveyId) &&
!CommonFeedbackSurveyService.checkIsFeedbackSurveyAnswerSent(feedbackSurveyConfig) &&
feedbackSurveyConfig.checkIdeIsSuitable() &&
feedbackSurveyConfig.checkIsFeedbackCollectionDeadlineNotPast() &&
feedbackSurveyConfig.checkIsIdeEAPIfRequired() &&
@@ -106,7 +105,8 @@ private fun browseToSurvey(project: Project, feedbackSurveyConfig: ExternalFeedb
}
private fun checkNumberShowsNotExceeded(feedbackSurveyConfig: FeedbackSurveyConfig): Boolean {
return CommonFeedbackSurveyService.getNumberShowsOfFeedbackSurvey(
feedbackSurveyConfig.surveyId) < MAX_FEEDBACK_SURVEY_NUMBER_SHOWS
if (feedbackSurveyConfig.isIndefinite) return true
return CommonFeedbackSurveyService.getNumberShowsOfFeedbackSurvey(feedbackSurveyConfig.surveyId) < MAX_FEEDBACK_SURVEY_NUMBER_SHOWS
}

View File

@@ -2,13 +2,13 @@
package com.intellij.platform.feedback.impl.state
import com.intellij.openapi.components.*
import com.intellij.platform.feedback.FeedbackSurveyConfig
import kotlinx.serialization.Serializable
@Service(Service.Level.APP)
@State(name = "CommonFeedbackSurveyService", storages = [Storage("CommonFeedbackSurveyService.xml", roamingType = RoamingType.DISABLED)])
class CommonFeedbackSurveyService : PersistentStateComponent<CommonFeedbackSurveysState> {
companion object {
@JvmStatic
fun getNumberShowsOfFeedbackSurvey(surveyId: String): Int {
return getInstance().state.feedbackSurveyToNumberNotificationShows.getOrDefault(surveyId, 0)
@@ -54,6 +54,13 @@ class CommonFeedbackSurveyService : PersistentStateComponent<CommonFeedbackSurve
return getInstance().state.answeredFeedbackSurveys.contains(surveyId)
}
@JvmStatic
fun checkIsFeedbackSurveyAnswerSent(config: FeedbackSurveyConfig): Boolean {
if (config.isIndefinite) return false
return checkIsFeedbackSurveyAnswerSent(config.surveyId)
}
@JvmStatic
fun getAllAnsweredFeedbackSurveys(): Set<String> {
return getInstance().state.answeredFeedbackSurveys