AcWing Better!

AcWing界面美化,功能增强,视频时间点标记跳转,代码markdown一键复制

Você precisará instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Você precisará instalar uma extensão como o Tampermonkey para instalar este script.

Você precisará instalar um gerenciador de scripts de usuário para instalar este script.

(Eu já tenho um gerenciador de scripts de usuário, me deixe instalá-lo!)

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

(Eu já possuo um gerenciador de estilos de usuário, me deixar fazer a instalação!)

// ==UserScript==
// @name         AcWing Better!
// @version      3.29.0
// @description  AcWing界面美化,功能增强,视频时间点标记跳转,代码markdown一键复制
// @author       北极小狐
// @match        https://www.acwing.com/*
// @icon         https://aowuucdn.oss-cn-beijing.aliyuncs.com/acwing.png
// @grant        GM_xmlhttpRequest
// @grant        GM_info
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_addStyle
// @grant        GM_setClipboard
// @connect      greatest.deepsurf.us
// @run-at       document-end
// @connect      sustech.edu.cn
// @require      https://mirrors.sustech.edu.cn/cdnjs/ajax/libs/turndown/7.2.0/turndown.min.js#sha512-sJzEecN5Nk8cq81zKtGq6/z9Z/r3q38zV9enY75IVxiG7ybtlNUt864sL4L1Kf36bYIwxTMVKQOtU4VhD7hGrw==
// @license      MIT
// @namespace    https://greatest.deepsurf.us/users/747162
// ==/UserScript==

// 状态与初始化
const getGMValue = (key, defaultValue) => {
    const value = GM_getValue(key);
    if (value === undefined) {
        GM_setValue(key, defaultValue);
        return defaultValue;
    }
    return value;
};
const { hostname, href } = window.location;
const bottomBar = getGMValue("bottomBar", true);
const bingWallpaper = getGMValue("bingWallpaper", true);
const widthAdjustment = getGMValue("widthAdjustment", true);
const autoPlay = getGMValue("autoPlay", true);
const acTimer = getGMValue("acTimer", true);
const hideNavbar = getGMValue("hideNavbar", false);

// 常量
const helpCircleHTML = '<div class="help-icon"><svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"><path fill="currentColor" d="M512 64a448 448 0 1 1 0 896 448 448 0 0 1 0-896zm23.744 191.488c-52.096 0-92.928 14.784-123.2 44.352-30.976 29.568-45.76 70.4-45.76 122.496h80.256c0-29.568 5.632-52.8 17.6-68.992 13.376-19.712 35.2-28.864 66.176-28.864 23.936 0 42.944 6.336 56.32 19.712 12.672 13.376 19.712 31.68 19.712 54.912 0 17.6-6.336 34.496-19.008 49.984l-8.448 9.856c-45.76 40.832-73.216 70.4-82.368 89.408-9.856 19.008-14.08 42.24-14.08 68.992v9.856h80.96v-9.856c0-16.896 3.52-31.68 10.56-45.76 6.336-12.672 15.488-24.64 28.16-35.2 33.792-29.568 54.208-48.576 60.544-55.616 16.896-22.528 26.048-51.392 26.048-86.592 0-42.944-14.08-76.736-42.24-101.376-28.16-25.344-65.472-37.312-111.232-37.312zm-12.672 406.208a54.272 54.272 0 0 0-38.72 14.784 49.408 49.408 0 0 0-15.488 38.016c0 15.488 4.928 28.16 15.488 38.016A54.848 54.848 0 0 0 523.072 768c15.488 0 28.16-4.928 38.72-14.784a51.52 51.52 0 0 0 16.192-38.72 51.968 51.968 0 0 0-15.488-38.016 55.936 55.936 0 0 0-39.424-14.784z"></path></svg></div>';
const darkenPageStyle = `body::before { content: ""; display: block; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.4); z-index: 9999; }`;

