AP Poly Dark Mode

A Tampermonkey script to darken the AP Polytechnic student portal interface.

当前为 2025-07-28 提交的版本,查看 最新版本

// ==UserScript==
// @name         AP Poly Dark Mode
// @icon         https://github.com/Tori0833/AP-Poly-Dark-Mode/blob/main/resources/icon.png?raw=true
// @namespace    https://github.com/Tori0833/AP-Poly-Dark-Mode
// @version      1.0.1
// @description  A Tampermonkey script to darken the AP Polytechnic student portal interface.
// @author       tori.toriko (discord) & Claude.ai
// @match        https://ap.poly.edu.vn/*
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // Create and inject dark mode CSS
    const darkModeCSS = `
        /* === GLOBAL DARK THEME === */
        body, html {
            background-color: #121212 !important;
            color: #eeeeee !important;
        }

        body.kt-page--loading.kt-header--fixed.kt-subheader--enabled.kt-aside--fixed {
            background-color: #121212 !important;
        }

        /* === HEADER DARK MODE === */
        #kt_header,
        .kt-header {
            background-color: #1e1e1e !important;
            border-bottom: 1px solid #333 !important;
        }

        .kt-header__topbar {
            background-color: #1e1e1e !important;
        }

        .kt-header__topbar-item,
        .kt-header__topbar-user {
            color: #eeeeee !important;
        }

        .kt-header__topbar-item a,
        .kt-header__topbar-user a {
            color: #eeeeee !important;
        }

        /* === SIDEBAR DARK MODE === */
        #kt_aside,
        .kt-aside {
            background-color: #1e1e1e !important;
            border-right: 1px solid #333 !important;
        }

        .kt-aside__brand {
            background-color: #1e1e1e !important;
            border-bottom: 1px solid #333 !important;
        }

        .kt-aside__menu-wrapper {
            background-color: #1e1e1e !important;
        }

        .kt-menu__nav {
            background-color: #1e1e1e !important;
        }

        .kt-menu__item {
            border-bottom: 1px solid #2c2c2c !important;
        }

        .kt-menu__link {
            color: #eeeeee !important;
            background-color: transparent !important;
        }

        .kt-menu__link:hover {
            background-color: #2c2c2c !important;
            color: #80b3ff !important;
        }

        .kt-menu__link-text {
            color: #eeeeee !important;
        }

        .kt-menu__link-icon {
            color: #eeeeee !important;
        }

        /* Active menu items */
        .kt-menu__item--active .kt-menu__link {
            background-color: #2c2c2c !important;
            color: #80b3ff !important;
        }

        /* === MAIN CONTENT AREA === */
        #kt_wrapper,
        .kt-wrapper {
            background-color: #121212 !important;
        }

        .kt-grid__item--fluid {
            background-color: #121212 !important;
        }

        .kt-content {
            background-color: #121212 !important;
        }

        /* === DROPDOWNS === */
        .dropdown-menu {
            background-color: #2c2c2c !important;
            border: 1px solid #444 !important;
            color: #eeeeee !important;
        }

        .dropdown-item {
            color: #eeeeee !important;
            background-color: transparent !important;
        }

        .dropdown-item:hover,
        .dropdown-item:focus {
            background-color: #444 !important;
            color: #80b3ff !important;
        }

        /* === MODALS & POPUPS === */
        .modal-content {
            background-color: #2c2c2c !important;
            border: 1px solid #444 !important;
            color: #eeeeee !important;
        }

        .modal-header {
            background-color: #2c2c2c !important;
            border-bottom: 1px solid #444 !important;
        }

        .modal-body {
            background-color: #2c2c2c !important;
            color: #eeeeee !important;
        }

        .modal-footer {
            background-color: #2c2c2c !important;
            border-top: 1px solid #444 !important;
        }

        /* === FORMS === */
        .form-container {
            background-color: #2c2c2c !important;
            color: #eeeeee !important;
        }

        .form-group {
            color: #eeeeee !important;
        }

        .form-control {
            background-color: #1e1e1e !important;
            border: 1px solid #555 !important;
            color: #eeeeee !important;
        }

        .form-control:focus {
            background-color: #1e1e1e !important;
            border-color: #80b3ff !important;
            color: #eeeeee !important;
            box-shadow: 0 0 0 0.2rem rgba(128, 179, 255, 0.25) !important;
        }

        .form-control::placeholder {
            color: #999 !important;
        }

        .custom-control {
            color: #eeeeee !important;
        }

        .custom-control-input:checked ~ .custom-control-label::before {
            background-color: #80b3ff !important;
            border-color: #80b3ff !important;
        }

        /* === BUTTONS === */
        .btn {
            border: 1px solid #555 !important;
        }

        .btn-primary {
            background-color: #0d6efd !important;
            border-color: #0d6efd !important;
            color: #ffffff !important;
        }

        .btn-secondary {
            background-color: #2c2c2c !important;
            border-color: #555 !important;
            color: #eeeeee !important;
        }

        .btn:hover {
            opacity: 0.8 !important;
        }

        /* === TABLES === */
        .table {
            background-color: #2c2c2c !important;
            color: #eeeeee !important;
        }

        .table th,
        .table td {
            border-color: #444 !important;
            color: #eeeeee !important;
        }

        .table-striped tbody tr:nth-of-type(odd) {
            background-color: rgba(255, 255, 255, 0.05) !important;
        }

        /* === NOTIFICATIONS === */
        .kt-notification {
            background-color: #2c2c2c !important;
            border: 1px solid #444 !important;
            color: #eeeeee !important;
        }

        .kt-user-card {
            background-color: #2c2c2c !important;
            color: #eeeeee !important;
        }

        /* === LINKS === */
        a {
            color: #80b3ff !important;
        }

        a:hover {
            color: #66a3ff !important;
        }

        /* === CARDS & PANELS === */
        .card {
            background-color: #2c2c2c !important;
            border: 1px solid #444 !important;
            color: #eeeeee !important;
        }

        .card-header {
            background-color: #1e1e1e !important;
            border-bottom: 1px solid #444 !important;
            color: #eeeeee !important;
        }

        .card-body {
            background-color: #2c2c2c !important;
            color: #eeeeee !important;
        }

        /* === SCROLLBARS === */
        ::-webkit-scrollbar {
            width: 8px !important;
            height: 8px !important;
        }

        ::-webkit-scrollbar-track {
            background: #1e1e1e !important;
        }

        ::-webkit-scrollbar-thumb {
            background: #555 !important;
            border-radius: 4px !important;
        }

        ::-webkit-scrollbar-thumb:hover {
            background: #777 !important;
        }

        /* === TEXT INPUTS & SELECTS === */
        input, textarea, select {
            background-color: #1e1e1e !important;
            border: 1px solid #555 !important;
            color: #eeeeee !important;
        }

        input:focus, textarea:focus, select:focus {
            border-color: #80b3ff !important;
            box-shadow: 0 0 0 0.2rem rgba(128, 179, 255, 0.25) !important;
        }

        /* === BREADCRUMBS === */
        .breadcrumb {
            background-color: #2c2c2c !important;
        }

        .breadcrumb-item a {
            color: #80b3ff !important;
        }

        .breadcrumb-item.active {
            color: #eeeeee !important;
        }

        /* === ALERTS === */
        .alert {
            border: 1px solid #444 !important;
            color: #eeeeee !important;
        }

        .alert-info {
            background-color: #1a4a6b !important;
            border-color: #1e5f7d !important;
        }

        .alert-warning {
            background-color: #6b4a1a !important;
            border-color: #7d5f1e !important;
        }

        .alert-danger {
            background-color: #6b1a1a !important;
            border-color: #7d1e1e !important;
        }

        .alert-success {
            background-color: #1a6b1a !important;
            border-color: #1e7d1e !important;
        }

        /* === GENERAL OVERRIDES === */
        * {
            scrollbar-width: thin !important;
            scrollbar-color: #555 #1e1e1e !important;
        }

        /* Force any remaining white backgrounds to dark */
        div, span, section, article, main, aside, header, footer, nav {
            background-color: inherit !important;
        }

        /* Ensure text remains readable */
        p, h1, h2, h3, h4, h5, h6, span, div, td, th, li {
            color: #eeeeee !important;
        }

        /* Fix nav tabs */
        .nav-tabs {
          background-color: #1e1e1e !important;
          border-color: #333 !important;
        }

        .nav-link {
          background-color: transparent !important;
          color: #aaa !important;
          border-color: #444 !important;
        }

        .nav-link.active {
          background-color: #2a2a2a !important;
          color: #fff !important;
          border-color: #444 #444 #2a2a2a !important;
        }

    `;

    // Function to inject CSS with higher priority
    function injectCSS() {
        // Remove any existing dark mode styles
        const existingStyle = document.getElementById('darkmode-ap-poly');
        if (existingStyle) {
            existingStyle.remove();
        }

        const style = document.createElement('style');
        style.type = 'text/css';
        style.id = 'darkmode-ap-poly';
        style.innerHTML = darkModeCSS;

        // Inject into head with high priority
        if (document.head) {
            document.head.appendChild(style);
        } else {
            // Fallback: create head if it doesn't exist
            const head = document.createElement('head');
            head.appendChild(style);
            document.documentElement.insertBefore(head, document.documentElement.firstChild);
        }

        console.log('AP Poly Dark Mode: CSS injected successfully');
    }

    // Inject CSS immediately and repeatedly to ensure it applies
    injectCSS();

    // Also inject after a short delay to override any late-loading styles
    setTimeout(injectCSS, 500);
    setTimeout(injectCSS, 1000);
    setTimeout(injectCSS, 2000);

    // Also inject when DOM is ready (backup)
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', injectCSS);
    }

    // Watch for dynamically loaded content
    const observer = new MutationObserver(function(mutations) {
        mutations.forEach(function(mutation) {
            if (mutation.addedNodes.length > 0) {
                // Re-apply styles to new elements if needed
                mutation.addedNodes.forEach(function(node) {
                    if (node.nodeType === 1) { // Element node
                        // Force dark background on new elements
                        if (node.style) {
                            if (node.classList && (
                                node.classList.contains('modal-content') ||
                                node.classList.contains('dropdown-menu') ||
                                node.classList.contains('form-control')
                            )) {
                                // These elements get special handling
                                setTimeout(() => injectCSS(), 100);
                            }
                        }
                    }
                });
            }
        });
    });

    // Start observing
    if (document.body) {
        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
    } else {
        document.addEventListener('DOMContentLoaded', function() {
            observer.observe(document.body, {
                childList: true,
                subtree: true
            });
        });
    }

})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址