IDEA-254595 language plugin suggestion: try language if locale failed
[idea/community.git] / platform / platform-impl / src / com / intellij / ide / LanguageDetector.kt
1 // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 package com.intellij.ide
3
4 import com.intellij.ide.plugins.PluginManagerCore
5 import com.intellij.ide.plugins.PluginNode
6 import com.intellij.ide.plugins.marketplace.FeatureImpl
7 import com.intellij.ide.plugins.marketplace.MarketplaceRequests
8 import com.intellij.notification.Notification
9 import com.intellij.notification.NotificationAction
10 import com.intellij.notification.NotificationGroupManager
11 import com.intellij.openapi.application.ApplicationBundle
12 import com.intellij.openapi.application.ApplicationInfo
13 import com.intellij.openapi.application.Experiments
14 import com.intellij.openapi.application.ex.ApplicationManagerEx
15 import com.intellij.openapi.project.Project
16 import com.intellij.openapi.startup.StartupActivity
17 import com.intellij.openapi.updateSettings.impl.pluginsAdvertisement.PluginsAdvertiser
18 import java.util.*
19
20 class LanguageDetector : StartupActivity.Background {
21   override fun runActivity(project: Project) {
22     if (!Experiments.getInstance().isFeatureEnabled("language.detect.notification")) return
23
24     findPlugin()?.let { notify(project, it) }
25   }
26
27   companion object {
28     private fun matchedLanguagePlugins(): List<FeatureImpl> {
29       val features = getFeatures(Locale.getDefault().toLanguageTag())
30       if (features.isNotEmpty()) return features
31
32       return getFeatures(Locale.getDefault().language)
33     }
34
35     private fun getFeatures(languageTag: String): List<FeatureImpl> {
36       val build = MarketplaceRequests.getInstance().getBuildForPluginRepositoryRequests()
37       val params = mapOf("featureType" to "com.intellij.locale", "implementationName" to languageTag, "build" to build)
38       return MarketplaceRequests.getInstance().getFeatures(params)
39     }
40
41     private fun verifiedLanguagePlugins() = MarketplaceRequests.getInstance().searchPlugins("tags=Language%20Pack", 10)
42
43     private fun installAction(project: Project, matchedVerifiedPlugin: PluginNode, notification: Notification) =
44       NotificationAction.create(ApplicationBundle.message("notification.action.language.plugin.install.and.enable")) { _, _ ->
45         PluginsAdvertiser.installAndEnable(project, setOf(matchedVerifiedPlugin.pluginId), false, Runnable {
46           notification.expire()
47           ApplicationManagerEx.getApplicationEx().restart(true)
48         })
49       }
50
51     private fun findPlugin() = verifiedLanguagePlugins()
52       .firstOrNull {
53         matchedLanguagePlugins().any { matched -> matched.pluginId == it.pluginId.idString }
54         && !PluginManagerCore.isPluginInstalled(it.pluginId)
55       }
56
57     private fun notify(project: Project, plugin: PluginNode) {
58       val notificationTitle = ApplicationBundle.message("notification.title.language.plugin.enable",
59                                                         ApplicationInfo.getInstance().fullApplicationName)
60       NotificationGroupManager.getInstance().getNotificationGroup("Language Plugins Notifications")
61         .createNotification(notificationTitle, null, null)
62         .also { it.addAction(installAction(project, plugin, it)) }
63         .notify(project)
64     }
65   }
66 }