WME Edition Helper

Monitor editions count and shows a timer for next suggested save action

目前為 2021-10-23 提交的版本,檢視 最新版本

// ==UserScript==
// @name             WME Edition Helper
// @name:es          WME Ayudante de edición
// @description      Monitor editions count and shows a timer for next suggested save action
// @description:es   Monitorea el contador de ediciones y muestra un temporizador para la siguiente acción de guardado sugerida

// @author           EdwardNavarro
// @namespace        https://gf.qytechs.cn/en/users/670818-edward-navarro
// @version          2021.10.22.01

// @include          /^https:\/\/(www|beta)\.waze\.com\/(?!user\/)(.{2,6}\/)?editor\/?.*$/
// @exclude          https://www.waze.com/user/*
// @exclude          https://www.waze.com/*/user/*
// @require          https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js
// @icon             https://www.edwardnavarro.com/cdn/wme/wme_eh_icon_32x32.svg
// @connect          www.waze.com
// @grant            GM_xmlhttpRequest

// @contributionURL  https://github.com/WazeDev/Thank-The-Authors
// ==/UserScript==

/* global W */
/* global toastr */
/* global $ */
/* global GM_xmlhttpRequest */

/**
* ===============================================
*  This script is based on the following scripts:
*  - "Waze Edit Count Monitor" (by MapOMatic)
*  - "Waze Edit & UR Count Monitor" (by Crotalo)
* ===============================================
*/