// 样式
if (bottomBar) {
    GM_addStyle(`
        .fs-gui-taskbar {
            height: 3.5vh !important;
            background-color: #dde1e5  !important;
        }
        .fs-gui-taskbar-widgets-apps-item > img {
            height: 2.2vh !important;
            width: 2.2vh !important;
            margin: 0.5vh 0.5vh 0.5vh 0.5vh !important;
        }
        .fs-gui-taskbar-widgets-clock{
            width: 0px  !important;
            height: 0px  !important;
            overflow: hidden  !important;
        }
        .fs-gui-taskbar-widgets-apps-item {
            margin-right: 2vh !important;
        }
        #fs-gui-taskbar-search-field {
            font-size: 13px !important;
        }
        .fs-gui-taskbar-search-icon {
            font-size: 16px !important;
            top: 0.95vh !important;
            left: 4.3vh !important;
        }
        .fs-gui-taskbar-begin {
            height: 3vh !important;
            width: 3vh !important;
            margin: 0.2vh !important;
            border-radius: 60%;
            background-color: #fffefe80 !important;
        }
        button.fs-gui-taskbar-begin.pull-left.btn.btn-default img {
            width: 83% !important;
        }
        #fs-gui-taskbar-search-field {
            height: 90% !important;
            margin: 0.15vh;
            border-radius: 100px;
            border-width: 0.2vh;
            border-style: solid;
            border-color: #c7d2dd;
        }
        #fs-gui-taskbar-search-field:focus-visible {
            border-width: 0.2vh;
            border-style: solid;
            border-color: #8bb2d9;
            outline: -webkit-focus-ring-color auto 0px;
        }
    `);
}
if (bingWallpaper) {
    GM_addStyle(`
        #acwing_body {
            background: white url(https://bingw.jasonzeng.dev) fixed !important;
        }
    `);
}
if (widthAdjustment) {
    GM_addStyle(`
        .container {
            width: auto !important;
            margin: 0px 3px;
        }
    `);
    $(document).ready(function () {
        $('.base_body .container .row').children().removeClass(' col-sm-offset-2 col-sm-8 col-md-offset-2 col-md-9');
        $('.col-md-8').removeClass('col-md-8').addClass('col-md-12');
    })
}
GM_addStyle(`
span.mdViewContent {
    white-space: pre-wrap;
}
.file-explorer-main-field-item.file-explorer-main-field-item-desktop {
    width: 0px;
    height: 0px;
    overflow: hidden;
}
.comment-conent {
    overflow-x: auto;
}
/* 页脚 */
footer#acwing_footer .copyright {
    color: #fff;
}
footer#acwing_footer .copyright a, .links a, footer#acwing_footer .container {
    color: #fff;
}
/* 复制按钮 */
pre.hljs {
    display: flex;
    justify-content: space-between;
}
span.copy-button {
    cursor: pointer;
    background-color: #e6e6e6;
    color: #727378;
    height: 20px;
    font-size: 13px;
    border-radius: 0.3rem;
    padding: 1px 5px;
    margin: 5px;
    box-shadow: 0 0 1px #0000004d;
}
span.copy-button.copied {
    background-color: #07e65196;
    color: #104f2b;
}
/* html2md */
.html2md-panel {
    display: flex;
    justify-content: flex-end;
}
button.html2mdButton {
    height: 30px;
    width: 30px;
}
button.html2mdButton {
    display: flex;
    align-items: center;
    cursor: pointer;
    background-color: #ffffff;
    color: #606266;
    height: 22px;
    width: auto;
    font-size: 13px;
    border-radius: 0.3rem;
    padding: 1px 5px;
    margin: 5px;
    border: 1px solid #dcdfe6;
}
button.html2mdButton:hover {
    color: #409eff;
    border-color: #409eff;
    background-color: #f1f8ff;
}
button.html2mdButton.copied {
    background-color: #f0f9eb;
    color: #67c23e;
    border: 1px solid #b3e19d;
}
button.html2mdButton.html2md-view.mdViewed {
    background-color: #ff980057;
    color: #5a3a0c;
}
/* 打卡框 */
.ui.bottom.attached.tab.segment.active {
    padding: 0px;
}
/* 视频bar */
.embed-responsive {
    height: max-content;
    padding-bottom: 0px;
}
.player_bar {
    margin: 2px;
    display: flex;
    justify-content: space-between;
}
.player_bar_go {
    cursor: pointer;
    width: 50px;
    color: #999;
    height: auto;
    font-size: 13px;
    border-radius: 0.3rem;
    padding: 1px 5px;
    margin: 5px;
    border: none;
    background: linear-gradient(-225deg,#d5dbe4,#f8f8f8);
    box-shadow: inset 0 -2px 0 0 #cdcde6,inset 0 0 1px 1px #fff,0 1px 2px 1px rgba(30,35,90,.4);
    display: flex;
    justify-content: center;
    align-items: center;
}
button#player_bar_list_add_new_item_btn {
    height: 30px;
    width: 50px;
    background-color: #00aeec;
    color: #ffffff;
    font-size: 13px;
    border-radius: 0rem 0.5rem 0.5rem 0rem;
    padding: 1px 5px;
    margin: 5px 5px 5px 0px;
    border: none;
    box-shadow: 0 0 1px #0000004d;
}
div#player_bar_list {
    display: grid;
    width: 100%;
    border-radius: 0.3rem 0rem 0rem 0.3rem;
    margin: 5px 0px 5px 0px;
    border: 1px solid #00aeeccc;
}
div#player_bar_list input[type="radio"] {
    appearance: none;
    width: 0;
    height: 0;
    overflow: hidden;
}
div#player_bar_list input[type=radio]:focus {
    outline: 0px;
}
label.player_bar_ul_li_text {
    max-width: 100%;
    height: 90px;
    overflow-x: auto;
    font-weight: 400;
    margin: 0px 4px;
    border: 1px dashed #0000004d;
    padding: 3px;
}
ul#player_bar_ul li button {
    background-color: #e6e6e6;
    color: #727378;
    height: 23px;
    font-size: 14px;
    border-radius: 0.3rem;
    padding: 1px 5px;
    margin: 5px;
    border: none;
    box-shadow: 0 0 1px #0000004d;
}
ul#player_bar_ul {
    list-style-type: none;
    padding-inline-start: 0px;
    display: flex;
    overflow-x: auto;
    max-width: 100%;
    margin: 0px;
}
ul#player_bar_ul li {
    height: 100px;
    width: 80px;
    display: grid;
    overflow: hidden;
    margin: 4px 4px;
    min-width: 100px;
}
label.player_bar_ul_li_text:hover {
    background-color: #eae4dc24;
}
input[type="radio"]:checked + .player_bar_ul_li_text {
    background: #41e49930;
    border: 1px solid green;
    color: green;
}

ul#player_bar_ul::-webkit-scrollbar {
width: 5px;
height: 8px;
}
ul#player_bar_ul::-webkit-scrollbar-thumb {
    border-radius: 2px;
    border: 1px solid rgba(56,56,56,.3411764706);
    background-clip: padding-box;
    background-color: #a29bb84a;
    background-image: -webkit-linear-gradient(45deg,hsla(0deg,0%,100%,.4) 25%,transparent 0,transparent 50%,hsla(0deg,0%,100%,.4) 0,hsla(0deg,0%,100%,.4) 75%,transparent 0,transparent);
}
ul#player_bar_ul::-webkit-scrollbar-track {
background-color: #f1f1f1;
border-radius: 5px;
}

label.player_bar_ul_li_text::-webkit-scrollbar {
width: 5px;
height: 7px;
background-color: #aaa;
}
label.player_bar_ul_li_text::-webkit-scrollbar-thumb {
    border: 1px solid rgba(56,56,56,.3411764706);
    background-clip: padding-box;
    background-color: #a29bb84a;
}
label.player_bar_ul_li_text::-webkit-scrollbar-track {
background-color: #f1f1f1;
}
.player_bar_list_add_div {
    display: flex;
    height: 40px;
    margin: 4px 2px;
}
input#player_bar_list_add_input {
    width: 100%;
    height: 30px;
    background-color: #ffffff;
    color: #727378;
    font-size: 13px;
    border-radius: 0.3rem 0rem 0rem 0.3rem;
    padding: 1px 5px;
    margin: 5px 0px 5px 0px;
    border: 1px solid #00aeeccc;
    border-right: none;
    box-shadow: 0 0 1px #0000004d;
}
input#player_bar_list_add_input:focus-visible {
    border-width: 2px;
    border-style: solid;
    border-color: #8bb2d9;
    outline: -webkit-focus-ring-color auto 0px;
}
button#player_bar_list_add_new_item_btn.added {
    background-color: #07e65196;
    color: #104f2b;
}
div#player_bar_go.gone {
    color: #3f5a14;
    font-weight: 600;
    background: linear-gradient(-225deg,#9CCC65,#E6EE9C);
    box-shadow: inset 0 -2px 0 0 #cde3e6, inset 0 0 1px 1px #c6fd7d, 0 1px 2px 1px rgb(30 90 44 / 40%);
}
/* bar修改菜单 */
div#player_bar_menu {
    position: absolute;
    border-width: 1px;
    border-style: solid;
    border-color: #8bb2d9;
    box-shadow: 1px 1px 4px 0px #0000004d;
}
div#player_bar_menu_edit {
    cursor: pointer;
    background-color: #ffffff;
    color: black;
    box-shadow: inset 0px 0px 0px 0px #8bb2d9;
    padding: 2px 6px;
}
div#player_bar_menu_delete {
    cursor: pointer;
    background-color: #ffff;
    box-shadow: inset 0px 1px 0px 0px #8bb2d9;
    color: black;
    padding: 2px 6px;
}
div#player_bar_menu_edit:hover {
    background-color: #00aeec;
    color: white;
}
div#player_bar_menu_delete:hover {
    background-color: #FF5722;
    color: white;
}
/*设置面板*/
div#topNavBar {
    width: 80%;
}
nav.navbar.navbar-inverse.navbar-fixed-top.navbar-expand-lg .container {
    display: flex;
    align-items: center;
    justify-content: space-between;
}
button.html2mdButton.ACBetter_setting {
    background-color: #56aa56;
    color: white;
    white-space: nowrap;
    float: right;
    height: 30px;
    margin: 10px;
    border: 0px;
}
#ACwingBetter_setting_menu {
    z-index: 9999;
    border-radius: 0.5rem;
    box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
    display: grid;
    position: fixed;
    top: 50%;
    left: 50%;
    width: 270px;
    transform: translate(-50%, -50%);
    border-radius: 16px;
    background-color: #ecf0ff;
    border: 6px solid #ffffff;
    color: #697e91;
    padding: 10px 20px 20px 20px;
}

#ACwingBetter_setting_menu .tool-box {
    position: absolute;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    top: 3px;
    right: 3px;
}

#ACwingBetter_setting_menu .btn-close {
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 10px;
    width: 2rem;
    height: 2rem;
    color: transparent;
    font-size: 0;
    cursor: pointer;
    background-color: #ff000080;
    border: none;
    border-radius: 10px;
    transition: .2s ease all;
}

#ACwingBetter_setting_menu .btn-close:hover {
    width: 2rem;
    height: 2rem;
    font-size: 1rem;
    color: #ffffff;
    background-color: #ff0000cc;
    box-shadow: 0 5px 5px 0 #00000026;
}

#ACwingBetter_setting_menu .btn-close:active {
    width: .9rem;
    height: .9rem;
    font-size: .9rem;
    color: #ffffffde;
    --shadow-btn-close: 0 3px 3px 0 #00000026;
    box-shadow: var(--shadow-btn-close);
}

.checkbox-con {
    margin: 10px;
    display: flex;
    align-items: center;
    color: white;
}

#ACwingBetter_setting_menu input[type=checkbox]:focus {
    outline: 0px;
}

.checkbox-con input[type="checkbox"] {
    margin: 0px;
    appearance: none;
    width: 48px;
    height: 24px;
    border: 2px solid #6b8092;
    border-radius: 20px;
    background: #f1e1e1;
    position: relative;
    box-sizing: border-box;
}

.checkbox-con input[type="checkbox"]::before {
    content: "";
    width: 16px;
    height: 16px;
    background: #6b80927a;
    border: 2px solid #6b8092;
    border-radius: 50%;
    position: absolute;
    top: 0;
    left: 0;
    transform: translate(16%, 12%);
    transition: all 0.3s ease-in-out;
}

.checkbox-con input[type="checkbox"]::after {
    content: url("data:image/svg+xml,%3Csvg xmlns='://www.w3.org/2000/svg' width='23' height='23' viewBox='0 0 23 23' fill='none'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M6.55021 5.84315L17.1568 16.4498L16.4497 17.1569L5.84311 6.55026L6.55021 5.84315Z' fill='%23EA0707' fill-opacity='0.89'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M17.1567 6.55021L6.55012 17.1568L5.84302 16.4497L16.4496 5.84311L17.1567 6.55021Z' fill='%23EA0707' fill-opacity='0.89'/%3E%3C/svg%3E");
    position: absolute;
    top: 0;
    left: 24px;
}

.checkbox-con input[type="checkbox"]:checked {
    border: 2px solid #02c202;
    background: #e2f1e1;
}

.checkbox-con input[type="checkbox"]:checked::before {
    background: rgba(2, 194, 2, 0.5);
    border: 2px solid #02c202;
    transform: translate(160%, 13%);
    transition: all 0.3s ease-in-out;
}

.checkbox-con input[type="checkbox"]:checked::after {
    content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='13' viewBox='0 0 15 13' fill='none'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M14.8185 0.114533C15.0314 0.290403 15.0614 0.605559 14.8855 0.818454L5.00187 12.5L0.113036 6.81663C-0.0618274 6.60291 -0.0303263 6.2879 0.183396 6.11304C0.397119 5.93817 0.71213 5.96967 0.886994 6.18339L5.00187 11L14.1145 0.181573C14.2904 -0.0313222 14.6056 -0.0613371 14.8185 0.114533Z' fill='%2302C202' fill-opacity='0.9'/%3E%3C/svg%3E");
    position: absolute;
    top: 3px;
    left: 4px;
}

.checkbox-con label {
    margin: 0px 0px 0px 10px;
    cursor: pointer;
    user-select: none;
}

.ACBetter_setting_list {
    display: flex;
    align-items: center;
    margin-top: 18px;
}

.checkbox-con button {
    cursor: pointer;
    display: inline-flex;
    padding: 0.5rem 1rem;
    background-color: #1aa06d;
    color: #ffffff;
    font-size: 1rem;
    line-height: 1.5rem;
    font-weight: 500;
    justify-content: center;
    width: 100%;
    border-radius: 0.375rem;
    border: none;
    box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
}
/*设置面板-tip*/
.help_tip {
    margin-right: auto;
}
span.input_label {
    font-size: 14px;
}
.help_tip .tip_text {
    display: none;
    position: absolute;
    color: #697e91;
    font-weight: 400;
    font-size: 14px;
    letter-spacing: 0px;
    background-color: #ffffff;
    padding: 10px;
    margin: 5px 0px;
    border-radius: 4px;
    border: 1px solid #e4e7ed;
    box-shadow: 0px 0px 12px rgba(0, 0, 0, .12);
    z-index: 999;
}
.help_tip .tip_text p {
    margin-bottom: 5px;
}
.help_tip .tip_text:before {
    content: "";
    position: absolute;
    top: -20px;
    right: -10px;
    bottom: -10px;
    left: -10px;
    z-index: -1;
}
.help-icon {
    display: flex;
    cursor: help;
    width: 15px;
    color: #b4b9d4;
    margin-left: 5px;
}
.AtBetter_setting_menu .AtBetter_setting_menu_label_text .help_tip .help-icon {
    color: #7fbeb2;
}
.help_tip .help-icon:hover + .tip_text, .help_tip .tip_text:hover {
    display: block;
    cursor: help;
    width: 250px;
}
/*更新检查*/
div#update_panel {
    z-index: 9999;
    position: fixed;
    top: 50%;
    left: 50%;
    width: 240px;
    transform: translate(-50%, -50%);
    box-shadow: 0px 0px 4px 0px #0000004d;
    padding: 10px 20px 20px 20px;
    color: #444242;
    background-color: #f5f5f5;
    border: 1px solid #848484;
    border-radius: 8px;
}
div#update_panel #updating {
    cursor: pointer;
	display: inline-flex;
	padding: 0px;
	background-color: #1aa06d;
	color: #ffffff;
	font-size: 1rem;
	line-height: 1.5rem;
	font-weight: 500;
	justify-content: center;
	width: 100%;
	border-radius: 0.375rem;
	border: none;
	box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
}
div#update_panel #updating a {
    text-decoration: none;
    color: white;
    display: flex;
    position: inherit;
    top: 0;
    left: 0;
    width: 100%;
    height: 22px;
    font-size: 14px;
    justify-content: center;
    align-items: center;
}
#skip_menu {
    display: flex;
    margin-top: 10px;
    justify-content: flex-end;
    align-items: center;
}
#skip_menu .help_tip {
    margin-right: 5px;
    margin-left: -5px;
}
#skip_menu .help-icon {
    color: #f44336;
}
`);

