Skip to content

No Hiding button ? #7

@Medamine-Bahassou

Description

@Medamine-Bahassou

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();

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions