Custom Arka Plan Yöneticisi

Web siteleri için arka plan değiştirme [öncelikli manga-manhwa siteleri]

当前为 2025-01-28 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Custom Arka Plan Yöneticisi
  3. // @namespace http://Vebascans.net/
  4. // @version 2.3.1
  5. // @description Web siteleri için arka plan değiştirme [öncelikli manga-manhwa siteleri]
  6. // @author www.vebascans.net
  7. // @match https://*/*
  8. // @grant none
  9. // @icon https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhi0QDJZNeXWcaD9lXWMN2yenYt5XGrqfPavkCFpWLe01CpSEsMn7IGpbOLqxEfjx4QUUi4wgTw0Kc7vP7FrKjPKpcaaCu1N6QRJzlZvS_Wwr2r3kA4l0-E5wl7xObsZchd8YNSxySFZATPAr2bnrkANBUrmy8Rpdexe-mxG8N6QDojEj0onaNNXF_6g-s/w800/logo.png
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. // 1) SweetAlert2 kütüphanesini otomatik yükle:
  16. const script = document.createElement('script');
  17. script.src = 'https://cdn.jsdelivr.net/npm/sweetalert2@11';
  18. script.onload = main; // Kütüphane yüklendikten sonra main() fonksiyonunu çalıştır
  19. document.head.appendChild(script);
  20.  
  21. // 2) Tüm kodu main() içine alıyoruz:
  22. function main() {
  23.  
  24. /**************************************************************************
  25. * SweetAlert Tanımlaması
  26. **************************************************************************/
  27. const Toast = Swal.mixin({
  28. toast: true,
  29. position: "top",
  30. showConfirmButton: false,
  31. timer: 3000,
  32. timerProgressBar: true,
  33. didOpen: (toast) => {
  34. toast.onmouseenter = Swal.stopTimer;
  35. toast.onmouseleave = Swal.resumeTimer;
  36. }
  37. });
  38.  
  39. /**************************************************************************
  40. * 0) Sabitler
  41. **************************************************************************/
  42. const ACTIVE_KEY = 'VebaScans.net_custom_wp_active'; // Son seçilen veri (URL/Color)
  43. const HISTORY_KEY = 'VebaScans.net_custom_wp_history'; // Tüm geçmiş
  44. const SETTINGS_KEY = 'vebascans.net_custom_wp_settings'; // Arka plan ayarları
  45.  
  46. /**************************************************************************
  47. * 1) Local Storage Yardımcı Fonksiyonları
  48. **************************************************************************/
  49. function getActiveData() {
  50. try {
  51. const str = localStorage.getItem(ACTIVE_KEY);
  52. return str ? JSON.parse(str) : null;
  53. } catch (e) {
  54. return null;
  55. }
  56. }
  57.  
  58. function setActiveData(obj) {
  59. localStorage.setItem(ACTIVE_KEY, JSON.stringify(obj));
  60. applyActiveDataToBody(); // Aktif veri her değiştiğinde body'yi güncelle
  61. }
  62.  
  63. function removeActiveData() {
  64. localStorage.removeItem(ACTIVE_KEY);
  65. applyActiveDataToBody();
  66. }
  67.  
  68. function getHistoryData() {
  69. try {
  70. const str = localStorage.getItem(HISTORY_KEY);
  71. return str ? JSON.parse(str) : [];
  72. } catch (e) {
  73. return [];
  74. }
  75. }
  76.  
  77. function addToHistory(obj) {
  78. let history = getHistoryData();
  79.  
  80. // 1) Eğer geçmişte aynı öğe zaten varsa ekleme yapma
  81. const exists = history.some(item => item.type === obj.type && item.value === obj.value);
  82. if (exists) return; // Aynısı varsa, ekleme yapmadan çık
  83.  
  84. // 2) Yeni öğeyi ekle
  85. history.push(obj);
  86.  
  87. // 3) Aynı öğelerin tekrarını önlemek için filtrele (sadece bir tane kalacak)
  88. history = history.filter((item, index, self) =>
  89. index === self.findIndex(t => t.type === item.type && t.value === item.value)
  90. );
  91.  
  92. // 4) Güncellenmiş geçmişi kaydet
  93. localStorage.setItem(HISTORY_KEY, JSON.stringify(history));
  94. }
  95.  
  96. // Geçmişten silme
  97. function removeFromHistory(obj) {
  98. let history = getHistoryData();
  99. history = history.filter(x => !(x.type === obj.type && x.value === obj.value));
  100. localStorage.setItem(HISTORY_KEY, JSON.stringify(history));
  101. }
  102.  
  103. // Ayarlar
  104. function getSettings() {
  105. try {
  106. const str = localStorage.getItem(SETTINGS_KEY);
  107. return str ? JSON.parse(str) : {};
  108. } catch (e) {
  109. return {};
  110. }
  111. }
  112.  
  113. function setSettings(newSettings) {
  114. localStorage.setItem(SETTINGS_KEY, JSON.stringify(newSettings));
  115. }
  116.  
  117. /**************************************************************************
  118. * 2) BODY Arkaplanını Aktif Veriye (URL/Color) ve Ayarlara Göre Uygulama
  119. **************************************************************************/
  120. function applyActiveDataToBody() {
  121. const activeData = getActiveData();
  122. const settings = getSettings();
  123.  
  124. // Arkaplan tekrar ayarı (varsayılan = 'no-repeat')
  125. const bgRepeat = settings.bgRepeat || 'no-repeat';
  126. // Arkaplan sabit ayarı (varsayılan = 'scroll')
  127. const bgAttachment = settings.bgAttachment || 'scroll';
  128.  
  129. if (!activeData) {
  130. // Aktif bir şey yoksa varsayılan temize çek
  131. document.body.style.backgroundImage = '';
  132. document.body.style.backgroundColor = '';
  133. document.body.style.backgroundRepeat = '';
  134. document.body.style.backgroundAttachment = '';
  135. return;
  136. }
  137.  
  138. if (activeData.type === 'url') {
  139. // Body için arkaplan resmi
  140. document.body.style.backgroundImage = `url(${activeData.value})`;
  141. document.body.style.backgroundRepeat = bgRepeat;
  142. document.body.style.backgroundSize = 'cover';
  143. document.body.style.backgroundAttachment = bgAttachment;
  144. document.body.style.backgroundColor = '';
  145.  
  146. // .body-wrap için
  147. try {
  148. const bodyWrap = document.querySelector('body.text-ui-light .body-wrap');
  149. bodyWrap.style.backgroundImage = `url(${activeData.value})`;
  150. bodyWrap.style.backgroundRepeat = bgRepeat;
  151. bodyWrap.style.backgroundSize = 'cover';
  152. bodyWrap.style.backgroundAttachment = bgAttachment;
  153. bodyWrap.style.backgroundColor = '';
  154. } catch (error) { /* .body-wrap yoksa hata görmezden gel */ }
  155.  
  156. // .site-content için
  157. try {
  158. const sitecontent = document.querySelector('.site-content');
  159. sitecontent.style.backgroundImage = `url(${activeData.value})`;
  160. sitecontent.style.backgroundRepeat = bgRepeat;
  161. sitecontent.style.backgroundSize = 'cover';
  162. sitecontent.style.backgroundAttachment = bgAttachment;
  163. sitecontent.style.backgroundColor = '';
  164. } catch (error) { /* .site-content yoksa hata görmezden gel */ }
  165.  
  166. } else if (activeData.type === 'color') {
  167. // Body için arkaplan rengi
  168. document.body.style.backgroundImage = 'none';
  169. document.body.style.backgroundColor = activeData.value;
  170. document.body.style.backgroundRepeat = bgRepeat;
  171. document.body.style.backgroundAttachment = bgAttachment;
  172.  
  173. // .body-wrap için
  174. try {
  175. const bodyWrap = document.querySelector('body.text-ui-light .body-wrap');
  176. bodyWrap.style.backgroundImage = 'none';
  177. bodyWrap.style.backgroundColor = activeData.value;
  178. bodyWrap.style.backgroundRepeat = bgRepeat;
  179. bodyWrap.style.backgroundAttachment = bgAttachment;
  180. } catch (error) { /* .body-wrap yoksa hata görmezden gel */ }
  181.  
  182. // .site-content için
  183. try {
  184. const sitecontent = document.querySelector('.site-content');
  185. sitecontent.style.backgroundImage = 'none';
  186. sitecontent.style.backgroundColor = activeData.value;
  187. sitecontent.style.backgroundRepeat = bgRepeat;
  188. sitecontent.style.backgroundAttachment = bgAttachment;
  189. } catch (error) { /* .site-content yoksa hata görmezden gel */ }
  190. }
  191. }
  192.  
  193. /**************************************************************************
  194. * 3) MODAL Arayüzü Oluşturma
  195. **************************************************************************/
  196. let modalOverlay, modalContent;
  197.  
  198. window.addEventListener('load', () => {
  199. createModal();
  200. createToggleShortcut(); // F7 ile aç/kapa
  201. applyActiveDataToBody(); // Sayfa açıldığında kaydedilmiş aktif veriyi uygula
  202. });
  203.  
  204. // F7 ile modal aç/kapa
  205. function createToggleShortcut() {
  206. window.addEventListener('keydown', (e) => {
  207. if (e.key === 'F7') {
  208. toggleModal();
  209. }
  210. });
  211. }
  212.  
  213. function toggleModal(forceOpen) {
  214. const isHidden = (modalOverlay.style.display === 'none');
  215. if (forceOpen === true) {
  216. showModal();
  217. } else if (forceOpen === false) {
  218. hideModal();
  219. } else {
  220. if (isHidden) showModal(); else hideModal();
  221. }
  222. }
  223.  
  224. function showModal() {
  225. modalOverlay.style.display = 'block';
  226. refreshHistoryList();
  227. refreshActiveLabel();
  228. refreshSettingsUI();
  229. applyModalTheme(); // Tema ayarını modal açıldığında uygula
  230. }
  231.  
  232. function hideModal() {
  233. modalOverlay.style.display = 'none';
  234. }
  235.  
  236. function createModal() {
  237. // (1) Overlay
  238. modalOverlay = document.createElement('div');
  239. Object.assign(modalOverlay.style, {
  240. display: 'none',
  241. position: 'fixed',
  242. top: '0',
  243. left: '0',
  244. width: '100%',
  245. height: '100%',
  246. backgroundColor: 'rgba(0,0,0,0.5)',
  247. zIndex: '99999',
  248. color: '#000'
  249. });
  250. document.body.appendChild(modalOverlay);
  251.  
  252. // (2) İçerik
  253. modalContent = document.createElement('div');
  254. Object.assign(modalContent.style, {
  255. position: 'absolute',
  256. top: '50%',
  257. left: '50%',
  258. transform: 'translate(-50%, -50%)',
  259. width: '400px',
  260. backgroundColor: '#fff',
  261. padding: '20px',
  262. borderTopLeftRadius: '15px',
  263. borderBottomRightRadius: '15px',
  264. border: '3px solid black',
  265. minHeight: '450px',
  266. fontFamily: 'Arial, sans-serif',
  267. fontSize: '14px',
  268. fontWeight: 'normal',
  269. color: '#000',
  270. });
  271. modalOverlay.appendChild(modalContent);
  272.  
  273. // (3) Logo
  274. const img = document.createElement('img');
  275. img.src = 'https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhi0QDJZNeXWcaD9lXWMN2yenYt5XGrqfPavkCFpWLe01CpSEsMn7IGpbOLqxEfjx4QUUi4wgTw0Kc7vP7FrKjPKpcaaCu1N6QRJzlZvS_Wwr2r3kA4l0-E5wl7xObsZchd8YNSxySFZATPAr2bnrkANBUrmy8Rpdexe-mxG8N6QDojEj0onaNNXF_6g-s/w800/logo.png';
  276. img.alt = 'Logo';
  277. Object.assign(img.style, {
  278. width: '130px',
  279. position: 'absolute',
  280. top: '0',
  281. right: '50%',
  282. transform: 'translate(50%, -50%)'
  283. });
  284. modalContent.appendChild(img);
  285.  
  286. // (4) Başlık
  287. const header = document.createElement('h3');
  288. header.innerHTML = '<a href="https://www.vebascans.net/" style="color: #402870; font-weight: 500; text-decoration: none; font-family: fantasy;">Vebascans</a> - Custom Background';
  289. header.style.margin = '0 0 10px 0';
  290. header.style.color = 'black';
  291. header.style.marginTop = '45px';
  292. modalContent.appendChild(header);
  293.  
  294. // (5) Kapat butonu
  295. const closeBtn = document.createElement('button');
  296. closeBtn.innerHTML = `
  297. <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
  298. <g fill="none" fill-rule="evenodd">
  299. <path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z"/>
  300. <path fill="currentColor" d="m12 14.122l5.303 5.303a1.5 1.5 0 0 0 2.122-2.122L14.12 12l5.304-5.303a1.5 1.5 0 1 0-2.122-2.121L12 9.879L6.697 4.576a1.5 1.5 0 1 0-2.122 2.12L9.88 12l-5.304 5.304a1.5 1.5 0 1 0 2.122 2.12z"/>
  301. </g>
  302. </svg>`;
  303. Object.assign(closeBtn.style, {
  304. position: 'absolute',
  305. top: '10px',
  306. right: '10px',
  307. border: 'none',
  308. background: 'transparent',
  309. cursor: 'pointer',
  310. color: 'black'
  311. });
  312. closeBtn.onclick = () => hideModal();
  313. modalContent.appendChild(closeBtn);
  314.  
  315. // (6) Seçim Menüsü (URL mi Renk mi)
  316. const selectDiv = document.createElement('div');
  317. Object.assign(selectDiv.style, {
  318. display: 'flex',
  319. flexDirection: 'row',
  320. gap: '5px',
  321. marginBottom: '10px'
  322. });
  323. modalContent.appendChild(selectDiv);
  324.  
  325. const selectLabel = document.createElement('label');
  326. selectLabel.textContent = 'Seçim: ';
  327. selectLabel.style.display = 'flex';
  328. selectLabel.style.alignItems = 'center';
  329. selectDiv.appendChild(selectLabel);
  330.  
  331. const selectInput = document.createElement('select');
  332. selectInput.id = 'typeSelect';
  333. selectInput.style.background ='white';
  334. selectInput.style.border ='2px solid black';
  335. selectInput.style.borderRadius ='3px';
  336. selectInput.style.color = 'black';
  337. const optUrl = new Option('URL', 'url');
  338. const optColor = new Option('Renk', 'color');
  339. selectInput.add(optUrl);
  340. selectInput.add(optColor);
  341. selectDiv.appendChild(selectInput);
  342.  
  343. // (7) URL input
  344. const urlInput = document.createElement('input');
  345. urlInput.type = 'text';
  346. urlInput.id = 'urlInput';
  347. urlInput.placeholder = 'Görsel URL giriniz...';
  348. urlInput.style.background ='transparent';
  349. urlInput.style.border ='2px solid black';
  350. urlInput.style.borderRadius ='3px';
  351. selectDiv.appendChild(urlInput);
  352.  
  353. // (8) Color input
  354. const colorInput = document.createElement('input');
  355. colorInput.type = 'color';
  356. colorInput.id = 'colorInput';
  357. colorInput.value = '#000000';
  358. colorInput.style.width = '50px';
  359. colorInput.style.height = '30px';
  360. colorInput.style.display = 'none';
  361. selectDiv.appendChild(colorInput);
  362.  
  363. // Seçim değişince hangi input görünsün?
  364. selectInput.addEventListener('change', () => {
  365. if (selectInput.value === 'url') {
  366. urlInput.style.display = 'inline-block';
  367. colorInput.style.display = 'none';
  368. } else {
  369. urlInput.style.display = 'none';
  370. colorInput.style.display = 'inline-block';
  371. }
  372. });
  373.  
  374. // (9) Aktar butonu
  375. const aktarBtn = document.createElement('button');
  376. aktarBtn.textContent = 'Aktar';
  377. aktarBtn.style.marginLeft = '5px';
  378. aktarBtn.style.padding = '5px 10px';
  379. aktarBtn.style.cursor = 'pointer';
  380. aktarBtn.style.color = 'black';
  381. aktarBtn.style.border ='2px solid black';
  382. aktarBtn.style.borderRadius ='3px';
  383. aktarBtn.style.background = 'transparent';
  384. selectDiv.appendChild(aktarBtn);
  385.  
  386. aktarBtn.onclick = () => {
  387. const currentType = selectInput.value; // 'url' | 'color'
  388. let currentValue = '';
  389. if (currentType === 'url') {
  390. currentValue = urlInput.value.trim();
  391. if (!currentValue) {
  392. Toast.fire({ icon: 'error', title: 'Lütfen bir URL girin.' });
  393. return;
  394. }
  395. } else {
  396. currentValue = colorInput.value; // #rrggbb
  397. if (!currentValue) {
  398. Toast.fire({ icon: 'error', title: 'Lütfen bir renk seçin.' });
  399. return;
  400. }
  401. }
  402.  
  403. // Yeni aktif obje
  404. const newActiveObj = { type: currentType, value: currentValue };
  405. setActiveData(newActiveObj);
  406. addToHistory(newActiveObj);
  407.  
  408. refreshHistoryList();
  409. refreshActiveLabel();
  410.  
  411. // URL tipini kullandıysa inputu temizleyelim
  412. if (currentType === 'url') {
  413. urlInput.value = '';
  414. }
  415. Toast.fire({ icon: 'success', title: 'Yeni aktif değer atandı ve body arkaplanı güncellendi!' });
  416. };
  417.  
  418. // (10) Tekrar / Tek Sefer AYARI
  419. const repeatDiv = document.createElement('div');
  420. repeatDiv.style.margin = '10px 0';
  421. repeatDiv.style.display = 'flex';
  422. repeatDiv.style.flexDirection = 'row';
  423. repeatDiv.style.gap = '10px';
  424. modalContent.appendChild(repeatDiv);
  425.  
  426. const repeatLabel = document.createElement('span');
  427. repeatLabel.textContent = 'Arkaplan Tekrarı:';
  428. repeatLabel.style.alignSelf = 'center';
  429. repeatDiv.appendChild(repeatLabel);
  430.  
  431. const labelRepeat = document.createElement('label');
  432. const radioRepeat = document.createElement('input');
  433. radioRepeat.type = 'radio';
  434. radioRepeat.name = 'bgRepeat';
  435. radioRepeat.value = 'repeat';
  436. radioRepeat.style.marginRight = '5px';
  437. labelRepeat.appendChild(radioRepeat);
  438. labelRepeat.appendChild(document.createTextNode('Tekrarlı'));
  439. repeatDiv.appendChild(labelRepeat);
  440.  
  441. const labelNoRepeat = document.createElement('label');
  442. const radioNoRepeat = document.createElement('input');
  443. radioNoRepeat.type = 'radio';
  444. radioNoRepeat.name = 'bgRepeat';
  445. radioNoRepeat.value = 'no-repeat';
  446. radioNoRepeat.style.marginRight = '5px';
  447. labelNoRepeat.appendChild(radioNoRepeat);
  448. labelNoRepeat.appendChild(document.createTextNode('Tek Sefer'));
  449. repeatDiv.appendChild(labelNoRepeat);
  450.  
  451. [radioRepeat, radioNoRepeat].forEach(radio => {
  452. radio.addEventListener('change', () => {
  453. const newVal = radio.value; // 'repeat' | 'no-repeat'
  454. const s = getSettings();
  455. s.bgRepeat = newVal;
  456. setSettings(s);
  457. applyActiveDataToBody();
  458. });
  459. });
  460.  
  461. // (10b) Arkaplan Sabit AYARI
  462. const attachDiv = document.createElement('div');
  463. attachDiv.style.margin = '10px 0';
  464. attachDiv.style.display = 'flex';
  465. attachDiv.style.flexDirection = 'row';
  466. attachDiv.style.gap = '10px';
  467. modalContent.appendChild(attachDiv);
  468.  
  469. const attachLabel = document.createElement('span');
  470. attachLabel.textContent = 'Arkaplan Sabitliği:';
  471. attachLabel.style.alignSelf = 'center';
  472. attachDiv.appendChild(attachLabel);
  473.  
  474. const labelFixed = document.createElement('label');
  475. const radioFixed = document.createElement('input');
  476. radioFixed.type = 'radio';
  477. radioFixed.name = 'bgAttach';
  478. radioFixed.value = 'fixed';
  479. radioFixed.style.marginRight = '5px';
  480. labelFixed.appendChild(radioFixed);
  481. labelFixed.appendChild(document.createTextNode('Sabit (Fixed)'));
  482. attachDiv.appendChild(labelFixed);
  483.  
  484. const labelScroll = document.createElement('label');
  485. const radioScroll = document.createElement('input');
  486. radioScroll.type = 'radio';
  487. radioScroll.name = 'bgAttach';
  488. radioScroll.value = 'scroll';
  489. radioScroll.style.marginRight = '5px';
  490. labelScroll.appendChild(radioScroll);
  491. labelScroll.appendChild(document.createTextNode('Kaydır (Scroll)'));
  492. attachDiv.appendChild(labelScroll);
  493.  
  494. [radioFixed, radioScroll].forEach(radio => {
  495. radio.addEventListener('change', () => {
  496. const newVal = radio.value; // 'fixed' | 'scroll'
  497. const s = getSettings();
  498. s.bgAttachment = newVal;
  499. setSettings(s);
  500. applyActiveDataToBody();
  501. });
  502. });
  503.  
  504. // (11) Aktif Veriyi Sil
  505. const removeActiveBtn = document.createElement('button');
  506. removeActiveBtn.textContent = 'Devre dışı bırak';
  507. removeActiveBtn.style.marginBottom = '10px';
  508. removeActiveBtn.style.padding = '5px 10px';
  509. removeActiveBtn.style.cursor = 'pointer';
  510. removeActiveBtn.style.color = 'black';
  511. removeActiveBtn.style.background = 'transparent';
  512. removeActiveBtn.style.border ='2px solid black';
  513. removeActiveBtn.style.borderRadius ='3px';
  514. modalContent.appendChild(removeActiveBtn);
  515.  
  516. removeActiveBtn.onclick = () => {
  517. removeActiveData();
  518. refreshHistoryList();
  519. refreshActiveLabel();
  520. Toast.fire({ icon: 'info', title: 'Aktif veri silindi. Arkaplan temizlendi.' });
  521. };
  522.  
  523. // (12) Şu anda aktif veriyi gösteren label
  524. const activeDiv = document.createElement('div');
  525. activeDiv.id = 'activeDiv';
  526. activeDiv.style.marginTop = '10px';
  527. modalContent.appendChild(activeDiv);
  528.  
  529. // (13) Geçmiş Başlık
  530. const historyTitle = document.createElement('h4');
  531. historyTitle.textContent = 'Geçmiş';
  532. historyTitle.style.margin = '10px 0 5px 0';
  533. modalContent.appendChild(historyTitle);
  534.  
  535. // (14) Geçmiş Container
  536. const historyContainer = document.createElement('div');
  537. historyContainer.id = 'historyContainer';
  538. historyContainer.style.maxHeight = '200px';
  539. historyContainer.style.overflowY = 'auto';
  540. historyContainer.style.border = '1px solid #ccc';
  541. historyContainer.style.padding = '5px';
  542. modalContent.appendChild(historyContainer);
  543.  
  544. // Yedekleme (Dışa/İçe Aktar)
  545. const importExportTitle = document.createElement('h4');
  546. importExportTitle.textContent = 'Yedekleme';
  547. importExportTitle.style.margin = '10px 0 5px 0';
  548. modalContent.appendChild(importExportTitle);
  549.  
  550. const exportBtn = document.createElement('button');
  551. exportBtn.textContent = 'Dışa Aktar (JSON)';
  552. exportBtn.style.padding = '5px 10px';
  553. exportBtn.style.cursor = 'pointer';
  554. exportBtn.style.color = 'black';
  555. exportBtn.style.background = 'transparent';
  556. exportBtn.style.border = '2px solid black';
  557. exportBtn.style.borderRadius = '3px';
  558. exportBtn.style.marginRight = '10px';
  559. modalContent.appendChild(exportBtn);
  560.  
  561. exportBtn.onclick = () => {
  562. exportDataAsJson();
  563. };
  564.  
  565. const importBtn = document.createElement('button');
  566. importBtn.textContent = 'İçe Aktar (JSON)';
  567. importBtn.style.padding = '5px 10px';
  568. importBtn.style.cursor = 'pointer';
  569. importBtn.style.color = 'black';
  570. importBtn.style.background = 'transparent';
  571. importBtn.style.border = '2px solid black';
  572. importBtn.style.borderRadius = '3px';
  573. modalContent.appendChild(importBtn);
  574.  
  575. const importInput = document.createElement('input');
  576. importInput.type = 'file';
  577. importInput.accept = 'application/json';
  578. importInput.style.display = 'none';
  579. modalContent.appendChild(importInput);
  580.  
  581. importBtn.addEventListener('click', () => {
  582. importInput.click(); // Dosya seçme penceresini aç
  583. });
  584.  
  585. importInput.addEventListener('change', () => {
  586. if (importInput.files && importInput.files[0]) {
  587. importDataFromJson(importInput.files[0]);
  588. }
  589. });
  590.  
  591. /**************************************************************************
  592. * _Eklenen Kod Başlangıcı_ (Tema Ayarı)
  593. **************************************************************************/
  594. // Tema AYARI için radyo seçenekleri
  595. const themeDiv = document.createElement('div');
  596. themeDiv.style.marginTop = '15px';
  597. themeDiv.style.display = 'flex';
  598. themeDiv.style.flexDirection = 'row';
  599. themeDiv.style.gap = '10px';
  600. modalContent.appendChild(themeDiv);
  601.  
  602. const themeLabel = document.createElement('span');
  603. themeLabel.textContent = 'Modal Tema:';
  604. themeLabel.style.alignSelf = 'center';
  605. themeDiv.appendChild(themeLabel);
  606.  
  607. const labelLight = document.createElement('label');
  608. const radioLight = document.createElement('input');
  609. radioLight.type = 'radio';
  610. radioLight.name = 'modalTheme';
  611. radioLight.value = 'light';
  612. radioLight.style.marginRight = '5px';
  613. labelLight.appendChild(radioLight);
  614. labelLight.appendChild(document.createTextNode('Aydınlık'));
  615. themeDiv.appendChild(labelLight);
  616.  
  617. const labelDark = document.createElement('label');
  618. const radioDark = document.createElement('input');
  619. radioDark.type = 'radio';
  620. radioDark.name = 'modalTheme';
  621. radioDark.value = 'dark';
  622. radioDark.style.marginRight = '5px';
  623. labelDark.appendChild(radioDark);
  624. labelDark.appendChild(document.createTextNode('Karanlık'));
  625. themeDiv.appendChild(labelDark);
  626.  
  627. // Radyo değişimiyle tema ayarını kaydetme
  628. [radioLight, radioDark].forEach(radio => {
  629. radio.addEventListener('change', () => {
  630. const newVal = radio.value; // 'light' | 'dark'
  631. const s = getSettings();
  632. s.theme = newVal;
  633. setSettings(s);
  634. applyModalTheme(); // Tema uygulansın
  635. });
  636. });
  637. /**************************************************************************
  638. * _Eklenen Kod Sonu_
  639. **************************************************************************/
  640. }
  641.  
  642. /**************************************************************************
  643. * 4) Geçmiş & Aktif Listeyi Güncelleme
  644. **************************************************************************/
  645. function refreshHistoryList() {
  646. const historyContainer = document.getElementById('historyContainer');
  647. if (!historyContainer) return;
  648.  
  649. historyContainer.innerHTML = '';
  650.  
  651. const historyData = getHistoryData();
  652. const activeData = getActiveData(); // {type:'...', value:'...'}
  653.  
  654. historyData.forEach((item) => {
  655. const row = document.createElement('div');
  656. row.style.display = 'flex';
  657. row.style.alignItems = 'center';
  658. row.style.marginBottom = '8px';
  659. row.style.cursor = 'pointer';
  660. row.style.justifyContent = 'space-between';
  661.  
  662. const leftPart = document.createElement('div');
  663. leftPart.style.display = 'flex';
  664. leftPart.style.alignItems = 'center';
  665. leftPart.style.gap = '8px';
  666.  
  667. // URL ise küçük görsel
  668. if (item.type === 'url') {
  669. const imgThumb = document.createElement('img');
  670. imgThumb.src = item.value;
  671. imgThumb.alt = 'Görsel';
  672. imgThumb.style.width = '30px';
  673. imgThumb.style.height = '30px';
  674. imgThumb.style.objectFit = 'cover';
  675. leftPart.appendChild(imgThumb);
  676.  
  677. const label = document.createElement('span');
  678. label.textContent = 'URL';
  679. leftPart.appendChild(label);
  680.  
  681. } else if (item.type === 'color') {
  682. // Renk ise kutu
  683. const colorBox = document.createElement('span');
  684. colorBox.style.display = 'inline-block';
  685. colorBox.style.width = '30px';
  686. colorBox.style.height = '30px';
  687. colorBox.style.backgroundColor = item.value;
  688. colorBox.style.border = '1px solid #000';
  689. leftPart.appendChild(colorBox);
  690.  
  691. const label = document.createElement('span');
  692. label.textContent = item.value;
  693. leftPart.appendChild(label);
  694. }
  695.  
  696. // Aktif mi?
  697. if (activeData && activeData.type === item.type && activeData.value === item.value) {
  698. const activeSpan = document.createElement('span');
  699. activeSpan.textContent = ' (Aktif)';
  700. activeSpan.style.color = 'green';
  701. leftPart.appendChild(activeSpan);
  702. }
  703.  
  704. // Tıklayınca bu itemi aktif yap
  705. leftPart.addEventListener('click', () => {
  706. setActiveData(item);
  707. refreshHistoryList();
  708. refreshActiveLabel();
  709. Toast.fire({ icon: 'success', title: 'Aktif değer güncellendi!' });
  710. });
  711.  
  712. // Sağ kısma "Geçmişten Sil" butonu
  713. const rightPart = document.createElement('button');
  714. rightPart.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m20 9l-1.995 11.346A2 2 0 0 1 16.035 22h-8.07a2 2 0 0 1-1.97-1.654L4 9m17-3h-5.625M3 6h5.625m0 0V4a2 2 0 0 1 2-2h2.75a2 2 0 0 1 2 2v2m-6.75 0h6.75"/></svg>';
  715. rightPart.style.border ='2px solid black';
  716. rightPart.style.color= 'black'
  717. rightPart.style.borderRadius ='3px';
  718. rightPart.style.background = 'transparent';
  719. rightPart.style.padding = '3px 5px';
  720. rightPart.style.cursor = 'pointer';
  721.  
  722. rightPart.addEventListener('click', (e) => {
  723. e.stopPropagation(); // Aktif yapma tıklamasını engelle
  724.  
  725. // Aktif veriyi al
  726. const activeData = getActiveData();
  727.  
  728. // Eğer silinmek istenen veri aktif veriyle eşleşiyorsa, işlemi durdur
  729. if (activeData && activeData.type === item.type && activeData.value === item.value) {
  730. Toast.fire({ icon: 'warning', title: 'Aktif olan bir veriyi silemezsiniz!' });
  731. return; // İşlemi durdur
  732. }
  733.  
  734. // Eğer aktif veri değilse, geçmişten sil
  735. removeFromHistory(item);
  736. refreshHistoryList();
  737. Toast.fire({ icon: 'info', title: 'Geçmişten silindi.' });
  738. });
  739.  
  740. row.appendChild(leftPart);
  741. row.appendChild(rightPart);
  742. historyContainer.appendChild(row);
  743. });
  744. }
  745.  
  746. function refreshActiveLabel() {
  747. const activeDiv = document.getElementById('activeDiv');
  748. if (!activeDiv) return;
  749.  
  750. const activeData = getActiveData();
  751. if (!activeData) {
  752. activeDiv.textContent = 'Şu anda aktif bir değer yok.';
  753. } else {
  754. if (activeData.type === 'url') {
  755. activeDiv.innerHTML = `
  756. Aktif: URL
  757. <img src="${activeData.value}"
  758. alt="Aktif Görsel"
  759. style="width: 100px; height: auto; object-fit: cover; margin-left:5px;"/>
  760. `;
  761. } else {
  762. activeDiv.innerHTML = `
  763. Aktif: Renk
  764. <span style="display:inline-block; width:20px; height:20px;
  765. background-color:${activeData.value};
  766. border:1px solid #000; vertical-align:middle;">
  767. </span>
  768. ${activeData.value}
  769. `;
  770. }
  771. }
  772. }
  773.  
  774. /**************************************************************************
  775. * 5) Arkaplan Ayarı (Tekrar / Tek Sefer / Sabit) Radyo Butonlarını Güncelleme
  776. **************************************************************************/
  777. function refreshSettingsUI() {
  778. const settings = getSettings();
  779. const bgRepeat = settings.bgRepeat || 'no-repeat'; // Varsayılan no-repeat
  780. const bgAttach = settings.bgAttachment || 'scroll'; // Varsayılan scroll
  781.  
  782. // Tekrar radyo
  783. const radiosRepeat = document.getElementsByName('bgRepeat');
  784. radiosRepeat.forEach(radio => {
  785. radio.checked = (radio.value === bgRepeat);
  786. });
  787.  
  788. // Sabit/Kaydır radyo
  789. const radiosAttach = document.getElementsByName('bgAttach');
  790. radiosAttach.forEach(radio => {
  791. radio.checked = (radio.value === bgAttach);
  792. });
  793.  
  794. // _Eklenen Kod: Modal Tema radyo
  795. const theme = settings.theme || 'light'; // Varsayılan 'light'
  796. const radiosTheme = document.getElementsByName('modalTheme');
  797. radiosTheme.forEach(radio => {
  798. radio.checked = (radio.value === theme);
  799. });
  800. }
  801.  
  802. // Tema uygulama fonksiyonu
  803. function applyModalTheme() {
  804. const settings = getSettings();
  805. const theme = settings.theme || 'light';
  806.  
  807. if (theme === 'dark') {
  808. // Modal ana gövde
  809. modalContent.style.backgroundColor = '#070707';
  810. modalContent.style.color = 'white';
  811. modalContent.style.border = '2px solid white';
  812.  
  813. // Tüm alt öğeleri tarayalım:
  814. const allElements = modalContent.querySelectorAll('*');
  815. allElements.forEach(el => {
  816. // Eğer siyah sınır varsa beyaza çevir
  817. if (el.style.border === '2px solid black') {
  818. el.style.border = '2px solid white';
  819. }
  820. // Yazı rengi siyahsa beyaza çevir
  821. if (el.style.color === 'black') {
  822. el.style.color = 'white';
  823. }
  824. // Arka plan beyaz veya 'transparent' ise #070707 yap
  825. const bg = el.style.backgroundColor || el.style.background;
  826. if (bg === 'white' || bg === 'transparent') {
  827. el.style.backgroundColor = '#070707';
  828. }
  829. });
  830.  
  831. } else {
  832. // Light (aydınlık) tema için varsayılanlar
  833. modalContent.style.backgroundColor = '#fff';
  834. modalContent.style.color = 'black';
  835. modalContent.style.border = '2px solid black';
  836.  
  837. // Tekrar tüm alt öğeleri dolaşıp varsayılan değerlere çekebilirsiniz
  838. const allElements = modalContent.querySelectorAll('*');
  839. allElements.forEach(el => {
  840. // Siyah kenarlık
  841. if (el.style.border === '2px solid white') {
  842. el.style.border = '2px solid black';
  843. }
  844. // Yazı rengi beyaz ise siyaha çevir
  845. if (el.style.color === 'white') {
  846. el.style.color = 'black';
  847. }
  848. // Arka plan koyu ise beyaza veya transparent’e döndürebilirsiniz
  849. const bg = el.style.backgroundColor || el.style.background;
  850. if (bg === 'rgb(7, 7, 7)' || bg === '#070707') {
  851. el.style.backgroundColor = 'white';
  852. }
  853. });
  854. }
  855. }
  856.  
  857. // Dışa Aktar (JSON olarak)
  858. function exportDataAsJson() {
  859. // Tek bir obje içine aktif, geçmiş ve ayarları al
  860. const data = {
  861. active: getActiveData(),
  862. history: getHistoryData(),
  863. settings: getSettings()
  864. };
  865. const jsonStr = JSON.stringify(data, null, 2);
  866.  
  867. // Dosya oluşturup otomatik indirme linki
  868. const blob = new Blob([jsonStr], { type: 'application/json' });
  869. const url = URL.createObjectURL(blob);
  870. const a = document.createElement('a');
  871. a.href = url;
  872. a.download = 'Vebascans_CustomBackground.json';
  873. document.body.appendChild(a);
  874. a.click();
  875. a.remove();
  876. URL.revokeObjectURL(url);
  877.  
  878. Toast.fire({ icon: 'success', title: 'Veriler JSON formatında indirildi!' });
  879. }
  880.  
  881. // İçe Aktar (JSON dosyasından)
  882. function importDataFromJson(file) {
  883. const reader = new FileReader();
  884. reader.onload = (e) => {
  885. try {
  886. const imported = JSON.parse(e.target.result);
  887.  
  888. // Dosyada hangi veriler varsa alıp localStorage'a yazalım
  889. if (imported.active) {
  890. localStorage.setItem(ACTIVE_KEY, JSON.stringify(imported.active));
  891. }
  892. if (imported.history) {
  893. localStorage.setItem(HISTORY_KEY, JSON.stringify(imported.history));
  894. }
  895. if (imported.settings) {
  896. localStorage.setItem(SETTINGS_KEY, JSON.stringify(imported.settings));
  897. }
  898.  
  899. // Yeniden uygula ve arayüzü tazele
  900. applyActiveDataToBody();
  901. refreshHistoryList();
  902. refreshActiveLabel();
  903. refreshSettingsUI();
  904. applyModalTheme();
  905.  
  906. Toast.fire({ icon: 'success', title: 'JSON verileri başarıyla içe aktarıldı!' });
  907. } catch (error) {
  908. Toast.fire({ icon: 'error', title: 'Geçersiz JSON dosyası veya okuma hatası!' });
  909. }
  910. };
  911. reader.readAsText(file);
  912. }
  913.  
  914. } // main() sonu
  915.  
  916. })(); // IIFE sonu