c.ai X Text Color

Lets you change the text colors as you wish and highlight chosen words

目前為 2024-08-31 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name c.ai X Text Color
  3. // @namespace c.ai X Text Color
  4. // @match https://character.ai/*
  5. // @grant none
  6. // @license MIT
  7. // @version 3.5
  8. // @author Vishanka via chatGPT
  9. // @description Lets you change the text colors as you wish and highlight chosen words
  10. // @icon https://i.imgur.com/ynjBqKW.png
  11. // ==/UserScript==
  12.  
  13.  
  14.  
  15. (function () {
  16.  
  17. const currentTheme = document.documentElement.classList.contains('dark') ? 'dark' : 'light';
  18. var plaintextColor = localStorage.getItem('plaintext_color');
  19. var italicColor = localStorage.getItem('italic_color');
  20. var charbubbleColor = localStorage.getItem('charbubble_color') || '#26272B';
  21. var userbubbleColor = localStorage.getItem('userbubble_color') || '#303136';
  22. var defaultColor = '#A2A2AC'; // Default color if 'plaintext_color' is not set
  23. var GuideColor = localStorage.getItem('guide_color') || '#131316';
  24. var BodyColor = localStorage.getItem('body_color') || '#18181B';
  25. var InputColor = localStorage.getItem('input_color') || '#202024';
  26. var AccentColor = localStorage.getItem('accent_color') || '#26272b';
  27. const charbubbleMarginTop = localStorage.getItem('charbubbleMarginTop_color') || '0px';
  28. const charbubbleMarginLeft = localStorage.getItem('charbubbleMarginLeft_color') || '0px';
  29.  
  30. // Use the retrieved color or default color
  31. var color = plaintextColor || defaultColor;
  32.  
  33. // Retrieve the selected font and font size from local storage, or use defaults
  34. var selectedFont = localStorage.getItem('selected_font') || '__Inter_918210';
  35. var fontSize = localStorage.getItem('font_size') || '16px';
  36. var fontWeight = localStorage.getItem('fontWeight_color') || '300';
  37. var titlesWeight = localStorage.getItem('boldTitles') || 'normal';
  38. var imageSize = localStorage.getItem('ImageSize') || '24px';
  39. var removeTitle = localStorage.getItem('removeTitles') || 'block';
  40. var removeUserImage = localStorage.getItem('removeUserImage') || 'block';
  41. var cpfpPaddingRight = localStorage.getItem('cpfpPaddingRight') || '0px';
  42. var cpfpPaddingTop = localStorage.getItem('cpfpPaddingTop') || '0px';
  43. var upfpPaddingLeft = localStorage.getItem('upfpPaddingLeft') || '0px';
  44.  
  45. // Create the CSS style using the selected font, stored colors, and font size
  46. var css = `
  47. p[node='[object Object]'] {
  48. color: ${color} !important;
  49. font-family: '${selectedFont}', 'Noto Sans', sans-serif !important;
  50. font-size: ${fontSize} !important;
  51. font-weight: ${fontWeight} !important;
  52. }
  53. p, textarea, button, div.text-sm {
  54. font-family: '${selectedFont}', 'Noto Sans', sans-serif !important;
  55. }
  56. em {
  57. color: ${italicColor} !important;
  58. }
  59. `;
  60.  
  61. css += `
  62. .mt-1.bg-surface-elevation-2 {
  63. background-color: ${charbubbleColor};
  64. margin-top: ${charbubbleMarginTop};
  65. margin-left: ${charbubbleMarginLeft};
  66. }
  67. .mt-1.bg-surface-elevation-3 {
  68. background-color: ${userbubbleColor};
  69. }
  70. `;
  71.  
  72. // Apply styles to specific elements for the bold titles
  73. css += `
  74. .mx-2.flex.flex-row.items-center.gap-2.font-light .text-small:not(.text-muted-foreground) {
  75. font-weight: ${titlesWeight} !important;
  76. }
  77. `;
  78.  
  79.  
  80. // Apply image size to specified elements, excluding the exception class
  81. // Add styles for elements with specific classes and exclude images under .h-dvh > div:nth-child(1)
  82. css += `
  83. .mt-0.hidden.md\\:flex.flex-col.gap-3.items-center:not(
  84. .h-dvh > div:nth-child(1) *):not(
  85. .text-center *):not(
  86. .w-80 *):not(
  87. .m-0.flex.items-start.gap-2.justify-start.mr-0.md\\:mr-6.flex-row-reverse *):not(
  88. .flex.flex-col.items-center.justify-center.p-6.pt-0.mt-32.max-w-lg.mx-auto *):not(
  89. .flex.flex-col.items-center.h-full.overflow-y-hidden *):not(
  90. .flex.flex-col.justify-between.px-4.sm\\:px-8.pt-6 *):not(
  91. .flex.flex-col.flex-auto.gap-4.w-full.max-w-2xl *):not(
  92. .w-full.h-full.overflow-y-auto *):not(
  93. .flex.flex-col.justify-between.p-4 *):not(
  94. .flex.flex-col.flex-auto.gap-4.w-full.max-w-2xl *) {
  95. width: ${imageSize} !important;
  96. height: ${imageSize} !important;
  97. border-radius: 50px;
  98. }
  99. `;
  100.  
  101. // Add styles for elements with specific classes and exclude images under .h-dvh.fixed.z-50
  102. css += `
  103. .relative.flex.h-auto.w-full.overflow-hidden.rounded-full.shrink-0.grow-0:not(
  104. .h-dvh.fixed.z-50 *):not(
  105. .text-center *):not(
  106. .w-80 *):not(
  107. .flex.flex-col.items-center.justify-center.p-6.pt-0.mt-32.max-w-lg.mx-auto *):not(
  108. .flex.flex-col.items-center.h-full.overflow-y-hidden *):not(
  109. .flex.flex-col.justify-between.px-4.sm\\:px-8.pt-6 *):not(
  110. .flex.flex-col.flex-auto.gap-4.w-full.max-w-2xl *):not(
  111. .w-full.h-full.overflow-y-auto *):not(
  112. .flex.flex-col.justify-between.p-4 *):not(
  113. .flex.flex-col.flex-auto.gap-4.w-full.max-w-2xl *) {
  114. width: ${imageSize} !important;
  115. height: ${imageSize} !important;
  116. border-radius: 50px;
  117. }
  118. `;
  119.  
  120.  
  121.  
  122. // Add styles for elements with specific classes and exclude images under .w-full.h-full.flex
  123. css += `
  124. .object-cover.object-center.bg-card.shrink-0.grow-0.h-full:not(
  125. .h-dvh.fixed.z-50 *):not(
  126. .text-center *):not(
  127. .w-80 *):not(
  128. .flex.flex-col.items-center.justify-center.p-6.pt-0.mt-32.max-w-lg.mx-auto *):not(
  129. .flex.flex-col.items-center.h-full.overflow-y-hidden *):not(
  130. .flex.flex-col.justify-between.px-4.sm\\:px-8.pt-6 *):not(
  131. .flex.flex-col.items-center.justify-center.p-6.pt-0.mt-32.max-w-lg.mx-auto *):not(
  132. .flex.flex-col.items-center.h-full.overflow-y-hidden *):not(
  133. .flex.flex-col.justify-between.px-4.sm\\:px-8.pt-6 *):not(
  134. .w-full.h-full.overflow-y-auto *):not(
  135. .flex.flex-col.justify-between.p-4 *):not(
  136. .flex.flex-col.flex-auto.gap-4.w-full.max-w-2xl *) {
  137. width: ${imageSize} !important;
  138. height: ${imageSize} !important;
  139. border-radius: 50px;
  140.  
  141. }
  142. `;
  143.  
  144.  
  145. //Char pfp
  146. css += `
  147. .mt-0.hidden.md\\:flex.flex-col.gap-3.items-center:not(.h-dvh > div:nth-child(1) *):not(.text-center *):not(.w-80 *):not(.m-0.flex.items-start.gap-2.justify-start.mr-0.md\\:mr-6.flex-row-reverse *) {
  148. padding-right: ${cpfpPaddingRight};
  149. padding-top: ${cpfpPaddingTop};
  150. }
  151. `;
  152.  
  153. //user pfp
  154. css += `
  155. .mt-0.hidden.md\\:flex.flex-col.gap-3.items-center:not(
  156. .h-dvh > div:nth-child(1) *):not(
  157. .text-center *):not(
  158. .w-80 *):not(
  159. .m-0.flex.flex-row.items-start.gap-2.justify-start.ml-0.md\\:ml-6 *):not(
  160. .flex.flex-col.justify-end.pb-2.px-5 *) {
  161. padding-left: ${upfpPaddingLeft};
  162.  
  163. }
  164. `;
  165.  
  166.  
  167. //remove user pfp
  168. css += `
  169. .object-cover.object-top:not(
  170. .flex.flex-col.justify-end.pb-2.px-5 *):not(
  171. .flex.flex-col.items-center.justify-center.p-6.pt-0.mt-32.max-w-lg.mx-auto *):not(
  172. .flex.flex-col.items-center.h-full.overflow-y-hidden *):not(
  173. .flex.flex-col.items-center.justify-center.p-6.pt-0.mt-32.max-w-lg.mx-auto *):not(
  174. .flex.flex-col.items-center.h-full.overflow-y-hidden *):not(
  175. .flex.flex-col.flex-auto.gap-4.w-full.max-w-2xl *) {
  176. display: ${removeUserImage};
  177.  
  178. }
  179. `;
  180.  
  181. css += `.mx-2.flex.flex-row.items-center.gap-2.font-light > .text-small {
  182. display: ${removeTitle} !important;
  183. }
  184. `;
  185.  
  186.  
  187.  
  188. css += `
  189. .flex.items-center > .rounded-2xl.text-sm.bg-secondary.px-2.font-light.h-fit,
  190. .rounded-2xl.text-sm.bg-secondary.px-2.font-light.h-fit {
  191. display: ${removeTitle} !important;
  192.  
  193. }
  194. `;
  195.  
  196.  
  197. // Select the element you want to duplicate
  198.  
  199.  
  200.  
  201. /*css += `
  202. .text-small { display: ${removeTitle} !important; }`;
  203.  
  204. */
  205.  
  206. var head = document.getElementsByTagName("head")[0];
  207. var style = document.createElement("style");
  208. style.setAttribute("type", "text/css");
  209. style.innerHTML = css;
  210. head.appendChild(style);
  211.  
  212.  
  213. // Function to update CSS variables
  214. function updateCSSVariable(variableName, value) {
  215. document.documentElement.style.setProperty(variableName, value);
  216. }
  217.  
  218. if (currentTheme === 'dark') {
  219. // Update the specific CSS variables
  220. updateCSSVariable('--G800', AccentColor);
  221. updateCSSVariable('--G850', InputColor);
  222. updateCSSVariable('--G900', BodyColor);
  223. updateCSSVariable('--G950', GuideColor);
  224.  
  225.  
  226. updateCSSVariable('--G50', '#fafafa');
  227. updateCSSVariable('--G100', '#f4f4f5');
  228. updateCSSVariable('--G150', '#ececee');
  229. }
  230. else {
  231. // Update CSS variables for light theme (or any other theme)
  232. updateCSSVariable('--G850', '#202024');
  233. updateCSSVariable('--G900', '#18181B');
  234. updateCSSVariable('--G950', '#131316');
  235. updateCSSVariable('--G50', InputColor);
  236. updateCSSVariable('--G100', BodyColor);
  237. updateCSSVariable('--G150', GuideColor);
  238. }
  239. })();
  240.  
  241.  
  242.  
  243.  
  244. function changeColors() {
  245. const pTags = document.getElementsByTagName("p");
  246. const quotationMarksColor = localStorage.getItem('quotationmarks_color') || '#FFFFFF';
  247. const customColor = localStorage.getItem('custom_color') || '#FFFFFF';
  248. const wordlistCc = JSON.parse(localStorage.getItem('wordlist_cc')) || [];
  249.  
  250. const wordRegex = wordlistCc.length > 0 ? new RegExp('\\b(' + wordlistCc.map(word => word.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|') + ')\\b', 'gi') : null;
  251.  
  252. Array.from(pTags).forEach((pTag) => {
  253. if (
  254. pTag.dataset.colorChanged === "true" ||
  255. pTag.querySelector("code") ||
  256. pTag.querySelector("img") ||
  257. pTag.querySelector("textarea") ||
  258. pTag.querySelector("button") ||
  259. pTag.querySelector("div")
  260. ) {
  261. return; // Skip iteration
  262. }
  263.  
  264. let text = pTag.innerHTML;
  265.  
  266. // Save .katex elements' original HTML and replace with placeholders
  267. const katexElems = Array.from(pTag.querySelectorAll(".katex"));
  268. const katexReplacements = katexElems.map((elem, index) => {
  269. const placeholder = `KATEX_PLACEHOLDER_${index}`;
  270. text = text.replace(elem.outerHTML, placeholder);
  271. return { html: elem.outerHTML, placeholder };
  272. });
  273.  
  274. // Handle <a> tags by removing them temporarily and saving their HTML for later restoration
  275. const aTags = Array.from(pTag.getElementsByTagName("a"));
  276. const aTagsReplacements = aTags.map((aTag, j) => {
  277. const placeholder = `REPLACE_ME_${j}`;
  278. text = text.replace(aTag.outerHTML, placeholder);
  279. return { tag: aTag, placeholder };
  280. });
  281.  
  282. // Change text within quotation marks and for specific words based on the regex
  283. text = text.replace(/(["“”«»].*?["“”«»])/g, `<span style="color: ${quotationMarksColor}">$1</span>`);
  284. // text = text.replace(/(["“”«»][^"]*?,["“”«»])/g, `<span style="color: #E0DF7F">$1</span>`);
  285.  
  286. if (wordRegex) {
  287. text = text.replace(wordRegex, `<span style="color: ${customColor}">$1</span>`);
  288. }
  289.  
  290. // Restore .katex elements and <a> tags
  291. [...katexReplacements, ...aTagsReplacements].forEach(({ html, placeholder, tag }) => {
  292. text = text.replace(placeholder, html || tag.outerHTML);
  293. });
  294.  
  295. // Update the innerHTML and mark the <p> tag to avoid re-processing
  296. pTag.innerHTML = text;
  297. pTag.dataset.colorChanged = "true";
  298. });
  299.  
  300. console.log("Changed colors");
  301. }
  302.  
  303. const divElements = document.querySelectorAll('div');
  304.  
  305. divElements.forEach(div => {
  306. const observer = new MutationObserver(changeColors);
  307. observer.observe(div, { subtree: true, childList: true });
  308. });
  309.  
  310.  
  311.  
  312. function createButton(symbol, onClick) {
  313. const colorpalettebutton = document.createElement('button');
  314. colorpalettebutton.innerHTML = symbol;
  315. colorpalettebutton.style.position = 'relative';
  316. colorpalettebutton.style.background = 'none';
  317. colorpalettebutton.style.border = 'none';
  318. colorpalettebutton.style.fontSize = '18px';
  319. colorpalettebutton.style.top = '-5px';
  320. colorpalettebutton.style.cursor = 'pointer';
  321. colorpalettebutton.addEventListener('click', onClick);
  322. return colorpalettebutton;
  323. }
  324.  
  325. // Function to create the color selector panel
  326. function createColorPanel() {
  327. const panel = document.createElement('div');
  328. panel.id = 'colorPanel';
  329. panel.style.position = 'fixed';
  330. panel.style.top = '50%';
  331. panel.style.left = '50%';
  332. panel.style.transform = 'translate(-50%, -50%)';
  333. const currentTheme = document.documentElement.classList.contains('dark') ? 'dark' : 'light';
  334. if (currentTheme === 'dark') {
  335. panel.style.backgroundColor = 'rgba(19, 19, 22, 0.95)';
  336. } else {
  337. panel.style.backgroundColor = 'rgba(214, 214, 221, 0.95)';
  338. }
  339. panel.style.border = 'none';
  340. panel.style.borderRadius = '5px';
  341. panel.style.padding = '20px';
  342. // panel.style.border = '2px solid #000';
  343. panel.style.zIndex = '9999';
  344.  
  345.  
  346.  
  347. const categories = ['italic', 'quotationmarks', 'plaintext', 'custom', 'charbubble', 'userbubble', 'guide', 'body', 'input', 'accent'];
  348.  
  349. const colorPickers = {};
  350. const transparentCheckboxes = {}; // Store checkboxes separately
  351.  
  352. // Set a fixed width for the labels
  353. const labelWidth = '150px';
  354.  
  355. categories.forEach(category => {
  356. const colorPicker = document.createElement('input');
  357. colorPicker.type = 'color';
  358.  
  359. // Retrieve stored color from local storage
  360. const storedColor = localStorage.getItem(`${category}_color`);
  361. if (storedColor && storedColor !== 'transparent') {
  362. colorPicker.value = storedColor;
  363. } else {
  364. colorPicker.value = '#000000'; // Default color if not set
  365. }
  366.  
  367. colorPickers[category] = colorPicker;
  368.  
  369. // Create a div to hold color picker
  370. const colorDiv = document.createElement('div');
  371. colorDiv.style.position = 'relative';
  372. colorDiv.style.width = '20px';
  373. colorDiv.style.height = '20px';
  374. colorDiv.style.marginLeft = '10px';
  375. colorDiv.style.top = '0px';
  376. colorDiv.style.backgroundColor = storedColor === 'transparent' ? 'transparent' : colorPicker.value;
  377. colorDiv.style.display = 'inline-block';
  378. colorDiv.style.marginRight = '10px';
  379. colorDiv.style.cursor = 'pointer';
  380. colorDiv.style.border = '1px solid black';
  381.  
  382. // Event listener to open color picker when the color square is clicked
  383. colorDiv.addEventListener('click', function () {
  384. if (!transparentCheckbox.checked) {
  385. colorPicker.click();
  386. }
  387. });
  388.  
  389. // Event listener to update the color div when the color changes
  390. colorPicker.addEventListener('input', function () {
  391. if (!transparentCheckbox.checked) {
  392. colorDiv.style.backgroundColor = colorPicker.value;
  393. localStorage.setItem(`${category}_color`, colorPicker.value);
  394. }
  395. });
  396.  
  397. // Checkbox for transparency
  398. const transparentCheckbox = document.createElement('input');
  399. transparentCheckbox.type = 'checkbox';
  400. transparentCheckbox.style.marginLeft = '10px';
  401. transparentCheckbox.checked = storedColor === 'transparent';
  402. transparentCheckbox.title = 'Toggle transparency'; // Add tooltip text
  403. transparentCheckbox.style.marginRight = '5px'; // Add spacing between the checkbox and the reset button
  404.  
  405.  
  406. // Store the checkbox reference for later use
  407. transparentCheckboxes[category] = transparentCheckbox;
  408.  
  409. transparentCheckbox.addEventListener('change', function () {
  410. if (transparentCheckbox.checked) {
  411. // Set color to transparent and lock the color picker behavior
  412. colorDiv.style.backgroundColor = 'transparent';
  413. localStorage.setItem(`${category}_color`, 'transparent');
  414. } else {
  415. // Revert to the current value of the color picker
  416. colorDiv.style.backgroundColor = colorPicker.value;
  417. localStorage.setItem(`${category}_color`, colorPicker.value);
  418. }
  419. });
  420.  
  421. const label = document.createElement('label');
  422. label.style.width = labelWidth; // Set fixed width for the label
  423. label.style.margin = '0'; // Reduce label margin
  424. label.style.padding = '0'; // Reduce label padding
  425. label.appendChild(document.createTextNode(`${category}: `));
  426.  
  427. // Reset button for each color picker
  428. const resetButton = createButton('↺', function () {
  429. const defaultColor = getDefaultColor(category);
  430. colorPicker.value = defaultColor;
  431. colorDiv.style.backgroundColor = defaultColor;
  432. transparentCheckbox.checked = false;
  433. localStorage.setItem(`${category}_color`, defaultColor);
  434. });
  435. resetButton.style.position = 'relative';
  436. resetButton.style.top = '-2px';
  437. resetButton.style.margin = '0'; // Reduce button margin
  438. resetButton.style.padding = '0'; // Reduce button padding
  439.  
  440. // Create a div to hold label, color picker, and reset button
  441. const containerDiv = document.createElement('div');
  442. containerDiv.style.margin = '2px 0'; // Reduce vertical margin between rows
  443. containerDiv.style.padding = '0'; // Reduce padding within each row
  444. containerDiv.style.display = 'flex'; // Flex display for better control over spacing
  445. containerDiv.style.alignItems = 'center'; // Center align items vertically
  446.  
  447. containerDiv.appendChild(label);
  448. containerDiv.appendChild(colorDiv);
  449. containerDiv.appendChild(transparentCheckbox);
  450. containerDiv.appendChild(resetButton);
  451.  
  452. panel.appendChild(containerDiv);
  453. });
  454.  
  455. function createButton(text, onClick) {
  456. const button = document.createElement('button');
  457. button.textContent = text;
  458. button.addEventListener('click', onClick);
  459. return button;
  460. }
  461.  
  462.  
  463.  
  464.  
  465. // Create a new button for custom font selection
  466. /*const fontSelectorButton = document.createElement('button');
  467. fontSelectorButton.style.marginBottom = '20px';
  468. fontSelectorButton.style.borderRadius = '3px';
  469. fontSelectorButton.style.width = '120px';
  470. fontSelectorButton.style.marginLeft = '0px';
  471. fontSelectorButton.style.height = '30px';
  472. fontSelectorButton.style.border = 'none';
  473. fontSelectorButton.style.textAlign = 'left';
  474. fontSelectorButton.style.paddingLeft = '-10px';
  475. fontSelectorButton.innerText = 'Select Font';
  476. */
  477.  
  478. const fontSelectorButton = document.createElement('label');
  479. fontSelectorButton.innerText = 'Font: ';
  480. fontSelectorButton.style.marginRight = '5px';
  481. // Create a dropdown for font selection
  482. const fontDropdown = document.createElement('select');
  483. fontDropdown.style.marginLeft = '5px';
  484. fontDropdown.style.marginBottom = '20px';
  485. fontDropdown.style.borderRadius = '3px';
  486. fontDropdown.style.paddingLeft = '-20px';
  487. fontDropdown.style.height = '30px';
  488.  
  489. // List of font options
  490. const fonts = [
  491. { name: 'Onest', value: '__Onest_b2ce1d' },
  492. { name: 'Inter', value: '__Inter_918210' },
  493. { name: 'Noto Sans', value: 'Noto Sans' },
  494. { name: 'Arial', value: 'Arial' },
  495. { name: 'Times New Roman', value: 'Times New Roman' },
  496. { name: 'Verdana', value: 'Verdana' },
  497. { name: 'Roboto', value: 'Roboto' }
  498. ];
  499.  
  500. // Add fonts to the dropdown
  501. fonts.forEach(font => {
  502. const option = document.createElement('option');
  503. option.value = font.value;
  504. option.text = font.name;
  505. fontDropdown.appendChild(option);
  506. });
  507.  
  508. // Load saved font from local storage
  509. const savedFont = localStorage.getItem('selected_font');
  510. if (savedFont) {
  511. fontDropdown.value = savedFont;
  512. }
  513.  
  514. // Create a dropdown for font size selection
  515. const fontSizeDropdown = document.createElement('select');
  516. fontSizeDropdown.style.marginLeft = '5px';
  517. fontSizeDropdown.style.marginBottom = '20px';
  518. fontSizeDropdown.style.borderRadius = '3px';
  519. fontSizeDropdown.style.height = '30px';
  520.  
  521. // List of font size options
  522. const fontSizes = [
  523. { name: '12px', value: '12px' },
  524. { name: '14px', value: '14px' },
  525. { name: '15px', value: '15px' },
  526. { name: '16px', value: '16px' }, // Default font size
  527. { name: '17px', value: '17px' },
  528. { name: '18px', value: '18px' },
  529. { name: '20px', value: '20px' },
  530. { name: '24px', value: '24px' },
  531. { name: '28px', value: '28px' }
  532. ];
  533.  
  534. // Add font sizes to the dropdown
  535. fontSizes.forEach(size => {
  536. const option = document.createElement('option');
  537. option.value = size.value;
  538. option.text = size.name;
  539. fontSizeDropdown.appendChild(option);
  540. });
  541.  
  542. // Load saved font size from local storage
  543. const savedFontSize = localStorage.getItem('font_size') || '16px';
  544. fontSizeDropdown.value = savedFontSize;
  545.  
  546. // Add event listener to save the selected font size to local storage and apply it
  547. fontSizeDropdown.addEventListener('change', function () {
  548. const selectedFontSize = fontSizeDropdown.value;
  549. localStorage.setItem('font_size', selectedFontSize);
  550.  
  551. // Apply the selected font size to the document
  552. document.documentElement.style.setProperty('--font-size', selectedFontSize);
  553.  
  554.  
  555.  
  556.  
  557.  
  558.  
  559. // Update CSS dynamically
  560. const css = `
  561. p[node='[object Object]'] {
  562. font-size: ${selectedFontSize} !important;
  563. }
  564.  
  565. p, textarea, button, div.text-sm {
  566. /* Other styles here, without font-size modification */
  567. }
  568. `;
  569.  
  570. // Apply the new style
  571. const styleSheet = document.createElement('style');
  572. styleSheet.type = 'text/css';
  573. styleSheet.innerText = css;
  574. document.head.appendChild(styleSheet);
  575.  
  576. alert('Font size changed to ' + selectedFontSize);
  577. });
  578.  
  579.  
  580. // =========================== IMAGES
  581.  
  582. // Create a label for the dimension input
  583. const dimensionLabel = document.createElement('label');
  584. dimensionLabel.innerText = 'Image Size: ';
  585. dimensionLabel.style.marginRight = '5px'; // Optional styling to space the label and input
  586.  
  587. // Create an input field for dimension selection
  588. const dimensionInput = document.createElement('input');
  589. dimensionInput.type = 'number';
  590. dimensionInput.style.marginLeft = '5px';
  591. dimensionInput.style.marginBottom = '20px';
  592. dimensionInput.style.borderRadius = '3px';
  593. dimensionInput.style.height = '30px';
  594. dimensionInput.style.width = '60px'; // Optional styling for width
  595. dimensionInput.min = 1; // Optional: Set a minimum value
  596.  
  597. // Load saved dimension from local storage
  598. const savedImageSize = localStorage.getItem('ImageSize') || '24px'; // Default value set to '24px'
  599. dimensionInput.value = savedImageSize.replace('px', ''); // Remove 'px' for display in the input
  600.  
  601. // Add event listener to save the entered dimension to local storage with 'px' suffix
  602. dimensionInput.addEventListener('change', function () {
  603. const selectedSize = dimensionInput.value + 'px';
  604. localStorage.setItem('ImageSize', selectedSize);
  605. // alert('Image size saved as ' + selectedSize);
  606. });
  607.  
  608.  
  609. // Append the new dropdown to your existing setup
  610.  
  611.  
  612.  
  613. // =========================== END IMAGES
  614.  
  615.  
  616.  
  617. // Create a checkbox for font weight selection
  618. const fontWeightCheckbox = document.createElement('input');
  619. fontWeightCheckbox.type = 'checkbox';
  620. fontWeightCheckbox.style.marginLeft = '5px';
  621. fontWeightCheckbox.style.marginBottom = '20px';
  622. fontWeightCheckbox.style.width = '20px';
  623. fontWeightCheckbox.style.height = '20px';
  624.  
  625. // Label for the font weight checkbox
  626. const fontWeightLabel = document.createElement('label');
  627. fontWeightLabel.textContent = 'Bold Font';
  628. fontWeightLabel.style.marginLeft = '5px';
  629. fontWeightLabel.style.userSelect = 'none';
  630.  
  631. // Create a checkbox for bold titles
  632. const boldTitlesCheckbox = document.createElement('input');
  633. boldTitlesCheckbox.type = 'checkbox';
  634. boldTitlesCheckbox.style.marginLeft = '10px';
  635. boldTitlesCheckbox.style.marginBottom = '20px';
  636. boldTitlesCheckbox.style.width = '20px';
  637. boldTitlesCheckbox.style.height = '20px';
  638.  
  639. // Label for the bold titles checkbox
  640. const boldTitlesLabel = document.createElement('label');
  641. boldTitlesLabel.textContent = 'Bold Titles';
  642. boldTitlesLabel.style.marginLeft = '5px';
  643. boldTitlesLabel.style.userSelect = 'none';
  644.  
  645. // Load saved settings from local storage
  646. const savedFontWeight = localStorage.getItem('fontWeight_color') || '300';
  647. const savedBoldTitles = localStorage.getItem('boldTitles') || 'normal';
  648. fontWeightCheckbox.checked = savedFontWeight === '400';
  649. boldTitlesCheckbox.checked = savedBoldTitles === 'bold';
  650.  
  651. // Function to apply the selected font weight
  652. function applyFontWeight(weight, titlesWeight) {
  653. document.documentElement.style.setProperty('--font-weight', weight);
  654.  
  655. // Update CSS dynamically
  656. let css = `
  657. p[node='[object Object]'], p, textarea, button, div.text-sm {
  658. font-weight: ${weight} !important;
  659. }
  660. `;
  661.  
  662. // Add CSS for bold titles
  663. css += `
  664. .mx-2.flex.flex-row.items-center.gap-2.font-light .text-small:not(.text-muted-foreground) {
  665. font-weight: ${titlesWeight} !important;
  666. }
  667. `;
  668.  
  669. // Remove existing style element if any
  670. let existingStyle = document.getElementById('dynamicFontWeightStyle');
  671. if (existingStyle) existingStyle.remove();
  672.  
  673. // Apply the new style
  674. const styleSheet = document.createElement('style');
  675. styleSheet.type = 'text/css';
  676. styleSheet.id = 'dynamicFontWeightStyle';
  677. styleSheet.innerText = css;
  678. document.head.appendChild(styleSheet);
  679. }
  680.  
  681. // Apply initial settings based on saved preferences
  682. applyFontWeight(savedFontWeight, savedBoldTitles);
  683.  
  684. // Event listener for font weight checkbox
  685. fontWeightCheckbox.addEventListener('change', () => {
  686. const weight = fontWeightCheckbox.checked ? '400' : '300';
  687. localStorage.setItem('fontWeight_color', weight);
  688. applyFontWeight(weight, boldTitlesCheckbox.checked ? 'bold' : 'normal');
  689. });
  690.  
  691. // Event listener for bold titles checkbox
  692. boldTitlesCheckbox.addEventListener('change', () => {
  693. const titlesWeight = boldTitlesCheckbox.checked ? 'bold' : 'normal';
  694. localStorage.setItem('boldTitles', titlesWeight);
  695. applyFontWeight(fontWeightCheckbox.checked ? '400' : '300', titlesWeight);
  696. });
  697.  
  698. // Function to make text-small elements bold under a specific parent, except text-muted-foreground
  699. function makeTextSmallBold(weight) {
  700. const parents = document.querySelectorAll('.mx-2.flex.flex-row.items-center.gap-2.font-light');
  701.  
  702. parents.forEach(parent => {
  703. const textSmallElements = parent.querySelectorAll('.text-small:not(.text-muted-foreground)');
  704. textSmallElements.forEach(element => {
  705. element.style.fontWeight = weight;
  706. });
  707. });
  708. }
  709.  
  710. // Apply saved settings on page load
  711. applyFontWeight(savedFontWeight);
  712. makeTextSmallBold(savedBoldTitles);
  713.  
  714. // Event listener for font weight checkbox
  715. fontWeightCheckbox.addEventListener('change', function () {
  716. const selectedFontWeight = fontWeightCheckbox.checked ? '400' : '300';
  717. localStorage.setItem('fontWeight_color', selectedFontWeight);
  718. applyFontWeight(selectedFontWeight);
  719. });
  720.  
  721. // Event listener for bold titles checkbox
  722. boldTitlesCheckbox.addEventListener('change', function () {
  723. const boldTitleWeight = boldTitlesCheckbox.checked ? 'bold' : 'normal';
  724. localStorage.setItem('boldTitles', boldTitleWeight);
  725. makeTextSmallBold(boldTitleWeight);
  726. });
  727.  
  728.  
  729.  
  730. // ============== END FONT WEIGHT
  731.  
  732.  
  733. // Add event listener to save the selected font to local storage and apply it
  734. fontDropdown.addEventListener('change', function () {
  735. const selectedFont = fontDropdown.value;
  736. localStorage.setItem('selected_font', selectedFont);
  737.  
  738. // Apply the selected font to the document
  739. document.documentElement.style.setProperty('--font-family', selectedFont);
  740.  
  741. // Update CSS dynamically
  742. const css = `
  743. p[node='[object Object]'], p, textarea, button, div.text-sm {
  744. font-family: '${selectedFont}', sans-serif !important;
  745. }
  746. `;
  747.  
  748. // Apply the new style
  749. const styleSheet = document.createElement('style');
  750. styleSheet.type = 'text/css';
  751. styleSheet.innerText = css;
  752. document.head.appendChild(styleSheet);
  753.  
  754. // alert('Font changed to ' + fontDropdown.options[fontDropdown.selectedIndex].text);
  755. });
  756.  
  757. // Append the button and dropdowns to the panel
  758. panel.appendChild(fontSelectorButton);
  759. panel.appendChild(fontDropdown);
  760. panel.appendChild(fontSizeDropdown);
  761. // Append the checkbox and label to the document
  762. panel.appendChild(document.createElement('br'));
  763. // Append the label and dropdown to the document
  764. panel.appendChild(dimensionLabel);
  765.  
  766. panel.appendChild(dimensionInput);
  767. panel.appendChild(document.createElement('br'));
  768. // Append the checkboxes and labels to the document
  769. panel.appendChild(fontWeightCheckbox);
  770. panel.appendChild(fontWeightLabel);
  771. panel.appendChild(boldTitlesCheckbox);
  772. panel.appendChild(boldTitlesLabel);
  773.  
  774.  
  775.  
  776.  
  777.  
  778.  
  779.  
  780. // Custom word list input
  781. const wordListInput = document.createElement('input');
  782. wordListInput.type = 'text';
  783. wordListInput.placeholder = 'Separate words with commas';
  784. wordListInput.style.width = '250px';
  785. wordListInput.style.height = '35px';
  786. wordListInput.style.borderRadius = '3px';
  787. wordListInput.style.marginBottom = '10px';
  788. panel.appendChild(wordListInput);
  789. panel.appendChild(document.createElement('br'));
  790.  
  791. const wordListContainer = document.createElement('div');
  792. wordListContainer.style.display = 'flex';
  793. wordListContainer.style.flexWrap = 'wrap';
  794. wordListContainer.style.maxWidth = '300px'; // Set a fixed maximum width for the container
  795.  
  796. // Display custom word list buttons
  797. const wordListArray = JSON.parse(localStorage.getItem('wordlist_cc')) || [];
  798. const wordListButtons = [];
  799.  
  800. function createWordButton(word) {
  801. const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
  802.  
  803. const removeSymbol = isMobile ? '×' : '🞮';
  804.  
  805. const wordButton = createButton(`${word} ${removeSymbol}`, function() {
  806. // Remove the word from the list and update the panel
  807. const index = wordListArray.indexOf(word);
  808. if (index !== -1) {
  809. wordListArray.splice(index, 1);
  810. updateWordListButtons();
  811. }
  812. });
  813.  
  814. // Word Buttons
  815. wordButton.style.borderRadius = '3px';
  816. wordButton.style.border = 'none';
  817. if (currentTheme === 'dark') {
  818. wordButton.style.backgroundColor = '#26272B';
  819. } else {
  820. wordButton.style.backgroundColor = '#E4E4E7';
  821. }
  822. wordButton.style.marginBottom = '5px';
  823. wordButton.style.marginRight = '5px';
  824. wordButton.style.fontSize = '16px';
  825. wordButton.classList.add('word-button');
  826. return wordButton;
  827. }
  828.  
  829. function updateWordListButtons() {
  830. wordListContainer.innerHTML = ''; // Clear the container
  831. wordListArray.forEach(word => {
  832. const wordButton = createWordButton(word);
  833. wordListContainer.appendChild(wordButton);
  834. });
  835. }
  836.  
  837.  
  838.  
  839.  
  840.  
  841. updateWordListButtons();
  842.  
  843. // Add Words button
  844. const addWordsButton = document.createElement('button');
  845. addWordsButton.textContent = 'Add';
  846. addWordsButton.style.marginTop = '-8px';
  847. addWordsButton.style.marginLeft = '5px';
  848. addWordsButton.style.borderRadius = '3px';
  849. addWordsButton.style.border = 'none';
  850. if (currentTheme === 'dark') {
  851. addWordsButton.style.backgroundColor = '#26272B';
  852. } else {
  853. addWordsButton.style.backgroundColor = '#E4E4E7';
  854. }
  855. addWordsButton.addEventListener('click', function() {
  856. // Get the input value, split into words, and add to wordListArray
  857. const wordListValue = wordListInput.value;
  858. const newWords = wordListValue.split(',').map(word => word.trim().toLowerCase()).filter(word => word !== ''); // Convert to lowercase and remove empty entries
  859. wordListArray.push(...newWords);
  860.  
  861. // Update the word list buttons in the panel
  862. updateWordListButtons();
  863. });
  864.  
  865. // Create a div to group the input and button on the same line
  866. const inputButtonContainer = document.createElement('div');
  867. inputButtonContainer.style.display = 'flex';
  868. inputButtonContainer.style.alignItems = 'center';
  869.  
  870. inputButtonContainer.appendChild(wordListInput);
  871. inputButtonContainer.appendChild(addWordsButton);
  872.  
  873. // Append the container to the panel
  874. panel.appendChild(inputButtonContainer);
  875. panel.appendChild(wordListContainer);
  876. // Create initial word list buttons
  877. updateWordListButtons();
  878.  
  879.  
  880. // OK button
  881. const okButton = document.createElement('button');
  882. okButton.textContent = 'Confirm';
  883. okButton.style.marginTop = '-20px';
  884. okButton.style.width = '75px';
  885. okButton.style.height = '35px';
  886. okButton.style.marginRight = '5px';
  887. okButton.style.borderRadius = '3px';
  888. okButton.style.border = 'none';
  889. if (currentTheme === 'dark') {
  890. okButton.style.backgroundColor = '#26272B';
  891. } else {
  892. okButton.style.backgroundColor = '#D9D9DF';
  893. }
  894.  
  895. okButton.style.position = 'relative';
  896. okButton.style.left = '24%';
  897.  
  898. okButton.addEventListener('click', function () {
  899. // Save selected colors to local storage
  900. categories.forEach(category => {
  901. const colorPicker = colorPickers[category];
  902. const transparentCheckbox = transparentCheckboxes[category]; // Access the checkbox from stored references
  903.  
  904. // Determine the value to save: color picker value or 'transparent'
  905. const newValue = transparentCheckbox.checked ? 'transparent' : colorPicker.value;
  906. const oldValue = localStorage.getItem(`${category}_color`);
  907.  
  908. if (oldValue !== newValue) {
  909. localStorage.setItem(`${category}_color`, newValue);
  910.  
  911. // If 'plaintext' color is changed, auto-reload the page
  912. if (category === 'plaintext' || category === 'guide' || category === 'body' || category === 'input') {
  913. window.location.reload();
  914. }
  915. }
  916. });
  917.  
  918. // Save custom word list to local storage
  919. const wordListValue = wordListInput.value;
  920. const newWords = wordListValue.split(',').map(word => word.trim().toLowerCase()).filter(word => word !== ''); // Convert to lowercase and remove empty entries
  921. const uniqueNewWords = Array.from(new Set(newWords)); // Remove duplicates
  922.  
  923. // Check for existing words and add only new ones
  924. uniqueNewWords.forEach(newWord => {
  925. if (!wordListArray.includes(newWord)) {
  926. wordListArray.push(newWord);
  927. }
  928. });
  929.  
  930. localStorage.setItem('wordlist_cc', JSON.stringify(wordListArray));
  931.  
  932. updateWordListButtons();
  933.  
  934. // Close the panel
  935. panel.remove();
  936. });
  937.  
  938. // Cancel button
  939. const cancelButton = document.createElement('button');
  940. cancelButton.textContent = 'Cancel';
  941. cancelButton.style.marginTop = '-20px';
  942. cancelButton.style.borderRadius = '3px';
  943. cancelButton.style.width = '75px';
  944. cancelButton.style.marginLeft = '5px';
  945. cancelButton.style.height = '35px';
  946. cancelButton.style.border = 'none';
  947. if (currentTheme === 'dark') {
  948. cancelButton.style.backgroundColor = '#5E5E5E';
  949. } else {
  950. cancelButton.style.backgroundColor = '#CBD2D4';
  951. }
  952. cancelButton.style.position = 'relative';
  953. cancelButton.style.left = '25%';
  954. cancelButton.addEventListener('click', function() {
  955. // Close the panel without saving
  956. panel.remove();
  957. });
  958.  
  959. // ==== PRESETS ========
  960. // Create button
  961. const preset1 = document.createElement('button');
  962. preset1.style.marginBottom = '20px';
  963. preset1.style.borderRadius = '3px';
  964. preset1.style.width = '30px';
  965. preset1.style.marginLeft = '5px';
  966. preset1.style.height = '30px';
  967. preset1.style.border = 'none';
  968.  
  969. // Set image as button background
  970. preset1.style.backgroundImage = "url('https://i.imgur.com/91Z4AwP.png')";
  971. preset1.style.backgroundSize = 'contain';
  972. preset1.style.backgroundRepeat = 'no-repeat';
  973. preset1.style.backgroundPosition = 'center';
  974.  
  975.  
  976. localStorage.removeItem('charbubbleMarginTop_color');
  977. localStorage.removeItem('charbubbleMarginLeft_color');
  978. localStorage.setItem('removeTitles', 'block');
  979. localStorage.setItem('removeUserImage', 'block');
  980. localStorage.setItem('cpfpPaddingRight', '0px');
  981. localStorage.setItem('cpfpPaddingTop', '0px');
  982. localStorage.setItem('upfpPaddingLeft', '0px');
  983.  
  984. // Event listener for button click
  985. preset1.addEventListener('click', function () {
  986.  
  987. // Show confirmation dialog
  988. const userConfirmed = confirm('All colors will be replaced with Discord pallet. Proceed?');
  989.  
  990.  
  991.  
  992. if (userConfirmed) {
  993.  
  994. function updateCSSVariable(variableName, value) {
  995. document.documentElement.style.setProperty(variableName, value);
  996. }
  997. updateCSSVariable('--G850', '#383A40'); //input
  998. updateCSSVariable('--G900', '#313338'); //body
  999. updateCSSVariable('--G950', '#232428'); //guide
  1000. // Hardcode the selected colors to local storage
  1001. const hardcodedColors = {
  1002. 'guide': '#232428',
  1003. 'input': '#383A40',
  1004. 'body': '#313338',
  1005. 'charbubble': '#383A40',
  1006. 'userbubble': '#41434A',
  1007. 'accent': '#3E4047'
  1008. };
  1009.  
  1010.  
  1011. localStorage.setItem('ImageSize', '42px');
  1012. localStorage.setItem('cpfpPaddingRight', '30px');
  1013. localStorage.setItem('upfpPaddingLeft', '10px');
  1014.  
  1015. // Save hardcoded values to local storage
  1016. Object.keys(hardcodedColors).forEach(category => {
  1017. const newValue = hardcodedColors[category];
  1018. localStorage.setItem(`${category}_color`, newValue);
  1019. });
  1020. window.location.reload();
  1021. }
  1022. });
  1023.  
  1024. const preset2 = document.createElement('button');
  1025. preset2.style.marginBottom = '20px';
  1026. preset2.style.borderRadius = '3px';
  1027. preset2.style.width = '30px';
  1028. preset2.style.marginLeft = '5px';
  1029. preset2.style.height = '30px';
  1030. preset2.style.border = 'none';
  1031.  
  1032. // Set image as button background
  1033. preset2.style.backgroundImage = "url('https://i.imgur.com/PSkZ4Yq.png')";
  1034. preset2.style.backgroundSize = 'contain';
  1035. preset2.style.backgroundRepeat = 'no-repeat';
  1036. preset2.style.backgroundPosition = 'center';
  1037.  
  1038.  
  1039.  
  1040.  
  1041. // Event listener for button click
  1042. preset2.addEventListener('click', function () {
  1043. // Show confirmation dialog
  1044. const userConfirmed = confirm('All colors will be replaced with ChatGPT pallet. Proceed?');
  1045.  
  1046. if (userConfirmed) {
  1047. function updateCSSVariable(variableName, value) {
  1048. document.documentElement.style.setProperty(variableName, value);
  1049. }
  1050.  
  1051. // Update CSS variables with the new values
  1052. updateCSSVariable('--G850', '#2F2F2F'); // input
  1053. updateCSSVariable('--G900', '#212121'); // body
  1054. updateCSSVariable('--G950', '#171717'); // guide
  1055.  
  1056. // Hardcode the selected colors to local storage
  1057. const hardcodedColors = {
  1058. guide: '#171717',
  1059. input: '#2F2F2F',
  1060. body: '#212121',
  1061. charbubble: 'transparent',
  1062. userbubble: '#2F2F2F',
  1063. accent: '#323232',
  1064. charbubbleMarginTop: '-10px',
  1065. charbubbleMarginLeft: '-5px',
  1066. fontWeight: '400'
  1067. };
  1068.  
  1069. // Save hardcoded values to local storage
  1070. Object.keys(hardcodedColors).forEach(category => {
  1071. const newValue = hardcodedColors[category];
  1072. localStorage.setItem(`${category}_color`, newValue);
  1073. });
  1074.  
  1075. // Set the boldTitles variable in local storage to 'bold'
  1076. // localStorage.setItem('boldTitles', 'bold');
  1077. localStorage.setItem('removeTitles', 'none');
  1078. localStorage.setItem('removeUserImage', 'none');
  1079. localStorage.setItem('cpfpPaddingRight', '30px');
  1080. localStorage.setItem('cpfpPaddingTop', '10px');
  1081. localStorage.setItem('upfpPaddingLeft', '30px');
  1082.  
  1083.  
  1084. // Reload the page to apply changes
  1085. window.location.reload();
  1086. }
  1087. });
  1088.  
  1089. const preset3 = document.createElement('button');
  1090. preset3.style.marginBottom = '20px';
  1091. preset3.style.borderRadius = '3px';
  1092. preset3.style.width = '30px';
  1093. preset3.style.marginLeft = '5px';
  1094. preset3.style.height = '30px';
  1095. preset3.style.border = 'none';
  1096.  
  1097. // Set image as button background
  1098. preset3.style.backgroundImage = "url('https://i.imgur.com/wWpHDIj.png')";
  1099. preset3.style.backgroundSize = 'contain';
  1100. preset3.style.backgroundRepeat = 'no-repeat';
  1101. preset3.style.backgroundPosition = 'center';
  1102.  
  1103. localStorage.removeItem('charbubbleMarginTop_color');
  1104. localStorage.removeItem('charbubbleMarginLeft_color');
  1105. localStorage.setItem('removeTitles', 'block');
  1106. localStorage.setItem('removeUserImage', 'block');
  1107. localStorage.setItem('cpfpPaddingRight', '0px');
  1108. localStorage.setItem('cpfpPaddingTop', '0px');
  1109. localStorage.setItem('upfpPaddingLeft', '0px');
  1110. localStorage.setItem('ImageSize', '45px');
  1111.  
  1112.  
  1113.  
  1114. // Event listener for button click
  1115. preset3.addEventListener('click', function () {
  1116.  
  1117. // Show confirmation dialog
  1118. const userConfirmed = confirm('All colors will be replaced with old.character.ai pallet. Proceed?');
  1119.  
  1120.  
  1121.  
  1122. if (userConfirmed) {
  1123.  
  1124. function updateCSSVariable(variableName, value) {
  1125. document.documentElement.style.setProperty(variableName, value);
  1126. }
  1127. updateCSSVariable('--G850', '#242525'); //input
  1128. updateCSSVariable('--G900', '#242525'); //body
  1129. updateCSSVariable('--G950', '#2B2C2D'); //guide
  1130. // Hardcode the selected colors to local storage
  1131. const hardcodedColors = {
  1132. 'guide': '#2B2C2D',
  1133. 'input': '#242525',
  1134. 'body': '#242525',
  1135. 'charbubble': '#242525',
  1136. 'userbubble': '#2B2C2D',
  1137. 'accent': '#363838'
  1138. };
  1139.  
  1140. // Save hardcoded values to local storage
  1141. Object.keys(hardcodedColors).forEach(category => {
  1142. const newValue = hardcodedColors[category];
  1143. localStorage.setItem(`${category}_color`, newValue);
  1144. });
  1145. window.location.reload();
  1146. }
  1147. });
  1148.  
  1149.  
  1150. // Create 'resetall' button
  1151. const resetAll = document.createElement('button');
  1152. resetAll.style.marginBottom = '20px';
  1153. resetAll.style.borderRadius = '3px';
  1154. resetAll.style.width = '80px'; // Adjust width for text
  1155. resetAll.style.marginLeft = '5px';
  1156. resetAll.style.height = '30px';
  1157. resetAll.style.border = 'none';
  1158. resetAll.textContent = 'Reset All'; // Button text
  1159.  
  1160. // Add event listener to 'resetall' button
  1161. resetAll.addEventListener('click', function () {
  1162. // Reset all colors to their default values
  1163. function resetToDefault() {
  1164. const categories = [
  1165. 'italic', 'quotationmarks', 'plaintext', 'custom',
  1166. 'charbubble', 'userbubble', 'guide', 'input',
  1167. 'body', 'accent'
  1168. ];
  1169.  
  1170. // Set default colors based on the current theme
  1171. categories.forEach(category => {
  1172. const defaultColor = getDefaultColor(category);
  1173. updateCSSVariable(`--${category}`, defaultColor);
  1174. localStorage.setItem(`${category}_color`, defaultColor);
  1175. });
  1176.  
  1177. // Delete additional values from local storage
  1178. localStorage.removeItem('charbubbleMarginTop_color');
  1179. localStorage.removeItem('charbubbleMarginLeft_color');
  1180. localStorage.setItem('removeTitles', 'block');
  1181. localStorage.setItem('removeUserImage', 'block');
  1182. localStorage.setItem('cpfpPaddingRight', '0px');
  1183. localStorage.setItem('cpfpPaddingTop', '0px');
  1184. localStorage.setItem('upfpPaddingLeft', '0px');
  1185. localStorage.setItem('ImageSize', '24px');
  1186.  
  1187.  
  1188. // Reload the page to apply changes
  1189. window.location.reload();
  1190. }
  1191.  
  1192. // Show confirmation dialog
  1193. const resetConfirmed = confirm('This will reset all settings to default. Proceed?');
  1194.  
  1195. if (resetConfirmed) {
  1196. resetToDefault();
  1197. }
  1198. });
  1199.  
  1200. // Append 'resetall' button to the document
  1201.  
  1202.  
  1203. // Function to update CSS variable
  1204. function updateCSSVariable(variableName, value) {
  1205. document.documentElement.style.setProperty(variableName, value);
  1206. }
  1207.  
  1208.  
  1209. panel.appendChild(document.createElement('br'));
  1210.  
  1211.  
  1212. panel.appendChild(preset1);
  1213. panel.appendChild(preset2);
  1214. panel.appendChild(preset3);
  1215. panel.appendChild(resetAll);
  1216. panel.appendChild(document.createElement('br'));
  1217. panel.appendChild(okButton);
  1218. panel.appendChild(cancelButton);
  1219.  
  1220. document.body.appendChild(panel);
  1221. }
  1222.  
  1223.  
  1224.  
  1225.  
  1226.  
  1227.  
  1228. // Function to get the default color for a category
  1229. function getDefaultColor(category) {
  1230. const currentTheme = document.documentElement.classList.contains('dark') ? 'dark' : 'light';
  1231. if (currentTheme === 'dark') {
  1232. const defaultColors = {
  1233. 'italic': '#E0DF7F',
  1234. 'quotationmarks': '#FFFFFF',
  1235. 'plaintext': '#A2A2AC',
  1236. 'custom': '#E0DF7F',
  1237. 'charbubble': '#26272B',
  1238. 'userbubble': '#303136',
  1239. 'guide': '#131316',
  1240. 'input': '#202024',
  1241. 'body': '#18181B',
  1242. 'accent': '#26272B'
  1243. };
  1244. return defaultColors[category];
  1245. }
  1246. else {
  1247. const defaultColors = {
  1248. 'italic': '#4F7AA6',
  1249. 'quotationmarks': '#000000',
  1250. 'plaintext': '#374151',
  1251. 'custom': '#4F7AA6',
  1252. 'charbubble': '#E4E4E7',
  1253. 'userbubble': '#D9D9DF',
  1254. 'guide': '#FAFAFA',
  1255. 'input': '#F4F4F5',
  1256. 'body': '#ECECEE',
  1257. 'accent': '#26272B'
  1258. };
  1259. return defaultColors[category];
  1260. }
  1261. }
  1262.  
  1263.  
  1264.  
  1265. const mainButton = createButton('', function() {
  1266. const colorPanelExists = document.getElementById('colorPanel');
  1267. if (!colorPanelExists) {
  1268. createColorPanel();
  1269. }
  1270. });
  1271.  
  1272. // Set the background image of the button to the provided image
  1273. mainButton.style.backgroundImage = "url('https://i.imgur.com/yBgJ3za.png')";
  1274. mainButton.style.backgroundSize = "cover";
  1275. mainButton.style.position = "fixed"; // Use "fixed" for a position relative to the viewport
  1276. mainButton.style.top = "10px"; // Adjust the top position as needed
  1277. mainButton.style.right = "10px"; // Adjust the right position as needed
  1278. mainButton.style.width = "22px"; // Adjust the width and height as needed
  1279. mainButton.style.height = "22px"; // Adjust the width and height as needed
  1280.  
  1281. // Function to insert the mainButton into the body of the document
  1282. function insertMainButton() {
  1283. document.body.appendChild(mainButton);
  1284. }
  1285.  
  1286. // Call the function to insert the mainButton into the body
  1287. insertMainButton();
  1288.  
  1289. console.info('c.ai Text Color Button appended to the top right corner.');