Text Explainer Settings

Settings module for Text Explainer

2025-03-04 يوللانغان نەشرى. ئەڭ يېڭى نەشرىنى كۆرۈش.

بۇ قوليازمىنى بىۋاسىتە قاچىلاشقا بولمايدۇ. بۇ باشقا قوليازمىلارنىڭ ئىشلىتىشى ئۈچۈن تەمىنلەنگەن ئامبار بولۇپ، ئىشلىتىش ئۈچۈن مېتا كۆرسەتمىسىگە قىستۇرىدىغان كود: // @require https://update.greatest.deepsurf.us/scripts/528763/1547018/Text%20Explainer%20Settings.js

  1. // ==UserScript==
  2. // @name Text Explainer Settings
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1.0
  5. // @description Settings module for Text Explainer
  6. // @author RoCry
  7. // @license MIT
  8. // ==/UserScript==
  9.  
  10. class TextExplainerSettings {
  11. constructor(defaultConfig = {}) {
  12. this.defaultConfig = Object.assign({
  13. model: "gemini-2.0-flash",
  14. apiKey: null,
  15. baseUrl: "https://generativelanguage.googleapis.com",
  16. provider: "gemini",
  17. language: "Chinese"
  18. }, defaultConfig);
  19. this.config = this.load();
  20. }
  21. /**
  22. * Load settings from storage
  23. */
  24. load() {
  25. try {
  26. const savedConfig = typeof GM_getValue === 'function'
  27. ? GM_getValue('explainerConfig', {})
  28. : JSON.parse(localStorage.getItem('explainerConfig') || '{}');
  29. return Object.assign({}, this.defaultConfig, savedConfig);
  30. } catch (e) {
  31. console.error('Error loading settings:', e);
  32. return Object.assign({}, this.defaultConfig);
  33. }
  34. }
  35. /**
  36. * Save settings to storage
  37. */
  38. save() {
  39. try {
  40. if (typeof GM_setValue === 'function') {
  41. GM_setValue('explainerConfig', this.config);
  42. } else {
  43. localStorage.setItem('explainerConfig', JSON.stringify(this.config));
  44. }
  45. return true;
  46. } catch (e) {
  47. console.error('Error saving settings:', e);
  48. return false;
  49. }
  50. }
  51. /**
  52. * Get setting value
  53. */
  54. get(key) {
  55. return this.config[key];
  56. }
  57. /**
  58. * Set setting value
  59. */
  60. set(key, value) {
  61. this.config[key] = value;
  62. return this;
  63. }
  64. /**
  65. * Update multiple settings at once
  66. */
  67. update(settings) {
  68. Object.assign(this.config, settings);
  69. return this;
  70. }
  71. /**
  72. * Reset settings to defaults
  73. */
  74. reset() {
  75. this.config = Object.assign({}, this.defaultConfig);
  76. return this;
  77. }
  78. /**
  79. * Get all settings
  80. */
  81. getAll() {
  82. return Object.assign({}, this.config);
  83. }
  84. /**
  85. * Open settings dialog
  86. */
  87. openDialog(onSave = null) {
  88. // First check if dialog already exists and remove it
  89. const existingDialog = document.getElementById('explainer-settings-dialog');
  90. if (existingDialog) existingDialog.remove();
  91. // Create dialog container
  92. const dialog = document.createElement('div');
  93. dialog.id = 'explainer-settings-dialog';
  94. dialog.style = `
  95. position: fixed;
  96. top: 50%;
  97. left: 50%;
  98. transform: translate(-50%, -50%);
  99. background: white;
  100. padding: 16px;
  101. border-radius: 8px;
  102. box-shadow: 0 2px 10px rgba(0,0,0,0.2);
  103. z-index: 10001;
  104. width: 400px;
  105. max-width: 90vw;
  106. font-family: system-ui, sans-serif;
  107. `;
  108. // Add dark mode support
  109. const styleElement = document.createElement('style');
  110. styleElement.textContent = `
  111. #explainer-settings-dialog {
  112. color: #333;
  113. }
  114. #explainer-settings-dialog label {
  115. display: block;
  116. margin: 12px 0 4px;
  117. font-weight: 500;
  118. }
  119. #explainer-settings-dialog input[type="text"],
  120. #explainer-settings-dialog select {
  121. width: 100%;
  122. padding: 8px;
  123. border: 1px solid #ccc;
  124. border-radius: 4px;
  125. box-sizing: border-box;
  126. font-size: 14px;
  127. }
  128. #explainer-settings-dialog .buttons {
  129. display: flex;
  130. justify-content: flex-end;
  131. gap: 8px;
  132. margin-top: 20px;
  133. }
  134. #explainer-settings-dialog button {
  135. padding: 8px 12px;
  136. border: none;
  137. border-radius: 4px;
  138. cursor: pointer;
  139. font-size: 14px;
  140. }
  141. #explainer-settings-dialog button.primary {
  142. background-color: #4285f4;
  143. color: white;
  144. }
  145. #explainer-settings-dialog button.secondary {
  146. background-color: #f1f1f1;
  147. color: #333;
  148. }
  149. @media (prefers-color-scheme: dark) {
  150. #explainer-settings-dialog {
  151. background: #333;
  152. color: #eee;
  153. }
  154. #explainer-settings-dialog input[type="text"],
  155. #explainer-settings-dialog select {
  156. background: #444;
  157. color: #eee;
  158. border-color: #555;
  159. }
  160. #explainer-settings-dialog button.secondary {
  161. background-color: #555;
  162. color: #eee;
  163. }
  164. }
  165. `;
  166. document.head.appendChild(styleElement);
  167. // Create dialog content
  168. dialog.innerHTML = `
  169. <h3 style="margin-top:0;">Text Explainer Settings</h3>
  170. <div>
  171. <label for="explainer-language">Language</label>
  172. <select id="explainer-language">
  173. <option value="Chinese" ${this.config.language === 'Chinese' ? 'selected' : ''}>Chinese</option>
  174. <option value="English" ${this.config.language === 'English' ? 'selected' : ''}>English</option>
  175. <option value="Japanese" ${this.config.language === 'Japanese' ? 'selected' : ''}>Japanese</option>
  176. </select>
  177. </div>
  178. <div>
  179. <label for="explainer-provider">Provider</label>
  180. <select id="explainer-provider">
  181. <option value="gemini" ${this.config.provider === 'gemini' ? 'selected' : ''}>Gemini</option>
  182. <option value="openai" ${this.config.provider === 'openai' ? 'selected' : ''}>OpenAI</option>
  183. <option value="anthropic" ${this.config.provider === 'anthropic' ? 'selected' : ''}>Anthropic</option>
  184. </select>
  185. </div>
  186. <div>
  187. <label for="explainer-model">Model</label>
  188. <input id="explainer-model" type="text" value="${this.config.model}">
  189. </div>
  190. <div>
  191. <label for="explainer-api-key">API Key</label>
  192. <input id="explainer-api-key" type="text" value="${this.config.apiKey || ''}">
  193. </div>
  194. <div>
  195. <label for="explainer-base-url">API Base URL</label>
  196. <input id="explainer-base-url" type="text" value="${this.config.baseUrl}">
  197. </div>
  198. <div class="buttons">
  199. <button id="explainer-settings-cancel" class="secondary">Cancel</button>
  200. <button id="explainer-settings-save" class="primary">Save</button>
  201. </div>
  202. `;
  203. document.body.appendChild(dialog);
  204. // Add event listeners
  205. document.getElementById('explainer-settings-save').addEventListener('click', () => {
  206. // Update config with form values
  207. this.update({
  208. language: document.getElementById('explainer-language').value,
  209. model: document.getElementById('explainer-model').value,
  210. apiKey: document.getElementById('explainer-api-key').value,
  211. baseUrl: document.getElementById('explainer-base-url').value,
  212. provider: document.getElementById('explainer-provider').value
  213. });
  214. // Save to storage
  215. this.save();
  216. // Remove dialog
  217. dialog.remove();
  218. styleElement.remove();
  219. // Call save callback if provided
  220. if (typeof onSave === 'function') {
  221. onSave(this.config);
  222. }
  223. });
  224. document.getElementById('explainer-settings-cancel').addEventListener('click', () => {
  225. dialog.remove();
  226. styleElement.remove();
  227. });
  228. // Focus first field
  229. document.getElementById('explainer-language').focus();
  230. }
  231. }
  232.  
  233. // Make available globally and as a module if needed
  234. window.TextExplainerSettings = TextExplainerSettings;
  235.  
  236. if (typeof module !== 'undefined') {
  237. module.exports = TextExplainerSettings;
  238. }