Waze Manage Bookmarks with Backup2

Displays a UI for managing bookmarks on the Waze editor screen, adds clear cache, export, and import features for bookmarks.

// ==UserScript==
// @name         Waze Manage Bookmarks with Backup2
// @namespace    https://greasyfork.org/ja/users/735907-cauliflower-carrot
// @version      2.4
// @description  Displays a UI for managing bookmarks on the Waze editor screen, adds clear cache, export, and import features for bookmarks.
// @author       aoi
// @match        https://www.waze.com/*/editor*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    const defaultFontSize = '16px'; // Set default font size
    let allowedUrls = JSON.parse(localStorage.getItem('allowedUrls')) || []; // Load saved bookmarks

    window.addEventListener('load', function() {
        // Create and add the bookmark management button
        const button = document.createElement("button");
        button.innerHTML = "Bookmarks";
        button.style.position = "fixed";
        button.style.zIndex = "10000";
        button.style.backgroundColor = "#4CAF50";
        button.style.color = "white";
        button.style.border = "none";
        button.style.borderRadius = "5px";
        button.style.cursor = "pointer";
        button.style.fontSize = "14px";
        button.style.padding = "5px 10px";
        button.style.width = "100px";
        button.style.height = "30px";
        button.style.right = '310px';
        button.style.top = '1px';

        // Create the UI elements for bookmark management
        const bookmarkManagementDiv = document.createElement("div");
        bookmarkManagementDiv.innerHTML = `
            <h3 style="text-align: left; margin: 0 0 10px 0;">Bookmark Management</h3>
            <input type="text" id="urlInput" placeholder="Enter URL" style="width: 100%; padding: 5px; box-sizing: border-box;">
            <input type="text" id="nameInput" placeholder="Enter Bookmark Name" style="width: 100%; padding: 5px; box-sizing: border-box; margin-top: 5px;">
            <button id="addUrlButton" style="width: 100%; margin-top: 5px; padding: 5px; background-color: blue; color: white; border: none; border-radius: 5px;">Add Bookmark</button>
            <ul id="urlList" style="list-style: none; padding: 0; margin: 10px 0 0 0; max-height: 150px; overflow-y: auto;"></ul>
            <button id="clearCacheButton" style="width: 100%; margin-top: 15px; padding: 5px; background-color: blue; color: white; border: none; border-radius: 5px;">Clear Cache</button>
        `;
        bookmarkManagementDiv.style.position = "fixed";
        bookmarkManagementDiv.style.right = "10px";
        bookmarkManagementDiv.style.top = "60px";
        bookmarkManagementDiv.style.zIndex = "10000";
        bookmarkManagementDiv.style.backgroundColor = "#f9f9f9";
        bookmarkManagementDiv.style.padding = "15px";
        bookmarkManagementDiv.style.border = "1px solid #ccc";
        bookmarkManagementDiv.style.borderRadius = "5px";
        bookmarkManagementDiv.style.width = "350px";
        bookmarkManagementDiv.style.display = "none"; // Initially hidden

        // Function to update the displayed bookmark list
        function updateUrlList() {
            const urlList = document.getElementById('urlList');
            urlList.innerHTML = '';
            allowedUrls.forEach((item) => {
                const li = document.createElement('li');
                li.style.display = "flex";
                li.style.justifyContent = "space-between";
                li.style.alignItems = "center";
                li.innerHTML = `<span style="flex: 1; font-size: ${defaultFontSize};"><a href="${item.url}" style="color: blue;" class="clearCacheLink" data-url="${item.url}">${item.name || item.url}</a></span>`;
                const removeButton = document.createElement('button');
                removeButton.textContent = 'Remove';
                removeButton.style.marginLeft = "10px";
                removeButton.addEventListener('click', function() {
                    allowedUrls = allowedUrls.filter(i => i.url !== item.url);
                    localStorage.setItem('allowedUrls', JSON.stringify(allowedUrls));
                    updateUrlList();
                });
                li.appendChild(removeButton);
                urlList.appendChild(li);
            });
        }

        // Function to clear the cache and navigate to a specified URL
        function clearCacheAndNavigate(url) {
            caches.keys().then(names => {
                const cacheClearPromises = names.map(name => caches.delete(name));
                return Promise.all(cacheClearPromises);
            }).then(() => {
                window.location.href = url; // Navigate to the specified URL after cache is cleared
            });
        }

        // Add a bookmark
        document.addEventListener('click', function(e) {
            if (e.target && e.target.id === 'addUrlButton') {
                const urlInput = document.getElementById('urlInput');
                const nameInput = document.getElementById('nameInput');
                const newUrl = urlInput.value.trim();
                const newName = nameInput.value.trim();

                if (newUrl && !allowedUrls.some(item => item.url === newUrl)) {
                    allowedUrls.push({ url: newUrl, name: newName });
                    localStorage.setItem('allowedUrls', JSON.stringify(allowedUrls));
                    urlInput.value = '';
                    nameInput.value = '';
                    updateUrlList();
                } else if (allowedUrls.some(item => item.url === newUrl)) {
                    alert('This bookmark already exists in the list.');
                } else {
                    alert('Please enter a URL.');
                }
            }
        });

        // Clear cache and reload
        document.addEventListener('click', function(e) {
            if (e.target && e.target.id === 'clearCacheButton') {
                clearCacheAndNavigate(window.location.href); // Clear cache and reload the current page
            }
        });

        // Clear cache and navigate to the link
        document.addEventListener('click', function(e) {
            if (e.target && e.target.classList.contains('clearCacheLink')) {
                e.preventDefault();
                const targetUrl = e.target.getAttribute('data-url');
                clearCacheAndNavigate(targetUrl); // Call the function
            }
        });

        // Export bookmarks to JSON file
        function exportBookmarks() {
            const dataStr = JSON.stringify(allowedUrls);
            const dataUri = 'data:application/json;charset=utf-8,' + encodeURIComponent(dataStr);

            const exportFileDefaultName = 'bookmarks.json';
            const linkElement = document.createElement('a');
            linkElement.setAttribute('href', dataUri);
            linkElement.setAttribute('download', exportFileDefaultName);
            linkElement.click();
        }

        // Import bookmarks from JSON file
        function importBookmarks(event) {
            const file = event.target.files[0];
            const reader = new FileReader();
            reader.onload = function(e) {
                const importedData = JSON.parse(e.target.result);
                allowedUrls = importedData;
                localStorage.setItem('allowedUrls', JSON.stringify(allowedUrls));
                updateUrlList();
            };
            reader.readAsText(file);
        }

        // Create export button
        const exportButton = document.createElement("button");
        exportButton.textContent = "Export Bookmarks";
        exportButton.style.width = "100%";
        exportButton.style.marginTop = "10px";
        exportButton.addEventListener('click', exportBookmarks);
        bookmarkManagementDiv.appendChild(exportButton);

        // Create import input field
        const importButton = document.createElement("input");
        importButton.type = "file";
        importButton.style.width = "100%";
        importButton.style.marginTop = "10px";
        importButton.addEventListener('change', importBookmarks);
        bookmarkManagementDiv.appendChild(importButton);

        // Show or hide the UI when the management button is clicked
        button.addEventListener('click', function() {
            bookmarkManagementDiv.style.display = bookmarkManagementDiv.style.display === "none" ? "block" : "none";
        });

        // Add the button and UI to the page
        document.body.appendChild(button);
        document.body.appendChild(bookmarkManagementDiv);

        // Update the bookmark list on initial load
        updateUrlList();
    });
})();