mirror of
https://github.com/wth461694678/text-block-timer.git
synced 2026-07-22 05:46:04 +00:00
Feature: Enhance Apperance Settings
This commit is contained in:
parent
ac225c738e
commit
9c34f8e82b
3 changed files with 565 additions and 60 deletions
|
|
@ -8,5 +8,10 @@
|
|||
"pathRestrictionPaths": [],
|
||||
"runningIcon": "⏳",
|
||||
"pausedIcon": "💐",
|
||||
"timeDisplayFormat": "smart"
|
||||
"timeDisplayFormat": "smart",
|
||||
"timerDisplayStyle": "badge",
|
||||
"runningTextColor": "#10b981",
|
||||
"runningBgColor": "rgba(16, 185, 129, 0.15)",
|
||||
"pausedTextColor": "#6b7280",
|
||||
"pausedBgColor": "rgba(107, 114, 128, 0.12)"
|
||||
}
|
||||
456
main.js
456
main.js
|
|
@ -18,7 +18,11 @@ class TimerWidget extends WidgetType {
|
|||
|
||||
toDOM() {
|
||||
const span = document.createElement('span');
|
||||
span.className = 'timer-widget-display';
|
||||
|
||||
// Detect running vs paused state from the HTML class
|
||||
const isRunning = this.htmlText.includes('class="timer-r"');
|
||||
const stateClass = isRunning ? 'timer-widget-running' : 'timer-widget-paused';
|
||||
span.className = `timer-widget-display ${stateClass}`;
|
||||
|
||||
// Extract visible content from HTML (【⏳00:00:00 】)
|
||||
const match = this.htmlText.match(/>([^<]*)<\/span>/);
|
||||
|
|
@ -482,7 +486,8 @@ const TRANSLATIONS = {
|
|||
bycheckbox: {
|
||||
name: "Timer by Checkbox",
|
||||
desc: "Configure checkbox-based timer controls"
|
||||
}
|
||||
},
|
||||
appearance: { name: "Appearance Settings" }
|
||||
},
|
||||
autostop: {
|
||||
name: "Auto-stop timers",
|
||||
|
|
@ -519,6 +524,32 @@ const TRANSLATIONS = {
|
|||
smart: "Smart Format - Hide hours when zero (MM:SS), show full format (HH:MM:SS) when > 1 hour"
|
||||
}
|
||||
},
|
||||
timerDisplayStyle: {
|
||||
name: "Timer Display Style",
|
||||
desc: "Choose the visual style for timer display (applies to both edit and reading modes)",
|
||||
choice: {
|
||||
badge: "Badge - Timer shown as a styled badge with background and border",
|
||||
plain: "Plain - Timer shown as simple colored text"
|
||||
}
|
||||
},
|
||||
timerColors: {
|
||||
runningText: {
|
||||
name: "Running Timer Text Color",
|
||||
desc: "Text color for running timers"
|
||||
},
|
||||
runningBg: {
|
||||
name: "Running Timer Background Color",
|
||||
desc: "Background color for running timers (badge mode only)"
|
||||
},
|
||||
pausedText: {
|
||||
name: "Paused Timer Text Color",
|
||||
desc: "Text color for paused timers"
|
||||
},
|
||||
pausedBg: {
|
||||
name: "Paused Timer Background Color",
|
||||
desc: "Background color for paused timers (badge mode only)"
|
||||
}
|
||||
},
|
||||
enableCheckboxToTimer: {
|
||||
name: "Enable checkbox to timer",
|
||||
desc: "Allow checkboxes to control timers",
|
||||
|
|
@ -569,7 +600,8 @@ const TRANSLATIONS = {
|
|||
bycheckbox: {
|
||||
name: "通过任务状态自动控制计时器",
|
||||
desc: "你可以在切换任务状态(复选框类型)的同时,自动生成或更新计时器,对Tasks Plugin(任务插件)用户友好"
|
||||
}
|
||||
},
|
||||
appearance: { name: "外观设置" }
|
||||
},
|
||||
autostop: {
|
||||
name: "自动停止计时器",
|
||||
|
|
@ -606,6 +638,32 @@ const TRANSLATIONS = {
|
|||
smart: "智能格式 - 小时为零时隐藏 (MM:SS),超过1小时时显示完整格式 (HH:MM:SS)"
|
||||
}
|
||||
},
|
||||
timerDisplayStyle: {
|
||||
name: "计时器显示风格",
|
||||
desc: "选择计时器的显示风格(同时应用于编辑模式和阅读模式)",
|
||||
choice: {
|
||||
badge: "徽章样式 - 带背景色和边框的标签风格",
|
||||
plain: "纯文本样式 - 仅显示彩色文字"
|
||||
}
|
||||
},
|
||||
timerColors: {
|
||||
runningText: {
|
||||
name: "运行中计时器文字颜色",
|
||||
desc: "运行中计时器的文字颜色"
|
||||
},
|
||||
runningBg: {
|
||||
name: "运行中计时器背景颜色",
|
||||
desc: "运行中计时器的背景颜色(仅徽章模式)"
|
||||
},
|
||||
pausedText: {
|
||||
name: "已暂停计时器文字颜色",
|
||||
desc: "已暂停计时器的文字颜色"
|
||||
},
|
||||
pausedBg: {
|
||||
name: "已暂停计时器背景颜色",
|
||||
desc: "已暂停计时器的背景颜色(仅徽章模式)"
|
||||
}
|
||||
},
|
||||
enableCheckboxToTimer: {
|
||||
name: "使用任务状态控制计时器",
|
||||
desc: "启用此功能后,你可以通过更改任务框的状态自动控制计时器的启动、暂停、继续",
|
||||
|
|
@ -656,7 +714,8 @@ const TRANSLATIONS = {
|
|||
bycheckbox: {
|
||||
name: "通過任務狀態自動控制計時器",
|
||||
desc: "你可以在切換任務狀態的同時,自动生成或更新計時器,對Tasks Plugin(任務插件)用戶友好"
|
||||
}
|
||||
},
|
||||
appearance: { name: "外觀設定" }
|
||||
},
|
||||
autostop: {
|
||||
name: "自動停止計時器",
|
||||
|
|
@ -693,6 +752,32 @@ const TRANSLATIONS = {
|
|||
smart: "智能格式 - 小時為零時隱藏 (MM:SS),超過1小時時顯示完整格式 (HH:MM:SS)"
|
||||
}
|
||||
},
|
||||
timerDisplayStyle: {
|
||||
name: "計時器顯示風格",
|
||||
desc: "選擇計時器的顯示風格(同時應用於編輯模式和閱讀模式)",
|
||||
choice: {
|
||||
badge: "徽章樣式 - 帶背景色和邊框的標籤風格",
|
||||
plain: "純文字樣式 - 僅顯示彩色文字"
|
||||
}
|
||||
},
|
||||
timerColors: {
|
||||
runningText: {
|
||||
name: "運行中計時器文字顏色",
|
||||
desc: "運行中計時器的文字顏色"
|
||||
},
|
||||
runningBg: {
|
||||
name: "運行中計時器背景顏色",
|
||||
desc: "運行中計時器的背景顏色(僅徽章模式)"
|
||||
},
|
||||
pausedText: {
|
||||
name: "已暫停計時器文字顏色",
|
||||
desc: "已暫停計時器的文字顏色"
|
||||
},
|
||||
pausedBg: {
|
||||
name: "已暫停計時器背景顏色",
|
||||
desc: "已暫停計時器的背景顏色(僅徽章模式)"
|
||||
}
|
||||
},
|
||||
enableCheckboxToTimer: {
|
||||
name: "使用任務狀態控制計時器",
|
||||
desc: "啟用此功能後,你可以通過更改任務框的狀態自動控制計時器的啟動、暫停、繼續",
|
||||
|
|
@ -743,7 +828,8 @@ const TRANSLATIONS = {
|
|||
bycheckbox: {
|
||||
name: "チェックボックスでタイマーを自動制御",
|
||||
desc: "チェックボックスを切り替えるだけでタイマーが自動作成・更新されます。Tasks プラグインユーザーに特に便利です。"
|
||||
}
|
||||
},
|
||||
appearance: { name: "外観設定" }
|
||||
},
|
||||
autostop: {
|
||||
name: "タイマーの自動停止",
|
||||
|
|
@ -780,6 +866,32 @@ const TRANSLATIONS = {
|
|||
smart: "スマートフォーマット - 0時間の場合は非表示 (MM:SS)、1時間以上の場合はフルフォーマット (HH:MM:SS) を表示"
|
||||
}
|
||||
},
|
||||
timerDisplayStyle: {
|
||||
name: "タイマー表示スタイル",
|
||||
desc: "タイマーの表示スタイルを選択してください(編集モードと閲覧モードの両方に適用されます)",
|
||||
choice: {
|
||||
badge: "バッジスタイル - 背景色と枠線付きのラベルスタイル",
|
||||
plain: "プレーンスタイル - シンプルなカラーテキスト"
|
||||
}
|
||||
},
|
||||
timerColors: {
|
||||
runningText: {
|
||||
name: "実行中タイマーの文字色",
|
||||
desc: "実行中タイマーのテキスト色"
|
||||
},
|
||||
runningBg: {
|
||||
name: "実行中タイマーの背景色",
|
||||
desc: "実行中タイマーの背景色(バッジモードのみ)"
|
||||
},
|
||||
pausedText: {
|
||||
name: "一時停止タイマーの文字色",
|
||||
desc: "一時停止タイマーのテキスト色"
|
||||
},
|
||||
pausedBg: {
|
||||
name: "一時停止タイマーの背景色",
|
||||
desc: "一時停止タイマーの背景色(バッジモードのみ)"
|
||||
}
|
||||
},
|
||||
enableCheckboxToTimer: {
|
||||
name: "タスク状態制御タイマーを使います",
|
||||
desc: "この機能を有効にすると、タスクボックスの状態を変更することでタイマーの起動、停止、継続を自働的に制御できます。",
|
||||
|
|
@ -830,7 +942,8 @@ const TRANSLATIONS = {
|
|||
bycheckbox: {
|
||||
name: "체크박스를 통한 자동 타이머 제어",
|
||||
desc: "태스크 상태를 전환하는 동안 타이머를 자동으로 생성하거나 업데이트할 수 있으며, Tasks Plugin 사용자들에게 매우 우호적입니다"
|
||||
}
|
||||
},
|
||||
appearance: { name: "외관 설정" }
|
||||
},
|
||||
autostop: {
|
||||
name: "타이머 자동 정지",
|
||||
|
|
@ -867,6 +980,32 @@ const TRANSLATIONS = {
|
|||
smart: "스마트 형식 - 0시간일 때 숨김 (MM:SS), 1시간 이상일 때 전체 형식 (HH:MM:SS) 표시"
|
||||
}
|
||||
},
|
||||
timerDisplayStyle: {
|
||||
name: "타이머 표시 스타일",
|
||||
desc: "타이머의 표시 스타일을 선택하세요 (편집 모드와 읽기 모드 모두에 적용됩니다)",
|
||||
choice: {
|
||||
badge: "배지 스타일 - 배경색과 테두리가 있는 라벨 스타일",
|
||||
plain: "일반 스타일 - 심플한 컬러 텍스트"
|
||||
}
|
||||
},
|
||||
timerColors: {
|
||||
runningText: {
|
||||
name: "실행 중 타이머 텍스트 색상",
|
||||
desc: "실행 중인 타이머의 텍스트 색상"
|
||||
},
|
||||
runningBg: {
|
||||
name: "실행 중 타이머 배경 색상",
|
||||
desc: "실행 중인 타이머의 배경 색상 (배지 모드 전용)"
|
||||
},
|
||||
pausedText: {
|
||||
name: "일시정지 타이머 텍스트 색상",
|
||||
desc: "일시정지된 타이머의 텍스트 색상"
|
||||
},
|
||||
pausedBg: {
|
||||
name: "일시정지 타이머 배경 색상",
|
||||
desc: "일시정지된 타이머의 배경 색상 (배지 모드 전용)"
|
||||
}
|
||||
},
|
||||
enableCheckboxToTimer: {
|
||||
name: "체크박스로 타이머 제어",
|
||||
desc: "이 기능을 사용하면 작업 상자의 상태를 변경하여 타이머의 시작, 일시 정지, 계속을 자동으로 제어할 수 있습니다",
|
||||
|
|
@ -1506,11 +1645,20 @@ class TimerPlugin extends obsidian.Plugin {
|
|||
pathRestrictionPaths: [],
|
||||
runningIcon: '⏳',
|
||||
pausedIcon: '💐',
|
||||
timeDisplayFormat: 'full'
|
||||
timeDisplayFormat: 'full',
|
||||
timerDisplayStyle: 'badge',
|
||||
// Color customization
|
||||
runningTextColor: '#10b981',
|
||||
runningBgColor: 'rgba(16, 185, 129, 0.15)',
|
||||
pausedTextColor: '#6b7280',
|
||||
pausedBgColor: 'rgba(107, 114, 128, 0.12)'
|
||||
};
|
||||
|
||||
await this.loadSettings();
|
||||
|
||||
// Apply timer display style to body
|
||||
this.applyDisplayStyle();
|
||||
|
||||
// Initialize TimerFileManager with settings
|
||||
this.fileManager = new TimerFileManager(this.app, this.settings);
|
||||
|
||||
|
|
@ -1685,6 +1833,15 @@ class TimerPlugin extends obsidian.Plugin {
|
|||
onunload() {
|
||||
this.manager.clearAll();
|
||||
this.fileManager.clearLocations();
|
||||
// Clean up body class
|
||||
document.body.classList.remove('timer-style-badge', 'timer-style-plain');
|
||||
// Clean up CSS custom properties
|
||||
const root = document.documentElement;
|
||||
['--timer-running-color', '--timer-running-bg', '--timer-running-border',
|
||||
'--timer-running-bg-hover', '--timer-running-border-hover',
|
||||
'--timer-paused-color', '--timer-paused-bg', '--timer-paused-border',
|
||||
'--timer-paused-bg-hover', '--timer-paused-border-hover'
|
||||
].forEach(prop => root.style.removeProperty(prop));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1954,6 +2111,63 @@ class TimerPlugin extends obsidian.Plugin {
|
|||
}
|
||||
}
|
||||
|
||||
applyDisplayStyle() {
|
||||
const style = this.settings.timerDisplayStyle || 'badge';
|
||||
document.body.classList.remove('timer-style-badge', 'timer-style-plain');
|
||||
document.body.classList.add(`timer-style-${style}`);
|
||||
this.applyTimerColors();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a hex color to rgba with given alpha
|
||||
*/
|
||||
hexToRgba(hex, alpha) {
|
||||
const r = parseInt(hex.slice(1, 3), 16);
|
||||
const g = parseInt(hex.slice(3, 5), 16);
|
||||
const b = parseInt(hex.slice(5, 7), 16);
|
||||
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply user-customized timer colors as CSS custom properties
|
||||
*/
|
||||
applyTimerColors() {
|
||||
const root = document.documentElement;
|
||||
const s = this.settings;
|
||||
|
||||
// Running colors
|
||||
const runningColor = s.runningTextColor || '#10b981';
|
||||
const runningBg = s.runningBgColor || 'rgba(16, 185, 129, 0.15)';
|
||||
root.style.setProperty('--timer-running-color', runningColor);
|
||||
root.style.setProperty('--timer-running-bg', runningBg);
|
||||
|
||||
// Compute border & hover variants from bg
|
||||
// Parse runningBg to derive border (higher alpha) and hover (higher alpha)
|
||||
const runningBgMatch = runningBg.match(/rgba?\((\d+),\s*(\d+),\s*(\d+),?\s*([\d.]*)\)/);
|
||||
if (runningBgMatch) {
|
||||
const [, rr, rg, rb, ra] = runningBgMatch;
|
||||
const baseAlpha = parseFloat(ra) || 0.15;
|
||||
root.style.setProperty('--timer-running-border', `rgba(${rr}, ${rg}, ${rb}, ${Math.min(baseAlpha + 0.15, 1)})`);
|
||||
root.style.setProperty('--timer-running-bg-hover', `rgba(${rr}, ${rg}, ${rb}, ${Math.min(baseAlpha + 0.1, 1)})`);
|
||||
root.style.setProperty('--timer-running-border-hover', `rgba(${rr}, ${rg}, ${rb}, ${Math.min(baseAlpha + 0.35, 1)})`);
|
||||
}
|
||||
|
||||
// Paused colors
|
||||
const pausedColor = s.pausedTextColor || '#6b7280';
|
||||
const pausedBg = s.pausedBgColor || 'rgba(107, 114, 128, 0.12)';
|
||||
root.style.setProperty('--timer-paused-color', pausedColor);
|
||||
root.style.setProperty('--timer-paused-bg', pausedBg);
|
||||
|
||||
const pausedBgMatch = pausedBg.match(/rgba?\((\d+),\s*(\d+),\s*(\d+),?\s*([\d.]*)\)/);
|
||||
if (pausedBgMatch) {
|
||||
const [, pr, pg, pb, pa] = pausedBgMatch;
|
||||
const baseAlpha = parseFloat(pa) || 0.12;
|
||||
root.style.setProperty('--timer-paused-border', `rgba(${pr}, ${pg}, ${pb}, ${Math.min(baseAlpha + 0.13, 1)})`);
|
||||
root.style.setProperty('--timer-paused-bg-hover', `rgba(${pr}, ${pg}, ${pb}, ${Math.min(baseAlpha + 0.08, 1)})`);
|
||||
root.style.setProperty('--timer-paused-border-hover', `rgba(${pr}, ${pg}, ${pb}, ${Math.min(baseAlpha + 0.28, 1)})`);
|
||||
}
|
||||
}
|
||||
|
||||
toggleTimerbyCheckboxState(oldCheckboxState, newCheckboxState, newLineText, view, lineNum) {
|
||||
|
||||
if (oldCheckboxState === '') {
|
||||
|
|
@ -1996,6 +2210,20 @@ class TimerSettingTab extends obsidian.PluginSettingTab {
|
|||
return filePath + '/';
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert rgba string to hex color for color picker input
|
||||
*/
|
||||
rgbaToHex(rgba) {
|
||||
const match = rgba.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
|
||||
if (match) {
|
||||
const r = parseInt(match[1]).toString(16).padStart(2, '0');
|
||||
const g = parseInt(match[2]).toString(16).padStart(2, '0');
|
||||
const b = parseInt(match[3]).toString(16).padStart(2, '0');
|
||||
return `#${r}${g}${b}`;
|
||||
}
|
||||
return rgba; // fallback if already hex
|
||||
}
|
||||
|
||||
display() {
|
||||
const { containerEl } = this;
|
||||
containerEl.empty();
|
||||
|
|
@ -2054,47 +2282,6 @@ class TimerSettingTab extends obsidian.PluginSettingTab {
|
|||
});
|
||||
});
|
||||
|
||||
// Timer icon settings
|
||||
new obsidian.Setting(containerEl)
|
||||
.setName(lang.timerIcon.runningIcon.name)
|
||||
.setDesc(lang.timerIcon.runningIcon.desc)
|
||||
.addText(text => {
|
||||
text
|
||||
.setValue(this.plugin.settings.runningIcon)
|
||||
.onChange(async(value) => {
|
||||
this.plugin.settings.runningIcon = value || '⏳';
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
|
||||
new obsidian.Setting(containerEl)
|
||||
.setName(lang.timerIcon.pausedIcon.name)
|
||||
.setDesc(lang.timerIcon.pausedIcon.desc)
|
||||
.addText(text => {
|
||||
text
|
||||
.setValue(this.plugin.settings.pausedIcon)
|
||||
.onChange(async(value) => {
|
||||
this.plugin.settings.pausedIcon = value || '💐';
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
|
||||
// Time display format settings
|
||||
const timeFormatLang = lang.timeDisplayFormat;
|
||||
new obsidian.Setting(containerEl)
|
||||
.setName(timeFormatLang.name)
|
||||
.setDesc(timeFormatLang.desc)
|
||||
.addDropdown(dropdown => {
|
||||
dropdown
|
||||
.addOption('full', timeFormatLang.choice.full)
|
||||
.addOption('smart', timeFormatLang.choice.smart)
|
||||
.setValue(this.plugin.settings.timeDisplayFormat || 'full')
|
||||
.onChange(async(value) => {
|
||||
this.plugin.settings.timeDisplayFormat = value;
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
|
||||
containerEl.createEl('div', { text: '' });
|
||||
containerEl.createEl('h3', { text: lang.sections.bycommand.name });
|
||||
new obsidian.Setting(containerEl)
|
||||
|
|
@ -2255,6 +2442,179 @@ class TimerSettingTab extends obsidian.PluginSettingTab {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===== Appearance Settings Section =====
|
||||
containerEl.createEl('div', { text: '' });
|
||||
containerEl.createEl('h3', { text: lang.sections.appearance.name });
|
||||
|
||||
// Time display format settings
|
||||
const timeFormatLang = lang.timeDisplayFormat;
|
||||
new obsidian.Setting(containerEl)
|
||||
.setName(timeFormatLang.name)
|
||||
.setDesc(timeFormatLang.desc)
|
||||
.addDropdown(dropdown => {
|
||||
dropdown
|
||||
.addOption('full', timeFormatLang.choice.full)
|
||||
.addOption('smart', timeFormatLang.choice.smart)
|
||||
.setValue(this.plugin.settings.timeDisplayFormat || 'full')
|
||||
.onChange(async(value) => {
|
||||
this.plugin.settings.timeDisplayFormat = value;
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
|
||||
// Timer display style settings
|
||||
const displayStyleLang = lang.timerDisplayStyle;
|
||||
new obsidian.Setting(containerEl)
|
||||
.setName(displayStyleLang.name)
|
||||
.setDesc(displayStyleLang.desc)
|
||||
.addDropdown(dropdown => {
|
||||
dropdown
|
||||
.addOption('badge', displayStyleLang.choice.badge)
|
||||
.addOption('plain', displayStyleLang.choice.plain)
|
||||
.setValue(this.plugin.settings.timerDisplayStyle || 'badge')
|
||||
.onChange(async(value) => {
|
||||
this.plugin.settings.timerDisplayStyle = value;
|
||||
await this.plugin.saveSettings();
|
||||
this.plugin.applyDisplayStyle();
|
||||
this.display(); // Re-render to show/hide bg color pickers
|
||||
});
|
||||
});
|
||||
|
||||
// Color customization settings
|
||||
const colorLang = lang.timerColors;
|
||||
const isBadge = (this.plugin.settings.timerDisplayStyle || 'badge') === 'badge';
|
||||
|
||||
// Helper: create a color picker setting
|
||||
const addColorSetting = (name, desc, settingKey, defaultColor) => {
|
||||
const setting = new obsidian.Setting(containerEl)
|
||||
.setName(name)
|
||||
.setDesc(desc);
|
||||
setting.controlEl.createEl('input', {
|
||||
type: 'color',
|
||||
value: this.plugin.settings[settingKey] || defaultColor,
|
||||
cls: 'timer-color-input-native'
|
||||
}, (input) => {
|
||||
input.style.width = '40px';
|
||||
input.style.height = '30px';
|
||||
input.style.border = 'none';
|
||||
input.style.padding = '0';
|
||||
input.style.cursor = 'pointer';
|
||||
input.style.backgroundColor = 'transparent';
|
||||
input.addEventListener('input', async(e) => {
|
||||
this.plugin.settings[settingKey] = e.target.value;
|
||||
// For bg color, convert hex to rgba
|
||||
if (settingKey.endsWith('BgColor')) {
|
||||
const hex = e.target.value;
|
||||
const r = parseInt(hex.slice(1, 3), 16);
|
||||
const g = parseInt(hex.slice(3, 5), 16);
|
||||
const b = parseInt(hex.slice(5, 7), 16);
|
||||
this.plugin.settings[settingKey] = `rgba(${r}, ${g}, ${b}, 0.15)`;
|
||||
}
|
||||
await this.plugin.saveSettings();
|
||||
this.plugin.applyTimerColors();
|
||||
});
|
||||
});
|
||||
return setting;
|
||||
};
|
||||
|
||||
// Running timer icon
|
||||
new obsidian.Setting(containerEl)
|
||||
.setName(lang.timerIcon.runningIcon.name)
|
||||
.setDesc(lang.timerIcon.runningIcon.desc)
|
||||
.addText(text => {
|
||||
text
|
||||
.setValue(this.plugin.settings.runningIcon)
|
||||
.onChange(async(value) => {
|
||||
this.plugin.settings.runningIcon = value || '⏳';
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
|
||||
// Running text color
|
||||
addColorSetting(
|
||||
colorLang.runningText.name,
|
||||
colorLang.runningText.desc,
|
||||
'runningTextColor',
|
||||
'#10b981'
|
||||
);
|
||||
|
||||
// Running bg color (badge mode only)
|
||||
if (isBadge) {
|
||||
const runBgSetting = new obsidian.Setting(containerEl)
|
||||
.setName(colorLang.runningBg.name)
|
||||
.setDesc(colorLang.runningBg.desc);
|
||||
runBgSetting.controlEl.createEl('input', {
|
||||
type: 'color',
|
||||
value: this.rgbaToHex(this.plugin.settings.runningBgColor || 'rgba(16, 185, 129, 0.15)'),
|
||||
cls: 'timer-color-input-native'
|
||||
}, (input) => {
|
||||
input.style.width = '40px';
|
||||
input.style.height = '30px';
|
||||
input.style.border = 'none';
|
||||
input.style.padding = '0';
|
||||
input.style.cursor = 'pointer';
|
||||
input.style.backgroundColor = 'transparent';
|
||||
input.addEventListener('input', async(e) => {
|
||||
const hex = e.target.value;
|
||||
const r = parseInt(hex.slice(1, 3), 16);
|
||||
const g = parseInt(hex.slice(3, 5), 16);
|
||||
const b = parseInt(hex.slice(5, 7), 16);
|
||||
this.plugin.settings.runningBgColor = `rgba(${r}, ${g}, ${b}, 0.15)`;
|
||||
await this.plugin.saveSettings();
|
||||
this.plugin.applyTimerColors();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Paused timer icon
|
||||
new obsidian.Setting(containerEl)
|
||||
.setName(lang.timerIcon.pausedIcon.name)
|
||||
.setDesc(lang.timerIcon.pausedIcon.desc)
|
||||
.addText(text => {
|
||||
text
|
||||
.setValue(this.plugin.settings.pausedIcon)
|
||||
.onChange(async(value) => {
|
||||
this.plugin.settings.pausedIcon = value || '💐';
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
|
||||
// Paused text color
|
||||
addColorSetting(
|
||||
colorLang.pausedText.name,
|
||||
colorLang.pausedText.desc,
|
||||
'pausedTextColor',
|
||||
'#6b7280'
|
||||
);
|
||||
|
||||
// Paused bg color (badge mode only)
|
||||
if (isBadge) {
|
||||
const pausedBgSetting = new obsidian.Setting(containerEl)
|
||||
.setName(colorLang.pausedBg.name)
|
||||
.setDesc(colorLang.pausedBg.desc);
|
||||
pausedBgSetting.controlEl.createEl('input', {
|
||||
type: 'color',
|
||||
value: this.rgbaToHex(this.plugin.settings.pausedBgColor || 'rgba(107, 114, 128, 0.12)'),
|
||||
cls: 'timer-color-input-native'
|
||||
}, (input) => {
|
||||
input.style.width = '40px';
|
||||
input.style.height = '30px';
|
||||
input.style.border = 'none';
|
||||
input.style.padding = '0';
|
||||
input.style.cursor = 'pointer';
|
||||
input.style.backgroundColor = 'transparent';
|
||||
input.addEventListener('input', async(e) => {
|
||||
const hex = e.target.value;
|
||||
const r = parseInt(hex.slice(1, 3), 16);
|
||||
const g = parseInt(hex.slice(3, 5), 16);
|
||||
const b = parseInt(hex.slice(5, 7), 16);
|
||||
this.plugin.settings.pausedBgColor = `rgba(${r}, ${g}, ${b}, 0.12)`;
|
||||
await this.plugin.saveSettings();
|
||||
this.plugin.applyTimerColors();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
162
styles.css
162
styles.css
|
|
@ -1,27 +1,167 @@
|
|||
.timer-r {
|
||||
color: #10b981;
|
||||
/* ===== CSS Custom Properties (defaults, overridden by JS) ===== */
|
||||
|
||||
:root {
|
||||
/* Running timer colors */
|
||||
--timer-running-color: #10b981;
|
||||
--timer-running-bg: rgba(16, 185, 129, 0.15);
|
||||
--timer-running-border: rgba(16, 185, 129, 0.3);
|
||||
--timer-running-bg-hover: rgba(16, 185, 129, 0.25);
|
||||
--timer-running-border-hover: rgba(16, 185, 129, 0.5);
|
||||
/* Paused timer colors */
|
||||
--timer-paused-color: #6b7280;
|
||||
--timer-paused-bg: rgba(107, 114, 128, 0.12);
|
||||
--timer-paused-border: rgba(107, 114, 128, 0.25);
|
||||
--timer-paused-bg-hover: rgba(107, 114, 128, 0.2);
|
||||
--timer-paused-border-hover: rgba(107, 114, 128, 0.4);
|
||||
}
|
||||
|
||||
|
||||
/* Timer widget display in edit mode */
|
||||
/* ===== Common widget base ===== */
|
||||
|
||||
.timer-widget-display {
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
|
||||
/* ===== Badge Style (default) ===== */
|
||||
|
||||
|
||||
/* Badge common properties */
|
||||
|
||||
.timer-style-badge .timer-r,
|
||||
.timer-style-badge .timer-p,
|
||||
.timer-style-badge .timer-widget-running,
|
||||
.timer-style-badge .timer-widget-paused {
|
||||
display: inline-block;
|
||||
padding: 0 4px;
|
||||
margin: 0 2px;
|
||||
border-radius: 3px;
|
||||
background-color: rgba(16, 185, 129, 0.15);
|
||||
color: #10b981;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
border: 1px solid rgba(16, 185, 129, 0.3);
|
||||
font-family: system-ui, -apple-system, sans-serif;
|
||||
font-size: 0.95em;
|
||||
transition: background-color 0.2s ease;
|
||||
transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;
|
||||
}
|
||||
|
||||
.timer-widget-display:hover {
|
||||
background-color: rgba(16, 185, 129, 0.25);
|
||||
border-color: rgba(16, 185, 129, 0.5);
|
||||
|
||||
/* Badge - Running timer (preview mode) */
|
||||
|
||||
.timer-style-badge .timer-r {
|
||||
background-color: var(--timer-running-bg);
|
||||
color: var(--timer-running-color);
|
||||
border: 1px solid var(--timer-running-border);
|
||||
}
|
||||
|
||||
.timer-style-badge .timer-r:hover {
|
||||
background-color: var(--timer-running-bg-hover);
|
||||
border-color: var(--timer-running-border-hover);
|
||||
}
|
||||
|
||||
|
||||
/* Badge - Paused timer (preview mode) */
|
||||
|
||||
.timer-style-badge .timer-p {
|
||||
background-color: var(--timer-paused-bg);
|
||||
color: var(--timer-paused-color);
|
||||
border: 1px solid var(--timer-paused-border);
|
||||
}
|
||||
|
||||
.timer-style-badge .timer-p:hover {
|
||||
background-color: var(--timer-paused-bg-hover);
|
||||
border-color: var(--timer-paused-border-hover);
|
||||
}
|
||||
|
||||
|
||||
/* Badge - Running timer widget (edit mode) */
|
||||
|
||||
.timer-style-badge .timer-widget-running {
|
||||
background-color: var(--timer-running-bg);
|
||||
color: var(--timer-running-color);
|
||||
border: 1px solid var(--timer-running-border);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.timer-style-badge .timer-widget-running:hover {
|
||||
background-color: var(--timer-running-bg-hover);
|
||||
border-color: var(--timer-running-border-hover);
|
||||
}
|
||||
|
||||
|
||||
/* Badge - Paused timer widget (edit mode) */
|
||||
|
||||
.timer-style-badge .timer-widget-paused {
|
||||
background-color: var(--timer-paused-bg);
|
||||
color: var(--timer-paused-color);
|
||||
border: 1px solid var(--timer-paused-border);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.timer-style-badge .timer-widget-paused:hover {
|
||||
background-color: var(--timer-paused-bg-hover);
|
||||
border-color: var(--timer-paused-border-hover);
|
||||
}
|
||||
|
||||
|
||||
/* ===== Plain Style ===== */
|
||||
|
||||
|
||||
/* Plain - Running timer (preview mode) */
|
||||
|
||||
.timer-style-plain .timer-r {
|
||||
color: var(--timer-running-color);
|
||||
}
|
||||
|
||||
|
||||
/* Plain - Paused timer (preview mode) - no special style, inherit default */
|
||||
|
||||
.timer-style-plain .timer-p {
|
||||
color: var(--timer-paused-color);
|
||||
}
|
||||
|
||||
|
||||
/* Plain - Running timer widget (edit mode) */
|
||||
|
||||
.timer-style-plain .timer-widget-running {
|
||||
color: var(--timer-running-color);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
/* Plain - Paused timer widget (edit mode) */
|
||||
|
||||
.timer-style-plain .timer-widget-paused {
|
||||
color: var(--timer-paused-color);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
/* ===== Color Picker Settings UI ===== */
|
||||
|
||||
.timer-color-setting {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.timer-color-preview {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
cursor: pointer;
|
||||
transition: box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.timer-color-preview:hover {
|
||||
box-shadow: 0 0 0 2px var(--interactive-accent);
|
||||
}
|
||||
|
||||
.timer-color-input {
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
Loading…
Reference in a new issue