mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-377018: add an ability to use different splash screens depending on subscription
GitOrigin-RevId: 396dacfc24e9ab814f2e9d6645c0a4ae938999b7
This commit is contained in:
committed by
intellij-monorepo-bot
parent
e12247fcff
commit
c7fde2ed8c
+20
-1
@@ -7,6 +7,7 @@ import com.intellij.diagnostic.StartUpMeasurer;
|
||||
import com.intellij.ide.plugins.PluginManagerCore;
|
||||
import com.intellij.openapi.application.ApplicationNamesInfo;
|
||||
import com.intellij.openapi.application.IdeUrlTrackingParametersProvider;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.application.ex.ApplicationInfoEx;
|
||||
import com.intellij.openapi.application.ex.ApplicationManagerEx;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -20,6 +21,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.VisibleForTesting;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.text.MessageFormat;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
@@ -34,6 +37,7 @@ import java.util.*;
|
||||
public final class ApplicationInfoImpl extends ApplicationInfoEx {
|
||||
public static final String DEFAULT_PLUGINS_HOST = "https://plugins.jetbrains.com";
|
||||
public static final String IDEA_PLUGINS_HOST_PROPERTY = "idea.plugins.host";
|
||||
public static final String FREE_MODE_SPLASH_MARKER_FILE_NAME = "splash-free-mode.txt";
|
||||
|
||||
private static final String IDEA_APPLICATION_INFO_DEFAULT_DARK_LAF = "idea.application.info.default.dark.laf";
|
||||
private static final String IDEA_APPLICATION_INFO_DEFAULT_CLASSIC_DARK_LAF = "idea.application.info.default.classic.dark.laf";
|
||||
@@ -57,6 +61,7 @@ public final class ApplicationInfoImpl extends ApplicationInfoEx {
|
||||
private String myShortCompanyName;
|
||||
private String myCompanyUrl = "https://www.jetbrains.com/";
|
||||
private @Nullable String splashImageUrl;
|
||||
private @Nullable String freeModeSplashImageUrl;
|
||||
private @Nullable String eapSplashImageUrl;
|
||||
private String svgIconUrl;
|
||||
private String mySvgEapIconUrl;
|
||||
@@ -144,6 +149,11 @@ public final class ApplicationInfoImpl extends ApplicationInfoEx {
|
||||
}
|
||||
break;
|
||||
|
||||
case "logo-free-mode": {
|
||||
freeModeSplashImageUrl = getAttributeValue(child, "url");
|
||||
}
|
||||
break;
|
||||
|
||||
case "icon": {
|
||||
svgIconUrl = child.getAttributeValue("svg");
|
||||
mySmallSvgIconUrl = child.getAttributeValue("svg-small");
|
||||
@@ -432,7 +442,16 @@ public final class ApplicationInfoImpl extends ApplicationInfoEx {
|
||||
|
||||
@Override
|
||||
public @Nullable String getSplashImageUrl() {
|
||||
return isEap && eapSplashImageUrl != null ? eapSplashImageUrl : splashImageUrl;
|
||||
if (isEap && eapSplashImageUrl != null) return eapSplashImageUrl;
|
||||
|
||||
if (freeModeSplashImageUrl != null) {
|
||||
Path markerFile = PathManager.getConfigDir().resolve(FREE_MODE_SPLASH_MARKER_FILE_NAME);
|
||||
if (Files.exists(markerFile)) {
|
||||
return freeModeSplashImageUrl;
|
||||
}
|
||||
}
|
||||
|
||||
return splashImageUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
<xs:element type="buildType" name="build"/>
|
||||
<xs:element type="logoType" name="logo"/>
|
||||
<xs:element type="logoType" name="logo-eap" minOccurs="0"/>
|
||||
<xs:element type="logoType" name="logo-free-mode" minOccurs="0"/>
|
||||
<xs:element type="iconType" name="icon"/>
|
||||
<xs:element type="iconEapType" name="icon-eap" minOccurs="0"/>
|
||||
<xs:element type="namesType" name="names"/>
|
||||
|
||||
+110
-1
@@ -1,15 +1,20 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.openapi.application.impl;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationInfo;
|
||||
import com.intellij.testFramework.PlatformTestUtil;
|
||||
import com.intellij.util.xml.dom.XmlElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.intellij.openapi.application.impl.UtilKt.withTempConfigDirectory;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class ApplicationInfoTest {
|
||||
@@ -31,10 +36,114 @@ public class ApplicationInfoTest {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void splashImage_eapLogoPreferredInEap() {
|
||||
ApplicationInfo info = createAppInfo(eap(true), logo, logoEap);
|
||||
assertThat(info.isEAP()).isTrue();
|
||||
String url = info.getSplashImageUrl();
|
||||
assertThat(url).isEqualTo(logoEapUrl);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void splashImage_regularLogoWhenNotEap() {
|
||||
ApplicationInfo info = createAppInfo(eap(false), logo, logoEap);
|
||||
assertThat(info.isEAP()).isFalse();
|
||||
String url = info.getSplashImageUrl();
|
||||
assertThat(url).isEqualTo(logoUrl);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void splashImage_regularLogoInEapWithNoEapLogoProvided() {
|
||||
ApplicationInfo info = createAppInfo(eap(true), logo);
|
||||
assertThat(info.isEAP()).isTrue();
|
||||
String url = info.getSplashImageUrl();
|
||||
assertThat(url).isEqualTo(logoUrl);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void splashImage_freeModeLogoPreferredWhenMarkerPresent() {
|
||||
withTempConfigDirectory(configDir -> {
|
||||
createFreeModeSplashMarkerFile(configDir);
|
||||
ApplicationInfo info = createAppInfo(logo, logoFreeMode);
|
||||
String url = info.getSplashImageUrl();
|
||||
assertThat(url).isEqualTo(logoFreeModeUrl);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void splashImage_regularLogoWhenNoFreeModeMarker() {
|
||||
withTempConfigDirectory(configDir -> {
|
||||
deleteFreeModeSplashMarkerFile(configDir);
|
||||
ApplicationInfo info = createAppInfo(logo, logoFreeMode);
|
||||
String url = info.getSplashImageUrl();
|
||||
assertThat(url).isEqualTo(logoUrl);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void splashImage_regularLogoWhenMarkerPresentButNoFreeModeLogoProvided() {
|
||||
withTempConfigDirectory(configDir -> {
|
||||
createFreeModeSplashMarkerFile(configDir);
|
||||
ApplicationInfo info = createAppInfo(logo);
|
||||
String url = info.getSplashImageUrl();
|
||||
assertThat(url).isEqualTo(logoUrl);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void splashImage_eapLogoBeatsFreeModeInEapWhenBothAvailableAndMarkerPresent() {
|
||||
withTempConfigDirectory(configDir -> {
|
||||
createFreeModeSplashMarkerFile(configDir);
|
||||
ApplicationInfo info = createAppInfo(eap(true), logo, logoEap, logoFreeMode);
|
||||
String url = info.getSplashImageUrl();
|
||||
assertThat(url).isEqualTo(logoEapUrl);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void splashImage_freeModeLogoWhenNotEapAndMarkerPresent() {
|
||||
withTempConfigDirectory(configDir -> {
|
||||
createFreeModeSplashMarkerFile(configDir);
|
||||
ApplicationInfo info = createAppInfo(eap(false), logo, logoEap, logoFreeMode);
|
||||
String url = info.getSplashImageUrl();
|
||||
assertThat(url).isEqualTo(logoFreeModeUrl);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void splashImage_regularLogoWhenNotEapAndNoMarker() {
|
||||
withTempConfigDirectory(configDir -> {
|
||||
deleteFreeModeSplashMarkerFile(configDir);
|
||||
ApplicationInfo info = createAppInfo(eap(false), logo, logoEap, logoFreeMode);
|
||||
String url = info.getSplashImageUrl();
|
||||
assertThat(url).isEqualTo(logoUrl);
|
||||
});
|
||||
}
|
||||
|
||||
public static @NotNull ApplicationInfoImpl createAppInfo(@NotNull XmlElement @NotNull ... content) {
|
||||
var children = new ArrayList<>(List.of(content));
|
||||
children.add(new XmlElement("icon", Map.of("svg", "xxx.svg", "svg-small", "xxx.svg"), List.of(), null));
|
||||
children.add(new XmlElement("plugins", Map.of(), List.of(), null));
|
||||
return new ApplicationInfoImpl(new XmlElement("state", Map.of(), children, null));
|
||||
}
|
||||
|
||||
private static void createFreeModeSplashMarkerFile(@NotNull Path configDir) throws IOException {
|
||||
Files.writeString(configDir.resolve(ApplicationInfoImpl.FREE_MODE_SPLASH_MARKER_FILE_NAME), "");
|
||||
}
|
||||
|
||||
private static void deleteFreeModeSplashMarkerFile(@NotNull Path configDir) throws IOException {
|
||||
Files.deleteIfExists(configDir.resolve(ApplicationInfoImpl.FREE_MODE_SPLASH_MARKER_FILE_NAME));
|
||||
}
|
||||
|
||||
private static XmlElement eap(boolean isEap) {
|
||||
return new XmlElement("version", Map.of("eap", String.valueOf(isEap)), List.of(), null);
|
||||
}
|
||||
|
||||
private static final String logoUrl = "/logo.png";
|
||||
private static final String logoEapUrl = "/logo_eap.png";
|
||||
private static final String logoFreeModeUrl = "/logo_free.png";
|
||||
|
||||
private final XmlElement logo = new XmlElement("logo", Map.of("url", logoUrl), List.of(), null);
|
||||
private final XmlElement logoEap = new XmlElement("logo-eap", Map.of("url", logoEapUrl), List.of(), null);
|
||||
private final XmlElement logoFreeMode = new XmlElement("logo-free-mode", Map.of("url", logoFreeModeUrl), List.of(), null);
|
||||
}
|
||||
|
||||
@@ -2,19 +2,19 @@
|
||||
package com.intellij.openapi.application.impl
|
||||
|
||||
import com.intellij.concurrency.ContextAwareRunnable
|
||||
import com.intellij.openapi.application.Application
|
||||
import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.application.ModalityState
|
||||
import com.intellij.openapi.application.asContextElement
|
||||
import com.intellij.openapi.application.*
|
||||
import com.intellij.testFramework.LeakHunter
|
||||
import com.intellij.testFramework.utils.io.deleteRecursively
|
||||
import com.intellij.util.ui.EDT
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.junit.jupiter.api.Assertions.assertNotNull
|
||||
import org.junit.jupiter.api.function.ThrowingConsumer
|
||||
import java.nio.file.Path
|
||||
import java.util.function.Supplier
|
||||
import javax.swing.SwingUtilities
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.io.path.createTempDirectory
|
||||
import kotlin.test.assertFalse
|
||||
|
||||
fun Application.withModality(action: () -> Unit) {
|
||||
@@ -64,3 +64,26 @@ suspend fun pumpEDT() {
|
||||
internal suspend fun processApplicationQueue() {
|
||||
withContext(Dispatchers.EDT + ModalityState.any().asContextElement()) {}
|
||||
}
|
||||
|
||||
internal fun withTempDirectory(block: ThrowingConsumer<Path>) {
|
||||
val tempDirectory = createTempDirectory()
|
||||
try {
|
||||
block.accept(tempDirectory)
|
||||
}
|
||||
finally {
|
||||
tempDirectory.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
internal fun withTempConfigDirectory(block: ThrowingConsumer<Path>) {
|
||||
withTempDirectory { tempDirectory ->
|
||||
val oldConfigDir = PathManager.getConfigDir()
|
||||
try {
|
||||
PathManager.setExplicitConfigPath(tempDirectory)
|
||||
block.accept(tempDirectory)
|
||||
}
|
||||
finally {
|
||||
PathManager.setExplicitConfigPath(oldConfigDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user