Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Silence Breaker #43

Merged
merged 4 commits into from
Jan 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
# AMII Changelog

## [Unreleased]

### Added
- The ability for MIKU to continuously give you a stream of AniMemes (Silence Breaker feature).

### Changed

Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,15 @@ Programs that exit with:

are part of the default allowed exit codes, MIKU will not react to these (but can if you want to).

### Silence Breaker

So you've been working diligently building your code, but not using any features of your IDE.
Such as building, testing, or running your project.
Well MIKU likes to remind you every so often that they exist.

You can specify how long you can go without seeing a meme.
After that, MIKU will give you one!

### Logs

Do you work on a project that takes a billion years for the application to start?
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

pluginGroup = io.unthrottled
pluginName_ = AMII
pluginVersion = 0.3.1
pluginVersion = 0.4.0
pluginSinceBuild = 201.4515.24
pluginUntilBuild = 203.*
# Plugin Verifier integration -> https://github.com/JetBrains/gradle-intellij-plugin#plugin-verifier-dsl
Expand Down
377 changes: 207 additions & 170 deletions src/main/java/io/unthrottled/amii/config/ui/PluginSettingsUI.form

Large diffs are not rendered by default.

28 changes: 25 additions & 3 deletions src/main/java/io/unthrottled/amii/config/ui/PluginSettingsUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.JSpinner;
import javax.swing.JTabbedPane;
Expand All @@ -53,6 +54,7 @@
import static io.unthrottled.amii.events.UserEvents.IDLE;
import static io.unthrottled.amii.events.UserEvents.LOGS;
import static io.unthrottled.amii.events.UserEvents.PROCESS;
import static io.unthrottled.amii.events.UserEvents.SILENCE;
import static io.unthrottled.amii.events.UserEvents.STARTUP;
import static io.unthrottled.amii.events.UserEvents.TASK;
import static io.unthrottled.amii.events.UserEvents.TEST;
Expand Down Expand Up @@ -95,6 +97,9 @@ public class PluginSettingsUI implements SearchableConfigurable, Configurable.No
private JTextPane generalLinks;
private JPanel idleAnchorPanel;
private JTabbedPane tabbedPane1;
private JScrollPane eventsPane;
private JSpinner silenceSpinner;
private JCheckBox permitBreaksInSilenceCheckBox;
private PreferredCharacterPanel characterModel;
private PreferredCharacterPanel blacklistedCharacterModel;
private JBTable exitCodeTable;
Expand Down Expand Up @@ -285,8 +290,7 @@ public boolean isCellEditable(Integer info) {
1
);
eventsBeforeFrustrationSpinner.setModel(frustrationSpinnerModel);
eventsBeforeFrustrationSpinner.addChangeListener(e -> pluginSettingsModel.setEventsBeforFrustration(frustrationSpinnerModel.getNumber().intValue()));

eventsBeforeFrustrationSpinner.addChangeListener(e -> pluginSettingsModel.setEventsBeforeFrustration(frustrationSpinnerModel.getNumber().intValue()));

