-
Notifications
You must be signed in to change notification settings - Fork 5
No Hiding button ? #7
Copy link
Copy link
Open
Description
my version :
translation
// Define language translations
const trans = {
'cn': {
working: '工作中',
resting: '休息中',
doWork: '干活',
takeBreak: '休息',
start: '开始',
pause: '暂停',
reset: '重置',
restNotificationTitle: '放松自己',
restNotificationBody: '该休息咯~',
workNotificationTitle: '休息好了吗?',
workNotificationBody: "干点活吧",
takeBreakMessage: '休息一会儿.',
timeToDoSomething: '该做点什么了.'
},
'en': {
working: 'Working',
resting: 'Resting',
doWork: 'Do Work',
takeBreak: 'Take Break',
start: 'Start',
pause: 'Pause',
reset: 'Reset',
restNotificationTitle: 'Relax yourself',
restNotificationBody: 'Time to take a break~',
workNotificationTitle: 'Rest well?',
workNotificationBody: "Let's do some work",
takeBreakMessage: 'Take a break.',
timeToDoSomething: 'Time to do something.',
// Add these new keys:
hide: 'Hide',
show: 'Show',
// Add these new keys:
hideWidget: 'Hide Widget',
showWidget: 'Show Widget'
},
'pt-br': {
working: 'Trabalhando',
resting: 'Descansando',
doWork: 'Trabalhar',
takeBreak: 'Descansar',
start: 'Começar',
pause: 'Pausar',
reset: 'Resetar',
restNotificationTitle: 'Pausa',
restNotificationBody: 'Hora de descansar um pouco',
workNotificationTitle: 'Descansado?',
workNotificationBody: "Mãos à massa! De volta ao trabalho.",
takeBreakMessage: 'Faça uma pausa',
timeToDoSomething: 'De volta a ativa'
},
};
module.exports = {
trans
}
tomato
/*
* Pomodoro timer for Trilium Notes.
* A gift designed for me, who suffers from lumbar disc herniation, reminding me to take a break every half an hour.
*
* 1. You can tweak configs in the `config` subnote.
* 2. i18n support, check the `translations` subnote for the translated texts.
* 3. There will be a notification tells you to rest :)
* 4. Buttons comes with sound effects so does the notification alarm.
* 5. Includes a small circular button on the right with a clock icon to hide/show the widget bar.
*/
const i18n = key => translations.trans[config.lang][key];
const initialWidgetHiddenState = localStorage.getItem('tomatoWidgetHidden') === 'true';
// Define icons
const SHOW_ICON_HTML = '<i class="bx bx-time"></i>'; // Clock icon for 'hide'
const HIDE_ICON_HTML = '<i class="bx bx-chevron-right"></i>'; // Chevron for 'show'
const TPL = `
<audio id="tomatoButtonSound" src="custom/sound/tomatoButton.mp3"></audio>
<audio id="tomatoAlarmSound" src="custom/sound/tomatoAlarm.mp3"></audio>
<div id="tomato-bar" class="tomato ${initialWidgetHiddenState ? 'widget-hidden' : ''}">
<center class="widget-content"><div id="status">${i18n('working')}</div></center>
<center class="widget-content"><div id="timer">--:--</div></center>
<button id="workButton" class="widget-content">${i18n('doWork')}</button>
<button id="restButton" class="widget-content">${i18n('takeBreak')}</button>
<button id="startButton" class="widget-content">${i18n('start')}</button>
<button id="pauseButton" class="widget-content">${i18n('pause')}</button>
<button id="resetButton" class="widget-content">${i18n('reset')}</button>
<button id="toggleWidgetButton" title="${initialWidgetHiddenState ? i18n('showWidget') : i18n('hideWidget')}">
${initialWidgetHiddenState ? SHOW_ICON_HTML : HIDE_ICON_HTML}
</button>
</div>
`;
const styles = `
#tomato-bar {
display: flex;
align-items: center;
gap: 4px;
padding: 4px;
border-top: 1px solid var(--main-border-color, #555);
border-bottom: 1px solid var(--main-border-color, #555);
contain: none;
white-space: nowrap;
overflow: hidden;
transition: padding 0.3s ease, border 0.3s ease, min-height 0.3s ease;
position: relative;
min-height: 30px; /* Adjusted for typical button heights */
background-color: var(--main-background-color, #ffffff);
color: var(--main-text-color, #000000);
}
#tomato-bar.widget-hidden {
padding: 2px;
border-top: 1px solid transparent;
border-bottom: 1px solid transparent;
background-color: transparent;
gap: 0;
justify-content: flex-end;
}
#tomato-bar.widget-hidden > .widget-content {
display: none;
}
/* Toggle Button specific styles */
#toggleWidgetButton {
order: 99;
margin-left: auto;
width: 28px; /* Slightly larger for icon */
height: 28px;
border-radius: 50%;
padding: 0;
font-size: 16px; /* Icon size */
flex-shrink: 0;
background-color: var(--button-secondary-background-color, #cccccc);
border: 1px solid var(--button-secondary-border-color, #bbbbbb);
color: var(--button-secondary-text-color, #333333);
cursor: pointer;
transition: background-color 0.3s, border-color 0.3s;
display: inline-flex; /* Use flex to center icon */
align-items: center;
justify-content: center;
}
#toggleWidgetButton:hover {
background-color: var(--button-secondary-hover-background-color, #bbbbbb);
border-color: var(--button-secondary-hover-border-color, #aaaaaa);
}
#tomato-bar.widget-hidden > #toggleWidgetButton {
display: inline-flex; /* Keep display consistent */
margin-left: 0;
}
/* Other elements */
#status {
font-size: 1em; /* Use relative units */
width: auto;
min-width: 60px;
text-align: center;
padding: 0 10px;
font-weight: bold;
color: var(--main-text-color, #000000);
}
#timer {
font-size: 1.4em; /* Use relative units */
width: 70px;
border: 2px solid var(--accent-color, #FF6347);
background-color: transparent;
border-radius: var(--button-border-radius, 5px);
text-align: center;
display: block;
padding: 2px 0;
color: var(--main-text-color, #000000);
}
/* General Button styles (excluding toggle) */
.tomato button:not(#toggleWidgetButton) {
border-radius: var(--button-border-radius, 5px);
border: 1px solid var(--button-border-color, #adadad);
padding: 6px 12px; /* Standard padding */
font-size: 0.9em; /* Relative size */
cursor: pointer;
transition: background-color 0.2s, border-color 0.2s, color 0.2s;
color: var(--button-text-color, #ffffff);
background-color: var(--button-background-color, #777777); /* Default grey */
}
.tomato button:not(#toggleWidgetButton):hover {
background-color: var(--button-hover-background-color, #666666);
border-color: var(--button-hover-border-color, #999999);
}
/* Specific Button Colors (using more standard roles) */
#workButton, #startButton {
background-color: var(--button-primary-background-color, #007bff); /* Blue */
border-color: var(--button-primary-border-color, #0069d9);
color: var(--button-primary-text-color, #ffffff);
}
#workButton:hover, #startButton:hover {
background-color: var(--button-primary-hover-background-color, #0056b3);
border-color: var(--button-primary-hover-border-color, #004085);
}
#restButton {
background-color: var(--button-success-background-color, #28a745); /* Green */
border-color: var(--button-success-border-color, #218838);
color: var(--button-success-text-color, #ffffff);
}
#restButton:hover {
background-color: var(--button-success-hover-background-color, #1e7e34);
border-color: var(--button-success-hover-border-color, #1c7430);
}
#pauseButton {
background-color: var(--button-warning-background-color, #ffc107); /* Yellow/Orange */
border-color: var(--button-warning-border-color, #e0a800);
color: var(--button-warning-text-color, #212529); /* Dark text for light bg */
}
#pauseButton:hover {
background-color: var(--button-warning-hover-background-color, #d39e00);
border-color: var(--button-warning-hover-border-color, #c69500);
}
#resetButton {
background-color: var(--button-danger-background-color, #dc3545); /* Red */
border-color: var(--button-danger-border-color, #c82333);
color: var(--button-danger-text-color, #ffffff);
}
#resetButton:hover {
background-color: var(--button-danger-hover-background-color, #bd2130);
border-color: var(--button-danger-hover-border-color, #b21f2d);
}
#tomato-bar > center {
display: flex;
align-items: center;
justify-content: center;
}
/* Ensure BoxIcons/FontAwesome load if not already available globally */
/* @import url("https://unpkg.com/boxicons@2.1.2/css/boxicons.min.css"); */
`;
var isInit = true;
var timerInterval;
class TomatoWidget extends api.NoteContextAwareWidget {
get position() { return 200; }
get parentWidget() { return "center-pane"; }
constructor() {
super();
this.title = "";
this.isWidgetHidden = localStorage.getItem('tomatoWidgetHidden') === 'true';
}
isEnabled() {
if (!super.isEnabled()) return false;
const widgetDisable = api.startNote && api.startNote.hasLabel("disable");
return !widgetDisable;
}
doRender() {
this.$widget = $(TPL);
this.statusDisplayJQ = this.$widget.find("#status");
const tomatoStatus = localStorage.getItem('tomatoStatus');
if (tomatoStatus) {
this.statusDisplayJQ.text(i18n(tomatoStatus));
} else {
this.statusDisplayJQ.text(i18n('working'));
}
this.cssBlock(styles);
return this.$widget;
}
async refreshWithNote() {
const tomatoBar = document.getElementById('tomato-bar');
const toggleWidgetButton = document.getElementById('toggleWidgetButton');
if (!isInit && tomatoBar && toggleWidgetButton) {
this.isWidgetHidden = localStorage.getItem('tomatoWidgetHidden') === 'true';
if (this.isWidgetHidden) {
tomatoBar.classList.add('widget-hidden');
toggleWidgetButton.innerHTML = SHOW_ICON_HTML;
toggleWidgetButton.setAttribute('title', i18n('showWidget'));
} else {
tomatoBar.classList.remove('widget-hidden');
toggleWidgetButton.innerHTML = HIDE_ICON_HTML;
toggleWidgetButton.setAttribute('title', i18n('hideWidget'));
}
}
if (!isInit) {
return;
}
isInit = false;
const timerDisplay = document.getElementById('timer');
const statusDisplay = document.getElementById('status');
const startButton = document.getElementById('startButton');
const pauseButton = document.getElementById('pauseButton');
const resetButton = document.getElementById('resetButton');
const workButton = document.getElementById('workButton');
const restButton = document.getElementById('restButton');
const tomatoButtonSound = document.getElementById("tomatoButtonSound");
const tomatoAlarmSound = document.getElementById("tomatoAlarmSound");
if (!tomatoBar || !toggleWidgetButton || !timerDisplay || !statusDisplay || !startButton || !pauseButton || !resetButton || !workButton || !restButton || !tomatoButtonSound || !tomatoAlarmSound) {
console.error("Tomato Timer: One or more essential elements not found. Aborting initialization.");
api.showError("Pomodoro Timer Error: Failed to find essential elements. Widget might not work correctly.");
if (this.$widget) this.$widget.html("Error loading Pomodoro Timer elements.");
return;
}
const WORK_TIME = config.WORK_TIME;
const BREAK_TIME = config.BREAK_TIME;
let isWorking = localStorage.getItem('tomatoStatus') ? localStorage.getItem('tomatoStatus') == 'working' : true;
let time = localStorage.getItem('tomatoTime') ? parseInt(localStorage.getItem('tomatoTime')): WORK_TIME;
let running = false;
const playButtonSound = () => {
if (config.enableSound){
tomatoButtonSound.currentTime = 0;
tomatoButtonSound.play().catch(e => console.error("Error playing button sound:", e));
}
}
const playAlarmSound = () => {
if (config.enableSound){
tomatoAlarmSound.currentTime = 0;
tomatoAlarmSound.play().catch(e => console.error("Error playing alarm sound:", e));
}
}
const startTimer = () => {
if (!running) {
running = true;
clearInterval(timerInterval);
timerInterval = setInterval(updateTimer, 1000);
updateTimer();
}
};
const pauseTimer = () => {
if (running) {
playButtonSound();
running = false;
clearInterval(timerInterval);
}
};
const resetTimer = () => {
playButtonSound();
running = false;
clearInterval(timerInterval);
time = isWorking ? WORK_TIME : BREAK_TIME;
localStorage.setItem('tomatoTime', time);
updateDisplay();
};
const restTimer = () => {
playButtonSound();
running = false;
clearInterval(timerInterval);
time = BREAK_TIME;
isWorking = false;
localStorage.setItem('tomatoTime', time);
localStorage.setItem('tomatoStatus', 'resting');
statusDisplay.textContent = i18n('resting');
updateDisplay();
startTimer();
};
const workTimer = () => {
playButtonSound();
running = false;
clearInterval(timerInterval);
time = WORK_TIME;
isWorking = true;
localStorage.setItem('tomatoTime', time);
localStorage.setItem('tomatoStatus', 'working');
statusDisplay.textContent = i18n('working');
updateDisplay();
startTimer();
};
const updateDisplay = () => {
const minutes = Math.floor(time / 60);
let seconds = time % 60;
seconds = seconds < 10 ? '0' + seconds : seconds;
timerDisplay.textContent = `${minutes}:${seconds}`;
};
const updateTimer = () => {
updateDisplay();
if (time > 0 && running) {
time--;
localStorage.setItem('tomatoTime', time);
} else if (time <= 0 && running) {
if (isWorking) {
new window.Notification(i18n('restNotificationTitle'), { body: i18n('restNotificationBody') });
api.showMessage(i18n('takeBreakMessage'));
playAlarmSound();
restTimer();
} else {
new window.Notification(i18n('workNotificationTitle'), { body: i18n('workNotificationBody') });
api.showMessage(i18n('timeToDoSomething'));
playAlarmSound();
workTimer();
}
}
};
startButton.addEventListener('click', () => { playButtonSound(); startTimer(); });
pauseButton.addEventListener('click', pauseTimer);
resetButton.addEventListener('click', resetTimer);
workButton.addEventListener('click', workTimer);
restButton.addEventListener('click', restTimer);
toggleWidgetButton.addEventListener('click', () => {
playButtonSound();
this.isWidgetHidden = !this.isWidgetHidden;
localStorage.setItem('tomatoWidgetHidden', this.isWidgetHidden);
if (this.isWidgetHidden) {
tomatoBar.classList.add('widget-hidden');
toggleWidgetButton.innerHTML = SHOW_ICON_HTML;
toggleWidgetButton.setAttribute('title', i18n('showWidget'));
} else {
tomatoBar.classList.remove('widget-hidden');
toggleWidgetButton.innerHTML = HIDE_ICON_HTML;
toggleWidgetButton.setAttribute('title', i18n('hideWidget'));
}
});
statusDisplay.textContent = i18n(localStorage.getItem('tomatoStatus') || 'working');
updateDisplay();
if (config.autoStartCountDown && !this.isWidgetHidden){
startTimer();
} else {
updateDisplay();
}
}
async entitiesReloadedEvent({ loadResults }) {
}
}
module.exports = new TomatoWidget();
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels