Advertisement
NewBestPastebins

ViGGO

Jun 25th, 2025 (edited)
379
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==UserScript==
  2. // @name         ViGGO Sletter - Endelige Version 2
  3. // @namespace    http://tampermonkey.net/
  4. // @version      2025-06-26
  5. // @description  Sletter overflødige ViGGO beskeder lynhurtigt!
  6. // @author       Oliver AAE 24-25
  7. // @match        https://aae.viggo.dk/Basic*
  8. // @icon         https://www.google.com/s2/favicons?sz=64&domain=viggo.dk
  9. // @grant        none
  10. // ==/UserScript==
  11.  
  12. (function() {
  13.     'use strict';
  14.  
  15.     const addStyles = () => {
  16.         const style = document.createElement('style');
  17.         style.textContent = `
  18.             .trash-icon {
  19.                 position: absolute;
  20.                 top: 8px;
  21.                 right: 8px;
  22.                 width: 18px;
  23.                 height: 18px;
  24.                 background-color: #f44336;
  25.                 border-radius: 50%;
  26.                 display: flex;
  27.                 align-items: center;
  28.                 justify-content: center;
  29.                 color: white;
  30.                 font-size: 10px;
  31.                 font-weight: bold;
  32.                 z-index: 10;
  33.                 box-shadow: 0 0 3px rgba(0,0,0,0.5);
  34.             }
  35.  
  36.             .trash-icon::after {
  37.                 content: "🗑️";
  38.             }
  39.  
  40.             .help-popup {
  41.                 position: fixed;
  42.                 top: 50%;
  43.                 left: 50%;
  44.                 transform: translate(-50%, -50%);
  45.                 width: 90%;
  46.                 max-width: 600px;
  47.                 max-height: 90vh;
  48.                 background: #1a1a1a;
  49.                 color: #f1f1f1;
  50.                 padding: 25px;
  51.                 border-radius: 15px;
  52.                 box-shadow: 0 10px 30px rgba(0,0,0,0.5);
  53.                 z-index: 10001;
  54.                 overflow-y: auto;
  55.                 font-family: 'Arial', sans-serif;
  56.                 display: none;
  57.             }
  58.  
  59.             .help-overlay {
  60.                 position: fixed;
  61.                 top: 0;
  62.                 left: 0;
  63.                 width: 100%;
  64.                 height: 100%;
  65.                 background: rgba(0,0,0,0.7);
  66.                 backdrop-filter: blur(5px);
  67.                 z-index: 10000;
  68.                 display: none;
  69.             }
  70.  
  71.             .help-popup h2 {
  72.                 color: #007BFF;
  73.                 margin-top: 0;
  74.                 border-bottom: 1px solid #333;
  75.                 padding-bottom: 10px;
  76.             }
  77.  
  78.             .help-popup ol {
  79.                 text-align: left;
  80.                 padding-left: 20px;
  81.             }
  82.  
  83.             .help-popup li {
  84.                 margin-bottom: 15px;
  85.                 line-height: 1.5;
  86.             }
  87.  
  88.             .close-help {
  89.                 position: absolute;
  90.                 top: 15px;
  91.                 right: 15px;
  92.                 background: #555;
  93.                 border: none;
  94.                 color: white;
  95.                 width: 30px;
  96.                 height: 30px;
  97.                 border-radius: 50%;
  98.                 cursor: pointer;
  99.                 font-size: 18px;
  100.             }
  101.         `;
  102.         document.head.appendChild(style);
  103.     };
  104.  
  105.     (() => {
  106.         addStyles();
  107.  
  108.         let lastFolderId = null;
  109.         let markedForDeletion = new Set();
  110.  
  111.         const monitorFolderChange = () => {
  112.             setInterval(() => {
  113.                 const urlParams = new URLSearchParams(window.location.search);
  114.                 const currentFolderId = urlParams.get('folder');
  115.  
  116.                 if (currentFolderId !== lastFolderId) {
  117.                     lastFolderId = currentFolderId;
  118.                     markedForDeletion.clear();
  119.  
  120.                     const notificationBanner = document.getElementById('viggo-folder-notification');
  121.                     if (notificationBanner) notificationBanner.remove();
  122.  
  123.                     if (currentFolderId === '0') {
  124.                         const banner = document.createElement('div');
  125.                         banner.id = 'viggo-folder-notification';
  126.                         banner.textContent = '📨 Du er nu i "Sendt post" mappen!';
  127.                         banner.style.position = 'fixed';
  128.                         banner.style.top = '0';
  129.                         banner.style.left = '0';
  130.                         banner.style.width = '100%';
  131.                         banner.style.padding = '12px';
  132.                         banner.style.backgroundColor = '#ff9800';
  133.                         banner.style.color = 'black';
  134.                         banner.style.textAlign = 'center';
  135.                         banner.style.zIndex = '9999';
  136.                         banner.style.fontWeight = 'bold';
  137.                         banner.style.fontSize = '16px';
  138.                         banner.style.boxShadow = '0 2px 10px rgba(0, 0, 0, 0.3)';
  139.                         document.body.appendChild(banner);
  140.                     }
  141.                 }
  142.             }, 1000);
  143.         };
  144.  
  145.  let cancelRequested = false;
  146.  
  147.         const styleButton = (button, bgColor) => {
  148.             button.style.padding = '12px 18px';
  149.             button.style.width = '100%';
  150.             button.style.backgroundColor = bgColor;
  151.             button.style.border = 'none';
  152.             button.style.color = 'white';
  153.             button.style.borderRadius = '10px';
  154.             button.style.cursor = 'pointer';
  155.             button.style.fontSize = '16px';
  156.             button.style.transition = 'background-color 0.3s ease-in-out';
  157.             button.style.marginBottom = '10px';
  158.         };
  159.  
  160.         const styleInput = (input) => {
  161.             input.style.width = '100%';
  162.             input.style.padding = '10px';
  163.             input.style.marginBottom = '15px';
  164.             input.style.borderRadius = '10px';
  165.             input.style.border = '1px solid #333';
  166.             input.style.backgroundColor = '#2b2b2b';
  167.             input.style.color = '#f1f1f1';
  168.             input.style.fontSize = '16px';
  169.         };
  170.  
  171.         const extractMessageIds = () => {
  172.             const isSentFolder = window.location.pathname.includes("/Folder/0");
  173.             markedForDeletion.clear();
  174.  
  175.             if (isSentFolder) {
  176.                 const messageList = document.querySelector("ul.list-messages");
  177.                 if (!messageList) return [];
  178.  
  179.                 const checkboxes = messageList.querySelectorAll('input[type="checkbox"][name="MessageId"]');
  180.                 return Array.from(checkboxes)
  181.                     .map(cb => cb.value)
  182.                     .filter(id => /^\d{5,6}$/.test(id)); // Accept 5 or 6 digit IDs
  183.             } else {
  184.                 const messageElements = document.querySelectorAll('li[data-drag-id]');
  185.                 return Array.from(messageElements)
  186.                     .map(el => el.getAttribute('data-drag-id'))
  187.                     .filter(id => /^\d{5,6}$/.test(id));
  188.             }
  189.         };
  190.  
  191.         const markMessagesForDeletion = (idsToDelete) => {
  192.             // Remove existing trash icons
  193.             document.querySelectorAll('.trash-icon').forEach(icon => icon.remove());
  194.  
  195.             if (window.location.pathname.includes("/Folder/0")) {
  196.                 // Sent messages
  197.                 idsToDelete.forEach(id => {
  198.                     const checkbox = document.querySelector(`input[type="checkbox"][value="${id}"]`);
  199.                     if (checkbox) {
  200.                         const listItem = checkbox.closest('li');
  201.                         if (listItem) {
  202.                             const trashIcon = document.createElement('div');
  203.                             trashIcon.className = 'trash-icon';
  204.                             listItem.appendChild(trashIcon);
  205.                         }
  206.                     }
  207.                 });
  208.             } else {
  209.                 idsToDelete.forEach(id => {
  210.                     const message = document.querySelector(`li[data-drag-id="${id}"]`);
  211.                     if (message) {
  212.                         const trashIcon = document.createElement('div');
  213.                         trashIcon.className = 'trash-icon';
  214.                         message.appendChild(trashIcon);
  215.                     }
  216.                 });
  217.             }
  218.         };
  219.  
  220.         const showLoadingEffect = () => {
  221.             const messageList = document.getElementById('message-list');
  222.             if (messageList) {
  223.                 messageList.style.filter = 'blur(5px)';
  224.                 messageList.style.transition = 'filter 0.3s ease';
  225.                 document.getElementById("message-list").style.pointerEvents = "none";
  226.                 document.getElementById("message-list").style.userSelect = "none";
  227.                 document.getElementById("message-list").style.opacity = "0.6";
  228.             }
  229.  
  230.             const loadingContainer = document.createElement('div');
  231.             loadingContainer.classList.add('custom-loading-container');
  232.             loadingContainer.innerHTML = `
  233.                 <style>
  234.                     .custom-loading-container {
  235.                         position: fixed;
  236.                         top: 50vh;
  237.                         left: 50%;
  238.                         transform: translate(-250%, -50%);
  239.                         z-index: 9999;
  240.                         text-align: center;
  241.                         font-family: sans-serif;
  242.                         color: #333;
  243.                     }
  244.  
  245.                     .spinner {
  246.                         width: 40px;
  247.                         height: 40px;
  248.                         margin: 10px auto 0;
  249.                         border-radius: 50%;
  250.                         border: 5px solid #ccc;
  251.                         border-top-color: #007bff;
  252.                         animation: spin 1s linear infinite;
  253.                     }
  254.  
  255.                     @keyframes spin {
  256.                         to { transform: rotate(360deg); }
  257.                     }
  258.  
  259.                     .checkmark {
  260.                         width: 40px;
  261.                         height: 40px;
  262.                         display: inline-block;
  263.                         border-radius: 50%;
  264.                         background-color: #28a745;
  265.                         position: relative;
  266.                         animation: fadeIn 0.5s ease-in-out forwards;
  267.                     }
  268.  
  269.                     .checkmark::after {
  270.                         content: '';
  271.                         position: absolute;
  272.                         left: 12px;
  273.                         top: 6px;
  274.                         width: 10px;
  275.                         height: 20px;
  276.                         border: solid white;
  277.                         border-width: 0 4px 4px 0;
  278.                         transform: rotate(45deg);
  279.                     }
  280.  
  281.                     @keyframes fadeIn {
  282.                         from { opacity: 0; transform: scale(0.8); }
  283.                         to { opacity: 1; transform: scale(1); }
  284.                     }
  285.                 </style>
  286.                 <div id="loading-text">Sletter</div>
  287.                 <div class="spinner" id="spinner"></div>
  288.             `;
  289.             document.body.appendChild(loadingContainer);
  290.             return loadingContainer;
  291.         };
  292.  
  293.         const finishLoadingEffect = (container) => {
  294.             const spinner = container.querySelector('#spinner');
  295.             const text = container.querySelector('#loading-text');
  296.  
  297.             if (spinner) spinner.remove();
  298.             if (text) text.textContent = 'Sådan!';
  299.  
  300.             const checkmark = document.createElement('div');
  301.             checkmark.className = 'checkmark';
  302.             container.appendChild(checkmark);
  303.  
  304.             const audio = new Audio('https://notificationsounds.com/storage/sounds/file-sounds-1085-definite.mp3');
  305.             audio.volume = 0.6;
  306.             audio.play().catch(err => console.warn('Audio failed to play:', err));
  307.  
  308.             setTimeout(() => location.reload(), 1500);
  309.         };
  310.  
  311.         const deleteMessages = async (messageIds, statusText, progressBar, loadingContainer) => {
  312.             let url;
  313.             if (window.location.href.includes("/Folder/0")) {
  314.                 url = 'https://aae.viggo.dk/Basic/Message/DeleteMessages/?folderId=0';
  315.             } else {
  316.                 url = 'https://aae.viggo.dk/Basic/Message/DeleteMessages/?folderId=11';
  317.             }
  318.  
  319.             let deleted = 0;
  320.             let i = 0;
  321.  
  322.             while (i < messageIds.length) {
  323.                 if (cancelRequested) {
  324.                     statusText.textContent = `Annulleret efter ${deleted} / ${messageIds.length} beskeder.`;
  325.                     return;
  326.                 }
  327.  
  328.                 const bulkSize = Math.floor(Math.random() * (175 - 75 + 1)) + 75;
  329.                 const chunk = messageIds.slice(i, i + bulkSize);
  330.                 const payload = chunk.map(id => `MessageId=${encodeURIComponent(id)}`).join('&');
  331.  
  332.                 try {
  333.                     const res = await fetch(url, {
  334.                         method: 'DELETE',
  335.                         headers: {
  336.                             'Accept': '*/*',
  337.                             'Content-Type': 'application/x-www-form-urlencoded',
  338.                             'X-Requested-With': 'XMLHttpRequest'
  339.                         },
  340.                         body: payload,
  341.                         credentials: 'include'
  342.                     });
  343.  
  344.                     if (res.ok) {
  345.                         deleted += chunk.length;
  346.                         progressBar.value = (deleted / messageIds.length) * 100;
  347.                         statusText.textContent = `Sletter ${deleted} / ${messageIds.length}`;
  348.                     } else {
  349.                         console.error('Sletning fejlede:', res.statusText);
  350.                     }
  351.                 } catch (err) {
  352.                     console.error('Netværksfejl ved sletning:', err);
  353.                 }
  354.  
  355.                 i += bulkSize;
  356.             }
  357.  
  358.             statusText.textContent = 'Sletning færdig - opdaterer siden...';
  359.             finishLoadingEffect(loadingContainer);
  360.         };
  361.  
  362.         const showConfirmation = (count, onConfirm) => {
  363.             const overlay = document.createElement('div');
  364.             overlay.style.position = 'fixed';
  365.             overlay.style.top = 0;
  366.             overlay.style.left = 0;
  367.             overlay.style.width = '100%';
  368.             overlay.style.height = '100%';
  369.             overlay.style.backgroundColor = 'rgba(0, 0, 0, 0)';
  370.             overlay.style.backdropFilter = 'blur(0px)';
  371.             overlay.style.transition = 'background-color 300ms ease, backdrop-filter 300ms ease';
  372.             overlay.style.zIndex = '9999';
  373.             overlay.style.pointerEvents = 'auto';
  374.             document.body.appendChild(overlay);
  375.  
  376.             requestAnimationFrame(() => {
  377.                 overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.3)';
  378.                 overlay.style.backdropFilter = 'blur(5px)';
  379.             });
  380.  
  381.             const confirmBox = document.createElement('div');
  382.             confirmBox.style.position = 'fixed';
  383.             confirmBox.style.top = '50%';
  384.             confirmBox.style.left = '50%';
  385.             confirmBox.style.transform = 'translate(-50%, -50%) scale(0.9)';
  386.             confirmBox.style.opacity = '0';
  387.             confirmBox.style.transition = 'transform 250ms ease, opacity 250ms ease';
  388.             confirmBox.style.background = '#1a1a1a';
  389.             confirmBox.style.color = '#fff';
  390.             confirmBox.style.padding = '20px';
  391.             confirmBox.style.borderRadius = '12px';
  392.             confirmBox.style.boxShadow = '0 0 15px rgba(0,0,0,0.5)';
  393.             confirmBox.style.zIndex = '10000';
  394.             confirmBox.innerHTML = `<p style="font-size:16px;margin-bottom:15px;">Er du sikker på, at du vil slette <strong>${count}</strong> besked(er)?</p>`;
  395.  
  396.             const btnYes = document.createElement('button');
  397.             btnYes.textContent = '✅ Ja, slet';
  398.             styleButton(btnYes, '#f44336');
  399.             btnYes.style.width = '45%';
  400.             btnYes.style.marginRight = '10%';
  401.  
  402.             const btnNo = document.createElement('button');
  403.             btnNo.textContent = '❌ Annuller';
  404.             styleButton(btnNo, '#555');
  405.             btnNo.style.width = '45%';
  406.  
  407.             [btnYes, btnNo].forEach(btn => {
  408.                 btn.style.transition = 'transform 150ms ease';
  409.                 btn.addEventListener('mouseenter', () => btn.style.transform = 'scale(1.05)');
  410.                 btn.addEventListener('mouseleave', () => btn.style.transform = 'scale(1)');
  411.             });
  412.  
  413.             const removePopup = () => {
  414.                 overlay.style.backgroundColor = 'rgba(0, 0, 0, 0)';
  415.                 overlay.style.backdropFilter = 'blur(0px)';
  416.                 confirmBox.style.opacity = '0';
  417.                 confirmBox.style.transform = 'translate(-50%, -50%) scale(0.9)';
  418.                 setTimeout(() => {
  419.                     confirmBox.remove();
  420.                     overlay.remove();
  421.                 }, 250);
  422.             };
  423.  
  424.             btnYes.addEventListener('click', () => {
  425.                 removePopup();
  426.                 onConfirm();
  427.             });
  428.  
  429.             btnNo.addEventListener('click', () => {
  430.                 removePopup();
  431.             });
  432.  
  433.             confirmBox.appendChild(btnYes);
  434.             confirmBox.appendChild(btnNo);
  435.             document.body.appendChild(confirmBox);
  436.  
  437.             requestAnimationFrame(() => {
  438.                 confirmBox.style.opacity = '1';
  439.                 confirmBox.style.transform = 'translate(-50%, -50%) scale(1)';
  440.             });
  441.         };
  442.  
  443.         const createUI = () => {
  444.             setInterval(() => {
  445.                 const isSentView = window.location.href.includes("/Folder/0");
  446.                 const existingBanner = document.getElementById('sent-mode-banner');
  447.  
  448.                 if (isSentView && !existingBanner) {
  449.                     const sentModeBanner = document.createElement('div');
  450.                     sentModeBanner.id = 'sent-mode-banner';
  451.                     sentModeBanner.textContent = '📤 Du ser sendte beskeder';
  452.                     sentModeBanner.style.backgroundColor = '#444';
  453.                     sentModeBanner.style.color = '#ffc107';
  454.                     sentModeBanner.style.padding = '8px';
  455.                     sentModeBanner.style.borderRadius = '8px';
  456.                     sentModeBanner.style.marginBottom = '10px';
  457.                     sentModeBanner.style.textAlign = 'center';
  458.                     uiContainer.appendChild(sentModeBanner);
  459.                 } else if (!isSentView && existingBanner) {
  460.                     existingBanner.remove();
  461.                 }
  462.             }, 1000);
  463.  
  464.             // Create help popup elements
  465.             const helpOverlay = document.createElement('div');
  466.             helpOverlay.className = 'help-overlay';
  467.  
  468.             const helpPopup = document.createElement('div');
  469.             helpPopup.className = 'help-popup';
  470.             helpPopup.innerHTML = `
  471.                 <h2>Brugsanvisning</h2>
  472.                 <ol>
  473.                     <li>Klik "🔎 Find alle besked ID(er)" for at samle ID'erne.</li>
  474.                    <li>Udfyld antallet af beskeder, du vil beholde fra toppen af indbakken.</li>
  475.                    <li>Klik "🗑️ Slet Beskeder" for at starte sletningen.</li>
  476.                    <li>Du kan manuelt fjerne ID(er) på enkelte beskeder fra bunden eller midten af mængden, hvis du ønsker det. Rækkefølgen på ID(erne) i tekstfeltet er den samme som i indbakken.</li>
  477.                    <li>⛔ Du kan afbryde sletningen med "Annuller".</li>
  478.                    <li>✅ Når sletningen er færdig, genindlæses siden automatisk.</li>
  479.                </ol>
  480.                <button class="close-help">×</button>
  481.            `;
  482.  
  483.            document.body.appendChild(helpOverlay);
  484.            document.body.appendChild(helpPopup);
  485.  
  486.            // Help popup controls
  487.            document.querySelector('.close-help').addEventListener('click', () => {
  488.                helpOverlay.style.display = 'none';
  489.                helpPopup.style.display = 'none';
  490.            });
  491.  
  492.            helpOverlay.addEventListener('click', (e) => {
  493.                if (e.target === helpOverlay) {
  494.                    helpOverlay.style.display = 'none';
  495.                    helpPopup.style.display = 'none';
  496.                }
  497.            });
  498.  
  499.            const uiContainer = document.createElement('div');
  500.            uiContainer.style.width = '300px';
  501.            uiContainer.style.position = 'fixed';
  502.            uiContainer.style.top = '85px';
  503.            uiContainer.style.right = '2px';
  504.            uiContainer.style.backgroundColor = '#1a1a1a';
  505.            uiContainer.style.color = '#f1f1f1';
  506.            uiContainer.style.padding = '20px';
  507.            uiContainer.style.borderRadius = '15px';
  508.            uiContainer.style.boxShadow = '0 6px 12px rgba(0, 0, 0, 0.3)';
  509.            uiContainer.style.zIndex = '9999';
  510.            uiContainer.style.fontFamily = "'Arial', sans-serif";
  511.            uiContainer.style.display = 'none';
  512.  
  513.            const header = document.createElement('div');
  514.            header.innerHTML = '🗑️ <strong>Viggo Besked Sletter</strong>';
  515.            header.style.marginBottom = '15px';
  516.            header.style.fontSize = '18px';
  517.            uiContainer.appendChild(header);
  518.  
  519.            const label = document.createElement('label');
  520.            label.textContent = 'Skriv Besked ID(er) (komma-separeret):';
  521.            label.style.display = 'block';
  522.            label.style.marginBottom = '5px';
  523.  
  524.            const textarea = document.createElement('textarea');
  525.            textarea.style.width = '100%';
  526.            textarea.style.height = '100px';
  527.            textarea.style.padding = '10px';
  528.            textarea.style.borderRadius = '10px';
  529.            textarea.style.border = '1px solid #333';
  530.            textarea.style.marginBottom = '15px';
  531.            textarea.style.backgroundColor = '#2b2b2b';
  532.            textarea.style.color = '#f1f1f1';
  533.            textarea.style.resize = 'none';
  534.  
  535.            const extractButton = document.createElement('button');
  536.            extractButton.textContent = '🔎 Find alle besked ID(er)';
  537.            styleButton(extractButton, '#4CAF50');
  538.            extractButton.addEventListener('click', () => {
  539.                document.getElementById("message-list").style.pointerEvents = "none";
  540.                document.getElementById("message-list").style.userSelect = "none";
  541.                document.getElementById("message-list").style.opacity = "0.6";
  542.  
  543.                (function autoScrollMessageList() {
  544.                    const element = document.getElementById('message-list');
  545.                    if (!element) return console.warn('Element #message-list not found');
  546.  
  547.                    const interval = setInterval(() => {
  548.                        const maxScroll = element.scrollHeight - element.clientHeight;
  549.                        const currentScroll = element.scrollTop;
  550.  
  551.                        element.scrollTop += 10;
  552.  
  553.                        if (currentScroll >= maxScroll - 1) {
  554.                            clearInterval(interval);
  555.                            const messageIds = extractMessageIds();
  556.                            textarea.value = messageIds.join(', ');
  557.                            console.log('Reached bottom of #message-list');
  558.                            document.getElementById("message-list").style.pointerEvents = "auto";
  559.                            document.getElementById("message-list").style.userSelect = "auto";
  560.                            document.getElementById("message-list").style.opacity = "1";
  561.  
  562.                            // Update deletion marks
  563.                            const topCount = parseInt(topExclusionInput.value) || 0;
  564.                            const allIds = textarea.value.split(',').map(id => id.trim()).filter(Boolean);
  565.                            const idsToDelete = topCount > 0 ? allIds.slice(topCount) : allIds;
  566.                            markMessagesForDeletion(idsToDelete);
  567.                        }
  568.                    }, 1);
  569.                })();
  570.            });
  571.  
  572.            const topExclusionLabel = document.createElement('label');
  573.            topExclusionLabel.textContent = 'Antal beskeder der skal beholdes fra toppen:';
  574.            topExclusionLabel.style.display = 'block';
  575.            topExclusionLabel.style.marginBottom = '5px';
  576.  
  577.            const topExclusionInput = document.createElement('input');
  578.            topExclusionInput.type = 'number';
  579.            styleInput(topExclusionInput);
  580.            topExclusionInput.addEventListener('input', () => {
  581.                const topCount = parseInt(topExclusionInput.value) || 0;
  582.                const allIds = textarea.value.split(',').map(id => id.trim()).filter(Boolean);
  583.                const idsToDelete = topCount > 0 ? allIds.slice(topCount) : allIds;
  584.                markMessagesForDeletion(idsToDelete);
  585.            });
  586.  
  587.            const statusText = document.createElement('div');
  588.            statusText.style.marginBottom = '10px';
  589.  
  590.            const progressBar = document.createElement('progress');
  591.            progressBar.style.width = '100%';
  592.            progressBar.max = 100;
  593.            progressBar.value = 0;
  594.  
  595.            const cancelButton = document.createElement('button');
  596.            cancelButton.textContent = '⛔ Annuller';
  597.            styleButton(cancelButton, '#555');
  598.            cancelButton.style.marginTop = '10px';
  599.            cancelButton.addEventListener('click', () => {
  600.                cancelRequested = true;
  601.            });
  602.  
  603.            const deleteButton = document.createElement('button');
  604.            deleteButton.textContent = '🗑️ Slet Beskeder';
  605.            styleButton(deleteButton, '#f44336');
  606.            deleteButton.addEventListener('click', () => {
  607.                cancelRequested = false;
  608.                const topCount = parseInt(topExclusionInput.value) || 0;
  609.                const allIds = textarea.value.split(',').map(id => id.trim()).filter(Boolean);
  610.                const idsToDelete = topCount > 0 ? allIds.slice(topCount) : allIds;
  611.  
  612.                if (idsToDelete.length === 0) {
  613.                    statusText.textContent = 'Ingen beskeder valgt.';
  614.                    return;
  615.                }
  616.  
  617.                showConfirmation(idsToDelete.length, async () => {
  618.                    deleteButton.disabled = true;
  619.                    deleteButton.style.opacity = '0.5';
  620.                    deleteButton.textContent = '⏳ Sletter...';
  621.                    statusText.textContent = `Sletter 0 / ${idsToDelete.length}`;
  622.                    const loadingContainer = showLoadingEffect();
  623.                    await deleteMessages(idsToDelete, statusText, progressBar, loadingContainer);
  624.                    deleteButton.disabled = false;
  625.                    deleteButton.style.opacity = '1';
  626.                    deleteButton.textContent = '🗑️ Slet Beskeder';
  627.                });
  628.            });
  629.  
  630.            const helpButton = document.createElement('button');
  631.            helpButton.textContent = '📘 Brugsanvisning';
  632.            styleButton(helpButton, '#007BFF');
  633.            helpButton.addEventListener('click', () => {
  634.                helpOverlay.style.display = 'block';
  635.                helpPopup.style.display = 'block';
  636.            });
  637.  
  638.            uiContainer.appendChild(label);
  639.            uiContainer.appendChild(textarea);
  640.            uiContainer.appendChild(extractButton);
  641.            uiContainer.appendChild(topExclusionLabel);
  642.            uiContainer.appendChild(topExclusionInput);
  643.            uiContainer.appendChild(deleteButton);
  644.            uiContainer.appendChild(cancelButton);
  645.            uiContainer.appendChild(statusText);
  646.            uiContainer.appendChild(progressBar);
  647.            uiContainer.appendChild(helpButton);
  648.  
  649.            document.body.appendChild(uiContainer);
  650.  
  651.            const toggleButton = document.createElement('button');
  652.            toggleButton.textContent = '🔽 Åben Sletter';
  653.            toggleButton.id = 'customToggleButton';
  654.            toggleButton.style.position = 'fixed';
  655.            toggleButton.style.top = '41px';
  656.            toggleButton.style.right = '-2px';
  657.            toggleButton.style.backgroundColor = '#2b2a2d';
  658.            toggleButton.style.color = '#f1f1f1';
  659.            toggleButton.style.padding = '8px 14px';
  660.            toggleButton.style.border = 'none';
  661.            toggleButton.style.cursor = 'pointer';
  662.            toggleButton.style.width = '164px';
  663.            toggleButton.style.fontSize = '18px';
  664.            toggleButton.style.zIndex = '10000';
  665.  
  666.            toggleButton.addEventListener('click', () => {
  667.                const isVisible = uiContainer.style.display === 'block';
  668.                uiContainer.style.display = isVisible ? 'none' : 'block';
  669.                toggleButton.textContent = isVisible ? '🔽 Åben Sletter' : '🔼 Luk Sletter';
  670.                toggleButton.classList.toggle('active');
  671.            });
  672.  
  673.            document.body.appendChild(toggleButton);
  674.  
  675.            const style = document.createElement('style');
  676.            style.textContent = `
  677.                #customToggleButton {
  678.                    border-radius: 0 0 0 5px;
  679.                    position: relative;
  680.                    overflow: hidden;
  681.                    background-color: rgba(43, 42, 45, 1);
  682.                }
  683.  
  684.                #customToggleButton::after {
  685.                    content: '';
  686.                    position: absolute;
  687.                    bottom: 0;
  688.                    left: 50%;
  689.                    height: 2px;
  690.                    width: 0%;
  691.                    background-color: #f1f1f1;
  692.                    transition: width 0.3s ease, left 0.3s ease;
  693.                    transform: translateX(-50%);
  694.                }
  695.  
  696.                #customToggleButton::after {
  697.                    content: '';
  698.                    position: absolute;
  699.                    bottom: 0;
  700.                    left: 50%;
  701.                    height: 2px;
  702.                    width: 0%;
  703.                    background-color: #f1f1f1;
  704.                    transform: translateX(-50%);
  705.                    transition: none;
  706.                }
  707.  
  708.                #customToggleButton:hover::after {
  709.                    width: 100%;
  710.                    left: 0;
  711.                    transform: none;
  712.                    transition: width 0.3s ease, left 0.3s ease;
  713.                }
  714.  
  715.                #customToggleButton:hover {
  716.                  background-color: rgba(43, 42, 45, 0.1);
  717.                }
  718.  
  719.                #customToggleButton:focus {
  720.                    outline: none;
  721.                    box-shadow: none;
  722.                }
  723.  
  724.                #customToggleButton:hover::after {
  725.                    width: 100%;
  726.                    left: 0;
  727.                    transform: none;
  728.                }
  729.  
  730.                #customToggleButton.active::after {
  731.                    background-color: #117596;
  732.                    height: 4px;
  733.                }
  734.            `;
  735.            document.head.appendChild(style);
  736.        };
  737.  
  738.  
  739.        createUI();
  740.        monitorFolderChange();
  741.    })();
  742. })();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement