力扣题目计时

力扣题目界面显示当前用时, 可也进行倒计时

// ==UserScript==
// @name         力扣题目计时
// @description  力扣题目界面显示当前用时, 可也进行倒计时
// @namespace    https://greasyfork.org/zh-CN/users/412790
// @version      1.2
// @author       Permission
// @match        https://leetcode-cn.com/problems/*
// @require      https://cdn.jsdelivr.net/npm/sweetalert2@9
// @require      https://code.jquery.com/jquery-3.4.1.min.js
// @grant        GM_addStyle
// @grant        unsafeWindow
// ==/UserScript==

/* globals $, jQuery, Swal */
'use strict';

GM_addStyle(`
#lc-timer{
color: green;
font-size: 18px;
font-family: FetteMittelschrift, sans-serif;
margin: 0px 15px 0px 10px;
user-select: none;
width: 70px;
}

#reset-timer, #set-timer, #pause-timer, #stop-timer{
border:none;
outline:none;
user-select: none;
box-shadow: inset 0px 0px 0px 1px rgba(var(--grey-4-rgb), 1);
background-color: transparent;
color: rgba(var(--grey-8-rgb), 1);
border-radius: 3px;
height: 26px;
overflow: hidden;
text-overflow: ellipsis;
word-break: break-all;
white-space: nowrap;
}
#reset-timer:hover, #set-timer:hover, #pause-timer:hover, #stop-timer:hover{
cursor:pointer;
box-shadow: inset 0px 0px 0px 1px rgba(var(--primary-5-rgb), 1);
background-color: rgba(var(--primary-0-rgb), 1);
color: rgba(var(--grey-8-rgb), 1);
}
#set-timer, #pause-timer, #stop-timer{
margin-left: 2px;
}
`)

let sec = 0, min = 0, hr = 0;

const mode = {
    normal : "normal",
    countdown: "countdown",
    paused : "paused",
    stoped : "stoped"
}

let curMode = mode.normal;

const updateTimer = () => {
    if(sec == 59){
        sec = 0;
        if(min == 59){
            min = 0;
            hr++;
        }
        else{
            min++;
        }
    }
    else{
        sec++;
    }
    $("#lc-timer").text(`${hr < 10 ? "0" : ""}${hr}:${min < 10 ? "0" : ""}${min}:${sec < 10 ? "0" : ""}${sec}`);
}

const check = setInterval(() => {
    if($("#lang-select").length != 0){
        $("#lang-select").after(`<div id = "lc-timer"></div><button id = "reset-timer">重置</button> <button id = "set-timer">倒计时</button><button id = "pause-timer">当前: 正在计时</button><button id = "stop-timer">停止</button>`);
        clearInterval(check);
        let interval = setInterval(() => updateTimer(), 1e3);
        bind(interval);
    }
}, 2e2);

const bind = (interval) => {
    $("#reset-timer").bind("click", () => {
        if(curMode == mode.countdown){
            alert("倒计时模式不可重置时间!");
            return;
        }
        if(curMode != mode.stoped && !confirm("确定要重置?")){
            return;
        }
        sec = min = hr = 0;
        clearInterval(interval);
        $("#lc-timer").text("00:00:00");
        curMode = mode.normal;
        $("#pause-timer").text("当前: 正在计时");
        $("#reset-timer").text("重置");
        interval = setInterval(() => updateTimer(), 1e3);
    })

    $("#pause-timer").bind("click", () => {
        if(curMode == mode.countdown){
            return;
        }
        else if(curMode == mode.normal){
            $("#pause-timer").text("当前: 暂停");
            clearInterval(interval);
            curMode = mode.paused;
        }
        else if(curMode == mode.paused){
            $("#pause-timer").text("当前: 正在计时");
            clearInterval(interval);
            interval = setInterval(() => updateTimer(), 1e3);
            curMode = mode.normal;
        }
    })

    $("#stop-timer").bind("click", () => {
        if(curMode == mode.countdown){
            alert("倒计时模式不可停止!");
            return;
        }
        clearInterval(interval);
        curMode = mode.stoped;
        $("#lc-timer").text("00:00:00");
        $("#pause-timer").text("当前: 停止");
        $("#reset-timer").text("开始");
    })

    $("#set-timer").bind("click", () => {
        if(curMode == mode.countdown){
            alert("当前正在倒计时模式, 若要重新设置请刷新界面.");
            return;
        }
        Swal.mixin({
            input: 'text',
            confirmButtonText: 'Next &rarr;',
            showCancelButton: true,
            progressSteps: ['1', '2', '3']
        }).queue([
            {
                title: '设置秒'
            },
            {
                title: '设置分钟'
            },
            {
                title: '设置小时'
            }
        ]).then((result) => {
            if (result.value) {
                const choices = result.value;
                for(let pos = 0; pos < choices.length; pos++){
                    let a = parseInt(choices[pos]);
                    if(isNaN(a) || ((pos == 0 || pos == 1) && (a < 0 || a >= 60))){
                        alert(`时间设置有误!`);
                        return;
                    }
                }
                Swal.fire({
                    title: 'All done!',
                    text: `倒计时设置完成`,
                    confirmButtonText: '开始!'
                }).then(() => {
                    startCountdown(choices, interval);
                })
            }
        })
    })
};

const startCountdown = (choices, interval) => {
    curMode = mode.countdown;
    $("#pause-timer").text("当前: 倒计时");
    $("#stop-timer").attr("disabled", "true");
    $("#pause-timer").attr("disabled", "true");
    $("#reset-timer").attr("disabled", "true");
    $("#set-timer").attr("disabled", "true");
    $("#stop-timer").hide();
    $("#set-timer").hide();
    $("#reset-timer").hide();
    clearInterval(interval);
    let unload = e => {
        e.preventDefault();
        e.returnValue = '';
    };
    window.addEventListener('beforeunload', unload);
    sec = choices[0]; min = choices[1]; hr = choices[2];
    const countdownInterval = setInterval(() => {
        $("#lc-timer").text(`${hr < 10 ? "0" : ""}${hr}:${min < 10 ? "0" : ""}${min}:${sec < 10 ? "0" : ""}${sec}`);
        if(sec == 0 && min == 0 && hr == 0){
            clearInterval(countdownInterval);
            curMode = mode.stoped;
            $("#stop-timer").removeAttr("disabled");
            $("#pause-timer").removeAttr("disabled");
            $("#reset-timer").removeAttr("disabled");
            $("#set-timer").removeAttr("disabled");
            $("#stop-timer").show();
            $("#set-timer").show();
            $("#reset-timer").show();
            $("#pause-timer").text("当前: 停止");
            $("#reset-timer").text("计时");
            window.removeEventListener('beforeunload', unload);
            alert(`倒计时结束`);
        }
        if(sec == 0){
            sec = 59;
            if(min == 0){
                hr--;
                min = 59;
            }
            else{
                min--;
            }
        }
        else{
            sec--;
        }
    }, 1e3);
}