ResetEra Live Thread

Update threads without refreshing

当前为 2017-10-28 提交的版本,查看 最新版本

// ==UserScript==
// @name         ResetEra Live Thread
// @namespace    http://madjoki.com
// @version      1.3
// @description  Update threads without refreshing
// @author       Madjoki
// @match        https://www.resetera.com/threads/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    var globalSettings = {
        rememberThreads: true,
        updateTime: 30,
        enabledByDefault: false,
    };

    var settingsJson = localStorage.getItem("livethreadSettings");

    if (settingsJson !== null)
    {
        globalSettings = JSON.parse(settingsJson);
    }

    var defaultThreadSettings = {
        updateTime: globalSettings.updateTime || 30,
        enabled: globalSettings.enabledByDefault || false,
    };

    var threadID = parseInt($('[name="type[post][thread_id]"]').val(), 10);

    var currentThreadSettings = getSettings(threadID);

    var isRememberedThread = currentThreadSettings !== null || globalSettings.rememberThreads;

    if (currentThreadSettings === null)
    {
        isRememberedThread = false;
        currentThreadSettings = defaultThreadSettings;
    }

    function calculateNextUpdate()
    {
        var timer = currentThreadSettings.updateTime;

        // If we have more pages to load, use shorter timer
        if (currentPage < lastPage)
            timer = 10;

        timeToNextUpdate = timer;
    }

    function getSettings(thread)
    {
        var stored = localStorage.getItem("livethread_" + thread);

        if (stored === null)
            return defaultThreadSettings;

        return JSON.parse(stored);
    }

    function setSettings(thread, settings)
    {
        localStorage.setItem("livethread_" + thread, JSON.stringify(settings));
    }

	function saveSettings()
	{
        if (isRememberedThread)
            setSettings(threadID, currentThreadSettings);
        else
            setSettings(threadID, null);

        localStorage.setItem("livethreadSettings", JSON.stringify(globalSettings));

        updateForm();
        updateStatus();
	}

    var countNew = 0;
    var countNewLast = 0;
    var errors = 0;
    var updating = false;
    var lastUrl = window.location;
    var currentPage = $('div.PageNav').first().data('page') || 1;
    var lastLoadedPage = currentPage;
    var lastPage = $('div.PageNav').first().data('last') || 1;
    var threadTitle = $('title').text();
    var timeToNextUpdate = 60;
    calculateNextUpdate();

    $('#messageList > li').data('livethread-page', currentPage);

	var timeout = setInterval(timerTick, 1000);

    function updateStatus()
    {
        $('body').toggleClass('liveThread_enabled', currentThreadSettings.enabled);

        var status  = "";

        if (updating)
            status += "Updating";
        else if (currentThreadSettings.enabled)
        {
            status += "Next Update In " + timeToNextUpdate + " seconds - ";

            if (countNewLast > 0)
                status += countNewLast + " New Messages!";
            else
                status += "No New Messages";
        }
        else
            status += "Auto Update Disabled";

        $("#livethreadStatus").text(status);

        if (countNew > 0)
            $('title').text("(" + countNew + ") " + threadTitle);
        else
            $('title').text(threadTitle);
    }

    function enableDisable(event)
    {
        event.preventDefault();

        currentThreadSettings.enabled = !currentThreadSettings.enabled;

		saveSettings();

        updateStatus();
    }

    function timerTick()
    {
		if (!currentThreadSettings.enabled)
			return;

        timeToNextUpdate--;

        if (timeToNextUpdate === 0)
        {
            updateMessages();
            timeToNextUpdate = currentThreadSettings.updateTime;
        }

        updateStatus();
    }

    // Inserts marker after last message
    function insertNotifi(text)
    {
        var $el = $('<div>', {'class': "newMessagesNotice", 'text': text});

        $("#messageList").append($el);

        return $el;
    }

    // Get URL for current page
    function getCurrentURL()
    {
        var pageNav = $('div.PageNav').first();

        currentPage = pageNav.data('page') || 1;
        lastPage = pageNav.data('last') || 1;

        if (pageNav.data('baseurl') === undefined)
            return window.location;

        if (lastPage > currentPage)
            currentPage++;

        return pageNav.data('baseurl').replace('{{sentinel}}', currentPage);
    }

    function updateMessagesClick(event)
    {
        event.preventDefault();
        updateMessages();
    }

    function updateMessages()
    {
        if (updating)
            return;

        updating = true;
        updateStatus();

        countNewLast = 0;

        var thisUrl = getCurrentURL();
        lastUrl = getCurrentURL();

        $('body').addClass('liveThread_loading');

        $.get(lastUrl, function (data) {

            // If new page insert marker and update history
            if (lastLoadedPage < currentPage)
            {
                window.history.pushState(null, null, thisUrl);
                lastUrl = thisUrl;

                insertNotifi("Page " + currentPage);

                lastLoadedPage = currentPage;
            }

            var node = $($.parseHTML(data));

            var newNav = node.find('div.PageNav').first();

            $('div.PageNav').each(function (i, el) {

                $(el).replaceWith(newNav.clone());

            });

            // To avoid reloading mesasges after posting
            $('input[name="last_date"]').val(node.find('input[name="last_date"]').val());
            $('input[name="last_known_date"]').val(node.find('input[name="last_known_date"]').val());

            node.find('#messageList > li').each(function (i, el) {

                var $el = $(el);

                var id = $el.attr('id');

                var $curr = $('#' + id);

                // Update old message if changed
                if ($curr.length)
                {
                    var newMessage = $el.find('article');
                    var oldMessage = $curr.find('article');

                    if (newMessage.text() != oldMessage.text())
                    {
                        oldMessage.replaceWith(newMessage).xfActivate();

                        $curr.xfActivate();
                    }
                }
                // Insert new messages
                else
                {
                    $el.data('livethread-page', currentPage);

                    $el.xfInsert('appendTo', $("#messageList"));

                    countNew++;
                    countNewLast++;
                }

            });

        }).always(function () {
            updating = false;
            calculateNextUpdate();
            updateStatus();

            $('body').removeClass('liveThread_loading');
        });
    }

    // Control Panel
    function updateForm()
    {
        $("#updateTime option[value='" + currentThreadSettings.updateTime  + "']").attr("selected", true);

        $("#liveThread_remember").attr("checked", globalSettings.rememberThreads);

        $('#livethreadEnabled > span').text(currentThreadSettings.enabled ? "Turn Off" : "Turn On");

        $('#liveThread_currentRemember').attr("checked", isRememberedThread);
    }

    $('Div.pageNavLinkGroup').last().before('\
<style>\
    #livethreadControl {\
        text-align: center;\
        margin-bottom: 5px;\
    }\
    #livethreadStatus {\
        text-align: center; \
    }\
    #livethreadSettings {\
        text-align: center; \
    }\
    #livethreadGlobalSettings {\
        display: none;\
    }\
    .liveThread_enabled #AjaxProgress {\
        display: none !important;\
    }\
</style>\
<div id="livethreadPanel" class="DiscussionListOptions secondaryContent">\
   <div id="livethreadStatus"></div>\
   <div id="livethreadControl" class="publicControls">\
       <a id="livethreadEnabled" href="#" class="callToAction"><span>Turn On</span></a>\
       <a id="livethreadUpdate" href="#" class="callToAction"><span>Update Now</span></a>\
       <a id="livethreadSettingsToggle" href="#" class="callToAction"><span>Settings</span></a>\
   </div>\
   <div id="livethreadSettings">\
      <div class="controlGroup">\
         <label for="updateTime">Update Speed:</label>\
         <select id="updateTime" class="textCtrl">\
             <option value="15">Fast (15s)</option>\
             <option value="30">Normal (30s)</option>\
             <option value="60">Slow (1m)</option>\
             <option value="120">Very Slow (2m)</option>\
         </select>\
       <label><input type="checkbox" id="liveThread_currentRemember" value="1"> Remember this thread</label>\
    </div>\
    <div id="livethreadGlobalSettings">\
        <h2 class="heading h1">Global Settings</h2>\
        <ul>\
				<li><label><input type="checkbox" id="liveThread_remember" value="1"> Remember New Threads by Default</label></li>\
        </ul>\
    </div>\
</div>');

    updateForm();
    updateStatus();

    $('#livethreadEnabled').click(enableDisable);
    $('#livethreadUpdate').click(updateMessagesClick);

    $('#livethreadSettingsToggle').click(function (event) {
        event.preventDefault();

        $('#livethreadGlobalSettings').toggle();
    });

    $('#liveThread_currentRemember').change(function () {

        isRememberedThread = $('#liveThread_currentRemember').is(':checked');

        saveSettings();
    });

    $('#liveThread_remember').change(function () {

        globalSettings.rememberThreads = $('#liveThread_remember').is(':checked');

        saveSettings();
    });

    $('#updateTime').change(function () {
        currentThreadSettings.updateTime = parseInt($('#updateTime').val());

		saveSettings();

        if (currentThreadSettings.updateTime < timeToNextUpdate)
            calculateNextUpdate();

        updateStatus();
    });

    $(window).focus(function () {
        // Reset new messages on focus
        countNew = 0;
        updateStatus();
    });

    updateStatus();
})();