Greasy Fork 还支持 简体中文。

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