diff --git a/python/educational-core/educational-core.iml b/python/educational-core/educational-core.iml index 8433b9de516e..1df588c98a73 100644 --- a/python/educational-core/educational-core.iml +++ b/python/educational-core/educational-core.iml @@ -8,5 +8,12 @@ + + + + + + + \ No newline at end of file diff --git a/python/educational-core/student/lib/twitter4j-core-4.0.4.jar b/python/educational-core/student/lib/twitter4j-core-4.0.4.jar new file mode 100644 index 000000000000..029abce2bc28 Binary files /dev/null and b/python/educational-core/student/lib/twitter4j-core-4.0.4.jar differ diff --git a/python/educational-core/student/resources/META-INF/plugin.xml b/python/educational-core/student/resources/META-INF/plugin.xml index 3e10b6a2bb2e..9d5142d93775 100644 --- a/python/educational-core/student/resources/META-INF/plugin.xml +++ b/python/educational-core/student/resources/META-INF/plugin.xml @@ -80,8 +80,6 @@ displayName="Educational"/> - diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyBasePluginConfigurator.java b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyBasePluginConfigurator.java index e1900e133df5..801410c8d431 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyBasePluginConfigurator.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyBasePluginConfigurator.java @@ -6,9 +6,11 @@ import com.intellij.openapi.fileEditor.FileEditorManagerEvent; import com.intellij.openapi.fileEditor.FileEditorManagerListener; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; +import com.jetbrains.edu.learning.actions.*; +import com.jetbrains.edu.learning.courseFormat.StudyStatus; import com.jetbrains.edu.learning.courseFormat.Task; import com.jetbrains.edu.learning.courseFormat.TaskFile; -import com.jetbrains.edu.learning.actions.*; +import com.jetbrains.edu.learning.twitter.StudyTwitterUtils; import com.jetbrains.edu.learning.ui.StudyToolWindow; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -93,4 +95,44 @@ public abstract class StudyBasePluginConfigurator implements StudyPluginConfigur public StudyAfterCheckAction[] getAfterCheckActions() { return null; } + + @NotNull + @Override + public String getConsumerKey(@NotNull Project project) { + return ""; + } + + @NotNull + @Override + public String getConsumerSecret(@NotNull Project project) { + return ""; + } + + @Override + public void storeTwitterTokens(@NotNull Project project, @NotNull String accessToken, @NotNull String tokenSecret) { + // do nothing + } + + @NotNull + @Override + public String getTwitterTokenSecret(@NotNull Project project) { + return ""; + } + + @NotNull + @Override + public String getTwitterAccessToken(@NotNull Project project) { + return ""; + } + + @Override + public boolean askToTweet(@NotNull Project project, Task solvedTask, StudyStatus statusBeforeCheck) { + return false; + } + + @Nullable + @Override + public StudyTwitterUtils.TwitterDialogPanel getTweetDialogPanel(@NotNull Task solvedTask) { + return null; + } } diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyPluginConfigurator.java b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyPluginConfigurator.java index 4561c2b903aa..4aa1f272acb5 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyPluginConfigurator.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyPluginConfigurator.java @@ -5,7 +5,10 @@ import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.fileEditor.FileEditorManagerListener; import com.intellij.openapi.project.Project; import com.jetbrains.edu.learning.actions.StudyAfterCheckAction; +import com.jetbrains.edu.learning.courseFormat.StudyStatus; +import com.jetbrains.edu.learning.courseFormat.Task; import com.jetbrains.edu.learning.settings.ModifiableSettingsPanel; +import com.jetbrains.edu.learning.twitter.StudyTwitterUtils; import com.jetbrains.edu.learning.ui.StudyToolWindow; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -18,7 +21,6 @@ public interface StudyPluginConfigurator { /** * Provide action group that should be placed on the tool window toolbar. - * @param project * @return */ @NotNull @@ -26,7 +28,6 @@ public interface StudyPluginConfigurator { /** * Provide panels, that could be added to Task tool window. - * @param project * @return Map from panel id, i.e. "Task description", to panel itself. */ @NotNull @@ -45,9 +46,50 @@ public interface StudyPluginConfigurator { StudyAfterCheckAction[] getAfterCheckActions(); @NotNull String getLanguageScriptUrl(); - - boolean accept(@NotNull final Project project); @Nullable ModifiableSettingsPanel getSettingsPanel(); + + /** + * To implement tweeting you should register you app in twitter. For registered application twitter provide + * consumer key and consumer secret, that are used for authorize by OAuth. + * @return consumer key for current educational plugin + */ + @NotNull String getConsumerKey(@NotNull final Project project); + + /** + * To implement tweeting you should register you app in twitter. For registered application twitter provide + * consumer key and consumer secret, that are used for authorize by OAuth. + * @return consumer secret for current educational plugin + */ + @NotNull String getConsumerSecret(@NotNull final Project project); + + /** + * The plugin implemented tweeting should define policy when user will be asked to tweet. + *@param statusBeforeCheck @return + */ + boolean askToTweet(@NotNull final Project project, Task solvedTask, StudyStatus statusBeforeCheck); + + /** + * Stores access token and token secret, obtained by authorizing PyCharm. + */ + void storeTwitterTokens(@NotNull final Project project, @NotNull final String accessToken, @NotNull final String tokenSecret); + + /** + * @return stored access token + */ + @NotNull String getTwitterAccessToken(@NotNull Project project); + + /** + * @return stored token secret + */ + @NotNull String getTwitterTokenSecret(@NotNull Project project); + + /** + * @return panel that will be shown to user in ask to tweet dialog. + */ + @Nullable + StudyTwitterUtils.TwitterDialogPanel getTweetDialogPanel(@NotNull Task solvedTask); + + boolean accept(@NotNull final Project project); } diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/actions/StudyAfterCheckAction.java b/python/educational-core/student/src/com/jetbrains/edu/learning/actions/StudyAfterCheckAction.java index b85df4256cf8..ecd467777219 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/actions/StudyAfterCheckAction.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/actions/StudyAfterCheckAction.java @@ -1,8 +1,8 @@ package com.jetbrains.edu.learning.actions; import com.intellij.openapi.project.Project; -import com.jetbrains.edu.courseFormat.StudyStatus; -import com.jetbrains.edu.courseFormat.Task; +import com.jetbrains.edu.learning.courseFormat.StudyStatus; +import com.jetbrains.edu.learning.courseFormat.Task; import org.jetbrains.annotations.NotNull; public abstract class StudyAfterCheckAction { diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java b/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java index bdeb215a89f1..9a372fe39fc1 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java @@ -11,15 +11,15 @@ import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; -import com.jetbrains.edu.learning.core.EduUtils; -import com.jetbrains.edu.learning.courseFormat.StudyStatus; -import com.jetbrains.edu.learning.courseFormat.Task; import com.jetbrains.edu.learning.StudyPluginConfigurator; import com.jetbrains.edu.learning.StudyState; import com.jetbrains.edu.learning.StudyTaskManager; import com.jetbrains.edu.learning.StudyUtils; import com.jetbrains.edu.learning.actions.StudyAfterCheckAction; -import com.jetbrains.edu.learning.EduStepicConnector; +import com.jetbrains.edu.learning.core.EduUtils; +import com.jetbrains.edu.learning.courseFormat.StudyStatus; +import com.jetbrains.edu.learning.courseFormat.Task; +import com.jetbrains.edu.learning.stepic.EduStepicConnector; import com.jetbrains.edu.learning.stepic.StudySettings; import org.jetbrains.annotations.NotNull; diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/twitter/StudyTwitterAction.java b/python/educational-core/student/src/com/jetbrains/edu/learning/twitter/StudyTwitterAction.java new file mode 100644 index 000000000000..dd74afa0d273 --- /dev/null +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/twitter/StudyTwitterAction.java @@ -0,0 +1,49 @@ +package com.jetbrains.edu.learning.twitter; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.jetbrains.edu.learning.StudyPluginConfigurator; +import com.jetbrains.edu.learning.StudyUtils; +import com.jetbrains.edu.learning.actions.StudyAfterCheckAction; +import com.jetbrains.edu.learning.courseFormat.StudyStatus; +import com.jetbrains.edu.learning.courseFormat.Task; +import org.jetbrains.annotations.NotNull; +import twitter4j.Twitter; +import twitter4j.TwitterException; + +/** + * Action that provide tweeting functionality to plugin. + * Is performed for every solved task and configured by StudyPluginConfigurator instance. + * + * In order to provide tweeting functionality in your plugin you should override twitter + * methods in StudyPluginConfigurator instance of your plugin. + */ +public class StudyTwitterAction extends StudyAfterCheckAction { + Logger LOG = Logger.getInstance(StudyTwitterAction.class); + @Override + public void run(@NotNull Project project, @NotNull Task solvedTask, StudyStatus statusBeforeCheck) { + try { + StudyPluginConfigurator configurator = StudyUtils.getConfigurator(project); + if (configurator == null) { + LOG.warn("Plugin configurator not found"); + return; + } + + if (configurator.askToTweet(project, solvedTask, statusBeforeCheck)) { + boolean isAuthorized = !configurator.getTwitterAccessToken(project).isEmpty(); + Twitter twitter = StudyTwitterUtils.getTwitter(configurator.getConsumerKey(project), configurator.getConsumerSecret(project)); + StudyTwitterUtils.configureTwitter(twitter, project, isAuthorized); + StudyTwitterUtils.TwitterDialogPanel panel = configurator.getTweetDialogPanel(solvedTask); + if (panel != null) { + StudyTwitterUtils.showPostTweetDialogAndPostTweet(twitter, panel); + } + else { + LOG.warn("Plugin didn't provide twitter panel"); + } + } + } + catch (TwitterException e) { + LOG.warn(e.getMessage()); + } + } +} diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/twitter/StudyTwitterUtils.java b/python/educational-core/student/src/com/jetbrains/edu/learning/twitter/StudyTwitterUtils.java new file mode 100644 index 000000000000..3fdab6b6a761 --- /dev/null +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/twitter/StudyTwitterUtils.java @@ -0,0 +1,212 @@ +package com.jetbrains.edu.learning.twitter; + +import com.intellij.ide.BrowserUtil; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogBuilder; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.ui.DocumentAdapter; +import com.intellij.ui.components.JBScrollPane; +import com.jetbrains.edu.learning.StudyPluginConfigurator; +import com.jetbrains.edu.learning.StudyUtils; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import twitter4j.StatusUpdate; +import twitter4j.Twitter; +import twitter4j.TwitterException; +import twitter4j.TwitterFactory; +import twitter4j.auth.AccessToken; +import twitter4j.auth.RequestToken; +import twitter4j.conf.ConfigurationBuilder; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + + +public class StudyTwitterUtils { + private static final Logger LOG = Logger.getInstance(StudyTwitterUtils.class); + + /** + * Configure twitter instance: authorize if needed or set access token and token secret provided by configurator. + * @param twitter + * @param project + * @param isAuthorized + * @throws TwitterException + */ + public static void configureTwitter(@NotNull final Twitter twitter, @NotNull final Project project, + final boolean isAuthorized) throws TwitterException { + if (!isAuthorized) { + authorize(project, twitter); + } + else { + StudyPluginConfigurator configurator = StudyUtils.getConfigurator(project); + if (configurator != null) { + getTwitterForAuthorizedApp(twitter, configurator.getTwitterAccessToken(project), configurator.getTwitterTokenSecret(project)); + } + } + } + + /** + * Set consumer key and secret. + * @param consumerKey + * @param consumerSecret + * @return + */ + @NotNull + public static Twitter getTwitter(@NotNull final String consumerKey, @NotNull final String consumerSecret) { + ConfigurationBuilder configurationBuilder = new ConfigurationBuilder(); + configurationBuilder.setOAuthConsumerKey(consumerKey); + configurationBuilder.setOAuthConsumerSecret(consumerSecret); + return new TwitterFactory(configurationBuilder.build()).getInstance(); + } + + /** + * Set access token and token secret in Twitter instance + * @param twitter + * @param accessToken + * @param tokenSecret + */ + private static void getTwitterForAuthorizedApp(Twitter twitter, @NotNull String accessToken, + @NotNull String tokenSecret) { + AccessToken token = new AccessToken(accessToken, tokenSecret); + twitter.setOAuthAccessToken(token); + } + + /** + * Authorize user and save tokens by StudyPluginConfigurator#storeTwitterTokens + * @param project + * @param twitter + * @throws TwitterException + */ + public static void authorize(@NotNull final Project project, @NotNull final Twitter twitter) throws TwitterException { + RequestToken requestToken = twitter.getOAuthRequestToken(); + BrowserUtil.browse(requestToken.getAuthorizationURL()); + + ApplicationManager.getApplication().invokeLater(() -> { + String pin = Messages.showInputDialog("Twitter PIN:", "Twitter Authorization", null, "", null); + try { + AccessToken token; + if (pin != null && pin.length() > 0) { + token = twitter.getOAuthAccessToken(requestToken, pin); + } + else { + token = twitter.getOAuthAccessToken(); + } + StudyPluginConfigurator configurator = StudyUtils.getConfigurator(project); + if (configurator != null) { + configurator.storeTwitterTokens(project, token.getToken(), token.getTokenSecret()); + } + else { + LOG.warn("Plugin configurator not found"); + } + } + catch (TwitterException e) { + if (401 == e.getStatusCode()) { + LOG.warn("Unable to get the access token."); + } + else { + LOG.warn(e.getMessage()); + } + } + }); + } + + /** + * Show twitter dialog, asking user to tweet about his achievements. Post tweet with provided by panel + * media and text. + * As a result of succeeded tweet twitter website is opened in default browser. + * @param twitter + * @param twitterDialogPanel + */ + public static void showPostTweetDialogAndPostTweet(@NotNull Twitter twitter, @NotNull final TwitterDialogPanel twitterDialogPanel) { + ApplicationManager.getApplication().invokeLater(() -> { + DialogBuilder builder = new DialogBuilder(); + twitterDialogPanel.addTextFieldVerifier(createTextFieldLengthDocumentListener(builder, twitterDialogPanel)); + builder.title("Twitter"); + builder.addOkAction().setText("Tweet"); + builder.addCancelAction(); + builder.setCenterPanel(new JBScrollPane(twitterDialogPanel)); + builder.resizable(true); + if (builder.showAndGet()) { + StatusUpdate update = new StatusUpdate(twitterDialogPanel.getMessage()); + try { + InputStream inputStream = twitterDialogPanel.getMediaSource(); + if (inputStream != null) { + File imageFile = FileUtil.createTempFile("twitter_media", "gif"); + + FileUtil.copy(inputStream, new FileOutputStream(imageFile)); + update.media(imageFile); + } + twitter.updateStatus(update); + BrowserUtil.browse("https://twitter.com/"); + } + catch (IOException | TwitterException e) { + LOG.warn(e.getMessage()); + Messages.showErrorDialog("Status wasn't updated. Please, check internet connection and try again", "Twitter"); + } + } + }); + } + + /** + * Listener updates label indicating remaining symbols number like in twitter. + * @param builder + * @param panel + * @return + */ + public static DocumentListener createTextFieldLengthDocumentListener(@NotNull DialogBuilder builder, @NotNull final TwitterDialogPanel panel) { + return new DocumentAdapter() { + @Override + protected void textChanged(DocumentEvent e) { + int length = e.getDocument().getLength(); + if (length > 140 || length == 0) { + builder.setOkActionEnabled(false); + panel.getRemainSymbolsLabel().setText("" + String.valueOf(140 - length) + ""); + } + else { + builder.setOkActionEnabled(true); + panel.getRemainSymbolsLabel().setText(String.valueOf(140 - length)); + } + + } + }; + } + + /** + * Class provides structure for twitter dialog panel + */ + public abstract static class TwitterDialogPanel extends JPanel { + + /** + * Provides tweet text + * @return + */ + @NotNull public abstract String getMessage(); + + /** + * + * @return Input stream of media should be posted or null if there's nothing to post + */ + @Nullable public abstract InputStream getMediaSource(); + + /** + * + * @return label that will be used to show remained symbol number + */ + @NotNull public abstract JLabel getRemainSymbolsLabel(); + + /** + * Api to add document listener to field containing tweet text + * @param documentListener + */ + public abstract void addTextFieldVerifier(@NotNull final DocumentListener documentListener); + + } +} diff --git a/python/educational-core/student/student.iml b/python/educational-core/student/student.iml index c4f9d2bccdb9..0ebe6c7ad38b 100644 --- a/python/educational-core/student/student.iml +++ b/python/educational-core/student/student.iml @@ -11,6 +11,8 @@ + + \ No newline at end of file diff --git a/python/educational-python/build/pycharm_edu_build.gant b/python/educational-python/build/pycharm_edu_build.gant index 25ca87b39d95..d78efb76507b 100644 --- a/python/educational-python/build/pycharm_edu_build.gant +++ b/python/educational-python/build/pycharm_edu_build.gant @@ -224,7 +224,9 @@ public layoutEducational(String classesPath, Set usedJars) { private layoutPlugins(layouts) { dir("plugins") { - layouts.layoutPlugin("student") + layouts.layoutPlugin("student") { + fileset(dir: "$pythonCommunityHome/educational-core/student/lib") + } layouts.layoutPlugin("student-python") { dir("courses") { fileset(dir: "$pythonEduHome/student-python/resources/courses") diff --git a/python/educational-python/educational-python.iml b/python/educational-python/educational-python.iml index 5832d9d1b31a..20278fc43f44 100644 --- a/python/educational-python/educational-python.iml +++ b/python/educational-python/educational-python.iml @@ -24,5 +24,6 @@ + \ No newline at end of file diff --git a/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyPluginConfigurator.java b/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyPluginConfigurator.java index e5e6dbec1daf..88688a8ae8a5 100644 --- a/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyPluginConfigurator.java +++ b/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyPluginConfigurator.java @@ -3,10 +3,7 @@ package com.jetbrains.edu.learning; import com.intellij.openapi.actionSystem.DefaultActionGroup; import com.intellij.openapi.project.Project; import com.jetbrains.edu.learning.courseFormat.Course; -import com.jetbrains.edu.learning.actions.PyTwitterAction; -import com.jetbrains.edu.learning.actions.StudyAfterCheckAction; import com.jetbrains.edu.learning.settings.ModifiableSettingsPanel; -import com.jetbrains.edu.learning.settings.PySettingsPanel; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -34,12 +31,6 @@ public class PyStudyPluginConfigurator extends StudyBasePluginConfigurator { return getClass().getResource("/python.js").toExternalForm(); } - @Nullable - @Override - public StudyAfterCheckAction[] getAfterCheckActions() { - return new StudyAfterCheckAction[]{new PyTwitterAction()}; - } - @Override public boolean accept(@NotNull Project project) { StudyTaskManager taskManager = StudyTaskManager.getInstance(project); @@ -51,6 +42,6 @@ public class PyStudyPluginConfigurator extends StudyBasePluginConfigurator { @Nullable @Override public ModifiableSettingsPanel getSettingsPanel() { - return new PySettingsPanel(); + return null; } } diff --git a/python/educational-python/student-python/src/com/jetbrains/edu/learning/settings/PySettingsPanel.form b/python/educational-python/student-python/src/com/jetbrains/edu/learning/settings/PySettingsPanel.form deleted file mode 100644 index a51a16c9216f..000000000000 --- a/python/educational-python/student-python/src/com/jetbrains/edu/learning/settings/PySettingsPanel.form +++ /dev/null @@ -1,52 +0,0 @@ - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/python/educational-python/student-python/src/com/jetbrains/edu/learning/settings/PySettingsPanel.java b/python/educational-python/student-python/src/com/jetbrains/edu/learning/settings/PySettingsPanel.java deleted file mode 100644 index 240b567135bb..000000000000 --- a/python/educational-python/student-python/src/com/jetbrains/edu/learning/settings/PySettingsPanel.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.jetbrains.edu.learning.settings; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.project.ProjectUtil; -import com.intellij.ui.components.JBCheckBox; -import com.intellij.util.ui.UIUtil; -import org.jetbrains.annotations.NotNull; - -import javax.swing.*; - - -public class PySettingsPanel implements ModifiableSettingsPanel{ - private JBCheckBox myAskToTweetCheckBox; - private JPanel myPanel; - private boolean myIsModified = false; - - public PySettingsPanel() { - myAskToTweetCheckBox.addActionListener(e -> myIsModified = true); - myAskToTweetCheckBox.setSelected(PyStudySettings.getInstance(ProjectUtil.guessCurrentProject(myPanel)).askToTweet()); - myPanel.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, UIUtil.getBoundsColor())); - } - - @Override - public void apply() { - Project project = ProjectUtil.guessCurrentProject(myPanel); - PyStudySettings.getInstance(project).setAskToTweet(myAskToTweetCheckBox.isSelected()); - } - - @Override - public void reset() { - Project project = ProjectUtil.guessCurrentProject(myPanel); - PyStudySettings.getInstance(project).setAskToTweet(true); - } - - @Override - public void resetCredentialsModification() { - myIsModified = false; - } - - @Override - public boolean isModified() { - return myIsModified; - } - - @NotNull - public JPanel getPanel() { - return myPanel; - } -} diff --git a/python/educational-python/student-python/src/com/jetbrains/edu/learning/settings/PyStudySettings.java b/python/educational-python/student-python/src/com/jetbrains/edu/learning/settings/PyStudySettings.java deleted file mode 100644 index b2bc22b0d18b..000000000000 --- a/python/educational-python/student-python/src/com/jetbrains/edu/learning/settings/PyStudySettings.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.jetbrains.edu.learning.settings; - -import com.intellij.openapi.components.PersistentStateComponent; -import com.intellij.openapi.components.ServiceManager; -import com.intellij.openapi.components.State; -import com.intellij.openapi.components.Storage; -import com.intellij.openapi.project.Project; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -@SuppressWarnings("MethodMayBeStatic") -@State(name = "PyStudySettings", storages = @Storage("py_study_settings.xml")) -public class PyStudySettings implements PersistentStateComponent { - - private State myState = new State(); - - - public static class State { - public boolean askToTweet = true; - } - - public static PyStudySettings getInstance(@NotNull final Project project) { - return ServiceManager.getService(project, PyStudySettings.class); - } - @Nullable - @Override - public State getState() { - return myState; - } - - @Override - public void loadState(State state) { - myState = state; - } - - public boolean askToTweet() { - return myState.askToTweet; - } - - public void setAskToTweet(final boolean askToTweet) { - myState.askToTweet = askToTweet; - } -} \ No newline at end of file