soundEnabled.addActionListener(e -> volumeSlider.setEnabled(soundEnabled.isSelected()));
volumeSlider.setForeground(UIUtil.getContextHelpForeground());
Expand All @@ -307,6 +311,19 @@ public boolean isCellEditable(Integer info) {
idleTimeoutSpinner.setModel(idleSpinnerModel);
idleTimeoutSpinner.addChangeListener(e -> pluginSettingsModel.setIdleTimeOutInMinutes(idleSpinnerModel.getNumber().intValue()));

SpinnerNumberModel silenceSpinnerModel = new SpinnerNumberModel(
config.getSilenceTimeoutInMinutes(),
1,
Integer.MAX_VALUE,
1
);
silenceSpinner.setModel(silenceSpinnerModel);
silenceSpinner.addChangeListener(e -> pluginSettingsModel.setSilenceTimeOutInMinutes(silenceSpinnerModel.getNumber().intValue()));

permitBreaksInSilenceCheckBox.addActionListener(e -> {
updateIdleComponents();
updateEventPreference(SILENCE.getValue(), permitBreaksInSilenceCheckBox.isSelected());
});
idleEnabled.addActionListener(e -> {
updateIdleComponents();
updateEventPreference(IDLE.getValue(), idleEnabled.isSelected());
Expand Down Expand Up @@ -364,6 +381,9 @@ private void updateLogComponents() {
private void updateIdleComponents() {
idleTimeoutSpinner.setEnabled(idleEnabled.isSelected());
}
private void updateSilenceComponents() {
silenceSpinner.setEnabled(permitBreaksInSilenceCheckBox.isSelected());
}

private void updateFrustrationComponents() {
frustrationProbabilitySlider.setEnabled(allowFrustrationCheckBox.isSelected());
Expand Down Expand Up @@ -398,6 +418,7 @@ private void initFromState() {
preferOther.setSelected(isGenderSelected(Gender.OTHER.getValue()));

idleEnabled.setSelected(isEventEnabled(IDLE.getValue()));
permitBreaksInSilenceCheckBox.setSelected(isEventEnabled(SILENCE.getValue()));
updateIdleComponents();
watchLogs.setSelected(isEventEnabled(LOGS.getValue()));
updateLogComponents();
Expand Down Expand Up @@ -469,7 +490,8 @@ public void apply() {
config.setLogSearchIgnoreCase(pluginSettingsModel.getLogSearchIgnoreCase());
config.setShowMood(pluginSettingsModel.getShowMood());
config.setIdleTimeoutInMinutes(pluginSettingsModel.getIdleTimeOutInMinutes());
config.setEventsBeforeFrustration(pluginSettingsModel.getEventsBeforFrustration());
config.setSilenceTimeoutInMinutes(pluginSettingsModel.getSilenceTimeOutInMinutes());
config.setEventsBeforeFrustration(pluginSettingsModel.getEventsBeforeFrustration());
ApplicationManager.getApplication().getMessageBus().syncPublisher(
ConfigListener.Companion.getCONFIG_TOPIC()
).pluginConfigUpdated(config);
Expand Down
3 changes: 3 additions & 0 deletions src/main/kotlin/io/unthrottled/amii/PluginMaster.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import io.unthrottled.amii.assets.CharacterContentManager
import io.unthrottled.amii.assets.Status
import io.unthrottled.amii.assets.VisualContentManager
import io.unthrottled.amii.listeners.IdleEventListener
import io.unthrottled.amii.listeners.SilenceListener
import io.unthrottled.amii.onboarding.UpdateNotification
import io.unthrottled.amii.onboarding.UserOnBoarding
import io.unthrottled.amii.platform.LifeCycleManager
Expand Down Expand Up @@ -83,8 +84,10 @@ internal data class ProjectListeners(
) : Disposable {

private val idleEventListener = IdleEventListener(project)
private val silenceListener = SilenceListener(project)

override fun dispose() {
idleEventListener.dispose()
silenceListener.dispose()
}
}
2 changes: 2 additions & 0 deletions src/main/kotlin/io/unthrottled/amii/config/Config.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class Config : PersistentStateComponent<Config>, Cloneable {
get() = ServiceManager.getService(Config::class.java)
const val DEFAULT_DELIMITER = ","
const val DEFAULT_IDLE_TIMEOUT_IN_MINUTES: Long = 5L
const val DEFAULT_SILENCE_TIMEOUT_IN_MINUTES: Long = 10L
const val DEFAULT_MEME_INVULNERABLE_DURATION: Int = 3
const val DEFAULT_TIMED_MEME_DISPLAY_DURATION: Int = 40
const val DEFAULT_EVENTS_BEFORE_FRUSTRATION: Int = 5
Expand All @@ -48,6 +49,7 @@ class Config : PersistentStateComponent<Config>, Cloneable {
FORCE_KILLED_EXIT_CODE
).joinToString(DEFAULT_DELIMITER)
var idleTimeoutInMinutes = DEFAULT_IDLE_TIMEOUT_IN_MINUTES
var silenceTimeoutInMinutes = DEFAULT_SILENCE_TIMEOUT_IN_MINUTES
var allowFrustration = true
var eventsBeforeFrustration = DEFAULT_EVENTS_BEFORE_FRUSTRATION
var probabilityOfFrustration = DEFAULT_FRUSTRATION_PROBABILITY
Expand Down
4 changes: 3 additions & 1 deletion src/main/kotlin/io/unthrottled/amii/config/PluginSettings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import java.net.URI
data class ConfigSettingsModel(
var allowedExitCodes: String,
var idleTimeOutInMinutes: Long,
var silenceTimeOutInMinutes: Long,
var memeDisplayAnchorValue: String,
var idleMemeDisplayAnchorValue: String,
var memeDisplayModeValue: String,
Expand All @@ -18,7 +19,7 @@ data class ConfigSettingsModel(
var logKeyword: String,
var logSearchIgnoreCase: Boolean,
var showMood: Boolean,
var eventsBeforFrustration: Int,
var eventsBeforeFrustration: Int,
) {
fun duplicate(): ConfigSettingsModel = copy()
}
Expand All @@ -34,6 +35,7 @@ object PluginSettings {
fun getInitialConfigSettingsModel() = ConfigSettingsModel(
Config.instance.allowedExitCodes,
Config.instance.idleTimeoutInMinutes,
Config.instance.silenceTimeoutInMinutes,
Config.instance.memeDisplayAnchorValue,
Config.instance.memeDisplayModeValue,
Config.instance.idleMemeDisplayAnchorValue,
Expand Down
1 change: 1 addition & 0 deletions src/main/kotlin/io/unthrottled/amii/core/MIKU.kt
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ class MIKU :
private fun reactToEvent(userEvent: UserEvent, emotionalState: Mood) {
when (userEvent.type) {
in USER_TRIGGERED_EVENTS -> taskPersonalityCore.processUserEvent(userEvent, emotionalState)
UserEvents.SILENCE,
UserEvents.ON_DEMAND -> onDemandPersonalityCore.processUserEvent(userEvent, emotionalState)
UserEvents.IDLE,
UserEvents.RETURN, -> idlePersonalityCore.processUserEvent(userEvent, emotionalState)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package io.unthrottled.amii.core.personality

import io.unthrottled.amii.assets.MemeAssetCategory
import io.unthrottled.amii.config.Config
import io.unthrottled.amii.core.personality.emotions.Mood
import io.unthrottled.amii.events.UserEvent
import io.unthrottled.amii.events.UserEvents
import io.unthrottled.amii.memes.Comparison
import io.unthrottled.amii.memes.memeService

Expand All @@ -13,13 +15,20 @@ class OnDemandPersonalityCore : PersonalityCore {
mood: Mood
) {
userEvent.project.memeService()
.createMeme(
.createMemeFromCategories(
userEvent,
MemeAssetCategory.MOTIVATION,
MemeAssetCategory.HAPPY,
MemeAssetCategory.CELEBRATION,
MemeAssetCategory.ALERT,
) {
it.withComparator {
Comparison.GREATER
}.build()
it
.withSound(
if (userEvent.type == UserEvents.SILENCE) false
else Config.instance.soundEnabled
)
.withComparator {
Comparison.GREATER
}.build()
}
}
}
1 change: 1 addition & 0 deletions src/main/kotlin/io/unthrottled/amii/events/UserEvents.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ enum class UserEvents(val value: Int) {
TASK(1 shl 5),
TEST(1 shl 6),
RELAX(1 shl 7),
SILENCE(1 shl 8),
}

enum class UserEventCategory {
Expand Down
83 changes: 83 additions & 0 deletions src/main/kotlin/io/unthrottled/amii/listeners/SilenceListener.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package io.unthrottled.amii.listeners

import com.intellij.openapi.Disposable
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.project.Project
import com.intellij.util.Alarm
import io.unthrottled.amii.config.Config
import io.unthrottled.amii.config.ConfigListener
import io.unthrottled.amii.events.EVENT_TOPIC
import io.unthrottled.amii.events.UserEvent
import io.unthrottled.amii.events.UserEventCategory
import io.unthrottled.amii.events.UserEventListener
import io.unthrottled.amii.events.UserEvents
import io.unthrottled.amii.tools.PluginMessageBundle
import java.util.concurrent.TimeUnit

class SilenceListener(private val project: Project) : Runnable, UserEventListener, Disposable {
private val messageBus = ApplicationManager.getApplication().messageBus.connect()
private val log = Logger.getInstance(this::class.java)
private val silenceAlarm = Alarm()

init {
val self = this
messageBus.subscribe(EVENT_TOPIC, this)
messageBus.subscribe(
ConfigListener.CONFIG_TOPIC,
ConfigListener { newPluginState ->
silenceAlarm.cancelAllRequests()
silenceAlarm.addRequest(
self,
TimeUnit.MILLISECONDS.convert(
newPluginState.silenceTimeoutInMinutes,
TimeUnit.MINUTES
).toInt()
)
}
)
scheduleSilenceAlert()
}

private fun scheduleSilenceAlert() {
silenceAlarm.addRequest(
this,
TimeUnit.MILLISECONDS.convert(
getCurrentTimoutInMinutes(),
TimeUnit.MINUTES
).toInt()
)
}

private fun getCurrentTimoutInMinutes(): Long =
Config.instance.silenceTimeoutInMinutes

override fun dispose() {
messageBus.dispose()
silenceAlarm.dispose()
}

override fun run() {
log.debug("Observed silence timeout")
ApplicationManager.getApplication().messageBus
.syncPublisher(EVENT_TOPIC)
.onDispatch(
UserEvent(
UserEvents.SILENCE,
UserEventCategory.NEUTRAL,
PluginMessageBundle.message("user.event.silence.name"),
project
)
)
}

override fun onDispatch(userEvent: UserEvent) {
when (userEvent.type) {
UserEvents.IDLE -> silenceAlarm.cancelAllRequests()
else -> {
silenceAlarm.cancelAllRequests()
scheduleSilenceAlert()
}
}
}
}
7 changes: 7 additions & 0 deletions src/main/kotlin/io/unthrottled/amii/memes/Meme.kt
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class Meme(
) {
private var notificationMode = Config.instance.notificationMode
private var notificationAnchor = Config.instance.notificationAnchor
private var soundEnabled = Config.instance.soundEnabled
private var memeDisplayInvulnerabilityDuration = Config.instance.memeDisplayInvulnerabilityDuration
private var memeDisplayTimedDuration = Config.instance.memeDisplayTimedDuration
private var memeComparator: (Meme) -> Comparison = { Comparison.EQUAL }
Expand All @@ -69,6 +70,11 @@ class Meme(
return this
}

fun withSound(newSoundOption: Boolean): Builder {
soundEnabled = newSoundOption
return this
}

fun withMetaData(newMetaData: Map<String, Any>): Builder {
metaData = newMetaData
return this
Expand All @@ -81,6 +87,7 @@ class Meme(

fun build(): Meme {
val memePlayer = audibleContent.toOptional()
.filter { soundEnabled }
.map { MemePlayerFactory.createPlayer(it) }
.orElse(null)
return Meme(
Expand Down
50 changes: 0 additions & 50 deletions src/main/kotlin/io/unthrottled/amii/memes/player/Mp3Player.kt

This file was deleted.

Loading