// ==UserScript==
// @name Chatgpt 角色扮演助手/Chatgpt Role Play Helper
// @namespace http://tampermonkey.net/
// @version 2.8.3
// @description 在屏幕中央弹出一个可拖动位置的悬浮窗,悬浮窗内有三个文本框并且可以编辑,以及一个按钮,点击按钮后将这三个文本框的内容合并,并将合并后的文本输入到页面中符合特定CSS类别的文本框中,最后触发符合特定CSS类别的提交按钮以提交表单。
// @author Chatgpt (most)and 环白
// @match https://chat.openai.com/*
// @match https://app.slack.com/*
// @icon https://chat.openai.com/favicon.ico
// @grant GM_addStyle
// ==/UserScript==
(function() {
'use strict';
// Define CSS styles
GM_addStyle(`
/* Styles for elements with transparent or transparent black background */
[style*="background: transparent"],
[style*="background: rgba(0, 0, 0, 0)"] {
color: black !important;
}
.my-clickme-button {
position: fixed;
bottom: 0;
right: 0;
margin: 20px;
background-color: rgba(255, 165, 0, 0.8);
border-radius: 30px;
width: 50px;
height: 50px;
font-size: 16px;
line-height: 50px;
text-align: center;
color: white;
box-shadow: 2px 2px 3px gray;
z-index: 9999;
}
@media (max-width: 480px) {
.my-clickme-button {
font-size: 80%; /* 缩小按钮字体大小 */
width: 40px; /* 缩小按钮宽度 */
height: 40px; /* 缩小按钮高度 */
line-height: 40px; /* 缩小按钮行高 */
border-radius: 20px; /* 缩小按钮圆角 */
margin: 10px; /* 缩小按钮外边距 */
right: 0px; /* 调整按钮在右侧的位置 */
top: calc(20%);
}
}
.my-button {
display: inline-block;
padding: 8px;
background-color: #2196F3;
color: white;
border-radius: 5px;
cursor: pointer;
}
.my-button:hover {
background-color: #0c7cd5;
}
.my-button-load {
position: absolute;
top: 0;
left: 0;
margin: 20px;
}
.my-button-save {
position: absolute;
top: 0;
right: 0;
margin: 20px;
}
.my-button-send {
position: absolute;
bottom: 0;
right: 0;
margin: 20px;
}
.my-button-add {
position: absolute;
bottom: 0;
right: 70px;
margin: 20px;
}.my-button-en {
position: absolute;
top: 82px;
left: 200px;
margin: 20px;
}
.my-special-button {
display: inline-block;
padding: 10px;
background-color: #FF5722;
color: white;
border-radius: 8px;
cursor: pointer;
}
.my-special-button-loadSave1 {
position: absolute;
top: 100px;
left: 60px;
margin: 20px;
}
.my-special-button-loadSave2 {
position: absolute;
top: 100px;
left: 230px;
margin: 20px;
}
.my-special-button-loadSave3 {
position: absolute;
top: 160px;
left: 60px;
margin: 20px;
}
.my-special-button-loadSave4 {
position: absolute;
top: 160px;
left: 230px;
margin: 20px;
}
.my-special-button-loadSave5 {
position: absolute;
top: 220px;
left: 60px;
margin: 20px;
}
.my-special-button-loadSave6 {
position: absolute;
top: 220px;
left: 230px;
margin: 20px;
}
.my-special-button-loadSave7 {
position: absolute;
top: 280px;
left: 60px;
margin: 20px;
}
.my-special-button-loadSave8 {
position: absolute;
top: 280px;
left: 230px;
margin: 20px;
}
.my-special-button-loadSave9 {
position: absolute;
top: 340px;
left: 60px;
margin: 20px;
}
.my-special-button-loadSave10 {
position: absolute;
top: 340px;
left: 230px;
margin: 20px;
}
.my-special-button-loadSave11 {
position: absolute;
top: 400px;
left: 60px;
margin: 20px;
}
.my-special-button-loadSave12 {
position: absolute;
top: 400px;
left: 230px;
margin: 20px;
}
.my-special-button-Save1 {
position: absolute;
top: 100px;
left: 60px;
margin: 20px;
}
.my-special-button-Save2 {
position: absolute;
top: 100px;
left: 230px;
margin: 20px;
}
.my-special-button-Save3 {
position: absolute;
top: 160px;
left: 60px;
margin: 20px;
}
.my-special-button-Save4 {
position: absolute;
top: 160px;
left: 230px;
margin: 20px;
}
.my-special-button-Save5 {
position: absolute;
top: 220px;
left: 60px;
margin: 20px;
}
.my-special-button-Save6 {
position: absolute;
top: 220px;
left: 230px;
margin: 20px;
}
.my-special-button-Save7 {
position: absolute;
top: 280px;
left: 60px;
margin: 20px;
}.my-special-button-Save8 {
position: absolute;
top: 280px;
left: 230px;
margin: 20px;
}
.my-special-button-Save9 {
position: absolute;
top: 340px;
left: 60px;
margin: 20px;
}
.my-special-button-Save10 {
position: absolute;
top: 340px;
left: 230px;
margin: 20px;
}
.my-special-button-Save11 {
position: absolute;
top: 400px;
left: 60px;
margin: 20px;
}
.my-special-button-Save12 {
position: absolute;
top: 400px;
left: 230px;
margin: 20px;
}
.my-hover-box {
position: fixed;
top: 100px;
right: 50px;
width: 400px;
height: 600px;
padding: 20px;
background-color: #f1f1f1;
border: 1px solid #ccc;
border-radius: 5px;
z-index: 9999;
display: flex;
flex-direction: column;
}@media (max-width: 480px) {
.my-hover-box {
width: 320px;
height: 480px;
font-size: 80%; /* 缩小根元素的字体大小 */
}
/* 使用rem单位缩小所有子元素的大小 */
.my-hover-box * {
font-size: 1rem;
} .my-help-label {
font-size: 8px;
}
}
.my-text-area {
display: block;
margin: 0;
padding: 0;
border-radius: 5px;
border: 1px solid #ccc;
font-size: 16px;
width: calc(100% - 16px);
height: calc(20%);
/* 设置自动换行 */
white-space: pre-wrap;
word-wrap: break-word;
}
.my-label {
display: block;
margin-bottom: 0;
font-weight: bold;
font-size: 14px;
}
.space-div {
height: 60px;
}
/* Position text boxes and labels in hover box */
.my-text-area:nth-child(odd) {
margin-right: 16px;
}
.my-label:nth-child(odd) {
text-align: left;
margin-right: 16px;
}
.my-text-area:nth-child(even) {
margin-left: 16px;
}
.my-label:nth-child(even) {
text-align: left;
margin-left: 16px;
}
.my-sellect-label {
text-align: left;
margin-left: 20px;
font-family: KaiTi, 'Microsoft Yahei', sans-serif;
font-weight: bold;
margin-bottom: 0;
font-size: 20px;
}
.my-en-label {
text-align: left;
margin-left: 60px;
font-weight: bold;
margin-bottom: 0;
font-size: 20px;
}
.my-help-label {
margin-bottom: 0;
font-weight: bold;
font-size: 14px;
text-align: left;
margin-left: 45px;
white-space: pre-wrap;
}
.my-text-area.fourtextareamode{
height: calc(15%);
}
.space-div.fourtextareamode{
height: 30px;
}
.my-fourtextareamode-button{
position: absolute;
top: 20px;
right: 140px;
width: 40px;
height: 40px;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor' class='bi bi-dice-4' viewBox='0 0 16 16'%3E%3Cpath d='M13 1a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h10zM3 0a3 3 0 0 0-3 3v10a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V3a3 3 0 0 0-3-3H3z'/%3E%3Cpath d='M5.5 4a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm8 0a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0 8a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm-8 0a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z'/%3E%3C/svg%3E");
background-size: 20px;
background-repeat: no-repeat;
background-position: center;
background-color: transparent;
border-radius: 50%;
border: none;
cursor: pointer;
z-index: 9999;
}
.my-fourtextareamode-button.fourtextareamode {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor' class='bi bi-dice-3' viewBox='0 0 16 16'%3E%3Cpath d='M13 1a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h10zM3 0a3 3 0 0 0-3 3v10a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3V3a3 3 0 0 0-3-3H3z'/%3E%3Cpath d='M5.5 4a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm8 8a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm-4-4a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z'/%3E%3C/svg%3E");
}
.my-help-button {
position: absolute;
top: 20px;
right: 80px;
width: 40px;
height: 40px;
background-color: transparent;
background-size: 20px;
background-repeat: no-repeat;
background-position: center;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor' class='bi bi-question-circle' viewBox='0 0 16 16'%3E%3Cpath d='M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z'/%3E%3Cpath d='M5.255 5.786a.237.237 0 0 0 .241.247h.825c.138 0 .248-.113.266-.25.09-.656.54-1.134 1.342-1.134.686 0 1.314.343 1.314 1.168 0 .635-.374.927-.965 1.371-.673.489-1.206 1.06-1.168 1.987l.003.217a.25.25 0 0 0 .25.246h.811a.25.25 0 0 0 .25-.25v-.105c0-.718.273-.927 1.01-1.486.609-.463 1.244-.977 1.244-2.056 0-1.511-1.276-2.241-2.673-2.241-1.267 0-2.655.59-2.75 2.286zm1.557 5.763c0 .533.425.927 1.01.927.609 0 1.028-.394 1.028-.927 0-.552-.42-.94-1.029-.94-.584 0-1.009.388-1.009.94z'/%3E%3C/svg%3E");
border-radius: 50%;
border: none;
cursor: pointer;
z-index: 9999;
}
.my-skin-button {
position: absolute;
top: 20px;
right: 110px;
width: 40px;
height: 40px;
background-color: transparent;
background-size: 20px;
background-repeat: no-repeat;
background-position: center;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor' class='bi bi-palette' viewBox='0 0 16 16'%3E%3Cpath d='M8 5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm4 3a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zM5.5 7a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm.5 6a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z'/%3E%3Cpath d='M16 8c0 3.15-1.866 2.585-3.567 2.07C11.42 9.763 10.465 9.473 10 10c-.603.683-.475 1.819-.351 2.92C9.826 14.495 9.996 16 8 16a8 8 0 1 1 8-8zm-8 7c.611 0 .654-.171.655-.176.078-.146.124-.464.07-1.119-.014-.168-.037-.37-.061-.591-.052-.464-.112-1.005-.118-1.462-.01-.707.083-1.61.704-2.314.369-.417.845-.578 1.272-.618.404-.038.812.026 1.16.104.343.077.702.186 1.025.284l.028.008c.346.105.658.199.953.266.653.148.904.083.991.024C14.717 9.38 15 9.161 15 8a7 7 0 1 0-7 7z'/%3E%3C/svg%3E");
border-radius: 50%;
border: none;
cursor: pointer;
z-index: 9999;
}
`);
const originalTexts = {};
function changeTextContent(elementIds, newTexts) {
elementIds.forEach((id, index) => {
const element = document.getElementById(id);
if (element) {
if (originalTexts[id] === undefined) {
originalTexts[id] = element.textContent;
}
if (element.textContent === newTexts[index]) {
element.textContent = originalTexts[id];
} else {
element.textContent = newTexts[index];
}
}
});
}
function switchSkin(elementIds, targetClass, remove = false) {
elementIds.forEach((id) => {
const element = document.getElementById(id);
if (element) {
// 获取元素当前的类名
const currentClass = element.getAttribute("class");
const classList = currentClass.split(" ");
const hasTargetClass = classList.includes(targetClass);
if (remove && hasTargetClass) {
// 如果 remove 为 true 且元素包含目标类名,则移除目标类名
const updatedClassList = classList.filter(className => className !== targetClass);
element.setAttribute("class", updatedClassList.join(" "));
} else if (!remove && !hasTargetClass) {
// 如果 remove 为 false 且元素不包含目标类名,则添加目标类名
element.setAttribute("class", `${currentClass} ${targetClass}`);
}
}
});
}
function toggleVisibility(...elementIds) {
elementIds.forEach(elementId => {
const element = document.getElementById(elementId);
if (element) {
if (element.style.display === 'none') { // 如果元素不可见,则显示它
element.style.display = '';
} else { // 如果元素可见,则隐藏它
element.style.display = 'none';
}
}
});
}
function makeDraggable(element) {
let isDragging = false;
let offsetX = 0;
let offsetY = 0;
let isResizing = false;
let initialMousePos;
let initialSize;
element.addEventListener("mousedown", handleMouseDown);
element.addEventListener("touchstart", handleTouchStart);
document.addEventListener("mousemove", handleMouseMove);
document.addEventListener("touchmove", handleTouchMove);
document.addEventListener("mouseup", handleMouseUp);
document.addEventListener("touchend", handleTouchEnd);
function getCurrentScale() {
const transform = window.getComputedStyle(element).transform;
if (transform === 'none') {
return 1;
}
const matrix = transform.match(/matrix\((.+)\)/)[1].split(',').map(parseFloat);
return matrix[0]; // 假设 scaleX 和 scaleY 相同
}
function handleMouseDown(event) {
// If the target element is a text input or textarea or the zoom slider, do not start dragging
if ((event.target.tagName === 'INPUT' && event.target.type === 'text') || event.target.tagName === 'TEXTAREA' ) {
return;
}
isDragging = true;
offsetX = event.clientX - element.offsetLeft;
offsetY = event.clientY - element.offsetTop;
const cursorType = element.style.cursor;
if (cursorType.includes("nw") || cursorType.includes("ne") || cursorType.includes("sw") || cursorType.includes("se")) {
isResizing = true;
isDragging = false;
initialMousePos = { x: event.clientX, y: event.clientY };
const currentScale = getCurrentScale();
initialSize = { width: element.offsetWidth / currentScale, height: element.offsetHeight / currentScale };
} else {
isDragging = true;
offsetX = event.clientX - element.offsetLeft;
offsetY = event.clientY - element.offsetTop;
}
// Disable text selection behavior
document.body.style.userSelect = "none";
document.body.style.webkitUserSelect = "none";
document.body.style.MozUserSelect = "none";
}
function handleTouchStart(event) {
// If the target element is a text input, do not start dragging
if ((event.target.tagName === 'INPUT' && event.target.type === 'text') || event.target.tagName === 'TEXTAREA' ) {
return;
}
if (event.touches.length === 1) {
isDragging = true;
offsetX = event.touches[0].clientX - element.offsetLeft;
offsetY = event.touches[0].clientY - element.offsetTop;
// Disable text selection behavior
document.body.style.userSelect = 'none';
document.body.style.webkitUserSelect = 'none';
document.body.style.MozUserSelect = 'none';
}
}
function handleMouseMove(event) {
// Detect mouse position near the edges of the element
const rect = element.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
const edge = 16; // The number of pixels near the edge to trigger the effect
if (element.id === "button") {
if (isDragging) {
const newX = event.clientX - offsetX;
const newY = event.clientY - offsetY;
const viewportWidth = document.documentElement.clientWidth;
const viewportHeight = document.documentElement.clientHeight;
// 限制元素在浏览器可见范围内移动
const minX = 0;
const maxX = viewportWidth - element.offsetWidth-30;
const minY = 0;
const maxY = viewportHeight - element.offsetHeight-30;
element.style.left = Math.min(Math.max(newX, minX), maxX) + "px";
element.style.top = Math.min(Math.max(newY, minY), maxY) + "px";
}
} else {
// Check if the mouse is near the top edge
if (y <= edge) {
// Check if the mouse is near the left corner
if (x <= edge) {
element.style.cursor = 'nw-resize'; // Top-left corner
} else if (x >= rect.width - edge) {
element.style.cursor = 'ne-resize'; // Top-right corner
} else {
element.style.cursor = 'n-resize'; // Top edge
}
}
// Check if the mouse is near the bottom edge
else if (y >= rect.height - edge) {
// Check if the mouse is near the left corner
if (x <= edge) {
element.style.cursor = 'sw-resize'; // Bottom-left corner
} else if (x >= rect.width - edge) {
element.style.cursor = 'se-resize'; // Bottom-right corner
} else {
element.style.cursor = 's-resize'; // Bottom edge
}
}
// Check if the mouse is near the left edge
else if (x <= edge) {
element.style.cursor = 'w-resize'; // Left edge
}
// Check if the mouse is near the right edge
else if (x >= rect.width - edge) {
element.style.cursor = 'e-resize'; // Right edge
} else {
element.style.cursor = 'default'; // Default cursor
}
if (element.style.cursor.includes('nw') || element.style.cursor.includes('ne') || element.style.cursor.includes('sw') || element.style.cursor.includes('se')) {
isDragging = false;
} else {
isResizing = false;
}
if (isDragging) {
element.style.left = (event.clientX - offsetX) + "px";
element.style.top = (event.clientY - offsetY) + "px";
} else if (isResizing) {
// 计算水平和垂直方向上的缩放比例
const dx = event.clientX - initialMousePos.x;
const dy = event.clientY - initialMousePos.y;
let scaleX, scaleY;
// 根据按住的角来调整缩放中心和更新长宽比例
switch (element.style.cursor) {
case 'nw-resize':
scaleX = (initialSize.width - dx) / initialSize.width;
scaleY = (initialSize.height - dy) / initialSize.height;
element.style.transformOrigin = 'bottom right';
break;
case 'ne-resize':
scaleX = (initialSize.width + dx) / initialSize.width;
scaleY = (initialSize.height - dy) / initialSize.height;
element.style.transformOrigin = 'bottom left';
break;
case 'sw-resize':
scaleX = (initialSize.width - dx) / initialSize.width;
scaleY = (initialSize.height + dy) / initialSize.height;
element.style.transformOrigin = 'top right';
break;
case 'se-resize':
scaleX = (initialSize.width + dx) / initialSize.width;
scaleY = (initialSize.height + dy) / initialSize.height;
element.style.transformOrigin = 'top left';
break;
}
// 使缩放保持长宽比例相同
const scale = Math.min(scaleX, scaleY);
// 更新悬浮窗的缩放比例
element.style.transform = `scale(${scale})`;
}
}
}
function handleTouchMove(event) {
if (isDragging) {
event.preventDefault(); // 阻止页面滚动
element.style.left = (event.touches[0].clientX - offsetX) + 'px';
element.style.top = (event.touches[0].clientY - offsetY) + 'px';
}
}
function handleMouseUp() {
isDragging = false;
isResizing = false;
// Restore text selection behavior
document.body.style.userSelect = '';
document.body.style.webkitUserSelect = '';
document.body.style.MozUserSelect = '';
}
function handleTouchEnd() {
isDragging = false;
isResizing = false;
// Restore text selection behavior
document.body.style.userSelect = '';
document.body.style.webkitUserSelect = '';
document.body.style.MozUserSelect = '';
}
// 添加事件监听器
element.addEventListener("mousedown", handleMouseDown);
document.addEventListener("mousemove", handleMouseMove);
document.addEventListener("mouseup", handleMouseUp);
}
// Loop through all elements and set font color to black for elements with transparent backgrounds
const allElements = document.getElementsByTagName("*");
for (let i = 0; i < allElements.length; i++) {
const el = allElements[i];
const bgColor = window.getComputedStyle(el).getPropertyValue("background-color");
if (bgColor === "transparent" || bgColor === "rgba(0, 0, 0, 0)") {
el.style.color = "black";
}
}
function applyScale(scale) {
const targetElement = document.getElementById('elementToScale');
// 为目标元素添加 CSS 过渡
targetElement.style.transition = 'transform 0.3s ease-out';
// 设置缩放值
targetElement.style.transform = `scale(${scale})`;
}//获取最新的助手消息
function getLatestAssistantMessage() {
const isSlackApp = window.location.hostname === 'app.slack.com';
if (isSlackApp) {
const matchedDivs = document.querySelectorAll('div[class*="c-message_kit__blocks--rich_text"]');
for (let i = matchedDivs.length - 1; i >= 0; i--) {
const div = matchedDivs[i];
const text = div.textContent.trim();
if (text !== 'Please note: This request may violate our Acceptable Use Policy.See the Claude documentation for more information.' && text !== 'Conversation history forgotten.') {
return text;
}
}
} else {
const matchedDivs = document.querySelectorAll('div[class*="w-[calc(100%"]');
for (let i = matchedDivs.length - 1; i >= 0; i--) {
const div = matchedDivs[i];
const flexBetweenDiv = div.querySelector('div.flex.justify-between');
if (flexBetweenDiv && flexBetweenDiv.children.length > 0) {
const text = div.textContent.trim();
return text;
}
}
}
}
// Create button element and add to page
const button = document.createElement("button");
button.textContent = "ON";
button.classList.add("my-clickme-button");
button.id = "button";
document.body.appendChild(button);
makeDraggable(button);
// Create hover box element and add to page
const hoverBox = document.createElement('div');
hoverBox.classList.add('my-hover-box');
document.body.appendChild(hoverBox);
hoverBox.style.display = "none";
hoverBox.id = "hoverBox";
makeDraggable(hoverBox);
const spaceDiv = document.createElement("div");
spaceDiv.classList.add("space-div");
spaceDiv.id = "space-div";
hoverBox.appendChild(spaceDiv);
const label1 = document.createElement("label");
label1.textContent = "编写区:";
label1.classList.add("my-label");
label1.id = "label1";
hoverBox.appendChild(label1);
const textArea1 = document.createElement("textarea");
textArea1.classList.add("my-text-area");
textArea1.id = "textArea1";
hoverBox.appendChild(textArea1);
const label4 = document.createElement("label");
label4.textContent = "编写区[副]:";
label4.classList.add("my-label");
label4.id = "label4";
label4.style.display = "none";
hoverBox.appendChild(label4);
const textArea4 = document.createElement("textarea");
textArea4.classList.add("my-text-area");
textArea4.id = "textArea4"
textArea4.style.display = "none";
hoverBox.appendChild(textArea4);
const label2 = document.createElement("label");
label2.textContent = "回顾区:";
label2.classList.add("my-label");
label2.id = "label2";
hoverBox.appendChild(label2);
const textArea2 = document.createElement("textarea");
textArea2.classList.add("my-text-area");
textArea2.id = "textArea2"
hoverBox.appendChild(textArea2);
const label3 = document.createElement("label");
label3.textContent = "交互区:";
label3.classList.add("my-label");
label3.id = "label3";
hoverBox.appendChild(label3);
const textArea3 = document.createElement("textarea");
textArea3.classList.add("my-text-area");
textArea3.id = "textArea3"
hoverBox.appendChild(textArea3);
// Create load and save buttons and add to hover box
const loadButton = document.createElement("button");
loadButton.textContent = "加载";
loadButton.classList.add("my-button", "my-button-load");
loadButton.id = "loadButton";
hoverBox.appendChild(loadButton);
const saveButton = document.createElement("button");
saveButton.textContent = "保存";
saveButton.classList.add("my-button", "my-button-save");
saveButton.id = "saveButton";
hoverBox.appendChild(saveButton);
const sendButton = document.createElement("button");
sendButton.textContent = "发送";
sendButton.classList.add("my-button", "my-button-send");
sendButton.id = "sendButton";
hoverBox.appendChild(sendButton);
const skinButton = document.createElement('button');
skinButton.classList.add('my-skin-button');
skinButton.id = "skinButton";
hoverBox.appendChild(skinButton);
const addButton = document.createElement("button");
addButton.textContent = "添加";
addButton.classList.add("my-button", "my-button-add");
addButton.id = "addButton";
hoverBox.appendChild(addButton);
const fourtextareamodeButton = document.createElement("button");
fourtextareamodeButton.classList.add("my-fourtextareamode-button");
fourtextareamodeButton.id = "fourtextareamodeButton";
hoverBox.appendChild(fourtextareamodeButton);
const labelSellect = document.createElement("label");
labelSellect.textContent = "选择:";
labelSellect.classList.add("my-sellect-label");
labelSellect.id = "labelSellect";
labelSellect.style.display = "none";
hoverBox.appendChild(labelSellect);
const helpButton = document.createElement('button');
helpButton.classList.add('my-help-button');
helpButton.id = "helpButton";
hoverBox.appendChild(helpButton);
const labelHelp = document.createElement("label");
labelHelp.textContent = "\n保存按钮(Save)\n -进入保存界面,选择存档存档\n加载按钮(Load)\n -进入加载界面,选择存档加载\n加载界面\n -预设按钮1(Pre1)-加载预设文本1\n -预设按钮2(Pre2)-加载预设文本2\n发送按钮(Send)\n -点击后发送文本\n添加按钮(Add)\n -点击后将最新回复填入回顾区\n右上左侧按钮(Dice)\n -切换单/双编写区模式\n右上中间按钮(Palette)\n -进入皮肤界面,选择皮肤\n右上右侧按钮(Help)\n -显示帮助文本\n编写区规则:\n使用{R}指代回顾区内容\n使用{D}指代交互区内容\n eg:\n【123{R}{D}】\n\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0【456】>>>>>>123456789\n\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0\u00A0【789】";
labelHelp.classList.add("my-help-label");
labelHelp.id = "labelHelp";
labelHelp.style.display = "none";
hoverBox.appendChild(labelHelp);
const labelEn = document.createElement("label");
labelEn.textContent = "Language:";
labelEn.classList.add("my-en-label");
labelEn.id = "labelEn";
labelEn.style.display = "none";
hoverBox.appendChild(labelEn);
const addButtonEn = document.createElement("button");
addButtonEn.textContent = "English";
addButtonEn.classList.add("my-button", "my-button-en");
addButtonEn.id = "addButtonEn";
addButtonEn.style.display = "none";
hoverBox.appendChild(addButtonEn);
for (let i = 1; i <= 12; i++) {
const loadSaveButton = document.createElement("button");
loadSaveButton.textContent = `存档 ${i}`;
loadSaveButton.classList.add(`my-special-button`, `my-special-button-loadSave${i}`);
loadSaveButton.id = `loadSaveButton${i}`;
loadSaveButton.style.display = "none";
hoverBox.appendChild(loadSaveButton);
}
for (let i = 1; i <= 12; i++) {
const SaveButton = document.createElement("button");
SaveButton.textContent = `存档 ${i}`;
SaveButton.classList.add("my-special-button", `my-special-button-Save${i}`);
SaveButton.id = `SaveButton${i}`;
SaveButton.style.display = "none";
hoverBox.appendChild(SaveButton);
}
const skinhide = ["saveButton","fourtextareamodeButton",'label1', 'label2', 'label3', 'textArea1', 'textArea2', 'textArea3', 'addButton', 'helpButton', 'loadButton', 'sendButton','labelSellect',"labelEn","addButtonEn"];
const helphide = ["saveButton","fourtextareamodeButton",'label1', 'label2', 'label3', 'textArea1', 'textArea2', 'textArea3', 'addButton', 'skinButton', 'loadButton', 'sendButton','labelHelp',"space-div"];
const loadhide = ["helpButton","fourtextareamodeButton",'label1', 'label2', 'label3', 'textArea1', 'textArea2', 'textArea3', 'addButton', 'skinButton', 'loadButton', 'sendButton','labelSellect'];
for (let i = 1; i <= 12; i++) {
const saveButtonhub = document.createElement('button');
saveButtonhub.textContent = `Save ${i}`;
saveButtonhub.classList.add('my-special-button', `my-special-button-Save${i}`);
saveButtonhub.id = `SaveButton${i}`;
saveButtonhub.style.display = 'none';
hoverBox.appendChild(saveButtonhub);
loadhide.push(`SaveButton${i}`);
}
const savehide = ["helpButton","fourtextareamodeButton",'label1', 'label2', 'label3', 'textArea1', 'textArea2', 'textArea3','addButton', 'skinButton', 'saveButton', 'sendButton', 'labelSellect'];
for (let i = 1; i <= 12; i++) {
const loadSaveButtonhub = document.createElement('button');
loadSaveButtonhub.textContent = `Save ${i}`;
loadSaveButtonhub.classList.add('my-special-button', `my-special-button-loadSave${i}`);
loadSaveButtonhub.id = `loadSaveButton${i}`;
loadSaveButtonhub.style.display = 'none';
hoverBox.appendChild(loadSaveButtonhub);
savehide.push(`loadSaveButton${i}`);
}
button.addEventListener("click", () => {toggleVisibility('hoverBox');var elementIds = ["button"];var newValues =["OFF"];changeTextContent(elementIds, newValues);});
loadButton.addEventListener("click", () => {toggleVisibility(...savehide);});
saveButton.addEventListener("click", () => {toggleVisibility(...loadhide);});
skinButton.addEventListener("click", () => {toggleVisibility(...skinhide);});
helpButton.addEventListener("click", () => {toggleVisibility(...helphide);});
addButtonEn.addEventListener("click", () => {
var elementIds = ["label1","label2","label3","label4","loadButton","saveButton","sendButton","addButton","labelSellect","labelHelp","labelEn","addButtonEn"];
for (let i = 1; i <= 12; i++) {
elementIds.push(`loadSaveButton${i}`);
elementIds.push(`SaveButton${i}`);
}
var newValues =["Settings area","Review area","Interaction area","Settings area [Sub]","Load", "Save", "Send", "Add","Sellect:","Save Button (Save)\n- Enter save mode and choose a slot to save\nLoad Button (Load)\n- Enter load mode and choose a slot to load\nLoad Mode\n- Preset Button 1 (Pre1) - Load preset text 1\n- Preset Button 2 (Pre2) - Load preset text 2\nSend Button (Send)\n- Send the text\nAdd Button (Add)\n- Add the latest reply to the review area\nTop left button (Dice)\n- Switch between single/dual writing mode\nTop middle button (Palette)\n- Enter the skin selection screen and choose a skin\nTop right button (Help)\n- Display help text\nSettings area rules:\nUse {R} to represent the content in the review area\nUse {D} to represent the content in the interaction area","语言:","中文"];
for (let i = 1; i <= 12; i++) {
newValues.push(`Save${i}`);
newValues.push(`Save${i}`);
}
changeTextContent(elementIds, newValues);
toggleVisibility(...skinhide);});
fourtextareamodeButton.addEventListener("click", () => {
const fourtextareamodeSwitch = ["fourtextareamodeButton","textArea1","textArea2","textArea3","textArea4"];
const element = document.getElementById("fourtextareamodeButton");
if (element) {
const currentClass = element.getAttribute("class");
const hasTargetClass = currentClass.split(" ").includes("fourtextareamode");
// 根据当前状态调用 switchSkin 函数
loadhide.push("label4", "textArea4");
savehide.push("label4", "textArea4");
skinhide.push("label4", "textArea4");
helphide.push("label4", "textArea4");
switchSkin(fourtextareamodeSwitch, "fourtextareamode", hasTargetClass);
} else {
loadhide.splice(loadhide.indexOf("label4"), 1);
loadhide.splice(loadhide.indexOf("textArea4"), 1);
savehide.splice(savehide.indexOf("label4"), 1);
savehide.splice(savehide.indexOf("textArea4"), 1);
skinhide.splice(skinhide.indexOf("label4"), 1);
skinhide.splice(skinhide.indexOf("textArea4"), 1);
helphide.splice(skinhide.indexOf("label4"), 1);
helphide.splice(skinhide.indexOf("textArea4"), 1);
// 同理,如果还有其他数组需要处理,也可以在这里进行修改。
}
toggleVisibility('label4','textArea4');
});
addButton.addEventListener('click', function() {
const latestAssistantMessage = getLatestAssistantMessage('div[class*="w-[calc(100%"]');
if (latestAssistantMessage) {
const isSlackApp = window.location.hostname === 'app.slack.com';
if (isSlackApp) {
textArea2.value = latestAssistantMessage.substring(0, latestAssistantMessage.length - 5);
} else {
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
textArea2.value = latestAssistantMessage.substring(0, latestAssistantMessage.length - 5);
} else {
textArea2.value = latestAssistantMessage;
}
}
}
});
const MAX_CHUNK_COUNT = 100;
// 存储存档数据的数组
const SaveData = [
{ text1: '', text2: '', text3: '' },
{ text1: '', text2: '', text3: '' },
{ text1: '', text2: '', text3: '' },
{ text1: '', text2: '', text3: '' },
{ text1: '', text2: '', text3: '' },
{ text1: '', text2: '', text3: '' },
{ text1: '', text2: '', text3: '' },
{ text1: '', text2: '', text3: '' },
{ text1: '', text2: '', text3: '' },
{ text1: '', text2: '', text3: '' },
{ text1: '', text2: '', text3: '' },
{ text1: '', text2: '', text3: '' }
];
// 存储历史记录的键名
const HISTORY_KEY = 'SaveHistory';
// 获取存档历史记录
const getSaveHistory = () => {
const historyStr = localStorage.getItem(HISTORY_KEY) || '[]';
return JSON.parse(historyStr);
};
// 添加存档历史记录
const addSaveHistory = SaveData => {
const history = getSaveHistory();
history.push(SaveData);
if (history.length > MAX_CHUNK_COUNT) {
history.shift();
}
localStorage.setItem(HISTORY_KEY, JSON.stringify(history));
};
// 获取最近的存档数据
const getLastSaveData = () => {
const history = getSaveHistory();
if (history.length > 0) {
return history[history.length - 1];
} else {
return SaveData;
}
};
// 存储悬浮窗的文本到指定存档中
const saveSaveData = (index) => {
const SaveData = JSON.parse(localStorage.getItem('SaveData')) || [];
SaveData[index] = {
text1: textArea1.value,
text2: textArea2.value,
text3: textArea3.value
};
localStorage.setItem('SaveData', JSON.stringify(SaveData));
addSaveHistory(SaveData);
textArea1.value = '';
textArea2.value = '';
textArea3.value = '';
};
// 加载指定存档中的文本到悬浮窗中
const loadSaveData = (index) => {
const SaveData = JSON.parse(localStorage.getItem('SaveData')) || [];
if (SaveData[index]) {
textArea1.value = SaveData[index].text1;
textArea2.value = SaveData[index].text2;
textArea3.value = SaveData[index].text3;
addSaveHistory(SaveData); // 添加历史记录
textArea4.value = textArea1.value;
}
};
// 存储按钮点击事件
for (let i = 0; i < 12; i++) {
const saveButton = document.getElementById(`SaveButton${i + 1}`);
saveButton.addEventListener('click', () => {
toggleVisibility(...loadhide);
saveSaveData(i);
textArea4.value = textArea1.value;
});
}
// 加载按钮点击事件
for (let i = 0; i < 12; i++) {
const loadButton = document.getElementById(`loadSaveButton${i + 1}`);
loadButton.addEventListener('click', () => {
toggleVisibility(...savehide);
loadSaveData(i);
textArea4.value = textArea1.value;
});
}
textArea4.value = textArea1.value;
textArea1.addEventListener('input', () => {
textArea4.value = textArea1.value;
});
textArea4.addEventListener('input', () => {
textArea1.value = textArea4.value;
});
function triggerKeyboardEvent(el, keyCode) {
const event = new KeyboardEvent('keydown', { key: 'a', code: 'KeyA', keyCode: keyCode, which: keyCode });
el.dispatchEvent(event);
}
sendButton.addEventListener('click', function() {
const inputText1 = textArea1.value.trim();
const inputText2 = textArea2.value.trim();
const inputText3 = textArea3.value.trim();
let intermediateText = '';
let mergedTextOutput = '';
if (inputText1 !== '') {
intermediateText += inputText1;
}
mergedTextOutput = intermediateText.replace(/{\IN回顾区\}|{review}|{\回顾区\}|{\回顾\}|{\回\}|{R}|{r}|{H}|{h}/g, inputText2).replace(/{\IN交互区\}|{dialog}|{\交互区\}|{\交互\}|{\交\}|{D}|{d}|{J}|{j}/g, inputText3);
mergedTextOutput = mergedTextOutput.replace(/\r\n/g, '\n');
mergedTextOutput = mergedTextOutput.replace(/\n{3,}/g, '\n\n');
console.log(mergedTextOutput);
let targetTextArea;
if (window.location.href.startsWith("https://app.slack.com/")) {
targetTextArea = document.querySelector('.c-texty_input_unstyled__container [role="textbox"]');
} else {
targetTextArea = document.querySelector('[role="textbox"]');
}
if (targetTextArea) {
targetTextArea.innerHTML = mergedTextOutput;
let sendButton;
if (window.location.href.startsWith("https://app.slack.com/")) {
sendButton = document.querySelector('[data-qa="texty_send_button"]');
} else {
sendButton = document.querySelector('[class*="absolute"][class*="rounded-md"][class*="bottom-"][class*="right-"][class*="disabled"]');
}
if (sendButton) {
sendButton.disabled = false;
setTimeout(function() {
sendButton.click();
}, 100); // Adjust the delay (in ms) as needed
}
}
});
})();