Removed Floating timer -> Status Bar
This commit is contained in:
@@ -48,7 +48,7 @@ Focus Task brings the power of time-boxed task management directly into your Obs
|
|||||||
- **Pomodoro Count**: Track total pomodoros completed
|
- **Pomodoro Count**: Track total pomodoros completed
|
||||||
|
|
||||||
### 🎨 User Experience
|
### 🎨 User Experience
|
||||||
- **Floating Timer Widget**: Draggable timer that stays visible while you work
|
- **Status Bar Timer**: timer that stays visible while you work
|
||||||
- **Celebration Messages**: Fun, randomized messages when you complete tasks
|
- **Celebration Messages**: Fun, randomized messages when you complete tasks
|
||||||
- **Sound Notifications**: Audio alerts for timer completion and task completion
|
- **Sound Notifications**: Audio alerts for timer completion and task completion
|
||||||
- **Keyboard Shortcuts**: Quick access to common actions
|
- **Keyboard Shortcuts**: Quick access to common actions
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"id": "focus-task",
|
"id": "focus-task",
|
||||||
"name": "Focus Task",
|
"name": "Focus Task",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"minAppVersion": "0.15.0",
|
"minAppVersion": "0.15.0",
|
||||||
"description": "A Blitzit-inspired task management and focus timer plugin. Plan your day, track time with Pomodoro technique, and crush your tasks with satisfying checkoffs.",
|
"description": "A Blitzit-inspired task management and focus timer plugin. Plan your day, track time with Pomodoro technique, and crush your tasks with satisfying checkoffs.",
|
||||||
"author": "Crib",
|
"author": "Crib",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "focus-task",
|
"name": "focus-task",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"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": {
|
||||||
|
|||||||
156
src/main.ts
156
src/main.ts
@@ -36,8 +36,8 @@ export default class FocusTaskPlugin extends Plugin {
|
|||||||
activeTaskId: string | null = null;
|
activeTaskId: string | null = null;
|
||||||
pomodoroCount: number = 0;
|
pomodoroCount: number = 0;
|
||||||
|
|
||||||
// Floating timer element
|
// Status Bar element
|
||||||
floatingTimerEl: HTMLElement | null = null;
|
statusBarEl: HTMLElement | null = null;
|
||||||
|
|
||||||
async onload() {
|
async onload() {
|
||||||
await this.loadAllData();
|
await this.loadAllData();
|
||||||
@@ -91,15 +91,13 @@ export default class FocusTaskPlugin extends Plugin {
|
|||||||
this.addSettingTab(new FocusTaskSettingTab(this.app, this));
|
this.addSettingTab(new FocusTaskSettingTab(this.app, this));
|
||||||
|
|
||||||
// Create floating timer if enabled
|
// Create floating timer if enabled
|
||||||
if (this.settings.showFloatingTimer) {
|
this.createStatusBar();
|
||||||
this.createFloatingTimer();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onunload() {
|
onunload() {
|
||||||
this.stopTimer();
|
this.stopTimer();
|
||||||
this.removeFloatingTimer();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
async loadAllData() {
|
async loadAllData() {
|
||||||
const loaded = await this.loadData();
|
const loaded = await this.loadData();
|
||||||
@@ -272,7 +270,7 @@ export default class FocusTaskPlugin extends Plugin {
|
|||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
this.saveAllData();
|
this.saveAllData();
|
||||||
this.refreshView();
|
this.updateTimerDisplay();
|
||||||
this.updateFloatingTimer();
|
this.updateFloatingTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,7 +302,7 @@ export default class FocusTaskPlugin extends Plugin {
|
|||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
this.updateFloatingTimer();
|
this.updateFloatingTimer();
|
||||||
this.refreshView();
|
this.updateTimerDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePomodoroEnd() {
|
handlePomodoroEnd() {
|
||||||
@@ -357,7 +355,7 @@ export default class FocusTaskPlugin extends Plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.updateFloatingTimer();
|
this.updateFloatingTimer();
|
||||||
this.refreshView();
|
this.updateTimerDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleTimer() {
|
toggleTimer() {
|
||||||
@@ -388,7 +386,7 @@ export default class FocusTaskPlugin extends Plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.updateFloatingTimer();
|
this.updateFloatingTimer();
|
||||||
this.refreshView();
|
this.updateTimerDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
stopTimer() {
|
stopTimer() {
|
||||||
@@ -419,106 +417,38 @@ export default class FocusTaskPlugin extends Plugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============ Floating Timer ============
|
// ============ Status Bar Timer ============
|
||||||
|
|
||||||
createFloatingTimer() {
|
createStatusBar() {
|
||||||
if (this.floatingTimerEl) return;
|
this.statusBarEl = this.addStatusBarItem();
|
||||||
|
this.statusBarEl.addClass('focus-task-status-bar');
|
||||||
|
this.updateStatusBar();
|
||||||
|
|
||||||
this.floatingTimerEl = document.body.createEl('div', {
|
// Click to open panel
|
||||||
cls: 'focus-task-floating-timer',
|
this.statusBarEl.addEventListener('click', () => {
|
||||||
});
|
this.activateView();
|
||||||
|
});
|
||||||
this.floatingTimerEl.innerHTML = `
|
|
||||||
<div class="focus-task-floating-inner">
|
|
||||||
<div class="focus-task-floating-task">No active task</div>
|
|
||||||
<div class="focus-task-floating-time">00:00</div>
|
|
||||||
<div class="focus-task-floating-controls">
|
|
||||||
<button class="focus-task-float-btn play-pause">▶</button>
|
|
||||||
<button class="focus-task-float-btn complete">✓</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
// Make draggable
|
|
||||||
this.makeDraggable(this.floatingTimerEl);
|
|
||||||
|
|
||||||
// Add event listeners
|
|
||||||
const playPauseBtn = this.floatingTimerEl.querySelector('.play-pause');
|
|
||||||
const completeBtn = this.floatingTimerEl.querySelector('.complete');
|
|
||||||
|
|
||||||
playPauseBtn?.addEventListener('click', () => this.toggleTimer());
|
|
||||||
completeBtn?.addEventListener('click', () => this.completeActiveTask());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
removeFloatingTimer() {
|
updateStatusBar() {
|
||||||
if (this.floatingTimerEl) {
|
if (!this.statusBarEl) return;
|
||||||
this.floatingTimerEl.remove();
|
|
||||||
this.floatingTimerEl = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updateFloatingTimer() {
|
|
||||||
if (!this.floatingTimerEl) return;
|
|
||||||
|
|
||||||
const taskEl = this.floatingTimerEl.querySelector('.focus-task-floating-task');
|
|
||||||
const timeEl = this.floatingTimerEl.querySelector('.focus-task-floating-time');
|
|
||||||
const playPauseBtn = this.floatingTimerEl.querySelector('.play-pause');
|
|
||||||
|
|
||||||
if (this.activeTaskId) {
|
if (this.activeTaskId) {
|
||||||
const task = this.data.tasks.find(t => t.id === this.activeTaskId);
|
const task = this.data.tasks.find(t => t.id === this.activeTaskId);
|
||||||
if (task && taskEl) {
|
const taskName = this.isBreakMode ? '☕ Break' : (task?.text.substring(0, 20) || 'Task');
|
||||||
taskEl.textContent = this.isBreakMode ? '☕ Break Time' : task.text;
|
const timeStr = this.formatTime(this.currentTimerSeconds);
|
||||||
}
|
const icon = this.isTimerRunning ? '▶' : '⏸';
|
||||||
} else if (taskEl) {
|
|
||||||
taskEl.textContent = 'No active task';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timeEl) {
|
this.statusBarEl.setText(`⚡ ${icon} ${timeStr} - ${taskName}${task && task.text.length > 20 ? '...' : ''}`);
|
||||||
timeEl.textContent = this.formatTime(this.currentTimerSeconds);
|
this.statusBarEl.addClass('focus-task-status-active');
|
||||||
timeEl.classList.toggle('focus-task-overtime', this.currentTimerSeconds < 0);
|
} else {
|
||||||
}
|
this.statusBarEl.setText('⚡ Focus Task');
|
||||||
|
this.statusBarEl.removeClass('focus-task-status-active');
|
||||||
if (playPauseBtn) {
|
|
||||||
playPauseBtn.textContent = this.isTimerRunning ? '⏸' : '▶';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update color based on state
|
|
||||||
this.floatingTimerEl.classList.toggle('focus-task-break-mode', this.isBreakMode);
|
|
||||||
this.floatingTimerEl.classList.toggle('focus-task-active', this.isTimerRunning);
|
|
||||||
}
|
|
||||||
|
|
||||||
makeDraggable(el: HTMLElement) {
|
|
||||||
let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
|
|
||||||
|
|
||||||
el.onmousedown = dragMouseDown;
|
|
||||||
|
|
||||||
function dragMouseDown(e: MouseEvent) {
|
|
||||||
if ((e.target as HTMLElement).tagName === 'BUTTON') return;
|
|
||||||
e.preventDefault();
|
|
||||||
pos3 = e.clientX;
|
|
||||||
pos4 = e.clientY;
|
|
||||||
document.onmouseup = closeDragElement;
|
|
||||||
document.onmousemove = elementDrag;
|
|
||||||
}
|
|
||||||
|
|
||||||
function elementDrag(e: MouseEvent) {
|
|
||||||
e.preventDefault();
|
|
||||||
pos1 = pos3 - e.clientX;
|
|
||||||
pos2 = pos4 - e.clientY;
|
|
||||||
pos3 = e.clientX;
|
|
||||||
pos4 = e.clientY;
|
|
||||||
el.style.top = (el.offsetTop - pos2) + "px";
|
|
||||||
el.style.left = (el.offsetLeft - pos1) + "px";
|
|
||||||
el.style.right = 'auto';
|
|
||||||
el.style.bottom = 'auto';
|
|
||||||
}
|
|
||||||
|
|
||||||
function closeDragElement() {
|
|
||||||
document.onmouseup = null;
|
|
||||||
document.onmousemove = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ============ Sounds & Celebrations ============
|
// ============ Sounds & Celebrations ============
|
||||||
|
|
||||||
showCelebration(task: FocusTask) {
|
showCelebration(task: FocusTask) {
|
||||||
@@ -612,6 +542,16 @@ export default class FocusTaskPlugin extends Plugin {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Light refresh - only updates timer display without rebuilding DOM
|
||||||
|
updateTimerDisplay() {
|
||||||
|
const leaves = this.app.workspace.getLeavesOfType(VIEW_TYPE_FOCUS_TASK);
|
||||||
|
leaves.forEach(leaf => {
|
||||||
|
if (leaf.view instanceof FocusTaskView) {
|
||||||
|
leaf.view.updateTimerDisplay();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
getTasksByList(listId: string): FocusTask[] {
|
getTasksByList(listId: string): FocusTask[] {
|
||||||
return this.data.tasks.filter(t => t.list === listId);
|
return this.data.tasks.filter(t => t.list === listId);
|
||||||
}
|
}
|
||||||
@@ -761,20 +701,6 @@ class FocusTaskSettingTab extends PluginSettingTab {
|
|||||||
await this.plugin.saveAllData();
|
await this.plugin.saveAllData();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
new Setting(containerEl)
|
|
||||||
.setName('Show Floating Timer')
|
|
||||||
.setDesc('Display a draggable floating timer widget')
|
|
||||||
.addToggle(toggle => toggle
|
|
||||||
.setValue(this.plugin.settings.showFloatingTimer)
|
|
||||||
.onChange(async value => {
|
|
||||||
this.plugin.settings.showFloatingTimer = value;
|
|
||||||
if (value) {
|
|
||||||
this.plugin.createFloatingTimer();
|
|
||||||
} else {
|
|
||||||
this.plugin.removeFloatingTimer();
|
|
||||||
}
|
|
||||||
await this.plugin.saveAllData();
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Lists Management
|
// Lists Management
|
||||||
containerEl.createEl('h2', { text: '📋 Lists' });
|
containerEl.createEl('h2', { text: '📋 Lists' });
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export interface FocusTaskSettings {
|
|||||||
enableCelebrations: boolean;
|
enableCelebrations: boolean;
|
||||||
defaultEstimateMinutes: number;
|
defaultEstimateMinutes: number;
|
||||||
lists: TaskList[];
|
lists: TaskList[];
|
||||||
showFloatingTimer: boolean;
|
showFloatingTimer: true;
|
||||||
autoStartBreak: boolean;
|
autoStartBreak: boolean;
|
||||||
tickSoundEnabled: boolean;
|
tickSoundEnabled: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
65
src/view.ts
65
src/view.ts
@@ -13,6 +13,12 @@ export class FocusTaskView extends ItemView {
|
|||||||
plugin: FocusTaskPlugin;
|
plugin: FocusTaskPlugin;
|
||||||
currentFilter: string = 'all';
|
currentFilter: string = 'all';
|
||||||
|
|
||||||
|
// References to elements that need frequent updates
|
||||||
|
private timerTimeEl: HTMLElement | null = null;
|
||||||
|
private progressBarEl: HTMLElement | null = null;
|
||||||
|
private actualTimeEl: HTMLElement | null = null;
|
||||||
|
private pauseBtnEl: HTMLElement | null = null;
|
||||||
|
|
||||||
constructor(leaf: WorkspaceLeaf, plugin: FocusTaskPlugin) {
|
constructor(leaf: WorkspaceLeaf, plugin: FocusTaskPlugin) {
|
||||||
super(leaf);
|
super(leaf);
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
@@ -34,11 +40,48 @@ export class FocusTaskView extends ItemView {
|
|||||||
this.refresh();
|
this.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Light update - only updates timer display without rebuilding DOM
|
||||||
|
updateTimerDisplay() {
|
||||||
|
if (!this.timerTimeEl) return;
|
||||||
|
|
||||||
|
// Update timer text
|
||||||
|
this.timerTimeEl.textContent = this.plugin.formatTime(this.plugin.currentTimerSeconds);
|
||||||
|
|
||||||
|
// Update progress bar
|
||||||
|
if (this.progressBarEl) {
|
||||||
|
let progressPercent = 0;
|
||||||
|
if (this.plugin.isBreakMode) {
|
||||||
|
const breakDuration = this.plugin.pomodoroCount % this.plugin.settings.longBreakInterval === 0
|
||||||
|
? this.plugin.settings.longBreakMinutes * 60
|
||||||
|
: this.plugin.settings.pomodoroBreakMinutes * 60;
|
||||||
|
progressPercent = ((breakDuration - this.plugin.currentTimerSeconds) / breakDuration) * 100;
|
||||||
|
} else {
|
||||||
|
const workDuration = this.plugin.settings.pomodoroWorkMinutes * 60;
|
||||||
|
progressPercent = ((workDuration - this.plugin.currentTimerSeconds) / workDuration) * 100;
|
||||||
|
}
|
||||||
|
this.progressBarEl.style.width = `${Math.min(Math.max(progressPercent, 0), 100)}%`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update actual time display
|
||||||
|
if (this.actualTimeEl && this.plugin.activeTaskId) {
|
||||||
|
const task = this.plugin.data.tasks.find(t => t.id === this.plugin.activeTaskId);
|
||||||
|
if (task) {
|
||||||
|
this.actualTimeEl.textContent = `Actual: ${this.plugin.formatTimeHuman(task.actualMinutes)}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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('focus-task-container');
|
||||||
|
|
||||||
|
// Reset element references
|
||||||
|
this.timerTimeEl = null;
|
||||||
|
this.progressBarEl = null;
|
||||||
|
this.actualTimeEl = null;
|
||||||
|
this.pauseBtnEl = null;
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
this.renderHeader(container);
|
this.renderHeader(container);
|
||||||
|
|
||||||
@@ -109,16 +152,16 @@ export class FocusTaskView extends ItemView {
|
|||||||
|
|
||||||
activeCard.createEl('div', { cls: 'focus-task-active-task-name', text: task.text });
|
activeCard.createEl('div', { cls: 'focus-task-active-task-name', text: task.text });
|
||||||
|
|
||||||
// Timer display
|
// Timer display - store reference for updates
|
||||||
const timerDisplay = activeCard.createEl('div', { cls: 'focus-task-timer-display' });
|
const timerDisplay = activeCard.createEl('div', { cls: 'focus-task-timer-display' });
|
||||||
timerDisplay.createEl('span', {
|
this.timerTimeEl = timerDisplay.createEl('span', {
|
||||||
cls: 'focus-task-timer-time',
|
cls: 'focus-task-timer-time',
|
||||||
text: this.plugin.formatTime(this.plugin.currentTimerSeconds)
|
text: this.plugin.formatTime(this.plugin.currentTimerSeconds)
|
||||||
});
|
});
|
||||||
|
|
||||||
// Progress bar
|
// Progress bar - store reference for updates
|
||||||
const progressWrap = activeCard.createEl('div', { cls: 'focus-task-progress-wrap' });
|
const progressWrap = activeCard.createEl('div', { cls: 'focus-task-progress-wrap' });
|
||||||
const progress = progressWrap.createEl('div', { cls: 'focus-task-progress-bar' });
|
this.progressBarEl = progressWrap.createEl('div', { cls: 'focus-task-progress-bar' });
|
||||||
|
|
||||||
let progressPercent = 0;
|
let progressPercent = 0;
|
||||||
if (this.plugin.isBreakMode) {
|
if (this.plugin.isBreakMode) {
|
||||||
@@ -131,22 +174,22 @@ export class FocusTaskView extends ItemView {
|
|||||||
progressPercent = ((workDuration - this.plugin.currentTimerSeconds) / workDuration) * 100;
|
progressPercent = ((workDuration - this.plugin.currentTimerSeconds) / workDuration) * 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
progress.style.width = `${Math.min(Math.max(progressPercent, 0), 100)}%`;
|
this.progressBarEl.style.width = `${Math.min(Math.max(progressPercent, 0), 100)}%`;
|
||||||
if (progressPercent >= 100) progress.addClass('focus-task-overtime');
|
if (progressPercent >= 100) this.progressBarEl.addClass('focus-task-overtime');
|
||||||
|
|
||||||
// Time info
|
// 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: 'focus-task-time-info' });
|
||||||
timeInfo.createEl('span', { text: `Est: ${this.plugin.formatTimeHuman(task.estimatedMinutes)}` });
|
timeInfo.createEl('span', { text: `Est: ${this.plugin.formatTimeHuman(task.estimatedMinutes)}` });
|
||||||
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: 'focus-task-active-controls' });
|
||||||
|
|
||||||
const pauseBtn = controls.createEl('button', { cls: 'focus-task-btn focus-task-btn-secondary' });
|
this.pauseBtnEl = controls.createEl('button', { cls: 'focus-task-btn focus-task-btn-secondary' });
|
||||||
pauseBtn.innerHTML = this.plugin.isTimerRunning ? '⏸ Pause' : '▶ Resume';
|
this.pauseBtnEl.innerHTML = this.plugin.isTimerRunning ? '⏸ Pause' : '▶ Resume';
|
||||||
pauseBtn.addEventListener('click', () => this.plugin.toggleTimer());
|
this.pauseBtnEl.addEventListener('click', () => this.plugin.toggleTimer());
|
||||||
|
|
||||||
if (!this.plugin.isBreakMode) {
|
if (!this.plugin.isBreakMode) {
|
||||||
const completeBtn = controls.createEl('button', { cls: 'focus-task-btn focus-task-btn-success' });
|
const completeBtn = controls.createEl('button', { cls: 'focus-task-btn focus-task-btn-success' });
|
||||||
|
|||||||
90
styles.css
90
styles.css
@@ -512,86 +512,24 @@
|
|||||||
background: var(--ft-danger);
|
background: var(--ft-danger);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============ Floating Timer ============ */
|
/* ============ Status Bar Timer ============ */
|
||||||
.focus-task-floating-timer {
|
.focus-task-status-bar {
|
||||||
position: fixed;
|
cursor: pointer;
|
||||||
bottom: 20px;
|
padding: 0 8px;
|
||||||
right: 20px;
|
display: flex;
|
||||||
z-index: 9999;
|
align-items: center;
|
||||||
background: var(--background-primary);
|
gap: 4px;
|
||||||
border: 1px solid var(--background-modifier-border);
|
font-size: 12px;
|
||||||
border-radius: 16px;
|
transition: all 0.2s ease;
|
||||||
padding: 12px 16px;
|
|
||||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
|
|
||||||
cursor: move;
|
|
||||||
min-width: 180px;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.focus-task-floating-timer:hover {
|
.focus-task-status-bar:hover {
|
||||||
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3);
|
color: var(--text-accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
.focus-task-floating-timer.focus-task-active {
|
.focus-task-status-bar.focus-task-status-active {
|
||||||
border-color: var(--ft-primary);
|
color: var(--text-accent);
|
||||||
box-shadow: 0 8px 32px rgba(99, 102, 241, 0.3);
|
font-weight: 500;
|
||||||
}
|
|
||||||
|
|
||||||
.focus-task-floating-timer.focus-task-break-mode {
|
|
||||||
border-color: var(--ft-break);
|
|
||||||
box-shadow: 0 8px 32px rgba(6, 182, 212, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.focus-task-floating-inner {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.focus-task-floating-task {
|
|
||||||
font-size: 12px;
|
|
||||||
color: var(--text-muted);
|
|
||||||
max-width: 150px;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.focus-task-floating-time {
|
|
||||||
font-size: 28px;
|
|
||||||
font-weight: 700;
|
|
||||||
font-variant-numeric: tabular-nums;
|
|
||||||
color: var(--ft-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.focus-task-floating-time.focus-task-overtime {
|
|
||||||
color: var(--ft-warning);
|
|
||||||
}
|
|
||||||
|
|
||||||
.focus-task-floating-controls {
|
|
||||||
display: flex;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.focus-task-float-btn {
|
|
||||||
width: 36px;
|
|
||||||
height: 36px;
|
|
||||||
border-radius: 50%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
background: var(--ft-bg-secondary);
|
|
||||||
border: 1px solid var(--ft-border);
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 14px;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.focus-task-float-btn:hover {
|
|
||||||
background: var(--ft-primary);
|
|
||||||
color: white;
|
|
||||||
border-color: var(--ft-primary);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============ Modal Styles ============ */
|
/* ============ Modal Styles ============ */
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"1.0.0": "0.15.0"
|
"1.0.1": "0.15.0"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user