// 隐藏顶栏
if (hideNavbar & href.includes("/problem/content/")) {
    GM_addStyle(`
    nav.navbar {
        display: none;
    }    
    .base_body {
        padding-top: 10px !important;
    }
    `);
};

// 获取cookie
function getCookie(name) {
    const cookies = document.cookie.split(";");
    for (let i = 0; i < cookies.length; i++) {
        const cookie = cookies[i].trim();
        const [cookieName, cookieValue] = cookie.split("=");

        if (cookieName === name) {
            return decodeURIComponent(cookieValue);
        }
    }
    return "";
}

// 防抖函数
function debounce(callback) {
    let timer;
    let immediateExecuted = false;
    const delay = 500;
    return function () {
        clearTimeout(timer);
        if (!immediateExecuted) { callback.call(this); immediateExecuted = true; }
        timer = setTimeout(() => { immediateExecuted = false; }, delay);
    };
}

// 为元素添加鼠标拖动
function addDraggable(element) {
    let isDragging = false;
    let initialX, initialY; // 元素的初始位置
    let startX, startY, offsetX, offsetY; // 鼠标起始位置,移动偏移量
    let isSpecialMouseDown = false; // 选取某些元素时不拖动

    element.on('mousedown', function (e) {
        var elem = $(this);
        var elemOffset = elem.offset();
        var centerX = elemOffset.left + elem.outerWidth() / 2;
        var centerY = elemOffset.top + elem.outerHeight() / 2;
        initialX = centerX - window.pageXOffset;
        initialY = centerY - window.pageYOffset;

        isDragging = true;
        startX = e.clientX;
        startY = e.clientY;

        isSpecialMouseDown = $(e.target).is('label, p, input, textarea, span');

        $('body').css('cursor', 'all-scroll');
    });


    $(document).on('mousemove', function (e) {
        if (!isDragging) return;
        // 不执行拖动操作
        if ($(e.target).is('label, p, input, textarea, span') || isSpecialMouseDown && !$(e.target).is('input, textarea')) return;
        e.preventDefault();
        offsetX = e.clientX - startX;
        offsetY = e.clientY - startY;
        element.css({ top: initialY + offsetY + 'px', left: initialX + offsetX + 'px' });
    });

    $(document).on('mouseup', function () {
        isDragging = false;
        isSpecialMouseDown = false;
        $('body').css('cursor', 'default');
    });
}

