PixAI UI Helpers

Helpers for PixAI: Toggle between 4x1 and 2x2 layouts for the image grid, toggle the visibility of the right sidebar, and enable "Ctrl+Enter" for generating images. Remembers layout and Ctrl+Enter settings across refreshes.

当前为 2024-08-21 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name PixAI UI Helpers
  3. // @namespace http://yourname.tampermonkey.net/
  4. // @version 1.4.1
  5. // @description Helpers for PixAI: Toggle between 4x1 and 2x2 layouts for the image grid, toggle the visibility of the right sidebar, and enable "Ctrl+Enter" for generating images. Remembers layout and Ctrl+Enter settings across refreshes.
  6. // @author Yada
  7. // @match https://pixai.art/*
  8. // @icon https://pixai.art/favicon.ico
  9. // @grant none
  10. // @license MIT
  11. // ==/UserScript==
  12. (function() {
  13. 'use strict';
  14.  
  15. let is2x2Layout = localStorage.getItem('pixai-layout') === '2x2';
  16. let isCtrlEnterEnabled = localStorage.getItem('pixai-ctrl-enter') === 'enabled';
  17. let isRightBarCollapsed = false;
  18. let buttonsAdded = false;
  19. let layoutInterval;
  20.  
  21. // Function to get the target element for grid layout
  22. function getGridTargetElement() {
  23. return document.querySelector('#workbench-layout main > div > div:nth-child(2) > div > div:nth-child(1)');
  24. }
  25.  
  26. // Function to set the layout to 4x1
  27. function setLayout4x1() {
  28. const imageContainer = getGridTargetElement();
  29. if (imageContainer) {
  30. imageContainer.style.setProperty('--grid-cols', '4');
  31. imageContainer.style.setProperty('--grid-rows', '1');
  32. is2x2Layout = false;
  33. localStorage.setItem('pixai-layout', '4x1');
  34. }
  35. }
  36.  
  37. // Function to set the layout to 2x2
  38. function setLayout2x2() {
  39. const imageContainer = getGridTargetElement();
  40. if (imageContainer) {
  41. imageContainer.style.setProperty('--grid-cols', '2');
  42. imageContainer.style.setProperty('--grid-rows', '2');
  43. is2x2Layout = true;
  44. localStorage.setItem('pixai-layout', '2x2');
  45. }
  46. }
  47.  
  48. // Function to reapply the current layout
  49. function reapplyLayout() {
  50. if (is2x2Layout) {
  51. setLayout2x2();
  52. } else {
  53. setLayout4x1();
  54. }
  55. }
  56.  
  57. // Function to toggle between layouts
  58. function toggleLayout() {
  59. is2x2Layout = !is2x2Layout;
  60. reapplyLayout();
  61. }
  62.  
  63. // Function to set right bar width to zero
  64. function setRightBarWidthToZero() {
  65. const workbenchLayout = document.querySelector('#workbench-layout');
  66. if (workbenchLayout) {
  67. workbenchLayout.style.gridTemplateColumns = 'min-content 1fr 0px';
  68. isRightBarCollapsed = true;
  69. }
  70. }
  71.  
  72. // Function to restore the original width of the right bar
  73. function restoreRightBarWidth() {
  74. const workbenchLayout = document.querySelector('#workbench-layout');
  75. if (workbenchLayout) {
  76. workbenchLayout.style.gridTemplateColumns = 'min-content 1fr 380px';
  77. isRightBarCollapsed = false;
  78. }
  79. }
  80.  
  81. // Function to toggle the right bar's visibility
  82. function toggleRightBar() {
  83. if (isRightBarCollapsed) {
  84. restoreRightBarWidth();
  85. } else {
  86. setRightBarWidthToZero();
  87. }
  88. }
  89.  
  90. // Function to handle Ctrl+Enter key press for generating images
  91. function handleCtrlEnter(event) {
  92. if (event.ctrlKey && event.key === 'Enter') {
  93. const generateButton = document.querySelector('[data-tutorial-target="generate-button"]');
  94. if (generateButton) {
  95. generateButton.click();
  96. }
  97. }
  98. }
  99.  
  100. // Function to enable Ctrl+Enter for generating images
  101. function enableCtrlEnter() {
  102. if (!isCtrlEnterEnabled) {
  103. document.addEventListener('keydown', handleCtrlEnter);
  104. isCtrlEnterEnabled = true;
  105. localStorage.setItem('pixai-ctrl-enter', 'enabled');
  106. }
  107. }
  108.  
  109. // Function to disable Ctrl+Enter for generating images
  110. function disableCtrlEnter() {
  111. if (isCtrlEnterEnabled) {
  112. document.removeEventListener('keydown', handleCtrlEnter);
  113. isCtrlEnterEnabled = false;
  114. localStorage.setItem('pixai-ctrl-enter', 'disabled');
  115. }
  116. }
  117.  
  118. // Function to toggle Ctrl+Enter feature
  119. function toggleCtrlEnter() {
  120. if (isCtrlEnterEnabled) {
  121. disableCtrlEnter();
  122. } else {
  123. enableCtrlEnter();
  124. }
  125. }
  126.  
  127. // Function to add the buttons
  128. function addButtons() {
  129. if (buttonsAdded) return;
  130.  
  131. // Create button container
  132. const buttonContainer = document.createElement('div');
  133. buttonContainer.id = 'pixai-ui-helpers-buttons';
  134. buttonContainer.style.position = 'fixed';
  135. buttonContainer.style.top = '10px';
  136. buttonContainer.style.right = '10px';
  137. buttonContainer.style.zIndex = '1000';
  138. buttonContainer.style.display = 'flex';
  139. buttonContainer.style.flexDirection = 'row';
  140. buttonContainer.style.gap = '5px';
  141.  
  142. // Button styles
  143. const buttonStyle = {
  144. display: 'flex',
  145. justifyContent: 'center',
  146. alignItems: 'center',
  147. backgroundColor: 'transparent',
  148. color: 'white',
  149. fontFamily: 'Inter, sans-serif',
  150. fontSize: '0.75rem',
  151. fontWeight: '500',
  152. textShadow: '0 1px 2px rgba(0, 0, 0, 0.5)',
  153. padding: '0.25rem 0.5rem',
  154. border: 'none',
  155. borderRadius: '0.25rem',
  156. cursor: 'pointer',
  157. transition: 'background-color 0.3s',
  158. };
  159.  
  160. // Create toggle layout button
  161. const toggleLayoutButton = document.createElement('button');
  162. toggleLayoutButton.textContent = 'Toggle Layout';
  163. Object.assign(toggleLayoutButton.style, buttonStyle);
  164. toggleLayoutButton.onclick = toggleLayout;
  165.  
  166. // Create toggle right bar button
  167. const toggleRightBarButton = document.createElement('button');
  168. toggleRightBarButton.textContent = 'Toggle Right Bar';
  169. Object.assign(toggleRightBarButton.style, buttonStyle);
  170. toggleRightBarButton.onclick = toggleRightBar;
  171.  
  172. // Create toggle Ctrl+Enter button
  173. const toggleCtrlEnterButton = document.createElement('button');
  174. toggleCtrlEnterButton.textContent = isCtrlEnterEnabled ? 'Disable Ctrl+Enter' : 'Enable Ctrl+Enter';
  175. Object.assign(toggleCtrlEnterButton.style, buttonStyle);
  176. toggleCtrlEnterButton.onclick = function() {
  177. toggleCtrlEnter();
  178. toggleCtrlEnterButton.textContent = isCtrlEnterEnabled ? 'Disable Ctrl+Enter' : 'Enable Ctrl+Enter';
  179. };
  180.  
  181. // Append buttons to container
  182. buttonContainer.appendChild(toggleCtrlEnterButton);
  183. buttonContainer.appendChild(toggleLayoutButton);
  184. buttonContainer.appendChild(toggleRightBarButton);
  185.  
  186. // Append button container to body
  187. document.body.appendChild(buttonContainer);
  188.  
  189. buttonsAdded = true;
  190.  
  191. // Start interval to reapply layout every 0.1 seconds
  192. layoutInterval = setInterval(reapplyLayout, 100);
  193.  
  194. // Apply initial settings based on saved preferences
  195. reapplyLayout();
  196. if (isCtrlEnterEnabled) {
  197. enableCtrlEnter();
  198. }
  199. }
  200.  
  201. // Function to remove the buttons and clear the interval
  202. function removeButtons() {
  203. const buttonContainer = document.querySelector('#pixai-ui-helpers-buttons');
  204. if (buttonContainer) {
  205. buttonContainer.remove();
  206. buttonsAdded = false;
  207. }
  208.  
  209. if (layoutInterval) {
  210. clearInterval(layoutInterval);
  211. layoutInterval = null;
  212. }
  213. }
  214.  
  215. // Function to monitor URL changes and add/remove buttons accordingly
  216. function monitorURLChanges() {
  217. const currentURL = window.location.href;
  218.  
  219. if (currentURL.includes('/generator/')) {
  220. addButtons();
  221. } else {
  222. removeButtons();
  223. disableCtrlEnter(); // Ensure Ctrl+Enter is disabled when leaving the page
  224. }
  225. }
  226.  
  227. // Monitor for history changes (when navigating between pages using internal links)
  228. window.addEventListener('popstate', monitorURLChanges);
  229.  
  230. // Monitor for pushState changes (when navigating between pages using internal links)
  231. const originalPushState = history.pushState;
  232. history.pushState = function() {
  233. originalPushState.apply(this, arguments);
  234. monitorURLChanges();
  235. };
  236.  
  237. // Initial check to add/remove buttons based on the current page
  238. monitorURLChanges();
  239. })();