Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

import com.github.akshayashokcode.devfocus.model.PomodoroMode
import com.github.akshayashokcode.devfocus.model.PomodoroSettings
import com.intellij.notification.NotificationGroupManager
import com.intellij.notification.NotificationType
import com.intellij.openapi.components.Service
import com.intellij.openapi.project.Project
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
Expand All @@ -15,17 +18,20 @@
import java.util.concurrent.TimeUnit

@Service(Service.Level.PROJECT)
class PomodoroTimerService {
class PomodoroTimerService(private val project: Project) {
companion object {
private const val ONE_SECOND = 1000L
private const val NOTIFICATION_GROUP_ID = "DevFocus Notifications"
}

enum class TimerState { IDLE, RUNNING, PAUSED }
enum class TimerPhase { WORK, BREAK }

private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
private var job: Job? = null

private var settings = PomodoroMode.CLASSIC.toSettings()
private var currentPhase = TimerPhase.WORK
private var remainingTimeMs: Long = TimeUnit.MINUTES.toMillis(settings.sessionMinutes.toLong())

private val _timeLeft = MutableStateFlow(formatTime(remainingTimeMs))
Expand Down Expand Up @@ -55,10 +61,73 @@
}
if (remainingTimeMs <= 0) {
_state.value = TimerState.IDLE
onSessionComplete()
}
}
}

private fun onSessionComplete() {
val currentSessionNum = _currentSession.value
val totalSessions = settings.sessionsPerRound

if (currentPhase == TimerPhase.WORK) {
// Work session complete
if (currentSessionNum >= totalSessions) {
// Last session complete - all done!
NotificationGroupManager.getInstance()
.getNotificationGroup(NOTIFICATION_GROUP_ID)
.createNotification(
"\uD83C\uDF89 All Sessions Complete!",

Check warning on line 80 in src/main/kotlin/com/github/akshayashokcode/devfocus/services/pomodoro/PomodoroTimerService.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Incorrect string capitalization

String '🎉 All Sessions Complete!' is not properly capitalized. It should have sentence capitalization
"You've completed all $totalSessions sessions. Take a well-deserved break!",
NotificationType.INFORMATION
)
.notify(project)

// Reset to initial state
currentPhase = TimerPhase.WORK
_currentSession.value = 1
remainingTimeMs = TimeUnit.MINUTES.toMillis(settings.sessionMinutes.toLong())
_timeLeft.value = formatTime(remainingTimeMs)
} else {
// Work session complete - start break
NotificationGroupManager.getInstance()
.getNotificationGroup(NOTIFICATION_GROUP_ID)
.createNotification(
"\uD83C\uDF45 Session Complete!",

Check warning on line 96 in src/main/kotlin/com/github/akshayashokcode/devfocus/services/pomodoro/PomodoroTimerService.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Incorrect string capitalization

String '🍅 Session Complete!' is not properly capitalized. It should have sentence capitalization
"Great work! Starting ${settings.breakMinutes}-minute break ☕.",
NotificationType.INFORMATION
)
.notify(project)

// Start break timer
currentPhase = TimerPhase.BREAK
remainingTimeMs = TimeUnit.MINUTES.toMillis(settings.breakMinutes.toLong())
_timeLeft.value = formatTime(remainingTimeMs)
start()
}

} else {
// Break complete
// More sessions remaining - start next session
NotificationGroupManager.getInstance()
.getNotificationGroup(NOTIFICATION_GROUP_ID)
.createNotification(
"☕ Break Complete!",

Check warning on line 115 in src/main/kotlin/com/github/akshayashokcode/devfocus/services/pomodoro/PomodoroTimerService.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Incorrect string capitalization

String '☕ Break Complete!' is not properly capitalized. It should have sentence capitalization
"Starting session ${currentSessionNum + 1} of $totalSessions.",
NotificationType.INFORMATION
)
.notify(project)

// Start next work session
currentPhase = TimerPhase.WORK
_currentSession.value = currentSessionNum + 1
remainingTimeMs = TimeUnit.MINUTES.toMillis(settings.sessionMinutes.toLong())
_timeLeft.value = formatTime(remainingTimeMs)
start()

}
}

fun pause() {
if (_state.value == TimerState.RUNNING) {
job?.cancel()
Expand All @@ -72,6 +141,7 @@
job = null

// Reset to initial state
currentPhase = TimerPhase.WORK
remainingTimeMs = TimeUnit.MINUTES.toMillis(settings.sessionMinutes.toLong())
_timeLeft.value = formatTime(remainingTimeMs)
_currentSession.value = 1
Expand All @@ -92,6 +162,7 @@

settings = newSettings
_settings.value = newSettings
currentPhase = TimerPhase.WORK
remainingTimeMs = TimeUnit.MINUTES.toMillis(newSettings.sessionMinutes.toLong())
_timeLeft.value = formatTime(remainingTimeMs)
_currentSession.value = 1
Expand All @@ -105,7 +176,11 @@
fun getSettings(): PomodoroSettings = settings

fun getProgress(): Float {
val totalMs = TimeUnit.MINUTES.toMillis(settings.sessionMinutes.toLong())
val totalMs = if (currentPhase == TimerPhase.WORK) {
TimeUnit.MINUTES.toMillis(settings.sessionMinutes.toLong())
} else {
TimeUnit.MINUTES.toMillis(settings.breakMinutes.toLong())
}
return if (totalMs > 0) remainingTimeMs.toFloat() / totalMs.toFloat() else 0f
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.github.akshayashokcode.devfocus.ui.components

import java.awt.*
import javax.swing.JPanel
import javax.swing.UIManager

class CircularTimerPanel : JPanel() {

Expand All @@ -13,7 +14,6 @@ class CircularTimerPanel : JPanel() {
private val workColor = Color(74, 144, 226) // Blue for focus/work
private val breakColor = Color(80, 200, 120) // Green for rest
private val backgroundColor = Color(224, 224, 224) // Light gray
private val textColor = Color(60, 60, 60) // Dark gray for text

private val diameter = 180
private val strokeWidth = 10f
Expand All @@ -34,7 +34,7 @@ class CircularTimerPanel : JPanel() {
super.paintComponent(g)
val g2d = g as Graphics2D

// Enable anti-aliasing for smooth circles
// Enable antialiasing for smooth circles
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON)

Expand All @@ -60,7 +60,7 @@ class CircularTimerPanel : JPanel() {
g2d.drawArc(arcX, arcY, arcSize, arcSize, 90, -arcAngle) // Negative for clockwise

// Draw time text in center
g2d.color = textColor
g2d.color = UIManager.getColor("Label.foreground") ?: Color.BLACK
val font = Font("SansSerif", Font.BOLD, 36)
g2d.font = font

Expand Down
1 change: 1 addition & 0 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,6 @@
/>
<postStartupActivity implementation="com.github.akshayashokcode.devfocus.startup.MyProjectActivity" />
<projectService serviceImplementation="com.github.akshayashokcode.devfocus.services.pomodoro.PomodoroTimerService"/>
<notificationGroup id="DevFocus Notifications" displayType="BALLOON"/>
</extensions>
</idea-plugin>
Loading