Release v1.1.4: Pomodoro & Stopwatch Mode Streamlining
Streamlined timer modes with bug fixes and code cleanup: Bug Fixes: - Fixed "POMODORO COMPLETE" showing in stopwatch mode - Fixed break timer showing pomodoro notices in stopwatch mode - Fixed pause/resume resetting timer to 0 in stopwatch mode - Fixed "Continue Working" button appearing in stopwatch mode - Fixed "Skip Break" button changing to "Continue" incorrectly Improvements: - Stopwatch mode now completely independent from pomodoro workflow - Removed break functionality from stopwatch mode (only Pause, Complete, Stop buttons) - Stopwatch mode maintains "FOCUSING ON" label throughout session - Cleaned up dead code (wasStopwatchBeforeBreak flag and related logic) - Simplified break resume logic (always returns to pomodoro mode) Technical: - Added isStopwatchMode flag for proper mode tracking - Fixed toggleTimer to handle stopwatch count-up vs pomodoro countdown - Removed unnecessary break integration code from stopwatch workflow
This commit is contained in:
@@ -4,7 +4,7 @@ A powerful task management and focus timer plugin for [Obsidian](https://obsidia
|
|||||||
|
|
||||||

|

|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
## 🎯 Overview
|
## 🎯 Overview
|
||||||
|
|
||||||
|
|||||||
21
main.js
21
main.js
@@ -749,7 +749,12 @@ var ImmerseView = class extends import_obsidian2.ItemView {
|
|||||||
const breakLabel = this.plugin.currentTimerSeconds > 0 ? "\u2615 BREAK TIME" : "\u2728 BREAK COMPLETE";
|
const breakLabel = this.plugin.currentTimerSeconds > 0 ? "\u2615 BREAK TIME" : "\u2728 BREAK COMPLETE";
|
||||||
activeCard.createEl("div", { cls: "immerse-active-label", text: breakLabel });
|
activeCard.createEl("div", { cls: "immerse-active-label", text: breakLabel });
|
||||||
} else {
|
} else {
|
||||||
const workLabel = this.plugin.currentTimerSeconds > 0 ? "\u{1F3AF} FOCUSING ON" : "\u{1F345} POMODORO COMPLETE";
|
let workLabel;
|
||||||
|
if (this.plugin.currentTimerSeconds > 0 || this.plugin.isStopwatchMode) {
|
||||||
|
workLabel = "\u{1F3AF} FOCUSING ON";
|
||||||
|
} else {
|
||||||
|
workLabel = "\u{1F345} POMODORO COMPLETE";
|
||||||
|
}
|
||||||
activeCard.createEl("div", { cls: "immerse-active-label", text: workLabel });
|
activeCard.createEl("div", { cls: "immerse-active-label", text: workLabel });
|
||||||
}
|
}
|
||||||
activeCard.createEl("div", { cls: "immerse-active-task-name", text: task.text });
|
activeCard.createEl("div", { cls: "immerse-active-task-name", text: task.text });
|
||||||
@@ -809,7 +814,7 @@ var ImmerseView = class extends import_obsidian2.ItemView {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (this.plugin.currentTimerSeconds > 0) {
|
if (this.plugin.currentTimerSeconds > 0 || this.plugin.isStopwatchMode) {
|
||||||
this.pauseBtnEl = controls.createEl("button", { cls: "immerse-btn immerse-btn-secondary" });
|
this.pauseBtnEl = controls.createEl("button", { cls: "immerse-btn immerse-btn-secondary" });
|
||||||
this.pauseBtnEl.innerHTML = this.plugin.isTimerRunning ? "\u23F8 Pause" : "\u25B6 Resume";
|
this.pauseBtnEl.innerHTML = this.plugin.isTimerRunning ? "\u23F8 Pause" : "\u25B6 Resume";
|
||||||
this.pauseBtnEl.addEventListener("click", () => this.plugin.toggleTimer());
|
this.pauseBtnEl.addEventListener("click", () => this.plugin.toggleTimer());
|
||||||
@@ -1250,6 +1255,7 @@ var ImmersePlugin = class extends import_obsidian4.Plugin {
|
|||||||
this.currentTimerSeconds = 0;
|
this.currentTimerSeconds = 0;
|
||||||
this.isTimerRunning = false;
|
this.isTimerRunning = false;
|
||||||
this.isBreakMode = false;
|
this.isBreakMode = false;
|
||||||
|
this.isStopwatchMode = false;
|
||||||
this.activeTaskId = null;
|
this.activeTaskId = null;
|
||||||
this.pomodoroCount = 0;
|
this.pomodoroCount = 0;
|
||||||
// Timestamp-based tracking for reliable background timing
|
// Timestamp-based tracking for reliable background timing
|
||||||
@@ -1652,6 +1658,7 @@ var ImmersePlugin = class extends import_obsidian4.Plugin {
|
|||||||
this.activeTaskId = taskId;
|
this.activeTaskId = taskId;
|
||||||
task.isActive = true;
|
task.isActive = true;
|
||||||
this.isBreakMode = false;
|
this.isBreakMode = false;
|
||||||
|
this.isStopwatchMode = true;
|
||||||
this.currentTimerSeconds = 0;
|
this.currentTimerSeconds = 0;
|
||||||
this.isTimerRunning = true;
|
this.isTimerRunning = true;
|
||||||
this.secondsWorkedOnCurrentTask = task.actualMinutes * 60;
|
this.secondsWorkedOnCurrentTask = task.actualMinutes * 60;
|
||||||
@@ -1690,6 +1697,7 @@ var ImmersePlugin = class extends import_obsidian4.Plugin {
|
|||||||
this.activeTaskId = taskId;
|
this.activeTaskId = taskId;
|
||||||
task.isActive = true;
|
task.isActive = true;
|
||||||
this.isBreakMode = false;
|
this.isBreakMode = false;
|
||||||
|
this.isStopwatchMode = false;
|
||||||
this.currentTimerSeconds = this.settings.pomodoroWorkMinutes * 60;
|
this.currentTimerSeconds = this.settings.pomodoroWorkMinutes * 60;
|
||||||
this.isTimerRunning = true;
|
this.isTimerRunning = true;
|
||||||
this.secondsWorkedOnCurrentTask = Math.floor(task.actualMinutes * 60);
|
this.secondsWorkedOnCurrentTask = Math.floor(task.actualMinutes * 60);
|
||||||
@@ -1788,7 +1796,11 @@ var ImmersePlugin = class extends import_obsidian4.Plugin {
|
|||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const elapsedMs = now - this.timerStartTimestamp;
|
const elapsedMs = now - this.timerStartTimestamp;
|
||||||
const elapsedSeconds = Math.floor(elapsedMs / 1e3);
|
const elapsedSeconds = Math.floor(elapsedMs / 1e3);
|
||||||
this.currentTimerSeconds = Math.max(0, this.pausedTimeRemaining - elapsedSeconds);
|
if (this.pausedTimeRemaining === 0 || this.isStopwatchMode) {
|
||||||
|
this.currentTimerSeconds = this.pausedTimeRemaining + elapsedSeconds;
|
||||||
|
} else {
|
||||||
|
this.currentTimerSeconds = Math.max(0, this.pausedTimeRemaining - elapsedSeconds);
|
||||||
|
}
|
||||||
if (task && !this.isBreakMode) {
|
if (task && !this.isBreakMode) {
|
||||||
this.secondsWorkedOnCurrentTask = initialSecondsWorked + elapsedSeconds;
|
this.secondsWorkedOnCurrentTask = initialSecondsWorked + elapsedSeconds;
|
||||||
task.actualMinutes = Math.floor(this.secondsWorkedOnCurrentTask / 60);
|
task.actualMinutes = Math.floor(this.secondsWorkedOnCurrentTask / 60);
|
||||||
@@ -1797,7 +1809,7 @@ var ImmersePlugin = class extends import_obsidian4.Plugin {
|
|||||||
}
|
}
|
||||||
this.updateStatusBar();
|
this.updateStatusBar();
|
||||||
this.updateTimerDisplay();
|
this.updateTimerDisplay();
|
||||||
if (this.currentTimerSeconds <= 0) {
|
if (this.currentTimerSeconds <= 0 && !this.isStopwatchMode) {
|
||||||
this.handlePomodoroEnd();
|
this.handlePomodoroEnd();
|
||||||
}
|
}
|
||||||
}, 1e3);
|
}, 1e3);
|
||||||
@@ -1822,6 +1834,7 @@ var ImmersePlugin = class extends import_obsidian4.Plugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.isTimerRunning = false;
|
this.isTimerRunning = false;
|
||||||
|
this.isStopwatchMode = false;
|
||||||
this.activeTaskId = null;
|
this.activeTaskId = null;
|
||||||
this.secondsWorkedOnCurrentTask = 0;
|
this.secondsWorkedOnCurrentTask = 0;
|
||||||
this.timerStartTimestamp = 0;
|
this.timerStartTimestamp = 0;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"id": "immerse",
|
"id": "immerse",
|
||||||
"name": "Immerse",
|
"name": "Immerse",
|
||||||
"version": "1.1.3",
|
"version": "1.1.4",
|
||||||
"minAppVersion": "0.15.0",
|
"minAppVersion": "0.15.0",
|
||||||
"description": "A Blitzit-inspired task management and focus timer plugin. Plan your day, track time with Pomodoro technique, and crush your tasks with satisfying checkoffs.",
|
"description": "A Blitzit-inspired task management and focus timer plugin. Plan your day, track time with Pomodoro technique, and crush your tasks with satisfying checkoffs.",
|
||||||
"author": "Crib",
|
"author": "Crib",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "immerse",
|
"name": "immerse",
|
||||||
"version": "1.1.3",
|
"version": "1.1.4",
|
||||||
"description": "A Blitzit-inspired task management and focus timer plugin for Obsidian",
|
"description": "A Blitzit-inspired task management and focus timer plugin for Obsidian",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
16
src/main.ts
16
src/main.ts
@@ -35,6 +35,7 @@ export default class ImmersePlugin extends Plugin {
|
|||||||
currentTimerSeconds: number = 0;
|
currentTimerSeconds: number = 0;
|
||||||
isTimerRunning: boolean = false;
|
isTimerRunning: boolean = false;
|
||||||
isBreakMode: boolean = false;
|
isBreakMode: boolean = false;
|
||||||
|
isStopwatchMode: boolean = false;
|
||||||
activeTaskId: string | null = null;
|
activeTaskId: string | null = null;
|
||||||
pomodoroCount: number = 0;
|
pomodoroCount: number = 0;
|
||||||
|
|
||||||
@@ -551,6 +552,7 @@ export default class ImmersePlugin extends Plugin {
|
|||||||
this.activeTaskId = taskId;
|
this.activeTaskId = taskId;
|
||||||
task.isActive = true;
|
task.isActive = true;
|
||||||
this.isBreakMode = false;
|
this.isBreakMode = false;
|
||||||
|
this.isStopwatchMode = true;
|
||||||
this.currentTimerSeconds = 0;
|
this.currentTimerSeconds = 0;
|
||||||
this.isTimerRunning = true;
|
this.isTimerRunning = true;
|
||||||
this.secondsWorkedOnCurrentTask = task.actualMinutes * 60;
|
this.secondsWorkedOnCurrentTask = task.actualMinutes * 60;
|
||||||
@@ -610,6 +612,7 @@ export default class ImmersePlugin extends Plugin {
|
|||||||
this.activeTaskId = taskId;
|
this.activeTaskId = taskId;
|
||||||
task.isActive = true;
|
task.isActive = true;
|
||||||
this.isBreakMode = false;
|
this.isBreakMode = false;
|
||||||
|
this.isStopwatchMode = false;
|
||||||
this.currentTimerSeconds = this.settings.pomodoroWorkMinutes * 60;
|
this.currentTimerSeconds = this.settings.pomodoroWorkMinutes * 60;
|
||||||
this.isTimerRunning = true;
|
this.isTimerRunning = true;
|
||||||
|
|
||||||
@@ -766,8 +769,14 @@ export default class ImmersePlugin extends Plugin {
|
|||||||
const elapsedMs = now - this.timerStartTimestamp;
|
const elapsedMs = now - this.timerStartTimestamp;
|
||||||
const elapsedSeconds = Math.floor(elapsedMs / 1000);
|
const elapsedSeconds = Math.floor(elapsedMs / 1000);
|
||||||
|
|
||||||
// Update timer (countdown from paused position)
|
// Update timer based on mode
|
||||||
this.currentTimerSeconds = Math.max(0, this.pausedTimeRemaining - elapsedSeconds);
|
if (this.pausedTimeRemaining === 0 || this.isStopwatchMode) {
|
||||||
|
// Stopwatch mode - count up from paused position
|
||||||
|
this.currentTimerSeconds = this.pausedTimeRemaining + elapsedSeconds;
|
||||||
|
} else {
|
||||||
|
// Countdown mode (pomodoro/break) - count down from paused position
|
||||||
|
this.currentTimerSeconds = Math.max(0, this.pausedTimeRemaining - elapsedSeconds);
|
||||||
|
}
|
||||||
|
|
||||||
if (task && !this.isBreakMode) {
|
if (task && !this.isBreakMode) {
|
||||||
// Update actual time worked
|
// Update actual time worked
|
||||||
@@ -783,7 +792,7 @@ export default class ImmersePlugin extends Plugin {
|
|||||||
this.updateStatusBar();
|
this.updateStatusBar();
|
||||||
this.updateTimerDisplay();
|
this.updateTimerDisplay();
|
||||||
|
|
||||||
if (this.currentTimerSeconds <= 0) {
|
if (this.currentTimerSeconds <= 0 && !this.isStopwatchMode) {
|
||||||
this.handlePomodoroEnd();
|
this.handlePomodoroEnd();
|
||||||
}
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
@@ -814,6 +823,7 @@ export default class ImmersePlugin extends Plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.isTimerRunning = false;
|
this.isTimerRunning = false;
|
||||||
|
this.isStopwatchMode = false;
|
||||||
this.activeTaskId = null;
|
this.activeTaskId = null;
|
||||||
this.secondsWorkedOnCurrentTask = 0;
|
this.secondsWorkedOnCurrentTask = 0;
|
||||||
this.timerStartTimestamp = 0;
|
this.timerStartTimestamp = 0;
|
||||||
|
|||||||
14
src/view.ts
14
src/view.ts
@@ -154,7 +154,13 @@ export class ImmerseView extends ItemView {
|
|||||||
const breakLabel = this.plugin.currentTimerSeconds > 0 ? '☕ BREAK TIME' : '✨ BREAK COMPLETE';
|
const breakLabel = this.plugin.currentTimerSeconds > 0 ? '☕ BREAK TIME' : '✨ BREAK COMPLETE';
|
||||||
activeCard.createEl('div', { cls: 'immerse-active-label', text: breakLabel });
|
activeCard.createEl('div', { cls: 'immerse-active-label', text: breakLabel });
|
||||||
} else {
|
} else {
|
||||||
const workLabel = this.plugin.currentTimerSeconds > 0 ? '🎯 FOCUSING ON' : '🍅 POMODORO COMPLETE';
|
// Determine label based on whether timer is active and mode (stopwatch vs pomodoro)
|
||||||
|
let workLabel: string;
|
||||||
|
if (this.plugin.currentTimerSeconds > 0 || this.plugin.isStopwatchMode) {
|
||||||
|
workLabel = '🎯 FOCUSING ON';
|
||||||
|
} else {
|
||||||
|
workLabel = '🍅 POMODORO COMPLETE';
|
||||||
|
}
|
||||||
activeCard.createEl('div', { cls: 'immerse-active-label', text: workLabel });
|
activeCard.createEl('div', { cls: 'immerse-active-label', text: workLabel });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,8 +240,8 @@ export class ImmerseView extends ItemView {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Work mode controls
|
// Work mode controls
|
||||||
if (this.plugin.currentTimerSeconds > 0) {
|
if (this.plugin.currentTimerSeconds > 0 || this.plugin.isStopwatchMode) {
|
||||||
// Work session still running
|
// Work session still running (or stopwatch mode active)
|
||||||
this.pauseBtnEl = controls.createEl('button', { cls: 'immerse-btn immerse-btn-secondary' });
|
this.pauseBtnEl = controls.createEl('button', { cls: 'immerse-btn immerse-btn-secondary' });
|
||||||
this.pauseBtnEl.innerHTML = this.plugin.isTimerRunning ? '⏸ Pause' : '▶ Resume';
|
this.pauseBtnEl.innerHTML = this.plugin.isTimerRunning ? '⏸ Pause' : '▶ Resume';
|
||||||
this.pauseBtnEl.addEventListener('click', () => this.plugin.toggleTimer());
|
this.pauseBtnEl.addEventListener('click', () => this.plugin.toggleTimer());
|
||||||
@@ -248,7 +254,7 @@ export class ImmerseView extends ItemView {
|
|||||||
stopBtn.innerHTML = '✕ Stop';
|
stopBtn.innerHTML = '✕ Stop';
|
||||||
stopBtn.addEventListener('click', () => this.plugin.stopTimer());
|
stopBtn.addEventListener('click', () => this.plugin.stopTimer());
|
||||||
} else {
|
} else {
|
||||||
// Work session finished - show break and completion options
|
// Pomodoro session finished - show break and completion options
|
||||||
const startBreakBtn = controls.createEl('button', { cls: 'immerse-btn immerse-btn-secondary' });
|
const startBreakBtn = controls.createEl('button', { cls: 'immerse-btn immerse-btn-secondary' });
|
||||||
startBreakBtn.innerHTML = '☕ Start Break';
|
startBreakBtn.innerHTML = '☕ Start Break';
|
||||||
startBreakBtn.addEventListener('click', () => this.plugin.startBreak());
|
startBreakBtn.addEventListener('click', () => this.plugin.startBreak());
|
||||||
|
|||||||
@@ -5,5 +5,6 @@
|
|||||||
"1.0.7": "0.15.0",
|
"1.0.7": "0.15.0",
|
||||||
"1.0.8": "0.15.0",
|
"1.0.8": "0.15.0",
|
||||||
"1.0.9": "0.15.0",
|
"1.0.9": "0.15.0",
|
||||||
"1.1.3": "0.15.0"
|
"1.1.3": "0.15.0",
|
||||||
|
"1.1.4": "0.15.0"
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user