// 更新检查
(function checkScriptVersion() {
    function compareVersions(version1 = "0", version2 = "0") {
        const v1Array = String(version1).split(".");
        const v2Array = String(version2).split(".");
        const minLength = Math.min(v1Array.length, v2Array.length);
        let result = 0;
        for (let i = 0; i < minLength; i++) {
            const curV1 = Number(v1Array[i]);
            const curV2 = Number(v2Array[i]);
            if (curV1 > curV2) {
                result = 1;
                break;
            } else if (curV1 < curV2) {
                result = -1;
                break;
            }
        }
        if (result === 0 && v1Array.length !== v2Array.length) {
            const v1IsBigger = v1Array.length > v2Array.length;
            const maxLenArray = v1IsBigger ? v1Array : v2Array;
            for (let i = minLength; i < maxLenArray.length; i++) {
                const curVersion = Number(maxLenArray[i]);
                if (curVersion > 0) {
                    v1IsBigger ? result = 1 : result = -1;
                    break;
                }
            }
        }
        return result;
    }

    GM_xmlhttpRequest({
        method: "GET",
        url: "https://greatest.deepsurf.us/zh-CN/scripts/464981.json",
        timeout: 10 * 1e3,
        onload: function (response) {
            const scriptData = JSON.parse(response.responseText);
            const skipUpdate = getCookie("skipUpdate");

            if (
                scriptData.name === GM_info.script.name &&
                compareVersions(scriptData.version, GM_info.script.version) === 1 &&
                skipUpdate !== "true"
            ) {
                const styleElement = GM_addStyle(darkenPageStyle);
                $("body").append(`
                    <div id='update_panel'>
                        <h3>${GM_info.script.name}有新版本!</h3>
                        <hr>
                        <div class='update_panel_menu'>
                            <span class ='tip'>版本信息:${GM_info.script.version} → ${scriptData.version}</span>
                        </div>
                        <br>
                        <div id="skip_menu">
                            <div class="help_tip">
                                `+ helpCircleHTML + `
                                <div class="tip_text">
                                    <p><b>更新遇到了问题?</b></p>
                                    <p>由于 Greasyfork 平台的原因,当新版本刚发布时,点击 Greasyfork 上的更新按钮<u>可能</u>会出现<u>实际更新/安装的却是上一个版本</u>的情况</p>
                                    <p>通常你只需要稍等几分钟,然后再次前往更新/安装即可</p>
                                    <p>你也可以<u>点击下方按钮,在本次浏览器会话期间将不再提示更新</u></p>
                                    <button id='skip_update' class='html2mdButton'>暂不更新</button>
                                </div>
                            </div>
                            <button id='updating'><a target="_blank" href="${scriptData.url}">更新</a></button>
                        </div>
                    </div>
                `);

                $("#skip_update").click(function () {
                    document.cookie = "skipUpdate=true; expires=session; path=/";
                    styleElement.remove();
                    $("#update_panel").remove();
                });
            }
        }
    });
})();

