From 40077ea08dff31d4e8778ded6e908475dc4de1a9 Mon Sep 17 00:00:00 2001 From: Alexander Lobas Date: Mon, 10 Oct 2022 17:40:56 +0200 Subject: [PATCH] IDEA-296952 Plugins managment improvements GitOrigin-RevId: bf00b97938dbd803f81bad8120180eec6e0a5925 --- .../com/intellij/ide/plugins/PluginNode.java | 9 +++ .../marketplace/MarketplaceRequests.kt | 5 ++ .../newui/PluginDetailsPageComponent.java | 61 ++++++++++++++++--- .../plugins/newui/PluginImagesComponent.java | 4 +- .../plugins/newui/ReviewCommentComponent.java | 5 +- .../impl/PluginUpdateDialog.java | 4 +- .../updateSettings/impl/UpdateChecker.kt | 1 + 7 files changed, 74 insertions(+), 15 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginNode.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginNode.java index 8096e311cfec..2d1e45da788f 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginNode.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginNode.java @@ -66,6 +66,7 @@ public final class PluginNode implements IdeaPluginDescriptor { private String externalPluginId; private PageContainer reviewComments; private List screenShots; + private String externalPluginIdForScreenShots; /** * @deprecated Use {@link #PluginNode(PluginId)} @@ -566,6 +567,14 @@ public final class PluginNode implements IdeaPluginDescriptor { return screenShots; } + public @Nullable String getExternalPluginIdForScreenShots() { + return externalPluginIdForScreenShots; + } + + public void setExternalPluginIdForScreenShots(@Nullable String externalPluginId) { + externalPluginIdForScreenShots = externalPluginId; + } + public void setScreenShots(@NotNull List screenshots) { this.screenShots = screenshots; } diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/marketplace/MarketplaceRequests.kt b/platform/platform-impl/src/com/intellij/ide/plugins/marketplace/MarketplaceRequests.kt index 77df58f6932d..b5dea734b59a 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/marketplace/MarketplaceRequests.kt +++ b/platform/platform-impl/src/com/intellij/ide/plugins/marketplace/MarketplaceRequests.kt @@ -423,7 +423,12 @@ class MarketplaceRequests : PluginInfoProvider { @RequiresReadLockAbsence fun loadPluginMetadata(pluginNode: PluginNode): IntellijPluginMetadata? { val externalPluginId = pluginNode.externalPluginId ?: return null + return loadPluginMetadata(pluginNode, externalPluginId) + } + @RequiresBackgroundThread + @RequiresReadLockAbsence + fun loadPluginMetadata(pluginNode: PluginNode, externalPluginId: String): IntellijPluginMetadata? { try { return readOrUpdateFile( Paths.get(PathManager.getPluginTempPath(), "${externalPluginId}-meta.json"), diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/newui/PluginDetailsPageComponent.java b/platform/platform-impl/src/com/intellij/ide/plugins/newui/PluginDetailsPageComponent.java index b42731764fe8..c9bbf0b2a726 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/newui/PluginDetailsPageComponent.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/newui/PluginDetailsPageComponent.java @@ -117,6 +117,8 @@ public final class PluginDetailsPageComponent extends MultiPanel { private ListPluginComponent myShowComponent; + private boolean myUpdateOnly; + public PluginDetailsPageComponent(@NotNull MyPluginModel pluginModel, @NotNull LinkListener searchListener, boolean marketplace) { this(pluginModel, searchListener, marketplace, false); } @@ -355,12 +357,19 @@ public final class PluginDetailsPageComponent extends MultiPanel { } public void setOnlyUpdateMode() { - myNameAndButtons.removeButtons(); - Container parent = myEnabledForProject.getParent(); - if (parent != null) { - parent.remove(myEnabledForProject); + myUpdateOnly = true; + + if (myMultiTabs) { + myNameAndButtons.moveButtonToBase(myVersion); + } + else { + myNameAndButtons.removeButtons(); + Container parent = myEnabledForProject.getParent(); + if (parent != null) { + parent.remove(myEnabledForProject); + } + myPanel.setBorder(JBUI.Borders.empty(15, 20, 0, 0)); } - myPanel.setBorder(JBUI.Borders.empty(15, 20, 0, 0)); myEmptyPanel.setBorder(null); } @@ -753,12 +762,12 @@ public final class PluginDetailsPageComponent extends MultiPanel { IntellijPluginMetadata metadata = marketplace.loadPluginMetadata(node); if (metadata != null && metadata.getScreenshots() != null) { - pluginNode.setExternalPluginId(node.getExternalPluginId()); pluginNode.setScreenShots(metadata.getScreenshots()); + pluginNode.setExternalPluginIdForScreenShots(node.getExternalPluginId()); } PageContainer reviewComments = new PageContainer<>(20, 0); - List items = MarketplaceRequests.getInstance().loadPluginReviews(node, reviewComments.getNextPage()); + List items = marketplace.loadPluginReviews(node, reviewComments.getNextPage()); if (items != null) { reviewComments.addItems(items); } @@ -766,6 +775,36 @@ public final class PluginDetailsPageComponent extends MultiPanel { component.setPluginDescriptor(pluginNode); + ApplicationManager.getApplication().invokeLater(() -> { + if (myShowComponent == component) { + stopLoading(); + showPluginImpl(component.getPluginDescriptor(), component.myUpdateDescriptor); + PluginManagerUsageCollector.pluginCardOpened(component.getPluginDescriptor(), component.getGroup()); + } + }, ModalityState.stateForComponent(component)); + }); + } + else if (myUpdateOnly && (node.getScreenShots() == null || node.getReviewComments() == null)) { + syncLoading = false; + startLoading(); + ProcessIOExecutorService.INSTANCE.execute(() -> { + MarketplaceRequests marketplace = MarketplaceRequests.getInstance(); + + if (node.getScreenShots() == null && node.getExternalPluginIdForScreenShots() != null) { + IntellijPluginMetadata metadata = marketplace.loadPluginMetadata(node, node.getExternalPluginIdForScreenShots()); + if (metadata != null && metadata.getScreenshots() != null) { + node.setScreenShots(metadata.getScreenshots()); + } + } + if (node.getReviewComments() == null) { + PageContainer reviewComments = new PageContainer<>(20, 0); + List items = marketplace.loadPluginReviews(node, reviewComments.getNextPage()); + if (items != null) { + reviewComments.addItems(items); + } + node.setReviewComments(reviewComments); + } + ApplicationManager.getApplication().invokeLater(() -> { if (myShowComponent == component) { stopLoading(); @@ -956,14 +995,16 @@ public final class PluginDetailsPageComponent extends MultiPanel { } private void updateReviews(@NotNull PluginNode pluginNode) { - PageContainer comments = Objects.requireNonNull(pluginNode.getReviewComments()); + PageContainer comments = pluginNode.getReviewComments(); myReviewPanel.clear(); - myReviewPanel.addComments(comments.getItems()); + if (comments != null) { + myReviewPanel.addComments(comments.getItems()); + } myReviewNextPageButton.setIcon(null); myReviewNextPageButton.setEnabled(true); - myReviewNextPageButton.setVisible(comments.isNextPage()); + myReviewNextPageButton.setVisible(comments != null && comments.isNextPage()); } private static void updateUrlComponent(@Nullable LinkPanel panel, @NotNull String messageKey, @Nullable String url) { diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/newui/PluginImagesComponent.java b/platform/platform-impl/src/com/intellij/ide/plugins/newui/PluginImagesComponent.java index 62623b50dc36..ab2e1f39c762 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/newui/PluginImagesComponent.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/newui/PluginImagesComponent.java @@ -132,7 +132,7 @@ public class PluginImagesComponent extends JPanel { } private void loadImages(@NotNull IdeaPluginDescriptor descriptor, @NotNull Object state) { - if (!(descriptor instanceof PluginNode node)) { + if (!(descriptor instanceof PluginNode node) || node.getExternalPluginIdForScreenShots() == null) { handleImages(state, null); return; } @@ -145,7 +145,7 @@ public class PluginImagesComponent extends JPanel { ProcessIOExecutorService.INSTANCE.execute(() -> { List images = new ArrayList<>(); - File parentDir = new File(PathManager.getPluginTempPath(), "imageCache/" + node.getExternalPluginId()); + File parentDir = new File(PathManager.getPluginTempPath(), "imageCache/" + node.getExternalPluginIdForScreenShots()); for (String screenShot : screenShots) { try { diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/newui/ReviewCommentComponent.java b/platform/platform-impl/src/com/intellij/ide/plugins/newui/ReviewCommentComponent.java index 477146890cf5..3be3e96133cb 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/newui/ReviewCommentComponent.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/newui/ReviewCommentComponent.java @@ -11,6 +11,7 @@ import com.intellij.openapi.actionSystem.impl.ActionButton; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.impl.ApplicationInfoImpl; import com.intellij.openapi.ide.CopyPasteManager; +import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.JBPopupListener; import com.intellij.openapi.ui.popup.LightweightWindowEvent; @@ -90,7 +91,7 @@ public class ReviewCommentComponent extends JPanel { DefaultActionGroup group = new DefaultActionGroup(); group.setPopup(true); - group.add(new AnAction(IdeBundle.message("plugins.review.action.copy.link.text")) { + group.add(new DumbAwareAction(IdeBundle.message("plugins.review.action.copy.link.text")) { @Override public void actionPerformed(@NotNull AnActionEvent e) { String url = ApplicationInfoImpl.getShadowInstance().getPluginManagerUrl() + @@ -132,7 +133,7 @@ public class ReviewCommentComponent extends JPanel { else if (state == EventHandler.SelectionType.HOVER) { setBackground(new JBColor(Gray.xF8, JBUI.CurrentTheme.Table.Hover.background(true))); } - myMoreButton.setVisible(state == EventHandler.SelectionType.HOVER || myShowPopup); + //myMoreButton.setVisible(state == EventHandler.SelectionType.HOVER || myShowPopup); // TODO: rollback after adding a few more actions myState = state; } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginUpdateDialog.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginUpdateDialog.java index 49a456b5bd5a..c7c7548aa8a5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginUpdateDialog.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginUpdateDialog.java @@ -20,6 +20,7 @@ import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Divider; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtilRt; import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeFrame; import com.intellij.ui.OnePixelSplitter; @@ -99,8 +100,9 @@ final class PluginUpdateDialog extends DialogWrapper { public void finishUpdate() { } }); + boolean multiTabs = Registry.is("plugins.show.multi.tabs", false); //noinspection unchecked - myDetailsPage = new PluginDetailsPageComponent(myPluginModel, LinkListener.NULL, true); + myDetailsPage = new PluginDetailsPageComponent(myPluginModel, LinkListener.NULL, true, multiTabs); myDetailsPage.setOnlyUpdateMode(); MultiSelectionEventHandler eventHandler = new MultiSelectionEventHandler(); diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.kt b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.kt index 1563e9be383d..ce909a3500a1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.kt +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.kt @@ -441,6 +441,7 @@ object UpdateChecker { buildNumber) > 0)) { runCatching { MarketplaceRequests.loadPluginDescriptor(id.idString, lastUpdate, indicator) } .onFailure { if (it !is HttpRequests.HttpStatusException || it.statusCode != HttpURLConnection.HTTP_NOT_FOUND) throw it } + .onSuccess { it.externalPluginIdForScreenShots = lastUpdate.externalPluginId } .onSuccess { prepareDownloader(state, it, buildNumber, toUpdate, toUpdateDisabled, indicator, null) } } }