feat: Add task scheduling and reminders system
Add comprehensive scheduling functionality with reminder notifications: - Add scheduledDate, scheduledTime, and reminderMinutes fields to ImmerseTask - Add enableReminders and defaultReminderMinutes to plugin settings - Implement reminder notification system with 30-second background checks - Add overdue task detection with visual indicators - Add native HTML5 date/time pickers in Quick Add and Edit modals - Add reminder dropdown with 5/10/15/30/60 minute options - Display scheduled date/time with blue badge (📅) in task list - Show pulsing red "OVERDUE" badge (⚠️) for past-due tasks - Add red left border highlight for overdue tasks - Implement startup check for due/overdue tasks when plugin loads - Show overdue notices when Obsidian opens if tasks are past due - Play alert sounds for reminders (if sounds enabled) - Track shown reminders to prevent duplicate notifications
This commit is contained in:
29
src/view.ts
29
src/view.ts
@@ -326,9 +326,13 @@ export class ImmerseView extends ItemView {
|
||||
|
||||
renderTaskItem(container: Element, task: ImmerseTask) {
|
||||
const list = this.plugin.settings.lists.find(l => l.id === task.list);
|
||||
|
||||
const taskEl = container.createEl('div', {
|
||||
cls: `immerse-task-item ${task.completed ? 'completed' : ''} ${task.isActive ? 'active' : ''}`
|
||||
|
||||
// Check if task is overdue
|
||||
const isOverdue = !task.completed && task.scheduledDate && task.scheduledTime &&
|
||||
new Date(`${task.scheduledDate}T${task.scheduledTime}`).getTime() < Date.now();
|
||||
|
||||
const taskEl = container.createEl('div', {
|
||||
cls: `immerse-task-item ${task.completed ? 'completed' : ''} ${task.isActive ? 'active' : ''} ${isOverdue ? 'overdue' : ''}`
|
||||
});
|
||||
|
||||
// Checkbox
|
||||
@@ -363,7 +367,7 @@ export class ImmerseView extends ItemView {
|
||||
|
||||
const taskMeta = content.createEl('div', { cls: 'immerse-task-meta' });
|
||||
taskMeta.createEl('span', { text: `Est: ${this.plugin.formatTimeHuman(task.estimatedMinutes)}` });
|
||||
|
||||
|
||||
if (task.actualMinutes > 0) {
|
||||
const actualSpan = taskMeta.createEl('span');
|
||||
actualSpan.setText(`Actual: ${this.plugin.formatTimeHuman(task.actualMinutes)}`);
|
||||
@@ -372,6 +376,23 @@ export class ImmerseView extends ItemView {
|
||||
}
|
||||
}
|
||||
|
||||
// Show scheduled date/time if set
|
||||
if (task.scheduledDate) {
|
||||
const scheduleSpan = taskMeta.createEl('span', {
|
||||
cls: `immerse-schedule-badge ${isOverdue ? 'overdue' : ''}`
|
||||
});
|
||||
const dateStr = task.scheduledDate;
|
||||
const timeStr = task.scheduledTime || '';
|
||||
if (isOverdue) {
|
||||
scheduleSpan.setText(`⚠️ OVERDUE: ${dateStr}${timeStr ? ' ' + timeStr : ''}`);
|
||||
} else {
|
||||
scheduleSpan.setText(`📅 ${dateStr}${timeStr ? ' ' + timeStr : ''}`);
|
||||
}
|
||||
if (task.reminderMinutes) {
|
||||
scheduleSpan.title = `Reminder set for ${task.reminderMinutes} min before`;
|
||||
}
|
||||
}
|
||||
|
||||
// Actions
|
||||
const actions = taskEl.createEl('div', { cls: 'immerse-task-actions' });
|
||||
|
||||
|
||||
Reference in New Issue
Block a user