// 随机数生成
function getRandomNumber(numDigits) {
    let min = Math.pow(10, numDigits - 1);
    let max = Math.pow(10, numDigits) - 1;
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

// 设置面板
$(document).ready(function () {
    $("#topNavBar").after(
        "<button class='html2mdButton ACBetter_setting'>AcWingBetter设置</button>"
    );
});

const ACwingBetterSettingMenuHTML = `
    <div class='checkbox-con' id='ACwingBetter_setting_menu'>
    <div class="tool-box">
        <button class="btn-close">×</button>
    </div>
    <h3>AcWingBetter设置</h3>
    <div class='ACBetter_setting_list'>
        <input type="checkbox" id="bottomBar" name="bottomBar" checked>
        <label for="bottomBar">美化底栏</label>
    </div>
    <div class='ACBetter_setting_list'>
        <input type="checkbox" id="hideNavbar" name="hideNavbar" checked>
        <label for="hideNavbar">题目页隐藏顶栏</label>
    </div>
    <div class='ACBetter_setting_list'>
        <input type="checkbox" id="bingWallpaper" name="bingWallpaper" checked>
        <label for="bingWallpaper">Bing每日壁纸</label>
    </div>
    <div class='ACBetter_setting_list'>
        <input type="checkbox" id="widthAdjustment" name="widthAdjustment" checked>
        <label for="widthAdjustment">页面宽屏</label>
    </div>
    <div class='ACBetter_setting_list'>
        <input type="checkbox" id="autoPlay" name="autoPlay" checked>
        <label for="autoPlay">不自动播放视频</label>
    </div>
    <div class='ACBetter_setting_list'>
        <input type="checkbox" id="acTimer" name="acTimer" checked>
        <label for="acTimer">开启AC计时器</label>
    </div>
    <br>
    <button id='save'>保存</button>
    </div>
`;

$(document).ready(function () {
    $(".ACBetter_setting").click(function () {
        const styleElement = GM_addStyle(darkenPageStyle);

        $(".ACBetter_setting").attr("disabled", true);
        $(".ACBetter_setting").css("background-color", "#e6e6e6");
        $(".ACBetter_setting").css("color", "#727378");
        $(".ACBetter_setting").css("cursor", "not-allowed");
        $("body").append(ACwingBetterSettingMenuHTML);

        addDraggable($('#ACwingBetter_setting_menu'));
        $("#bottomBar").prop("checked", GM_getValue("bottomBar"));
        $("#hideNavbar").prop("checked", GM_getValue("hideNavbar"));
        $("#bingWallpaper").prop("checked", GM_getValue("bingWallpaper"));
        $("#widthAdjustment").prop("checked", GM_getValue("widthAdjustment"));
        $("#autoPlay").prop("checked", GM_getValue("autoPlay"));
        $("#acTimer").prop("checked", GM_getValue("acTimer"));

        $("#save").click(function () {
            GM_setValue("bottomBar", $("#bottomBar").prop("checked"));
            GM_setValue("hideNavbar", $("#hideNavbar").prop("checked"));
            GM_setValue("bingWallpaper", $("#bingWallpaper").prop("checked"));
            GM_setValue("widthAdjustment", $("#widthAdjustment").prop("checked"));
            GM_setValue("autoPlay", $("#autoPlay").prop("checked"));
            GM_setValue("acTimer", $("#acTimer").prop("checked"));
            $(styleElement).remove();
            location.reload();
        });
        // 关闭
        $("#ACwingBetter_setting_menu .btn-close").click(function () {
            $("#ACwingBetter_setting_menu").remove();
            $(".ACBetter_setting").attr("disabled", false);
            $(".ACBetter_setting").css("background-color", "#56aa56");
            $(".ACBetter_setting").css("color", "white");
            $(".ACBetter_setting").css("cursor", "pointer");
            $(styleElement).remove();
        })
    });
});

// html2md转换/处理规则
let turndownService = new TurndownService();

turndownService.keep(['del']);

// 丢弃
turndownService.addRule('remove-by-class', {
    filter: function (node) {
        return node.classList.contains('html2md-panel') ||
            node.classList.contains('html2mdButton');
    },
    replacement: function (content, node) {
        return "";
    }
});
turndownService.addRule('remove-script', {
    filter: function (node, options) {
        return node.tagName.toLowerCase() == "script" && node.type.startsWith("math/tex");
    },
    replacement: function (content, node) {
        return "";
    }
});

// code block
turndownService.addRule('pre', {
    filter: 'pre',
    replacement: function (content, node) {
        let t = $(node).attr("class").split(/\s+/).slice(-1);
        if (t == "hljs") t = "";
        return "```" + t + "\n" + content.trim() + "\n```";
    }
});

// inline math
turndownService.addRule('inline-math', {
    filter: function (node, options) {
        return node.tagName.toLowerCase() == "span" && node.className == "MathJax";
    },
    replacement: function (content, node) {
        return "$" + $(node).next().text() + "$";
    }
});

// block math
turndownService.addRule('block-math', {
    filter: function (node, options) {
        return node.tagName.toLowerCase() == "div" && node.className == "MathJax_Display";
    },
    replacement: function (content, node) {
        return "\n$$\n" + $(node).next().text() + "\n$$\n";
    }
});

// 按钮面板
function addButtonPanel(parent, suffix, type) {
    let htmlString = `<div class='html2md-panel'>
    <button class='html2mdButton html2md-view${suffix}'>MarkDown视图</button>
    <button class='html2mdButton html2md-cb${suffix}'>Copy</button>
  </div>`;
    if (type === "this_level") {
        $(parent).before(htmlString);
    } else if (type === "child_level") {
        $(parent).prepend(htmlString);
    }
}

function addButtonWithHTML2MD(parent, suffix, type) {
    $(document).on("click", ".html2md-view" + suffix, function () {
        var target, removedChildren = $();
        if (type === "this_level") {
            target = $(".html2md-view" + suffix).parent().next().get(0);
        } else if (type === "child_level") {
            target = $(".html2md-view" + suffix).parent().parent().get(0);
            removedChildren = $(".html2md-view" + suffix).parent().parent().children(':first').detach();
        }
        if (target.viewmd) {
            target.viewmd = false;
            $(this).text("MarkDown视图");
            $(this).removeClass("mdViewed");
            $(target).html(target.original_html);
        } else {
            target.viewmd = true;
            if (!target.original_html) {
                target.original_html = $(target).html();
            }
            if (!target.markdown) {
                target.markdown = turndownService.turndown($(target).html());
            }
            $(this).text("原始内容");
            $(this).addClass("mdViewed");
            $(target).html(`<span class="mdViewContent" oninput="$(this).parent().get(0).markdown=this.value;" style="width:auto; height:auto;">${target.markdown}</span>`);
        }
        // 恢复删除的元素
        if (removedChildren) $(target).prepend(removedChildren);
    });
}

function addButtonWithCopy(parent, suffix, type) {
    $(document).on("click", ".html2md-cb" + suffix, function () {
        let target, removedChildren, text;
        if (type === "this_level") {
            target = $(".html2md-cb" + suffix).parent().next().eq(0).clone();
        } else if (type === "child_level") {
            target = $(".html2md-cb" + suffix).parent().parent().eq(0).clone();
            $(target).children(':first').remove();
        }
        if ($(target).find('.mdViewContent').length <= 0) {
            text = turndownService.turndown($(target).html());
        } else {
            text = $(target).find('.mdViewContent').text();
        }
        GM_setClipboard(text);
        $(this).addClass("copied");
        $(this).text("Copied");
        // 更新复制按钮文本
        setTimeout(() => {
            $(this).removeClass("copied");
            $(this).text("Copy");
        }, 2000);
        $(target).remove();
    });
}

// 代码块复制按钮
function codeCopy() {
    $('.hljs code').each(function () {
        let codeBlock = $(this);
        let id = "_" + getRandomNumber(8);
        let beforeButton = $('<button>').text("Copy").addClass(`html2mdButton copy-button${id}`);
        let wrapperDiv = $('<div>').addClass('copy-div');
        $(wrapperDiv).append(beforeButton);
        $(wrapperDiv).css({
            display: "flex",
            justifyContent: "flex-end"
        });
        codeBlock.parent().before(wrapperDiv);

        $(document).on("click", `.copy-button${id}`, debounce(function () {
            GM_setClipboard(codeBlock.text().replace(/\n+$/, ''));
            // 更新复制按钮文本
            var self = this;
            $(self).addClass('copied');
            $(self).text("Copied");
            var self = this;
            setTimeout(function () {
                $(self).removeClass('copied');
                $(self).text("Copy");
            }, 2000);
        }));
    });
}

function addConversionButton() {
    // 添加按钮到content部分
    if (!window.location.href.includes("code")) {
        $('div[data-field-name="content"]').each(function () {
            let id = "_question-oi-bd_" + getRandomNumber(8);
            addButtonPanel(this, id, "this_level");
            addButtonWithHTML2MD(this, id, "this_level");
            addButtonWithCopy(this, id, "this_level");
        });
    }

    // 为代码块添加复制按钮
    codeCopy();
};

// 播放器添加节点标签功能
function addPlayerBar(player_bar_video) {
    $('.prism-player').after(`
        <div class='player_bar'>
            <div class='player_bar_list' id='player_bar_list'>
                <ul class='player_bar_ul' id='player_bar_ul'></ul>
            </div>
            <div class='player_bar_go' id='player_bar_go'>Go!</div>
        </div>
        <div class='player_bar_list_add_div'>
            <input class='player_bar_list_add_input' type='text' id='player_bar_list_add_input' placeholder='在这里输入备注内容,点击Add添加一个时间点标记;选中一个标记,点击Go跳转;右键标记,修改或删除'>
            </input>
            <button class='player_bar_list_add_button' id='player_bar_list_add_new_item_btn'>Add</button>
        </div>
    `);

    // 页面路径标识
    const PAGE_IDENTIFIER = window.location.href;
    // 计数器
    let counter = 0;

    // 获取数据
    function getListData() {
        let data = GM_getValue("cookieData");
        if (!data) {
            data = {};
        } else {
            data = JSON.parse(data);
        }
        if (!data[PAGE_IDENTIFIER]) {
            data[PAGE_IDENTIFIER] = [];
        }
        return data[PAGE_IDENTIFIER];
    }

    // 保存数据
    function saveListData(data) {
        let cookieData = GM_getValue("cookieData");
        if (cookieData) {
            cookieData = JSON.parse(cookieData);
        } else {
            cookieData = {};
        }
        cookieData[PAGE_IDENTIFIER] = data;
        GM_setValue("cookieData", JSON.stringify(cookieData));
    }

    // 创建新的li元素
    function createListItemElement(text) {
        const li = $("<li></li>");
        const radio = $("<input type='radio' name='player_bar_ul'></input>").appendTo(li);
        radio.attr("id", counter++);
        const label = $("<label class='player_bar_ul_li_text'></label>").text(text).attr("for", radio.attr("id")).appendTo(li);

        li.on("contextmenu", (event) => {
            event.preventDefault();
            const menu = $("#player_bar_menu");
            menu.css({ display: "block", left: event.pageX, top: event.pageY });

            const deleteItem = $("#player_bar_menu_delete");
            const editItem = $("#player_bar_menu_edit");

            function onDelete() {
                deleteItem.off("click", onDelete);
                const list = $("#player_bar_ul");
                const index = Array.from(list.children()).indexOf(li.get(0));
                const data = getListData();
                data.splice(index, 1);
                saveListData(data);
                li.remove();
                menu.css({ display: "none" });
            }

            function onEdit() {
                editItem.off("click", onEdit);
                const list = $("#player_bar_ul");
                const index = Array.from(list.children()).indexOf(li.get(0));
                const data = getListData();
                label.text(data[index].text);
                const text = prompt("请输入修改后的内容", label.text());
                if (text !== undefined && text !== null) {
                    data[index].text = text.trim();
                    saveListData(data);
                }
                renderList();
                menu.css({ display: "none" });
            }

            deleteItem.on("click", onDelete);
            editItem.on("click", onEdit);

            $(document).on("click", (event) => {
                if (!menu.get(0).contains(event.target)) {
                    menu.css({ display: "none" });
                    deleteItem.off("click", onDelete);
                    editItem.off("click", onEdit);
                }
            });
        });

        return li;
    }

    // 渲染列表
    function renderList() {
        const listContainer = $("#player_bar_list");
        const list = $("#player_bar_ul");
        list.empty();
        const data = getListData();
        data.forEach((item) => {
            list.append(createListItemElement(item.text));
        });
    }

    // 新增列表项
    function addNewItem() {
        const input = $("#player_bar_list_add_input");
        const text = input.val().trim();
        if (text === "") {
            alert("请输入内容");
            return;
        }
        const data = getListData();
        data.push({ text: text, time: player_bar_video.currentTime });
        saveListData(data);
        const list = $("#player_bar_ul");
        list.append(createListItemElement(text));
        input.val("");
    }

    // 为添加按钮添加事件处理程序
    const player_bar_add_button = $("#player_bar_list_add_new_item_btn");
    player_bar_add_button.on("click", () => {
        addNewItem();
        player_bar_add_button.addClass('added');
        player_bar_add_button.text("Added");
        setTimeout(() => {
            player_bar_add_button.removeClass('added');
            player_bar_add_button.text("Add");
        }, 2000);
    });

    // 渲染列表
    renderList();

    // 跳转按钮
    const click_player_bar_go = $("#player_bar_go");
    click_player_bar_go.on("click", () => {
        const selected = $('input[name="player_bar_ul"]:checked');
        if (selected.length) {
            const data = getListData();
            const index = selected.parent().index();
            player_bar_video.currentTime = data[index].time;
            click_player_bar_go.addClass('gone');
            click_player_bar_go.text("Gone");
            setTimeout(() => {
                click_player_bar_go.removeClass('gone');
                click_player_bar_go.text("Go!");
            }, 2000);
        } else {
            alert("请选择一项");
        }
    });

    // 创建自定义菜单
    const menu = $("<div id='player_bar_menu' style='display: none;'></div>");
    menu.html(`
        <div id='player_bar_menu_edit'>修改</div>
        <div id='player_bar_menu_delete'>删除</div>
    `);
    $("body").append(menu);
}

function formatTime(time) {
    var seconds = Math.floor((time / 1000) % 60);
    var minutes = Math.floor((time / (1000 * 60)) % 60);
    var hours = Math.floor((time / (1000 * 60 * 60)) % 24);
    var days = Math.floor(time / (1000 * 60 * 60 * 24));

    var timeString = '';

    if (days > 0) {
        timeString += days + '天';
    }

    if (hours > 0) {
        timeString += hours + '小时';
    }

    if (minutes > 0) {
        timeString += minutes + '分钟';
    }

    if (seconds > 0) {
        timeString += seconds + '秒';
    }

    return timeString;
}

// AC计时器
function acTiming() {
    var startTime = new Date();
    var timer = setInterval(function () {
        var status = $('#submit-code-status-value-id').text().trim();

        if (status === 'Accepted') {
            clearInterval(timer);

            var endTime = new Date();
            var totalTime = endTime - startTime;

            var timeString = formatTime(totalTime);
            $('#submit-code-status-value-id').after('<div class="time-info">耗时:' + timeString + ' 要重新开始计时请刷新页面</div>');
        }
    }, 500);
}

$(document).ready(function () {
    if (acTimer && window.location.href.includes("/problem/content/")) acTiming();
    // 让某些链接在新窗口打开
    var regExps = [
        /常用代码模板/,
        /example/,
        /test/
    ];
    var aTags = document.getElementsByTagName('a');
    for (var i = 0; i < aTags.length; i++) {
        for (var j = 0; j < regExps.length; j++) {
            if (regExps[j].test(aTags[i].textContent)) {
                aTags[i].setAttribute('target', '_blank');
                break;
            }
        }
    }
    // 自动恢复进度条
    (function checkAndPlay() {
        if ($('.play-jump').length > 0) {
            $('.play-jump').click();
            if (GM_getValue("autoPlay") === true) {
                let player_bar_video = document.querySelector('video');
                if (!player_bar_video.paused) player_bar_video.pause();
            }
        } else {
            setTimeout(checkAndPlay, 500);
        }
    })();
    // 调整视频高度
    $('.prism-player').height($('.prism-player').width() / 1.7);

    // 添加按钮
    addConversionButton();
    // 移除广告元素
    let ADidADList = ["1024-activity", "test"];
    ADtraverseDom(document.body);
    function ADtraverseDom(node) {
        if (node.nodeType === Node.ELEMENT_NODE && ADidADList.includes(node.id)) {
            node.parentNode.removeChild(node);
        } else {
            for (let i = 0; i < node.childNodes.length; i++) {
                ADtraverseDom(node.childNodes[i]);
            }
        }
    }
    // 修改打卡页代码框默认高度
    var element = document.getElementById("martor-content");
    if (element) {
        var style = window.getComputedStyle(element);
        element.style.height = "55vh";
    }

    var player_bar_video = document.querySelector('video');
    if (player_bar_video != null) addPlayerBar(player_bar_video);
});