AO3: [Wrangling] UW Tag Snooze Buttons

Adds snooze buttons for unwrangled tags

As of 2022-01-05. See the latest version.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         AO3: [Wrangling] UW Tag Snooze Buttons
// @description  Adds snooze buttons for unwrangled tags
// @version      0.1

// @author       endofthyme
// @namespace    http://tampermonkey.net/
// @license      GPL-3.0 <https://www.gnu.org/licenses/gpl.html>

// @match        *://*.archiveofourown.org/tags/*/wrangle?*&status=unwrangled
// @require      https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js
// @grant        GM.getValue
// @grant        GM.setValue
// @grant        GM_setValue
// @grant        GM_getValue
// ==/UserScript==

var DEFAULT_DAYS_TO_SNOOZE = 7;

// 1: hide snoozed, 2: hide unsnoozed, 3: show all tags
var DEFAULT_BUTTON_OPTION = 1;

(function($) {

    var saved_date_map = GM_getValue('tags_saved_date_map', '{}');
    saved_date_map = saved_date_map == '{}' ? new Map() : new Map(JSON.parse(saved_date_map));
    var today = new Date();
    clearOldSnoozes();

    console.log(saved_date_map);

    // Load icons
    var font_awesome_icons = document.createElement('script');
    font_awesome_icons.setAttribute('src', 'https://code.iconify.design/2/2.1.0/iconify.min.js');
    document.getElementsByTagName('head')[0].appendChild(font_awesome_icons);

    // add Snooze column header
    $('thead tr th:contains("Canonical")').before('<th scope="col">Snooze</th>');

    // For each tag row on the page:
    $('tbody tr').each(function(i, row) {

        // Check if the tag's been snoozed.
        var tag_name = $(this).find("th[title='tag'] label").text();
        if (saved_date_map.has(tag_name) && new Date(saved_date_map.get(tag_name)) > today) {
            $(this).addClass('snoozed');

            // delete checkboxes for snoozed items (to prevent tags being wrangled accidentally)
            $(this).find("input[type='checkbox']").remove();
        } else {
            $(this).addClass('unsnoozed');
        }

        // Add snooze button for each tag.
        var snooze_button = $('<td><ul class="actions" role="menu"><li><a><span class="iconify" data-icon="mdi:sleep"></span></a></li></ul></td>');
        snooze_button.click(function() {
            addSnooze(tag_name, DEFAULT_DAYS_TO_SNOOZE);
        });
        var snoozecol = $(this).find('td[title="canonical?"]').before(snooze_button);
    });

    var toggle_p = $('<p></p>').html('Show:&nbsp;&nbsp;');
    setUpToggleMenu();

    var style = $('<style type="text/css"></style>').appendTo($('head'));
    addCss(DEFAULT_BUTTON_OPTION);

    function setUpToggleMenu() {
        var only_unsnoozed_tags = $('<a style="font-weight: bold"></a>').html('[ unsnoozed ]');
        var only_snoozed_tags = $('<a></a>').html('[ snoozed ]');
        var all_tags = $('<a></a>').html('[ snoozed + unsnoozed ]');
        var clear_snoozes = $('<a></a>').html('[ clear all snoozes ]');

        only_unsnoozed_tags.click(() => onSnoozeSelection(only_unsnoozed_tags, 1));
        only_snoozed_tags.click(() => onSnoozeSelection(only_snoozed_tags, 2));
        all_tags.click(() => onSnoozeSelection(all_tags, 3));

        clear_snoozes.click(function() {
            saved_date_map = new Map();
            GM_setValue('tags_saved_date_map', '{}');

            // Set all rows to unsnoozed on click.
            $('tbody tr').each(function(index) {
                $(this).removeClass('snoozed').addClass('unsnoozed');
            });
        });

        toggle_p.append(only_unsnoozed_tags, '&nbsp;&nbsp;', only_snoozed_tags, '&nbsp;&nbsp;',
                        all_tags, '&nbsp;&nbsp;-&nbsp;&nbsp;', clear_snoozes);
        $('#wrangulator').before(toggle_p);
    }

    function addSnooze(tag_name, days) {
        var snoozedDate = new Date();
        snoozedDate.setDate(snoozedDate.getDate() + days);
        saved_date_map.set(tag_name, snoozedDate);
        GM_setValue('tags_saved_date_map', JSON.stringify(Array.from(saved_date_map.entries())));
        console.log(tag_name + ' snoozed to ' + snoozedDate);

        // Disappear the snoozed row.
        $('tbody tr').each(function(index) {
            if ($(this).find('th label').text() == tag_name) {
                $(this).removeClass('unsnoozed').addClass('snoozed');

                // delete checkboxes for snoozed items
                $(this).find("input[type='checkbox']").remove();
            }
        });
    }

    function clearOldSnoozes() {
        GM_setValue('tags_saved_date_map',
                    JSON.stringify([...saved_date_map].filter(([k, v]) => new Date(v) > today)));
    }

    function onSnoozeSelection(button, css_option) {
        addCss(css_option);
        toggle_p.find('a').css('font-weight', 'normal');
        button.css('font-weight', 'bold');
    }

    // 1: hide snoozed, 2: hide unsnoozed, 3: show all tags
    function addCss(option) {
        var css_unsnoozed = '.snoozed {display: none;}';
        var css_snoozed = '.unsnoozed {display: none;}';

        switch (option) {
            case 1:
                style.html(css_unsnoozed);
                break;
            case 2:
                style.html(css_snoozed);
                break;
            default:
                style.html('');
        }
    }
})(jQuery);