// This function is injected into the page to allow it to run in the page's context.
function wmeEH_Injected() {
    'use strict';

    let _toastr_settings = {
        remindAtEditCount: 30,
        warnAtEditCount: 45,
        wasReminded: false,
        wasWarned: false
    };

    let debugLevel = 0;
    let userName = '';
    let lastTodayEditCount = 0;
    let lastYesterdayEditCount = 0;
    let lastDayBeforeEditCount = 0;
    let savesWithoutIncrease = 0;
    let button_container, button_content_wrap, button_item_container, button_item_icon, button_item_link, button_item_content, progress_bar_wrap, progress_bar_fill;
    let tooltipText = '<b>Ediciones Diarias</b><br><small>(Clic para ver el perfil)<small>';

    function log(message, level, prefix = 'LOG', bgColor = 'darkslategrey', textColor = 'white') {
        if (message && level <= debugLevel) {
            console.log('%c%s%s', `background:${bgColor};color:${textColor};padding:5px 10px;`, `[${prefix}] WME Edition Helper >>`, message);
        }
    }

    function checkEditCount() {
        window.postMessage(JSON.stringify(['wmeEHGetCounts',userName]),'*');
        _toastr_settings.wasReminded = false;
        _toastr_settings.wasWarned = false;
        toastr.remove();
    }

    function getChangedObjectCount() {
        let count = W.changesLogController._changesLogViewModel.attributes.actionsCount;
        return count;
    }

    function updateEditCount(todayEditCount = 0, yesterdayEditCount = 0, dayBeforeEditCount = 0, noIncrement) {
        let textColor;
        let bgColor;
        let tooltipTextColor;

        // Add the counter div if it doesn't exist.
        if ($('#eh-button').length === 0) {
            button_container = $('<div>', { id: 'eh-button' });
            button_content_wrap = $('<div>', { class: 'toolbar-button toolbar-button-with-icon' });
            button_item_link = $('<a>', { href: 'https://www.waze.com/user/editor/' + userName.toLowerCase(), target: '_blank', style:'text-decoration: none;', 'data-original-title': tooltipText });
            button_item_container = $('<div>', { class: 'item-container' });
            button_item_icon = $('<div>', { class: 'toolbar-icon-eh w-icon w-icon-pencil' });
            button_item_content = $('<div>', { style: 'margin:5px 0 0 5px; line-height: 1;' });

            progress_bar_wrap = $('<div>', { style: 'width: 100%; height: 5px; background-color: #d7dadc; border:1px #fff solid; box-sizing: content-box;' });
            progress_bar_fill = $('<div>', { class: 'progress', style: 'width: 0%; height: 5px;' });

            button_container.append(button_content_wrap);
            button_content_wrap.append(button_item_link);
            button_item_link.append(button_item_container);
            button_item_container.append(button_item_icon);
            button_item_container.append(button_item_content);

            button_item_content.append(progress_bar_wrap);
            progress_bar_wrap.append(progress_bar_fill);

            $('#edit-buttons').prepend(button_container);

            button_item_link.tooltip({
                placement: 'auto top',
                delay: { show: 100, hide: 100 },
                html: true,
                template: '<div class="tooltip" role="tooltip" style="opacity:0.95"><div class="tooltip-arrow"></div><div class="my-tooltip-header" style="display:block;"><b></b></div><div class="my-tooltip-body tooltip-inner" style="display:block;"></div></div>'
            });
        }

        log(`EDIT COUNTS -> Today: ${todayEditCount}, Yesterday: ${yesterdayEditCount}, Day before: ${dayBeforeEditCount}`, 1, 'INFO', 'purple');

        if (lastTodayEditCount !== todayEditCount) {
            savesWithoutIncrease = 0;
        } else {
            if (!noIncrement) savesWithoutIncrease += 1;
        }

        switch (savesWithoutIncrease) {
            case 0:
            case 1:
                textColor = '#354148';
                bgColor = '';
                tooltipTextColor = 'white';
                break;
            case 2:
                textColor = '#354148';
                bgColor = 'yellow';
                tooltipTextColor = 'black';
                break;
            default:
                textColor = 'white';
                bgColor = 'red';
                tooltipTextColor = 'white';
        }

        button_container.css('background-color', bgColor);
        button_item_icon.css('color', textColor);
        button_item_content.css('color', textColor).html(`Ediciones: ${todayEditCount}`);
        button_item_content.append(progress_bar_wrap);

        let dayBeforeEditCountText = `<hr style="border:0 none; border-bottom:1px #999 solid; margin:5px 0;"/><div class="days-group"><div class="day-1"><h3>Hoy</h3><span>${todayEditCount}</span></div><div class="day-2"><h3>Ayer</h3><span>${yesterdayEditCount}</span></div><div class="day-3"><h3>Antier</h3><span>${dayBeforeEditCount}</span></div></div>`;
        let warningText = (savesWithoutIncrease > 0) ? `<div style="font-size:13px;border-radius:5px;padding:5px;margin-top:5px;color:${tooltipTextColor};background-color:${bgColor};"><b>${savesWithoutIncrease}</b> salvadas/guardadas consecutivas sin incremento en el contador.<br><span style="font-weight:bold;font-size:16px;">Estás estragulado?<span></div>` : '';
        button_item_link.attr('data-original-title', tooltipText + dayBeforeEditCountText + warningText);

        lastTodayEditCount = todayEditCount;
        lastYesterdayEditCount = yesterdayEditCount;
        lastDayBeforeEditCount = dayBeforeEditCount;
    }

    function receiveMessage(event) {
        let msg;

        try {
            msg = JSON.parse(event.data);
        } catch (err) {
            // Do nothing
        }

        if (msg && msg[0] === 'wmeEHUpdateUi') {
            let todayEditCount = msg[1][0];
            let yesterdayEditCount = msg[1][1];
            let dayBeforeEditCount = msg[1][2];
            updateEditCount(todayEditCount, yesterdayEditCount, dayBeforeEditCount);
        }
    }

    function checkChangedObjectCount() {
        let objectEditCount = getChangedObjectCount();

        if (objectEditCount >= _toastr_settings.warnAtEditCount && !_toastr_settings.wasWarned) {
            toastr.remove();
            toastr.error('<span style="font-size:16px;">Has editado al menos <b>' + _toastr_settings.warnAtEditCount + '</b> objetos.</span><br><br> Deberías considerar guardar pronto. Si obtienes un error al guardar, necesitarás deshacer algunos cambios/acciones e intentar nuevamente.', 'Edition Helper:', {timeOut: 25000});
            _toastr_settings.wasWarned = true;
            //log('WARMED', 0, 'ALERT', 'tomato')
        } else if (objectEditCount >= _toastr_settings.remindAtEditCount && !_toastr_settings.wasReminded) {
            toastr.remove();
            toastr.warning('<span style="font-size:16px;">Has editado al menos <b>' + _toastr_settings.remindAtEditCount + '</b> objetos.</span><br><br> Deberías considerar guardar pronto.', 'Edition Helper:', {timeOut: 15000});
            _toastr_settings.wasReminded = true;
            //log('REMINDED', 0, 'ALERT', 'orange')
        } else if (objectEditCount < _toastr_settings.remindAtEditCount) {
            _toastr_settings.wasWarned = false;
            _toastr_settings.wasReminded = false;
            toastr.remove();
            //log('REMOVED', 0, 'ALERT', 'sienna')
        }
    }

    function errorHandler(callback) {
        try {
            callback();
        } catch (e) {
            console.error('%c%s%s', 'background:darkred;color:white;padding:5px 10px;', '[ERROR] WME Edition Helper >>', e);
        }
    }

    function init() {
        userName = W.loginManager.user.userName;
        window.addEventListener('message', receiveMessage);

        $('head').append(
            $('<link/>', {
                rel: 'stylesheet',
                type: 'text/css',
                href: 'https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.4/toastr.min.css'
            }),
            $('<style type="text/css"> \
                #toast-container {position: absolute;} \
                #toast-container > div {opacity: 0.95;} \
                .toast-top-center {top: 30px;} \
                #edit-buttons #eh-button { display:flex; } \
                .toolbar .toolbar-icon-eh { color: #484848; font-size: 24px; margin: 8px 0; position: relative; text-align: center; width: 24px; } \
                .progress { background-color: red; animation: progressBar 70s ease-in-out; animation-fill-mode:both; } \
                @keyframes progressBar { 0% { width: 0; } 99% { background-color: red; } 100% { width: 100%; background-color: green; } } \
                .days-group { width:100%; display:flex; justify-content:space-between; align-item:center; } \
                .days-group div { width:30%; padding:5px; background-color:darkgray; color:white; display:flex; flex-direction:column; align-item:center; border-radius:5px; } \
                .days-group div h3 { font-size:12px; font-weight:bold; line-height:1; margin:5px 0; } \
                .days-group div span { font-size:14px; font-weight:bold; } \
                .days-group .day-1 { background-color:darkcyan; } \
                .days-group .day-2 { background-color:darkgreen; } \
                .days-group .day-3 { background-color:darkolivegreen; } \
                </style>')
        );

        $.getScript('https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.4/toastr.min.js', function() {
            toastr.options = {
                target:'#map',
                showDuration: 300,
                hideDuration: 1000,
                timeOut: 10000,
                extendedTimeOut: 1000,
                positionClass: 'toast-top-right',
                closeOnHover: false,
                closeButton: true,
                newestOnTop: true,
                progressBar: true,
                showEasing: 'swing',
                hideEasing: 'linear',
                showMethod: 'fadeIn',
                hideMethod: 'fadeOut',
            };

            W.model.actionManager.events.register('afterclearactions', null, () => errorHandler(checkEditCount));
            W.model.actionManager.events.register('afteraction', null, () => errorHandler(checkChangedObjectCount));
            W.model.actionManager.events.register('afterundoaction', null, () => errorHandler(checkChangedObjectCount));

            // Update the edit count first time.
            checkEditCount();
            toastr.success("Edition Helper Inicializado!");
            log('Initialized!', 0, 'SUCCESS', 'green');
        });
    }

    function bootstrap() {
        if (W &&
            W.loginManager &&
            W.loginManager.events &&
            W.loginManager.events.register &&
            W.map &&
            W.loginManager.user) {
            log('Initializing...', 0);
            init();
        } else {
            log('Bootstrap failed. Trying again...', 0, 'ERROR', 'darkred');
            window.setTimeout(function () {
                bootstrap();
            }, 1000);
        }
    }

    bootstrap();
}


