// ==UserScript==
// @name Better AutomationAnywhere
// @namespace http://tampermonkey.net/
// @version 0.4.3
// @description Enhanced Automation Anywhere developer experience. Working at CR Version 34.0.0
// @author jamir-boop
// @match ://.automationanywhere.digital/*
// @icon https://cmpc-1dev.my.automationanywhere.digital/favicon.ico
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_registerMenuCommand
// @license MIT
// ==/UserScript==
(function () {
"use strict";
let activePredictionIndex = -1; // Track the active (highlighted) prediction
let currentPredictionActions = []; // Store current predictions' actions for keyboard navigation
// Universal Copy and Paste functionality with 3 slots
// Register menu commands for selecting copy/paste slots
GM_registerMenuCommand("Copy to Slot 1", () => copyToSlot(1));
GM_registerMenuCommand("Copy to Slot 2", () => copyToSlot(2));
GM_registerMenuCommand("Copy to Slot 3", () => copyToSlot(3));
GM_registerMenuCommand("Paste from Slot 1", () => pasteFromSlot(1));
GM_registerMenuCommand("Paste from Slot 2", () => pasteFromSlot(2));
GM_registerMenuCommand("Paste from Slot 3", () => pasteFromSlot(3));
// Commands and their aliases mapping to functions
const commandsWithAliases = {
addAction: {
action: addAction,
aliases: ["a", "addaction", "add action", "action"],
description: "Shows actions in sidebar",
},
addVariable: {
action: addVariable,
aliases: ["adv", "addvar", "add variable"],
description: "Shows dialog to create a new variable",
},
showVariables: {
action: showVariables,
aliases: ["v", "showvars", "list variables", "variables"],
description: "Shows variables in sidebar",
},
deleteUnusedVariables: {
action: deleteUnusedVariables,
aliases: ["duv", "delete unused", "remove unused variables"],
description: "Shows dialog to select and delete unused variables",
},
updatePackages: {
action: updatePackages,
aliases: ["up", "updatepkgs", "upgrade packages"],
description: "Opens the packages menu and unfolds the updatable items",
},
foldAll: {
action: foldAll,
aliases: ["fa", "fold all", "collapse all"],
description: "Folds all sections in the code",
},
redirectToPrivateRepository: {
action: redirectToPrivateRepository,
aliases: ["p", "private", "private bots"],
description: "Redirects to the private bots folder",
},
redirectToActivityHistorical: {
action: redirectToActivityHistorical,
aliases: ["historical", "history","activity historical"],
description: "Redirects to the activities historical tab",
},
showHelp: {
action: function () {
showHelp();
},
aliases: ["help", "man", "show help"],
description: "Displays help information for available commands",
},
};
//============ Command palette START ============
// Helper function to get DOM elements dynamically
function getCommandPalette() {
return document.getElementById("commandPalette");
}
function getCommandInput() {
return document.getElementById("commandInput");
}
function getCommandPredictions() {
return document.getElementById("commandPredictions");
}
// Toggle palette visibility
function togglePaletteVisibility() {
const commandPalette = getCommandPalette();
if (commandPalette.classList.contains("command_palette--visible")) {
commandPalette.classList.remove("command_palette--visible");
commandPalette.classList.add("command_palette--hidden");
getCommandInput().value = ""; // Clear input on hide
clearPredictions(); // Clear predictions on hide
} else {
commandPalette.classList.remove("command_palette--hidden");
commandPalette.classList.add("command_palette--visible");
getCommandInput().focus(); // Focus on the input field when showing the palette
}
}
function clearPredictions() {
getCommandPredictions().innerHTML = "";
}
function updatePredictions(input) {
clearPredictions();
if (!input) return;
Object.entries(commandsWithAliases).forEach(
([commandKey, { action, aliases, description }]) => {
const match = aliases.find((alias) =>
alias.startsWith(input.toLowerCase()),
);
if (match) {
const predictionItem = document.createElement("div");
predictionItem.classList.add("command_prediction-item");
predictionItem.innerHTML = `<strong>${match}</strong> - ${description}`;
predictionItem.addEventListener("click", () => {
getCommandInput().value = match;
executeCommand(action);
clearPredictions();
});
getCommandPredictions().appendChild(predictionItem);
}
},
);
}
// Function to setup event listeners for commandInput
function setupCommandInputEventListeners() {
const commandInput = getCommandInput(); // Ensure we're getting the current element
if (commandInput) {
// Input event listener for updating predictions
commandInput.addEventListener("input", function () {
updatePredictions(this.value);
});
// Keydown event listener for navigating and selecting predictions
commandInput.addEventListener("keydown", navigatePredictions);
}
}
// Execute command function based on input or selected prediction
function executeCommand(action) {
if (action) {
action();
} else {
showHelp(); // Show help or error if command is unknown
}
togglePaletteVisibility(); // Hide palette after executing command
}
function navigatePredictions(e) {
let commandPredictions = getCommandPredictions();
const items = commandPredictions.getElementsByClassName(
"command_prediction-item",
);
if (!items.length) {
if (e.key === "Escape") {
togglePaletteVisibility();
e.preventDefault();
}
return;
}
// Automatically select the prediction if there's only one and Enter is pressed
if (items.length === 1 && e.key === "Enter") {
items[0].click(); // Execute the single available command
e.preventDefault();
return;
}
if (["ArrowDown", "ArrowUp", "Enter"].includes(e.key)) {
e.preventDefault(); // Prevent default only for navigation keys
if (e.key === "ArrowDown") {
activePredictionIndex = (activePredictionIndex + 1) % items.length;
updateActivePrediction(items);
} else if (e.key === "ArrowUp") {
if (activePredictionIndex <= 0) {
activePredictionIndex = items.length - 1;
} else activePredictionIndex -= 1;
updateActivePrediction(items);
} else if (e.key === "Enter" && activePredictionIndex >= 0) {
items[activePredictionIndex].click();
}
} else if (e.key === "Escape") {
togglePaletteVisibility();
e.preventDefault();
}
}
function updateActivePrediction(items) {
Array.from(items).forEach((item, index) => {
item.classList.toggle("active", index === activePredictionIndex);
});
}
// Toggle command palette visibility with Shift+C
document.addEventListener("keydown", function (e) {
if (e.altKey && e.key === "p") {
e.preventDefault();
//insertCommandPalette();
insertCustomEditorPaletteButtons();
togglePaletteVisibility();
}
});
// Shortcuts to show Actions/Variables
document.addEventListener("keydown", function (e) {
if (e.code === "KeyA" && e.altKey) {
addAction();
e.preventDefault(); // Prevent default action of Alt+A
}
});
document.addEventListener("keydown", function (e) {
if (e.code === "KeyV" && e.altKey) {
showVariables();
e.preventDefault(); // Prevent default action of Alt+V
}
});
// Shortcuts to toggle sidebar
document.addEventListener("keydown", function (e) {
if (e.ctrlKey && e.code === "KeyD") {
(function () {
toogleToolbar();
})();
e.preventDefault();
}
});
// Function to toggle toolbar
function toogleToolbar() {
document
.querySelector(
"div.editor-layout__resize:nth-child(2) > button:nth-child(2)",
)
.click();
}
// Function to check if toolbar is opened
function checkPaletteState() {
let paletteElement = document.querySelector(".editor-layout__palette");
let width = paletteElement.offsetWidth; // Get the actual width
if (width <= 8) {
return "closed";
} else {
return "opened";
}
}
// Features
function addAction() {
const state = checkPaletteState();
if (state === "closed") {
toogleToolbar(); // Open the toolbar if it's closed
}
try {
document
.querySelector(
"div.editor-palette__accordion:nth-child(2) > div:nth-child(1) > header:nth-child(1) > div:nth-child(1) > button:nth-child(1) > div:nth-child(1) > div:nth-child(2)",
)
.click();
} catch {}
try {
document
.querySelector(
'.editor-palette-search__cancel button[type="button"][tabindex="-1"]',
)
.click();
} catch {}
}
function addVariable() {
const state = checkPaletteState();
if (state === "closed") {
toogleToolbar(); // Open the toolbar if it's closed
}
try {
const accordion = document.querySelector(
"div.editor-palette__accordion:nth-child(1)",
);
const addButton = accordion.querySelector(
"header:nth-child(1) button:nth-child(1)",
);
addButton.click();
} catch (error) {}
try {
const cancelButton = document.querySelector(
"div.editor-palette-search__cancel button",
);
cancelButton.click();
} catch (error) {}
try {
const createButton = document.querySelector('button[name="create"]');
createButton.click();
} catch (error) {}
try {
const confirmButton = document.querySelector(
"div.action-bar--theme_default:nth-child(1) > button:nth-child(2)",
);
confirmButton.click();
} catch (error) {}
}
function showVariables() {
const state = checkPaletteState();
if (state === "closed") {
toogleToolbar(); // Open the toolbar if it's closed
}
document
.querySelector(
'span.clipped-text.clipped-text--no_wrap.editor-palette-section__header-title[title="Variables"]',
)
?.click();
}
function showTriggers() {
const state = checkPaletteState();
if (state === "closed") {
toogleToolbar(); // Open the toolbar if it's closed
}
document
.querySelector(
'span.clipped-text.clipped-text--no_wrap.editor-palette-section__header-title[title="Triggers"]',
)
?.click();
}
async function deleteUnusedVariables() {
showVariables();
await new Promise(resolve => setTimeout(resolve, 1000));
let dropdownMenu = document.querySelector("button.action-bar__item--is_menu:nth-child(5)");
dropdownMenu.click();
await new Promise(resolve => setTimeout(resolve, 1000));
let duvButton = document.querySelector(".dropdown-options.g-scroller button.rio-focus--inset_4px:nth-child(2)");
duvButton.click();
}
function openLinkInNewTab(url) {
var newWindow = window.open(url, "_blank");
if (newWindow) {
newWindow.blur();
window.focus();
} else {
alert("Pop-up blocked. Please allow pop-ups for this website.");
}
}
function foldAll() {
const folderClicks = document.querySelectorAll(
".taskbot-canvas-list-node__collapser",
);
Array.from(folderClicks)
.reverse()
.forEach((element) => element.click());
}
function showHelp() {
// Create modal elements
const modalOverlay = document.createElement('div');
const modal = document.createElement('div');
const modalContent = document.createElement('div');
const closeButton = document.createElement('button');
// Set styles for the modal
modalOverlay.style.position = 'fixed';
modalOverlay.style.top = '0';
modalOverlay.style.left = '0';
modalOverlay.style.width = '100vw';
modalOverlay.style.height = '100vh';
modalOverlay.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
modalOverlay.style.display = 'flex';
modalOverlay.style.justifyContent = 'center';
modalOverlay.style.alignItems = 'center';
modalOverlay.style.zIndex = '1000'; // Ensure it appears above other elements
modalOverlay.style.fontSize = '16px';
modal.style.backgroundColor = 'white';
modal.style.padding = '20px';
modal.style.borderRadius = '8px';
modal.style.boxShadow = '0 4px 8px rgba(0, 0, 0, 0.1)';
modal.style.maxWidth = '800px';
modal.style.width = '80%';
modal.style.position = 'relative';
// Build the help content from the commandsWithAliases object
let helpContent = "<h3>List of Commands:</h3><ul>";
for (let command in commandsWithAliases) {
const { aliases, description } = commandsWithAliases[command];
helpContent += `<li><b>${aliases.join(', ')}:</b> ${description}</li>`;
}
helpContent += "</ul>";
modalContent.innerHTML = helpContent;
closeButton.textContent = 'Close';
closeButton.style.marginTop = '10px';
closeButton.style.padding = '8px 16px';
closeButton.style.border = 'none';
closeButton.style.backgroundColor = 'var(--color_background_interactive)';
closeButton.style.color = 'white';
closeButton.style.cursor = 'pointer';
closeButton.style.borderRadius = '4px';
// Append elements
modal.appendChild(modalContent);
modal.appendChild(closeButton);
modalOverlay.appendChild(modal);
document.body.appendChild(modalOverlay);
// Close function
function closeModal() {
document.body.removeChild(modalOverlay);
}
// Close when clicking outside the modal
modalOverlay.addEventListener('click', (e) => {
if (e.target === modalOverlay) {
closeModal();
}
});
// Close on Escape key
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
closeModal();
}
});
// Close on button click
closeButton.addEventListener('click', closeModal);
}
//============ Command palette stuff END ============
//============ Feat updatePackages stuff START ============
function updatePackages() {
document
.querySelector(".rio-icon--icon_three-vertical-dots-meatball-menu")
.click();
function clickSpanWithText(text) {
var spans = document.querySelectorAll(
"span.clipped-text.clipped-text--no_wrap.dropdown-option-label span.clipped-text__string",
);
for (var i = 0; i < spans.length; i++) {
if (spans[i].textContent.toLowerCase().includes(text.toLowerCase())) {
spans[i].click();
break;
}
}
}
// Call the function with "package"
clickSpanWithText("packages");
document
.querySelectorAll('.package-resource__title[title*="not default"]')
.forEach((span) => {
// Simulate a click on the span
span.click();
// Wait for the DOM changes to occur after the click, then perform further actions
setTimeout(() => {
let versionCell = span.querySelector(
".taskbot-edit-page__package__versions__cell.taskbot-edit-page__package__versions__cell--select",
);
if (versionCell) {
versionCell.click();
// Wait for the dropdown to appear, then perform further actions
setTimeout(() => {
let option = versionCell.querySelector(
'.choice-input-dropdown__options .choice-input-dropdown__option[role="option"]',
);
if (option) {
option.click();
}
}, 5000); // Adjust the timeout as needed
}
}, 3000); // Adjust the timeout as needed
});
}
//============ Feat updatePackages stuff END ============
//============ Feat snippets START ============
function generateEmojiString() {
const emojis = [
"😀",
"😃",
"😄",
"😁",
"😆",
"😅",
"😂",
"🤣",
"😊",
"😇",
"🙂",
"🙃",
"😉",
"😌",
"😍",
"🥰",
"😘",
"😗",
"😙",
"😚",
"😋",
"😛",
"😝",
"😜",
"🤪",
"🤨",
"🧐",
"🤓",
"😎",
"🤩",
"🥳",
"😏",
"😒",
"😞",
"😔",
"😟",
"😕",
"🙁",
"😣",
"😖",
"😫",
"😩",
"🥺",
"😢",
"😭",
"😤",
"😠",
"😡",
"🤬",
"🤯",
"😳",
"🥵",
"🥶",
"😱",
"😨",
"😰",
"😥",
"😓",
"🤗",
"🤔",
"🤭",
"🤫",
"🤥",
"😶",
"😐",
"😑",
"😬",
"🙄",
"😯",
"😦",
"😧",
"😮",
"😲",
"🥱",
"😴",
"🤤",
"😪",
"😵",
"🤐",
"🥴",
"🤢",
"🤮",
"🤧",
"😷",
"🤒",
"🤕",
"🤑",
"🤠",
"😈",
"👿",
"👹",
"👺",
"🤡",
"💩",
"👻",
"💀",
"☠️",
"👽",
"👾",
"🤖",
"🎃",
"😺",
"😸",
"😹",
"😻",
"😼",
"😽",
"🙀",
"😿",
"😾",
];
let uniqueString = "";
for (let i = 0; i < 10; i++) {
uniqueString += emojis[Math.floor(Math.random() * emojis.length)];
}
return uniqueString;
}
//============ Feat snippets END ============
//============ Feat custom selector Variables/Actions/Triggers START============
// Define updateActiveButton in the outer scope
function updateActiveButton() {
const activeSection = document.querySelector(
".editor-palette-section__header--is_active .clipped-text__string--for_presentation",
)?.innerText;
const buttons = document.querySelectorAll(".customActionVariableButton");
buttons.forEach((button) => {
if (button.textContent === activeSection) {
button.classList.add("buttonToolbarActive");
} else {
button.classList.remove("buttonToolbarActive");
}
});
}
function insertCustomEditorPaletteButtons() {
if (document.getElementById("customActionVariableButtons")) {
console.log("Custom buttons already added.");
return;
}
const containerDiv = document.createElement("div");
containerDiv.id = "customActionVariableButtons";
const variableButton = document.createElement("button");
variableButton.className = "customActionVariableButton";
variableButton.textContent = "Variables";
variableButton.onclick = function () {
showVariables();
updateActiveButton();
};
const actionButton = document.createElement("button");
actionButton.className = "customActionVariableButton";
actionButton.textContent = "Actions";
actionButton.onclick = function () {
addAction();
updateActiveButton();
};
const triggerButton = document.createElement("button");
triggerButton.className = "customActionVariableButton";
triggerButton.textContent = "Triggers";
triggerButton.onclick = function () {
showTriggers();
updateActiveButton();
};
containerDiv.appendChild(variableButton);
containerDiv.appendChild(actionButton);
containerDiv.appendChild(triggerButton);
const palette = document.querySelector(".editor-layout__palette");
if (palette) {
palette.appendChild(containerDiv);
} else {
console.log(".editor-layout__palette not found.");
return;
}
const style = document.createElement("style");
style.textContent = `
#customActionVariableButtons {
display: flex;
width: 100%;
height: 38px !important;
background: white;
}
#customActionVariableButtons button {
all: unset;
font-size: .85rem;
font-weight: 300;
cursor: pointer;
margin: 4px;
border-radius: 5px;
border: 1px solid transparent;
background-color: transparent;
color: #3c5e83;
flex-grow: 1;
text-align: center;
transition: background-color 0.3s;
}
#customActionVariableButtons button:hover {
background-color: #dae9f3;
}
.buttonToolbarActive {
border: 1px solid #3c5e83 !important;
text-shadow: 0.5px 0 0 #3c5e83 , -0.01px 0 0 #3c5e83 !important;
}
.editor-palette.g-box-sizing_border-box {
margin-top: 38px;
}
`;
document.head.appendChild(style);
}
//============ Feat custom selector Variables/Actions/Triggers END============
//============ Feat UNIVERSAL COPY/PASTE START============
// Function to copy data to the specified slot
function copyToSlot(slot) {
// Trigger the copy action in the UI
const copyButton = document.querySelector(".aa-icon-action-clipboard-copy--shared");
if (copyButton) {
copyButton.click();
// Retrieve the JSON string from localStorage
const globalClipboardJSON = localStorage.getItem('globalClipboard');
// Parse the JSON and store it in the specific slot using Tampermonkey storage
try {
const clipboardData = JSON.parse(globalClipboardJSON);
clipboardData.uid = "🔥🔥🔥"; // Reset UID
GM_setValue(`universalClipboardSlot${slot}`, JSON.stringify(clipboardData));
} catch (error) {
console.error("Failed to copy data to slot:", error);
}
}
}
// Function to paste data from the specified slot
function pasteFromSlot(slot) {
// Retrieve the JSON string from the specified slot in Tampermonkey storage
const clipboardData = GM_getValue(`universalClipboardSlot${slot}`);
if (!clipboardData) {
alert(`No data in Slot ${slot}`);
return;
}
// Generate a new unique ID for this session
let emojiUid = generateEmojiString();
// Replace the UID and store it back into localStorage
let modifiedData = clipboardData.replace(/🔥🔥🔥/g, emojiUid);
localStorage.setItem('globalClipboard', modifiedData);
localStorage.setItem('globalClipboardUid', `"${emojiUid}"`);
// Ensure the paste button is available
const pasteButton = document.querySelector(".aa-icon-action-clipboard-paste--shared");
if (pasteButton) {
// Trigger the paste action
setTimeout(() => {
pasteButton.click();
}, 500); // Adjust the timeout as needed
}
}
function insertUniversalCopyPasteButtons(attempt = 1) {
setTimeout(() => {
const actionBar = document.querySelector('.action-bar--theme_info');
// If actionBar is found and the buttons have not been added yet
if (actionBar && !actionBar.querySelector('.universalCopy')) {
const separator = document.createElement('div');
separator.className = 'action-bar__separator';
actionBar.appendChild(separator);
// Create the Universal Copy button
const copyButton = document.createElement('button');
copyButton.className = 'universalCopy rio-focus rio-focus--inset_0 rio-focus--border-radius_4px rio-focus--has_element-focus-visible rio-bare-button g-reset-element rio-bare-button--rio_interactive-softest rio-bare-button--is_parent rio-bare-button--is_clickable rio-bare-button--size_14px rio-bare-button--is_square rio-bare-button--square_26x26 action-bar__item action-bar__item--is_action taskbot-editor__toolbar__action';
copyButton.setAttribute('data-button-loading', 'false');
copyButton.setAttribute('data-button-working', 'false');
copyButton.setAttribute('data-button-ready', 'true');
copyButton.setAttribute('name', 'shared-clipboard-copy');
copyButton.setAttribute('type', 'button');
copyButton.setAttribute('tabindex', '-1');
copyButton.setAttribute('aria-label', 'Copy to shared clipboard');
copyButton.setAttribute('data-poppy-parentid', '1');
copyButton.innerHTML = `<span class="icon fa fa-rocket icon--block"></span>`;
copyButton.title = 'Universal Copy';
copyButton.onclick = universalCopy;
actionBar.appendChild(copyButton);
// Create the Universal Paste button
const pasteButton = document.createElement('button');
pasteButton.className = 'universalPaste rio-focus rio-focus--inset_0 rio-focus--border-radius_4px rio-focus--has_element-focus-visible rio-bare-button g-reset-element rio-bare-button--rio_interactive-softest rio-bare-button--is_parent rio-bare-button--is_clickable rio-bare-button--size_14px rio-bare-button--is_square rio-bare-button--square_26x26 action-bar__item action-bar__item--is_action taskbot-editor__toolbar__action';
pasteButton.setAttribute('data-button-loading', 'false');
pasteButton.setAttribute('data-button-working', 'false');
pasteButton.setAttribute('data-button-ready', 'true');
pasteButton.setAttribute('name', 'shared-clipboard-paste');
pasteButton.setAttribute('type', 'button');
pasteButton.setAttribute('tabindex', '-1');
pasteButton.setAttribute('aria-label', 'Paste from shared clipboard');
pasteButton.setAttribute('data-poppy-parentid', '1');
pasteButton.innerHTML = `<span class="icon fa fa-rocket icon--block" style="transform: rotate(180deg);"></span>`;
pasteButton.title = 'Universal Paste';
pasteButton.onclick = universalPaste;
actionBar.appendChild(pasteButton);
} else if (attempt < 3) {
// If not found, retry up to 3 times
insertUniversalCopyPasteButtons(attempt + 1);
}
}, 1000 * attempt); // Delay increases with each attempt
}
function universalCopy() {
// Trigger the copy action in the UI
document.querySelector(".aa-icon-action-clipboard-copy--shared").click();
// Retrieve the JSON string from local storage
const globalClipboardJSON = localStorage.getItem('globalClipboard');
// Parse the JSON string into an object
let globalClipboard = {};
try {
globalClipboard = JSON.parse(globalClipboardJSON);
} catch(e) {
console.error("Error parsing JSON:", e);
return; // Exit if there is a parsing error
}
// Update the "uid" key to 🔥🔥🔥
globalClipboard.uid = "🔥🔥🔥";
// Stringify the modified object and store it in Tampermonkey storage
GM_setValue('universalClipboard', JSON.stringify(globalClipboard));
}
function universalPaste() {
// Click on copy to activate paste button
document.querySelector(".aa-icon-action-clipboard-copy--shared").click();
// Retrieve the JSON string from Tampermonkey storage
let universalClipboard = GM_getValue('universalClipboard')
// Write the JSON string to local storage after replacing single quotes and UID
if (universalClipboard) {
let emojiUid = generateEmojiString();
universalClipboard = universalClipboard.replace(/'/g, '"');
universalClipboard = universalClipboard.replace(/🔥🔥🔥/g, emojiUid);
localStorage.setItem("globalClipboard", universalClipboard);
localStorage.setItem("globalClipboardUid", `"${emojiUid}"`);
}
// Wait for a second before triggering the paste action
setTimeout(() => {
document.querySelector(".aa-icon-action-clipboard-paste--shared").click();
}, 1000);
}
//============ Feat UNIVERSAL COPY/PASTE END============
//============ Feat redirect utility START ============
function redirectToPath(targetPath) {
const currentUrl = window.location.href;
// Match the base URL, keeping everything up to the first part of the domain and protocol.
const pattern = /^(https:\/\/[^\/]*\.automationanywhere\.digital)/;
// Extract the base URL using the pattern
const match = currentUrl.match(pattern);
if (match) {
const baseUrl = match[1]; // Get the base URL (e.g., https://aa-saleseng-us-4sbx.cloud.automationanywhere.digital)
const newUrl = baseUrl + targetPath; // Append the target path
window.location.href = newUrl; // Redirect to the new URL
} else {
console.error("Pattern didn't match. The URL might not be in the expected format.");
}
}
// Function to redirect to the private bots repository
function redirectToPrivateRepository() {
const privateBotsPath = '/#/bots/repository/private/';
redirectToPath(privateBotsPath);
}
// Function to redirect to the activity historical page
function redirectToActivityHistorical() {
const activityHistoricalPath = '/#/activity/historical/';
redirectToPath(activityHistoricalPath);
}
//============ Feat redirect utility END ============
//============ Feat insert command palette START ============
// Insterts the command palette
function insertCommandPalette(retryCount = 0) {
// Check if the palette was already inserted
if (document.querySelector("#commandPalette")) {
console.log("Command palette already inserted.");
return;
}
// Create the container div and set its inner HTML
const containerDiv = document.createElement("div");
containerDiv.id = "commandPalette";
containerDiv.className = "command_palette--hidden";
containerDiv.innerHTML = `
<input type="text" id="commandInput" placeholder="Enter command...">
<div id="commandPredictions" class="command_predictions"></div>
`;
// Append the container div to the body
document.body.appendChild(containerDiv);
// Create and insert CSS
const css = `
#commandPalette * {
font-size: 1.15rem;
font-family: Museo Sans,sans-serif;
}
#commandPalette {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: white;
border-radius: 10px 10px 0 0;
display: flex;
flex-direction: column;
align-items: center;
min-width: 30vw;
max-width: 80vw;
width: 600px;
z-index: 99999;
box-shadow: 0px 0px 0px 5000px #00000054;
}
#commandInput,
#commandInput:focus-visible,
#commandInput:active {
unset: all;
padding: 10px;
width: 93%;
margin-bottom: 10px;
border: 2px solid transparent;
border-radius: 5px;
}
#commandPalette:focus,
#commandPalette:active {
border-color: orange;
}
#commandPredictions {
position: absolute;
top: 100%;
left: 0;
width: 100%;
background-color: white;
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
border-radius: 0 0 10px 10px;
max-height: 200px;
overflow-y: auto;
z-index: 100000;
}
.command_prediction-item.active {
background-color: #f0f0f0;
}
.command_prediction-item strong {
font-weight: bold;
}
.command_prediction-item {
padding: 8px;
cursor: pointer;
border-bottom: 1px solid #eee;
}
.command_prediction-item:hover,
.command_prediction-item.active {
background-color: #f0f0f0;
}
@keyframes fadeIn {
from { opacity: 0; transform: translate(-50%, -50%) scale(0.85); }
to { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}
@keyframes fadeOut {
from { opacity: 1; transform: translate(-50%, -50%) scale(1); }
to { opacity: 0; transform: translate(-50%, -50%) scale(0.95); }
}
.command_palette--visible {
display: block;
animation: fadeIn 0.25s ease-out forwards;
}
.command_palette--hidden {
animation: fadeOut 0.25s ease-out forwards;
display: none;
pointer-events: none;
opacity: 0;
z-index: -1;
}
`;
const style = document.createElement("style");
style.type = "text/css";
style.appendChild(document.createTextNode(css));
document.head.appendChild(style);
setupCommandInputEventListeners();
// Check if the palette was successfully inserted, and if not, retry
if (!document.querySelector("#commandPalette")) {
if (retryCount < 5) {
console.log(`Insert failed, retrying... (${retryCount + 1}/5)`);
setTimeout(() => insertCommandPalette(retryCount + 1), 3000);
} else {
console.error("Failed to insert command palette after 5 retries.");
}
} else {
console.log("Command palette successfully inserted.");
}
}
//============ Feat insert command palette END ============
//============ Call insert functions START ============
function executeStartFunctionsRepeatedly() {
let count = 0;
const intervalId = setInterval(() => {
insertCommandPalette();
insertCustomEditorPaletteButtons();
setInterval(function () {updateActiveButton();}, 1000);
insertUniversalCopyPasteButtons();
count++;
if (count >= 3) {
clearInterval(intervalId);
}
}, 5000); // Execute every 5 seconds
}
if (document.readyState === "loading") {
// The document is still loading, wait for DOMContentLoaded
document.addEventListener(
"DOMContentLoaded",
executeStartFunctionsRepeatedly,
);
} else {
// The `DOMContentLoaded` event has already fired, execute immediately
executeStartFunctionsRepeatedly();
}
let lastHref = document.location.href;
setInterval(function () {
const currentHref = document.location.href;
if (lastHref !== currentHref) {
lastHref = currentHref;
insertCommandPalette();
insertCustomEditorPaletteButtons();
insertUniversalCopyPasteButtons();
}
}, 5000);
//============ Call insert functions END ============
})();