c.ai X Text Color

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

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