mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-214866 Plugins Update dialog
GitOrigin-RevId: 2f7d41a5ea45c1148c4172b75de6aaa7fe3f2d66
This commit is contained in:
committed by
intellij-monorepo-bot
parent
f61a1eeac0
commit
e6de8d8c64
@@ -64,6 +64,8 @@ import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static java.lang.System.out;
|
||||
|
||||
/**
|
||||
* @author Alexander Lobas
|
||||
*/
|
||||
@@ -104,9 +106,6 @@ public class PluginManagerConfigurable
|
||||
private SearchResultPanel myMarketplaceSearchPanel;
|
||||
private SearchResultPanel myInstalledSearchPanel;
|
||||
|
||||
private LinkListener<IdeaPluginDescriptor> myNameListener;
|
||||
private LinkListener<String> mySearchListener;
|
||||
|
||||
private final LinkLabel<Object> myUpdateAll = new LinkLabel<>("Update All", null);
|
||||
private final JLabel myUpdateCounter = new CountComponent();
|
||||
private final CountIcon myCountIcon = new CountIcon();
|
||||
@@ -198,13 +197,6 @@ public class PluginManagerConfigurable
|
||||
});
|
||||
myPluginModel.setPluginUpdatesService(myPluginUpdatesService);
|
||||
|
||||
myNameListener = (aSource, aLinkData) -> {
|
||||
// TODO: unused
|
||||
};
|
||||
mySearchListener = (aSource, aLinkData) -> {
|
||||
// TODO: unused
|
||||
};
|
||||
|
||||
createMarketplaceTab();
|
||||
createInstalledTab();
|
||||
|
||||
@@ -359,8 +351,7 @@ public class PluginManagerConfigurable
|
||||
protected JComponent createPluginsPanel(@NotNull Consumer<? super PluginsGroupComponent> selectionListener) {
|
||||
MultiSelectionEventHandler eventHandler = new MultiSelectionEventHandler();
|
||||
myMarketplacePanel =
|
||||
new PluginsGroupComponentWithProgress(new PluginListLayout(), eventHandler, myNameListener,
|
||||
PluginManagerConfigurable.this.mySearchListener,
|
||||
new PluginsGroupComponentWithProgress(new PluginListLayout(), eventHandler,
|
||||
d -> new ListPluginComponent(myPluginModel, d, mySearchListener, true));
|
||||
|
||||
myMarketplacePanel.setSelectionListener(selectionListener);
|
||||
@@ -623,10 +614,8 @@ public class PluginManagerConfigurable
|
||||
marketplaceController.setSearchResultEventHandler(eventHandler);
|
||||
|
||||
PluginsGroupComponentWithProgress panel =
|
||||
new PluginsGroupComponentWithProgress(new PluginListLayout(), eventHandler, myNameListener,
|
||||
PluginManagerConfigurable.this.mySearchListener,
|
||||
descriptor -> new ListPluginComponent(myPluginModel, descriptor, mySearchListener,
|
||||
true));
|
||||
new PluginsGroupComponentWithProgress(new PluginListLayout(), eventHandler,
|
||||
descriptor -> new ListPluginComponent(myPluginModel, descriptor, mySearchListener, true));
|
||||
|
||||
panel.setSelectionListener(selectionListener);
|
||||
registerCopyProvider(panel);
|
||||
@@ -775,8 +764,7 @@ public class PluginManagerConfigurable
|
||||
protected JComponent createPluginsPanel(@NotNull Consumer<? super PluginsGroupComponent> selectionListener) {
|
||||
MultiSelectionEventHandler eventHandler = new MultiSelectionEventHandler();
|
||||
myInstalledPanel =
|
||||
new PluginsGroupComponent(new PluginListLayout(), eventHandler, myNameListener,
|
||||
PluginManagerConfigurable.this.mySearchListener,
|
||||
new PluginsGroupComponent(new PluginListLayout(), eventHandler,
|
||||
descriptor -> new ListPluginComponent(myPluginModel, descriptor, mySearchListener, false));
|
||||
|
||||
myInstalledPanel.setSelectionListener(selectionListener);
|
||||
@@ -922,8 +910,7 @@ public class PluginManagerConfigurable
|
||||
installedController.setSearchResultEventHandler(eventHandler);
|
||||
|
||||
PluginsGroupComponent panel =
|
||||
new PluginsGroupComponent(new PluginListLayout(), eventHandler, myNameListener,
|
||||
PluginManagerConfigurable.this.mySearchListener,
|
||||
new PluginsGroupComponent(new PluginListLayout(), eventHandler,
|
||||
descriptor -> new ListPluginComponent(myPluginModel, descriptor, mySearchListener, false));
|
||||
|
||||
panel.setSelectionListener(selectionListener);
|
||||
|
||||
@@ -157,6 +157,16 @@ public class BaselinePanel extends NonOpaquePanel {
|
||||
add(component, null);
|
||||
}
|
||||
|
||||
public void removeButtons() {
|
||||
List<Component> buttons = new ArrayList<>(myButtonComponents);
|
||||
myButtonComponents.clear();
|
||||
myButtonEnableStates = null;
|
||||
|
||||
for (Component button : buttons) {
|
||||
remove(button);
|
||||
}
|
||||
}
|
||||
|
||||
public void setProgressComponent(@Nullable ListPluginComponent pluginComponent, @NotNull JComponent progressComponent) {
|
||||
assert myProgressComponent == null;
|
||||
myProgressComponent = progressComponent;
|
||||
|
||||
@@ -54,7 +54,7 @@ public class InstallPluginInfo {
|
||||
if (myPluginModel == null) {
|
||||
MyPluginModel.finishInstall(myDescriptor);
|
||||
closeStatusBarIndicator();
|
||||
if (success && restartRequired) {
|
||||
if (success && !cancel && restartRequired) {
|
||||
ApplicationManager.getApplication().invokeLater(() -> PluginManagerConfigurable.shutdownOrRestartApp());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ public class ListPluginComponent extends JPanel {
|
||||
private final boolean myMarketplace;
|
||||
public IdeaPluginDescriptor myPlugin;
|
||||
private boolean myUninstalled;
|
||||
private boolean myOnlyUpdateMode;
|
||||
public IdeaPluginDescriptor myUpdateDescriptor;
|
||||
|
||||
private final JLabel myNameComponent = new JLabel();
|
||||
@@ -149,7 +150,8 @@ public class ListPluginComponent extends JPanel {
|
||||
else {
|
||||
myLayout.addButtonComponent(myInstallButton = new InstallButton(false));
|
||||
|
||||
myInstallButton.addActionListener(e -> myPluginModel.installOrUpdatePlugin(myPlugin, null, ModalityState.stateForComponent(myInstallButton)));
|
||||
myInstallButton
|
||||
.addActionListener(e -> myPluginModel.installOrUpdatePlugin(myPlugin, null, ModalityState.stateForComponent(myInstallButton)));
|
||||
myInstallButton.setEnabled(PluginManagerCore.getPlugin(myPlugin.getPluginId()) == null, "Installed");
|
||||
ColorButton.setWidth72(myInstallButton);
|
||||
}
|
||||
@@ -295,6 +297,17 @@ public class ListPluginComponent extends JPanel {
|
||||
}
|
||||
}
|
||||
|
||||
public void setOnlyUpdateMode(@Nullable IdeaPluginDescriptor descriptor) {
|
||||
myOnlyUpdateMode = true;
|
||||
|
||||
if (myEnableDisableButton != null) {
|
||||
myLayout.removeButtonComponent(myEnableDisableButton);
|
||||
myEnableDisableButton = null;
|
||||
}
|
||||
|
||||
setUpdateDescriptor(descriptor);
|
||||
}
|
||||
|
||||
public void setUpdateDescriptor(@Nullable IdeaPluginDescriptor descriptor) {
|
||||
if (myUpdateDescriptor == null && descriptor == null) {
|
||||
return;
|
||||
@@ -337,9 +350,11 @@ public class ListPluginComponent extends JPanel {
|
||||
}
|
||||
if (myUpdateButton == null) {
|
||||
myLayout.addButtonComponent(myUpdateButton = new UpdateButton(), 0);
|
||||
myUpdateButton.addActionListener(e -> myPluginModel.installOrUpdatePlugin(myPlugin, myUpdateDescriptor, ModalityState.stateForComponent(myUpdateButton)));
|
||||
myUpdateButton.addActionListener(
|
||||
e -> myPluginModel.installOrUpdatePlugin(myPlugin, myUpdateDescriptor, ModalityState.stateForComponent(myUpdateButton)));
|
||||
}
|
||||
else {
|
||||
myUpdateButton.setEnabled(true);
|
||||
myUpdateButton.setVisible(true);
|
||||
}
|
||||
if (myAlignButton != null) {
|
||||
@@ -350,9 +365,7 @@ public class ListPluginComponent extends JPanel {
|
||||
doLayout();
|
||||
}
|
||||
|
||||
public void setListeners(@NotNull LinkListener<? super IdeaPluginDescriptor> listener,
|
||||
@NotNull LinkListener<String> searchListener,
|
||||
@NotNull EventHandler eventHandler) {
|
||||
public void setListeners(@NotNull EventHandler eventHandler) {
|
||||
myEventHandler = eventHandler;
|
||||
eventHandler.addAll(this);
|
||||
}
|
||||
@@ -520,7 +533,7 @@ public class ListPluginComponent extends JPanel {
|
||||
}
|
||||
|
||||
public void updatePlugin() {
|
||||
if (!myMarketplace && myUpdateButton != null && myUpdateButton.isVisible()) {
|
||||
if (!myMarketplace && myUpdateButton != null && myUpdateButton.isVisible() && myUpdateButton.isEnabled()) {
|
||||
myUpdateButton.doClick();
|
||||
}
|
||||
}
|
||||
@@ -533,6 +546,18 @@ public class ListPluginComponent extends JPanel {
|
||||
return myMarketplace;
|
||||
}
|
||||
|
||||
public boolean isRestartEnabled() {
|
||||
return myRestartButton != null && myRestartButton.isVisible();
|
||||
}
|
||||
|
||||
public boolean isUpdatedWithoutRestart() {
|
||||
return myUpdateButton != null && myUpdateButton.isVisible() && !myUpdateButton.isEnabled();
|
||||
}
|
||||
|
||||
public boolean underProgress() {
|
||||
return myIndicator != null;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
if (myIndicator != null) {
|
||||
MyPluginModel.removeProgress(myPlugin, myIndicator);
|
||||
@@ -581,7 +606,7 @@ public class ListPluginComponent extends JPanel {
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
JButton button = selection.get(i).myUpdateButton;
|
||||
if (button == null || !button.isVisible()) {
|
||||
if (button == null || !button.isVisible() || !button.isEnabled()) {
|
||||
updateButtons = null;
|
||||
break;
|
||||
}
|
||||
@@ -595,6 +620,10 @@ public class ListPluginComponent extends JPanel {
|
||||
}
|
||||
}
|
||||
|
||||
if (myOnlyUpdateMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
Pair<Boolean, IdeaPluginDescriptor[]> result = getSelectionNewState(selection);
|
||||
group.add(new MyAnAction(result.first ? "Enable" : "Disable", null, KeyEvent.VK_SPACE) {
|
||||
@Override
|
||||
@@ -663,7 +692,7 @@ public class ListPluginComponent extends JPanel {
|
||||
boolean update = true;
|
||||
for (ListPluginComponent component : selection) {
|
||||
JButton button = component.myUpdateButton;
|
||||
if (button == null || !button.isVisible()) {
|
||||
if (button == null || !button.isVisible() || !button.isEnabled()) {
|
||||
update = false;
|
||||
break;
|
||||
}
|
||||
@@ -680,6 +709,9 @@ public class ListPluginComponent extends JPanel {
|
||||
}
|
||||
}
|
||||
else if (!restart && !update) {
|
||||
if (myOnlyUpdateMode) {
|
||||
return;
|
||||
}
|
||||
if (keyCode == KeyEvent.VK_SPACE) {
|
||||
if (selection.size() == 1) {
|
||||
myPluginModel.changeEnableDisable(selection.get(0).myPlugin);
|
||||
|
||||
@@ -422,10 +422,11 @@ public class MyPluginModel extends InstalledPluginsTableModel implements PluginM
|
||||
});
|
||||
}
|
||||
|
||||
public void toBackground() {
|
||||
public boolean toBackground() {
|
||||
for (InstallPluginInfo info : myInstallingInfos.values()) {
|
||||
info.toBackground(myStatusBar);
|
||||
}
|
||||
return !myInstallingInfos.isEmpty();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+10
-2
@@ -187,10 +187,12 @@ public class PluginDetailsPageComponent extends MultiPanel {
|
||||
myNameAndButtons.addButtonComponent(myRestartButton = new RestartButton(myPluginModel));
|
||||
|
||||
myNameAndButtons.addButtonComponent(myUpdateButton = new UpdateButton());
|
||||
myUpdateButton.addActionListener(e -> myPluginModel.installOrUpdatePlugin(myPlugin, myUpdateDescriptor, ModalityState.stateForComponent(myUpdateButton)));
|
||||
myUpdateButton.addActionListener(
|
||||
e -> myPluginModel.installOrUpdatePlugin(myPlugin, myUpdateDescriptor, ModalityState.stateForComponent(myUpdateButton)));
|
||||
|
||||
myNameAndButtons.addButtonComponent(myInstallButton = new InstallButton(true));
|
||||
myInstallButton.addActionListener(e -> myPluginModel.installOrUpdatePlugin(myPlugin, null, ModalityState.stateForComponent(myInstallButton)));
|
||||
myInstallButton
|
||||
.addActionListener(e -> myPluginModel.installOrUpdatePlugin(myPlugin, null, ModalityState.stateForComponent(myInstallButton)));
|
||||
|
||||
myEnableDisableButton = new JButton();
|
||||
myEnableDisableButton.addActionListener(e -> myPluginModel.changeEnableDisable(myPlugin));
|
||||
@@ -216,6 +218,12 @@ public class PluginDetailsPageComponent extends MultiPanel {
|
||||
}
|
||||
}
|
||||
|
||||
public void setOnlyUpdateMode() {
|
||||
myNameAndButtons.removeButtons();
|
||||
myPanel.setBorder(JBUI.Borders.empty(15, 20, 0, 0));
|
||||
myEmptyPanel.setBorder(null);
|
||||
}
|
||||
|
||||
private void createMetricsPanel(@NotNull JPanel centerPanel) {
|
||||
// text field without horizontal margins
|
||||
myVersion = new JTextField();
|
||||
|
||||
+6
-10
@@ -5,7 +5,6 @@ import com.intellij.ide.plugins.IdeaPluginDescriptor;
|
||||
import com.intellij.ide.plugins.PluginManagerConfigurable;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.ui.components.JBPanelWithEmptyText;
|
||||
import com.intellij.ui.components.labels.LinkListener;
|
||||
import com.intellij.ui.components.panels.NonOpaquePanel;
|
||||
import com.intellij.ui.components.panels.OpaquePanel;
|
||||
import com.intellij.ui.scale.JBUIScale;
|
||||
@@ -28,20 +27,14 @@ import java.util.function.Consumer;
|
||||
*/
|
||||
public class PluginsGroupComponent extends JBPanelWithEmptyText {
|
||||
private final EventHandler myEventHandler;
|
||||
private final LinkListener<IdeaPluginDescriptor> myListener;
|
||||
private final LinkListener<String> mySearchListener;
|
||||
private final Function<? super IdeaPluginDescriptor, ? extends ListPluginComponent> myFunction;
|
||||
private final List<UIPluginGroup> myGroups = new ArrayList<>();
|
||||
|
||||
public PluginsGroupComponent(@NotNull LayoutManager layout,
|
||||
@NotNull EventHandler eventHandler,
|
||||
@NotNull LinkListener<IdeaPluginDescriptor> listener,
|
||||
@NotNull LinkListener<String> searchListener,
|
||||
@NotNull Function<? super IdeaPluginDescriptor, ? extends ListPluginComponent> function) {
|
||||
super(layout);
|
||||
myEventHandler = eventHandler;
|
||||
myListener = listener;
|
||||
mySearchListener = searchListener;
|
||||
myFunction = function;
|
||||
|
||||
myEventHandler.connect(this);
|
||||
@@ -195,13 +188,16 @@ public class PluginsGroupComponent extends JBPanelWithEmptyText {
|
||||
return -1;
|
||||
}
|
||||
|
||||
private void addToGroup(@NotNull PluginsGroup group, @NotNull List<? extends IdeaPluginDescriptor> descriptors, int index, int eventIndex) {
|
||||
private void addToGroup(@NotNull PluginsGroup group,
|
||||
@NotNull List<? extends IdeaPluginDescriptor> descriptors,
|
||||
int index,
|
||||
int eventIndex) {
|
||||
for (IdeaPluginDescriptor descriptor : descriptors) {
|
||||
ListPluginComponent pluginComponent = myFunction.fun(descriptor);
|
||||
group.ui.plugins.add(pluginComponent);
|
||||
add(pluginComponent, index);
|
||||
myEventHandler.addCell(pluginComponent, eventIndex);
|
||||
pluginComponent.setListeners(myListener, mySearchListener, myEventHandler);
|
||||
pluginComponent.setListeners(myEventHandler);
|
||||
if (index != -1) {
|
||||
index++;
|
||||
}
|
||||
@@ -233,7 +229,7 @@ public class PluginsGroupComponent extends JBPanelWithEmptyText {
|
||||
group.ui.plugins.add(index, pluginComponent);
|
||||
add(pluginComponent, uiIndex);
|
||||
myEventHandler.addCell(pluginComponent, anchor);
|
||||
pluginComponent.setListeners(myListener, mySearchListener, myEventHandler);
|
||||
pluginComponent.setListeners(myEventHandler);
|
||||
}
|
||||
|
||||
public void removeGroup(@NotNull PluginsGroup group) {
|
||||
|
||||
+1
-4
@@ -3,7 +3,6 @@ package com.intellij.ide.plugins.newui;
|
||||
|
||||
import com.intellij.ide.plugins.IdeaPluginDescriptor;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.ui.components.labels.LinkListener;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.ui.AsyncProcessIcon;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -20,10 +19,8 @@ public class PluginsGroupComponentWithProgress extends PluginsGroupComponent {
|
||||
|
||||
public PluginsGroupComponentWithProgress(@NotNull LayoutManager layout,
|
||||
@NotNull EventHandler eventHandler,
|
||||
@NotNull LinkListener<IdeaPluginDescriptor> listener,
|
||||
@NotNull LinkListener<String> searchListener,
|
||||
@NotNull Function<? super IdeaPluginDescriptor, ? extends ListPluginComponent> function) {
|
||||
super(layout, eventHandler, listener, searchListener, function);
|
||||
super(layout, eventHandler, function);
|
||||
myIcon.setOpaque(false);
|
||||
myIcon.setPaintPassiveIcon(false);
|
||||
add(myIcon);
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ public final class PluginDownloader {
|
||||
|
||||
private boolean myShownErrors;
|
||||
|
||||
private PluginDownloader(IdeaPluginDescriptor descriptor, String url, BuildNumber buildNumber) {
|
||||
private PluginDownloader(@NotNull IdeaPluginDescriptor descriptor, @NotNull String url, @Nullable BuildNumber buildNumber) {
|
||||
myPluginId = descriptor.getPluginId();
|
||||
myPluginName = descriptor.getName();
|
||||
myProductCode = descriptor.getProductCode();
|
||||
|
||||
+360
@@ -0,0 +1,360 @@
|
||||
// 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.CommonBundle;
|
||||
import com.intellij.ide.IdeBundle;
|
||||
import com.intellij.ide.plugins.IdeaPluginDescriptor;
|
||||
import com.intellij.ide.plugins.PluginManagerConfigurable;
|
||||
import com.intellij.ide.plugins.PluginManagerCore;
|
||||
import com.intellij.ide.plugins.PluginManagerMain;
|
||||
import com.intellij.ide.plugins.newui.*;
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.application.ex.ApplicationManagerEx;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.options.Configurable;
|
||||
import com.intellij.openapi.progress.PerformInBackgroundOption;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.Divider;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.ui.OnePixelSplitter;
|
||||
import com.intellij.ui.components.labels.LinkListener;
|
||||
import com.intellij.ui.components.panels.OpaquePanel;
|
||||
import com.intellij.util.LineSeparator;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.ui.JBDimension;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Alexander Lobas
|
||||
*/
|
||||
public class PluginUpdateDialog extends DialogWrapper {
|
||||
private final Collection<PluginDownloader> myDownloaders;
|
||||
|
||||
private final MyPluginModel myPluginModel = new MyPluginModel() {
|
||||
};
|
||||
private final PluginsGroupComponent myPluginsPanel;
|
||||
private final PluginsGroup myGroup;
|
||||
private final PluginDetailsPageComponent myDetailsPage;
|
||||
|
||||
private final Action myIgnoreAction;
|
||||
|
||||
public PluginUpdateDialog(@NotNull Collection<PluginDownloader> uploadedPlugins) {
|
||||
super(true);
|
||||
setTitle("Plugin Updates");
|
||||
|
||||
myDownloaders = uploadedPlugins;
|
||||
|
||||
myIgnoreAction = new AbstractAction(
|
||||
IdeBundle.message(uploadedPlugins.size() == 1 ? "updates.ignore.update.button" : "updates.ignore.updates.button")) {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
close(CANCEL_EXIT_CODE);
|
||||
ignorePlugins(ContainerUtil.map(myGroup.ui.plugins, component -> component.myUpdateDescriptor));
|
||||
}
|
||||
};
|
||||
|
||||
myPluginModel.setTopController(new Configurable.TopComponentController() {
|
||||
@Override
|
||||
public void setLeftComponent(@Nullable Component component) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showProgress(boolean start) {
|
||||
}
|
||||
});
|
||||
myPluginModel.setPluginUpdatesService(new PluginUpdatesService() {
|
||||
@Override
|
||||
public void finishUpdate(@NotNull IdeaPluginDescriptor descriptor) {
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishUpdate() {
|
||||
updateButtons();
|
||||
}
|
||||
});
|
||||
|
||||
myDetailsPage = new PluginDetailsPageComponent(myPluginModel, emptyListener(), false) {
|
||||
@Override
|
||||
public void showProgress() {
|
||||
}
|
||||
};
|
||||
myDetailsPage.setOnlyUpdateMode();
|
||||
|
||||
MultiSelectionEventHandler eventHandler = new MultiSelectionEventHandler();
|
||||
|
||||
myPluginsPanel = new PluginsGroupComponent(new PluginListLayout(), eventHandler, descriptor -> createListComponent(descriptor));
|
||||
PluginManagerConfigurable.registerCopyProvider(myPluginsPanel);
|
||||
myPluginsPanel.setSelectionListener(__ -> {
|
||||
List<ListPluginComponent> selection = myPluginsPanel.getSelection();
|
||||
int size = selection.size();
|
||||
myDetailsPage.showPlugin(size == 1 ? selection.get(0) : null, size > 1);
|
||||
});
|
||||
|
||||
myGroup = new PluginsGroup("Plugin updates available");
|
||||
for (PluginDownloader plugin : uploadedPlugins) {
|
||||
myGroup.descriptors.add(plugin.getDescriptor());
|
||||
}
|
||||
myGroup.sortByName();
|
||||
myPluginsPanel.addGroup(myGroup);
|
||||
|
||||
setOKButtonText(false, false);
|
||||
setCancelButtonText(IdeBundle.message("updates.remind.later.button"));
|
||||
init();
|
||||
|
||||
JRootPane rootPane = getPeer().getRootPane();
|
||||
if (rootPane != null) {
|
||||
rootPane.setPreferredSize(new JBDimension(800, 600));
|
||||
}
|
||||
}
|
||||
|
||||
private void updateButtons() {
|
||||
int count = myGroup.ui.plugins.size();
|
||||
int restart = 0;
|
||||
int progress = 0;
|
||||
int updatedWithoutRestart = 0;
|
||||
for (ListPluginComponent plugin : myGroup.ui.plugins) {
|
||||
if (plugin.isRestartEnabled()) {
|
||||
restart++;
|
||||
}
|
||||
else if (plugin.underProgress()) {
|
||||
progress++;
|
||||
}
|
||||
else if (plugin.isUpdatedWithoutRestart()) {
|
||||
updatedWithoutRestart++;
|
||||
}
|
||||
}
|
||||
|
||||
setOKButtonText(restart + progress > 0, updatedWithoutRestart == count);
|
||||
getCancelAction().setEnabled(restart + updatedWithoutRestart < count);
|
||||
myIgnoreAction.setEnabled(restart + progress + updatedWithoutRestart == 0);
|
||||
}
|
||||
|
||||
private void setOKButtonText(boolean restart, boolean close) {
|
||||
if (close) {
|
||||
setOKButtonText("Close");
|
||||
}
|
||||
else {
|
||||
String action = ApplicationManager.getApplication().isRestartCapable() ? "Restart" : "Shutdown";
|
||||
setOKButtonText(restart ? action + " IDE" : "Update All and " + action);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doOKAction() {
|
||||
super.doOKAction();
|
||||
|
||||
List<PluginDownloader> toDownloads = new ArrayList<>();
|
||||
List<IdeaPluginDescriptor> toIgnore = new ArrayList<>();
|
||||
int index = 0;
|
||||
boolean restart = false;
|
||||
|
||||
for (PluginDownloader downloader : myDownloaders) {
|
||||
ListPluginComponent component = myGroup.ui.plugins.get(index++);
|
||||
if (component.isRestartEnabled() || component.underProgress()) {
|
||||
restart = true;
|
||||
}
|
||||
else if (!component.isUpdatedWithoutRestart()) {
|
||||
toDownloads.add(downloader);
|
||||
toIgnore.add(component.myUpdateDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
boolean background = myPluginModel.toBackground();
|
||||
|
||||
if (toDownloads.size() != myDownloaders.size() || background) {
|
||||
if (!toIgnore.isEmpty()) {
|
||||
ignorePlugins(toIgnore);
|
||||
}
|
||||
if (!background && restart) {
|
||||
ApplicationManager.getApplication().invokeLater(() -> ApplicationManagerEx.getApplicationEx().restart(true));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
new Task.Backgroundable(null, IdeBundle.message("update.notifications.title"), true, PerformInBackgroundOption.DEAF) {
|
||||
@Override
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
final List<PluginDownloader> downloaders = UpdateInstaller.downloadPluginUpdates(toDownloads, indicator);
|
||||
if (!downloaders.isEmpty()) {
|
||||
ApplicationManager.getApplication().invokeLater(() -> {
|
||||
final PluginUpdateResult result = UpdateInstaller.installDownloadedPluginUpdates(downloaders, getContentPanel(), true);
|
||||
if (result.getPluginsInstalled().size() > 0) {
|
||||
if (result.getRestartRequired()) {
|
||||
PluginManagerMain.notifyPluginsUpdated(null);
|
||||
}
|
||||
else {
|
||||
String message;
|
||||
if (result.getPluginsInstalled().size() == 1) {
|
||||
final IdeaPluginDescriptor installedPlugin = result.getPluginsInstalled().get(0);
|
||||
message = "Updated " + installedPlugin.getName() + " plugin to version " + installedPlugin.getVersion();
|
||||
}
|
||||
else {
|
||||
message = "Updated " + result.getPluginsInstalled() + " plugins";
|
||||
}
|
||||
UpdateChecker.NOTIFICATIONS.createNotification(message, NotificationType.INFORMATION).notify(myProject);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}.queue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doCancelAction() {
|
||||
super.doCancelAction();
|
||||
|
||||
if (myPluginModel.toBackground()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (ListPluginComponent plugin : myGroup.ui.plugins) {
|
||||
if (plugin.isRestartEnabled()) {
|
||||
ApplicationManager.getApplication().invokeLater(() -> PluginManagerConfigurable.shutdownOrRestartApp());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Action[] createLeftSideActions() {
|
||||
return ContainerUtil.ar(myIgnoreAction);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected DialogStyle getStyle() {
|
||||
return DialogStyle.COMPACT;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDimensionServiceKey() {
|
||||
return "#com.intellij.openapi.updateSettings.impl.PluginUpdateInfoDialog";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private ListPluginComponent createListComponent(IdeaPluginDescriptor updateDescriptor) {
|
||||
IdeaPluginDescriptor descriptor = PluginManagerCore.getPlugin(updateDescriptor.getPluginId());
|
||||
assert descriptor != null;
|
||||
ListPluginComponent component = new ListPluginComponent(myPluginModel, descriptor, emptyListener(), false) {
|
||||
@Override
|
||||
public void showProgress() {
|
||||
super.showProgress();
|
||||
updateButtons();
|
||||
}
|
||||
};
|
||||
component.setOnlyUpdateMode(updateDescriptor);
|
||||
return component;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected JComponent createCenterPanel() {
|
||||
OnePixelSplitter splitter = new OnePixelSplitter(false, 0.45f) {
|
||||
@Override
|
||||
protected Divider createDivider() {
|
||||
Divider divider = super.createDivider();
|
||||
divider.setBackground(PluginManagerConfigurable.SEARCH_FIELD_BORDER_COLOR);
|
||||
return divider;
|
||||
}
|
||||
};
|
||||
|
||||
JPanel leftPanel = new JPanel(new BorderLayout());
|
||||
leftPanel.add(PluginManagerConfigurable.createScrollPane(myPluginsPanel, true));
|
||||
|
||||
OpaquePanel titlePanel = new OpaquePanel(new BorderLayout(), PluginManagerConfigurable.MAIN_BG_COLOR);
|
||||
titlePanel.setBorder(JBUI.Borders.empty(6, 10));
|
||||
leftPanel.add(titlePanel, BorderLayout.SOUTH);
|
||||
|
||||
JLabel titleComponent = new JLabel("Plugins can be updated later in " + CommonBundle.settingsTitle() + " | Plugins");
|
||||
titleComponent.setForeground(PluginsGroupComponent.SECTION_HEADER_FOREGROUND);
|
||||
titlePanel.add(titleComponent);
|
||||
|
||||
((JComponent)myGroup.ui.panel).setBorder(JBUI.Borders.empty(6, 10));
|
||||
|
||||
splitter.setFirstComponent(leftPanel);
|
||||
splitter.setSecondComponent(myDetailsPage);
|
||||
|
||||
return splitter;
|
||||
}
|
||||
|
||||
private static Set<String> myIgnoredPluginsWithVersions;
|
||||
private static final String DISABLED_UPDATE = "plugin_disabled_updates.txt";
|
||||
|
||||
@NotNull
|
||||
private static File getDisabledUpdateFile() {
|
||||
return new File(PathManager.getConfigPath(), DISABLED_UPDATE);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Set<String> getIgnoredPlugins() {
|
||||
if (myIgnoredPluginsWithVersions == null) {
|
||||
myIgnoredPluginsWithVersions = new HashSet<>();
|
||||
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
try {
|
||||
File file = getDisabledUpdateFile();
|
||||
if (file.isFile()) {
|
||||
myIgnoredPluginsWithVersions.addAll(FileUtil.loadLines(file));
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
Logger.getInstance(UpdateChecker.class).error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return myIgnoredPluginsWithVersions;
|
||||
}
|
||||
|
||||
private static void ignorePlugins(@NotNull List<IdeaPluginDescriptor> descriptors) {
|
||||
Set<String> ignoredPlugins = getIgnoredPlugins();
|
||||
|
||||
for (IdeaPluginDescriptor descriptor : descriptors) {
|
||||
ignoredPlugins.add(getIdVersionValue(descriptor));
|
||||
}
|
||||
|
||||
try {
|
||||
FileUtil
|
||||
.writeToFile(getDisabledUpdateFile(), StringUtil.join(ignoredPlugins, LineSeparator.getSystemLineSeparator().getSeparatorString()));
|
||||
}
|
||||
catch (IOException e) {
|
||||
Logger.getInstance(UpdateChecker.class).error(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isIgnored(@NotNull IdeaPluginDescriptor descriptor) {
|
||||
Set<String> plugins = getIgnoredPlugins();
|
||||
if (plugins.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return plugins.contains(getIdVersionValue(descriptor));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getIdVersionValue(@NotNull IdeaPluginDescriptor descriptor) {
|
||||
return descriptor.getPluginId().getIdString() + "+" + descriptor.getVersion();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static <T> LinkListener<T> emptyListener() {
|
||||
return (__, ___) -> {
|
||||
};
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -147,7 +147,8 @@ object UpdateChecker {
|
||||
val updatedPlugins: Collection<PluginDownloader>?
|
||||
val externalUpdates: Collection<ExternalUpdate>?
|
||||
try {
|
||||
updatedPlugins = checkPluginsUpdate(indicator, incompatiblePlugins, buildNumber)
|
||||
updatedPlugins = checkPluginsUpdate(indicator, incompatiblePlugins,
|
||||
buildNumber)?.filter { downloader -> !PluginUpdateDialog.isIgnored(downloader.descriptor) }
|
||||
externalUpdates = checkExternalUpdates(showDialog, updateSettings, indicator)
|
||||
}
|
||||
catch (e: IOException) {
|
||||
@@ -395,7 +396,7 @@ object UpdateChecker {
|
||||
|
||||
if (updatedPlugins != null && !updatedPlugins.isEmpty()) {
|
||||
updateFound = true
|
||||
val runnable = { PluginUpdateInfoDialog(updatedPlugins, showSettingsLink).show() }
|
||||
val runnable = { PluginUpdateDialog(updatedPlugins).show() }
|
||||
|
||||
ourShownNotifications.remove(NotificationUniqueType.PLUGINS)?.forEach { it.expire() }
|
||||
|
||||
|
||||
@@ -968,6 +968,7 @@ updates.incompatible.plugins.found={0,choice,1#Plugin|2#Plugins} incompatible wi
|
||||
updates.download.and.restart.button=Up&date and Restart
|
||||
updates.apply.manually.button=Up&date Manually
|
||||
updates.ignore.update.button=&Ignore This Update
|
||||
updates.ignore.updates.button=&Ignore These Updates
|
||||
updates.remind.later.button=&Remind Me Later
|
||||
updates.new.version.available=<b>A new version of {0} is <a href=\"{1}\">available</a>!</b>
|
||||
updates.current.version=Current version:
|
||||
|
||||
Reference in New Issue
Block a user