mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
ASPR-3010 Recommended plugin installation on IDEA startup
This commit is contained in:
committed by
Nikita Iarychenko
parent
e0972d8d7a
commit
87d9534fc9
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 60 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M59.024 19.4576C57.5531 18.4675 53.6878 18.0446 50.8776 18.8015C50.7261 16.0024 49.2829 13.6437 46.6426 11.5857L45.6651 10.9296L45.0138 11.9134C43.7333 13.8571 43.1938 16.4467 43.385 18.8007C43.5357 20.251 44.0403 21.8814 45.0138 23.0643C41.3563 25.1858 37.9852 24.7042 23.0555 24.7042H0.00465616C-0.062781 28.0753 0.479096 34.5603 4.60307 39.8395C5.05847 40.4226 5.5583 40.9867 6.10018 41.5302C9.45299 44.8877 14.5187 47.3496 22.0939 47.3567C33.6502 47.367 43.5516 41.1208 49.5741 26.0172C51.556 26.0498 56.7875 26.3727 59.3477 21.4252C59.4104 21.3419 59.9991 20.1129 59.9991 20.1129L59.0232 19.4568L59.024 19.4576ZM15.0479 16.3745H8.566V22.8564H15.0479V16.3745ZM23.422 16.3745H16.9401V22.8564H23.422V16.3745ZM31.7961 16.3745H25.3142V22.8564H31.7961V16.3745ZM40.1702 16.3745H33.6883V22.8564H40.1702V16.3745ZM6.67379 16.3745H0.191893V22.8564H6.67379V16.3745ZM15.0479 8.18766H8.566V14.6696H15.0479V8.18766ZM23.422 8.18766H16.9401V14.6696H23.422V8.18766ZM31.7961 8.18766H25.3142V14.6696H31.7961V8.18766ZM31.7961 0H25.3142V6.4819H31.7961V0Z" fill="#1D63ED"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,4 @@
|
||||
<!-- Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<path fill="#62B543" fill-opacity=".7" fill-rule="evenodd" d="M13.8189229,12.2851118 C11.7381304,15.0552815 7.29624189,14.1257561 4.44717245,14.2546012 C4.44717245,14.2546012 3.94283089,14.2832335 3.43439732,14.3670851 C3.43439732,14.3670851 3.62672229,14.2852786 3.87224354,14.2004045 C5.87221867,13.5091403 6.81849847,13.3700694 8.03485163,12.7452728 C10.3181992,11.5754411 12.5923397,9.02819378 13.0537151,6.3817562 C12.1841607,8.92798092 9.53969226,11.1183477 7.13256106,12.0059474 C5.4834767,12.61336 2.50243959,13.2064565 2.50243959,13.2074791 L2.38172498,13.1430565 C0.354128707,12.1572892 0.297863422,7.76939754 3.97863607,6.35516911 C5.59293826,5.73446293 7.13665308,6.07600472 8.88087692,5.65981457 C10.7417233,5.21805992 12.8961723,3.81917019 13.7718647,2 C14.7549727,4.91230844 15.9344977,9.46790327 13.8189229,12.2851118 Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
@@ -1,68 +1,19 @@
|
||||
<!-- Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
|
||||
<!-- -->
|
||||
<!-- Modified by Nikita Iarychenko at 2025 as part of the OpenIDE project (https://openide.ru). -->
|
||||
<!-- Any modifications are available on the same license terms as the original source code. -->
|
||||
<!-- Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_3181_691)">
|
||||
<mask id="mask0_3181_691" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="20" height="20">
|
||||
<rect width="20" height="20" rx="2.96875" fill="white"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_3181_691)">
|
||||
<g filter="url(#filter0_f_3181_691)">
|
||||
<circle cx="9.91837" cy="9.91837" r="9.91837" fill="#9B84E7"/>
|
||||
</g>
|
||||
<g filter="url(#filter1_f_3181_691)">
|
||||
<ellipse cx="18.125" cy="9.21875" rx="10" ry="17.3438" fill="#9B84E7"/>
|
||||
</g>
|
||||
<g filter="url(#filter2_f_3181_691)">
|
||||
<ellipse cx="7.30627" cy="22.7347" rx="8.77551" ry="9.10204" fill="#F24E4E"/>
|
||||
</g>
|
||||
<g filter="url(#filter3_f_3181_691)">
|
||||
<ellipse cx="-0.857113" cy="19.5102" rx="5.83673" ry="8.4898" fill="#9B84E7"/>
|
||||
</g>
|
||||
<g filter="url(#filter4_f_3181_691)">
|
||||
<ellipse cx="20.625" cy="21.25" rx="5.3125" ry="9.375" fill="white"/>
|
||||
</g>
|
||||
<g filter="url(#filter5_f_3181_691)">
|
||||
<ellipse cx="3.59191" cy="3.38776" rx="9.87755" ry="11.4694" fill="#4D409B"/>
|
||||
</g>
|
||||
</g>
|
||||
<path d="M12.6083 7.05312H15.9586C16.7326 7.05312 17.3599 6.46417 17.3599 5.73843V4.28846C17.3599 3.56272 16.7326 2.97377 15.9586 2.97377H12.6083C11.8343 2.97377 11.207 3.56272 11.207 4.28846V5.73843C11.207 6.46417 11.8343 7.05312 12.6083 7.05312Z" fill="white"/>
|
||||
<path d="M16.1192 8.12994H12.448C11.6854 8.12994 11.0672 8.75081 11.0672 9.51683V14.2034C11.0672 14.4906 10.8516 14.7422 10.5663 14.7597C10.2569 14.7787 9.99962 14.5324 9.99962 14.2239V3.44719C9.99962 2.87496 9.49723 2.42887 8.93354 2.50943C5.29571 3.02923 2.5 6.17082 2.5 9.96748C2.50076 14.1236 5.86242 17.5 10.0004 17.5C14.1383 17.5 17.5 14.1274 17.5 9.96596V9.51607C17.5 8.75005 16.8818 8.12918 16.1192 8.12918V8.12994Z" fill="white"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_f_3181_691" x="-4.57959" y="-4.57959" width="28.9961" height="28.9959" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="2.2898" result="effect1_foregroundBlur_3181_691"/>
|
||||
</filter>
|
||||
<filter id="filter1_f_3181_691" x="3.54541" y="-12.7046" width="29.1592" height="43.8467" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="2.2898" result="effect1_foregroundBlur_3181_691"/>
|
||||
</filter>
|
||||
<filter id="filter2_f_3181_691" x="-6.24475" y="8.85715" width="27.1018" height="27.7551" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="2.38776" result="effect1_foregroundBlur_3181_691"/>
|
||||
</filter>
|
||||
<filter id="filter3_f_3181_691" x="-11.2734" y="6.44082" width="20.8325" height="26.1388" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="2.2898" result="effect1_foregroundBlur_3181_691"/>
|
||||
</filter>
|
||||
<filter id="filter4_f_3181_691" x="8.56148" y="5.12398" width="24.127" height="32.252" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="3.37551" result="effect1_foregroundBlur_3181_691"/>
|
||||
</filter>
|
||||
<filter id="filter5_f_3181_691" x="-12.6203" y="-14.4163" width="32.4243" height="35.6082" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="3.16735" result="effect1_foregroundBlur_3181_691"/>
|
||||
</filter>
|
||||
<clipPath id="clip0_3181_691">
|
||||
<rect width="20" height="20" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g clip-path="url(#clip0_3917_59730)">
|
||||
<path d="M1.27273 20L12.1998 20C12.5373 20 12.8611 19.866 13.0998 19.6273L19.6273 13.1C19.866 12.8613 20 12.5376 20 12.2L20 1.27273C20 0.569819 19.4302 5.83484e-07 18.7273 5.22034e-07L7.80037 -4.33227e-07C7.46255 -4.6276e-07 7.13855 0.134364 6.89982 0.373273L0.372729 6.90782C0.134365 7.14636 0.000547716 7.47 0.000547686 7.80727L7.44565e-07 18.7273C6.83114e-07 19.4302 0.569819 20 1.27273 20Z" fill="url(#paint0_radial_3917_59730)"/>
|
||||
<path d="M16.6654 3.33398H3.33203V16.6673H16.6654V3.33398Z" fill="black"/>
|
||||
<path d="M10 14.166H5V14.9993H10V14.166Z" fill="white"/>
|
||||
<path d="M5 9.12853H5.99293V5.87147H5V5H7.94633V5.87147H6.9534V9.12853H7.94633V10H5V9.12853Z" fill="white"/>
|
||||
<path d="M8.44531 9.10008H9.16323C9.30838 9.10008 9.43767 9.06914 9.55074 9.00726C9.6638 8.94538 9.75127 8.85791 9.81315 8.74484C9.87503 8.63178 9.90597 8.50267 9.90597 8.35733V5H10.881V8.42494C10.881 8.72498 10.8118 8.99465 10.6737 9.23396C10.5356 9.47326 10.3452 9.66081 10.1023 9.79641C9.85937 9.9322 9.58683 10 9.2845 10H8.44531V9.10008Z" fill="white"/>
|
||||
</g>
|
||||
<defs>
|
||||
<radialGradient id="paint0_radial_3917_59730" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(19.4793 0.520923) rotate(135) scale(27.0205)">
|
||||
<stop offset="0.109181" stop-color="#FE2857"/>
|
||||
<stop offset="0.7" stop-color="#007EFF"/>
|
||||
</radialGradient>
|
||||
<clipPath id="clip0_3917_59730">
|
||||
<rect width="20" height="20" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 1.7 KiB |
@@ -1,68 +1,19 @@
|
||||
<!-- Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
|
||||
<!-- -->
|
||||
<!-- Modified by Nikita Iarychenko at 2025 as part of the OpenIDE project (https://openide.ru). -->
|
||||
<!-- Any modifications are available on the same license terms as the original source code. -->
|
||||
<!-- Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_3181_705)">
|
||||
<mask id="mask0_3181_705" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="24" height="24">
|
||||
<rect width="24" height="24" rx="3.5625" fill="white"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_3181_705)">
|
||||
<g filter="url(#filter0_f_3181_705)">
|
||||
<circle cx="11.902" cy="11.902" r="11.902" fill="#9B84E7"/>
|
||||
</g>
|
||||
<g filter="url(#filter1_f_3181_705)">
|
||||
<ellipse cx="21.75" cy="11.0625" rx="12" ry="20.8125" fill="#9B84E7"/>
|
||||
</g>
|
||||
<g filter="url(#filter2_f_3181_705)">
|
||||
<ellipse cx="8.76743" cy="27.2816" rx="10.5306" ry="10.9224" fill="#F24E4E"/>
|
||||
</g>
|
||||
<g filter="url(#filter3_f_3181_705)">
|
||||
<ellipse cx="-1.02863" cy="23.4122" rx="7.00408" ry="10.1878" fill="#9B84E7"/>
|
||||
</g>
|
||||
<g filter="url(#filter4_f_3181_705)">
|
||||
<ellipse cx="24.75" cy="25.5" rx="6.375" ry="11.25" fill="white"/>
|
||||
</g>
|
||||
<g filter="url(#filter5_f_3181_705)">
|
||||
<ellipse cx="4.31009" cy="4.06531" rx="11.8531" ry="13.7633" fill="#4D409B"/>
|
||||
</g>
|
||||
</g>
|
||||
<path d="M15.1298 8.46374H19.1501C20.079 8.46374 20.8316 7.757 20.8316 6.88611V5.14615C20.8316 4.27526 20.079 3.56851 19.1501 3.56851H15.1298C14.2009 3.56851 13.4482 4.27526 13.4482 5.14615V6.88611C13.4482 7.757 14.2009 8.46374 15.1298 8.46374Z" fill="white"/>
|
||||
<path d="M19.343 9.75593H14.9377C14.0224 9.75593 13.2807 10.501 13.2807 11.4202V17.0441C13.2807 17.3888 13.0219 17.6906 12.6796 17.7116C12.3082 17.7344 11.9995 17.4389 11.9995 17.0687V4.13663C11.9995 3.44995 11.3967 2.91465 10.7203 3.01131C6.35485 3.63507 3 7.40498 3 11.961C3.00091 16.9483 7.03491 21 12.0005 21C16.966 21 21 16.9529 21 11.9591V11.4193C21 10.5001 20.2582 9.75502 19.343 9.75502V9.75593Z" fill="white"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_f_3181_705" x="-5.49551" y="-5.49551" width="34.7952" height="34.7951" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="2.74776" result="effect1_foregroundBlur_3181_705"/>
|
||||
</filter>
|
||||
<filter id="filter1_f_3181_705" x="4.25449" y="-15.2455" width="34.991" height="52.616" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="2.74776" result="effect1_foregroundBlur_3181_705"/>
|
||||
</filter>
|
||||
<filter id="filter2_f_3181_705" x="-7.4938" y="10.6286" width="32.5223" height="33.3061" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="2.86531" result="effect1_foregroundBlur_3181_705"/>
|
||||
</filter>
|
||||
<filter id="filter3_f_3181_705" x="-13.5282" y="7.72898" width="24.9993" height="31.3665" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="2.74776" result="effect1_foregroundBlur_3181_705"/>
|
||||
</filter>
|
||||
<filter id="filter4_f_3181_705" x="10.2738" y="6.14878" width="28.9524" height="38.7024" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="4.05061" result="effect1_foregroundBlur_3181_705"/>
|
||||
</filter>
|
||||
<filter id="filter5_f_3181_705" x="-15.1446" y="-17.2996" width="38.9093" height="42.7298" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="3.80082" result="effect1_foregroundBlur_3181_705"/>
|
||||
</filter>
|
||||
<clipPath id="clip0_3181_705">
|
||||
<rect width="24" height="24" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g clip-path="url(#clip0_3917_59729)">
|
||||
<path d="M1.52727 24L14.6398 24C15.0447 24 15.4333 23.8392 15.7198 23.5527L23.5527 15.72C23.8392 15.4335 24 15.0452 24 14.64L24 1.52727C24 0.683782 23.3162 2.90399e-07 22.4727 2.16659e-07L9.36044 -9.29654e-07C8.95506 -9.65094e-07 8.56626 0.161236 8.27978 0.447927L0.447274 8.28938C0.161238 8.57563 0.000656849 8.964 0.000656814 9.36873L4.83696e-07 22.4727C4.09955e-07 23.3162 0.683782 24 1.52727 24Z" fill="url(#paint0_radial_3917_59729)"/>
|
||||
<path d="M20 4H4V20H20V4Z" fill="black"/>
|
||||
<path d="M12 17H6V18H12V17Z" fill="white"/>
|
||||
<path d="M6 10.9542H7.19152V7.04576H6V6H9.5356V7.04576H8.34408V10.9542H9.5356V12H6V10.9542Z" fill="white"/>
|
||||
<path d="M10.1367 10.9201H10.9982C11.1724 10.9201 11.3276 10.883 11.4632 10.8087C11.5989 10.7345 11.7039 10.6295 11.7781 10.4938C11.8524 10.3581 11.8895 10.2032 11.8895 10.0288V6H13.0595V10.1099C13.0595 10.47 12.9765 10.7936 12.8108 11.0807C12.6451 11.3679 12.4166 11.593 12.1251 11.7557C11.8336 11.9186 11.5065 12 11.1437 12H10.1367V10.9201Z" fill="white"/>
|
||||
</g>
|
||||
<defs>
|
||||
<radialGradient id="paint0_radial_3917_59729" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(23.3751 0.625108) rotate(135) scale(32.4245)">
|
||||
<stop offset="0.109181" stop-color="#FE2857"/>
|
||||
<stop offset="0.7" stop-color="#007EFF"/>
|
||||
</radialGradient>
|
||||
<clipPath id="clip0_3917_59729">
|
||||
<rect width="24" height="24" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 1.7 KiB |
+1
-1
@@ -29,7 +29,7 @@
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<applicationService serviceInterface="com.intellij.ide.startup.importSettings.data.StartupWizardService" open="true"
|
||||
serviceImplementation="com.intellij.ide.startup.importSettings.data.DisabledStartupWizardPages"/>
|
||||
serviceImplementation="com.intellij.ide.startup.importSettings.chooser.ui.OpenIdeStartupWizardService"/>
|
||||
|
||||
<transferSettings.thirdPartyProductSettingsTransfer id="VSCodeSettingsTransfer"
|
||||
implementation="com.intellij.ide.startup.importSettings.transfer.VsCodeSettingsTransfer"/>
|
||||
|
||||
+34
-8
@@ -41,11 +41,12 @@ exit.confirm.title = Settings Import Is in Progress
|
||||
exit.confirm.prompt = Do you want to stop the import?<br>If you stop it now, only part of the settings will be imported.
|
||||
stop.import = Stop Import
|
||||
|
||||
onboarding.wizard.finish-button=Finish
|
||||
onboarding.wizard.finish-button=Готово
|
||||
onboarding.wizard.getting-ready=Getting Ready\u2026
|
||||
|
||||
plugin-installation.progress.text-with-details={0} / {1}
|
||||
plugin-installation.progress.determining-plugins-to-download=Determining plugins to download
|
||||
plugin-installation.progress.downloading=Установка {0}...
|
||||
|
||||
settings.category.ui.name=UI settings
|
||||
settings.category.ui.description=Includes theme, editor font, toolbar, and notifications
|
||||
@@ -66,6 +67,7 @@ transfer.settings.message=Importing from {0}\u2026
|
||||
import.settings.title = Importing settings\u2026
|
||||
import.settings.ok = Import Settings
|
||||
import.settings.back = Back
|
||||
import.settings.back.ru = Назад
|
||||
import.settings.sync.ok = Sync Settings
|
||||
import.settings.sync.import.once = Import Once
|
||||
|
||||
@@ -87,13 +89,37 @@ choose.product.setting.sync.turned.off=Setting Sync Is Turned Off
|
||||
choose.keymap.title = Choose Keymap
|
||||
wizard.button.continue = Continue
|
||||
|
||||
plugins.page.title = Featured Plugins
|
||||
plugins.page.ok.button.continue.without = Continue without Plugins
|
||||
plugins.page.ok.button.install = Install Selected
|
||||
plugins.page.choose.counter.no = No plugins selected for installation
|
||||
plugins.page.choose.counter.one = 1 plugin selected for installation
|
||||
plugins.page.choose.counter.multiple = {0} plugins selected for installation
|
||||
install.plugins.page.title = Installing Plugins\u2026
|
||||
plugins.page.title = Рекомендуемые Плагины
|
||||
plugins.page.ok.button.continue.without = Продолжить без Плагинов
|
||||
plugins.page.ok.button.install = Установить Выбранные
|
||||
plugins.page.choose.counter.no = Нет плагинов для установки
|
||||
plugins.page.choose.counter.one = 1 плагин выбран для установки
|
||||
plugins.page.choose.counter.multiple = Выбрано плагинов для установки: {0}
|
||||
plugins.page.list.item.bundled = Предустановлен
|
||||
|
||||
# Plugin descriptions
|
||||
plugin.description.mapstruct = Плагин для редактирования MapStruct мапперов
|
||||
plugin.description.init.spring = Интеграция Init Spring для новых проектов
|
||||
plugin.description.checkStyle = Статический анализ кода на соответствие стандартам кодирования
|
||||
plugin.description.mavenHelper = Анализ зависимостей Maven и запуск из редактора
|
||||
plugin.description.java.kotlin.support = Поддерживается OpenIDE
|
||||
plugin.description.spring.support = Поддерживается Amplicode
|
||||
plugin.description.python = Поддержка языка Python
|
||||
plugin.description.django = Поддержка Django фреймворка для веб-приложений на Python
|
||||
plugin.description.pylint = Статический анализатор кода Python для выявления ошибок
|
||||
plugin.description.csvEditor = Редактор CSV и TSV файлов с подсветкой и форматированием
|
||||
plugin.description.pydantic = Поддержка Pydantic для валидации данных в Python
|
||||
plugin.description.webtools = Набор инструментов для веб-разработки
|
||||
plugin.description.go = Поддержка языка Go
|
||||
plugin.description.fileWatchers = Автоматический запуск внешних инструментов при изменении файлов
|
||||
plugin.description.makefile = Подсветка синтаксиса и навигация для Makefile
|
||||
plugin.description.protocolBuffers = Поддержка Protocol Buffers для сериализации данных
|
||||
plugin.description.easyp = Линтинг и форматирование proto файлов с помощью easyp
|
||||
plugin.description.kilocode = Kilo Code AI Агент
|
||||
plugin.description.continue = Open-source AI ассистент для кода
|
||||
plugin.description.docker = Поддержка Docker для управления контейнерами
|
||||
|
||||
install.plugins.page.title = Установка Плагинов\u2026
|
||||
|
||||
theme.page.title = Choose Theme
|
||||
theme.page.dark = Dark
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
// OpenIDE Project
|
||||
// Copyright (C) 2026 “Open Development Platform” Ltd. (https://openide.ru)
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License version 3 or later as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
package com.intellij.ide.startup.importSettings;
|
||||
|
||||
import com.intellij.ui.IconManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public final class OpenIdePluginIcons {
|
||||
private static @NotNull Icon load(@NotNull String path, int cacheKey, int flags) {
|
||||
return IconManager.getInstance().loadRasterizedIcon(path, OpenIdePluginIcons.class.getClassLoader(), cacheKey, flags);
|
||||
}
|
||||
|
||||
public static final class Icons {
|
||||
/** 60x48 */ public static final @NotNull Icon Docker = load("icons/docker.svg", -271658419, 0);
|
||||
/** 16x16 */ public static final @NotNull Icon Spring = load("icons/spring.svg", 1614158219, 0);
|
||||
}
|
||||
}
|
||||
+7
-4
@@ -1,4 +1,7 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
//
|
||||
// Modified by Artyom Orlov at 2026 as part of the OpenIDE project(https://openide.ru).
|
||||
// Any modifications are available on the same license terms as the original source code.
|
||||
package com.intellij.ide.startup.importSettings;
|
||||
|
||||
import com.intellij.ui.IconManager;
|
||||
@@ -45,9 +48,9 @@ public final class StartupImportIcons {
|
||||
/** 20x20 */ public static final @NotNull Icon GO_20 = load("ideIcons/GO_20.svg", -1868538832, 0);
|
||||
/** 24x24 */ public static final @NotNull Icon GO_24 = load("ideIcons/GO_24.svg", 1440377958, 0);
|
||||
/** 48x48 */ public static final @NotNull Icon GO_48 = load("ideIcons/GO_48.svg", 1561543628, 0);
|
||||
/** 20x20 */ public static final @NotNull Icon IC_20 = load("ideIcons/IC_20.svg", -1970123839, 0);
|
||||
/** 24x24 */ public static final @NotNull Icon IC_24 = load("ideIcons/IC_24.svg", 1159411325, 0);
|
||||
/** 48x48 */ public static final @NotNull Icon IC_48 = load("ideIcons/IC_48.svg", 337830589, 0);
|
||||
/** 20x20 */ public static final @NotNull Icon IC_20 = load("ideIcons/IC_20.svg", -1970123830, 0);
|
||||
/** 24x24 */ public static final @NotNull Icon IC_24 = load("ideIcons/IC_24.svg", 1159411326, 0);
|
||||
/** 48x48 */ public static final @NotNull Icon IC_48 = load("ideIcons/IC_48.svg", 337830580, 0);
|
||||
/** 20x20 */ public static final @NotNull Icon IU_20 = load("ideIcons/IU_20.svg", 1667621169, 0);
|
||||
/** 24x24 */ public static final @NotNull Icon IU_24 = load("ideIcons/IU_24.svg", 458021303, 0);
|
||||
/** 48x48 */ public static final @NotNull Icon IU_48 = load("ideIcons/IU_48.svg", 897538403, 0);
|
||||
|
||||
+5
-2
@@ -1,4 +1,7 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
//
|
||||
// Modified by Artyom Orlov at 2026 as part of the OpenIDE project(https://openide.ru).
|
||||
// Any modifications are available on the same license terms as the original source code.
|
||||
package com.intellij.ide.startup.importSettings.chooser.ui
|
||||
|
||||
import com.intellij.ide.startup.importSettings.data.StartupWizardService
|
||||
@@ -107,7 +110,7 @@ class OnboardingController private constructor(){
|
||||
}
|
||||
|
||||
service.onEnter()
|
||||
wizardController.goToThemePage(true)
|
||||
wizardController.goToPluginPage()
|
||||
|
||||
if(!dl.isShowing) {
|
||||
dl.initialize()
|
||||
|
||||
+272
@@ -0,0 +1,272 @@
|
||||
// OpenIDE Project
|
||||
// Copyright (C) 2026 “Open Development Platform” Ltd. (https://openide.ru)
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License version 3 or later as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
package com.intellij.ide.startup.importSettings.chooser.ui
|
||||
|
||||
import com.intellij.icons.AllIcons
|
||||
import com.intellij.ide.startup.importSettings.ImportSettingsBundle
|
||||
import com.intellij.ide.startup.importSettings.OpenIdePluginIcons
|
||||
import com.intellij.ide.startup.importSettings.data.*
|
||||
import com.intellij.ide.startup.importSettings.openide.utils.PluginInstallationUtil
|
||||
import com.intellij.ide.startup.importSettings.transfer.ProgressIndicatorAdapter
|
||||
import com.intellij.ide.startup.importSettings.transfer.TransferSettingsProgressIndicator
|
||||
import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.application.ModalityState
|
||||
import com.intellij.openapi.application.asContextElement
|
||||
import com.intellij.openapi.application.ex.ApplicationManagerEx
|
||||
import com.intellij.util.IconUtil
|
||||
import com.jetbrains.rd.util.lifetime.Lifetime
|
||||
import com.jetbrains.rd.util.reactive.Property
|
||||
import com.jetbrains.rd.util.reactive.Signal
|
||||
import kotlinx.coroutines.*
|
||||
|
||||
class OpenIdeStartupWizardService(private val coroutineScope: CoroutineScope) : StartupWizardService {
|
||||
override val isActive = true
|
||||
private val _shouldClose = Signal<Unit>()
|
||||
override val shouldClose: Signal<Unit>
|
||||
get() = _shouldClose
|
||||
|
||||
override fun getKeymapService(): KeymapService {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun getThemeService(): ThemeService {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
|
||||
override fun getPluginService(): PluginService {
|
||||
return object : PluginService {
|
||||
override val pluginGroups: List<WizardPluginGroup>
|
||||
get() = listOf(
|
||||
WizardPluginGroupImpl(
|
||||
id = "ai",
|
||||
name = "AI",
|
||||
icon = AllIcons.Actions.Lightning,
|
||||
plugins = listOf(
|
||||
WizardPluginImpl(
|
||||
id = "ai.kilocode.jetbrains",
|
||||
icon = AllIcons.Plugins.PluginLogo,
|
||||
name = "Kilo Code",
|
||||
description = ImportSettingsBundle.message("plugin.description.kilocode"),
|
||||
),
|
||||
WizardPluginImpl(
|
||||
id = "com.github.continuedev.continueintellijextension",
|
||||
icon = AllIcons.Plugins.PluginLogo,
|
||||
name = "Continue",
|
||||
description = ImportSettingsBundle.message("plugin.description.continue"),
|
||||
),
|
||||
)
|
||||
),
|
||||
WizardPluginGroupImpl(
|
||||
id = "java-kotlin",
|
||||
name = "Java / Kotlin",
|
||||
icon = AllIcons.FileTypes.Java,
|
||||
plugins = listOf(
|
||||
WizardPluginImpl(
|
||||
id = "org.mapstruct.intellij",
|
||||
icon = AllIcons.Plugins.PluginLogo,
|
||||
name = "MapStruct Support",
|
||||
description = ImportSettingsBundle.message("plugin.description.mapstruct"),
|
||||
),
|
||||
WizardPluginImpl(
|
||||
id = "pro.nikolaev.init-spring",
|
||||
icon = AllIcons.Plugins.PluginLogo,
|
||||
name = "Init Spring",
|
||||
description = ImportSettingsBundle.message("plugin.description.init.spring"),
|
||||
),
|
||||
WizardPluginImpl(
|
||||
id = "CheckStyle-IDEA",
|
||||
icon = AllIcons.Plugins.PluginLogo,
|
||||
name = "CheckStyle-IDEA",
|
||||
description = ImportSettingsBundle.message("plugin.description.checkStyle"),
|
||||
),
|
||||
WizardPluginImpl(
|
||||
id = "MavenRunHelper",
|
||||
icon = AllIcons.Plugins.PluginLogo,
|
||||
name = "Maven Helper",
|
||||
description = ImportSettingsBundle.message("plugin.description.mavenHelper"),
|
||||
),
|
||||
WizardPluginImpl(
|
||||
id = "bundled.java.kotlin",
|
||||
icon = AllIcons.FileTypes.Java,
|
||||
name = "Java / Kotlin support",
|
||||
description = ImportSettingsBundle.message("plugin.description.java.kotlin.support"),
|
||||
bundled = true,
|
||||
),
|
||||
WizardPluginImpl(
|
||||
id = "bundled.spring",
|
||||
icon = OpenIdePluginIcons.Icons.Spring,
|
||||
name = "Spring support",
|
||||
description = ImportSettingsBundle.message("plugin.description.spring.support"),
|
||||
bundled = true,
|
||||
),
|
||||
|
||||
)
|
||||
),
|
||||
WizardPluginGroupImpl(
|
||||
id = "python",
|
||||
name = "Python",
|
||||
icon = AllIcons.Language.Python,
|
||||
plugins = listOf(
|
||||
WizardPluginImpl(
|
||||
id = "PythonCore",
|
||||
icon = AllIcons.Plugins.PluginLogo,
|
||||
name = "Python Community Edition",
|
||||
description = ImportSettingsBundle.message("plugin.description.python"),
|
||||
),
|
||||
WizardPluginImpl(
|
||||
id = "com.haulmont.django",
|
||||
icon = AllIcons.Plugins.PluginLogo,
|
||||
name = "Django[beta]",
|
||||
description = ImportSettingsBundle.message("plugin.description.django"),
|
||||
),
|
||||
WizardPluginImpl(
|
||||
id = "com.leinardi.pycharm.pylint",
|
||||
icon = AllIcons.Plugins.PluginLogo,
|
||||
name = "Pylint",
|
||||
description = ImportSettingsBundle.message("plugin.description.pylint"),
|
||||
),
|
||||
WizardPluginImpl(
|
||||
id = "net.seesharpsoft.intellij.plugins.csv",
|
||||
icon = AllIcons.Plugins.PluginLogo,
|
||||
name = "CSV Editor",
|
||||
description = ImportSettingsBundle.message("plugin.description.csvEditor"),
|
||||
),
|
||||
//WizardPluginImpl(
|
||||
// id = "com.koxudaxi.pydantic",
|
||||
// icon = AllIcons.Plugins.PluginLogo,
|
||||
// name = "Pydantic",
|
||||
// description = ImportSettingsBundle.message("plugin.description.pydantic"),
|
||||
//),
|
||||
)
|
||||
),
|
||||
WizardPluginGroupImpl(
|
||||
id = "web",
|
||||
name = "Web",
|
||||
icon = AllIcons.FileTypes.Html,
|
||||
plugins = listOf(
|
||||
WizardPluginImpl(
|
||||
id = "com.haulmont.webtools",
|
||||
icon = AllIcons.Plugins.PluginLogo,
|
||||
name = "Frontend/Web [beta]",
|
||||
description = ImportSettingsBundle.message("plugin.description.webtools"),
|
||||
),
|
||||
)
|
||||
),
|
||||
WizardPluginGroupImpl(
|
||||
id = "go",
|
||||
name = "Go",
|
||||
icon = AllIcons.Language.GO,
|
||||
plugins = listOf(
|
||||
WizardPluginImpl(
|
||||
id = "com.haulmont.go",
|
||||
icon = AllIcons.Plugins.PluginLogo,
|
||||
name = "Go [beta]",
|
||||
description = ImportSettingsBundle.message("plugin.description.go"),
|
||||
),
|
||||
WizardPluginImpl(
|
||||
id = "com.intellij.plugins.watcher",
|
||||
icon = AllIcons.Plugins.PluginLogo,
|
||||
name = "File Watchers",
|
||||
description = ImportSettingsBundle.message("plugin.description.fileWatchers"),
|
||||
),
|
||||
WizardPluginImpl(
|
||||
id = "name.kropp.intellij.makefile",
|
||||
icon = AllIcons.Plugins.PluginLogo,
|
||||
name = "Makefile Language",
|
||||
description = ImportSettingsBundle.message("plugin.description.makefile"),
|
||||
),
|
||||
WizardPluginImpl(
|
||||
id = "idea.plugin.protoeditor",
|
||||
icon = AllIcons.Plugins.PluginLogo,
|
||||
name = "Protocol Buffers",
|
||||
description = ImportSettingsBundle.message("plugin.description.protocolBuffers"),
|
||||
),
|
||||
WizardPluginImpl(
|
||||
id = "com.github.easyptech.easyp",
|
||||
icon = AllIcons.Plugins.PluginLogo,
|
||||
name = "easyp",
|
||||
description = ImportSettingsBundle.message("plugin.description.easyp"),
|
||||
),
|
||||
)
|
||||
),
|
||||
WizardPluginGroupImpl(
|
||||
id = "deployment",
|
||||
name = "Deployment",
|
||||
icon = OpenIdePluginIcons.Icons.Docker,
|
||||
plugins = listOf(
|
||||
WizardPluginImpl(
|
||||
id = "ru.openide.docker",
|
||||
icon = AllIcons.Plugins.PluginLogo,
|
||||
name = "Docker",
|
||||
description = ImportSettingsBundle.message("plugin.description.docker"),
|
||||
),
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
override fun onStepEnter() {
|
||||
}
|
||||
|
||||
override fun install(lifetime: Lifetime, ids: List<String>): PluginImportProgress {
|
||||
val progressIndicator = TransferSettingsProgressIndicator()
|
||||
val progressAdapter = ProgressIndicatorAdapter(progressIndicator)
|
||||
val iconProperty = Property(AllIcons.Plugins.PluginLogo)
|
||||
|
||||
coroutineScope.launch {
|
||||
var needRestart = false
|
||||
try {
|
||||
needRestart = PluginInstallationUtil.installPlugins(ids, progressAdapter) { icon ->
|
||||
iconProperty.set(IconUtil.resizeSquared(icon, 64))
|
||||
}
|
||||
} catch (e: CancellationException) {
|
||||
throw e
|
||||
} catch (_: Exception) {
|
||||
} finally {
|
||||
withContext(Dispatchers.EDT + ModalityState.any().asContextElement()) {
|
||||
if (needRestart) {
|
||||
ApplicationManagerEx.getApplicationEx().restart(true)
|
||||
} else {
|
||||
_shouldClose.fire(Unit)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return object : PluginImportProgress {
|
||||
override val icon = iconProperty
|
||||
override val progressMessage = progressIndicator.progressMessage
|
||||
override val progress = progressIndicator.progress
|
||||
}
|
||||
}
|
||||
|
||||
override fun skipPlugins() {
|
||||
}
|
||||
|
||||
override fun shouldShowPage(pluginIdsMarkedForInstallation: List<String>): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
override fun onEnter() {
|
||||
}
|
||||
|
||||
override fun onCancel() {
|
||||
}
|
||||
|
||||
override fun onExit() {
|
||||
}
|
||||
}
|
||||
+6
-4
@@ -1,4 +1,7 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
//
|
||||
// Modified by Artyom Orlov at 2026 as part of the OpenIDE project(https://openide.ru).
|
||||
// Any modifications are available on the same license terms as the original source code.
|
||||
package com.intellij.ide.startup.importSettings.chooser.ui
|
||||
|
||||
import com.intellij.ide.startup.importSettings.data.StartupWizardService
|
||||
@@ -64,9 +67,8 @@ internal class WizardControllerImpl(dialog: OnboardingDialog,
|
||||
}
|
||||
|
||||
override fun goToPluginPage() {
|
||||
val page = WizardPluginsPage(this, service.getPluginService(), goBackAction = {
|
||||
goToKeymapPage(isForwardDirection = false)
|
||||
}, goForwardAction = { ids ->
|
||||
val page = WizardPluginsPage(this, service.getPluginService(), goBackAction = null,
|
||||
goForwardAction = { ids ->
|
||||
goToInstallPluginPage(ids)
|
||||
}, continueButtonTextOverride = null)
|
||||
dialog.changePage(page)
|
||||
|
||||
+14
-2
@@ -1,4 +1,7 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
//
|
||||
// Modified by Artyom Orlov at 2026 as part of the OpenIDE project(https://openide.ru).
|
||||
// Any modifications are available on the same license terms as the original source code.
|
||||
package com.intellij.ide.startup.importSettings.data
|
||||
|
||||
import com.intellij.ide.startup.importSettings.ImportSettingsBundle
|
||||
@@ -88,7 +91,7 @@ data class WizardScheme(
|
||||
)
|
||||
|
||||
interface PluginService {
|
||||
val plugins: List<WizardPlugin>
|
||||
val pluginGroups: List<WizardPluginGroup>
|
||||
fun onStepEnter()
|
||||
fun install(lifetime: Lifetime, ids: List<String>): PluginImportProgress
|
||||
fun skipPlugins()
|
||||
@@ -104,6 +107,15 @@ interface WizardPlugin {
|
||||
val icon: Icon
|
||||
val name: String
|
||||
val description: String?
|
||||
val bundled: Boolean
|
||||
get() = false
|
||||
}
|
||||
|
||||
interface WizardPluginGroup {
|
||||
val id: String
|
||||
val name: String
|
||||
val icon: Icon
|
||||
val plugins: List<WizardPlugin>
|
||||
}
|
||||
|
||||
interface KeymapService {
|
||||
|
||||
+19
-2
@@ -1,4 +1,7 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
//
|
||||
// Modified by Artyom Orlov at 2026 as part of the OpenIDE project(https://openide.ru).
|
||||
// Any modifications are available on the same license terms as the original source code.
|
||||
package com.intellij.ide.startup.importSettings.data
|
||||
|
||||
import com.intellij.icons.AllIcons
|
||||
@@ -91,7 +94,14 @@ class PluginServiceImpl : PluginService {
|
||||
WizardPluginImpl(AllIcons.TransferSettings.Vscode, "Ideolog", "An interactive viewer for log files with customizible highlighting, filtration and navigation to source code."),
|
||||
)
|
||||
|
||||
override val plugins: List<WizardPlugin> = listOf
|
||||
override val pluginGroups: List<WizardPluginGroup> = listOf(
|
||||
WizardPluginGroupImpl(
|
||||
id = "mock.group",
|
||||
name = "Mock Group",
|
||||
icon = AllIcons.Plugins.PluginLogo,
|
||||
plugins = listOf
|
||||
)
|
||||
)
|
||||
|
||||
override fun onStepEnter() {}
|
||||
|
||||
@@ -136,6 +146,13 @@ class WizardPluginImpl(
|
||||
override val id: String = UUID.randomUUID().toString(),
|
||||
) : WizardPlugin
|
||||
|
||||
class WizardPluginGroupImpl(
|
||||
override val id: String,
|
||||
override val name: String,
|
||||
override val icon: Icon,
|
||||
override val plugins: List<WizardPlugin>
|
||||
) : WizardPluginGroup
|
||||
|
||||
@Suppress("HardCodedStringLiteral")
|
||||
class TestKeymapService : KeymapService {
|
||||
override val keymaps: List<WizardKeymap> = listOf(
|
||||
|
||||
+6
-5
@@ -24,6 +24,7 @@ import com.intellij.ide.startup.importSettings.data.IconProductSize
|
||||
import com.intellij.ide.startup.importSettings.data.JbService
|
||||
import com.intellij.ide.startup.importSettings.data.Product
|
||||
import com.intellij.ide.startup.importSettings.data.SettingsService
|
||||
import com.intellij.ide.startup.importSettings.openide.utils.PluginInstallationUtil
|
||||
import com.intellij.ide.startup.importSettings.statistics.ImportSettingsEventsCollector
|
||||
import com.intellij.ide.startup.importSettings.transfer.TransferSettingsProgress
|
||||
import com.intellij.l10n.LocalizationStateService
|
||||
@@ -418,6 +419,8 @@ class JbImportServiceImpl(private val coroutineScope: CoroutineScope) : JbServic
|
||||
filteredCategories.add(SettingsCategory.PLUGINS)
|
||||
plugins2import = productInfo.getPluginsDescriptors().filter {
|
||||
setting.selectedChildIds?.contains(it.key.idString) ?: false
|
||||
}.filter { (_, descriptor) ->
|
||||
PluginManagerCore.isCompatible(descriptor) && descriptor.namespace?.lowercase() != "jetbrains"
|
||||
}
|
||||
unselectedPlugins = setting.unselectedChildIds
|
||||
logger.info(
|
||||
@@ -660,11 +663,9 @@ private suspend fun calculatePluginsToInstall(alreadyInstalled: Set<PluginId>, t
|
||||
if (pluginsToAttemptInstallation.isEmpty()) return emptyList()
|
||||
|
||||
reporter.text(ImportSettingsBundle.message("plugin-installation.progress.determining-plugins-to-download"))
|
||||
val loadedPlugins = withContext(Dispatchers.IO) {
|
||||
MarketplaceRequests.loadLastCompatiblePluginModels(pluginsToAttemptInstallation.toSet(), buildNumber = null, throwExceptions = true)
|
||||
.mapNotNull { it.getDescriptor() as? PluginNode }
|
||||
}
|
||||
return loadedPlugins
|
||||
val loadedPlugins = PluginInstallationUtil.getPluginsToInstall(pluginsToAttemptInstallation)
|
||||
|
||||
return loadedPlugins.filter { it.pluginId !in alreadyInstalled }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
// OpenIDE Project
|
||||
// Copyright (C) 2026 “Open Development Platform” Ltd. (https://openide.ru)
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License version 3 or later as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
package com.intellij.ide.startup.importSettings.openide.service
|
||||
|
||||
import com.intellij.ide.plugins.marketplace.MarketplaceRequests
|
||||
import com.intellij.ide.plugins.newui.PluginLogo
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.extensions.PluginId
|
||||
import com.intellij.openapi.util.IntellijInternalApi
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.swing.Icon
|
||||
|
||||
@Service(Service.Level.APP)
|
||||
class PluginIconService {
|
||||
|
||||
suspend fun loadIcon(pluginId: String): Icon? {
|
||||
return withContext(Dispatchers.IO) {
|
||||
loadFromMarketplace(pluginId)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(IntellijInternalApi::class)
|
||||
private fun loadFromMarketplace(pluginId: String): Icon? {
|
||||
return try {
|
||||
val marketplaceRequests = MarketplaceRequests.getInstance()
|
||||
val pluginNode = marketplaceRequests.getLastCompatiblePluginUpdateModel(
|
||||
PluginId.getId(pluginId),
|
||||
buildNumber = null
|
||||
) ?: return null
|
||||
|
||||
PluginLogo.getIcon(pluginNode.getDescriptor(), false, false, false)
|
||||
} catch (_: Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getInstance(): PluginIconService = service()
|
||||
}
|
||||
}
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
// OpenIDE Project
|
||||
// Copyright (C) 2026 “Open Development Platform” Ltd. (https://openide.ru)
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License version 3 or later as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
package com.intellij.ide.startup.importSettings.openide.utils
|
||||
|
||||
import com.intellij.ide.plugins.IdeaPluginDescriptor
|
||||
import com.intellij.ide.plugins.PluginManagerCore
|
||||
import com.intellij.ide.plugins.PluginNode
|
||||
import com.intellij.ide.plugins.marketplace.MarketplaceRequests
|
||||
import com.intellij.ide.startup.importSettings.ImportSettingsBundle
|
||||
import com.intellij.ide.startup.importSettings.openide.service.PluginIconService
|
||||
import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.application.ModalityState
|
||||
import com.intellij.openapi.application.asContextElement
|
||||
import com.intellij.openapi.extensions.PluginId
|
||||
import com.intellij.openapi.progress.ProgressIndicator
|
||||
import com.intellij.openapi.updateSettings.impl.PluginDownloader
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.swing.Icon
|
||||
|
||||
object PluginInstallationUtil {
|
||||
|
||||
/**
|
||||
* Installs plugins by their IDs.
|
||||
* @param onIconLoaded callback to update icon when plugin icon is loaded
|
||||
* @return true if IDE restart is required after installation
|
||||
*/
|
||||
@Suppress("DEPRECATION")
|
||||
suspend fun installPlugins(
|
||||
pluginIds: List<String>,
|
||||
progressIndicator: ProgressIndicator,
|
||||
onIconLoaded: ((Icon) -> Unit)? = null,
|
||||
): Boolean {
|
||||
if (progressIndicator.isCanceled || pluginIds.isEmpty()) {
|
||||
return false
|
||||
}
|
||||
|
||||
val idsToInstall = pluginIds
|
||||
.map { PluginId.Companion.getId(it) }
|
||||
.filter { !PluginManagerCore.isPluginInstalled(it) }
|
||||
|
||||
if (idsToInstall.isEmpty()) {
|
||||
progressIndicator.fraction = 1.0
|
||||
return false
|
||||
}
|
||||
|
||||
progressIndicator.text = ImportSettingsBundle.message("plugin-installation.progress.determining-plugins-to-download")
|
||||
progressIndicator.fraction = 0.05
|
||||
|
||||
val pluginsToInstall: List<IdeaPluginDescriptor> = getPluginsToInstall(idsToInstall)
|
||||
|
||||
if (pluginsToInstall.isEmpty()) {
|
||||
progressIndicator.fraction = 1.0
|
||||
return false
|
||||
}
|
||||
|
||||
var shouldRestart = false
|
||||
val progressPerPlugin = 0.9 / pluginsToInstall.size.coerceAtLeast(1)
|
||||
var currentProgress = 0.1
|
||||
|
||||
for (plugin in pluginsToInstall) {
|
||||
if (progressIndicator.isCanceled) break
|
||||
|
||||
progressIndicator.text = ImportSettingsBundle.message("plugin-installation.progress.downloading", plugin.name)
|
||||
|
||||
// Load and set plugin icon
|
||||
if (onIconLoaded != null) {
|
||||
try {
|
||||
val icon = PluginIconService.Companion.getInstance().loadIcon(plugin.pluginId.idString)
|
||||
if (icon != null) {
|
||||
withContext(Dispatchers.EDT + ModalityState.any().asContextElement()) {
|
||||
onIconLoaded(icon)
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (_: Exception) {
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
val downloader = PluginDownloader.createDownloader(plugin).withErrorsConsumer { problem ->
|
||||
}
|
||||
|
||||
withContext(Dispatchers.IO) {
|
||||
downloader.prepareToInstall(null)
|
||||
}
|
||||
|
||||
val appliedWithoutRestart = withContext(Dispatchers.EDT + ModalityState.any().asContextElement()) {
|
||||
downloader.installDynamically(null)
|
||||
}
|
||||
|
||||
if (!appliedWithoutRestart) {
|
||||
shouldRestart = true
|
||||
}
|
||||
}
|
||||
catch (_: Exception) {
|
||||
}
|
||||
|
||||
currentProgress += progressPerPlugin
|
||||
progressIndicator.fraction = currentProgress.coerceAtMost(0.99)
|
||||
}
|
||||
|
||||
progressIndicator.fraction = 1.0
|
||||
progressIndicator.text = null
|
||||
return shouldRestart
|
||||
}
|
||||
|
||||
suspend fun getPluginsToInstall(idsToInstall: List<PluginId>): List<PluginNode> = withContext(Dispatchers.IO) {
|
||||
val directPlugins = MarketplaceRequests.loadLastCompatiblePluginDescriptors(idsToInstall.toSet(), null, true)
|
||||
|
||||
val dependencyIds = directPlugins
|
||||
.asSequence()
|
||||
.flatMap { it.dependencies }
|
||||
.filter { !it.isOptional }
|
||||
.map { it.pluginId }
|
||||
.filter { it !in idsToInstall && !PluginManagerCore.isPluginInstalled(it) }
|
||||
.toSet()
|
||||
|
||||
val dependencyPlugins = MarketplaceRequests.loadLastCompatiblePluginDescriptors(dependencyIds, null, true)
|
||||
|
||||
(directPlugins + dependencyPlugins).distinctBy { it.pluginId }
|
||||
}
|
||||
}
|
||||
+173
@@ -0,0 +1,173 @@
|
||||
// OpenIDE Project
|
||||
// Copyright (C) 2026 “Open Development Platform” Ltd. (https://openide.ru)
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License version 3 or later as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
package com.intellij.ide.startup.importSettings.wizard.pluginChooser
|
||||
|
||||
import com.intellij.icons.AllIcons
|
||||
import com.intellij.ide.startup.importSettings.data.WizardPluginGroup
|
||||
import com.intellij.ui.components.JBLabel
|
||||
import com.intellij.ui.components.panels.VerticalLayout
|
||||
import com.intellij.util.IconUtil
|
||||
import com.intellij.util.ui.JBFont
|
||||
import com.intellij.util.ui.JBUI
|
||||
import com.intellij.util.ui.ThreeStateCheckBox
|
||||
import com.intellij.util.ui.UIUtil
|
||||
import java.awt.BorderLayout
|
||||
import java.awt.Cursor
|
||||
import java.awt.FlowLayout
|
||||
import java.awt.event.MouseAdapter
|
||||
import java.awt.event.MouseEvent
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import javax.swing.Icon
|
||||
import javax.swing.JLabel
|
||||
import javax.swing.JPanel
|
||||
|
||||
class OpenIdeWizardPluginGroupPane(
|
||||
private val group: WizardPluginGroup,
|
||||
private val coroutineScope: CoroutineScope,
|
||||
private val onSelectionChanged: () -> Unit
|
||||
) {
|
||||
private val pluginPanes = mutableListOf<OpenIdeWizardPluginPane>()
|
||||
private val groupCheckbox = ThreeStateCheckBox()
|
||||
private val counterLabel = JLabel()
|
||||
private val contentPanel = JPanel(VerticalLayout(0)).apply {
|
||||
isOpaque = false
|
||||
isVisible = false
|
||||
border = JBUI.Borders.emptyLeft(28)
|
||||
|
||||
group.plugins.forEach { plugin ->
|
||||
val pluginPane = OpenIdeWizardPluginPane(plugin, coroutineScope) {
|
||||
updateGroupCheckboxState()
|
||||
onSelectionChanged()
|
||||
}
|
||||
pluginPanes.add(pluginPane)
|
||||
add(pluginPane.pane)
|
||||
}
|
||||
}
|
||||
private val expandIcon = JLabel()
|
||||
private var isExpanded = false
|
||||
|
||||
val pane: JPanel = createPane()
|
||||
|
||||
private val selectablePanes: List<OpenIdeWizardPluginPane>
|
||||
get() = pluginPanes.filter { !it.isBundled }
|
||||
|
||||
val selectedPlugins: List<OpenIdeWizardPluginPane>
|
||||
get() = pluginPanes.filter { it.selected && !it.isBundled }
|
||||
|
||||
val selectedCount: Int
|
||||
get() = selectablePanes.count { it.selected }
|
||||
|
||||
val totalCount: Int
|
||||
get() = selectablePanes.size
|
||||
|
||||
private fun createPane(): JPanel {
|
||||
return JPanel(BorderLayout()).apply {
|
||||
isOpaque = false
|
||||
border = JBUI.Borders.empty(0, 16)
|
||||
|
||||
add(createHeader(), BorderLayout.NORTH)
|
||||
add(contentPanel, BorderLayout.CENTER)
|
||||
|
||||
updateGroupCheckboxState()
|
||||
}
|
||||
}
|
||||
|
||||
private fun createHeader(): JPanel {
|
||||
groupCheckbox.apply {
|
||||
isOpaque = false
|
||||
isThirdStateEnabled = false
|
||||
addActionListener {
|
||||
val shouldSelect = state == ThreeStateCheckBox.State.SELECTED
|
||||
selectablePanes.forEach { it.setSelected(shouldSelect) }
|
||||
updateGroupCheckboxState()
|
||||
onSelectionChanged()
|
||||
}
|
||||
}
|
||||
|
||||
counterLabel.apply {
|
||||
foreground = UIUtil.getContextHelpForeground()
|
||||
font = JBFont.label()
|
||||
}
|
||||
|
||||
expandIcon.apply {
|
||||
icon = getExpandIcon()
|
||||
cursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)
|
||||
addMouseListener(object : MouseAdapter() {
|
||||
override fun mouseClicked(e: MouseEvent) {
|
||||
toggleExpanded()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
val scaledIcon = IconUtil.scale(group.icon, null, 1.5f)
|
||||
val groupIcon = JLabel(scaledIcon).apply {
|
||||
border = JBUI.Borders.emptyRight(8)
|
||||
}
|
||||
|
||||
val groupName = JBLabel(group.name).apply {
|
||||
font = JBFont.h4()
|
||||
}
|
||||
|
||||
val headerClickArea = JPanel(FlowLayout(FlowLayout.LEFT, 0, 0)).apply {
|
||||
isOpaque = false
|
||||
add(expandIcon)
|
||||
add(groupCheckbox)
|
||||
add(groupIcon)
|
||||
add(groupName)
|
||||
add(JLabel(" ").apply { border = JBUI.Borders.emptyLeft(4) })
|
||||
add(counterLabel)
|
||||
|
||||
cursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)
|
||||
addMouseListener(object : MouseAdapter() {
|
||||
override fun mouseClicked(e: MouseEvent) {
|
||||
if (e.source !== expandIcon && e.source !== groupCheckbox) {
|
||||
toggleExpanded()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return JPanel(BorderLayout()).apply {
|
||||
isOpaque = false
|
||||
border = JBUI.Borders.empty(4, 0)
|
||||
add(headerClickArea, BorderLayout.CENTER)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateGroupCheckboxState() {
|
||||
val selectable = selectablePanes
|
||||
val selectedCount = selectable.count { it.selected }
|
||||
groupCheckbox.state = when (selectedCount) {
|
||||
0 -> ThreeStateCheckBox.State.NOT_SELECTED
|
||||
selectable.size -> ThreeStateCheckBox.State.SELECTED
|
||||
else -> ThreeStateCheckBox.State.DONT_CARE
|
||||
}
|
||||
counterLabel.text = "($selectedCount/${selectable.size})"
|
||||
}
|
||||
|
||||
private fun toggleExpanded() {
|
||||
isExpanded = !isExpanded
|
||||
contentPanel.isVisible = isExpanded
|
||||
expandIcon.icon = getExpandIcon()
|
||||
}
|
||||
|
||||
private fun getExpandIcon(): Icon {
|
||||
return if (isExpanded) AllIcons.General.ArrowDown else AllIcons.General.ArrowRight
|
||||
}
|
||||
|
||||
fun setAllSelected(selected: Boolean) {
|
||||
selectablePanes.forEach { it.setSelected(selected) }
|
||||
updateGroupCheckboxState()
|
||||
}
|
||||
}
|
||||
+173
@@ -0,0 +1,173 @@
|
||||
// OpenIDE Project
|
||||
// Copyright (C) 2026 “Open Development Platform” Ltd. (https://openide.ru)
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License version 3 or later as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
package com.intellij.ide.startup.importSettings.wizard.pluginChooser
|
||||
|
||||
import com.intellij.ide.startup.importSettings.ImportSettingsBundle
|
||||
import com.intellij.ide.startup.importSettings.data.WizardPlugin
|
||||
import com.intellij.ide.startup.importSettings.openide.service.PluginIconService
|
||||
import com.intellij.ui.components.JBCheckBox
|
||||
import com.intellij.ui.dsl.builder.HyperlinkEventAction
|
||||
import com.intellij.ui.dsl.builder.MAX_LINE_LENGTH_WORD_WRAP
|
||||
import com.intellij.ui.dsl.builder.components.DslLabel
|
||||
import com.intellij.ui.dsl.builder.components.DslLabelType
|
||||
import com.intellij.util.IconUtil
|
||||
import com.intellij.util.ui.JBUI
|
||||
import com.intellij.util.ui.UIUtil
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import java.awt.GridBagConstraints
|
||||
import java.awt.GridBagLayout
|
||||
import javax.swing.JEditorPane
|
||||
import javax.swing.JLabel
|
||||
import javax.swing.JPanel
|
||||
import javax.swing.SwingUtilities
|
||||
|
||||
class OpenIdeWizardPluginPane(val plugin: WizardPlugin, private val coroutineScope: CoroutineScope, changeHandler: () -> Unit) {
|
||||
|
||||
private var checkBox = JBCheckBox().apply {
|
||||
isOpaque = false
|
||||
}
|
||||
|
||||
val selected: Boolean
|
||||
get() = checkBox.isSelected
|
||||
|
||||
fun setSelected(value: Boolean) {
|
||||
checkBox.isSelected = value
|
||||
}
|
||||
|
||||
fun setEnabled(value: Boolean) {
|
||||
checkBox.isEnabled = value
|
||||
pane.isEnabled = value
|
||||
nameLabel.isEnabled = value
|
||||
}
|
||||
|
||||
private val iconLabel = JLabel(IconUtil.resizeSquared(plugin.icon, 24))
|
||||
private val nameLabel = createLabel()
|
||||
private val bundledLabel = JLabel(ImportSettingsBundle.message("plugins.page.list.item.bundled")).apply {
|
||||
foreground = UIUtil.getContextHelpForeground()
|
||||
border = JBUI.Borders.emptyRight(10)
|
||||
}
|
||||
|
||||
val pane = JPanel(GridBagLayout()).apply {
|
||||
val c = GridBagConstraints()
|
||||
|
||||
plugin.description?.let {
|
||||
c.gridx = 0
|
||||
c.gridy = 0
|
||||
c.weightx = 0.0
|
||||
c.anchor = GridBagConstraints.CENTER
|
||||
add(checkBox, c)
|
||||
|
||||
c.gridx = 1
|
||||
c.anchor = GridBagConstraints.CENTER
|
||||
add(iconLabel.apply {
|
||||
border = JBUI.Borders.empty(0, 10)
|
||||
}, c)
|
||||
|
||||
c.gridx = 2
|
||||
c.weightx = 1.0
|
||||
c.fill = GridBagConstraints.HORIZONTAL
|
||||
add(JPanel(GridBagLayout()).apply {
|
||||
isOpaque = false
|
||||
val inner = GridBagConstraints()
|
||||
inner.gridx = 0
|
||||
inner.gridy = 0
|
||||
inner.weightx = 1.0
|
||||
inner.fill = GridBagConstraints.HORIZONTAL
|
||||
inner.anchor = GridBagConstraints.WEST
|
||||
add(nameLabel.apply {
|
||||
text = plugin.name
|
||||
}, inner)
|
||||
|
||||
inner.gridy = 1
|
||||
add(createLabel().apply {
|
||||
text = plugin.description
|
||||
foreground = UIUtil.getLabelDisabledForeground()
|
||||
}, inner)
|
||||
}, c)
|
||||
|
||||
if (plugin.bundled) {
|
||||
c.gridx = 3
|
||||
c.weightx = 0.0
|
||||
c.fill = GridBagConstraints.NONE
|
||||
c.anchor = GridBagConstraints.EAST
|
||||
add(bundledLabel, c)
|
||||
}
|
||||
|
||||
} ?: run {
|
||||
c.gridx = 0
|
||||
c.gridy = 0
|
||||
c.weightx = 0.0
|
||||
add(checkBox, c)
|
||||
c.gridx = 1
|
||||
c.gridy = 0
|
||||
add(iconLabel.apply {
|
||||
border = JBUI.Borders.empty(0, 10)
|
||||
}, c)
|
||||
c.gridx = 2
|
||||
c.gridy = 0
|
||||
c.weightx = 1.0
|
||||
c.fill = GridBagConstraints.HORIZONTAL
|
||||
add(nameLabel.apply {
|
||||
text = plugin.name
|
||||
}, c)
|
||||
|
||||
if (plugin.bundled) {
|
||||
c.gridx = 3
|
||||
c.weightx = 0.0
|
||||
c.fill = GridBagConstraints.NONE
|
||||
c.anchor = GridBagConstraints.EAST
|
||||
add(bundledLabel, c)
|
||||
}
|
||||
}
|
||||
}.apply {
|
||||
isOpaque = false
|
||||
border = JBUI.Borders.empty(8, 20)
|
||||
}
|
||||
|
||||
val isBundled: Boolean = plugin.bundled
|
||||
|
||||
init {
|
||||
loadIconAsync()
|
||||
|
||||
if (isBundled) {
|
||||
checkBox.isSelected = true
|
||||
setEnabled(false)
|
||||
}
|
||||
|
||||
checkBox.addItemListener {
|
||||
changeHandler()
|
||||
}
|
||||
}
|
||||
|
||||
private fun createLabel(): JEditorPane {
|
||||
val dslLabel = DslLabel(DslLabelType.LABEL)
|
||||
dslLabel.action = HyperlinkEventAction.HTML_HYPERLINK_INSTANCE
|
||||
dslLabel.maxLineLength = MAX_LINE_LENGTH_WORD_WRAP
|
||||
|
||||
return dslLabel
|
||||
}
|
||||
|
||||
private fun loadIconAsync() {
|
||||
coroutineScope.launch {
|
||||
val icon = PluginIconService.getInstance().loadIcon(plugin.id)
|
||||
if (icon != null) {
|
||||
SwingUtilities.invokeLater {
|
||||
iconLabel.icon = IconUtil.resizeSquared(icon, 24)
|
||||
pane.repaint()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+37
-17
@@ -1,4 +1,7 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
//
|
||||
// Modified by Artyom Orlov at 2026 as part of the OpenIDE project(https://openide.ru).
|
||||
// Any modifications are available on the same license terms as the original source code.
|
||||
package com.intellij.ide.startup.importSettings.wizard.pluginChooser
|
||||
|
||||
import com.intellij.ide.startup.importSettings.ImportSettingsBundle
|
||||
@@ -8,6 +11,7 @@ import com.intellij.ide.startup.importSettings.chooser.ui.ScrollSnapToFocused
|
||||
import com.intellij.ide.startup.importSettings.chooser.ui.UiUtils
|
||||
import com.intellij.ide.startup.importSettings.chooser.ui.WizardPagePane
|
||||
import com.intellij.ide.startup.importSettings.data.PluginService
|
||||
import com.intellij.ide.startup.importSettings.data.WizardPluginGroup
|
||||
import com.intellij.openapi.util.NlsActions.ActionText
|
||||
import com.intellij.openapi.util.SystemInfo
|
||||
import com.intellij.platform.ide.bootstrap.StartupWizardStage
|
||||
@@ -29,14 +33,14 @@ import javax.swing.SwingUtilities
|
||||
internal class WizardPluginsPage(
|
||||
val controller: BaseController,
|
||||
private val pluginService: PluginService,
|
||||
goBackAction: () -> Unit,
|
||||
goBackAction: (() -> Unit)?,
|
||||
goForwardAction: (List<String>) -> Unit,
|
||||
private val continueButtonTextOverride: @ActionText String?
|
||||
) : OnboardingPage {
|
||||
|
||||
override val stage: StartupWizardStage = StartupWizardStage.WizardPluginPage
|
||||
|
||||
private val pluginPanes = mutableListOf<WizardPluginPane>()
|
||||
private val groupPanes = mutableListOf<OpenIdeWizardPluginGroupPane>()
|
||||
|
||||
private val contentPage: JComponent
|
||||
|
||||
@@ -44,14 +48,20 @@ internal class WizardPluginsPage(
|
||||
border = JBUI.Borders.emptyLeft(26)
|
||||
foreground = UIUtil.getContextHelpForeground()
|
||||
}
|
||||
|
||||
override fun confirmExit(parentComponent: Component?): Boolean = true
|
||||
|
||||
private fun getSelected(): List<WizardPluginPane> {
|
||||
return pluginPanes.filter { it.selected }.toList()
|
||||
private fun getSelected(): List<OpenIdeWizardPluginPane> {
|
||||
return groupPanes.flatMap { it.selectedPlugins }
|
||||
}
|
||||
|
||||
private fun getSelectedCount(): Int {
|
||||
return groupPanes.sumOf { it.selectedCount }
|
||||
}
|
||||
|
||||
private fun changeHandler() {
|
||||
val selected = getSelected()
|
||||
when(selected.size) {
|
||||
val selectedSize = getSelected().size
|
||||
when(selectedSize) {
|
||||
0 -> {
|
||||
leftLabel.text = ImportSettingsBundle.message("plugins.page.choose.counter.no")
|
||||
continueAction.text = continueButtonTextOverride ?: ImportSettingsBundle.message("plugins.page.ok.button.continue.without")
|
||||
@@ -61,7 +71,7 @@ internal class WizardPluginsPage(
|
||||
continueAction.text = continueButtonTextOverride ?: ImportSettingsBundle.message("plugins.page.ok.button.install")
|
||||
}
|
||||
else -> {
|
||||
leftLabel.text = ImportSettingsBundle.message("plugins.page.choose.counter.multiple", selected.size)
|
||||
leftLabel.text = ImportSettingsBundle.message("plugins.page.choose.counter.multiple", selectedSize)
|
||||
continueAction.text = continueButtonTextOverride ?: ImportSettingsBundle.message("plugins.page.ok.button.install")
|
||||
}
|
||||
}
|
||||
@@ -74,14 +84,14 @@ internal class WizardPluginsPage(
|
||||
border = JBUI.Borders.empty(18, 20)
|
||||
})
|
||||
|
||||
val plugins = pluginService.plugins
|
||||
val pluginGroups: List<WizardPluginGroup> = pluginService.pluginGroups
|
||||
|
||||
val listPane = JPanel(VerticalLayout(JBUI.scale(4))).apply {
|
||||
isOpaque = false
|
||||
plugins.forEach {
|
||||
val pl = WizardPluginPane(it) { changeHandler() }
|
||||
pluginPanes.add(pl)
|
||||
add(pl.pane)
|
||||
pluginGroups.forEach { group: WizardPluginGroup ->
|
||||
val groupPane = OpenIdeWizardPluginGroupPane(group, controller.lifetime.coroutineScope) { changeHandler() }
|
||||
groupPanes.add(groupPane)
|
||||
add(groupPane.pane)
|
||||
}
|
||||
border = JBUI.Borders.empty(10, 0)
|
||||
}
|
||||
@@ -102,7 +112,7 @@ internal class WizardPluginsPage(
|
||||
})
|
||||
}
|
||||
|
||||
private val backAction = controller.createButton(ImportSettingsBundle.message("import.settings.back"), goBackAction)
|
||||
private val backAction = controller.createButton(ImportSettingsBundle.message("import.settings.back.ru"), goBackAction ?: {})
|
||||
|
||||
private val continueAction = controller.createDefaultButton(continueButtonTextOverride ?: ImportSettingsBundle.message("plugins.page.ok.button.continue.without")) {
|
||||
val ids = getSelected().map { it.plugin.id }.toList()
|
||||
@@ -110,10 +120,20 @@ internal class WizardPluginsPage(
|
||||
}
|
||||
|
||||
init {
|
||||
val buttons: List<JButton> = if (SystemInfo.isMac) {
|
||||
listOf(backAction, continueAction)
|
||||
val buttons: List<JButton> = buildList {
|
||||
if (SystemInfo.isMac) {
|
||||
if (goBackAction != null) {
|
||||
add(backAction)
|
||||
}
|
||||
add(continueAction)
|
||||
}
|
||||
else {
|
||||
add(continueAction)
|
||||
if (goBackAction != null) {
|
||||
add(backAction)
|
||||
}
|
||||
}
|
||||
}
|
||||
else listOf(continueAction, backAction)
|
||||
|
||||
|
||||
contentPage = WizardPagePane(pane, buttons, leftLabel)
|
||||
|
||||
Reference in New Issue
Block a user