mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-223967 new update dialog: provide "What's New" notification that opens editor with HTML after IDE restart
GitOrigin-RevId: 243fadd69f9e7efc1d25e26a6e4c7831f87214a9
This commit is contained in:
committed by
intellij-monorepo-bot
parent
3c4b5284a8
commit
ef891fef3d
@@ -2,6 +2,7 @@
|
||||
package com.intellij.internal
|
||||
|
||||
import com.intellij.ide.util.BrowseFilesListener
|
||||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.application.ApplicationInfo
|
||||
import com.intellij.openapi.application.ApplicationNamesInfo
|
||||
@@ -32,7 +33,7 @@ class ShowUpdateInfoDialogAction : DumbAwareAction() {
|
||||
val dialog = MyDialog(e.project)
|
||||
if (dialog.showAndGet()) {
|
||||
try {
|
||||
UpdateChecker.testPlatformUpdate(dialog.updateXmlText(), dialog.patchFilePath(), dialog.forceUpdate())
|
||||
UpdateChecker.testPlatformUpdate(AnAction.getEventProject(e), dialog.updateXmlText (), dialog.patchFilePath(), dialog.forceUpdate())
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
Messages.showErrorDialog(e.project, "${ex.javaClass.name}: ${ex.message}", "Something Went Wrong")
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
// Copyright 2000-2019 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.
|
||||
package com.intellij.openapi.fileEditor.impl
|
||||
|
||||
import com.intellij.openapi.fileEditor.FileEditor
|
||||
import com.intellij.openapi.fileEditor.FileEditorPolicy
|
||||
import com.intellij.openapi.fileEditor.FileEditorProvider
|
||||
import com.intellij.openapi.project.DumbAware
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.openapi.util.KeyWithDefaultValue
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
|
||||
class HTMLEditorProvider : FileEditorProvider, DumbAware {
|
||||
override fun createEditor(project: Project, file: VirtualFile): FileEditor = HTMLFileEditor(file)
|
||||
|
||||
override fun accept(project: Project, file: VirtualFile) = file.getUserData(HTML_CONTENT_TYPE)!!
|
||||
|
||||
override fun getEditorTypeId() = "html-editor"
|
||||
|
||||
override fun getPolicy() = FileEditorPolicy.HIDE_DEFAULT_EDITOR
|
||||
|
||||
companion object {
|
||||
val HTML_CONTENT_TYPE: Key<Boolean> = KeyWithDefaultValue.create("HTML_CONTENT_TYPE", false)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// Copyright 2000-2019 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.
|
||||
package com.intellij.openapi.fileEditor.impl
|
||||
|
||||
import com.intellij.openapi.fileEditor.FileEditor
|
||||
import com.intellij.openapi.fileEditor.FileEditorLocation
|
||||
import com.intellij.openapi.fileEditor.FileEditorState
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.openapi.vfs.VfsUtil
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.util.ui.JBUI
|
||||
import com.intellij.util.ui.UIUtil
|
||||
import java.beans.PropertyChangeListener
|
||||
import javax.swing.JComponent
|
||||
import javax.swing.JEditorPane
|
||||
|
||||
class HTMLFileEditor(private val vFile: VirtualFile) : FileEditor {
|
||||
private val component: JComponent =
|
||||
JEditorPane().also {
|
||||
it.editorKit = UIUtil.getHTMLEditorKit()
|
||||
it.text = VfsUtil.loadText(vFile)
|
||||
it.border = JBUI.Borders.empty(8, 12)
|
||||
it.isEditable = false
|
||||
}
|
||||
|
||||
override fun getComponent(): JComponent = component
|
||||
override fun getPreferredFocusedComponent() = component
|
||||
override fun getName() = "HTML Preview"
|
||||
override fun setState(state: FileEditorState) {}
|
||||
override fun isModified(): Boolean = false
|
||||
override fun isValid(): Boolean = true
|
||||
override fun addPropertyChangeListener(listener: PropertyChangeListener) {}
|
||||
override fun <T : Any?> getUserData(key: Key<T>): T? = null
|
||||
override fun <T : Any?> putUserData(key: Key<T>, value: T?) {}
|
||||
override fun removePropertyChangeListener(listener: PropertyChangeListener) {}
|
||||
override fun getCurrentLocation(): FileEditorLocation? = null
|
||||
override fun dispose() {}
|
||||
}
|
||||
+2
-2
@@ -508,7 +508,7 @@ object UpdateChecker {
|
||||
}
|
||||
|
||||
/** A helper method for manually testing platform updates (see [com.intellij.internal.ShowUpdateInfoDialogAction]). */
|
||||
fun testPlatformUpdate(updateInfoText: String, patchFilePath: String?, forceUpdate: Boolean) {
|
||||
fun testPlatformUpdate(project: Project?, updateInfoText: String, patchFilePath: String?, forceUpdate: Boolean) {
|
||||
if (!ApplicationManager.getApplication().isInternal) {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
@@ -533,7 +533,7 @@ object UpdateChecker {
|
||||
|
||||
if (channel != null && newBuild != null) {
|
||||
val patchFile = if (patchFilePath != null) File(FileUtil.toSystemDependentName(patchFilePath)) else null
|
||||
UpdateInfoDialog(channel, newBuild, patches, patchFile).show()
|
||||
UpdateInfoDialog(project, channel, newBuild, patches, patchFile).show()
|
||||
}
|
||||
else {
|
||||
NoUpdatesDialog(true).show()
|
||||
|
||||
+43
-2
@@ -3,11 +3,16 @@ package com.intellij.openapi.updateSettings.impl;
|
||||
|
||||
import com.intellij.ide.IdeBundle;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.notification.Notification;
|
||||
import com.intellij.notification.NotificationAction;
|
||||
import com.intellij.notification.NotificationListener;
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.application.*;
|
||||
import com.intellij.openapi.application.ex.ApplicationInfoEx;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.fileEditor.impl.HTMLEditorProvider;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.openapi.project.ProjectManagerListener;
|
||||
@@ -15,11 +20,13 @@ import com.intellij.openapi.startup.StartupManager;
|
||||
import com.intellij.openapi.updateSettings.UpdateStrategyCustomization;
|
||||
import com.intellij.openapi.util.BuildNumber;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.testFramework.LightVirtualFile;
|
||||
import com.intellij.util.concurrency.AppExecutorUtil;
|
||||
import com.intellij.util.concurrency.NonUrgentExecutor;
|
||||
import com.intellij.util.messages.MessageBusConnection;
|
||||
import com.intellij.util.text.DateFormatUtil;
|
||||
import org.jdom.JDOMException;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
@@ -38,6 +45,7 @@ public final class UpdateCheckerComponent implements Runnable {
|
||||
}
|
||||
|
||||
static final String SELF_UPDATE_STARTED_FOR_BUILD_PROPERTY = "ide.self.update.started.for.build";
|
||||
@NonNls static final String UPDATE_WHATS_NEW_MESSAGE = "ide.update.whats.new.message";
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(UpdateCheckerComponent.class);
|
||||
|
||||
@@ -50,13 +58,22 @@ public final class UpdateCheckerComponent implements Runnable {
|
||||
Application app = ApplicationManager.getApplication();
|
||||
if (!app.isCommandLine()) {
|
||||
NonUrgentExecutor.getInstance().execute(() -> {
|
||||
checkIfPreviousUpdateFailed();
|
||||
boolean updateFailed = checkIfPreviousUpdateFailed();
|
||||
|
||||
updateDefaultChannel();
|
||||
scheduleFirstCheck();
|
||||
snapPackageNotification();
|
||||
|
||||
MessageBusConnection connection = app.getMessageBus().connect();
|
||||
if (!updateFailed) {
|
||||
connection.subscribe(ProjectManager.TOPIC, new ProjectManagerListener() {
|
||||
@Override
|
||||
public void projectOpened(@NotNull Project project) {
|
||||
StartupManager.getInstance(project).registerPostStartupActivity(() -> { showWhatsNewNotification(project); });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
connection.subscribe(ProjectManager.TOPIC, new ProjectManagerListener() {
|
||||
@Override
|
||||
public void projectOpened(@NotNull Project project) {
|
||||
@@ -82,14 +99,38 @@ public final class UpdateCheckerComponent implements Runnable {
|
||||
if (future != null) future.cancel(false);
|
||||
}
|
||||
|
||||
private static void checkIfPreviousUpdateFailed() {
|
||||
private static void showWhatsNewNotification(@NotNull Project project) {
|
||||
PropertiesComponent properties = PropertiesComponent.getInstance();
|
||||
String updateHtmlMessage = properties.getValue(UPDATE_WHATS_NEW_MESSAGE);
|
||||
if (updateHtmlMessage == null) {
|
||||
LOG.warn("Cannot show what's new notification: no content found.");
|
||||
return;
|
||||
}
|
||||
|
||||
String title = IdeBundle.message("update.whats.new.notification.title", ApplicationNamesInfo.getInstance().getFullProductName());
|
||||
UpdateChecker.NOTIFICATIONS.createNotification(title, null, null, NotificationType.INFORMATION, null)
|
||||
.addAction(new NotificationAction(IdeBundle.message("update.whats.new.notification.action")) {
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e, @NotNull Notification notification) {
|
||||
LightVirtualFile file = new LightVirtualFile(IdeBundle.message("update.whats.new.file.name", ApplicationInfo.getInstance().getFullVersion()), updateHtmlMessage);
|
||||
file.putUserData(HTMLEditorProvider.Companion.getHTML_CONTENT_TYPE(), true);
|
||||
FileEditorManager.getInstance(project).openFile(file, true);
|
||||
IdeUpdateUsageTriggerCollector.trigger("update.whats.new");
|
||||
}
|
||||
});
|
||||
properties.setValue(UPDATE_WHATS_NEW_MESSAGE, null);
|
||||
}
|
||||
|
||||
private static boolean checkIfPreviousUpdateFailed() {
|
||||
PropertiesComponent properties = PropertiesComponent.getInstance();
|
||||
if (ApplicationInfo.getInstance().getBuild().asString().equals(properties.getValue(SELF_UPDATE_STARTED_FOR_BUILD_PROPERTY)) &&
|
||||
new File(PathManager.getLogPath(), ERROR_LOG_FILE_NAME).length() > 0) {
|
||||
IdeUpdateUsageTriggerCollector.trigger("update.failed");
|
||||
LOG.info("The previous IDE update failed");
|
||||
return false;
|
||||
}
|
||||
properties.setValue(SELF_UPDATE_STARTED_FOR_BUILD_PROPERTY, null);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void updateDefaultChannel() {
|
||||
|
||||
+23
-1
@@ -11,15 +11,19 @@ import com.intellij.notification.NotificationType;
|
||||
import com.intellij.openapi.application.*;
|
||||
import com.intellij.openapi.application.impl.ApplicationImpl;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.fileEditor.impl.HTMLEditorProvider;
|
||||
import com.intellij.openapi.progress.PerformInBackgroundOption;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.testFramework.LightVirtualFile;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.ui.LicensingFacade;
|
||||
import com.intellij.util.SystemProperties;
|
||||
@@ -54,6 +58,8 @@ class UpdateInfoDialog extends AbstractUpdateDialog {
|
||||
private final Pair<String, Color> myLicenseInfo;
|
||||
private final File myTestPatch;
|
||||
|
||||
private AbstractAction myWhatsNewAction;
|
||||
|
||||
UpdateInfoDialog(@NotNull UpdateChannel channel,
|
||||
@NotNull BuildInfo newBuild,
|
||||
@Nullable UpdateChain patches,
|
||||
@@ -77,7 +83,7 @@ class UpdateInfoDialog extends AbstractUpdateDialog {
|
||||
IdeUpdateUsageTriggerCollector.triggerUpdateDialog(myPatches, ApplicationManager.getApplication().isRestartCapable());
|
||||
}
|
||||
|
||||
UpdateInfoDialog(UpdateChannel channel, BuildInfo newBuild, UpdateChain patches, @Nullable File patchFile) {
|
||||
UpdateInfoDialog(@Nullable Project project, UpdateChannel channel, BuildInfo newBuild, UpdateChain patches, @Nullable File patchFile) {
|
||||
super(true);
|
||||
myUpdatedChannel = channel;
|
||||
myUpdatedPlugins = null;
|
||||
@@ -86,6 +92,18 @@ class UpdateInfoDialog extends AbstractUpdateDialog {
|
||||
myWriteProtected = false;
|
||||
myLicenseInfo = initLicensingInfo(myUpdatedChannel, myNewBuild);
|
||||
myTestPatch = patchFile;
|
||||
if (project != null) {
|
||||
myWhatsNewAction = new AbstractAction("What's new") {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
String title = IdeBundle.message("update.whats.new.file.name", ApplicationInfo.getInstance().getFullVersion());
|
||||
LightVirtualFile file = new LightVirtualFile(title, myNewBuild.getMessage());
|
||||
file.putUserData(HTMLEditorProvider.Companion.getHTML_CONTENT_TYPE(), true);
|
||||
FileEditorManager.getInstance(project).openFile(file, true);
|
||||
close(OK_EXIT_CODE);
|
||||
}
|
||||
};
|
||||
}
|
||||
init();
|
||||
setTitle("[TEST] " + getTitle());
|
||||
}
|
||||
@@ -175,6 +193,10 @@ class UpdateInfoDialog extends AbstractUpdateDialog {
|
||||
actions.add(updateButton);
|
||||
}
|
||||
|
||||
if (myWhatsNewAction != null) {
|
||||
actions.add(myWhatsNewAction);
|
||||
}
|
||||
|
||||
return actions.toArray(new Action[0]);
|
||||
}
|
||||
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// Copyright 2000-2019 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.
|
||||
package com.intellij.openapi.updateSettings.impl;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.FileIconProvider;
|
||||
import com.intellij.ide.IdeBundle;
|
||||
import com.intellij.openapi.fileEditor.impl.HTMLEditorProvider;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Iconable;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public final class WhatsNewFileIconProvider implements FileIconProvider {
|
||||
@Nullable
|
||||
@Override
|
||||
public Icon getIcon(@NotNull VirtualFile virtualFile, @Iconable.IconFlags int flags, @Nullable Project project) {
|
||||
Boolean isHtml = virtualFile.getUserData(HTMLEditorProvider.Companion.getHTML_CONTENT_TYPE());
|
||||
if (isHtml != null && isHtml && virtualFile.getName().startsWith(IdeBundle.message("update.whats.new.file.name", ""))) {
|
||||
return AllIcons.General.Information;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1023,6 +1023,9 @@ updates.settings.current.version=Current version
|
||||
updates.settings.last.check=Last checked
|
||||
updates.settings.ignored=View/edit ignored updates
|
||||
updates.settings.ignored.title=Ignored Updates
|
||||
update.whats.new.notification.title={0} Update Installed
|
||||
update.whats.new.file.name=What''s New in {0}
|
||||
update.whats.new.notification.action=What''s New
|
||||
update.plugin.host.url.message=Repository URL:
|
||||
update.no.update.hosts=No plugin repositories configured
|
||||
update.edit.plugin.host.title=Edit Repository
|
||||
|
||||
@@ -689,6 +689,7 @@
|
||||
id="PlatformProjectConfigurator"/>
|
||||
<directoryProjectConfigurator implementation="com.intellij.platform.PlatformProjectViewOpener"/>
|
||||
|
||||
<fileIconProvider implementation="com.intellij.openapi.updateSettings.impl.WhatsNewFileIconProvider"/>
|
||||
<fileIconProvider implementation="com.intellij.ide.FileIconPatcherImpl"/>
|
||||
<iconProvider implementation="com.intellij.ide.NativeIconProvider" id="native"/>
|
||||
<iconProvider implementation="com.intellij.psi.impl.file.SourceRootIconProvider$DirectoryProvider" id="directory" order="last"/>
|
||||
|
||||
@@ -620,6 +620,7 @@
|
||||
<iconLayerProvider implementation="com.intellij.ide.LockedIconLayerProvider"/>
|
||||
|
||||
<fileEditorProvider implementation="com.intellij.openapi.fileEditor.impl.text.LargeFileEditorProvider"/>
|
||||
<fileEditorProvider implementation="com.intellij.openapi.fileEditor.impl.HTMLEditorProvider"/>
|
||||
<editorNotificationProvider implementation="com.intellij.openapi.fileEditor.impl.text.LargeFileNotificationProvider"/>
|
||||
<fileDocumentSynchronizationVetoer implementation="com.intellij.openapi.fileEditor.impl.LargeFileSavingVetoer"/>
|
||||
<frameEditorComponentProvider implementation="com.intellij.openapi.wm.ex.DefaultFrameEditorComponentProvider"/>
|
||||
|
||||
Reference in New Issue
Block a user