diff --git a/README.md b/README.md index 78bbb23..3ac245a 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,6 @@ # Reset Your IDE Eval Information 1. Download and install plugin from [Release Page](https://gitee.com/pengzhile/ide-eval-resetter/releases). -2. Click `Help` or `Get Help` -> `Reset IDE Eval` menu. +2. Click `Help` or `Get Help` -> `Eval Reset` menu. 3. Restart your IDE. 4. Now you have another 30 days eval time :) - ------------------------------------------- - -### Alternative - -* Or run script in the [reset_eval](https://gitee.com/pengzhile/ide-eval-resetter/tree/master/reset_eval) folder directly. diff --git a/build.gradle b/build.gradle index 34bef97..d292e73 100644 --- a/build.gradle +++ b/build.gradle @@ -1,10 +1,13 @@ plugins { id 'java' - id 'org.jetbrains.intellij' version '0.4.21' + id 'org.jetbrains.intellij' version '0.5.0' } group 'io.zhile.research.intellij' -version '1.0.5' +version '2.0.0' + +sourceCompatibility = 1.7 +targetCompatibility = 1.7 repositories { mavenCentral() @@ -14,17 +17,21 @@ dependencies { testCompile group: 'junit', name: 'junit', version: '4.12' } +buildPlugin { + buildSearchableOptions.enabled = false +} + // See https://github.com/JetBrains/gradle-intellij-plugin/ intellij { -// localPath "${System.properties['user.home']}/Applications/IntelliJ IDEA.app" -// alternativeIdePath localPath - version "2020.2.3" type "IU" } patchPluginXml { changeNotes """ + release v2.0.0 + 1. add ui + 2. more stable and accurate release v1.0.5 1. update for 2020.2.x release v1.0.4 @@ -34,6 +41,6 @@ patchPluginXml { release v1.0.2 1. compatibility fix""" - sinceBuild "162" + sinceBuild "145.258" untilBuild null } \ No newline at end of file diff --git a/reset_eval/reset_jetbrains_eval_mac_linux.sh b/reset_eval/reset_jetbrains_eval_mac_linux.sh deleted file mode 100755 index d6d8b58..0000000 --- a/reset_eval/reset_jetbrains_eval_mac_linux.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash -# reset jetbrains ide evals v1.0.5 - -OS_NAME=$(uname -s) -JB_PRODUCTS="IntelliJIdea CLion PhpStorm GoLand PyCharm WebStorm Rider DataGrip RubyMine AppCode" - -if [ "$OS_NAME" == "Darwin" ]; then - echo 'macOS:' - - for PRD in $JB_PRODUCTS; do - rm -rf ~/Library/Preferences/"${PRD}"*/eval - sed -i '' '/name="evlsprt.*"/d' ~/Library/Preferences/"${PRD}"*/options/other.xml >/dev/null 2>&1 - rm -rf ~/Library/Application\ Support/JetBrains/"${PRD}"*/eval - sed -i '' '/name="evlsprt.*"/d' ~/Library/Application\ Support/JetBrains/"${PRD}"*/options/other.xml >/dev/null 2>&1 - done - - rm -rf ~/Library/Preferences/jetbrains.*.*.plist - plutil -remove "/.JetBrains\.UserIdOnMachine" ~/Library/Preferences/com.apple.java.util.prefs.plist >/dev/null - plutil -remove "/.jetbrains/.user_id_on_machine" ~/Library/Preferences/com.apple.java.util.prefs.plist >/dev/null - plutil -remove "/.jetbrains/.device_id" ~/Library/Preferences/com.apple.java.util.prefs.plist >/dev/null -elif [ "$OS_NAME" == "Linux" ]; then - echo 'Linux:' - - for PRD in $JB_PRODUCTS; do - rm -rf ~/."${PRD}"*/config/eval - sed -i '/name="evlsprt.*"/d' ~/."${PRD}"*/config/options/other.xml >/dev/null 2>&1 - rm -rf ~/.config/JetBrains/"${PRD}"*/eval - sed -i '/name="evlsprt.*"/d' ~/.config/JetBrains/"${PRD}"*/options/other.xml >/dev/null 2>&1 - done - - sed -i '/key="JetBrains\.UserIdOnMachine"/d' ~/.java/.userPrefs/prefs.xml - sed -i '/key="device_id"/d' ~/.java/.userPrefs/jetbrains/prefs.xml - sed -i '/key="user_id_on_machine"/d' ~/.java/.userPrefs/jetbrains/prefs.xml - find ~/.java/.userPrefs/jetbrains/ -name "evlsprt*" -type d -exec rm -rf {} \; >/dev/null 2>&1 -else - echo 'unsupport' - exit -fi - -echo 'done.' diff --git a/reset_eval/reset_jetbrains_eval_windows.vbs b/reset_eval/reset_jetbrains_eval_windows.vbs deleted file mode 100644 index b743b5a..0000000 --- a/reset_eval/reset_jetbrains_eval_windows.vbs +++ /dev/null @@ -1,62 +0,0 @@ -' reset jetbrains ide evals v1.0.5 -Set oShell = CreateObject("WScript.Shell") -Set oFS = CreateObject("Scripting.FileSystemObject") -sHomeFolder = oShell.ExpandEnvironmentStrings("%USERPROFILE%") -sJBDataFolder = oShell.ExpandEnvironmentStrings("%APPDATA%") + "\JetBrains" - -Set re = New RegExp -re.Global = True -re.IgnoreCase = True -re.Pattern = "\.?(IntelliJIdea|GoLand|CLion|PyCharm|DataGrip|RubyMine|AppCode|PhpStorm|WebStorm|Rider).*" - -Sub removeEval(ByVal file, ByVal sEvalPath) - bMatch = re.Test(file.Name) - If Not bMatch Then - Exit Sub - End If - - If oFS.FolderExists(sEvalPath) Then - oFS.DeleteFolder sEvalPath, True - End If - - content = "" - otherFile = oFS.GetParentFolderName(sEvalPath) + "\options\other.xml" - If oFS.FileExists(otherFile) Then - Set txtStream = oFS.OpenTextFile(otherFile, 1, False) - Do While Not txtStream.AtEndOfStream - line = txtStream.ReadLine - If InStr(line, "name=""evlsprt") = 0 Then - content = content + line + vbLf - End If - Loop - txtStream.Close - - Set txtStream = oFS.OpenTextFile(otherFile, 2, False) - txtStream.Write content - txtStream.Close - End If -End Sub - -If oFS.FolderExists(sHomeFolder) Then - For Each oFile In oFS.GetFolder(sHomeFolder).SubFolders - removeEval oFile, sHomeFolder + "\" + oFile.Name + "\config\eval" - Next -End If - -If oFS.FolderExists(sJBDataFolder) Then - For Each oFile In oFS.GetFolder(sJBDataFolder).SubFolders - removeEval oFile, sJBDataFolder + "\" + oFile.Name + "\eval" - Next -End If - -On Error Resume Next -oShell.RegDelete "HKEY_CURRENT_USER\Software\JavaSoft\Prefs\/Jet/Brains./User/Id/On/Machine" -oShell.RegDelete "HKEY_CURRENT_USER\Software\JavaSoft\Prefs\jetbrains\device_id" -oShell.RegDelete "HKEY_CURRENT_USER\Software\JavaSoft\Prefs\jetbrains\user_id_on_machine" -oShell.RegDelete "HKEY_CURRENT_USER\Software\JavaSoft\Prefs\jetbrains\" -oFs.DeleteFile sJBDataFolder + "\bl" -oFs.DeleteFile sJBDataFolder + "\crl" -oFs.DeleteFile sJBDataFolder + "\PermanentUserId" -oFs.DeleteFile sJBDataFolder + "\PermanentDeviceId" - -MsgBox "done" diff --git a/src/main/java/io/zhile/research/intellij/MainComponent.java b/src/main/java/io/zhile/research/intellij/MainComponent.java deleted file mode 100644 index ab22119..0000000 --- a/src/main/java/io/zhile/research/intellij/MainComponent.java +++ /dev/null @@ -1,69 +0,0 @@ -package io.zhile.research.intellij; - -import com.intellij.notification.Notification; -import com.intellij.notification.NotificationType; -import com.intellij.openapi.components.ApplicationComponent; -import io.zhile.research.intellij.action.ResetAction; -import io.zhile.research.intellij.helper.Constants; -import io.zhile.research.intellij.helper.NotificationHelper; -import org.jetbrains.annotations.NotNull; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Timer; -import java.util.TimerTask; -import java.util.prefs.Preferences; - -public class MainComponent implements ApplicationComponent { - private static final long RESET_PERIOD = 2160000000L; // 25 days - - public void initComponent() { - Preferences prefs = Preferences.userRoot().node(Constants.PLUGIN_NAME); - long lastResetTime = prefs.getLong(Constants.PRODUCT_NAME + Constants.PRODUCT_HASH, 0L); - - new Timer().schedule(new TimerTask() { - @Override - public void run() { - if (lastResetTime > 0) { - Date date = new Date(lastResetTime); - DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - NotificationHelper.showInfo(null, "The last reset time: " + format.format(date)); - } - - new ResetTimerTask(lastResetTime).run(); - } - }, 3000); - } - - protected static class ResetTimerTask extends TimerTask { - private final long lastResetTime; - - public ResetTimerTask(long lastResetTime) { - this.lastResetTime = lastResetTime; - } - - @Override - public void run() { - if (System.currentTimeMillis() - lastResetTime > RESET_PERIOD) { - String message = "It has been a long time since the last reset!\nWould you like to reset it again?"; - Notification notification = NotificationHelper.NOTIFICATION_GROUP.createNotification(Constants.PLUGIN_NAME, null, message, NotificationType.INFORMATION); - notification.addAction(new ResetAction()); - notification.notify(null); - } - - new Timer().schedule(new ResetTimerTask(lastResetTime), 3600000); // 60 min - } - } - - @Override - public void disposeComponent() { - // for compatibility - } - - @Override - public @NotNull - String getComponentName() { - return getClass().getName(); // for compatibility - } -} diff --git a/src/main/java/io/zhile/research/intellij/action/ResetAction.java b/src/main/java/io/zhile/research/intellij/action/ResetAction.java deleted file mode 100644 index c37757f..0000000 --- a/src/main/java/io/zhile/research/intellij/action/ResetAction.java +++ /dev/null @@ -1,146 +0,0 @@ -package io.zhile.research.intellij.action; - -import com.intellij.icons.AllIcons; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.PathManager; -import com.intellij.openapi.application.ex.ApplicationInfoEx; -import com.intellij.openapi.application.impl.ApplicationInfoImpl; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.SystemInfo; -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.util.text.StringUtil; -import io.zhile.research.intellij.helper.Constants; -import io.zhile.research.intellij.helper.NotificationHelper; -import org.jetbrains.annotations.NotNull; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Scanner; -import java.util.prefs.BackingStoreException; -import java.util.prefs.Preferences; - -public class ResetAction extends AnAction { - private static final String OLD_MACHINE_ID_KEY = "JetBrains.UserIdOnMachine"; - private static final String NEW_MACHINE_ID_KEY = "user_id_on_machine"; - private static final String DEVICE_ID_KEY = "device_id"; - private static final String DEFAULT_COMPANY_NAME = "jetbrains"; - - public ResetAction() { - super("Reset " + Constants.PRODUCT_NAME + "'s Eval", "Reset my IDE eval information", AllIcons.General.Reset); - } - - @Override - public void actionPerformed(@NotNull AnActionEvent anActionEvent) { - Project project = anActionEvent.getProject(); - File evalFile = getEvalFile(); - if (evalFile.exists()) { - if (!FileUtil.delete(evalFile)) { - NotificationHelper.showError(project, "Remove eval folder failed!"); - return; - } - } - - File optionsFile = getOptionsFile(); - if (optionsFile.exists()) { - try (Scanner scanner = new Scanner(optionsFile)) { - StringBuilder sbContent = new StringBuilder(); - while (scanner.hasNextLine()) { - String line = scanner.nextLine(); - if (!line.contains("name=\"evlsprt")) { - sbContent.append(line).append("\n"); - } - } - - Files.write(Paths.get(optionsFile.toURI()), sbContent.toString().getBytes()); - } catch (IOException e) { - NotificationHelper.showError(project, e.getMessage()); - return; - } - } - - ApplicationInfoEx appInfo = ApplicationInfoImpl.getShadowInstance(); - - String companyName = appInfo.getShortCompanyName(); - String node = StringUtil.isEmptyOrSpaces(companyName) ? DEFAULT_COMPANY_NAME : companyName.toLowerCase(); - - Preferences prefsRoot = Preferences.userRoot(); - Preferences prefs = prefsRoot.node(node); - - prefsRoot.remove(OLD_MACHINE_ID_KEY); - prefs.remove(NEW_MACHINE_ID_KEY); - prefs.remove(DEVICE_ID_KEY); - - try { - removeEvalNode(prefs); - } catch (BackingStoreException e) { - NotificationHelper.showError(project, "Remove evlsprt failed!"); - return; - } - - Preferences.userRoot().node(Constants.PLUGIN_NAME).put(Constants.PRODUCT_NAME + Constants.PRODUCT_HASH, Long.toString(System.currentTimeMillis())); - - if (appInfo.isVendorJetBrains() && SystemInfo.isWindows) { - String[] names = new String[]{"PermanentUserId", "PermanentDeviceId"}; - for (String name : names) { - if (deleteSharedFile(name)) { - continue; - } - - NotificationHelper.showError(project, "Remove " + name + " file failed!"); - return; - } - } - - NotificationHelper.showInfo(project, "Reset successfully!\nPlease restart your IDE and enjoy it!"); - ApplicationManager.getApplication().invokeLater(() -> ApplicationManager.getApplication().restart()); - } - - @Override - public boolean isDumbAware() { - return false; - } - - protected boolean deleteSharedFile(String fileName) { - String appData = System.getenv("APPDATA"); - if (appData == null) { - return false; - } - - File dir = Paths.get(appData, "JetBrains", fileName).toFile(); - - return !dir.exists() || dir.delete(); - } - - protected File getEvalFile() { - String configPath = PathManager.getConfigPath(); - - return new File(configPath, "eval"); - } - - protected File getOptionsFile() { - String configPath = PathManager.getConfigPath(); - - return new File(new File(configPath, "options"), "other.xml"); - } - - protected void removeEvalNode(Preferences prefs) throws BackingStoreException { - String[] keys = prefs.childrenNames(); - if (keys.length == 0) { - return; - } - - for (String key : keys) { - Preferences node = prefs.node(key); - if (key.startsWith("evlsprt")) { - node.removeNode(); - continue; - } - - removeEvalNode(node); - } - } -} diff --git a/src/main/java/io/zhile/research/intellij/ier/action/ResetAction.java b/src/main/java/io/zhile/research/intellij/ier/action/ResetAction.java new file mode 100644 index 0000000..c87214a --- /dev/null +++ b/src/main/java/io/zhile/research/intellij/ier/action/ResetAction.java @@ -0,0 +1,29 @@ +package io.zhile.research.intellij.ier.action; + +import com.intellij.icons.AllIcons; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.wm.ToolWindowManager; +import io.zhile.research.intellij.ier.component.ResetTimer; +import io.zhile.research.intellij.ier.ui.dialog.MainDialog; +import org.jetbrains.annotations.NotNull; + +public class ResetAction extends AnAction implements DumbAware { + public ResetAction() { + super("Eval Reset", "Reset my IDE eval information", AllIcons.General.Reset); + new ResetTimer().start(this); + } + + @Override + public void actionPerformed(@NotNull AnActionEvent anActionEvent) { + Project project = anActionEvent.getProject(); + if (project == null) { + MainDialog mainDialog = new MainDialog(); + mainDialog.show(); + } else { + ToolWindowManager.getInstance(project).getToolWindow("Eval Reset").show(null); + } + } +} diff --git a/src/main/java/io/zhile/research/intellij/ier/common/RecordItem.java b/src/main/java/io/zhile/research/intellij/ier/common/RecordItem.java new file mode 100644 index 0000000..ff00df4 --- /dev/null +++ b/src/main/java/io/zhile/research/intellij/ier/common/RecordItem.java @@ -0,0 +1,29 @@ +package io.zhile.research.intellij.ier.common; + +public class RecordItem { + private final RecordType type; + private final String key; + private final String value; + + public RecordItem(RecordType type, String key, String value) { + this.type = type; + this.key = key; + this.value = value; + } + + public RecordItem(RecordType type, String key) { + this(type, key, null); + } + + public RecordType getType() { + return type; + } + + public String getKey() { + return key; + } + + public String getValue() { + return value; + } +} diff --git a/src/main/java/io/zhile/research/intellij/ier/common/RecordType.java b/src/main/java/io/zhile/research/intellij/ier/common/RecordType.java new file mode 100644 index 0000000..6bb668a --- /dev/null +++ b/src/main/java/io/zhile/research/intellij/ier/common/RecordType.java @@ -0,0 +1,17 @@ +package io.zhile.research.intellij.ier.common; + +public enum RecordType { + FILE("FILE"), + PREFERENCE("PREFERENCE"), + PROPERTY("PROPERTY"); + + private final String value; + + RecordType(String value) { + this.value = value; + } + + public String getValue() { + return value; + } +} diff --git a/src/main/java/io/zhile/research/intellij/ier/common/Resetter.java b/src/main/java/io/zhile/research/intellij/ier/common/Resetter.java new file mode 100644 index 0000000..6f5e9b1 --- /dev/null +++ b/src/main/java/io/zhile/research/intellij/ier/common/Resetter.java @@ -0,0 +1,182 @@ +package io.zhile.research.intellij.ier.common; + +import com.intellij.ide.Prefs; +import com.intellij.ide.plugins.IdeaPluginDescriptor; +import com.intellij.ide.plugins.PluginManager; +import com.intellij.ide.util.PropertiesComponent; +import com.intellij.ide.util.PropertiesComponentImpl; +import com.intellij.openapi.application.PathManager; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.io.FileUtil; +import io.zhile.research.intellij.ier.helper.Constants; +import io.zhile.research.intellij.ier.helper.NotificationHelper; +import io.zhile.research.intellij.ier.helper.Reflection; +import org.jdom.Attribute; +import org.jdom.Element; + +import java.io.File; +import java.lang.reflect.Method; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.prefs.BackingStoreException; +import java.util.prefs.Preferences; + +public class Resetter { + private static final String DEFAULT_VENDOR = "jetbrains"; + private static final String OLD_MACHINE_ID_KEY = "JetBrains.UserIdOnMachine"; + private static final String NEW_MACHINE_ID_KEY = DEFAULT_VENDOR + ".user_id_on_machine"; + private static final String DEVICE_ID_KEY = DEFAULT_VENDOR + ".device_id"; + private static final String IDE_EVAL_PREFIX = DEFAULT_VENDOR + "/" + Constants.IDE_NAME_LOWER + "/" + Constants.IDE_HASH; + private static final String EVAL_KEY = "evlsprt"; + + private static final PropertiesComponentImpl PROPS = (PropertiesComponentImpl) PropertiesComponent.getInstance(); + + public static List getEvalRecords() { + List list = new ArrayList<>(); + + File evalDir = getEvalDir(); + if (evalDir.exists()) { + for (File file : evalDir.listFiles()) { + list.add(new RecordItem(RecordType.FILE, file.getAbsolutePath())); + } + } + + Element state = PROPS.getState(); + if (state != null) { + Attribute attrName, attrValue; + String key, value; + for (Element element : state.getChildren()) { + if (!element.getName().equals("property")) { + continue; + } + + attrName = element.getAttribute("name"); + attrValue = element.getAttribute("value"); + if (attrName == null || attrValue == null) { + continue; + } + + key = attrName.getValue(); + value = attrValue.getValue(); + if (key.startsWith(EVAL_KEY)) { + list.add(new RecordItem(RecordType.PROPERTY, key, value)); + } + } + } + + RecordItem[] prefsValue = new RecordItem[]{ + new RecordItem(RecordType.PREFERENCE, OLD_MACHINE_ID_KEY, Preferences.userRoot().get(OLD_MACHINE_ID_KEY, null)), + new RecordItem(RecordType.PREFERENCE, NEW_MACHINE_ID_KEY, Prefs.get(NEW_MACHINE_ID_KEY, null)), + new RecordItem(RecordType.PREFERENCE, DEVICE_ID_KEY, Prefs.get(DEVICE_ID_KEY, null)), + }; + for (RecordItem item : prefsValue) { + if (null == item.getValue()) { + continue; + } + list.add(item); + } + + try { + List prefsList = new ArrayList<>(); + getAllPrefsKeys(Preferences.userRoot().node(IDE_EVAL_PREFIX), prefsList); + + Method methodGetProductCode = Reflection.getMethod(IdeaPluginDescriptor.class, "getProductCode"); + Method methodGetReleaseVersion = Reflection.getMethod(IdeaPluginDescriptor.class, "getReleaseVersion"); + if (null != methodGetProductCode && null != methodGetReleaseVersion) { + for (IdeaPluginDescriptor descriptor : PluginManager.getPlugins()) { + String productCode = (String) methodGetProductCode.invoke(descriptor); + if (null == productCode || productCode.isEmpty()) { + continue; + } + + int releaseVersion = (int) methodGetReleaseVersion.invoke(descriptor); + getAllPrefsKeys(Preferences.userRoot().node(DEFAULT_VENDOR + "/" + productCode.toLowerCase() + "/" + releaseVersion), prefsList); + } + } + + for (String key : prefsList) { + if (!key.contains(EVAL_KEY)) { + continue; + } + + if (key.startsWith("/")) { + key = key.substring(1).replace('/', '.'); + } + list.add(new RecordItem(RecordType.PREFERENCE, key, Prefs.get(key, null))); + } + } catch (Exception e) { + NotificationHelper.showError(null, "List eval preferences failed!"); + } + + if (SystemInfo.isWindows) { + String[] names = new String[]{"PermanentUserId", "PermanentDeviceId"}; + for (String name : names) { + File file = getSharedFile(name); + + if (null != file && file.exists()) { + list.add(new RecordItem(RecordType.FILE, file.getAbsolutePath())); + } + } + } + + return list; + } + + public static void reset(List recordItems) { + for (RecordItem item : recordItems) { + reset(item); + } + } + + public static void reset(RecordItem recordItem) { + RecordType type = recordItem.getType(); + String key = recordItem.getKey(); + switch (type) { + case FILE: + if (!FileUtil.delete(new File(key))) { + NotificationHelper.showError(null, "Remove " + type.getValue() + " failed: " + key); + } + break; + case PREFERENCE: + if (OLD_MACHINE_ID_KEY.equals(key)) { + Preferences.userRoot().remove(key); + } else { + Prefs.remove(key); + } + break; + case PROPERTY: + PROPS.unsetValue(key); + break; + } + } + + protected static File getSharedFile(String fileName) { + String appData = System.getenv("APPDATA"); + if (appData == null) { + return null; + } + + return Paths.get(appData, "JetBrains", fileName).toFile(); + } + + protected static File getEvalDir() { + String configPath = PathManager.getConfigPath(); + + return new File(configPath, "eval"); + } + + protected static void getAllPrefsKeys(Preferences prefs, List list) throws BackingStoreException { + String[] childrenNames = prefs.childrenNames(); + if (childrenNames.length == 0) { + for (String key : prefs.keys()) { + list.add(prefs.absolutePath() + "/" + key); + } + return; + } + + for (String childName : childrenNames) { + getAllPrefsKeys(prefs.node(childName), list); + } + } +} diff --git a/src/main/java/io/zhile/research/intellij/ier/component/ResetTimer.java b/src/main/java/io/zhile/research/intellij/ier/component/ResetTimer.java new file mode 100644 index 0000000..b59f319 --- /dev/null +++ b/src/main/java/io/zhile/research/intellij/ier/component/ResetTimer.java @@ -0,0 +1,62 @@ +package io.zhile.research.intellij.ier.component; + +import com.intellij.ide.Prefs; +import com.intellij.notification.Notification; +import com.intellij.notification.NotificationType; +import com.intellij.openapi.actionSystem.AnAction; +import io.zhile.research.intellij.ier.helper.Constants; +import io.zhile.research.intellij.ier.helper.DateTime; +import io.zhile.research.intellij.ier.helper.NotificationHelper; + +import java.util.Timer; +import java.util.TimerTask; + +public class ResetTimer { + private static final long RESET_PERIOD = 2160000000L; // 25 days + private static final String RESET_KEY = "Ide-Eval-Reset." + Constants.IDE_NAME_LOWER + "." + Constants.IDE_HASH; + + public static long getLastResetTime() { + return Prefs.getLong(RESET_KEY, 0L); + } + + public static void resetLastResetTime() { + Prefs.putLong(RESET_KEY, System.currentTimeMillis()); + } + + public static String getLastResetTimeStr() { + long lastResetTime = getLastResetTime(); + + return lastResetTime > 0 ? DateTime.getStringFromTimestamp(lastResetTime) : "not yet"; + } + + public void start(final AnAction resetAction) { + new Timer().schedule(new TimerTask() { + @Override + public void run() { + new ResetTimerTask(getLastResetTime(), resetAction).run(); + } + }, 3000); + } + + protected static class ResetTimerTask extends TimerTask { + private final long lastResetTime; + private final AnAction resetAction; + + public ResetTimerTask(long lastResetTime, AnAction resetAction) { + this.lastResetTime = lastResetTime; + this.resetAction = resetAction; + } + + @Override + public void run() { + if (System.currentTimeMillis() - lastResetTime > RESET_PERIOD) { + String message = "It has been a long time since the last reset!\nWould you like to reset it again?"; + Notification notification = NotificationHelper.NOTIFICATION_GROUP.createNotification(Constants.PLUGIN_NAME, null, message, NotificationType.INFORMATION); + notification.addAction(resetAction); + notification.notify(null); + } + + new Timer().schedule(new ResetTimerTask(lastResetTime, resetAction), 3600000); // 60 min + } + } +} diff --git a/src/main/java/io/zhile/research/intellij/helper/Constants.java b/src/main/java/io/zhile/research/intellij/ier/helper/Constants.java similarity index 60% rename from src/main/java/io/zhile/research/intellij/helper/Constants.java rename to src/main/java/io/zhile/research/intellij/ier/helper/Constants.java index 022775b..a832228 100644 --- a/src/main/java/io/zhile/research/intellij/helper/Constants.java +++ b/src/main/java/io/zhile/research/intellij/ier/helper/Constants.java @@ -1,15 +1,17 @@ -package io.zhile.research.intellij.helper; +package io.zhile.research.intellij.ier.helper; import com.intellij.ide.plugins.PluginManager; import com.intellij.ide.plugins.cl.PluginClassLoader; import com.intellij.openapi.application.ApplicationNamesInfo; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.extensions.PluginId; +import com.intellij.openapi.util.io.FileUtil; public class Constants { public static final PluginClassLoader CLASS_LOADER = (PluginClassLoader) Constants.class.getClassLoader(); public static final PluginId PLUGIN_ID = CLASS_LOADER.getPluginId(); public static final String PLUGIN_NAME = PluginManager.getPlugin(PLUGIN_ID).getName(); - public static final String PRODUCT_NAME = ApplicationNamesInfo.getInstance().getFullProductName(); - public static final String PRODUCT_HASH = Integer.toString(PathManager.getConfigPath().hashCode()); + public static final String IDE_NAME = ApplicationNamesInfo.getInstance().getProductName(); + public static final String IDE_NAME_LOWER = IDE_NAME.toLowerCase(); + public static final String IDE_HASH = Integer.toHexString(FileUtil.pathHashCode(PathManager.getHomePath())); } diff --git a/src/main/java/io/zhile/research/intellij/ier/helper/DateTime.java b/src/main/java/io/zhile/research/intellij/ier/helper/DateTime.java new file mode 100644 index 0000000..3f6426e --- /dev/null +++ b/src/main/java/io/zhile/research/intellij/ier/helper/DateTime.java @@ -0,0 +1,15 @@ +package io.zhile.research.intellij.ier.helper; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +public class DateTime { + public static final DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + + public static String getStringFromTimestamp(long timestamp) { + Date date = new Date(timestamp); + + return df.format(date); + } +} diff --git a/src/main/java/io/zhile/research/intellij/helper/NotificationHelper.java b/src/main/java/io/zhile/research/intellij/ier/helper/NotificationHelper.java similarity index 98% rename from src/main/java/io/zhile/research/intellij/helper/NotificationHelper.java rename to src/main/java/io/zhile/research/intellij/ier/helper/NotificationHelper.java index 92e19c1..58df34d 100644 --- a/src/main/java/io/zhile/research/intellij/helper/NotificationHelper.java +++ b/src/main/java/io/zhile/research/intellij/ier/helper/NotificationHelper.java @@ -1,4 +1,4 @@ -package io.zhile.research.intellij.helper; +package io.zhile.research.intellij.ier.helper; import com.intellij.icons.AllIcons; import com.intellij.notification.Notification; diff --git a/src/main/java/io/zhile/research/intellij/ier/helper/Reflection.java b/src/main/java/io/zhile/research/intellij/ier/helper/Reflection.java new file mode 100644 index 0000000..6f7465e --- /dev/null +++ b/src/main/java/io/zhile/research/intellij/ier/helper/Reflection.java @@ -0,0 +1,13 @@ +package io.zhile.research.intellij.ier.helper; + +import java.lang.reflect.Method; + +public class Reflection { + public static Method getMethod(Class klass, String methodName, Class... methodParameterTypes) { + try { + return klass.getMethod(methodName, methodParameterTypes); + } catch (NoSuchMethodException e) { + return null; + } + } +} diff --git a/src/main/java/io/zhile/research/intellij/ier/listener/PluginListener.java b/src/main/java/io/zhile/research/intellij/ier/listener/PluginListener.java new file mode 100644 index 0000000..69e91ed --- /dev/null +++ b/src/main/java/io/zhile/research/intellij/ier/listener/PluginListener.java @@ -0,0 +1,16 @@ +package io.zhile.research.intellij.ier.listener; + +import com.intellij.ide.plugins.DynamicPluginListener; +import com.intellij.ide.plugins.IdeaPluginDescriptor; +import com.intellij.openapi.actionSystem.ActionManager; +import io.zhile.research.intellij.ier.helper.NotificationHelper; +import org.jetbrains.annotations.NotNull; + +public class PluginListener implements DynamicPluginListener { + @Override + public void pluginLoaded(@NotNull IdeaPluginDescriptor pluginDescriptor) { + ActionManager.getInstance().getAction("io.zhile.research.intellij.ier.action.ResetAction"); + + NotificationHelper.showInfo(null, "Plugin installed successfully! Now enjoy it~"); + } +} diff --git a/src/main/java/io/zhile/research/intellij/ier/tw/MainToolWindowFactory.java b/src/main/java/io/zhile/research/intellij/ier/tw/MainToolWindowFactory.java new file mode 100644 index 0000000..2fc42c9 --- /dev/null +++ b/src/main/java/io/zhile/research/intellij/ier/tw/MainToolWindowFactory.java @@ -0,0 +1,19 @@ +package io.zhile.research.intellij.ier.tw; + +import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.wm.ToolWindow; +import com.intellij.openapi.wm.ToolWindowFactory; +import com.intellij.ui.content.Content; +import com.intellij.ui.content.ContentFactory; +import io.zhile.research.intellij.ier.ui.form.MainForm; +import org.jetbrains.annotations.NotNull; + +public class MainToolWindowFactory implements ToolWindowFactory, DumbAware { + @Override + public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) { + MainForm mainForm = new MainForm(null); + Content content = ContentFactory.SERVICE.getInstance().createContent(mainForm.getContent(), "", true); + toolWindow.getContentManager().addContent(content); + } +} diff --git a/src/main/java/io/zhile/research/intellij/ier/ui/dialog/MainDialog.java b/src/main/java/io/zhile/research/intellij/ier/ui/dialog/MainDialog.java new file mode 100644 index 0000000..91673c9 --- /dev/null +++ b/src/main/java/io/zhile/research/intellij/ier/ui/dialog/MainDialog.java @@ -0,0 +1,26 @@ +package io.zhile.research.intellij.ier.ui.dialog; + +import com.intellij.openapi.ui.DialogWrapper; +import io.zhile.research.intellij.ier.ui.form.MainForm; + +import javax.swing.*; + +public class MainDialog extends DialogWrapper { + public MainDialog() { + super(true); + init(); + setTitle("Eval Reset"); + } + + + @Override + protected JComponent createCenterPanel() { + MainForm mainForm = new MainForm(this); + return mainForm.getContent(); + } + + @Override + protected JComponent createSouthPanel() { + return null; + } +} diff --git a/src/main/java/io/zhile/research/intellij/ier/ui/form/MainForm.form b/src/main/java/io/zhile/research/intellij/ier/ui/form/MainForm.form new file mode 100644 index 0000000..adf08c4 --- /dev/null +++ b/src/main/java/io/zhile/research/intellij/ier/ui/form/MainForm.form @@ -0,0 +1,93 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/src/main/java/io/zhile/research/intellij/ier/ui/form/MainForm.java b/src/main/java/io/zhile/research/intellij/ier/ui/form/MainForm.java new file mode 100644 index 0000000..3445e54 --- /dev/null +++ b/src/main/java/io/zhile/research/intellij/ier/ui/form/MainForm.java @@ -0,0 +1,100 @@ +package io.zhile.research.intellij.ier.ui.form; + +import com.intellij.icons.AllIcons; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.ui.Messages; +import io.zhile.research.intellij.ier.common.RecordItem; +import io.zhile.research.intellij.ier.common.Resetter; +import io.zhile.research.intellij.ier.component.ResetTimer; +import io.zhile.research.intellij.ier.helper.Constants; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.util.List; + +public class MainForm { + private JPanel rootPanel; + private JButton btnReset; + private JList lstMain; + private JLabel lblLastResetTime; + private JButton btnReloadList; + private JLabel lblFound; + private JLabel lblLastResetTimeLabel; + + private final DialogWrapper dialogWrapper; + private final DefaultListModel listModel = new DefaultListModel<>(); + + public MainForm(DialogWrapper dialogWrapper) { + this.dialogWrapper = dialogWrapper; + } + + public JPanel getContent() { + boldFont(lblFound); + boldFont(lblLastResetTimeLabel); + + lblLastResetTime.setText(ResetTimer.getLastResetTimeStr()); + lstMain.setModel(listModel); + + reloadRecordItems(); + btnReloadList.addActionListener(new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + reloadRecordItems(); + } + }); + + btnReset.setIcon(AllIcons.General.Reset); + btnReset.addActionListener(new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + resetEvalItems(); + } + }); + + if (null != dialogWrapper) { + dialogWrapper.getRootPane().setDefaultButton(btnReset); + } + + rootPanel.setMinimumSize(new Dimension(600, 240)); + return rootPanel; + } + + private void reloadRecordItems() { + listModel.clear(); + + List recordItemList = Resetter.getEvalRecords(); + for (RecordItem item : recordItemList) { + listModel.addElement(item.getType().getValue() + ": \t" + item.getKey() + (null == item.getValue() ? "" : " = \t" + item.getValue())); + } + } + + private void resetEvalItems() { + Resetter.reset(Resetter.getEvalRecords()); + ResetTimer.resetLastResetTime(); + listModel.clear(); + + if (Messages.YES == Messages.showYesNoDialog("Reset successfully!\nWould like to restart your IDE?", Constants.PLUGIN_NAME, AllIcons.General.Reset)) { + if (null != dialogWrapper) { + dialogWrapper.close(0); + } + + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + ApplicationManager.getApplication().restart(); + } + }); + + return; + } + + reloadRecordItems(); + } + + private static void boldFont(Component component) { + Font font = component.getFont(); + component.setFont(font.deriveFont(font.getStyle() | Font.BOLD)); + } +} diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 3dee8ce..74e55a9 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -1,24 +1,30 @@ io.zhile.research.ide-eval-resetter - ide-eval-resetter + IDE Eval Reset zhile.io - Click "Help" menu and select "Reset IDE Eval" + Click "Help" menu and select "Eval Reset" ]]> - com.intellij.modules.lang + com.intellij.modules.ultimate + + + + - + - - - io.zhile.research.intellij.MainComponent - - + + + + \ No newline at end of file