Greasy Fork 支持简体中文。

Fast Rise

2/14/2025, 4:22:13 PM

// ==UserScript==
// @name        Fast Rise
// @namespace   Violentmonkey Scripts
// @match       https://rise.articulate.com/author/*
// @grant       none
// @version     1.2.2
// @author      AMC-Albert
// @description 2/14/2025, 4:22:13 PM
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    const style = document.createElement('style');
    style.textContent = `

        /* Disable animations to make things snappy and instant, except on a few elements that break if their animations are removed */
        *:not(.author-layout--process *, [data-rmiz-modal-content] *, .curtain *, .upload-progress *) {
            animation: none !important;
            transition: none !important;
        }

        /* Remove banner thumbnails from 'copy to another course' feature to make it load faster */
        .copy-lesson-dialog__course-list__course-icon {
            background-image: none !important;
        }

        /* Remove AI garbage */
        button:has(.ai-gradient), .menu__item:has(.ai-gradient), .ai-tooltip-rich, .authoring-tooltip:has([src="https://cdn.articulate.com/assets/rise/assets/ai/block-wizard/generate-image-thumbnail.webp"]) {
            display: none;
        }
    `;
    document.head.appendChild(style);


    const isCourseOutline = () => window.location.href.includes('/author/course');
    const isSectionPage = () => window.location.href.includes('/author/details/');
    const scrollKey = `scrollPos_${window.location.pathname}`;
    const buttonKey = `lastClickedButton`;
    const navKey = `sectionNav`;
    const highlightColor = '#15095814';

    console.log('Userscript loaded. Current URL:', window.location.href);

    // Save scroll position every 500ms, only if on the course outline page
    setInterval(() => {
        if (isCourseOutline()) {
            localStorage.setItem(scrollKey, window.scrollY);
            console.log('Saved scroll position:', window.scrollY);
        }
    }, 500);

    // Restore scroll position only if on the course outline page
    window.addEventListener('load', () => {
        if (isCourseOutline()) {
            const savedScrollPos = localStorage.getItem(scrollKey);
            console.log('Restoring scroll position:', savedScrollPos);
            if (savedScrollPos !== null) {
                setTimeout(() => {
                    window.scrollTo(0, parseInt(savedScrollPos, 10));
                }, 100);
            }
            highlightLastClickedButton();
            storeButtonHrefs();
        } else if (isSectionPage()) {
            updateLastClickedButton();
        }
    });

    // Update last clicked button on popstate (browser back/forward)
    window.addEventListener('popstate', () => {
        if (isSectionPage()) {
            updateLastClickedButton();
        } else if (isCourseOutline()) {
            highlightLastClickedButton();
        }
    });

    // Override Articulate's scroll resets, but only on the course outline page
    const originalScrollTo = window.scrollTo;
    window.scrollTo = function(x, y) {
        if (isCourseOutline() && y === 0) {
            const savedScrollPos = localStorage.getItem(scrollKey);
            if (savedScrollPos !== null) {
                y = parseInt(savedScrollPos, 10);
                console.log('Overriding scrollTo:', y);
            }
        }
        originalScrollTo.call(this, x, y);
    };

    // Save the last clicked button's href to localStorage
    function attachClickListeners() {
        const buttons = document.querySelectorAll('a.course-outline-lesson__edit-content');
        console.log('Found buttons:', buttons.length);
        buttons.forEach(button => {
            button.addEventListener('click', () => {
                const href = button.getAttribute('href');
                localStorage.setItem(buttonKey, href);
                console.log('Button clicked, saving href:', href);
            });
        });
    }

    // Highlight the last clicked button
    function highlightLastClickedButton() {
        const lastClickedHref = localStorage.getItem(buttonKey);
        console.log('Last clicked href:', lastClickedHref);
        if (lastClickedHref) {
            const button = document.querySelector(`a.course-outline-lesson__edit-content[href="${lastClickedHref}"]`);
            if (button) {
                console.log('Highlighting button:', button);
                button.style.background = highlightColor;
            } else {
                console.log('Button not found for href:', lastClickedHref);
            }
        }
    }

    // Store all "Edit Content" button hrefs for navigation
    function storeButtonHrefs() {
        const buttons = document.querySelectorAll('a.course-outline-lesson__edit-content');
        const hrefs = Array.from(buttons).map(button => button.getAttribute('href'));
        localStorage.setItem(navKey, JSON.stringify(hrefs));
        console.log('Stored button hrefs:', hrefs);
    }

    // Update the last clicked button when arriving at a section page
    function updateLastClickedButton() {
        const currentHref = window.location.hash;
        localStorage.setItem(buttonKey, currentHref);
        console.log('Updated last clicked button on section load:', currentHref);
    }

    // Keyboard shortcuts for section navigation
    window.addEventListener('keydown', (e) => {
        if (isSectionPage() && e.ctrlKey && e.altKey) {
            const hrefs = JSON.parse(localStorage.getItem(navKey) || '[]');
            const currentHref = window.location.hash;
            const currentIndex = hrefs.indexOf(currentHref);
            console.log('Current section index:', currentIndex);

            let nextHref = null;
            if (e.key === 'ArrowRight' && currentIndex < hrefs.length - 1) {
                nextHref = hrefs[currentIndex + 1];
            } else if (e.key === 'ArrowLeft' && currentIndex > 0) {
                nextHref = hrefs[currentIndex - 1];
            }

            if (nextHref) {
                localStorage.setItem(buttonKey, nextHref); // Update last clicked button when navigating
                window.location.hash = nextHref;
                console.log('Navigating to:', nextHref);
            }
        }
    });

    // Observe dynamic changes for React-rendered buttons
    const observer = new MutationObserver(() => {
        if (isCourseOutline()) {
            attachClickListeners();
            highlightLastClickedButton();
            storeButtonHrefs();
        }
    });

    observer.observe(document.body, { childList: true, subtree: true });

})();