// Code that is NOT injected into the page.
// Note that jQuery may or may not be available, so don't rely on it in this part of the script.
(function(){
    'use strict';

    function getEditorProfileFromSource(source) {
        let match = source.match(/gon.data=({.*?});gon.env=/i);
        return JSON.parse(match[1]);
    }

    function getEditCountFromProfile(profile) {
        let editingActivity = profile.editingActivity;
        return editingActivity[editingActivity.length-1];
    }

    function getEditCountByTypeFromProfile(profile, type) {
        let edits = profile.editsByType.find(edits => edits.key === type);
        return edits ? edits.value : -1;
    }

    function getEditCountByDayFromProfile(profile, day) {
        let editingActivity = profile.editingActivity;
        return editingActivity[editingActivity.length-day];
    }

    // Handle messages from the page.
    function receiveMessage(event) {
        let msg;

        try {
            msg = JSON.parse(event.data);
        }
        catch (err) {
            // Ignore errors
        }

        if (msg && msg[0] === 'wmeEHGetCounts') {
            let userName = msg[1];
            GM_xmlhttpRequest({
                method: 'GET',
                url: `https://www.waze.com/user/editor/${userName}`,
                onload: function(res) {
                    let profile = getEditorProfileFromSource(res.responseText);
                    window.postMessage(JSON.stringify(['wmeEHUpdateUi',[getEditCountFromProfile(profile), getEditCountByDayFromProfile(profile,2), getEditCountByDayFromProfile(profile,3)]]),'*');
                }
            });
        }
    }

    let wmeEH_Injected_script = document.createElement('script');
    wmeEH_Injected_script.textContent = '' + wmeEH_Injected.toString() + ' \nwmeEH_Injected();';
    wmeEH_Injected_script.setAttribute('type', 'application/javascript');
    document.body.appendChild(wmeEH_Injected_script);

    // Listen for events coming from the page script.
    window.addEventListener('message', receiveMessage);
})();

QingJ © 2025

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