Release v1.0.9: Rename plugin from Focus Task to Immerse

This commit is contained in:
2025-11-23 19:56:06 +01:00
parent 364935af66
commit 95983a1a2a
10 changed files with 328 additions and 327 deletions

View File

@@ -1,16 +1,16 @@
# ⚡ Focus Task # ⚡ Immerse
A powerful task management and focus timer plugin for [Obsidian](https://obsidian.md), heavily inspired by [Blitzit](https://www.blitzit.app/). A powerful task management and focus timer plugin for [Obsidian](https://obsidian.md), heavily inspired by [Blitzit](https://www.blitzit.app/).
![Focus Task Banner](https://img.shields.io/badge/Obsidian-Plugin-7c3aed?style=for-the-badge&logo=obsidian&logoColor=white) ![Immerse Banner](https://img.shields.io/badge/Obsidian-Plugin-7c3aed?style=for-the-badge&logo=obsidian&logoColor=white)
![License](https://img.shields.io/badge/License-MIT-green?style=for-the-badge) ![License](https://img.shields.io/badge/License-MIT-green?style=for-the-badge)
![Version](https://img.shields.io/badge/Version-1.0.8-blue?style=for-the-badge) ![Version](https://img.shields.io/badge/Version-1.0.9-blue?style=for-the-badge)
## 🎯 Overview ## 🎯 Overview
Focus Task brings the power of time-boxed task management directly into your Obsidian vault. Plan your day, track time with the Pomodoro technique, and crush your tasks with satisfying checkoffs - all without leaving your notes. Immerse brings the power of time-boxed task management directly into your Obsidian vault. Plan your day, track time with the Pomodoro technique, and crush your tasks with satisfying checkoffs - all without leaving your notes.
### Why Focus Task? ### Why Immerse?
- **Stay in Flow**: No need to switch between apps - manage tasks where you take notes - **Stay in Flow**: No need to switch between apps - manage tasks where you take notes
- **Time Awareness**: Know exactly how long tasks take vs. your estimates - **Time Awareness**: Know exactly how long tasks take vs. your estimates
@@ -60,12 +60,12 @@ Focus Task brings the power of time-boxed task management directly into your Obs
### From Obsidian Community Plugins (Coming Soon) ### From Obsidian Community Plugins (Coming Soon)
1. Open Obsidian Settings 1. Open Obsidian Settings
2. Go to Community Plugins 2. Go to Community Plugins
3. Search for "Focus Task" 3. Search for "Immerse"
4. Click Install, then Enable 4. Click Install, then Enable
### Manual Installation ### Manual Installation
1. Download the latest release from the [releases page](https://git.cribdev.com/crib/focus-task/releases) 1. Download the latest release from the [releases page](https://git.cribdev.com/crib/immerse/releases)
2. Extract the files to your vault's `.obsidian/plugins/focus-task/` folder 2. Extract the files to your vault's `.obsidian/plugins/immerse/` folder
3. **⚠️ IMPORTANT**: When updating, do NOT replace or delete the existing `data.json` file - this contains all your tasks, settings, and progress! 3. **⚠️ IMPORTANT**: When updating, do NOT replace or delete the existing `data.json` file - this contains all your tasks, settings, and progress!
4. Reload Obsidian 4. Reload Obsidian
5. Enable the plugin in Settings → Community Plugins 5. Enable the plugin in Settings → Community Plugins
@@ -75,8 +75,8 @@ Focus Task brings the power of time-boxed task management directly into your Obs
### Building from Source ### Building from Source
```bash ```bash
# Clone the repository # Clone the repository
git clone https://git.cribdev.com/crib/focus-task.git git clone https://git.cribdev.com/crib/immerse.git
cd focus-task cd immerse
# Install dependencies # Install dependencies
npm install npm install
@@ -85,14 +85,14 @@ npm install
npm run build npm run build
# Copy to your vault # Copy to your vault
cp main.js manifest.json styles.css /path/to/your/vault/.obsidian/plugins/focus-task/ cp main.js manifest.json styles.css /path/to/your/vault/.obsidian/plugins/immerse/
``` ```
## 📖 Usage ## 📖 Usage
### Getting Started ### Getting Started
1. **Open Focus Task**: Click the ⚡ icon in the ribbon or use the command palette (`Ctrl/Cmd + P` → "Open Focus Task Panel") 1. **Open Immerse**: Click the ⚡ icon in the ribbon or use the command palette (`Ctrl/Cmd + P` → "Open Immerse Panel")
2. **Add a Task**: Click "+ Add Task" and fill in: 2. **Add a Task**: Click "+ Add Task" and fill in:
- Task description - Task description
@@ -107,7 +107,7 @@ cp main.js manifest.json styles.css /path/to/your/vault/.obsidian/plugins/focus-
| Action | Command | | Action | Command |
|--------|---------| |--------|---------|
| Open Panel | `Ctrl/Cmd + P` → "Open Focus Task Panel" | | Open Panel | `Ctrl/Cmd + P` → "Open Immerse Panel" |
| Quick Add Task | `Ctrl/Cmd + P` → "Quick Add Task" | | Quick Add Task | `Ctrl/Cmd + P` → "Quick Add Task" |
| Toggle Timer | `Ctrl/Cmd + P` → "Toggle Timer" | | Toggle Timer | `Ctrl/Cmd + P` → "Toggle Timer" |
| Complete Task | `Ctrl/Cmd + P` → "Complete Current Task" | | Complete Task | `Ctrl/Cmd + P` → "Complete Current Task" |
@@ -188,12 +188,12 @@ Default lists: Work 💼, Personal 🏠, Learning 📚
4. Click Save 4. Click Save
### Theming ### Theming
Focus Task respects your Obsidian theme and adapts to both light and dark modes automatically. Immerse respects your Obsidian theme and adapts to both light and dark modes automatically.
## 📁 Project Structure ## 📁 Project Structure
``` ```
focus-task/ immerse/
├── src/ ├── src/
│ ├── main.ts # Main plugin class │ ├── main.ts # Main plugin class
│ ├── types.ts # TypeScript interfaces │ ├── types.ts # TypeScript interfaces
@@ -218,7 +218,7 @@ Blitzit's approach to productivity resonated with me:
- Satisfying task completion experience - Satisfying task completion experience
- Progress insights - Progress insights
I wanted to bring this experience directly into Obsidian, where I already manage my notes and knowledge. Focus Task is my attempt to capture the essence of what makes Blitzit great while leveraging Obsidian's powerful ecosystem. I wanted to bring this experience directly into Obsidian, where I already manage my notes and knowledge. Immerse is my attempt to capture the essence of what makes Blitzit great while leveraging Obsidian's powerful ecosystem.
**If you're looking for a dedicated productivity app, I highly recommend checking out [Blitzit](https://www.blitzit.app/)!** **If you're looking for a dedicated productivity app, I highly recommend checking out [Blitzit](https://www.blitzit.app/)!**
@@ -236,8 +236,8 @@ Contributions are welcome! Feel free to:
```bash ```bash
# Clone the repo # Clone the repo
git clone https://git.cribdev.com/crib/focus-task.git git clone https://git.cribdev.com/crib/immerse.git
cd focus-task cd immerse
# Install dependencies # Install dependencies
npm install npm install
@@ -246,7 +246,7 @@ npm install
npm run dev npm run dev
# Create symlink to your test vault # Create symlink to your test vault
ln -s $(pwd) /path/to/vault/.obsidian/plugins/focus-task ln -s $(pwd) /path/to/vault/.obsidian/plugins/immerse
``` ```
## 📜 License ## 📜 License
@@ -255,8 +255,8 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
## 🔗 Links ## 🔗 Links
- **Repository**: [https://git.cribdev.com/crib/focus-task](https://git.cribdev.com/crib/focus-task) - **Repository**: [https://git.cribdev.com/crib/immerse](https://git.cribdev.com/crib/immerse)
- **Issues**: [https://git.cribdev.com/crib/focus-task/issues](https://git.cribdev.com/crib/focus-task/issues) - **Issues**: [https://git.cribdev.com/crib/immerse/issues](https://git.cribdev.com/crib/immerse/issues)
- **Inspiration**: [Blitzit App](https://www.blitzit.app/) - **Inspiration**: [Blitzit App](https://www.blitzit.app/)
--- ---

190
main.js
View File

@@ -24,7 +24,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
// src/main.ts // src/main.ts
var main_exports = {}; var main_exports = {};
__export(main_exports, { __export(main_exports, {
default: () => FocusTaskPlugin default: () => ImmersePlugin
}); });
module.exports = __toCommonJS(main_exports); module.exports = __toCommonJS(main_exports);
var import_obsidian3 = require("obsidian"); var import_obsidian3 = require("obsidian");
@@ -56,7 +56,7 @@ var DEFAULT_DATA = {
lastActiveDate: "", lastActiveDate: "",
pomodorosCompleted: 0 pomodorosCompleted: 0
}; };
var VIEW_TYPE_FOCUS_TASK = "focus-task-view"; var VIEW_TYPE_IMMERSE = "immerse-view";
var CELEBRATION_MESSAGES = [ var CELEBRATION_MESSAGES = [
{ emoji: "\u{1F4A5}", message: "Crushed it!" }, { emoji: "\u{1F4A5}", message: "Crushed it!" },
{ emoji: "\u{1F525}", message: "On fire!" }, { emoji: "\u{1F525}", message: "On fire!" },
@@ -98,7 +98,7 @@ var QuickAddTaskModal = class extends import_obsidian.Modal {
} }
onOpen() { onOpen() {
const { contentEl } = this; const { contentEl } = this;
contentEl.addClass("focus-task-modal"); contentEl.addClass("immerse-modal");
contentEl.createEl("h2", { text: "\u26A1 Add New Task" }); contentEl.createEl("h2", { text: "\u26A1 Add New Task" });
new import_obsidian.Setting(contentEl).setName("Task").addText((text) => { new import_obsidian.Setting(contentEl).setName("Task").addText((text) => {
text.setPlaceholder("What do you need to do?").onChange((value) => this.taskText = value); text.setPlaceholder("What do you need to do?").onChange((value) => this.taskText = value);
@@ -137,10 +137,10 @@ var QuickAddTaskModal = class extends import_obsidian.Modal {
dropdown.setValue(this.selectedList); dropdown.setValue(this.selectedList);
dropdown.onChange((value) => this.selectedList = value); dropdown.onChange((value) => this.selectedList = value);
}); });
const buttonContainer = contentEl.createEl("div", { cls: "focus-task-modal-buttons" }); const buttonContainer = contentEl.createEl("div", { cls: "immerse-modal-buttons" });
const cancelBtn = buttonContainer.createEl("button", { text: "Cancel", cls: "focus-task-btn" }); const cancelBtn = buttonContainer.createEl("button", { text: "Cancel", cls: "immerse-btn" });
cancelBtn.addEventListener("click", () => this.close()); cancelBtn.addEventListener("click", () => this.close());
const addBtn = buttonContainer.createEl("button", { text: "Add Task", cls: "focus-task-btn focus-task-btn-primary" }); const addBtn = buttonContainer.createEl("button", { text: "Add Task", cls: "immerse-btn immerse-btn-primary" });
addBtn.addEventListener("click", () => this.submitTask()); addBtn.addEventListener("click", () => this.submitTask());
} }
submitTask() { submitTask() {
@@ -166,7 +166,7 @@ var EditTaskModal = class extends import_obsidian.Modal {
} }
onOpen() { onOpen() {
const { contentEl } = this; const { contentEl } = this;
contentEl.addClass("focus-task-modal"); contentEl.addClass("immerse-modal");
contentEl.createEl("h2", { text: "\u270F\uFE0F Edit Task" }); contentEl.createEl("h2", { text: "\u270F\uFE0F Edit Task" });
new import_obsidian.Setting(contentEl).setName("Task").addText((text) => text.setValue(this.task.text).onChange((value) => this.task.text = value)); new import_obsidian.Setting(contentEl).setName("Task").addText((text) => text.setValue(this.task.text).onChange((value) => this.task.text = value));
new import_obsidian.Setting(contentEl).setName("Estimated Time").addDropdown((dropdown) => { new import_obsidian.Setting(contentEl).setName("Estimated Time").addDropdown((dropdown) => {
@@ -204,10 +204,10 @@ var EditTaskModal = class extends import_obsidian.Modal {
if (this.task.actualMinutes > 0) { if (this.task.actualMinutes > 0) {
new import_obsidian.Setting(contentEl).setName("Time Tracked").setDesc(`You've worked on this task for ${this.plugin.formatTimeHuman(this.task.actualMinutes)}`); new import_obsidian.Setting(contentEl).setName("Time Tracked").setDesc(`You've worked on this task for ${this.plugin.formatTimeHuman(this.task.actualMinutes)}`);
} }
const buttonContainer = contentEl.createEl("div", { cls: "focus-task-modal-buttons" }); const buttonContainer = contentEl.createEl("div", { cls: "immerse-modal-buttons" });
const cancelBtn = buttonContainer.createEl("button", { text: "Cancel", cls: "focus-task-btn" }); const cancelBtn = buttonContainer.createEl("button", { text: "Cancel", cls: "immerse-btn" });
cancelBtn.addEventListener("click", () => this.close()); cancelBtn.addEventListener("click", () => this.close());
const saveBtn = buttonContainer.createEl("button", { text: "Save", cls: "focus-task-btn focus-task-btn-primary" }); const saveBtn = buttonContainer.createEl("button", { text: "Save", cls: "immerse-btn immerse-btn-primary" });
saveBtn.addEventListener("click", () => { saveBtn.addEventListener("click", () => {
this.plugin.updateTask(this.task.id, this.task); this.plugin.updateTask(this.task.id, this.task);
new import_obsidian.Notice("\u2705 Task updated!"); new import_obsidian.Notice("\u2705 Task updated!");
@@ -221,7 +221,7 @@ var EditTaskModal = class extends import_obsidian.Modal {
}; };
// src/view.ts // src/view.ts
var FocusTaskView = class extends import_obsidian2.ItemView { var ImmerseView = class extends import_obsidian2.ItemView {
constructor(leaf, plugin) { constructor(leaf, plugin) {
super(leaf); super(leaf);
this.currentFilter = "all"; this.currentFilter = "all";
@@ -233,10 +233,10 @@ var FocusTaskView = class extends import_obsidian2.ItemView {
this.plugin = plugin; this.plugin = plugin;
} }
getViewType() { getViewType() {
return VIEW_TYPE_FOCUS_TASK; return VIEW_TYPE_IMMERSE;
} }
getDisplayText() { getDisplayText() {
return "Focus Task"; return "Immerse";
} }
getIcon() { getIcon() {
return "zap"; return "zap";
@@ -270,7 +270,7 @@ var FocusTaskView = class extends import_obsidian2.ItemView {
refresh() { refresh() {
const container = this.containerEl.children[1]; const container = this.containerEl.children[1];
container.empty(); container.empty();
container.addClass("focus-task-container"); container.addClass("immerse-container");
this.timerTimeEl = null; this.timerTimeEl = null;
this.progressBarEl = null; this.progressBarEl = null;
this.actualTimeEl = null; this.actualTimeEl = null;
@@ -281,14 +281,14 @@ var FocusTaskView = class extends import_obsidian2.ItemView {
this.renderTaskList(container); this.renderTaskList(container);
} }
renderHeader(container) { renderHeader(container) {
const header = container.createEl("div", { cls: "focus-task-header" }); const header = container.createEl("div", { cls: "immerse-header" });
const titleSection = header.createEl("div", { cls: "focus-task-title-section" }); const titleSection = header.createEl("div", { cls: "immerse-title-section" });
titleSection.createEl("h2", { text: "\u26A1 Focus Task", cls: "focus-task-title" }); titleSection.createEl("h2", { text: "\u26A1 Immerse", cls: "immerse-title" });
const today = new Date(); const today = new Date();
const dateStr = today.toLocaleDateString("en-US", { weekday: "long", month: "short", day: "numeric" }); const dateStr = today.toLocaleDateString("en-US", { weekday: "long", month: "short", day: "numeric" });
titleSection.createEl("div", { text: dateStr, cls: "focus-task-date" }); titleSection.createEl("div", { text: dateStr, cls: "immerse-date" });
const actions = header.createEl("div", { cls: "focus-task-header-actions" }); const actions = header.createEl("div", { cls: "immerse-header-actions" });
const addBtn = actions.createEl("button", { cls: "focus-task-btn focus-task-btn-primary" }); const addBtn = actions.createEl("button", { cls: "immerse-btn immerse-btn-primary" });
addBtn.innerHTML = "+ Add Task"; addBtn.innerHTML = "+ Add Task";
addBtn.addEventListener("click", () => { addBtn.addEventListener("click", () => {
new QuickAddTaskModal(this.app, this.plugin).open(); new QuickAddTaskModal(this.app, this.plugin).open();
@@ -296,7 +296,7 @@ var FocusTaskView = class extends import_obsidian2.ItemView {
} }
renderStatsBar(container) { renderStatsBar(container) {
const stats = this.plugin.getStats(); const stats = this.plugin.getStats();
const statsBar = container.createEl("div", { cls: "focus-task-stats-bar" }); const statsBar = container.createEl("div", { cls: "immerse-stats-bar" });
const statItems = [ const statItems = [
{ label: "Pending", value: stats.pendingCount.toString(), icon: "\u{1F4CB}" }, { label: "Pending", value: stats.pendingCount.toString(), icon: "\u{1F4CB}" },
{ label: "Done Today", value: stats.completedToday.toString(), icon: "\u2705" }, { label: "Done Today", value: stats.completedToday.toString(), icon: "\u2705" },
@@ -304,35 +304,35 @@ var FocusTaskView = class extends import_obsidian2.ItemView {
{ label: "Streak", value: `${stats.streak} days`, icon: "\u{1F525}" } { label: "Streak", value: `${stats.streak} days`, icon: "\u{1F525}" }
]; ];
statItems.forEach((stat) => { statItems.forEach((stat) => {
const item = statsBar.createEl("div", { cls: "focus-task-stat-item" }); const item = statsBar.createEl("div", { cls: "immerse-stat-item" });
item.createEl("div", { cls: "focus-task-stat-icon", text: stat.icon }); item.createEl("div", { cls: "immerse-stat-icon", text: stat.icon });
item.createEl("div", { cls: "focus-task-stat-value", text: stat.value }); item.createEl("div", { cls: "immerse-stat-value", text: stat.value });
item.createEl("div", { cls: "focus-task-stat-label", text: stat.label }); item.createEl("div", { cls: "immerse-stat-label", text: stat.label });
}); });
} }
renderActiveTask(container) { renderActiveTask(container) {
const activeSection = container.createEl("div", { cls: "focus-task-active-section" }); const activeSection = container.createEl("div", { cls: "immerse-active-section" });
if (this.plugin.activeTaskId) { if (this.plugin.activeTaskId) {
const task = this.plugin.data.tasks.find((t) => t.id === this.plugin.activeTaskId); const task = this.plugin.data.tasks.find((t) => t.id === this.plugin.activeTaskId);
if (task) { if (task) {
activeSection.addClass("focus-task-has-active"); activeSection.addClass("immerse-has-active");
const activeCard = activeSection.createEl("div", { cls: "focus-task-active-card" }); const activeCard = activeSection.createEl("div", { cls: "immerse-active-card" });
if (this.plugin.isBreakMode) { if (this.plugin.isBreakMode) {
activeCard.addClass("focus-task-break-card"); activeCard.addClass("immerse-break-card");
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: "focus-task-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"; const workLabel = this.plugin.currentTimerSeconds > 0 ? "\u{1F3AF} FOCUSING ON" : "\u{1F345} POMODORO COMPLETE";
activeCard.createEl("div", { cls: "focus-task-active-label", text: workLabel }); activeCard.createEl("div", { cls: "immerse-active-label", text: workLabel });
} }
activeCard.createEl("div", { cls: "focus-task-active-task-name", text: task.text }); activeCard.createEl("div", { cls: "immerse-active-task-name", text: task.text });
const timerDisplay = activeCard.createEl("div", { cls: "focus-task-timer-display" }); const timerDisplay = activeCard.createEl("div", { cls: "immerse-timer-display" });
this.timerTimeEl = timerDisplay.createEl("span", { this.timerTimeEl = timerDisplay.createEl("span", {
cls: "focus-task-timer-time", cls: "immerse-timer-time",
text: this.plugin.formatTime(this.plugin.currentTimerSeconds) text: this.plugin.formatTime(this.plugin.currentTimerSeconds)
}); });
const progressWrap = activeCard.createEl("div", { cls: "focus-task-progress-wrap" }); const progressWrap = activeCard.createEl("div", { cls: "immerse-progress-wrap" });
this.progressBarEl = progressWrap.createEl("div", { cls: "focus-task-progress-bar" }); this.progressBarEl = progressWrap.createEl("div", { cls: "immerse-progress-bar" });
let progressPercent = 0; let progressPercent = 0;
if (this.plugin.isBreakMode) { if (this.plugin.isBreakMode) {
const breakDuration = this.plugin.pomodoroCount % this.plugin.settings.longBreakInterval === 0 ? this.plugin.settings.longBreakMinutes * 60 : this.plugin.settings.pomodoroBreakMinutes * 60; const breakDuration = this.plugin.pomodoroCount % this.plugin.settings.longBreakInterval === 0 ? this.plugin.settings.longBreakMinutes * 60 : this.plugin.settings.pomodoroBreakMinutes * 60;
@@ -343,38 +343,38 @@ var FocusTaskView = class extends import_obsidian2.ItemView {
} }
this.progressBarEl.style.width = `${Math.min(Math.max(progressPercent, 0), 100)}%`; this.progressBarEl.style.width = `${Math.min(Math.max(progressPercent, 0), 100)}%`;
if (progressPercent >= 100) if (progressPercent >= 100)
this.progressBarEl.addClass("focus-task-overtime"); this.progressBarEl.addClass("immerse-overtime");
if (!this.plugin.isBreakMode) { if (!this.plugin.isBreakMode) {
const timeInfo = activeCard.createEl("div", { cls: "focus-task-time-info" }); const timeInfo = activeCard.createEl("div", { cls: "immerse-time-info" });
timeInfo.createEl("span", { text: `Est: ${this.plugin.formatTimeHuman(task.estimatedMinutes)}` }); timeInfo.createEl("span", { text: `Est: ${this.plugin.formatTimeHuman(task.estimatedMinutes)}` });
this.actualTimeEl = timeInfo.createEl("span", { text: `Actual: ${this.plugin.formatTimeHuman(task.actualMinutes)}` }); this.actualTimeEl = timeInfo.createEl("span", { text: `Actual: ${this.plugin.formatTimeHuman(task.actualMinutes)}` });
} }
const controls = activeCard.createEl("div", { cls: "focus-task-active-controls" }); const controls = activeCard.createEl("div", { cls: "immerse-active-controls" });
if (this.plugin.isBreakMode) { if (this.plugin.isBreakMode) {
if (this.plugin.currentTimerSeconds > 0) { if (this.plugin.currentTimerSeconds > 0) {
this.pauseBtnEl = controls.createEl("button", { cls: "focus-task-btn focus-task-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());
const skipBreakBtn = controls.createEl("button", { cls: "focus-task-btn focus-task-btn-primary" }); const skipBreakBtn = controls.createEl("button", { cls: "immerse-btn immerse-btn-primary" });
skipBreakBtn.innerHTML = "\u23ED Skip Break"; skipBreakBtn.innerHTML = "\u23ED Skip Break";
skipBreakBtn.addEventListener("click", () => { skipBreakBtn.addEventListener("click", () => {
this.plugin.isBreakMode = false; this.plugin.isBreakMode = false;
this.plugin.startPomodoro(task.id); this.plugin.startPomodoro(task.id);
}); });
const stopBtn = controls.createEl("button", { cls: "focus-task-btn focus-task-btn-danger" }); const stopBtn = controls.createEl("button", { cls: "immerse-btn immerse-btn-danger" });
stopBtn.innerHTML = "\u2715 Stop"; stopBtn.innerHTML = "\u2715 Stop";
stopBtn.addEventListener("click", () => { stopBtn.addEventListener("click", () => {
this.plugin.isBreakMode = false; this.plugin.isBreakMode = false;
this.plugin.stopTimer(); this.plugin.stopTimer();
}); });
} else { } else {
const resumeWorkBtn = controls.createEl("button", { cls: "focus-task-btn focus-task-btn-success" }); const resumeWorkBtn = controls.createEl("button", { cls: "immerse-btn immerse-btn-success" });
resumeWorkBtn.innerHTML = "\u25B6 Resume Work"; resumeWorkBtn.innerHTML = "\u25B6 Resume Work";
resumeWorkBtn.addEventListener("click", () => { resumeWorkBtn.addEventListener("click", () => {
this.plugin.isBreakMode = false; this.plugin.isBreakMode = false;
this.plugin.startPomodoro(task.id); this.plugin.startPomodoro(task.id);
}); });
const stopBtn = controls.createEl("button", { cls: "focus-task-btn focus-task-btn-danger" }); const stopBtn = controls.createEl("button", { cls: "immerse-btn immerse-btn-danger" });
stopBtn.innerHTML = "\u2715 Stop"; stopBtn.innerHTML = "\u2715 Stop";
stopBtn.addEventListener("click", () => { stopBtn.addEventListener("click", () => {
this.plugin.isBreakMode = false; this.plugin.isBreakMode = false;
@@ -383,41 +383,41 @@ var FocusTaskView = class extends import_obsidian2.ItemView {
} }
} else { } else {
if (this.plugin.currentTimerSeconds > 0) { if (this.plugin.currentTimerSeconds > 0) {
this.pauseBtnEl = controls.createEl("button", { cls: "focus-task-btn focus-task-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());
const completeBtn = controls.createEl("button", { cls: "focus-task-btn focus-task-btn-success" }); const completeBtn = controls.createEl("button", { cls: "immerse-btn immerse-btn-success" });
completeBtn.innerHTML = "\u2713 Complete"; completeBtn.innerHTML = "\u2713 Complete";
completeBtn.addEventListener("click", () => this.plugin.completeTask(task.id)); completeBtn.addEventListener("click", () => this.plugin.completeTask(task.id));
const stopBtn = controls.createEl("button", { cls: "focus-task-btn focus-task-btn-danger" }); const stopBtn = controls.createEl("button", { cls: "immerse-btn immerse-btn-danger" });
stopBtn.innerHTML = "\u2715 Stop"; stopBtn.innerHTML = "\u2715 Stop";
stopBtn.addEventListener("click", () => this.plugin.stopTimer()); stopBtn.addEventListener("click", () => this.plugin.stopTimer());
} else { } else {
const startBreakBtn = controls.createEl("button", { cls: "focus-task-btn focus-task-btn-secondary" }); const startBreakBtn = controls.createEl("button", { cls: "immerse-btn immerse-btn-secondary" });
startBreakBtn.innerHTML = "\u2615 Start Break"; startBreakBtn.innerHTML = "\u2615 Start Break";
startBreakBtn.addEventListener("click", () => this.plugin.startBreak()); startBreakBtn.addEventListener("click", () => this.plugin.startBreak());
const continueBtn = controls.createEl("button", { cls: "focus-task-btn focus-task-btn-primary" }); const continueBtn = controls.createEl("button", { cls: "immerse-btn immerse-btn-primary" });
continueBtn.innerHTML = "\u25B6 Continue Working"; continueBtn.innerHTML = "\u25B6 Continue Working";
continueBtn.addEventListener("click", () => this.plugin.startPomodoro(task.id)); continueBtn.addEventListener("click", () => this.plugin.startPomodoro(task.id));
const completeBtn = controls.createEl("button", { cls: "focus-task-btn focus-task-btn-success" }); const completeBtn = controls.createEl("button", { cls: "immerse-btn immerse-btn-success" });
completeBtn.innerHTML = "\u2713 Complete"; completeBtn.innerHTML = "\u2713 Complete";
completeBtn.addEventListener("click", () => this.plugin.completeTask(task.id)); completeBtn.addEventListener("click", () => this.plugin.completeTask(task.id));
const stopBtn = controls.createEl("button", { cls: "focus-task-btn focus-task-btn-danger" }); const stopBtn = controls.createEl("button", { cls: "immerse-btn immerse-btn-danger" });
stopBtn.innerHTML = "\u2715 Stop"; stopBtn.innerHTML = "\u2715 Stop";
stopBtn.addEventListener("click", () => this.plugin.stopTimer()); stopBtn.addEventListener("click", () => this.plugin.stopTimer());
} }
} }
} }
} else { } else {
const startPrompt = activeSection.createEl("div", { cls: "focus-task-start-prompt" }); const startPrompt = activeSection.createEl("div", { cls: "immerse-start-prompt" });
startPrompt.createEl("div", { cls: "focus-task-prompt-icon", text: "\u26A1" }); startPrompt.createEl("div", { cls: "immerse-prompt-icon", text: "\u26A1" });
startPrompt.createEl("div", { cls: "focus-task-prompt-text", text: "Ready to focus?" }); startPrompt.createEl("div", { cls: "immerse-prompt-text", text: "Ready to focus?" });
startPrompt.createEl("div", { cls: "focus-task-prompt-hint", text: "Click \u25B6 on a task to start a Pomodoro session" }); startPrompt.createEl("div", { cls: "immerse-prompt-hint", text: "Click \u25B6 on a task to start a Pomodoro session" });
} }
} }
renderTaskList(container) { renderTaskList(container) {
const listSection = container.createEl("div", { cls: "focus-task-list-section" }); const listSection = container.createEl("div", { cls: "immerse-list-section" });
const filters = listSection.createEl("div", { cls: "focus-task-filters" }); const filters = listSection.createEl("div", { cls: "immerse-filters" });
const filterOptions = [ const filterOptions = [
{ id: "all", label: "All Tasks" }, { id: "all", label: "All Tasks" },
{ id: "today", label: "Today" }, { id: "today", label: "Today" },
@@ -426,7 +426,7 @@ var FocusTaskView = class extends import_obsidian2.ItemView {
]; ];
filterOptions.forEach((opt) => { filterOptions.forEach((opt) => {
const btn = filters.createEl("button", { const btn = filters.createEl("button", {
cls: `focus-task-filter-btn ${this.currentFilter === opt.id ? "active" : ""}`, cls: `immerse-filter-btn ${this.currentFilter === opt.id ? "active" : ""}`,
text: opt.label text: opt.label
}); });
btn.addEventListener("click", () => { btn.addEventListener("click", () => {
@@ -434,7 +434,7 @@ var FocusTaskView = class extends import_obsidian2.ItemView {
this.refresh(); this.refresh();
}); });
}); });
const taskList = listSection.createEl("div", { cls: "focus-task-task-list" }); const taskList = listSection.createEl("div", { cls: "immerse-task-list" });
let tasks = this.plugin.data.tasks; let tasks = this.plugin.data.tasks;
if (this.currentFilter === "today") { if (this.currentFilter === "today") {
tasks = this.plugin.getTodaysTasks(); tasks = this.plugin.getTodaysTasks();
@@ -449,10 +449,10 @@ var FocusTaskView = class extends import_obsidian2.ItemView {
return b.createdAt - a.createdAt; return b.createdAt - a.createdAt;
}); });
if (tasks.length === 0) { if (tasks.length === 0) {
const emptyState = taskList.createEl("div", { cls: "focus-task-empty-state" }); const emptyState = taskList.createEl("div", { cls: "immerse-empty-state" });
emptyState.createEl("div", { cls: "focus-task-empty-icon", text: "\u{1F4DD}" }); emptyState.createEl("div", { cls: "immerse-empty-icon", text: "\u{1F4DD}" });
emptyState.createEl("div", { cls: "focus-task-empty-text", text: "No tasks yet" }); emptyState.createEl("div", { cls: "immerse-empty-text", text: "No tasks yet" });
emptyState.createEl("div", { cls: "focus-task-empty-hint", text: "Add a task to get started!" }); emptyState.createEl("div", { cls: "immerse-empty-hint", text: "Add a task to get started!" });
} else { } else {
tasks.forEach((task) => this.renderTaskItem(taskList, task)); tasks.forEach((task) => this.renderTaskItem(taskList, task));
} }
@@ -460,9 +460,9 @@ var FocusTaskView = class extends import_obsidian2.ItemView {
renderTaskItem(container, task) { renderTaskItem(container, task) {
const list = this.plugin.settings.lists.find((l) => l.id === task.list); const list = this.plugin.settings.lists.find((l) => l.id === task.list);
const taskEl = container.createEl("div", { const taskEl = container.createEl("div", {
cls: `focus-task-task-item ${task.completed ? "completed" : ""} ${task.isActive ? "active" : ""}` cls: `immerse-task-item ${task.completed ? "completed" : ""} ${task.isActive ? "active" : ""}`
}); });
const checkbox = taskEl.createEl("div", { cls: "focus-task-checkbox" }); const checkbox = taskEl.createEl("div", { cls: "immerse-checkbox" });
checkbox.innerHTML = task.completed ? "\u2713" : ""; checkbox.innerHTML = task.completed ? "\u2713" : "";
checkbox.style.borderColor = (list == null ? void 0 : list.color) || "#6366f1"; checkbox.style.borderColor = (list == null ? void 0 : list.color) || "#6366f1";
if (task.completed) { if (task.completed) {
@@ -475,48 +475,48 @@ var FocusTaskView = class extends import_obsidian2.ItemView {
this.plugin.completeTask(task.id); this.plugin.completeTask(task.id);
} }
}); });
const content = taskEl.createEl("div", { cls: "focus-task-task-content" }); const content = taskEl.createEl("div", { cls: "immerse-task-content" });
const taskHeader = content.createEl("div", { cls: "focus-task-task-header" }); const taskHeader = content.createEl("div", { cls: "immerse-task-header" });
taskHeader.createEl("span", { cls: "focus-task-task-text", text: task.text }); taskHeader.createEl("span", { cls: "immerse-task-text", text: task.text });
if (list) { if (list) {
const listBadge = taskHeader.createEl("span", { const listBadge = taskHeader.createEl("span", {
cls: "focus-task-list-badge", cls: "immerse-list-badge",
text: `${list.icon} ${list.name}` text: `${list.icon} ${list.name}`
}); });
listBadge.style.backgroundColor = list.color + "20"; listBadge.style.backgroundColor = list.color + "20";
listBadge.style.color = list.color; listBadge.style.color = list.color;
} }
const taskMeta = content.createEl("div", { cls: "focus-task-task-meta" }); const taskMeta = content.createEl("div", { cls: "immerse-task-meta" });
taskMeta.createEl("span", { text: `Est: ${this.plugin.formatTimeHuman(task.estimatedMinutes)}` }); taskMeta.createEl("span", { text: `Est: ${this.plugin.formatTimeHuman(task.estimatedMinutes)}` });
if (task.actualMinutes > 0) { if (task.actualMinutes > 0) {
const actualSpan = taskMeta.createEl("span"); const actualSpan = taskMeta.createEl("span");
actualSpan.setText(`Actual: ${this.plugin.formatTimeHuman(task.actualMinutes)}`); actualSpan.setText(`Actual: ${this.plugin.formatTimeHuman(task.actualMinutes)}`);
if (task.actualMinutes > task.estimatedMinutes) { if (task.actualMinutes > task.estimatedMinutes) {
actualSpan.addClass("focus-task-overtime-text"); actualSpan.addClass("immerse-overtime-text");
} }
} }
const actions = taskEl.createEl("div", { cls: "focus-task-task-actions" }); const actions = taskEl.createEl("div", { cls: "immerse-task-actions" });
if (!task.completed) { if (!task.completed) {
const startBtn = actions.createEl("button", { cls: "focus-task-task-btn", attr: { "aria-label": "Start Pomodoro" } }); const startBtn = actions.createEl("button", { cls: "immerse-task-btn", attr: { "aria-label": "Start Pomodoro" } });
startBtn.innerHTML = "\u25B6"; startBtn.innerHTML = "\u25B6";
startBtn.addEventListener("click", (e) => { startBtn.addEventListener("click", (e) => {
e.stopPropagation(); e.stopPropagation();
this.plugin.startPomodoro(task.id); this.plugin.startPomodoro(task.id);
}); });
const stopwatchBtn = actions.createEl("button", { cls: "focus-task-task-btn", attr: { "aria-label": "Start Stopwatch" } }); const stopwatchBtn = actions.createEl("button", { cls: "immerse-task-btn", attr: { "aria-label": "Start Stopwatch" } });
stopwatchBtn.innerHTML = "\u23F1"; stopwatchBtn.innerHTML = "\u23F1";
stopwatchBtn.addEventListener("click", (e) => { stopwatchBtn.addEventListener("click", (e) => {
e.stopPropagation(); e.stopPropagation();
this.plugin.startTimer(task.id); this.plugin.startTimer(task.id);
}); });
} }
const editBtn = actions.createEl("button", { cls: "focus-task-task-btn", attr: { "aria-label": "Edit" } }); const editBtn = actions.createEl("button", { cls: "immerse-task-btn", attr: { "aria-label": "Edit" } });
editBtn.innerHTML = "\u270F\uFE0F"; editBtn.innerHTML = "\u270F\uFE0F";
editBtn.addEventListener("click", (e) => { editBtn.addEventListener("click", (e) => {
e.stopPropagation(); e.stopPropagation();
new EditTaskModal(this.app, this.plugin, task).open(); new EditTaskModal(this.app, this.plugin, task).open();
}); });
const deleteBtn = actions.createEl("button", { cls: "focus-task-task-btn focus-task-delete-btn", attr: { "aria-label": "Delete" } }); const deleteBtn = actions.createEl("button", { cls: "immerse-task-btn immerse-delete-btn", attr: { "aria-label": "Delete" } });
deleteBtn.innerHTML = "\u{1F5D1}"; deleteBtn.innerHTML = "\u{1F5D1}";
deleteBtn.addEventListener("click", (e) => { deleteBtn.addEventListener("click", (e) => {
e.stopPropagation(); e.stopPropagation();
@@ -526,7 +526,7 @@ var FocusTaskView = class extends import_obsidian2.ItemView {
}; };
// src/main.ts // src/main.ts
var FocusTaskPlugin = class extends import_obsidian3.Plugin { var ImmersePlugin = class extends import_obsidian3.Plugin {
constructor() { constructor() {
super(...arguments); super(...arguments);
// Timer state // Timer state
@@ -554,15 +554,15 @@ var FocusTaskPlugin = class extends import_obsidian3.Plugin {
} }
}); });
this.registerView( this.registerView(
VIEW_TYPE_FOCUS_TASK, VIEW_TYPE_IMMERSE,
(leaf) => new FocusTaskView(leaf, this) (leaf) => new ImmerseView(leaf, this)
); );
this.addRibbonIcon("zap", "Open Focus Task", () => { this.addRibbonIcon("zap", "Open Immerse", () => {
this.activateView(); this.activateView();
}); });
this.addCommand({ this.addCommand({
id: "open-focus-task", id: "open-immerse",
name: "Open Focus Task Panel", name: "Open Immerse Panel",
callback: () => this.activateView() callback: () => this.activateView()
}); });
this.addCommand({ this.addCommand({
@@ -585,7 +585,7 @@ var FocusTaskPlugin = class extends import_obsidian3.Plugin {
name: "Complete Current Task", name: "Complete Current Task",
callback: () => this.completeActiveTask() callback: () => this.completeActiveTask()
}); });
this.addSettingTab(new FocusTaskSettingTab(this.app, this)); this.addSettingTab(new ImmerseSettingTab(this.app, this));
this.createStatusBar(); this.createStatusBar();
} }
onunload() { onunload() {
@@ -627,13 +627,13 @@ var FocusTaskPlugin = class extends import_obsidian3.Plugin {
async activateView() { async activateView() {
const { workspace } = this.app; const { workspace } = this.app;
let leaf = null; let leaf = null;
const leaves = workspace.getLeavesOfType(VIEW_TYPE_FOCUS_TASK); const leaves = workspace.getLeavesOfType(VIEW_TYPE_IMMERSE);
if (leaves.length > 0) { if (leaves.length > 0) {
leaf = leaves[0]; leaf = leaves[0];
} else { } else {
leaf = workspace.getRightLeaf(false); leaf = workspace.getRightLeaf(false);
if (leaf) { if (leaf) {
await leaf.setViewState({ type: VIEW_TYPE_FOCUS_TASK, active: true }); await leaf.setViewState({ type: VIEW_TYPE_IMMERSE, active: true });
} }
} }
if (leaf) { if (leaf) {
@@ -931,7 +931,7 @@ var FocusTaskPlugin = class extends import_obsidian3.Plugin {
this.statusBarEl.setText(`\u26A1 ${icon} ${timeStr} - ${taskName}${task && task.text.length > 20 ? "..." : ""}`); this.statusBarEl.setText(`\u26A1 ${icon} ${timeStr} - ${taskName}${task && task.text.length > 20 ? "..." : ""}`);
this.statusBarEl.addClass("focus-task-status-active"); this.statusBarEl.addClass("focus-task-status-active");
} else { } else {
this.statusBarEl.setText("\u26A1 Focus Task"); this.statusBarEl.setText("\u26A1 Immerse");
this.statusBarEl.removeClass("focus-task-status-active"); this.statusBarEl.removeClass("focus-task-status-active");
} }
} }
@@ -1109,18 +1109,18 @@ var FocusTaskPlugin = class extends import_obsidian3.Plugin {
return mins > 0 ? `${hours}hr ${mins}min` : `${hours}hr`; return mins > 0 ? `${hours}hr ${mins}min` : `${hours}hr`;
} }
refreshView() { refreshView() {
const leaves = this.app.workspace.getLeavesOfType(VIEW_TYPE_FOCUS_TASK); const leaves = this.app.workspace.getLeavesOfType(VIEW_TYPE_IMMERSE);
leaves.forEach((leaf) => { leaves.forEach((leaf) => {
if (leaf.view instanceof FocusTaskView) { if (leaf.view instanceof ImmerseView) {
leaf.view.refresh(); leaf.view.refresh();
} }
}); });
} }
// Light refresh - only updates timer display without rebuilding DOM // Light refresh - only updates timer display without rebuilding DOM
updateTimerDisplay() { updateTimerDisplay() {
const leaves = this.app.workspace.getLeavesOfType(VIEW_TYPE_FOCUS_TASK); const leaves = this.app.workspace.getLeavesOfType(VIEW_TYPE_IMMERSE);
leaves.forEach((leaf) => { leaves.forEach((leaf) => {
if (leaf.view instanceof FocusTaskView) { if (leaf.view instanceof ImmerseView) {
leaf.view.updateTimerDisplay(); leaf.view.updateTimerDisplay();
} }
}); });
@@ -1157,7 +1157,7 @@ var FocusTaskPlugin = class extends import_obsidian3.Plugin {
}; };
} }
}; };
var FocusTaskSettingTab = class extends import_obsidian3.PluginSettingTab { var ImmerseSettingTab = class extends import_obsidian3.PluginSettingTab {
constructor(app, plugin) { constructor(app, plugin) {
super(app, plugin); super(app, plugin);
this.plugin = plugin; this.plugin = plugin;
@@ -1165,7 +1165,7 @@ var FocusTaskSettingTab = class extends import_obsidian3.PluginSettingTab {
display() { display() {
const { containerEl } = this; const { containerEl } = this;
containerEl.empty(); containerEl.empty();
containerEl.createEl("h1", { text: "\u26A1 Focus Task Settings" }); containerEl.createEl("h1", { text: "\u26A1 Immerse Settings" });
containerEl.createEl("h2", { text: "\u{1F345} Pomodoro Timer" }); containerEl.createEl("h2", { text: "\u{1F345} Pomodoro Timer" });
new import_obsidian3.Setting(containerEl).setName("Work Duration").setDesc("Length of each work session in minutes").addSlider((slider) => slider.setLimits(5, 60, 5).setValue(this.plugin.settings.pomodoroWorkMinutes).setDynamicTooltip().onChange(async (value) => { new import_obsidian3.Setting(containerEl).setName("Work Duration").setDesc("Length of each work session in minutes").addSlider((slider) => slider.setLimits(5, 60, 5).setValue(this.plugin.settings.pomodoroWorkMinutes).setDynamicTooltip().onChange(async (value) => {
this.plugin.settings.pomodoroWorkMinutes = value; this.plugin.settings.pomodoroWorkMinutes = value;
@@ -1243,14 +1243,14 @@ var FocusTaskSettingTab = class extends import_obsidian3.PluginSettingTab {
this.display(); this.display();
})); }));
containerEl.createEl("h2", { text: "\u{1F4D6} About" }); containerEl.createEl("h2", { text: "\u{1F4D6} About" });
const aboutDiv = containerEl.createDiv({ cls: "focus-task-about" }); const aboutDiv = containerEl.createDiv({ cls: "immerse-about" });
aboutDiv.innerHTML = ` aboutDiv.innerHTML = `
<p><strong>Focus Task</strong> is heavily inspired by <a href="https://www.blitzit.app/">Blitzit</a>, <p><strong>Immerse</strong> is heavily inspired by <a href="https://www.blitzit.app/">Blitzit</a>,
a fantastic productivity app that combines task management with focused time tracking.</p> a fantastic productivity app that combines task management with focused time tracking.</p>
<p>This plugin brings similar functionality directly into Obsidian, allowing you to manage tasks, <p>This plugin brings similar functionality directly into Obsidian, allowing you to manage tasks,
use the Pomodoro technique, and track your productivity without leaving your notes.</p> use the Pomodoro technique, and track your productivity without leaving your notes.</p>
<p> <p>
<a href="https://git.cribdev.com/crib/focus-task">Source Code</a> <a href="https://git.cribdev.com/crib/immerse">Source Code</a>
</p> </p>
`; `;
} }

View File

@@ -1,7 +1,7 @@
{ {
"id": "focus-task", "id": "immerse",
"name": "Focus Task", "name": "Immerse",
"version": "1.0.8", "version": "1.0.9",
"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",

View File

@@ -1,6 +1,6 @@
{ {
"name": "focus-task", "name": "immerse",
"version": "1.0.8", "version": "1.0.9",
"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": {
@@ -22,7 +22,7 @@
"license": "MIT", "license": "MIT",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://git.cribdev.com/crib/focus-task" "url": "https://git.cribdev.com/crib/immerse"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^16.11.6", "@types/node": "^16.11.6",

View File

@@ -14,18 +14,18 @@ import {
FocusTaskData, FocusTaskData,
DEFAULT_SETTINGS, DEFAULT_SETTINGS,
DEFAULT_DATA, DEFAULT_DATA,
VIEW_TYPE_FOCUS_TASK, VIEW_TYPE_IMMERSE,
CELEBRATION_MESSAGES, CELEBRATION_MESSAGES,
EARLY_FINISH_MESSAGES, EARLY_FINISH_MESSAGES,
OVERTIME_MESSAGES, OVERTIME_MESSAGES,
} from './types'; } from './types';
import { FocusTaskView } from './view'; import { ImmerseView } from './view';
import { QuickAddTaskModal } from './modals'; import { QuickAddTaskModal } from './modals';
// ============ Main Plugin Class ============ // ============ Main Plugin Class ============
export default class FocusTaskPlugin extends Plugin { export default class ImmersePlugin extends Plugin {
settings: FocusTaskSettings; settings: FocusTaskSettings;
data: FocusTaskData; data: FocusTaskData;
@@ -63,19 +63,19 @@ export default class FocusTaskPlugin extends Plugin {
// Register the main view // Register the main view
this.registerView( this.registerView(
VIEW_TYPE_FOCUS_TASK, VIEW_TYPE_IMMERSE,
(leaf) => new FocusTaskView(leaf, this) (leaf) => new ImmerseView(leaf, this)
); );
// Add ribbon icon // Add ribbon icon
this.addRibbonIcon('zap', 'Open Focus Task', () => { this.addRibbonIcon('zap', 'Open Immerse', () => {
this.activateView(); this.activateView();
}); });
// Add commands // Add commands
this.addCommand({ this.addCommand({
id: 'open-focus-task', id: 'open-immerse',
name: 'Open Focus Task Panel', name: 'Open Immerse Panel',
callback: () => this.activateView(), callback: () => this.activateView(),
}); });
@@ -104,7 +104,7 @@ export default class FocusTaskPlugin extends Plugin {
}); });
// Add settings tab // Add settings tab
this.addSettingTab(new FocusTaskSettingTab(this.app, this)); this.addSettingTab(new ImmerseSettingTab(this.app, this));
// Create status bar timer // Create status bar timer
this.createStatusBar(); this.createStatusBar();
@@ -165,14 +165,14 @@ export default class FocusTaskPlugin extends Plugin {
const { workspace } = this.app; const { workspace } = this.app;
let leaf: WorkspaceLeaf | null = null; let leaf: WorkspaceLeaf | null = null;
const leaves = workspace.getLeavesOfType(VIEW_TYPE_FOCUS_TASK); const leaves = workspace.getLeavesOfType(VIEW_TYPE_IMMERSE);
if (leaves.length > 0) { if (leaves.length > 0) {
leaf = leaves[0]; leaf = leaves[0];
} else { } else {
leaf = workspace.getRightLeaf(false); leaf = workspace.getRightLeaf(false);
if (leaf) { if (leaf) {
await leaf.setViewState({ type: VIEW_TYPE_FOCUS_TASK, active: true }); await leaf.setViewState({ type: VIEW_TYPE_IMMERSE, active: true });
} }
} }
@@ -599,7 +599,7 @@ export default class FocusTaskPlugin extends Plugin {
this.statusBarEl.setText(`${icon} ${timeStr} - ${taskName}${task && task.text.length > 20 ? '...' : ''}`); this.statusBarEl.setText(`${icon} ${timeStr} - ${taskName}${task && task.text.length > 20 ? '...' : ''}`);
this.statusBarEl.addClass('focus-task-status-active'); this.statusBarEl.addClass('focus-task-status-active');
} else { } else {
this.statusBarEl.setText('⚡ Focus Task'); this.statusBarEl.setText('⚡ Immerse');
this.statusBarEl.removeClass('focus-task-status-active'); this.statusBarEl.removeClass('focus-task-status-active');
} }
} }
@@ -844,9 +844,9 @@ export default class FocusTaskPlugin extends Plugin {
} }
refreshView() { refreshView() {
const leaves = this.app.workspace.getLeavesOfType(VIEW_TYPE_FOCUS_TASK); const leaves = this.app.workspace.getLeavesOfType(VIEW_TYPE_IMMERSE);
leaves.forEach(leaf => { leaves.forEach(leaf => {
if (leaf.view instanceof FocusTaskView) { if (leaf.view instanceof ImmerseView) {
leaf.view.refresh(); leaf.view.refresh();
} }
}); });
@@ -854,9 +854,9 @@ export default class FocusTaskPlugin extends Plugin {
// Light refresh - only updates timer display without rebuilding DOM // Light refresh - only updates timer display without rebuilding DOM
updateTimerDisplay() { updateTimerDisplay() {
const leaves = this.app.workspace.getLeavesOfType(VIEW_TYPE_FOCUS_TASK); const leaves = this.app.workspace.getLeavesOfType(VIEW_TYPE_IMMERSE);
leaves.forEach(leaf => { leaves.forEach(leaf => {
if (leaf.view instanceof FocusTaskView) { if (leaf.view instanceof ImmerseView) {
leaf.view.updateTimerDisplay(); leaf.view.updateTimerDisplay();
} }
}); });
@@ -901,10 +901,10 @@ export default class FocusTaskPlugin extends Plugin {
// ============ Settings Tab ============ // ============ Settings Tab ============
class FocusTaskSettingTab extends PluginSettingTab { class ImmerseSettingTab extends PluginSettingTab {
plugin: FocusTaskPlugin; plugin: ImmersePlugin;
constructor(app: App, plugin: FocusTaskPlugin) { constructor(app: App, plugin: ImmersePlugin) {
super(app, plugin); super(app, plugin);
this.plugin = plugin; this.plugin = plugin;
} }
@@ -913,7 +913,7 @@ class FocusTaskSettingTab extends PluginSettingTab {
const { containerEl } = this; const { containerEl } = this;
containerEl.empty(); containerEl.empty();
containerEl.createEl('h1', { text: '⚡ Focus Task Settings' }); containerEl.createEl('h1', { text: '⚡ Immerse Settings' });
// Pomodoro Settings // Pomodoro Settings
containerEl.createEl('h2', { text: '🍅 Pomodoro Timer' }); containerEl.createEl('h2', { text: '🍅 Pomodoro Timer' });
@@ -1089,14 +1089,14 @@ class FocusTaskSettingTab extends PluginSettingTab {
// About section // About section
containerEl.createEl('h2', { text: '📖 About' }); containerEl.createEl('h2', { text: '📖 About' });
const aboutDiv = containerEl.createDiv({ cls: 'focus-task-about' }); const aboutDiv = containerEl.createDiv({ cls: 'immerse-about' });
aboutDiv.innerHTML = ` aboutDiv.innerHTML = `
<p><strong>Focus Task</strong> is heavily inspired by <a href="https://www.blitzit.app/">Blitzit</a>, <p><strong>Immerse</strong> is heavily inspired by <a href="https://www.blitzit.app/">Blitzit</a>,
a fantastic productivity app that combines task management with focused time tracking.</p> a fantastic productivity app that combines task management with focused time tracking.</p>
<p>This plugin brings similar functionality directly into Obsidian, allowing you to manage tasks, <p>This plugin brings similar functionality directly into Obsidian, allowing you to manage tasks,
use the Pomodoro technique, and track your productivity without leaving your notes.</p> use the Pomodoro technique, and track your productivity without leaving your notes.</p>
<p> <p>
<a href="https://git.cribdev.com/crib/focus-task">Source Code</a> <a href="https://git.cribdev.com/crib/immerse">Source Code</a>
</p> </p>
`; `;
} }

View File

@@ -6,17 +6,17 @@ import {
} from 'obsidian'; } from 'obsidian';
import { FocusTask } from './types'; import { FocusTask } from './types';
import FocusTaskPlugin from './main'; import ImmersePlugin from './main';
// ============ Quick Add Task Modal ============ // ============ Quick Add Task Modal ============
export class QuickAddTaskModal extends Modal { export class QuickAddTaskModal extends Modal {
plugin: FocusTaskPlugin; plugin: ImmersePlugin;
taskText: string = ''; taskText: string = '';
estimatedMinutes: number; estimatedMinutes: number;
selectedList: string = 'work'; selectedList: string = 'work';
constructor(app: App, plugin: FocusTaskPlugin) { constructor(app: App, plugin: ImmersePlugin) {
super(app); super(app);
this.plugin = plugin; this.plugin = plugin;
this.estimatedMinutes = plugin.settings.defaultEstimateMinutes; this.estimatedMinutes = plugin.settings.defaultEstimateMinutes;
@@ -27,7 +27,7 @@ export class QuickAddTaskModal extends Modal {
onOpen() { onOpen() {
const { contentEl } = this; const { contentEl } = this;
contentEl.addClass('focus-task-modal'); contentEl.addClass('immerse-modal');
contentEl.createEl('h2', { text: '⚡ Add New Task' }); contentEl.createEl('h2', { text: '⚡ Add New Task' });
@@ -83,12 +83,12 @@ export class QuickAddTaskModal extends Modal {
}); });
// Buttons // Buttons
const buttonContainer = contentEl.createEl('div', { cls: 'focus-task-modal-buttons' }); const buttonContainer = contentEl.createEl('div', { cls: 'immerse-modal-buttons' });
const cancelBtn = buttonContainer.createEl('button', { text: 'Cancel', cls: 'focus-task-btn' }); const cancelBtn = buttonContainer.createEl('button', { text: 'Cancel', cls: 'immerse-btn' });
cancelBtn.addEventListener('click', () => this.close()); cancelBtn.addEventListener('click', () => this.close());
const addBtn = buttonContainer.createEl('button', { text: 'Add Task', cls: 'focus-task-btn focus-task-btn-primary' }); const addBtn = buttonContainer.createEl('button', { text: 'Add Task', cls: 'immerse-btn immerse-btn-primary' });
addBtn.addEventListener('click', () => this.submitTask()); addBtn.addEventListener('click', () => this.submitTask());
} }
@@ -112,10 +112,10 @@ export class QuickAddTaskModal extends Modal {
// ============ Edit Task Modal ============ // ============ Edit Task Modal ============
export class EditTaskModal extends Modal { export class EditTaskModal extends Modal {
plugin: FocusTaskPlugin; plugin: ImmersePlugin;
task: FocusTask; task: FocusTask;
constructor(app: App, plugin: FocusTaskPlugin, task: FocusTask) { constructor(app: App, plugin: ImmersePlugin, task: FocusTask) {
super(app); super(app);
this.plugin = plugin; this.plugin = plugin;
this.task = { ...task }; this.task = { ...task };
@@ -123,7 +123,7 @@ export class EditTaskModal extends Modal {
onOpen() { onOpen() {
const { contentEl } = this; const { contentEl } = this;
contentEl.addClass('focus-task-modal'); contentEl.addClass('immerse-modal');
contentEl.createEl('h2', { text: '✏️ Edit Task' }); contentEl.createEl('h2', { text: '✏️ Edit Task' });
@@ -184,12 +184,12 @@ export class EditTaskModal extends Modal {
.setDesc(`You've worked on this task for ${this.plugin.formatTimeHuman(this.task.actualMinutes)}`); .setDesc(`You've worked on this task for ${this.plugin.formatTimeHuman(this.task.actualMinutes)}`);
} }
const buttonContainer = contentEl.createEl('div', { cls: 'focus-task-modal-buttons' }); const buttonContainer = contentEl.createEl('div', { cls: 'immerse-modal-buttons' });
const cancelBtn = buttonContainer.createEl('button', { text: 'Cancel', cls: 'focus-task-btn' }); const cancelBtn = buttonContainer.createEl('button', { text: 'Cancel', cls: 'immerse-btn' });
cancelBtn.addEventListener('click', () => this.close()); cancelBtn.addEventListener('click', () => this.close());
const saveBtn = buttonContainer.createEl('button', { text: 'Save', cls: 'focus-task-btn focus-task-btn-primary' }); const saveBtn = buttonContainer.createEl('button', { text: 'Save', cls: 'immerse-btn immerse-btn-primary' });
saveBtn.addEventListener('click', () => { saveBtn.addEventListener('click', () => {
this.plugin.updateTask(this.task.id, this.task); this.plugin.updateTask(this.task.id, this.task);
new Notice('✅ Task updated!'); new Notice('✅ Task updated!');

View File

@@ -73,7 +73,7 @@ export const DEFAULT_DATA: FocusTaskData = {
pomodorosCompleted: 0, pomodorosCompleted: 0,
}; };
export const VIEW_TYPE_FOCUS_TASK = 'focus-task-view'; export const VIEW_TYPE_IMMERSE = 'immerse-view';
// ============ Celebration Messages ============ // ============ Celebration Messages ============

View File

@@ -3,14 +3,14 @@ import {
WorkspaceLeaf, WorkspaceLeaf,
} from 'obsidian'; } from 'obsidian';
import { VIEW_TYPE_FOCUS_TASK, FocusTask } from './types'; import { VIEW_TYPE_IMMERSE, FocusTask } from './types';
import { QuickAddTaskModal, EditTaskModal } from './modals'; import { QuickAddTaskModal, EditTaskModal } from './modals';
import FocusTaskPlugin from './main'; import ImmersePlugin from './main';
// ============ Main View ============ // ============ Main View ============
export class FocusTaskView extends ItemView { export class ImmerseView extends ItemView {
plugin: FocusTaskPlugin; plugin: ImmersePlugin;
currentFilter: string = 'all'; currentFilter: string = 'all';
// References to elements that need frequent updates // References to elements that need frequent updates
@@ -19,17 +19,17 @@ export class FocusTaskView extends ItemView {
private actualTimeEl: HTMLElement | null = null; private actualTimeEl: HTMLElement | null = null;
private pauseBtnEl: HTMLElement | null = null; private pauseBtnEl: HTMLElement | null = null;
constructor(leaf: WorkspaceLeaf, plugin: FocusTaskPlugin) { constructor(leaf: WorkspaceLeaf, plugin: ImmersePlugin) {
super(leaf); super(leaf);
this.plugin = plugin; this.plugin = plugin;
} }
getViewType(): string { getViewType(): string {
return VIEW_TYPE_FOCUS_TASK; return VIEW_TYPE_IMMERSE;
} }
getDisplayText(): string { getDisplayText(): string {
return 'Focus Task'; return 'Immerse';
} }
getIcon(): string { getIcon(): string {
@@ -74,7 +74,7 @@ export class FocusTaskView extends ItemView {
refresh() { refresh() {
const container = this.containerEl.children[1]; const container = this.containerEl.children[1];
container.empty(); container.empty();
container.addClass('focus-task-container'); container.addClass('immerse-container');
// Reset element references // Reset element references
this.timerTimeEl = null; this.timerTimeEl = null;
@@ -96,18 +96,18 @@ export class FocusTaskView extends ItemView {
} }
renderHeader(container: Element) { renderHeader(container: Element) {
const header = container.createEl('div', { cls: 'focus-task-header' }); const header = container.createEl('div', { cls: 'immerse-header' });
const titleSection = header.createEl('div', { cls: 'focus-task-title-section' }); const titleSection = header.createEl('div', { cls: 'immerse-title-section' });
titleSection.createEl('h2', { text: '⚡ Focus Task', cls: 'focus-task-title' }); titleSection.createEl('h2', { text: '⚡ Immerse', cls: 'immerse-title' });
const today = new Date(); const today = new Date();
const dateStr = today.toLocaleDateString('en-US', { weekday: 'long', month: 'short', day: 'numeric' }); const dateStr = today.toLocaleDateString('en-US', { weekday: 'long', month: 'short', day: 'numeric' });
titleSection.createEl('div', { text: dateStr, cls: 'focus-task-date' }); titleSection.createEl('div', { text: dateStr, cls: 'immerse-date' });
const actions = header.createEl('div', { cls: 'focus-task-header-actions' }); const actions = header.createEl('div', { cls: 'immerse-header-actions' });
const addBtn = actions.createEl('button', { cls: 'focus-task-btn focus-task-btn-primary' }); const addBtn = actions.createEl('button', { cls: 'immerse-btn immerse-btn-primary' });
addBtn.innerHTML = '+ Add Task'; addBtn.innerHTML = '+ Add Task';
addBtn.addEventListener('click', () => { addBtn.addEventListener('click', () => {
new QuickAddTaskModal(this.app, this.plugin).open(); new QuickAddTaskModal(this.app, this.plugin).open();
@@ -116,7 +116,7 @@ export class FocusTaskView extends ItemView {
renderStatsBar(container: Element) { renderStatsBar(container: Element) {
const stats = this.plugin.getStats(); const stats = this.plugin.getStats();
const statsBar = container.createEl('div', { cls: 'focus-task-stats-bar' }); const statsBar = container.createEl('div', { cls: 'immerse-stats-bar' });
const statItems = [ const statItems = [
{ label: 'Pending', value: stats.pendingCount.toString(), icon: '📋' }, { label: 'Pending', value: stats.pendingCount.toString(), icon: '📋' },
@@ -126,44 +126,44 @@ export class FocusTaskView extends ItemView {
]; ];
statItems.forEach(stat => { statItems.forEach(stat => {
const item = statsBar.createEl('div', { cls: 'focus-task-stat-item' }); const item = statsBar.createEl('div', { cls: 'immerse-stat-item' });
item.createEl('div', { cls: 'focus-task-stat-icon', text: stat.icon }); item.createEl('div', { cls: 'immerse-stat-icon', text: stat.icon });
item.createEl('div', { cls: 'focus-task-stat-value', text: stat.value }); item.createEl('div', { cls: 'immerse-stat-value', text: stat.value });
item.createEl('div', { cls: 'focus-task-stat-label', text: stat.label }); item.createEl('div', { cls: 'immerse-stat-label', text: stat.label });
}); });
} }
renderActiveTask(container: Element) { renderActiveTask(container: Element) {
const activeSection = container.createEl('div', { cls: 'focus-task-active-section' }); const activeSection = container.createEl('div', { cls: 'immerse-active-section' });
if (this.plugin.activeTaskId) { if (this.plugin.activeTaskId) {
const task = this.plugin.data.tasks.find(t => t.id === this.plugin.activeTaskId); const task = this.plugin.data.tasks.find(t => t.id === this.plugin.activeTaskId);
if (task) { if (task) {
activeSection.addClass('focus-task-has-active'); activeSection.addClass('immerse-has-active');
const activeCard = activeSection.createEl('div', { cls: 'focus-task-active-card' }); const activeCard = activeSection.createEl('div', { cls: 'immerse-active-card' });
if (this.plugin.isBreakMode) { if (this.plugin.isBreakMode) {
activeCard.addClass('focus-task-break-card'); activeCard.addClass('immerse-break-card');
const breakLabel = this.plugin.currentTimerSeconds > 0 ? '☕ BREAK TIME' : '✨ BREAK COMPLETE'; const breakLabel = this.plugin.currentTimerSeconds > 0 ? '☕ BREAK TIME' : '✨ BREAK COMPLETE';
activeCard.createEl('div', { cls: 'focus-task-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'; const workLabel = this.plugin.currentTimerSeconds > 0 ? '🎯 FOCUSING ON' : '🍅 POMODORO COMPLETE';
activeCard.createEl('div', { cls: 'focus-task-active-label', text: workLabel }); activeCard.createEl('div', { cls: 'immerse-active-label', text: workLabel });
} }
activeCard.createEl('div', { cls: 'focus-task-active-task-name', text: task.text }); activeCard.createEl('div', { cls: 'immerse-active-task-name', text: task.text });
// Timer display - store reference for updates // Timer display - store reference for updates
const timerDisplay = activeCard.createEl('div', { cls: 'focus-task-timer-display' }); const timerDisplay = activeCard.createEl('div', { cls: 'immerse-timer-display' });
this.timerTimeEl = timerDisplay.createEl('span', { this.timerTimeEl = timerDisplay.createEl('span', {
cls: 'focus-task-timer-time', cls: 'immerse-timer-time',
text: this.plugin.formatTime(this.plugin.currentTimerSeconds) text: this.plugin.formatTime(this.plugin.currentTimerSeconds)
}); });
// Progress bar - store reference for updates // Progress bar - store reference for updates
const progressWrap = activeCard.createEl('div', { cls: 'focus-task-progress-wrap' }); const progressWrap = activeCard.createEl('div', { cls: 'immerse-progress-wrap' });
this.progressBarEl = progressWrap.createEl('div', { cls: 'focus-task-progress-bar' }); this.progressBarEl = progressWrap.createEl('div', { cls: 'immerse-progress-bar' });
let progressPercent = 0; let progressPercent = 0;
if (this.plugin.isBreakMode) { if (this.plugin.isBreakMode) {
@@ -177,34 +177,34 @@ export class FocusTaskView extends ItemView {
} }
this.progressBarEl.style.width = `${Math.min(Math.max(progressPercent, 0), 100)}%`; this.progressBarEl.style.width = `${Math.min(Math.max(progressPercent, 0), 100)}%`;
if (progressPercent >= 100) this.progressBarEl.addClass('focus-task-overtime'); if (progressPercent >= 100) this.progressBarEl.addClass('immerse-overtime');
// Time info - store reference for actual time updates // Time info - store reference for actual time updates
if (!this.plugin.isBreakMode) { if (!this.plugin.isBreakMode) {
const timeInfo = activeCard.createEl('div', { cls: 'focus-task-time-info' }); const timeInfo = activeCard.createEl('div', { cls: 'immerse-time-info' });
timeInfo.createEl('span', { text: `Est: ${this.plugin.formatTimeHuman(task.estimatedMinutes)}` }); timeInfo.createEl('span', { text: `Est: ${this.plugin.formatTimeHuman(task.estimatedMinutes)}` });
this.actualTimeEl = timeInfo.createEl('span', { text: `Actual: ${this.plugin.formatTimeHuman(task.actualMinutes)}` }); this.actualTimeEl = timeInfo.createEl('span', { text: `Actual: ${this.plugin.formatTimeHuman(task.actualMinutes)}` });
} }
// Controls // Controls
const controls = activeCard.createEl('div', { cls: 'focus-task-active-controls' }); const controls = activeCard.createEl('div', { cls: 'immerse-active-controls' });
if (this.plugin.isBreakMode) { if (this.plugin.isBreakMode) {
// Break mode controls // Break mode controls
if (this.plugin.currentTimerSeconds > 0) { if (this.plugin.currentTimerSeconds > 0) {
// Break is still counting down // Break is still counting down
this.pauseBtnEl = controls.createEl('button', { cls: 'focus-task-btn focus-task-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());
const skipBreakBtn = controls.createEl('button', { cls: 'focus-task-btn focus-task-btn-primary' }); const skipBreakBtn = controls.createEl('button', { cls: 'immerse-btn immerse-btn-primary' });
skipBreakBtn.innerHTML = '⏭ Skip Break'; skipBreakBtn.innerHTML = '⏭ Skip Break';
skipBreakBtn.addEventListener('click', () => { skipBreakBtn.addEventListener('click', () => {
this.plugin.isBreakMode = false; this.plugin.isBreakMode = false;
this.plugin.startPomodoro(task.id); this.plugin.startPomodoro(task.id);
}); });
const stopBtn = controls.createEl('button', { cls: 'focus-task-btn focus-task-btn-danger' }); const stopBtn = controls.createEl('button', { cls: 'immerse-btn immerse-btn-danger' });
stopBtn.innerHTML = '✕ Stop'; stopBtn.innerHTML = '✕ Stop';
stopBtn.addEventListener('click', () => { stopBtn.addEventListener('click', () => {
this.plugin.isBreakMode = false; this.plugin.isBreakMode = false;
@@ -212,14 +212,14 @@ export class FocusTaskView extends ItemView {
}); });
} else { } else {
// Break timer finished - show resume button // Break timer finished - show resume button
const resumeWorkBtn = controls.createEl('button', { cls: 'focus-task-btn focus-task-btn-success' }); const resumeWorkBtn = controls.createEl('button', { cls: 'immerse-btn immerse-btn-success' });
resumeWorkBtn.innerHTML = '▶ Resume Work'; resumeWorkBtn.innerHTML = '▶ Resume Work';
resumeWorkBtn.addEventListener('click', () => { resumeWorkBtn.addEventListener('click', () => {
this.plugin.isBreakMode = false; this.plugin.isBreakMode = false;
this.plugin.startPomodoro(task.id); this.plugin.startPomodoro(task.id);
}); });
const stopBtn = controls.createEl('button', { cls: 'focus-task-btn focus-task-btn-danger' }); const stopBtn = controls.createEl('button', { cls: 'immerse-btn immerse-btn-danger' });
stopBtn.innerHTML = '✕ Stop'; stopBtn.innerHTML = '✕ Stop';
stopBtn.addEventListener('click', () => { stopBtn.addEventListener('click', () => {
this.plugin.isBreakMode = false; this.plugin.isBreakMode = false;
@@ -230,32 +230,32 @@ export class FocusTaskView extends ItemView {
// Work mode controls // Work mode controls
if (this.plugin.currentTimerSeconds > 0) { if (this.plugin.currentTimerSeconds > 0) {
// Work session still running // Work session still running
this.pauseBtnEl = controls.createEl('button', { cls: 'focus-task-btn focus-task-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());
const completeBtn = controls.createEl('button', { cls: 'focus-task-btn focus-task-btn-success' }); const completeBtn = controls.createEl('button', { cls: 'immerse-btn immerse-btn-success' });
completeBtn.innerHTML = '✓ Complete'; completeBtn.innerHTML = '✓ Complete';
completeBtn.addEventListener('click', () => this.plugin.completeTask(task.id)); completeBtn.addEventListener('click', () => this.plugin.completeTask(task.id));
const stopBtn = controls.createEl('button', { cls: 'focus-task-btn focus-task-btn-danger' }); const stopBtn = controls.createEl('button', { cls: 'immerse-btn immerse-btn-danger' });
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 // Work session finished - show break and completion options
const startBreakBtn = controls.createEl('button', { cls: 'focus-task-btn focus-task-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());
const continueBtn = controls.createEl('button', { cls: 'focus-task-btn focus-task-btn-primary' }); const continueBtn = controls.createEl('button', { cls: 'immerse-btn immerse-btn-primary' });
continueBtn.innerHTML = '▶ Continue Working'; continueBtn.innerHTML = '▶ Continue Working';
continueBtn.addEventListener('click', () => this.plugin.startPomodoro(task.id)); continueBtn.addEventListener('click', () => this.plugin.startPomodoro(task.id));
const completeBtn = controls.createEl('button', { cls: 'focus-task-btn focus-task-btn-success' }); const completeBtn = controls.createEl('button', { cls: 'immerse-btn immerse-btn-success' });
completeBtn.innerHTML = '✓ Complete'; completeBtn.innerHTML = '✓ Complete';
completeBtn.addEventListener('click', () => this.plugin.completeTask(task.id)); completeBtn.addEventListener('click', () => this.plugin.completeTask(task.id));
const stopBtn = controls.createEl('button', { cls: 'focus-task-btn focus-task-btn-danger' }); const stopBtn = controls.createEl('button', { cls: 'immerse-btn immerse-btn-danger' });
stopBtn.innerHTML = '✕ Stop'; stopBtn.innerHTML = '✕ Stop';
stopBtn.addEventListener('click', () => this.plugin.stopTimer()); stopBtn.addEventListener('click', () => this.plugin.stopTimer());
} }
@@ -263,18 +263,18 @@ export class FocusTaskView extends ItemView {
} }
} else { } else {
// No active task - show start focus prompt // No active task - show start focus prompt
const startPrompt = activeSection.createEl('div', { cls: 'focus-task-start-prompt' }); const startPrompt = activeSection.createEl('div', { cls: 'immerse-start-prompt' });
startPrompt.createEl('div', { cls: 'focus-task-prompt-icon', text: '⚡' }); startPrompt.createEl('div', { cls: 'immerse-prompt-icon', text: '⚡' });
startPrompt.createEl('div', { cls: 'focus-task-prompt-text', text: 'Ready to focus?' }); startPrompt.createEl('div', { cls: 'immerse-prompt-text', text: 'Ready to focus?' });
startPrompt.createEl('div', { cls: 'focus-task-prompt-hint', text: 'Click ▶ on a task to start a Pomodoro session' }); startPrompt.createEl('div', { cls: 'immerse-prompt-hint', text: 'Click ▶ on a task to start a Pomodoro session' });
} }
} }
renderTaskList(container: Element) { renderTaskList(container: Element) {
const listSection = container.createEl('div', { cls: 'focus-task-list-section' }); const listSection = container.createEl('div', { cls: 'immerse-list-section' });
// Filters // Filters
const filters = listSection.createEl('div', { cls: 'focus-task-filters' }); const filters = listSection.createEl('div', { cls: 'immerse-filters' });
const filterOptions = [ const filterOptions = [
{ id: 'all', label: 'All Tasks' }, { id: 'all', label: 'All Tasks' },
@@ -285,7 +285,7 @@ export class FocusTaskView extends ItemView {
filterOptions.forEach(opt => { filterOptions.forEach(opt => {
const btn = filters.createEl('button', { const btn = filters.createEl('button', {
cls: `focus-task-filter-btn ${this.currentFilter === opt.id ? 'active' : ''}`, cls: `immerse-filter-btn ${this.currentFilter === opt.id ? 'active' : ''}`,
text: opt.label, text: opt.label,
}); });
btn.addEventListener('click', () => { btn.addEventListener('click', () => {
@@ -295,7 +295,7 @@ export class FocusTaskView extends ItemView {
}); });
// Task items // Task items
const taskList = listSection.createEl('div', { cls: 'focus-task-task-list' }); const taskList = listSection.createEl('div', { cls: 'immerse-task-list' });
let tasks = this.plugin.data.tasks; let tasks = this.plugin.data.tasks;
@@ -315,10 +315,10 @@ export class FocusTaskView extends ItemView {
}); });
if (tasks.length === 0) { if (tasks.length === 0) {
const emptyState = taskList.createEl('div', { cls: 'focus-task-empty-state' }); const emptyState = taskList.createEl('div', { cls: 'immerse-empty-state' });
emptyState.createEl('div', { cls: 'focus-task-empty-icon', text: '📝' }); emptyState.createEl('div', { cls: 'immerse-empty-icon', text: '📝' });
emptyState.createEl('div', { cls: 'focus-task-empty-text', text: 'No tasks yet' }); emptyState.createEl('div', { cls: 'immerse-empty-text', text: 'No tasks yet' });
emptyState.createEl('div', { cls: 'focus-task-empty-hint', text: 'Add a task to get started!' }); emptyState.createEl('div', { cls: 'immerse-empty-hint', text: 'Add a task to get started!' });
} else { } else {
tasks.forEach(task => this.renderTaskItem(taskList, task)); tasks.forEach(task => this.renderTaskItem(taskList, task));
} }
@@ -328,11 +328,11 @@ export class FocusTaskView extends ItemView {
const list = this.plugin.settings.lists.find(l => l.id === task.list); const list = this.plugin.settings.lists.find(l => l.id === task.list);
const taskEl = container.createEl('div', { const taskEl = container.createEl('div', {
cls: `focus-task-task-item ${task.completed ? 'completed' : ''} ${task.isActive ? 'active' : ''}` cls: `immerse-task-item ${task.completed ? 'completed' : ''} ${task.isActive ? 'active' : ''}`
}); });
// Checkbox // Checkbox
const checkbox = taskEl.createEl('div', { cls: 'focus-task-checkbox' }); const checkbox = taskEl.createEl('div', { cls: 'immerse-checkbox' });
checkbox.innerHTML = task.completed ? '✓' : ''; checkbox.innerHTML = task.completed ? '✓' : '';
checkbox.style.borderColor = list?.color || '#6366f1'; checkbox.style.borderColor = list?.color || '#6366f1';
if (task.completed) { if (task.completed) {
@@ -347,37 +347,37 @@ export class FocusTaskView extends ItemView {
}); });
// Task content // Task content
const content = taskEl.createEl('div', { cls: 'focus-task-task-content' }); const content = taskEl.createEl('div', { cls: 'immerse-task-content' });
const taskHeader = content.createEl('div', { cls: 'focus-task-task-header' }); const taskHeader = content.createEl('div', { cls: 'immerse-task-header' });
taskHeader.createEl('span', { cls: 'focus-task-task-text', text: task.text }); taskHeader.createEl('span', { cls: 'immerse-task-text', text: task.text });
if (list) { if (list) {
const listBadge = taskHeader.createEl('span', { const listBadge = taskHeader.createEl('span', {
cls: 'focus-task-list-badge', cls: 'immerse-list-badge',
text: `${list.icon} ${list.name}`, text: `${list.icon} ${list.name}`,
}); });
listBadge.style.backgroundColor = list.color + '20'; listBadge.style.backgroundColor = list.color + '20';
listBadge.style.color = list.color; listBadge.style.color = list.color;
} }
const taskMeta = content.createEl('div', { cls: 'focus-task-task-meta' }); const taskMeta = content.createEl('div', { cls: 'immerse-task-meta' });
taskMeta.createEl('span', { text: `Est: ${this.plugin.formatTimeHuman(task.estimatedMinutes)}` }); taskMeta.createEl('span', { text: `Est: ${this.plugin.formatTimeHuman(task.estimatedMinutes)}` });
if (task.actualMinutes > 0) { if (task.actualMinutes > 0) {
const actualSpan = taskMeta.createEl('span'); const actualSpan = taskMeta.createEl('span');
actualSpan.setText(`Actual: ${this.plugin.formatTimeHuman(task.actualMinutes)}`); actualSpan.setText(`Actual: ${this.plugin.formatTimeHuman(task.actualMinutes)}`);
if (task.actualMinutes > task.estimatedMinutes) { if (task.actualMinutes > task.estimatedMinutes) {
actualSpan.addClass('focus-task-overtime-text'); actualSpan.addClass('immerse-overtime-text');
} }
} }
// Actions // Actions
const actions = taskEl.createEl('div', { cls: 'focus-task-task-actions' }); const actions = taskEl.createEl('div', { cls: 'immerse-task-actions' });
if (!task.completed) { if (!task.completed) {
// Start pomodoro button // Start pomodoro button
const startBtn = actions.createEl('button', { cls: 'focus-task-task-btn', attr: { 'aria-label': 'Start Pomodoro' } }); const startBtn = actions.createEl('button', { cls: 'immerse-task-btn', attr: { 'aria-label': 'Start Pomodoro' } });
startBtn.innerHTML = '▶'; startBtn.innerHTML = '▶';
startBtn.addEventListener('click', (e) => { startBtn.addEventListener('click', (e) => {
e.stopPropagation(); e.stopPropagation();
@@ -385,7 +385,7 @@ export class FocusTaskView extends ItemView {
}); });
// Stopwatch mode button // Stopwatch mode button
const stopwatchBtn = actions.createEl('button', { cls: 'focus-task-task-btn', attr: { 'aria-label': 'Start Stopwatch' } }); const stopwatchBtn = actions.createEl('button', { cls: 'immerse-task-btn', attr: { 'aria-label': 'Start Stopwatch' } });
stopwatchBtn.innerHTML = '⏱'; stopwatchBtn.innerHTML = '⏱';
stopwatchBtn.addEventListener('click', (e) => { stopwatchBtn.addEventListener('click', (e) => {
e.stopPropagation(); e.stopPropagation();
@@ -394,7 +394,7 @@ export class FocusTaskView extends ItemView {
} }
// Edit button // Edit button
const editBtn = actions.createEl('button', { cls: 'focus-task-task-btn', attr: { 'aria-label': 'Edit' } }); const editBtn = actions.createEl('button', { cls: 'immerse-task-btn', attr: { 'aria-label': 'Edit' } });
editBtn.innerHTML = '✏️'; editBtn.innerHTML = '✏️';
editBtn.addEventListener('click', (e) => { editBtn.addEventListener('click', (e) => {
e.stopPropagation(); e.stopPropagation();
@@ -402,7 +402,7 @@ export class FocusTaskView extends ItemView {
}); });
// Delete button // Delete button
const deleteBtn = actions.createEl('button', { cls: 'focus-task-task-btn focus-task-delete-btn', attr: { 'aria-label': 'Delete' } }); const deleteBtn = actions.createEl('button', { cls: 'immerse-task-btn immerse-delete-btn', attr: { 'aria-label': 'Delete' } });
deleteBtn.innerHTML = '🗑'; deleteBtn.innerHTML = '🗑';
deleteBtn.addEventListener('click', (e) => { deleteBtn.addEventListener('click', (e) => {
e.stopPropagation(); e.stopPropagation();

View File

@@ -1,10 +1,10 @@
/* ============================================ /* ============================================
FOCUS TASK - Obsidian Plugin Styles IMMERSE - Obsidian Plugin Styles
Inspired by https://www.blitzit.app/ Inspired by https://www.blitzit.app/
============================================ */ ============================================ */
/* ============ CSS Variables ============ */ /* ============ CSS Variables ============ */
.focus-task-container { .immerse-container {
--ft-primary: #6366f1; --ft-primary: #6366f1;
--ft-primary-light: #818cf8; --ft-primary-light: #818cf8;
--ft-primary-dark: #4f46e5; --ft-primary-dark: #4f46e5;
@@ -27,7 +27,7 @@
} }
/* ============ Container ============ */ /* ============ Container ============ */
.focus-task-container { .immerse-container {
padding: 16px; padding: 16px;
font-family: var(--font-interface); font-family: var(--font-interface);
overflow-y: auto; overflow-y: auto;
@@ -35,7 +35,7 @@
} }
/* ============ Header ============ */ /* ============ Header ============ */
.focus-task-header { .immerse-header {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
@@ -44,13 +44,13 @@
border-bottom: 1px solid var(--ft-border); border-bottom: 1px solid var(--ft-border);
} }
.focus-task-title-section { .immerse-title-section {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 4px; gap: 4px;
} }
.focus-task-title { .immerse-title {
margin: 0; margin: 0;
font-size: 24px; font-size: 24px;
font-weight: 700; font-weight: 700;
@@ -60,18 +60,18 @@
background-clip: text; background-clip: text;
} }
.focus-task-date { .immerse-date {
color: var(--ft-text-muted); color: var(--ft-text-muted);
font-size: 13px; font-size: 13px;
} }
.focus-task-header-actions { .immerse-header-actions {
display: flex; display: flex;
gap: 8px; gap: 8px;
} }
/* ============ Buttons ============ */ /* ============ Buttons ============ */
.focus-task-btn { .immerse-btn {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -87,48 +87,48 @@
color: var(--ft-text); color: var(--ft-text);
} }
.focus-task-btn:hover { .immerse-btn:hover {
background: var(--ft-border); background: var(--ft-border);
transform: translateY(-1px); transform: translateY(-1px);
} }
.focus-task-btn-primary { .immerse-btn-primary {
background: linear-gradient(135deg, var(--ft-primary) 0%, var(--ft-primary-dark) 100%); background: linear-gradient(135deg, var(--ft-primary) 0%, var(--ft-primary-dark) 100%);
color: white; color: white;
} }
.focus-task-btn-primary:hover { .immerse-btn-primary:hover {
background: linear-gradient(135deg, var(--ft-primary-light) 0%, var(--ft-primary) 100%); background: linear-gradient(135deg, var(--ft-primary-light) 0%, var(--ft-primary) 100%);
box-shadow: 0 4px 12px rgba(99, 102, 241, 0.4); box-shadow: 0 4px 12px rgba(99, 102, 241, 0.4);
} }
.focus-task-btn-success { .immerse-btn-success {
background: var(--ft-success); background: var(--ft-success);
color: white; color: white;
} }
.focus-task-btn-success:hover { .immerse-btn-success:hover {
background: #16a34a; background: #16a34a;
} }
.focus-task-btn-secondary { .immerse-btn-secondary {
background: var(--ft-bg-secondary); background: var(--ft-bg-secondary);
border: 1px solid var(--ft-border); border: 1px solid var(--ft-border);
} }
.focus-task-btn-danger { .immerse-btn-danger {
background: transparent; background: transparent;
color: var(--ft-danger); color: var(--ft-danger);
border: 1px solid var(--ft-danger); border: 1px solid var(--ft-danger);
} }
.focus-task-btn-danger:hover { .immerse-btn-danger:hover {
background: var(--ft-danger); background: var(--ft-danger);
color: white; color: white;
} }
/* ============ Stats Bar ============ */ /* ============ Stats Bar ============ */
.focus-task-stats-bar { .immerse-stats-bar {
display: grid; display: grid;
grid-template-columns: repeat(4, 1fr); grid-template-columns: repeat(4, 1fr);
gap: 12px; gap: 12px;
@@ -136,12 +136,12 @@
} }
@media (max-width: 600px) { @media (max-width: 600px) {
.focus-task-stats-bar { .immerse-stats-bar {
grid-template-columns: repeat(2, 1fr); grid-template-columns: repeat(2, 1fr);
} }
} }
.focus-task-stat-item { .immerse-stat-item {
background: var(--ft-bg-secondary); background: var(--ft-bg-secondary);
border-radius: var(--ft-radius); border-radius: var(--ft-radius);
padding: 12px; padding: 12px;
@@ -149,23 +149,23 @@
transition: all 0.2s ease; transition: all 0.2s ease;
} }
.focus-task-stat-item:hover { .immerse-stat-item:hover {
transform: translateY(-2px); transform: translateY(-2px);
box-shadow: var(--ft-shadow); box-shadow: var(--ft-shadow);
} }
.focus-task-stat-icon { .immerse-stat-icon {
font-size: 20px; font-size: 20px;
margin-bottom: 4px; margin-bottom: 4px;
} }
.focus-task-stat-value { .immerse-stat-value {
font-size: 18px; font-size: 18px;
font-weight: 700; font-weight: 700;
color: var(--ft-primary); color: var(--ft-primary);
} }
.focus-task-stat-label { .immerse-stat-label {
font-size: 11px; font-size: 11px;
color: var(--ft-text-muted); color: var(--ft-text-muted);
text-transform: uppercase; text-transform: uppercase;
@@ -173,11 +173,11 @@
} }
/* ============ Active Task Section ============ */ /* ============ Active Task Section ============ */
.focus-task-active-section { .immerse-active-section {
margin-bottom: 24px; margin-bottom: 24px;
} }
.focus-task-start-prompt { .immerse-start-prompt {
background: linear-gradient(135deg, var(--ft-bg-secondary) 0%, var(--ft-bg-tertiary) 100%); background: linear-gradient(135deg, var(--ft-bg-secondary) 0%, var(--ft-bg-tertiary) 100%);
border: 2px dashed var(--ft-border); border: 2px dashed var(--ft-border);
border-radius: var(--ft-radius); border-radius: var(--ft-radius);
@@ -185,7 +185,7 @@
text-align: center; text-align: center;
} }
.focus-task-prompt-icon { .immerse-prompt-icon {
font-size: 48px; font-size: 48px;
margin-bottom: 12px; margin-bottom: 12px;
animation: ft-pulse 2s ease-in-out infinite; animation: ft-pulse 2s ease-in-out infinite;
@@ -196,20 +196,20 @@
50% { transform: scale(1.1); opacity: 0.8; } 50% { transform: scale(1.1); opacity: 0.8; }
} }
.focus-task-prompt-text { .immerse-prompt-text {
font-size: 18px; font-size: 18px;
font-weight: 600; font-weight: 600;
color: var(--ft-text); color: var(--ft-text);
margin-bottom: 4px; margin-bottom: 4px;
} }
.focus-task-prompt-hint { .immerse-prompt-hint {
font-size: 14px; font-size: 14px;
color: var(--ft-text-muted); color: var(--ft-text-muted);
} }
/* ============ Active Task Card ============ */ /* ============ Active Task Card ============ */
.focus-task-active-card { .immerse-active-card {
background: linear-gradient(135deg, var(--ft-primary) 0%, var(--ft-primary-dark) 100%); background: linear-gradient(135deg, var(--ft-primary) 0%, var(--ft-primary-dark) 100%);
border-radius: var(--ft-radius); border-radius: var(--ft-radius);
padding: 24px; padding: 24px;
@@ -217,11 +217,11 @@
box-shadow: var(--ft-shadow-lg); box-shadow: var(--ft-shadow-lg);
} }
.focus-task-break-card { .immerse-break-card {
background: linear-gradient(135deg, var(--ft-break) 0%, #0891b2 100%); background: linear-gradient(135deg, var(--ft-break) 0%, #0891b2 100%);
} }
.focus-task-active-label { .immerse-active-label {
font-size: 12px; font-size: 12px;
font-weight: 600; font-weight: 600;
text-transform: uppercase; text-transform: uppercase;
@@ -230,31 +230,31 @@
margin-bottom: 8px; margin-bottom: 8px;
} }
.focus-task-active-task-name { .immerse-active-task-name {
font-size: 20px; font-size: 20px;
font-weight: 700; font-weight: 700;
margin-bottom: 16px; margin-bottom: 16px;
word-break: break-word; word-break: break-word;
} }
.focus-task-timer-display { .immerse-timer-display {
text-align: center; text-align: center;
margin-bottom: 16px; margin-bottom: 16px;
} }
.focus-task-timer-time { .immerse-timer-time {
font-size: 48px; font-size: 48px;
font-weight: 700; font-weight: 700;
font-variant-numeric: tabular-nums; font-variant-numeric: tabular-nums;
letter-spacing: 2px; letter-spacing: 2px;
} }
.focus-task-timer-time.focus-task-overtime { .immerse-timer-time.immerse-overtime {
color: var(--ft-warning); color: var(--ft-warning);
} }
/* Progress Bar */ /* Progress Bar */
.focus-task-progress-wrap { .immerse-progress-wrap {
background: rgba(255, 255, 255, 0.2); background: rgba(255, 255, 255, 0.2);
border-radius: 999px; border-radius: 999px;
height: 8px; height: 8px;
@@ -262,18 +262,18 @@
margin-bottom: 12px; margin-bottom: 12px;
} }
.focus-task-progress-bar { .immerse-progress-bar {
height: 100%; height: 100%;
background: rgba(255, 255, 255, 0.9); background: rgba(255, 255, 255, 0.9);
border-radius: 999px; border-radius: 999px;
transition: width 0.3s ease; transition: width 0.3s ease;
} }
.focus-task-progress-bar.focus-task-overtime { .immerse-progress-bar.immerse-overtime {
background: var(--ft-warning); background: var(--ft-warning);
} }
.focus-task-time-info { .immerse-time-info {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
font-size: 13px; font-size: 13px;
@@ -281,13 +281,13 @@
margin-bottom: 16px; margin-bottom: 16px;
} }
.focus-task-active-controls { .immerse-active-controls {
display: flex; display: flex;
gap: 8px; gap: 8px;
flex-wrap: wrap; flex-wrap: wrap;
} }
.focus-task-active-controls .focus-task-btn { .immerse-active-controls .immerse-btn {
flex: 1; flex: 1;
min-width: 80px; min-width: 80px;
background: rgba(255, 255, 255, 0.2); background: rgba(255, 255, 255, 0.2);
@@ -295,33 +295,33 @@
border: none; border: none;
} }
.focus-task-active-controls .focus-task-btn:hover { .immerse-active-controls .immerse-btn:hover {
background: rgba(255, 255, 255, 0.3); background: rgba(255, 255, 255, 0.3);
} }
.focus-task-active-controls .focus-task-btn-success { .immerse-active-controls .immerse-btn-success {
background: var(--ft-success); background: var(--ft-success);
} }
.focus-task-active-controls .focus-task-btn-danger { .immerse-active-controls .immerse-btn-danger {
background: transparent; background: transparent;
border: 1px solid rgba(255, 255, 255, 0.4); border: 1px solid rgba(255, 255, 255, 0.4);
} }
/* ============ Task List Section ============ */ /* ============ Task List Section ============ */
.focus-task-list-section { .immerse-list-section {
flex: 1; flex: 1;
} }
/* Filters */ /* Filters */
.focus-task-filters { .immerse-filters {
display: flex; display: flex;
gap: 8px; gap: 8px;
margin-bottom: 16px; margin-bottom: 16px;
flex-wrap: wrap; flex-wrap: wrap;
} }
.focus-task-filter-btn { .immerse-filter-btn {
padding: 6px 12px; padding: 6px 12px;
border-radius: 999px; border-radius: 999px;
font-size: 13px; font-size: 13px;
@@ -332,49 +332,49 @@
transition: all 0.2s ease; transition: all 0.2s ease;
} }
.focus-task-filter-btn:hover { .immerse-filter-btn:hover {
background: var(--ft-bg-tertiary); background: var(--ft-bg-tertiary);
color: var(--ft-text); color: var(--ft-text);
} }
.focus-task-filter-btn.active { .immerse-filter-btn.active {
background: var(--ft-primary); background: var(--ft-primary);
border-color: var(--ft-primary); border-color: var(--ft-primary);
color: white; color: white;
} }
/* Task List */ /* Task List */
.focus-task-task-list { .immerse-task-list {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 8px; gap: 8px;
} }
/* Empty State */ /* Empty State */
.focus-task-empty-state { .immerse-empty-state {
text-align: center; text-align: center;
padding: 40px 20px; padding: 40px 20px;
color: var(--ft-text-muted); color: var(--ft-text-muted);
} }
.focus-task-empty-icon { .immerse-empty-icon {
font-size: 48px; font-size: 48px;
margin-bottom: 12px; margin-bottom: 12px;
opacity: 0.5; opacity: 0.5;
} }
.focus-task-empty-text { .immerse-empty-text {
font-size: 16px; font-size: 16px;
font-weight: 500; font-weight: 500;
margin-bottom: 4px; margin-bottom: 4px;
} }
.focus-task-empty-hint { .immerse-empty-hint {
font-size: 14px; font-size: 14px;
} }
/* ============ Task Item ============ */ /* ============ Task Item ============ */
.focus-task-task-item { .immerse-task-item {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 12px; gap: 12px;
@@ -385,27 +385,27 @@
transition: all 0.2s ease; transition: all 0.2s ease;
} }
.focus-task-task-item:hover { .immerse-task-item:hover {
border-color: var(--ft-primary); border-color: var(--ft-primary);
box-shadow: var(--ft-shadow); box-shadow: var(--ft-shadow);
transform: translateX(4px); transform: translateX(4px);
} }
.focus-task-task-item.active { .immerse-task-item.active {
border-color: var(--ft-primary); border-color: var(--ft-primary);
background: linear-gradient(90deg, rgba(99, 102, 241, 0.1) 0%, var(--ft-bg-secondary) 100%); background: linear-gradient(90deg, rgba(99, 102, 241, 0.1) 0%, var(--ft-bg-secondary) 100%);
} }
.focus-task-task-item.completed { .immerse-task-item.completed {
opacity: 0.6; opacity: 0.6;
} }
.focus-task-task-item.completed .focus-task-task-text { .immerse-task-item.completed .immerse-task-text {
text-decoration: line-through; text-decoration: line-through;
} }
/* Checkbox */ /* Checkbox */
.focus-task-checkbox { .immerse-checkbox {
width: 24px; width: 24px;
height: 24px; height: 24px;
min-width: 24px; min-width: 24px;
@@ -420,18 +420,18 @@
transition: all 0.2s ease; transition: all 0.2s ease;
} }
.focus-task-checkbox:hover { .immerse-checkbox:hover {
transform: scale(1.1); transform: scale(1.1);
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.2); box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.2);
} }
/* Task Content */ /* Task Content */
.focus-task-task-content { .immerse-task-content {
flex: 1; flex: 1;
min-width: 0; min-width: 0;
} }
.focus-task-task-header { .immerse-task-header {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 8px; gap: 8px;
@@ -439,44 +439,44 @@
margin-bottom: 4px; margin-bottom: 4px;
} }
.focus-task-task-text { .immerse-task-text {
font-size: 14px; font-size: 14px;
font-weight: 500; font-weight: 500;
color: var(--ft-text); color: var(--ft-text);
word-break: break-word; word-break: break-word;
} }
.focus-task-list-badge { .immerse-list-badge {
font-size: 11px; font-size: 11px;
padding: 2px 8px; padding: 2px 8px;
border-radius: 999px; border-radius: 999px;
font-weight: 500; font-weight: 500;
} }
.focus-task-task-meta { .immerse-task-meta {
display: flex; display: flex;
gap: 12px; gap: 12px;
font-size: 12px; font-size: 12px;
color: var(--ft-text-muted); color: var(--ft-text-muted);
} }
.focus-task-overtime-text { .immerse-overtime-text {
color: var(--ft-warning); color: var(--ft-warning);
} }
/* Task Actions */ /* Task Actions */
.focus-task-task-actions { .immerse-task-actions {
display: flex; display: flex;
gap: 4px; gap: 4px;
opacity: 0; opacity: 0;
transition: opacity 0.2s ease; transition: opacity 0.2s ease;
} }
.focus-task-task-item:hover .focus-task-task-actions { .immerse-task-item:hover .immerse-task-actions {
opacity: 1; opacity: 1;
} }
.focus-task-task-btn { .immerse-task-btn {
width: 32px; width: 32px;
height: 32px; height: 32px;
border-radius: 6px; border-radius: 6px;
@@ -490,18 +490,18 @@
transition: all 0.2s ease; transition: all 0.2s ease;
} }
.focus-task-task-btn:hover { .immerse-task-btn:hover {
background: var(--ft-primary); background: var(--ft-primary);
color: white; color: white;
transform: scale(1.1); transform: scale(1.1);
} }
.focus-task-delete-btn:hover { .immerse-delete-btn:hover {
background: var(--ft-danger); background: var(--ft-danger);
} }
/* ============ Status Bar Timer ============ */ /* ============ Status Bar Timer ============ */
.focus-task-status-bar { .immerse-status-bar {
cursor: pointer; cursor: pointer;
padding: 0 8px; padding: 0 8px;
display: flex; display: flex;
@@ -511,26 +511,26 @@
transition: all 0.2s ease; transition: all 0.2s ease;
} }
.focus-task-status-bar:hover { .immerse-status-bar:hover {
color: var(--text-accent); color: var(--text-accent);
} }
.focus-task-status-bar.focus-task-status-active { .immerse-status-bar.immerse-status-active {
color: var(--text-accent); color: var(--text-accent);
font-weight: 500; font-weight: 500;
} }
/* ============ Modal Styles ============ */ /* ============ Modal Styles ============ */
.focus-task-modal { .immerse-modal {
padding: 20px; padding: 20px;
} }
.focus-task-modal h2 { .immerse-modal h2 {
margin-top: 0; margin-top: 0;
margin-bottom: 20px; margin-bottom: 20px;
} }
.focus-task-modal-buttons { .immerse-modal-buttons {
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
gap: 8px; gap: 8px;
@@ -540,41 +540,41 @@
} }
/* About section in settings */ /* About section in settings */
.focus-task-about { .immerse-about {
background: var(--ft-bg-secondary); background: var(--ft-bg-secondary);
border-radius: var(--ft-radius); border-radius: var(--ft-radius);
padding: 16px; padding: 16px;
margin-top: 8px; margin-top: 8px;
} }
.focus-task-about p { .immerse-about p {
margin: 0 0 12px 0; margin: 0 0 12px 0;
line-height: 1.6; line-height: 1.6;
} }
.focus-task-about p:last-child { .immerse-about p:last-child {
margin-bottom: 0; margin-bottom: 0;
} }
.focus-task-about a { .immerse-about a {
color: var(--ft-primary); color: var(--ft-primary);
} }
/* ============ Scrollbar Styling ============ */ /* ============ Scrollbar Styling ============ */
.focus-task-container::-webkit-scrollbar { .immerse-container::-webkit-scrollbar {
width: 8px; width: 8px;
} }
.focus-task-container::-webkit-scrollbar-track { .immerse-container::-webkit-scrollbar-track {
background: transparent; background: transparent;
} }
.focus-task-container::-webkit-scrollbar-thumb { .immerse-container::-webkit-scrollbar-thumb {
background: var(--ft-border); background: var(--ft-border);
border-radius: 4px; border-radius: 4px;
} }
.focus-task-container::-webkit-scrollbar-thumb:hover { .immerse-container::-webkit-scrollbar-thumb:hover {
background: var(--ft-text-muted); background: var(--ft-text-muted);
} }
@@ -585,37 +585,37 @@
100% { transform: scale(1); } 100% { transform: scale(1); }
} }
.focus-task-checkbox.completing { .immerse-checkbox.completing {
animation: ft-checkComplete 0.3s ease; animation: ft-checkComplete 0.3s ease;
} }
/* ============ Dark mode adjustments ============ */ /* ============ Dark mode adjustments ============ */
.theme-dark .focus-task-status-bar { .theme-dark .immerse-status-bar {
background: var(--background-secondary); background: var(--background-secondary);
} }
/* ============ Mobile Responsive ============ */ /* ============ Mobile Responsive ============ */
@media (max-width: 400px) { @media (max-width: 400px) {
.focus-task-header { .immerse-header {
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: flex-start;
gap: 12px; gap: 12px;
} }
.focus-task-active-controls { .immerse-active-controls {
flex-direction: column; flex-direction: column;
} }
.focus-task-active-controls .focus-task-btn { .immerse-active-controls .immerse-btn {
flex: none; flex: none;
width: 100%; width: 100%;
} }
.focus-task-task-item { .immerse-task-item {
flex-wrap: wrap; flex-wrap: wrap;
} }
.focus-task-task-actions { .immerse-task-actions {
opacity: 1; opacity: 1;
width: 100%; width: 100%;
justify-content: flex-end; justify-content: flex-end;

View File

@@ -3,5 +3,6 @@
"1.0.5": "0.15.0", "1.0.5": "0.15.0",
"1.0.6": "0.15.0", "1.0.6": "0.15.0",
"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"
} }