- 去支持Tempermonkey的浏览器的Add-ons安装
- 代码
- https://pomodoro.pomodorotechnique.com/ 打开后刷新一次
// ==UserScript==
// @name Automated Pomodoro with Long Break
// @namespace http://tampermonkey.net/
// @version 1.4
// @description Automated Pomodoro cycles with long breaks after user-defined intervals (e.g., every 4 pomodoros with 15 or 50 minutes break options)
// @author Syl
// @match https://pomodoro.pomodorotechnique.com/*
// @grant none
// ==/UserScript==
(function () {
'use strict';
let isRunning = false;
let timeoutHandles = [];
function findButtonByText(text) {
const buttons = Array.from(document.querySelectorAll('button'));
return buttons.find(button => button.textContent.trim() === text);
}
function simulateUserClick(element) {
if (!element) return console.error("Element not found.");
const mouseDownEvent = new MouseEvent('mousedown', { bubbles: true, cancelable: true, view: window });
const clickEvent = new MouseEvent('click', { bubbles: true, cancelable: true, view: window });
element.dispatchEvent(mouseDownEvent);
element.dispatchEvent(clickEvent);
}
function waitForButton(text, callback) {
const interval = setInterval(() => {
if (!isRunning) {
clearInterval(interval);
return;
}
const button = findButtonByText(text);
if (button) {
clearInterval(interval);
callback(button);
}
}, 500);
}
function startPomodoroCycles(cycles, longBreakInterval, longBreakTime) {
let currentCycle = 0;
function runCycle() {
if (!isRunning) return;
if (currentCycle >= cycles) {
console.log("All Pomodoro cycles completed!");
endPomodoroProcess();
return;
}
console.log(`Starting pomodoro cycle ${currentCycle + 1}`);
waitForButton("Wind Up", (windUpButton) => {
console.log("Clicking Wind Up button...");
simulateUserClick(windUpButton);
const workTimeout = setTimeout(() => {
if (!isRunning) return;
console.log(`Work session for cycle ${currentCycle + 1} completed.`);
if (longBreakInterval > 0 && (currentCycle + 1) % longBreakInterval === 0) {
console.log(`Long break required after cycle ${currentCycle + 1}.`);
waitForPageState("Take a break").then(() => {
const longBreakText = longBreakTime === 15 ? "15" : "30";
waitForButton(longBreakText, (longBreakButton) => {
simulateUserClick(longBreakButton);
const longBreakTimeout = setTimeout(() => {
if (!isRunning) return;
currentCycle++;
runCycle();
}, longBreakTime * 60 * 1000);
timeoutHandles.push(longBreakTimeout);
});
});
} else {
currentCycle++;
runCycle();
}
}, 30 * 1000 * 60);
timeoutHandles.push(workTimeout);
});
}
runCycle();
}
function endPomodoroProcess() {
console.log("Pomodoro process ended.");
isRunning = false;
}
function stopPomodoro() {
console.log("Stopping Pomodoro...");
isRunning = false;
timeoutHandles.forEach(handle => clearTimeout(handle));
timeoutHandles = [];
}
function waitForPageState(targetText, timeout = 30000) {
return new Promise((resolve, reject) => {
const interval = 500;
let elapsedTime = 0;
const checkState = setInterval(() => {
elapsedTime += interval;
if (elapsedTime > timeout) {
clearInterval(checkState);
console.error(`Timeout: Page did not reach the expected state with text "${targetText}".`);
resolve(null);
return;
}
const targetElement = Array.from(document.querySelectorAll('button, div, span'))
.find(el => el.textContent.trim() === targetText);
if (targetElement) {
clearInterval(checkState);
resolve(targetElement);
}
}, interval);
});
}
const inputContainer = document.createElement('div');
inputContainer.style.position = 'fixed';
inputContainer.style.top = '100px';
inputContainer.style.right = '25px';
inputContainer.style.backgroundColor = 'white';
inputContainer.style.border = '2px solid grey';
inputContainer.style.borderRadius = '10px'; // 添加圆角样式
inputContainer.style.padding = '10px';
inputContainer.style.zIndex = '1000';
inputContainer.style.display = 'flex';
inputContainer.style.flexDirection = 'column';
inputContainer.style.gap = '10px';
const cyclesRow = document.createElement('div');
cyclesRow.style.display = 'flex';
cyclesRow.style.alignItems = 'center';
cyclesRow.style.justifyContent = 'space-between';
const inputLabel1 = document.createElement('label');
inputLabel1.textContent = 'Number of cycles: ';
const inputBox1 = document.createElement('input');
inputBox1.type = 'number';
inputBox1.min = '1';
inputBox1.value = '4';
inputBox1.style.width = '60px';
cyclesRow.appendChild(inputLabel1);
cyclesRow.appendChild(inputBox1);
const everyRow = document.createElement('div');
everyRow.style.display = 'flex';
everyRow.style.alignItems = 'center';
everyRow.style.justifyContent = 'space-between';
const inputLabel2 = document.createElement('label');
inputLabel2.textContent = 'Long break after every: ';
const inputBox2 = document.createElement('input');
inputBox2.type = 'number';
inputBox2.min = '0';
inputBox2.value = '0';
inputBox2.style.width = '60px';
everyRow.appendChild(inputLabel2);
everyRow.appendChild(inputBox2);
const durationRow = document.createElement('div');
durationRow.style.display = 'flex';
durationRow.style.alignItems = 'center';
durationRow.style.justifyContent = 'space-between';
const inputLabel3 = document.createElement('label');
inputLabel3.textContent = 'Long break duration: ';
const selectBox = document.createElement('select');
selectBox.style.width = '80px';
const option15 = document.createElement('option');
option15.value = '15';
option15.textContent = '15 min';
const option30 = document.createElement('option');
option30.value = '30';
option30.textContent = '30 min';
selectBox.appendChild(option15);
selectBox.appendChild(option30);
durationRow.appendChild(inputLabel3);
durationRow.appendChild(selectBox);
const buttonRow = document.createElement('div');
buttonRow.style.display = 'flex';
buttonRow.style.justifyContent = 'space-between';
const startButton = document.createElement('button');
startButton.textContent = 'Start';
const endButton = document.createElement('button');
endButton.textContent = 'End';
buttonRow.appendChild(startButton);
buttonRow.appendChild(endButton);
inputContainer.appendChild(cyclesRow);
inputContainer.appendChild(everyRow);
inputContainer.appendChild(durationRow);
inputContainer.appendChild(buttonRow);
document.body.appendChild(inputContainer);
startButton.addEventListener('click', () => {
const cycles = parseInt(inputBox1.value, 10);
const longBreakInterval = parseInt(inputBox2.value, 10);
const longBreakTime = parseInt(selectBox.value, 10);
if (!isNaN(cycles) && !isNaN(longBreakInterval) && !isNaN(longBreakTime) && cycles > 0) {
isRunning = true;
startPomodoroCycles(cycles, longBreakInterval, longBreakTime);
} else {
alert('Please enter valid numbers for cycles and long break settings.');
}
});
endButton.addEventListener('click', () => {
stopPomodoro();
alert("Pomodoro cycle stopped.");
});
})();
标签:appendChild,style,const,inputContainer,番茄,createElement,document,休息,时钟
From: https://www.cnblogs.com/Xeonilian/p/18675012/upgrade-pomodoro