Greasy Fork is available in English.

Wykop XS

Wykop XS służy do wspomagania działania stylu "Wykop X Style", który jest wymagany do poprawnego działania niniejszego skryptu. Wykop X Style znajdziesz na: http://style.wykopx.pl

Versão de: 15/12/2023. Veja: a última versão.

  1. // ==UserScript==
  2. // @name Wykop XS
  3. // @name:pl Wykop XS
  4. // @name:en Wykop XS
  5. // @author Wykop X <wykopx@gmail.com>
  6. // @namespace Violentmonkey Scripts
  7. // @match https://wykop.pl/*
  8.  
  9.  
  10. // @require https://unpkg.com/xhook@latest/dist/xhook.min.js
  11. // @require https://greasyfork.org/scripts/458629-depaginator-for-wykop-pl/code/Depaginator%20for%20Wykoppl.user.js
  12. // @require https://unpkg.com/localforage@1.10.0/dist/localforage.min.js
  13. // @require https://cdn.jsdelivr.net/npm/dayjs@1/dayjs.min.js
  14. // @require http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js
  15. // @require https://greasyfork.org/scripts/383527-wait-for-key-elements/code/Wait_for_key_elements.js?version=701631
  16.  
  17. // @supportURL http://wykop.pl/tag/wykopwnowymstylu
  18. // @contributionURL https://buycoffee.to/sebastiandosiadlgo
  19. // @compatible chrome, firefox, opera, safari, edge
  20. // @license No License
  21. // @description Wykop XS służy do wspomagania działania stylu "Wykop X Style", który jest wymagany do poprawnego działania niniejszego skryptu. Wykop X Style znajdziesz na: http://style.wykopx.pl
  22. // @description:en Wykop XS is a helper script for userstyle "Wykop X Style" which modifies wykop.pl website and make it easier to use adding enhancements and new features. Check it out here: http://style.wykopx.pl
  23.  
  24. // @version 2.41.2
  25. // ==/UserScript==
  26.  
  27. (async function ()
  28. {
  29. 'use strict';
  30.  
  31.  
  32. const currentVersion = "2.41.2";
  33. const dev = false;
  34. const promoString = " [Dodane przez Wykop XS #wykopwnowymstylu]";
  35.  
  36. // user.username - nazwa zalogowanego uzytkownika
  37.  
  38.  
  39. let wykopxStorageMirkoukrywacz = localforage.createInstance({
  40. driver: localforage.LOCALSTORAGE,
  41. name: "wykopx",
  42. storeName: "mirkoukrywacz",
  43. });
  44.  
  45. let wykopxStorageNotatkowator = localforage.createInstance({
  46. driver: localforage.LOCALSTORAGE,
  47. name: "wykopx",
  48. storeName: "notatkowator",
  49. });
  50.  
  51. let wykopxStorageObservedTags = localforage.createInstance({
  52. driver: localforage.LOCALSTORAGE,
  53. name: "wykopx",
  54. storeName: "observedTags",
  55. });
  56.  
  57.  
  58. // getComputedStyle(document.documentElement) -- nie działa, nie wczytuje właściwości z :root
  59. let wykopxSettings = getComputedStyle(document.querySelector("body"));
  60. let settings = {};
  61.  
  62. // boolean
  63. settings.hitsInTopNavJS = (wykopxSettings.getPropertyValue("--hitsInTopNavJS") == `"true"`); // boolean
  64. settings.votingExplosion = (wykopxSettings.getPropertyValue("--votingExplosion") == `"true"`); // boolean
  65. settings.tabTitleEnabled = (wykopxSettings.getPropertyValue("--tabTitleEnabled") == `"true"`); // boolean
  66. settings.tabFaviconEnabled = (wykopxSettings.getPropertyValue("--tabFaviconEnabled") == `"true"`); // boolean
  67. settings.tagHeaderEditable = (wykopxSettings.getPropertyValue("--tagHeaderEditable") == `"true"`); // boolean
  68. settings.myWykopInTopNavJS = (wykopxSettings.getPropertyValue("--myWykopInTopNavJS") == `"true"`); // boolean
  69. settings.enableNotatkowator = (wykopxSettings.getPropertyValue("--enableNotatkowator") == `"true"`); // boolean
  70. settings.linksAnalyzerEnable = (wykopxSettings.getPropertyValue("--linksAnalyzerEnable") == `"true"`); // boolean
  71. settings.favoritesInTopNavJS = (wykopxSettings.getPropertyValue("--favoritesInTopNavJS") == `"true"`); // boolean
  72. settings.addNewLinkInTopNavJS = (wykopxSettings.getPropertyValue("--addNewLinkInTopNavJS") == `"true"`); // boolean
  73. settings.addNewEntryInTopNavJS = (wykopxSettings.getPropertyValue("--addNewEntryInTopNavJS") == `"true"`); // boolean
  74. settings.tabChangeOnlyOnHiddenState = (wykopxSettings.getPropertyValue("--tabChangeOnlyOnHiddenState") == `"true"`); // boolean
  75. settings.linksAnalyzerSortByVotesCount = (wykopxSettings.getPropertyValue("--linksAnalyzerSortByVotesCount") == `"true"`); // boolean
  76. settings.showObservedTagsAlphabetically = (wykopxSettings.getPropertyValue("--showObservedTagsAlphabetically") == `"true"`); // boolean
  77. settings.showObservedTagsInRightSidebar = (wykopxSettings.getPropertyValue("--showObservedTagsInRightSidebar") == `"true"`); // boolean
  78.  
  79. settings.fixCaseSensitiveTagsRedirection = (wykopxSettings.getPropertyValue("--fixCaseSensitiveTagsRedirection") == `"true"`); // boolean
  80.  
  81. settings.tabTitleShowNotificationsEnabled = (wykopxSettings.getPropertyValue("--tabTitleShowNotificationsEnabled") == `"true"`); // boolean
  82. settings.tabTitleShowNotificationsCountPM = (wykopxSettings.getPropertyValue("--tabTitleShowNotificationsCountPM") == `"true"`); // boolean
  83. settings.tabTitleShowNotificationsCountEntries = (wykopxSettings.getPropertyValue("--tabTitleShowNotificationsCountEntries") == `"true"`); // boolean
  84. settings.tabTitleShowNotificationsCountTagsNewLink = (wykopxSettings.getPropertyValue("--tabTitleShowNotificationsCountTagsNewLink") == `"true"`); // boolean
  85. settings.tabTitleShowNotificationsCountTagsNewEntry = (wykopxSettings.getPropertyValue("--tabTitleShowNotificationsCountTagsNewEntry") == `"true"`); // boolean
  86. settings.tabTitleShowNotificationsCountSeparated = (wykopxSettings.getPropertyValue("--tabTitleShowNotificationsCountSeparated") == `"true"`); // boolean
  87.  
  88.  
  89.  
  90.  
  91. // boolean - domyslnie WŁĄCZONE bez Wykop X Style
  92. settings.disableNewLinkEditorPastedTextLimit = wykopxSettings.getPropertyValue("--disableNewLinkEditorPastedTextLimit") ? wykopxSettings.getPropertyValue("--disableNewLinkEditorPastedTextLimit") === '1' : true;
  93.  
  94. settings.notatkowatorUpdateInterval = parseFloat(wykopxSettings.getPropertyValue("--notatkowatorUpdateInterval")); // number
  95. settings.homepagePinnedEntriesHideBelowLimit = parseFloat(wykopxSettings.getPropertyValue("--homepagePinnedEntriesHideBelowLimit")); // number
  96. settings.showObservedTagsInRightSidebarUpdateInterval = parseFloat(wykopxSettings.getPropertyValue("--showObservedTagsInRightSidebarUpdateInterval")); // number
  97.  
  98.  
  99. // strings
  100. settings.WykopXStyleVersion = (wykopxSettings.getPropertyValue("--version").trim().slice(1, -1)); // "2.40"
  101. settings.tabTitleSelect = wykopxSettings.getPropertyValue("--tabTitleSelect").trim()
  102. settings.tabTitleCustom = wykopxSettings.getPropertyValue("--tabTitleCustom").trim();
  103. settings.tabFaviconSelect = wykopxSettings.getPropertyValue("--tabFaviconSelect").trim()
  104.  
  105.  
  106. if (dev) consoleX("Settings: ", 1);
  107. if (dev) console.log(settings);
  108.  
  109. // przenoszenie na tagi: wykop.pl/#heheszki
  110. // i na profile użytkownikow: wykop.pl/@m__b
  111. // wyszukiwanie wpisów danej osoby w konkretnym tagu wykop.pl/@m__b/#internet albo wykop.pl/#internet/@m__b/
  112.  
  113. let hash = new URL(document.URL).hash;
  114. let pathname = new URL(document.URL).pathname;
  115. let pathnameArray = pathname.split("/");
  116. /*
  117.  
  118. ['', 'wpis', '74111643', 'dobranoc-panstwu']
  119. ['', 'wykopalisko']
  120. ['', 'link', '7303053', 'braun-gasi-chanuke-gasnica-mem']
  121.  
  122. */
  123. function hashAndPathNameLoad()
  124. {
  125. hash = new URL(document.URL).hash;
  126. pathname = new URL(document.URL).pathname;
  127. pathnameArray = pathname.split("/");
  128. consoleX(`hashAndPathNameLoad() - hash: ${hash}, pathname: ${pathname}, pathnameArray: `, 1)
  129. console.log(pathnameArray)
  130. }
  131.  
  132.  
  133.  
  134. (async () =>
  135. {
  136. consoleX("(async () => {", 1);
  137.  
  138. let at, tag;
  139. if (settings.fixCaseSensitiveTagsRedirection)
  140. {
  141. /* fixing case sensitive tags https://github.com/wykopx/WykopX/issues/21 */
  142. if (pathnameArray[1] == "tag" && /[A-Z]/.test(pathnameArray[2]))
  143. {
  144. consoleX(`Błędny tag "${pathnameArray[2]}"`);
  145. pathnameArray[2] = pathnameArray[2].toLowerCase();
  146. let newPathname = "https://wykop.pl" + pathnameArray.join("/");
  147. consoleX(`Otwieram poprawny adres: ${newPathname}`);
  148. window.location.replace(newPathname);
  149. }
  150. }
  151.  
  152. // # przekierowanie URL http://wykop.pl/#heheszki albo http://wykop.pl/#wykop/@m__b
  153. if (hash.length > 0)
  154. {
  155. let tagWithHash = hash.split("/")[0];
  156. let tagWithoutHash = tagWithHash.slice(1);
  157. let tagNumber = Number.parseInt(tagWithoutHash);
  158.  
  159. if (tagWithoutHash.length > 1 && (tagNumber == "NaN" || tagWithoutHash.length < 9) && tagWithoutHash != "dodaj")
  160. {
  161. if ((tag = getTagFromUrl(tagWithHash))) { }
  162. if ((at = getUserFromUrl(hash))) { }
  163. }
  164. }
  165.  
  166. // @ przekierowanie URL http://wykop.pl/@NadiaFrance albo http://wykop.pl/#wykop/@m__b
  167. if (pathnameArray[1] !== "szukaj" && pathname.length > 2)
  168. {
  169. if (at || (at = getUserFromUrl(pathname))) { }
  170. }
  171.  
  172. if (at || tag) smartRedirectBasedOnUserAndTag(at, tag);
  173.  
  174. })();
  175.  
  176.  
  177.  
  178.  
  179.  
  180.  
  181.  
  182.  
  183. function redirectToSearchUserEntriesInTag(user, tag)
  184. {
  185. window.location.replace(`https://wykop.pl/szukaj/wszystkie/@${user}?tags=${tag}`);
  186. }
  187.  
  188. function redirectToTag(tag)
  189. {
  190. window.location.replace(`https://go.wykopx.pl/#${tag}`);
  191. }
  192.  
  193. function redirectToUser(user)
  194. {
  195. window.location.replace(`https://wykopx.pl/@${user}`);
  196. }
  197.  
  198. function smartRedirectBasedOnUserAndTag(user, tag)
  199. {
  200. consoleX(`Wprowadzono: tag #${tag}, user @${user}`, 1);
  201.  
  202. if (tag && user) redirectToSearchUserEntriesInTag(user, tag)
  203. else if (tag) redirectToTag(tag)
  204. else if (user) redirectToUser(user)
  205. }
  206. // returns 'tag' from /#tag in string
  207. function getTagFromUrl(url, splitSeparator = "/", tagSymbol = "#")
  208. {
  209. let tagArray = url.split(splitSeparator);
  210. for (let element of tagArray)
  211. {
  212. if (element.charAt(0) == "#" || element.charAt(0) == tagSymbol)
  213. {
  214. element = element.slice(1);
  215. return element;
  216. } else if (tagSymbol == "" && (/^[0-9a-zA-Z]/i.test(element.charAt(0))))
  217. {
  218. return element;
  219. } else
  220. {
  221. continue;
  222. }
  223. }
  224. return false;
  225. }
  226.  
  227. function getUserFromUrl(url, splitSeparator = "/", userSymbol = "@")
  228. {
  229. let atArray = url.split(splitSeparator);
  230. for (let element of atArray)
  231. {
  232. if (element.charAt(0) == userSymbol)
  233. {
  234. return element.slice(1);
  235. }
  236. }
  237. return false;
  238. }
  239.  
  240.  
  241.  
  242.  
  243.  
  244.  
  245.  
  246.  
  247.  
  248.  
  249. /* LENNY FACE */
  250. // waitForKeyElements("section.editor", editorAddLennyFace, false);
  251. /*
  252. function editorAddLennyFace(jNode) {
  253. $("section.editor > div.content > textarea", "body").on("focus", function (e) {
  254. //$(this).val("");
  255. //$(this).text("");
  256. $(this).html("");
  257. consoleX($(this).val())
  258. })
  259. let lennyFaceHtml = `<div class="wykopx_lenny_face_row">`;
  260. let lennyArray = [
  261. `( ͡° ͜ʖ ͡°)`,
  262. `( ͡° ʖ̯ ͡°)`,
  263. `( ͡º ͜ʖ͡º)`,
  264. `( ͡°( ͡° ͜ʖ( ͡° ͜ʖ ͡°)ʖ ͡°) ͡°)`,
  265. `(⌐ ͡■ ͜ʖ ͡■)`,
  266. `(╥﹏╥)`,
  267. `(╯︵╰,)`,
  268. `(ʘ‿ʘ)`,
  269. `(。◕‿‿◕。)`,
  270. `ᕙ(⇀‸↼‶)ᕗ`,
  271. `ᕦ(òóˇ)ᕤ`,
  272. `(✌ ゚ ∀ ゚)☞`,
  273. `ʕ•ᴥ•ʔ`,
  274. `ᶘᵒᴥᵒᶅ`,
  275. `(⌒(oo)⌒)`
  276. ]
  277. lennyArray.forEach(function (lenny) {
  278. lennyFaceHtml += `<button title="${ lenny } Lenny Face " class="wykopx_lenny_face_button" data-insert="${ lenny }">${ lenny }</button>`;
  279. });
  280. lennyFaceHtml += `</div>`;
  281. $(lennyFaceHtml).appendTo("section.editor > header");
  282. $("section.editor > header button.wykopx_lenny_face_button").on("click", function (e) {
  283. e.preventDefault();
  284. let x = $(this).parent().parent().parent().find("div.content > textarea").css("opacity", "1");
  285. let textarea = document.querySelector(`div.content textarea`)
  286. let selectionStart = textarea.selectionStart;
  287. let textareaValue = $(textarea).val();
  288. textareaValueWithLenny = textareaValue.slice(0, selectionStart) + $(this).data("insert") + textareaValue.slice(selectionStart);
  289. $(textarea).attr("data-value", textareaValueWithLenny);
  290. $(textarea).html(textareaValueWithLenny);
  291. textarea.innerText = textareaValueWithLenny;
  292. });
  293. }
  294. */
  295.  
  296.  
  297.  
  298.  
  299.  
  300.  
  301.  
  302.  
  303.  
  304.  
  305. /* QUICK SEARCH */
  306.  
  307. /* Edytuj nagłówek tagu, aby przejść na inny tag */
  308.  
  309. function tagHeaderEditableLoad()
  310. {
  311. // consoleX("tagHeaderEditableLoad()", 1)
  312. if (settings.tagHeaderEditable && pathnameArray[1] == "tag")
  313. {
  314. waitForKeyElements(".main-content .main aside.tag-top .content header h1", tagHeaderEditable, false);
  315. }
  316. }
  317.  
  318. function tagHeaderEditable(jNode)
  319. {
  320. consoleX("tagHeaderEditable(jNode)", 1)
  321.  
  322. let tagHeaderEditable = jNode[0];
  323. let originalValue = tagHeaderEditable.textContent.toLowerCase();
  324. tagHeaderEditable.contentEditable = "true";
  325. tagHeaderEditable.className = "wykopx_quick_search";
  326. tagHeaderEditable.setAttribute("data-wykopx-original-value", originalValue);
  327.  
  328. let wykopx_quick_search = document.querySelector(".wykopx_quick_search");
  329. if (originalValue != "")
  330. {
  331. wykopx_quick_search.value = originalValue;
  332. wykopx_quick_search.dispatchEvent(new Event('change'));
  333. wykopx_quick_search.setAttribute("data-wykopx-original-value", originalValue);
  334. }
  335. wykopx_quick_search.addEventListener("blur", eventInsertedTagOrUser);
  336. wykopx_quick_search.addEventListener("keydown", eventInsertedTagOrUser);
  337. }
  338.  
  339. waitForKeyElements("input.wykopx_quick_search", wykopx_quick_search, false);
  340.  
  341. function wykopx_quick_search(jNodeWykopxQuickSearch)
  342. {
  343. const wykopxQuickSearch = jNodeWykopxQuickSearch[0];
  344. wykopxQuickSearch.addEventListener("blur", eventInsertedTagOrUser);
  345. wykopxQuickSearch.addEventListener("keydown", eventInsertedTagOrUser);
  346. }
  347.  
  348. function eventInsertedTagOrUser(e)
  349. {
  350. if (e.type === "blur" || (e.type === "keydown" && e.keyCode == 13)) // out of focus or enter
  351. {
  352. consoleX("blur keydown .wykopx_quick_search");
  353. e.preventDefault();
  354.  
  355. console.log("Type of the element: " + e.target.tagName);
  356. let editedValue;
  357. if (e.target.tagName == "INPUT") editedValue = e.target.value.toLowerCase();
  358. else if (e.target.tagName == "H1") editedValue = e.target.textContent.toLowerCase();
  359.  
  360. if (editedValue != e.target.getAttribute("data-wykopx-original-value"))
  361. {
  362. smartRedirectBasedOnUserAndTag(getUserFromUrl(editedValue, " "), getTagFromUrl(editedValue, " ", ""));
  363. }
  364. }
  365. }
  366.  
  367.  
  368.  
  369. /* RIGHT SIDEBAR - DODAJ LISTE OBSERWOWANYCH TAGÓW */
  370. function addObservedTagsToRightSidebar()
  371. {
  372. let observedTagsArray = [];
  373.  
  374. if (settings.showObservedTagsInRightSidebar)
  375. {
  376. // consoleX("addObservedTagsToRightSidebar()", 1)
  377.  
  378. checkLocalForageupdatedDate(wykopxStorageObservedTags, getObservedTags, settings.showObservedTagsInRightSidebarUpdateInterval * 3600);
  379.  
  380. let section_html = `
  381. <section class="wykopxs wykopx_your_observed_tags custom-sidebar tags-sidebar" data-v-3f88526c="" data-v-89888658="" data-v-5d67dfc3="">
  382. <header data-v-3f88526c="">
  383. <h4 data-v-3f88526c="">Przejdź na #tag lub @profil</h4>
  384. </header>
  385. <div class="content wykopx_quick_search_container" data-v-3f88526c="">
  386. <input type="text" class="wykopx_quick_search" placeholder="#wykopwnowymstylu" title="${promoString}" />
  387. </div>
  388. <header data-v-3f88526c="">
  389. <h4 data-v-3f88526c="">Twoje obserwowane tagi</h4>
  390. </header>
  391. <div class="content" data-v-3f88526c="">
  392. <section class="tags" data-v-89888658="" data-v-3f88526c="" >
  393. <ul data-v-89888658="" data-v-3f88526c="">`;
  394.  
  395. wykopxStorageObservedTags.iterate(function (value, key, iterationNumber)
  396. {
  397. if (key != "storageUpdatedDate")
  398. {
  399. observedTagsArray.push(value)
  400. }
  401. })
  402. .then(function ()
  403. {
  404. if (settings.showObservedTagsAlphabetically)
  405. {
  406. observedTagsArray.sort(); // sortowanie alfabetyczne tagów
  407. }
  408. observedTagsArray.forEach(function (tag)
  409. {
  410. section_html += `
  411. <li data-v-89888658="" data-v-3f88526c="" title="Przejdź na tag #${tag} ${promoString}">
  412. <span data-v-89888658="" data-v-3f88526c="">#</span><a data-v-89888658="" href="https://go.wykopx.pl/#${tag}" class="hybrid" data-v-3f88526c="">${tag}</a>
  413. </li>`;
  414. });
  415.  
  416. section_html += `</ul>
  417. </section>
  418. </div>
  419. </section>`;
  420. // $(section_html).insertBefore(`section.sidebar > section:first-child`);
  421. document.querySelector(`section.sidebar`).insertAdjacentHTML('beforeend', section_html);
  422. })
  423. .catch(function (err) { });
  424. }
  425. }
  426.  
  427.  
  428. async function checkLocalForageupdatedDate(wykopxStorageName, updateStorageFunction, updateIntervalSeconds)
  429. {
  430. consoleX("checkLocalForageupdatedDate", 1)
  431. try
  432. {
  433. let storageUpdatedDate = await wykopxStorageName.getItem("storageUpdatedDate");
  434. if (storageUpdatedDate == null)
  435. {
  436. consoleX("Selected info wasn't downloaded. Updating now...", 1)
  437. updateStorageFunction();
  438. } else
  439. {
  440. const date1 = dayjs()
  441. const date2 = dayjs(storageUpdatedDate)
  442. if (date1.diff(date2, "second") > parseFloat(updateIntervalSeconds))
  443. {
  444. consoleX(`Update interval: ${date1.diff(date2, "second")}s > ${updateIntervalSeconds}s`, 1)
  445. updateStorageFunction();
  446. }
  447. }
  448. } catch (err)
  449. {
  450. console.log(err);
  451. }
  452. }
  453.  
  454. async function getObservedTags()
  455. {
  456. const apiGetObservedTags = `https://wykop.pl/api/v3/profile/users/${user.username}/observed/tags`;
  457. consoleX(`async function getObservedTags(${user.username}`, 1);
  458.  
  459. await fetch(apiGetObservedTags, {
  460. method: "GET", // or 'PUT'
  461. headers: {
  462. "Content-Type": "application/json",
  463. Authorization: "Bearer " + window.localStorage.token,
  464. },
  465. })
  466. .then((response) => response.json())
  467. .then((observedTagsJson) =>
  468. {
  469. if (dev) console.log(observedTagsJson)
  470. const observedTagsArray = observedTagsJson.data;
  471.  
  472. wykopxStorageObservedTags.setItem("storageUpdatedDate", dayjs())
  473.  
  474. observedTagsArray.forEach(function (tag)
  475. {
  476. wykopxStorageObservedTags.setItem(tag.name, tag.name)
  477. .then(function (value)
  478. {
  479. consoleX(`Zapisano do LocalStorage Twój obserwowany tag: #${tag.name}"`);
  480. })
  481. .catch(function (err)
  482. {
  483. consoleX(`getObservedTags = error: ` + err);
  484. });
  485. });
  486. return true;
  487. });
  488. }
  489.  
  490.  
  491.  
  492.  
  493.  
  494.  
  495.  
  496.  
  497.  
  498.  
  499.  
  500.  
  501.  
  502.  
  503.  
  504.  
  505.  
  506.  
  507.  
  508.  
  509.  
  510.  
  511.  
  512.  
  513.  
  514.  
  515.  
  516.  
  517.  
  518.  
  519.  
  520.  
  521. function addActionBoxesToAllEntriesAndComments()
  522. {
  523. // consoleX("addActionBoxesToAllEntriesAndComments()", 1)
  524. $("section.entry").each(function ()
  525. {
  526. addWykopXActionBoxToEntryAndComment($(this))
  527. })
  528. }
  529.  
  530.  
  531.  
  532. async function addWykopXActionBoxToEntryAndComment(jNode)
  533. {
  534. // consoleX(`addWykopXActionBoxToEntryAndComment(jNode)`, 1);
  535. // if (dev) console.log(jNode);
  536.  
  537.  
  538.  
  539. if (settings.enableNotatkowator)
  540. {
  541. var elements = document.querySelectorAll(".wykopx_action_box_usernote");
  542. elements.forEach(function (element)
  543. {
  544. element.parentNode.removeChild(element);
  545. });
  546.  
  547. const comment_id = jNode.context.id.replace("comment-", "");
  548. const $entry_object = $(`#comment-${comment_id}`);
  549. const comment_username = $entry_object.find("> article > header > div.left > a.avatar > span").text();
  550.  
  551.  
  552. if (comment_username.length > 0)
  553. {
  554. let usernoteObject = wykopxStorageNotatkowator.getItem(comment_username);
  555. try
  556. {
  557. usernoteObject = await wykopxStorageNotatkowator.getItem(comment_username);
  558. // usernoteObject == "" -> Notatkowator do wersji 2.14 zapisywał tylko notatkę, bez daty
  559. if (usernoteObject == null || usernoteObject == "")
  560. {
  561. // brak notatki o tym użytkowniku w localforage więc pobieramy z serwera Wykopu
  562. // console.log(`Brak notatki o użytkowniku ${ comment_username }. Sprawdzam na serwerze. Wywołuję getUserNotes( ${ comment_username }, ${ comment_id })`)
  563. getUserNotes(comment_username, comment_id);
  564. }
  565. else
  566. {
  567. const date1 = dayjs();
  568. const date2 = dayjs(usernoteObject.lastUpdate);
  569.  
  570. // consoleX(`Update interval: ${date1.diff(date2, "second")}s <?> ${settings.notatkowatorUpdateInterval * 3600}s`, 1)
  571.  
  572. if (date1.diff(date2, "second") > parseFloat(settings.notatkowatorUpdateInterval * 3600))
  573. {
  574. getUserNotes(comment_username, comment_id);
  575. }
  576. else
  577. {
  578. // consoleX(`Notatkowator wczytał notatkę z LocalStorage. Użytkownik: @${ comment_username }. Notatka: "${ usernote }"`);
  579. displayUserNote(comment_username, usernoteObject.usernote, comment_id)
  580. }
  581. }
  582. } catch (err)
  583. {
  584. console.log(err);
  585. }
  586. }
  587. }
  588.  
  589.  
  590.  
  591.  
  592.  
  593.  
  594.  
  595.  
  596.  
  597. // console.log("comment_id: " + comment_id);
  598. // console.log("$entry_object: ");
  599. // console.log($entry_object);
  600. // console.log("comment_username: " + comment_username);
  601.  
  602. // let html = `<div class="wykopxs wykopx_action_box"
  603. // id="wykopx_action_box-${ comment_id }"
  604. // data-username="${ comment_username }"
  605. // data-comment-id="${ comment_id }"
  606. // data-base-uri="${ jNode.context.baseURI }"
  607. // data-entry-type="entry-subcomment"
  608. // data-parent-comment-id="123456789"
  609. // data-grandparent-comment-id="123456789">
  610. // <div class="wykopx_action_box_username">${ comment_username }</div>
  611. // </div>`;
  612. //jNode.find("> article > header").after(html);
  613. }
  614.  
  615.  
  616. // NOTATKOWATOR 2000
  617.  
  618. async function displayUserNote(username, usernote, comment_id)
  619. {
  620. if (usernote.length > 0)
  621. {
  622. $(`section#comment-${comment_id} > article > header`).after(`<div class="wykopxs wykopx_action_box_usernote">Twoja notatka do <strong>${username}</strong> : <var>${usernote}</var></div>`);
  623. }
  624. }
  625.  
  626. const apiGetNotes = "https://wykop.pl/api/v3/notes/";
  627. async function getUserNotes(username, comment_id)
  628. {
  629. // consoleX(`async function getUserNotes(${username}, ${comment_id})`, 1);
  630.  
  631. const response = await fetch(apiGetNotes + username, {
  632. method: "GET", // or 'PUT'
  633. headers: {
  634. "Content-Type": "application/json",
  635. Authorization: "Bearer " + window.localStorage.token,
  636. },
  637. })
  638. .then((response) => response.json())
  639. .then((user) =>
  640. {
  641. const usernote = user.data.content;
  642. wykopxStorageNotatkowator.setItem(username, { usernote: usernote, lastUpdate: dayjs() })
  643. .then(function (value)
  644. {
  645. // consoleX(`Notatkowator zapisał notatkę o użytkowniku @${ username }: "${ usernote }"`);
  646. displayUserNote(username, usernote, comment_id)
  647.  
  648. })
  649. .catch(function (err)
  650. {
  651. consoleX(`Notatkowator = error: ` + err);
  652. });
  653. return usernote;
  654. });
  655. }
  656.  
  657.  
  658.  
  659.  
  660.  
  661.  
  662.  
  663.  
  664.  
  665.  
  666.  
  667.  
  668. function mirkoukrywaczAddButtons(jNode)
  669. {
  670. // if (dev) consoleX("mirkoukrywaczAddButtons(jNode)", 1);
  671.  
  672. mirkoukrywaczHideAllBlockedElements();
  673.  
  674. let html = `<button class="wykopxs hideThisShit" title="Wykop X - Mirkoukrywacz - Ukryj to na zawsze">Ukryj</button>`;
  675.  
  676. jNode.find(`ul li.right`).prepend(html);
  677. // consoleX(`Dodano przycisk "Ukryj" z Mirkoukrywacza`, 1);
  678.  
  679. $(".hideThisShit").on("click", function ()
  680. {
  681. let type = "unknown";
  682.  
  683. let entry_stream = $(this).closest(".stream");
  684. if (entry_stream.hasClass("microblog")) type = "entry";
  685. else if (entry_stream.hasClass("entry-comments")) type = "entry";
  686. else if (entry_stream.hasClass("entry-subcomments")) type = "entry-subcomments";
  687. else if (entry_stream.hasClass("link-comments")) type = "link-comments";
  688.  
  689. let entry = $(this).closest(".entry");
  690.  
  691. let comment_id = entry.attr("id").split("-")[1];
  692. let username = entry[0].querySelector("a.username span").innerText;
  693. let text = entry[0].querySelector("div.content div.wrapper").innerText.replace(/\n/g, " ");
  694.  
  695. let grandcomment_id = comment_id; /* id nad-komentarza */
  696. if (type == "entry-subcomments")
  697. {
  698. let entry_grandparent = entry.parent().closest(".entry");
  699. grandcomment_id = entry_grandparent.attr("id").split("-")[1];
  700. }
  701.  
  702. /*let link_id = null;
  703. if (type == "link-comments")
  704. {
  705. link_id = link_aside.attr("data-url").split("/")[1]; // /link/7013759/tu-najwiecej-polskich-dzieci-probuje-popelnic-samobojstwo
  706. }*/
  707. if (text.length > 50) text = text.substring(0, 50);
  708. mirkoukrywaczAddNewBlockedElement(comment_id, grandcomment_id, username, text, type);
  709. });
  710. }
  711.  
  712. function mirkoukrywaczAddNewBlockedElement(id, grandcomment_id, username, text, type)
  713. {
  714. wykopxStorageMirkoukrywacz
  715. .setItem(id, {
  716. id,
  717. grandcomment_id,
  718. type,
  719. username,
  720. text,
  721. date: dayjs()
  722. })
  723. .then(function (value)
  724. {
  725. consoleX(`Mirkoukrywacz dodał do listy ukrywanych @${username}: ${text}`);
  726. })
  727. .catch(function (err)
  728. {
  729. consoleX(`mirkoukrywaczAddNewBlockedElement = error: ` + err);
  730. });
  731. mirkoukrywaczHideAllBlockedElements();
  732. }
  733.  
  734. function mirkoukrywaczHideAllBlockedElements()
  735. {
  736. wykopxStorageMirkoukrywacz
  737. .iterate(function (value, key, iterationNumber)
  738. {
  739. $(`section#comment-${key}`).addClass("wykopx_mirkoukrywacz_hide");
  740. })
  741. .then(function () { })
  742. .catch(function (err) { });
  743. }
  744.  
  745. function mirkoukrywaczAppendOneElementToHideList(value, key, iterationNumber = "⭐")
  746. {
  747. if ($(`#wykopx_modal_mirkoukrywacz .wykopx_mirkoukrywacz_list_of_hidden_items #wykopx_mirkoukrywacz_element_${key}`).length == 0)
  748. {
  749. let hidden_element_html = ``;
  750. hidden_element_html += `
  751. <div class="wykopx_mirkoukrywacz_element" id="wykopx_mirkoukrywacz_element_${key}">
  752. <div class="wykopx_mirkoukrywacz_unhide" id="${key}" title="Przestań ukrywać ten element">❌</div>
  753. <div class="wykopx_mirkoukrywacz_lp">${iterationNumber}</div>
  754. <div class="wykopx_mirkoukrywacz_text">${value.text}</div>
  755. <div class="wykopx_mirkoukrywacz_id">${key}</div>
  756. <div class="wykopx_mirkoukrywacz_type">${value.type}</div>
  757. <div class="wykopx_mirkoukrywacz_date">${dayjs(value.date).format("YYYY-MM-DD HH:mm")}</div>
  758. </div>`;
  759. $("#wykopx_modal_mirkoukrywacz .wykopx_mirkoukrywacz_list_of_hidden_items").append(hidden_element_html);
  760. $(".wykopx_mirkoukrywacz_unhide").on("click", function ()
  761. {
  762. mirkoukrywaczRemoveHiddenElement($(this).attr("id"));
  763. });
  764. }
  765. }
  766.  
  767. function mirkoukrywaczRefreshHideList()
  768. {
  769. wykopxStorageMirkoukrywacz
  770. .iterate(function (value, key, iterationNumber)
  771. {
  772. mirkoukrywaczAppendOneElementToHideList(value, key, iterationNumber);
  773. })
  774. .then(function () { })
  775. .catch(function (err) { });
  776. }
  777.  
  778. function mirkoukrywaczBuildListOfHiddenElements()
  779. {
  780. let html = `
  781. <div class="wykopxs wykopx_modal" id="wykopx_modal_mirkoukrywacz">
  782. <div class="wykopx_modal-content">
  783. <aside class="wykopxs_info_bar wykopx_hide_this_if_stylus_is_installed">
  784. Masz już działający skrypt Wykop XS. Aby Mirkoukrywacz działał, musisz zainstalować i włączyć w Stylusie <a href="http://wiki.wykopx.pl" target="_blank">Wykop X</a>
  785. </aside>
  786.  
  787. <aside class="wykopxs wykopx_modal_mirkoukrywacz_is_turned_off wykopx_hide_this_if_mirkoukrywanie_is_turned_on">
  788. Wykop XS oraz Wykop X są zainstalowane poprawnie, ale Mirkoukrywacz jest wyłączony. Aby Mirkoukrywacz działał, włącz go w ustawieniach Stylusa. <a href="https://github.com/wykopx/WykopX/wiki/Extra#mirkoukrywacz" target="_blank">Zobacz instrukcję obsługi Mirkoukrywacza</a>
  789. </aside>
  790. <header class="wykopxs">
  791. <span>Mirkoukrywacz:</span>
  792. <span>Lista ukrytych elementów</span>
  793. </header>
  794. <section class="wykopxs wykopx_mirkoukrywacz_list_of_hidden_items">
  795. <span class="wykopx_mirkoukrywacz_hidden_list_is_empty">
  796. Żadne treści nie zostały jeszcze zaznaczone do ukrycia
  797. </span>
  798. </section>
  799. </div>
  800. </div>`;
  801.  
  802.  
  803. // $("body").prepend(html);
  804. document.body.insertAdjacentHTML('afterbegin', html);
  805.  
  806. createNewProfileDropdownMenuItem(
  807. {
  808. text: `Wykop X - Mirkoukrywacz`,
  809. title: "Wykop X - lista elementów ukrytych przez Mirkoukrywacz",
  810. className: `mirkoukrywacz`,
  811. id: "mirkoukrywacz_open_modal_button",
  812. url: null,
  813. target: null,
  814. icon: null,
  815. number: null
  816. });
  817.  
  818. let wykopx_modal_mirkoukrywacz = document.getElementById("wykopx_modal_mirkoukrywacz");
  819. let mirkoukrywacz_open_modal_button = document.getElementById("mirkoukrywacz_open_modal_button");
  820. //var span = document.getElementsByClassName("wykopx_close")[0];
  821. mirkoukrywacz_open_modal_button.onclick = function ()
  822. {
  823. mirkoukrywaczRefreshHideList();
  824. wykopx_modal_mirkoukrywacz.style.display = "block";
  825. };
  826. /* span.onclick = function() {
  827. wykopx_modal_mirkoukrywacz.style.display = "none";
  828. }*/
  829. window.onclick = function (event)
  830. {
  831. if (event.target == wykopx_modal_mirkoukrywacz)
  832. {
  833. wykopx_modal_mirkoukrywacz.style.display = "none";
  834. }
  835. };
  836. }
  837.  
  838. function mirkoukrywaczRemoveHiddenElement(id)
  839. {
  840. wykopxStorageMirkoukrywacz
  841. .removeItem(id)
  842. .then(function ()
  843. {
  844. $(`#wykopx_mirkoukrywacz_element_${id}`).remove();
  845. })
  846. .catch(function (err)
  847. {
  848. console.log(err);
  849. });
  850. }
  851.  
  852.  
  853.  
  854. /* Automatycznie "pokaż całość" długich treści */
  855. function autoOpenMoreContentEverywhere()
  856. {
  857. if (wykopxSettings.getPropertyValue("--autoOpenMoreContentEverywhere"))
  858. {
  859. let numberOfShowMoreButtons = $("div.wrapper button.more").length;
  860. if (numberOfShowMoreButtons > 0)
  861. {
  862. $("div.wrapper button.more").click();
  863. consoleX(`Automatycznie rozwinięto ${numberOfShowMoreButtons} długich wpisów i komentarzy`);
  864. }
  865. }
  866. }
  867. /* Kliknięcie w logo wykopu odświeża stronę */
  868. function refreshOrRedirectOnHomeButtonClick()
  869. {
  870. if (wykopxSettings.getPropertyValue("--refreshOrRedirectOnHomeButtonClick"))
  871. {
  872. refreshOrRedirectOnButtonClick("header.header div.left > a", "/");
  873. }
  874. }
  875. /* Kliknięcie w Mikroblog odświeża stronę */
  876. function refreshOrRedirectOnMicroblogButtonClick()
  877. {
  878. if (wykopxSettings.getPropertyValue("--refreshOrRedirectOnMicroblogButtonClick"))
  879. {
  880. refreshOrRedirectOnButtonClick(`nav.main ul li a[href="/mikroblog"]`, "/mikroblog");
  881. }
  882. }
  883.  
  884. function refreshOrRedirectOnButtonClick(selector, pathToRefresh = "/")
  885. {
  886. $(document).on("click", selector, function ()
  887. {
  888. let pathname = new URL(document.URL).pathname;
  889. if (pathname == pathToRefresh) window.location.reload();
  890. else window.location.href = pathToRefresh;
  891. });
  892. }
  893.  
  894. /* add micro button on left menu open, 2 versions
  895. $(`header.header > div.left > button`).on("click", function(){
  896. //categoryRedirectToMicroblogButton();
  897. }); */
  898.  
  899.  
  900.  
  901. // przyciski MIRKO w kategoriach
  902. function categoryRedirectToMicroblogButton()
  903. {
  904. consoleX("categoryRedirectToMicroblogButton()", 1);
  905. let categoryRedirectToMicroblogButtonFilter = wykopxSettings.getPropertyValue("--categoryRedirectToMicroblogButtonFilter");
  906. categoryRedirectToMicroblogButtonFilter = categoryRedirectToMicroblogButtonFilter.replaceAll("_", "/").replaceAll(" ", "");
  907.  
  908. if ($(`section.links div.content ul.categories .wykopx_categories_microblog_a`).length == 0)
  909. {
  910. $(`section.links div.content ul.categories li`).each(function (index)
  911. {
  912. const kategoria = $(this).context.outerText;
  913. let href = "";
  914. switch (kategoria)
  915. {
  916. case "Ciekawostki":
  917. href = "/k/ciekawostki";
  918. break;
  919. case "Informacje":
  920. href = "/k/informacje";
  921. break;
  922. case "Rozrywka":
  923. href = "/k/rozrywka";
  924. break;
  925. case "Sport":
  926. href = "/k/sport";
  927. break;
  928. case "Motoryzacja":
  929. href = "/k/motoryzacja";
  930. break;
  931. case "Technologia":
  932. href = "/k/technologia";
  933. break;
  934. case "Ukraina":
  935. href = "/k/ukraina";
  936. break;
  937. case "Gospodarka":
  938. href = "/k/gospodarka";
  939. break;
  940. case "Podróże":
  941. href = "/k/podroze";
  942. break;
  943. default:
  944. null;
  945. }
  946. href += categoryRedirectToMicroblogButtonFilter;
  947. const microblogButtonHtml = `<li class="wykopxs wykopx_categories_microblog_li"><a class="wykopx_categories_microblog_a" href="${href}">M</a></li>`;
  948. $(this).after(microblogButtonHtml);
  949. });
  950. }
  951.  
  952. if ($(`section.links div.content ul.buckets .wykopx_categories_microblog_a`).length == 0)
  953. {
  954. $(`section.links div.content ul.buckets li`).each(function (index)
  955. {
  956. let href = $(this).children("a").attr("href");
  957. href = href.replaceAll("/mikroblog", "");
  958. href += categoryRedirectToMicroblogButtonFilter;
  959. const microblogButtonHtml = `<li class="wykopxs wykopx_categories_microblog_li"><a class="wykopxs wykopx_categories_microblog_a" href="${href}">M</a></li>`;
  960. $(this).after(microblogButtonHtml);
  961. });
  962. }
  963. }
  964.  
  965. // otwieranie powiadomienia SPM w nowejkacie
  966. if (wykopxSettings.getPropertyValue("--middleClickOpensNotificationsInNewTab"))
  967. {
  968. /* środkowy przycisk na powiadomieniu otwiera je w nowej karcie */
  969. $("body").on("mousedown", "section.notifications-stream section.notify", function (e1)
  970. {
  971. if (e1.which === 2)
  972. {
  973. $(this).one("mouseup", function (e2)
  974. {
  975. if (e1.target === e2.target)
  976. {
  977. let url_to_open = $(this).find(`a[href^="/wpis/"`).attr("href");
  978. let tab_handle = window.open(url_to_open, "_blank"); // tab_handle.blur(); //window.focus();
  979. var e3 = $.event.fix(e2);
  980. e3.type = "middleclick";
  981. $(e2.target).trigger(e3);
  982. }
  983. });
  984. }
  985. });
  986. }
  987.  
  988. // otwieranie obrazka w nowej karcie klikając wybrany przycisk myszy
  989. const mouseClickOpensImageInNewTab = wykopxSettings.getPropertyValue("--mouseClickOpensImageInNewTab").replaceAll(" ", "");
  990.  
  991. if (mouseClickOpensImageInNewTab != "nie_otwieraj")
  992. {
  993. let detected_event_click;
  994. let event_trigger_type;
  995.  
  996. if (mouseClickOpensImageInNewTab == "lewy_przycisk_myszy")
  997. {
  998. detected_event_click = 1;
  999. event_trigger_type = "wykopx_leftclick";
  1000. }
  1001. if (mouseClickOpensImageInNewTab == "srodkowy_przycisk_myszy")
  1002. {
  1003. detected_event_click = 2;
  1004. event_trigger_type = "wykopx_middleclick";
  1005. }
  1006. if (mouseClickOpensImageInNewTab == "prawy_przycisk_myszy")
  1007. {
  1008. detected_event_click = 3;
  1009. event_trigger_type = "wykopx_rightclick";
  1010. }
  1011. $("body").on("mousedown", "section.entry section.entry-photo", function (e1)
  1012. {
  1013. e1.preventDefault();
  1014. consoleX("Kliknięto przycisk myszy: " + e1.which, 1);
  1015. if (e1.which === detected_event_click)
  1016. {
  1017. $(this).one("mouseup", function (e2)
  1018. {
  1019. e2.preventDefault();
  1020. if (e1.target === e2.target)
  1021. {
  1022. let url_to_open = $(this).find(`a[href^="https://wykop.pl/cdn/"`).attr("href");
  1023. var handle = window.open(url_to_open, "_blank");
  1024. var e3 = $.event.fix(e2);
  1025. e3.type = event_trigger_type;
  1026. $(e2.target).trigger(e3);
  1027. }
  1028. });
  1029. }
  1030. });
  1031. //$(document).on("wykopx_leftclick", function (e) {});
  1032. }
  1033.  
  1034.  
  1035.  
  1036.  
  1037.  
  1038.  
  1039.  
  1040.  
  1041.  
  1042.  
  1043.  
  1044. // WYKOP X PROMO
  1045. const adjacentCode = `
  1046. <style>
  1047. /* wykop x promo ON */
  1048. .wykopx_promo_banner { width: 100%; display: block!important; height: 300px!important; background: url('https://raw.githubusercontent.com/wykopx/wykopx-png/main/promo-images/wykopx-install-sidebar-day.png'); }
  1049. [data-night-mode] .wykopx_promo_banner { background: url('https://raw.githubusercontent.com/wykopx/wykopx-png/main/promo-images/wykopx-install-sidebar-night.png'); }
  1050. /* hide wykopxs features if wykopx is not installed */
  1051. .wykopxs { display: none; }
  1052. /* wykopxs_promo OFF */
  1053. body div.main-content section > section.sidebar:after,
  1054. section.editor.expand section.inline-autocomplete section.inline-autocomplete-stream div.content:after,
  1055. header.header div.right section.search-input section.inline-autocomplete section.inline-autocomplete-stream div.content:after
  1056. { display: none!important; }
  1057. /* wykopxs new version available, mirkoukrywacz modal info bar */
  1058. .wykopxs_info_bar
  1059. { display: flex; align-items: center;border-bottom: 1px solid rgba(128, 128, 128, 0.2); color: rgba(128, 128, 128, 1); padding: 8px 20px; font-size: 14px; }
  1060. aside.wykopxs_info_bar a
  1061. { display: inline-block;background: rgb(0,85,0);color: white;display: inline-block;background-color: #005200;padding: .3em 0.7em;margin: 0 10px;}
  1062. aside.wykopxs_info_bar a:hover
  1063. { background: rgba(0,85,0, 0.7); text-decoration: none!important; }
  1064. aside.wykopxs_info_bar footer
  1065. { opacity: 0.6; margin-left: auto; }
  1066. @media (max-width: 640px)
  1067. {
  1068. body > section > aside.wykopxs_info_bar { flex-direction: column; padding-top: 30px; }
  1069. body > section > aside.wykopxs_info_bar a { margin: 11px; padding: 14px; width: 100%; text-align: center;}
  1070. body > section > aside.wykopxs_info_bar span.wykopxs_new_version_second,
  1071. body > section > aside.wykopxs_info_bar > footer { display: none; }
  1072. }
  1073.  
  1074.  
  1075.  
  1076. body > section > header.header > div.left > nav.main > ul > li
  1077. {
  1078. white-space: nowrap!important;
  1079. height: calc(100% - 12px)!important;
  1080. position: relative!important;
  1081. }
  1082. body > section > header.header > div.left > nav.main > ul > li > a
  1083. {
  1084. text-decoration: none!important;
  1085. height: 100%!important;
  1086. display: flex!important;
  1087. flex-direction: column!important;
  1088. justify-content: center!important;
  1089. position: relative!important;
  1090. font-weight: 400!important;
  1091. padding: 0 12px!important;
  1092. }
  1093. body > section > header.header > div.left > nav.main > ul > li:hover a
  1094. {
  1095. background: rgba(255,255,255, 0.2)!important;
  1096. }
  1097. body > section > header.header > div.left > nav.main > ul > li > a > span
  1098. {
  1099. color: var(--blackish)!important;
  1100. white-space: nowrap!important;
  1101. }
  1102. </style>`;
  1103.  
  1104. document.head.insertAdjacentHTML("beforeend", adjacentCode);
  1105.  
  1106.  
  1107. /* checking for new versions */
  1108.  
  1109.  
  1110.  
  1111.  
  1112. async function checkVersionForUpdates()
  1113. {
  1114. if (!dev) console.clear();
  1115. consoleX("Sprawdzanie aktualizacji Wykop X Style i Wykop XS...");
  1116.  
  1117. $.get(`https://raw.githubusercontent.com/wykopx/wykopx-png/main/old-versions/wykopxs.${currentVersion}.gif`)
  1118. .done(function ()
  1119. {
  1120. addWykopXSNewVersionAvailableToast(); // new version available
  1121. consoleX("Hej, jest nowa wersja skryptu Wykop XS. Wejdź na http://script.wykopx.pl i zaktualizuj go");
  1122. })
  1123. .fail(function ()
  1124. {
  1125. consoleX("Masz najnowszą wersję skryptu Wykop XS v." + currentVersion);
  1126. });
  1127.  
  1128. $.get(`https://raw.githubusercontent.com/wykopx/wykopx-png/main/old-versions/wykopxstyle.${settings.WykopXStyleVersion}.gif`)
  1129. .done(function ()
  1130. {
  1131. addWykopXStyleNewVersionAvailableToast(); // new version available
  1132. consoleX("Hej, jest dostępna nowa wersja styli Wykop X Style. Wejdź na http://style.wykopx.pl i zaktualizuj je");
  1133. })
  1134. .fail(function ()
  1135. {
  1136. consoleX("Masz najnowszą wersję styli Wykop X Style v." + settings.WykopXStyleVersion);
  1137. });
  1138. }
  1139.  
  1140.  
  1141.  
  1142. function hideWykopXSPromo()
  1143. {
  1144. //$(`body div.main-content section > section.sidebar:after`).css("display: none!important;");
  1145. let style = document.createElement('style');
  1146. style.innerHTML = `body div.main-content section > section.sidebar:after { display: none !important; }`;
  1147. document.head.appendChild(style);
  1148. }
  1149.  
  1150. function addWykopXPromoBanner()
  1151. {
  1152. let targetElement = document.querySelector('section.sidebar > footer');
  1153. if (targetElement)
  1154. {
  1155. let wykopxpromo = document.createElement('section');
  1156. wykopxpromo.classList.add("wykopx_promo", "wykopx_promo_banner");
  1157. targetElement.parentNode.insertBefore(wykopxpromo, targetElement);
  1158. }
  1159. }
  1160.  
  1161. function addWykopXSNewVersionAvailableToast()
  1162. {
  1163. // <a href="http://script.wykopx.pl" target="_blank" style="color: #fff!important;">
  1164.  
  1165. let wykopxsnewversionavailabletoast = `
  1166. <aside class="wykopxs_new_version wykopxs_info_bar">
  1167. <span class="wykopxs_new_version_first">
  1168. Dostępna jest nowa wersja skryptu Wykop XS.
  1169. </span>
  1170. <a href="https://greasyfork.org/scripts/458860-wykop-xs/code/Wykop%20XS.user.js" target="_blank" style="color: #fff!important;">
  1171. Zaktualizuj Wykop XS
  1172. </a>
  1173. <span class="wykopxs_new_version_second">
  1174. do najnowszej wersji
  1175. </span>
  1176. <footer>
  1177. Twoja wersja Wykop XS to v.${currentVersion}
  1178. </footer>
  1179. </aside>`;
  1180. $(wykopxsnewversionavailabletoast).insertAfter(`body > section > header.header`);
  1181. }
  1182.  
  1183. function addWykopXStyleNewVersionAvailableToast()
  1184. {
  1185. let wykopxstylenewversionavailabletoast = `
  1186. <aside class="wykopxs_new_version wykopxs_info_bar">
  1187. <span class="wykopxs_new_version_first">
  1188. Dostępna jest nowa wersja styli Wykop X Style.
  1189. </span>
  1190. <a href="https://userstyles.world/style/8174/wykop-x-style" target="_blank" style="color: #fff!important;">
  1191. Zaktualizuj Wykop X Style
  1192. </a>
  1193. <span class="wykopxs_new_version_second">
  1194. do najnowszej wersji
  1195. </span>
  1196. <footer>
  1197. Twoja wersja Wykop X Style to v.${settings.WykopXStyleVersion}
  1198. </footer>
  1199. </aside>`;
  1200. $(wykopxstylenewversionavailabletoast).insertAfter(`body > section > header.header`);
  1201. }
  1202.  
  1203.  
  1204.  
  1205.  
  1206.  
  1207.  
  1208.  
  1209.  
  1210.  
  1211.  
  1212. const unreadNotifications = {
  1213. tags: 0,
  1214. tags_new_entry_with_observed_tag: 0,
  1215. tags_new_link_with_observed_tag: 0,
  1216. entries: 0,
  1217. pm: 0,
  1218. total: 0,
  1219. };
  1220.  
  1221.  
  1222. // ZLICZA NOWE POWIADOMIENIA Z MENU OD 1 DO 5+
  1223. function countNumberOfNotificationsOnDesktop()
  1224. {
  1225. $("header .right ul li.dropdown").removeClass("unread_5").removeClass("unread_4").removeClass("unread_3").removeClass("unread_2").removeClass("unread_1");
  1226.  
  1227. $("header .right ul li.dropdown:has(a.new)").each(function (index, value)
  1228. {
  1229. const lastWord = $(this).attr("class").split(" ").pop();
  1230. let numberOfNotifications = 0;
  1231. // liczba powiadomień o tagach / wołaniach
  1232. $(this)
  1233. .find(".notify:not(.read)")
  1234. .each(function (index, value)
  1235. {
  1236. ++numberOfNotifications;
  1237.  
  1238. $(this).addClass(`unread_${numberOfNotifications}`);
  1239.  
  1240. if (lastWord == "tags")
  1241. {
  1242. ++unreadNotifications["total"];
  1243.  
  1244. if ($(this).find(`div.content p.new-entry-with-observed-tag`).length > 0)
  1245. {
  1246. ++unreadNotifications["tags_new_entry_with_observed_tag"];
  1247. ++unreadNotifications["tags"];
  1248. ++unreadNotifications["total"];
  1249. }
  1250. else if ($(this).find(`div.content p.new-link-with-observed-tag`).length > 0)
  1251. {
  1252. ++unreadNotifications["tags_new_link_with_observed_tag"];
  1253. ++unreadNotifications["tags"];
  1254. ++unreadNotifications["total"];
  1255. }
  1256. } else if (lastWord == "entries")
  1257. {
  1258. ++unreadNotifications["entries"];
  1259. ++unreadNotifications["total"];
  1260. }
  1261. })
  1262. .parents(`.notifications.dropdown`)
  1263. .addClass(`unread_${numberOfNotifications}`);
  1264. });
  1265. if (unreadNotifications["tags"] > 0)
  1266. {
  1267. consoleX(`Liczba nowych powiadomień z obserwowanych tagów: ${unreadNotifications["tags"]} (w tym ${unreadNotifications["tags_new_entry_with_observed_tag"]} z wpisów i ${unreadNotifications["tags_new_link_with_observed_tag"]} ze znalezisk)`);
  1268. }
  1269. if (unreadNotifications["entries"] > 0)
  1270. {
  1271. consoleX(`Liczba nowych zawołań: ${unreadNotifications["entries"]}`);
  1272. }
  1273.  
  1274. $("header .right ul li.pm.dropdown:has(a.new)").each(function (index, value)
  1275. {
  1276. let numberOfNotifications = 0; // liczba powiadomień o wiadomościach PM
  1277.  
  1278. $(this)
  1279. .find(".item.unread")
  1280. .each(function (index, value)
  1281. {
  1282. ++numberOfNotifications;
  1283. ++unreadNotifications["total"];
  1284. $(this).addClass(`unread_${numberOfNotifications}`);
  1285. })
  1286. .parents(`.pm.dropdown`)
  1287. .addClass(`unread_${numberOfNotifications}`);
  1288. unreadNotifications["pm"] = numberOfNotifications;
  1289. consoleX(`Liczba nowych wiadomości: ${unreadNotifications["pm"]}`);
  1290. });
  1291.  
  1292. if (unreadNotifications.tags > 0)
  1293. {
  1294. createNewProfileDropdownMenuItem(
  1295. {
  1296. text: `Powiadomienia z #tagów: (${unreadNotifications.tags})`,
  1297. title: "Masz nowe powiadomienia z obserwowanych #tagów",
  1298. className: `wykopx_notifications_tags`,
  1299. id: undefined,
  1300. url: "/powiadomienia/tagi",
  1301. target: "_self",
  1302. icon: null,
  1303. number: unreadNotifications.tags
  1304. })
  1305. }
  1306. if (unreadNotifications.entries > 0)
  1307. {
  1308. createNewProfileDropdownMenuItem(
  1309. {
  1310. text: `Zawołania w komentarzach: (${unreadNotifications.entries})`,
  1311. title: "Zawołano Cię w komentarzu",
  1312. className: `wykopx_notifications_entries`,
  1313. id: undefined,
  1314. url: "/powiadomienia/moje",
  1315. target: "_self",
  1316. icon: null,
  1317. number: unreadNotifications.entries
  1318. })
  1319. }
  1320. if (unreadNotifications.pm > 0)
  1321. {
  1322. createNewProfileDropdownMenuItem(
  1323. {
  1324. text: `Nowe wiadomości: (${unreadNotifications.pm})`,
  1325. title: "Masz nowe, nieprzeczytane wiadomości prywatne",
  1326. className: `wykopx_notifications_pm`,
  1327. id: undefined,
  1328. url: "/wiadomosci",
  1329. target: "_self",
  1330. icon: null,
  1331. number: unreadNotifications.pm
  1332. })
  1333. }
  1334.  
  1335. executeTabAndFaviconChanges();
  1336. }
  1337.  
  1338.  
  1339. function addWykopXButtonsToNavBar()
  1340. {
  1341. if (settings.myWykopInTopNavJS == true)
  1342. {
  1343. createNewNavBarButton({
  1344. position: "left",
  1345. text: "Mój Wykop",
  1346. title: `Mój Wykop ${promoString}`,
  1347. class: "mywykop", // wykopx_mywykop_li
  1348. hideWithoutXStyle: true,
  1349. url: "/obserwowane",
  1350. target: "_self",
  1351. icon: null,
  1352. numer: null
  1353. })
  1354. }
  1355. if (settings.hitsInTopNavJS == true)
  1356. {
  1357. createNewNavBarButton({
  1358. position: "left",
  1359. text: "Hity",
  1360. title: `Hity ${promoString}`,
  1361. class: "hits",
  1362. hideWithoutXStyle: true,
  1363. url: "/hity",
  1364. target: "_self",
  1365. icon: null,
  1366. numer: null
  1367. })
  1368. }
  1369. if (settings.favoritesInTopNavJS == true)
  1370. {
  1371. createNewNavBarButton({
  1372. position: "left",
  1373. text: "Ulubione",
  1374. title: `Ulubione ${promoString}`,
  1375. class: "favorites",
  1376. hideWithoutXStyle: true,
  1377. url: "/ulubione",
  1378. target: "_self",
  1379. icon: null,
  1380. numer: null
  1381. })
  1382. }
  1383. if (settings.addNewLinkInTopNavJS == true)
  1384. {
  1385. createNewNavBarButton({
  1386. position: "left",
  1387. text: "+",
  1388. title: `Dodaj nowe Znalezisko ${promoString}`,
  1389. class: ["add_new_link", "plus"], // wykopx_add_new_link_li wykopx_plus_li // a > wykopx_add_new_link wykopx_plus_button
  1390. hideWithoutXStyle: true,
  1391. url: "/dodaj-link",
  1392. target: "_self",
  1393. icon: null,
  1394. numer: null,
  1395. insertAfter: `li:has(a[href="/wykopalisko"])`
  1396. })
  1397. }
  1398.  
  1399. if (settings.addNewEntryInTopNavJS == true)
  1400. {
  1401. createNewNavBarButton({
  1402. position: "left",
  1403. text: "+",
  1404. title: `Dodaj nowy wpis na Mirko ${promoString}`,
  1405. class: ["add_new_entry", "plus"], // wykopx_add_new_entry_li wykopx_plus_li // a > wykopx_add_new_entry wykopx_plus_button
  1406. hideWithoutXStyle: true,
  1407. url: "/mikroblog/#dodaj",
  1408. target: "_self",
  1409. icon: null,
  1410. numer: null,
  1411. insertAfter: `li:has(a[href="/mikroblog"])`
  1412. })
  1413. }
  1414.  
  1415. createNewNavBarButton({
  1416. position: "left",
  1417. text: "Zainstaluj Wykop X Style",
  1418. title: `Zainstaluj style CSS "𝗪𝘆𝗸𝗼𝗽 𝗫" w rozszerzeniu Stylus i odkryj dziesiątki dodatkowych funkcji Wykopu. Masz już zainstalowane rozszerzenie `,
  1419. class: ["promo", "install_wykopx"], // wykopx_promo (ukrywane przez X Style) wykopx_install_wykopx_li hybrid" | a > wykopx_promo wykopx_install_wykopx_button hybrid
  1420. hideWithoutXStyle: false,
  1421. url: "https://bit.ly/wykopx_install_wykopx_button",
  1422. target: "_blank",
  1423. icon: null,
  1424. numer: null
  1425. })
  1426.  
  1427.  
  1428. }
  1429.  
  1430.  
  1431.  
  1432.  
  1433.  
  1434. // options: { position: "left", "right", "center",
  1435. // text: ``, title: ``, : ``, id: null, url: null,
  1436. // target: "_blank", icon: null, number: null,
  1437. // insertAfter: selectorQuery, showWithoutXStyle: true
  1438. function createNewNavBarButton(options)
  1439. {
  1440. let nav_ul;
  1441.  
  1442. if (options.position == "left") nav_ul = document.querySelector("body header div.left nav.main ul");
  1443. else if (options.position == "center") nav_ul = document.querySelector("body header div.right nav aside"); // doodle
  1444. /*<aside title="Komentuj ważne wydarzenia" class="doodle">
  1445. <div class="v-portal"></div>
  1446. <a href="/tag/sejm/wpisy">
  1447. <div class="vue-portal-target">
  1448. <img src="/static/img/svg/doodles/gov.svg" alt="">
  1449. Komentuj ważne wydarzenia
  1450. </div>
  1451. </a>
  1452. </aside>*/
  1453. else nav_ul = document.querySelector("body header div.right nav ul");
  1454.  
  1455. if (nav_ul) // brak na wersji mobilnej
  1456. {
  1457. let nav_ul_li = nav_ul.querySelector(`li.wykopx_${options.class}_li`);
  1458. if (!nav_ul_li)
  1459. {
  1460. nav_ul_li = document.createElement("li");
  1461. if (options.hideWithoutXStyle == true) nav_ul_li.classList.add("wykopxs");
  1462. addWykopXSClassesToElement(nav_ul_li, options.class, "li") // class="wykopx_aaaaaa_li"
  1463.  
  1464. let nav_ul_li_a = document.createElement("a");
  1465. if (options.url) nav_ul_li_a.setAttribute("href", options.url);
  1466. if (options.href) nav_ul_li_a.setAttribute("href", options.href);
  1467. if (options.target) nav_ul_li_a.setAttribute("target", options.target);
  1468. if (options.title) nav_ul_li_a.setAttribute("title", options.title);
  1469. nav_ul_li_a.classList.add("hybrid");
  1470. if (options.class) addWykopXSClassesToElement(nav_ul_li_a, options.class);
  1471.  
  1472.  
  1473. let nav_ul_li_a_span = document.createElement("span");
  1474. nav_ul_li_a_span.textContent = options.text;
  1475.  
  1476. nav_ul_li_a.appendChild(nav_ul_li_a_span);
  1477. nav_ul_li.appendChild(nav_ul_li_a);
  1478.  
  1479. if (options.insertAfter != null)
  1480. {
  1481. let section = nav_ul.querySelector(options.insertAfter);
  1482. section.insertAdjacentElement('afterend', nav_ul_li);
  1483. }
  1484. else
  1485. {
  1486. nav_ul.appendChild(nav_ul_li);
  1487. }
  1488. }
  1489. }
  1490.  
  1491. }
  1492.  
  1493.  
  1494.  
  1495.  
  1496. // returnWykopXSClassesString("klasa", "li") >> class="wykopx_klasa_li"
  1497. // returnWykopXSClassesString(["klasa1", "klasa2"]) class="wykopx_klasa1 wykopx_klasa2"
  1498. function addWykopXSClassesToElement(element, inputClassOrArray, suffix = null)
  1499. {
  1500. if (inputClassOrArray)
  1501. {
  1502. if (typeof inputClassOrArray === 'string')
  1503. {
  1504. element.classList.add(`wykopx_${inputClassOrArray}${suffix != null ? "_" + suffix : ""}`);
  1505. }
  1506. else if (Array.isArray(inputClassOrArray) && inputClassOrArray.every(item => typeof item === 'string'))
  1507. {
  1508. inputClassOrArray.map(item =>
  1509. {
  1510. element.classList.add(`wykopx_${item}${suffix != null ? "_" + suffix : ""}`);
  1511. });
  1512. }
  1513. }
  1514.  
  1515. }
  1516.  
  1517. // options: { text: null, title: null, className: ``, id: null, url: null, target: "_blank", icon: null, number: null
  1518. function createNewProfileDropdownMenuItem(options)
  1519. {
  1520. let dropdownBody = document.querySelector("body header div.right nav ul li.account.dropdown ul.dropdown-body");
  1521. if (dropdownBody)
  1522. {
  1523. let dropdownItem = dropdownBody.querySelector(`li.${options.className}_li`);
  1524.  
  1525. if (!dropdownItem)
  1526. {
  1527. // dropdownItem.remove();
  1528. let clonedDropdownItem = dropdownBody.querySelector("li.settings").cloneNode(true);
  1529. if (options.className)
  1530. {
  1531. clonedDropdownItem.setAttribute("class", `${options.className}_li`);
  1532.  
  1533. let clonedDropdownItemLink = clonedDropdownItem.querySelector("a");
  1534. clonedDropdownItemLink.setAttribute("class", `${options.className}_button`);
  1535.  
  1536. if (options.url) clonedDropdownItemLink.setAttribute("href", options.url);
  1537. if (options.href) clonedDropdownItemLink.setAttribute("href", options.href);
  1538. if (options.target) clonedDropdownItemLink.setAttribute("target", options.target);
  1539. if (options.id) clonedDropdownItemLink.setAttribute("id", options.id);
  1540. if (options.title) clonedDropdownItemLink.setAttribute("title", options.title);
  1541. if (options.text) clonedDropdownItemLink.textContent = options.text;
  1542. dropdownBody.appendChild(clonedDropdownItem);
  1543. }
  1544. }
  1545. }
  1546. else // niezalogowany brak menu, zamiast tego przyciski Zaloguj/Zarejestruj
  1547. {
  1548. createNewNavBarButton({
  1549. position: "left",
  1550. text: options.text,
  1551. title: options.title,
  1552. class: options.className,
  1553. hideWithoutXStyle: options.hideWithoutXStyle,
  1554. url: options.url,
  1555. target: options.target,
  1556. icon: options.icon,
  1557. numer: options.numer
  1558. })
  1559. }
  1560. }
  1561.  
  1562.  
  1563.  
  1564.  
  1565. function addNotificationSummaryButtonToNavBar()
  1566. {
  1567. let mojeLubTagi = $("header .right ul li.account.dropdown ul.dropdown-body li.notifications.new a").attr("href");
  1568. let wykopx_notification_summary_url = "/powiadomienia/";
  1569. if (typeof mojeLubTagi == "string")
  1570. {
  1571. mojeLubTagi = mojeLubTagi.split("/").pop();
  1572.  
  1573. if (mojeLubTagi == "tagi")
  1574. {
  1575. createNewProfileDropdownMenuItem(
  1576. {
  1577. text: `Powiadomienia z #tagów`,
  1578. title: "Masz nowe powiadomienia z obserwowanych #tagów",
  1579. className: `wykopx_notifications_tags`,
  1580. id: undefined,
  1581. url: "/powiadomienia/tagi",
  1582. target: "_self",
  1583. icon: null,
  1584. number: null
  1585. })
  1586. }
  1587. if (mojeLubTagi == "moje")
  1588. {
  1589. createNewProfileDropdownMenuItem(
  1590. {
  1591. text: `Powiadomienia z #tagów`,
  1592. title: "Masz nowe powiadomienia z obserwowanych #tagów",
  1593. className: `wykopx_notifications_tags`,
  1594. id: undefined,
  1595. url: "/powiadomienia/tagi",
  1596. target: "_self",
  1597. icon: null,
  1598. number: null
  1599. })
  1600. createNewProfileDropdownMenuItem(
  1601. {
  1602. text: `Zawołania w komentarzach`,
  1603. title: "Zawołano Cię w komentarzu",
  1604. className: `wykopx_notifications_entries`,
  1605. id: undefined,
  1606. url: "/powiadomienia/moje",
  1607. target: "_self",
  1608. icon: null,
  1609. number: null
  1610. })
  1611. }
  1612. wykopx_notification_summary_url += mojeLubTagi;
  1613. }
  1614.  
  1615. let li = document.createElement("li");
  1616. li.setAttribute("class", "wykopxs wykopx_notification_summary notifications dropdown");
  1617. li.setAttribute("title", `Nowe powiadomienia ${promoString}`);
  1618. let a = document.createElement("a");
  1619. a.setAttribute("href", wykopx_notification_summary_url);
  1620. let figure = document.createElement("figure");
  1621. a.appendChild(figure);
  1622. li.appendChild(a);
  1623. document.querySelector("header.header > .right > nav > ul").insertAdjacentElement("afterbegin", li);
  1624. }
  1625.  
  1626.  
  1627.  
  1628.  
  1629.  
  1630. // TRYB NOCNY W BELCE NAWIGACYJNEJ
  1631. function addNightModeButtonToNavBar()
  1632. {
  1633. let wykopx_night_mode = `<li class="wykopxs wykopx_night_mode notifications dropdown" title="Przełącz pomiędzy trybem nocnym/dziennym ${promoString}"><a href="#"><figure></figure></a></li>`;
  1634. $(wykopx_night_mode).prependTo(`header.header > .right > nav > ul`);
  1635.  
  1636. $(".wykopx_night_mode").on("click", function ()
  1637. {
  1638. let currentMode = localStorage.getItem("nightMode")
  1639.  
  1640. if (currentMode === null || currentMode === "0")
  1641. {
  1642. document.body.setAttribute("data-night-mode", "true");
  1643. localStorage.setItem("nightMode", 1);
  1644. }
  1645. else
  1646. {
  1647. document.body.removeAttribute("data-night-mode");
  1648. localStorage.setItem("nightMode", 0);
  1649. }
  1650. // window.location.reload();
  1651. })
  1652. }
  1653.  
  1654.  
  1655.  
  1656.  
  1657. function addExtraButtons()
  1658. {
  1659. let wykopx_wykopwnowymstylu_li = `<li class="wykopxs wykopx_wykopwnowymstylu_li dropdown"><a href="/tag/wykopwnowymstylu" class="wykopx_wykopwnowymstylu_button" title="Przejdź na #wykopwnowymstylu"><span>#</span></a></li>`;
  1660. $(wykopx_wykopwnowymstylu_li).appendTo(`header.header > .right > nav > ul`);
  1661.  
  1662. let wykopx_mywykop_mobile_li = `<li class="wykopxs wykopx_mywykop_mobile_li dropdown"><a href="/obserwowane" class="wykopx_mywykop_mobile_button" title="Mój Wykop ${promoString}"><figure></figure></a></li>`;
  1663. $(wykopx_mywykop_mobile_li).appendTo(`header.header > .right > nav > ul`);
  1664.  
  1665. /* dolna belka mobilna */
  1666. $(wykopx_mywykop_mobile_li).appendTo(`body section.default-layout nav.mobile-navbar > ul`);
  1667.  
  1668. let wykopx_microblog_mobile_li = `<li class="wykopxs wykopx_microblog_mobile_li dropdown"><a href="/mikroblog" class="wykopx_microblog_mobile_button" title="Mikroblog ${promoString}"><figure> </figure></a></li>`;
  1669. $(wykopx_microblog_mobile_li).appendTo(`header.header > .right > nav > ul`);
  1670.  
  1671. let wykopx_messages_mobile_li = `<li class="wykopxs wykopx_messages_mobile_li dropdown"><a href="/wiadomosci" class="wykopx wykopx_messages_button" title="Wiadomości ${promoString}"><figure></figure></a></li>`;
  1672.  
  1673. /* dolna belka mobilna */
  1674. $(wykopx_messages_mobile_li).appendTo(`body section.default-layout nav.mobile-navbar > ul`);
  1675.  
  1676. if (user !== null)
  1677. {
  1678. let wykopx_profile_mobile_li = `<li class="wykopxs wykopx_profile_mobile_li ${user.username}"><a href="/ludzie/${user.username}" class="wykopx wykopx_profile_button" title="Przejdź na swój profil ${user.username} ${promoString}"><figure></figure></a></li>`;
  1679. $(wykopx_profile_mobile_li).appendTo(`body section.default-layout nav.mobile-navbar > ul`);
  1680. }
  1681. }
  1682.  
  1683.  
  1684.  
  1685.  
  1686.  
  1687.  
  1688.  
  1689. // DODAJ NOWY WPIS NA MIRKO
  1690. function focusOnAddingNewMicroblogEntry()
  1691. {
  1692. let wykop_url = new URL(document.URL);
  1693. if (wykop_url.hash == "#dodaj")
  1694. {
  1695. document.querySelector(`section.microblog-page section.microblog section.editor div.content textarea`).focus();
  1696. }
  1697. }
  1698.  
  1699.  
  1700.  
  1701.  
  1702. // document.removeEventListener('click', this.documentClick)
  1703. function unrollDropdowns(dropdown)
  1704. {
  1705. // YYY - async document.removeEventListener("click", this.documentClick); // TypeError: Cannot read properties of undefined (reading 'documentClick')
  1706. }
  1707.  
  1708.  
  1709.  
  1710.  
  1711.  
  1712.  
  1713.  
  1714.  
  1715. /* ------ DEV waitForKeyElements --------- */
  1716.  
  1717. if (wykopxSettings.getPropertyValue("--allowToDownloadImage"))
  1718. {
  1719. waitForKeyElements("section.entry section.entry-photo figure", allowToDownloadImage, false);
  1720.  
  1721. function allowToDownloadImage(jNode)
  1722. {
  1723. if (wykopxSettings.getPropertyValue("--allowToDownloadImage"))
  1724. {
  1725. let html = `<figcaption class="wykopxs wykopx_download_image_ico"><a title="Pobierz ten obrazek w pełnej rozdzielczości ${promoString}" href="${jNode.find("figcaption a").attr("href")}" download>Pobierz ten obrazek</a></figcaption>`;
  1726. $(jNode).append(html);
  1727. }
  1728. }
  1729. }
  1730.  
  1731. waitForKeyElements(`ul.categories`, categoryRedirectToMicroblogButton, false); // waitForKeyElements sends jNode object, not DOM object
  1732. waitForKeyElements("section.actions", mirkoukrywaczAddButtons, false);
  1733.  
  1734.  
  1735.  
  1736.  
  1737.  
  1738.  
  1739.  
  1740.  
  1741.  
  1742.  
  1743.  
  1744.  
  1745.  
  1746. /* ------ TAB TITLE AND WEBSITE FAVICON CHANGES --------- */
  1747.  
  1748. let originalTabTitle = document.title;
  1749. const defaultWykopFacoviconURL = "https://wykop.pl/static/img/favicons/favicon.png";
  1750.  
  1751. let tabTitles = new Map([
  1752. ["wlasny", settings.tabTitleCustom],
  1753. ["wykop", "Wykop"],
  1754. ["pusty_tytul", "ᅟᅟ"],
  1755. ["adres_url", " "],
  1756. ["digg", "News and Trending Stories Around the Internet | Digg"],
  1757. ["google", "Google"],
  1758. ["interia", "Interia - Polska i świat: informacje, sport, gwiazdy."],
  1759. ["onet", "Onet – Jesteś na bieżąco"],
  1760. ["reddit", "Reddit - Dive into anything"],
  1761. ["wp", "Wirtualna Polska - Wszystko co ważne"],
  1762. ["x", "Home / X"],
  1763. ["youtube", "YouTube"],
  1764. ])
  1765.  
  1766. let tabFavicons = new Map([
  1767. ["wykop", defaultWykopFacoviconURL],
  1768. ["wykop_white", "https://raw.githubusercontent.com/wykopx/wykopx-png/main/icons/favicons/W_white.png"],
  1769. ["wykop_gray", "https://raw.githubusercontent.com/wykopx/wykopx-png/main/icons/favicons/W_black.png"],
  1770.  
  1771. ["digg", "https://raw.githubusercontent.com/wykopx/wykopx-png/main/icons/favicons/digg.png"],
  1772. ["google", "https://raw.githubusercontent.com/wykopx/wykopx-png/main/icons/favicons/google.svg"],
  1773. ["interia", "https://raw.githubusercontent.com/wykopx/wykopx-png/main/icons/favicons/interia.ico"],
  1774. ["onet", "https://raw.githubusercontent.com/wykopx/wykopx-png/main/icons/favicons/onet.png"],
  1775. ["reddit", "https://raw.githubusercontent.com/wykopx/wykopx-png/main/icons/favicons/reddit.png"],
  1776. ["wp", "https://raw.githubusercontent.com/wykopx/wykopx-png/main/icons/favicons/wp.png"],
  1777. ["x", "https://raw.githubusercontent.com/wykopx/wykopx-png/main/icons/favicons/x.png"],
  1778. ["youtube", "https://raw.githubusercontent.com/wykopx/wykopx-png/main/icons/favicons/youtube.ico"],
  1779. ])
  1780.  
  1781.  
  1782.  
  1783. // TAB TITLE
  1784. function changeDocumentTitle(new_document_title)
  1785. {
  1786. console.log("unreadNotifications")
  1787. console.log(unreadNotifications)
  1788. // changeDocumentTitle()
  1789. // changeDocumentTitle("youtube")
  1790. // changeDocumentTitle("Example new title")
  1791.  
  1792. /* dodaj liczbe powiadomien do tytulu strony na karcie */
  1793. /*
  1794. const unreadNotifications = {
  1795. tags: 0,
  1796. tags_new_entry_with_observed_tag: 0,
  1797. tags_new_link_with_observed_tag: 0,
  1798. entries: 0,
  1799. pm: 0,
  1800. total: 0,
  1801. };
  1802. */
  1803.  
  1804. //xxx
  1805.  
  1806.  
  1807. let tabTitleNotifications = "";
  1808.  
  1809. if (settings.tabTitleShowNotificationsEnabled == true)
  1810. {
  1811. let notificationsTotalCount = 0;
  1812.  
  1813. let tabNotificationsSeparated = "";
  1814.  
  1815. if (unreadNotifications["total"] > 0
  1816. && (settings.tabTitleShowNotificationsCountPM
  1817. || settings.tabTitleShowNotificationsCountTagsNewLink
  1818. || settings.tabTitleShowNotificationsCountTagsNewEntry
  1819. || settings.tabTitleShowNotificationsCountEntries))
  1820. {
  1821. let notificationsEmoji = ""; // 🔗✉📧📩
  1822.  
  1823.  
  1824. if (settings.tabTitleShowNotificationsCountPM && unreadNotifications["pm"] > 0)
  1825. {
  1826. notificationsTotalCount += unreadNotifications["pm"];
  1827. notificationsEmoji = "📧";
  1828. tabNotificationsSeparated += `${notificationsEmoji}${unreadNotifications["pm"]} `;
  1829. }
  1830.  
  1831. if (settings.tabTitleShowNotificationsCountEntries && unreadNotifications["entries"] > 0)
  1832. {
  1833. notificationsTotalCount += unreadNotifications["entries"];
  1834. notificationsEmoji = "🔔";
  1835. tabNotificationsSeparated += `${notificationsEmoji}${unreadNotifications["entries"]} `;
  1836. }
  1837.  
  1838. if (unreadNotifications["tags"] && settings.tabTitleShowNotificationsCountTagsNewLink || settings.tabTitleShowNotificationsCountTagsNewEntry)
  1839. {
  1840. notificationsEmoji = "#";
  1841. if (settings.tabTitleShowNotificationsCountTagsNewLink && unreadNotifications["tags_new_entry_with_observed_tag"] > 0)
  1842. {
  1843. notificationsTotalCount += unreadNotifications["tags_new_entry_with_observed_tag"];
  1844. }
  1845. if (settings.tabTitleShowNotificationsCountTagsNewEntry && unreadNotifications["tags_new_entry_with_observed_tag"] > 0)
  1846. {
  1847. notificationsTotalCount += unreadNotifications["tags_new_entry_with_observed_tag"];
  1848. }
  1849. tabNotificationsSeparated += `${notificationsEmoji}${unreadNotifications["tags"]} `;
  1850. }
  1851.  
  1852.  
  1853.  
  1854. if (settings.tabTitleShowNotificationsCountSeparated) tabTitleNotifications = tabNotificationsSeparated;
  1855. else tabTitleNotifications = `(${notificationsTotalCount}) `;
  1856. }
  1857.  
  1858. console.log(new_document_title)
  1859. console.log("new_document_title")
  1860. }
  1861.  
  1862. if (tabTitles.has(new_document_title)) // selected title from Map
  1863. {
  1864. document.title = `${tabTitleNotifications}${tabTitles.get(new_document_title)}`;
  1865. }
  1866. else
  1867. {
  1868. document.title = `${tabTitleNotifications}${new_document_title}`;
  1869. }
  1870.  
  1871. }
  1872.  
  1873.  
  1874. // FAVICON ICO
  1875. function changeDocumentFavicon(new_favicon = defaultWykopFacoviconURL)
  1876. {
  1877. // changeDocumentFavicon()
  1878. // changeDocumentFavicon("reddit")
  1879. // changeDocumentFavicon("https://www.interia.pl/favicon.ico")
  1880. // <link rel="icon" type="image/svg+xml" href="/static/img/favicons/favicon.svg">
  1881. // <link rel="alternate icon" type="image/png" href="/static/img/favicons/favicon.png">
  1882. let oldFaviconElement = document.querySelector('link[rel="icon"]');
  1883. let alternateFaviconElement = document.querySelector('link[rel="alternate icon"]');
  1884. if (oldFaviconElement) document.head.removeChild(oldFaviconElement);
  1885. if (alternateFaviconElement) document.head.removeChild(alternateFaviconElement);
  1886.  
  1887. let selectedFaviconURL = new_favicon;
  1888. if (tabFavicons.has(new_favicon)) selectedFaviconURL = tabFavicons.get(new_favicon);
  1889.  
  1890. const faviconLinkElement = document.createElement('link');
  1891. faviconLinkElement.rel = 'icon';
  1892. faviconLinkElement.type = 'image/x-icon'; // "image/svg+xml" "image/png"
  1893. faviconLinkElement.href = selectedFaviconURL + '?=' + Math.random();
  1894.  
  1895. document.head.appendChild(faviconLinkElement);
  1896. }
  1897.  
  1898.  
  1899.  
  1900. function executeTabAndFaviconChanges()
  1901. {
  1902. if (document.hidden || !settings.tabChangeOnlyOnHiddenState)
  1903. {
  1904. if (settings.tabFaviconEnabled) changeDocumentFavicon(settings.tabFaviconSelect);
  1905. if (settings.tabTitleEnabled) changeDocumentTitle(settings.tabTitleSelect);
  1906. }
  1907. }
  1908.  
  1909.  
  1910. // TITLE MUTATION
  1911.  
  1912. let titleMutationObserver = new MutationObserver(mutationsList =>
  1913. {
  1914. // console.log("titleMutationObserver")
  1915. // console.log(mutationsList);
  1916.  
  1917. for (let mutation of mutationsList)
  1918. {
  1919. if (mutation.type === 'childList')
  1920. {
  1921. console.log(`Nowy tytuł strony: ${mutation.addedNodes[0].textContent}`);
  1922.  
  1923. titleMutationObserver.disconnect();
  1924. executeTabAndFaviconChanges();
  1925. titleMutationObserver.observe(document.querySelector('title'), { childList: true, })
  1926.  
  1927. }
  1928. }
  1929. });
  1930. titleMutationObserver.observe(document.querySelector('title'), { childList: true, })
  1931.  
  1932.  
  1933. // EVENT: KARTA JEST W TLE document.hidden == true
  1934. // https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API
  1935. // https://developer.mozilla.org/en-US/docs/Web/API/Document/visibilitychange_event
  1936. function handleVisibilityChange()
  1937. {
  1938. // document.visibilityState > "visible"/"hidden"
  1939. // document.hidden > true/false
  1940. // document.title = document.visibilityState;
  1941.  
  1942. if (document.hidden)
  1943. {
  1944. executeTabAndFaviconChanges();
  1945. console.log(`document.hidden -> true > document.visibilityState: ${document.visibilityState}`);
  1946. }
  1947. else
  1948. {
  1949. if (settings.tabChangeOnlyOnHiddenState)
  1950. {
  1951. if (settings.tabTitleEnabled) changeDocumentTitle(originalTabTitle);
  1952. if (settings.tabFaviconEnabled) changeDocumentFavicon();
  1953. }
  1954. }
  1955. }
  1956. document.addEventListener("visibilitychange", handleVisibilityChange, false); // ICO PNG GIF JPEG SVG
  1957.  
  1958.  
  1959.  
  1960.  
  1961.  
  1962.  
  1963.  
  1964.  
  1965. // RATING BOX - <section class="rating-box"> -> PLUSOWANIE I MINUSOWANIE
  1966.  
  1967. // plusy we wpisach (.rating-box), plusy wpisow w sidebarze (bez rating-box), plusy w znaleziskach
  1968. // rating box - mozliwosc plusowania / minusowania
  1969. // runWithDelay(1000, function ()
  1970. // {
  1971. // waitForKeyElements("section.entry:not(.reply) > article > header > div.right > div > section.rating-box", ratingBoxDetected, false);
  1972. // })
  1973. waitForKeyElements("section.entry:not(.deleted) > article > header > div.right > div > section.rating-box", ratingBoxDetected, false);
  1974. // waitForKeyElements("section.entry:not(.reply) > article > header > div.right > div > section.rating-box", ratingBoxDetected, false);
  1975.  
  1976. function ratingBoxDetected(jNodeRatingBoxSection)
  1977. {
  1978. const ratingBoxSection = jNodeRatingBoxSection[0]; // =jNode > DOMElement
  1979. visiblePlusesObserver.observe(ratingBoxSection); // IntersectionObserver
  1980. }
  1981.  
  1982. const intersectionCallback = (intersectingPluses, observer) => // function intersectionCallback(entries, observer)
  1983. {
  1984. let timeoutId = null;
  1985. let fetchSeconds = 12;
  1986.  
  1987. intersectingPluses.forEach((plus) =>
  1988. {
  1989. let plus_target = plus.target; // element <select class="rating-box">
  1990. console.log("intersectionCallback: possible intersection element detected 'plus_target'");
  1991. // console.log(plus_target);
  1992.  
  1993. if (settings.votingExplosion) votingExplosionEventListener(plus_target);
  1994.  
  1995. if (plus.isIntersecting)
  1996. {
  1997. // console.log("intersectionCallback: new ratingBox is intersecting")
  1998. plus_target.classList.add("isIntersecting");
  1999. plus_target.classList.remove("notIntersecting");
  2000. parseRatingBoxCurrentContentAndCreateDataValues(plus_target);
  2001.  
  2002. // timeoutId = setInterval(() => checkPluses(plus_target), fetchSeconds * 1000);
  2003. }
  2004. else
  2005. {
  2006. // clearInterval(timeoutId);
  2007. plus_target.classList.remove("isIntersecting");
  2008. plus_target.classList.add("notIntersecting");
  2009. }
  2010. });
  2011.  
  2012. // intersectingPluses.forEach((plus) =>
  2013. // {
  2014. // let plus_target = plus.target; // element <select class="rating-box">
  2015. // console.log("possible intersectionElement detected plus_target");
  2016.  
  2017. // let plusTimeoutId = null;
  2018. // if (plus.isIntersecting)
  2019. // {
  2020. // console.log("new intersecting plus")
  2021. // if (settings.votingExplosion) votingExplosionEventListener(plus_target);
  2022. // plus_target.classList.add("isIntersecting");
  2023. // plus_target.classList.remove("notIntersecting");
  2024. // parseRatingBoxCurrentContentAndCreateDataValues(plus_target);
  2025.  
  2026. // plusTimeoutId = setTimeout(() =>
  2027. // {
  2028. // clearTimeout(plusTimeoutId);
  2029. // plusTimeoutId = setInterval(() => checkPluses(plus_target), fetchSeconds * 1000);
  2030. // });
  2031. // }
  2032. // else
  2033. // {
  2034. // clearTimeout(plusTimeoutId);
  2035. // plus_target.classList.remove("isIntersecting");
  2036. // plus_target.classList.add("notIntersecting");
  2037. // }
  2038. // });
  2039.  
  2040.  
  2041.  
  2042.  
  2043. };
  2044. let observerOptions = { root: null, rootMargin: "-70px 0px -120px 0px", threshold: 1.0, /* [0.25, 0.5, 0.75, 1.0] */ };
  2045. const visiblePlusesObserver = new IntersectionObserver(intersectionCallback, observerOptions)
  2046.  
  2047.  
  2048.  
  2049. function getEntryBlocks(elem)
  2050. {
  2051. /* returns:
  2052. {
  2053. resource: "entry"
  2054. element: DOMElement,
  2055. id: 123456,
  2056. entry: DOMElement,
  2057. entry_id: 123456,
  2058. }
  2059. or
  2060. {
  2061. resource: "entry_comment"
  2062. element: DOMElement
  2063. id: 12345678,
  2064. entry: DOMElement,
  2065. entry_id: 123456,
  2066. comment: DOMElement,
  2067. comment_id: 12345678,
  2068. }
  2069. or
  2070. {
  2071. resource: "link_comment"
  2072. element: DOMElement
  2073. id: 12345678,
  2074. entry: DOMElement,
  2075. entry_id: 123456,
  2076. link_id: 12345678,
  2077. }
  2078. */
  2079.  
  2080. let blocks = {
  2081. votesUp: 0,
  2082. votesDown: 0,
  2083. votesCount: 0,
  2084. votesAll: 0,
  2085.  
  2086. separated: false,
  2087. };
  2088.  
  2089. blocks.element = elem.closest('section.entry'); // returns the section element above .rating-box
  2090. blocks.id = blocks.element.id.replace('comment-', ''); // entry/comment id
  2091.  
  2092. /*
  2093. ['', 'wpis', '74111643', 'dobranoc-panstwu']
  2094. ['', 'wykopalisko']
  2095. ['', 'link', '7303053', 'braun-gasi-chanuke-gasnica-mem']
  2096. */
  2097. if (pathnameArray[1] == "link") // znalezisko
  2098. {
  2099. // PODKOMENTARZ W ZNALEZISKU
  2100. if (blocks.element.classList.contains("reply"))
  2101. {
  2102. return null;
  2103. }
  2104. // KOMENTARZ POD ZNALEZISKIEM
  2105. else
  2106. {
  2107. return null;
  2108. blocks.link_id = pathnameArray[2]; // id
  2109. blocks.entry_element = blocks.element;
  2110. blocks.entry_id = blocks.entry_element.id.replace('comment-', '');
  2111. blocks.resource = "link_comment";
  2112. blocks.fetchURL = `https://wykop.pl/api/v3/links/${blocks.link_id}/comments/${blocks.entry_id}`;
  2113. blocks.entry_element.dataset.resource = "link_comment";
  2114. }
  2115. }
  2116. // KOMENTARZP OD WPISEM
  2117. else if (blocks.element.classList.contains("reply"))
  2118. {
  2119. // return null;
  2120.  
  2121. blocks.comment_element = blocks.element;
  2122. blocks.entry_element = blocks.comment_element.parentNode.closest('section.entry');
  2123. blocks.entry_id = blocks.entry_element.id.replace('comment-', '');
  2124.  
  2125. blocks.resource = "entry_comment"; // komentarz pod wpisem
  2126. blocks.comment_id = blocks.comment_element.id.replace('comment-', '');
  2127. blocks.fetchURL = `https://wykop.pl/api/v3/entries/${blocks.entry_id}/comments/${blocks.comment_id}`;
  2128. blocks.comment_element.dataset.resource = "entry_comment";
  2129. }
  2130. // WPIS NA MIKROBLOGU
  2131. else
  2132. {
  2133. blocks.entry_element = blocks.element;
  2134. blocks.entry_id = blocks.entry_element.id.replace('comment-', '');
  2135. blocks.resource = "entry";
  2136. blocks.fetchURL = `https://wykop.pl/api/v3/entries/${blocks.entry_id}`;
  2137.  
  2138. blocks.entry_element.dataset.resource = "entry";
  2139. }
  2140.  
  2141. // console.log("blocks.element");
  2142. // console.log(blocks.element);
  2143.  
  2144.  
  2145. let plus_element = blocks.element.querySelector("section.rating-box > ul > li.plus"); // 12 <li class="plus separated">
  2146. if (plus_element)
  2147. {
  2148. blocks.separated = plus_element.classList.contains('separated');
  2149. blocks.votesUp = parseInt(plus_element.textContent);
  2150. }
  2151.  
  2152. // let zero_element = blocks.element.querySelector(".rating-box li.zero"); // 0 <li class="zero separated">
  2153. // if (zero_element)
  2154. // {
  2155. // blocks.separated = zero_element.classList.contains('separated');
  2156. // blocks.votesUp = 0;
  2157. // }
  2158.  
  2159. let minus_element = blocks.element.querySelector(".rating-box li.minus"); // -8
  2160. if (minus_element)
  2161. {
  2162. blocks.votesDown = Math.abs(parseInt(minus_element.textContent)); // 3 (dodatnia)
  2163. }
  2164. blocks.entry_element.dataset.votesUp = blocks.votesUp;
  2165. blocks.entry_element.dataset.votesDown = blocks.votesDown;
  2166.  
  2167. // console.log("blocks");
  2168. // console.log(blocks);
  2169.  
  2170. return blocks;
  2171. }
  2172.  
  2173.  
  2174. function checkPluses(entry_element)
  2175. {
  2176. // console.log("checkPluses: entry_element")
  2177. // console.log(entry_element);
  2178.  
  2179. if (entry_element)
  2180. {
  2181. const entryBlocksData = getEntryBlocks(entry_element);
  2182.  
  2183. if (entryBlocksData) // nie dla subkomentarzy
  2184. {
  2185. let entry_element = entryBlocksData.element;
  2186. entry_element.classList.remove("addedPluses");
  2187. entry_element.classList.remove("removedPluses");
  2188. entry_element.classList.remove("addedMinuses");
  2189. entry_element.classList.remove("removedMinuses");
  2190.  
  2191. entry_element.style.removeProperty('--addedPluses');
  2192. entry_element.style.removeProperty('--removedPluses');
  2193. entry_element.style.removeProperty('--addedMinuses');
  2194. entry_element.style.removeProperty('--removedMinuses');
  2195.  
  2196. console.log("API fetch: " + entryBlocksData.fetchURL);
  2197.  
  2198. fetch(entryBlocksData.fetchURL,
  2199. {
  2200. method: "GET", // or 'PUT'
  2201. headers: {
  2202. "Content-Type": "application/json",
  2203. Authorization: "Bearer " + window.localStorage.token,
  2204. },
  2205. })
  2206. .then(x => x.json())
  2207. .then(data =>
  2208. {
  2209. const entry_fetched_data = data.data;
  2210. // console.log("fetched data from API: entry_fetched_data");
  2211. // console.log(entry_fetched_data);
  2212.  
  2213. entry_fetched_data.votes.votesCount = entry_fetched_data.votes.up - entry_fetched_data.votes.down; // -10 (suma plusów i minusów nie dotyczy entry, entry_comment)
  2214. entry_fetched_data.votes.votesAll = entry_fetched_data.votes.up + entry_fetched_data.votes.down; // 30 (łączna liczba głosów nie dotyczy entry, entry_comment)
  2215. entry_fetched_data.votes.votesUpPercent = 0; // nie dotyczy entry, entry_comment zawsze 100%
  2216. entry_fetched_data.votes.votesDownPercent = 0; // nie dotyczy entry, entry_comment
  2217.  
  2218. // ile plusów przybyło/ubyło
  2219. let plusesDelta = entry_fetched_data.votes.up - entry_element.dataset.votesUp;
  2220. let minusesDelta = entry_fetched_data.votes.down - entry_element.dataset.votesDown;
  2221.  
  2222. // console.log("entry_element.dataset.votesUp: " + entry_element.dataset.votesUp)
  2223. // console.log("entry_element.dataset.votesDown: " + entry_element.dataset.votesDown)
  2224. // console.log("entry_fetched_data.votes.up: " + entry_fetched_data.votes.up)
  2225. // console.log("entry_fetched_data.votes.down: " + entry_fetched_data.votes.down)
  2226. // console.log("plusesDelta " + plusesDelta)
  2227. // console.log("minusesDelta: " + minusesDelta)
  2228.  
  2229.  
  2230. entry_element.dataset.votesUp = entry_fetched_data.votes.up; // 10
  2231. entry_element.dataset.votesDown = entry_fetched_data.votes.down; // 20 - dodatnia nie dotyczy entry, entry_comment
  2232. entry_element.dataset.votesCount = entry_fetched_data.votes.votesCount; // -10 (suma plusów i minusów nie dotyczy entry, entry_comment)
  2233. entry_element.dataset.votesAll = entry_fetched_data.votes.votesAll; // 30 (łączna liczba głosów nie dotyczy entry, entry_comment)
  2234.  
  2235.  
  2236. if (entry_fetched_data.votes.votesAll > 0)
  2237. {
  2238. entry_fetched_data.votes.votesDownPercent = Math.ceil(entry_fetched_data.votes.down * 100 / entry_fetched_data.votes.votesAll);
  2239. entry_fetched_data.votes.votesUpPercent = Math.ceil(entry_fetched_data.votes.up * 100 / entry_fetched_data.votes.votesAll);
  2240. }
  2241.  
  2242. entry_element.dataset.voted = entry_fetched_data.voted;
  2243. if (entryBlocksData.resource == "entry" || entryBlocksData.resource == "link_comment")
  2244. {
  2245. entry_element.dataset.commentsCount = entry_fetched_data.comments.count;
  2246. }
  2247.  
  2248. console.log("entryBlocksData:");
  2249. console.log(entryBlocksData);
  2250.  
  2251. console.log("entry_element.dataset:");
  2252. console.log(entry_element.dataset);
  2253.  
  2254.  
  2255. if (plusesDelta != 0)
  2256. {
  2257. // console.log("Zmienila sie liczba plusow - plusesDelta:" + plusesDelta);
  2258. // console.log("entry_element.dataset.votesUp:" + entry_element.dataset.votesUp);
  2259. // if() zamiana li.zero na li.plus
  2260. let plusLi = entry_element.querySelector("section.rating-box > ul > li.plus");
  2261. if (!plusLi) plusLi = entry_element.querySelector("section.rating-box > ul > li.zero");
  2262. plusLi.textContent = entry_element.dataset.votesUp;
  2263.  
  2264. if (plusesDelta > 0)
  2265. {
  2266. entry_element.style.setProperty('--addedPluses', JSON.stringify(plusesDelta.toString()));
  2267. entry_element.classList.add("addedPluses");
  2268. }
  2269. else
  2270. {
  2271. entry_element.style.setProperty('--removedPluses', JSON.stringify(plusesDelta.toString()));
  2272. entry_element.classList.add("removedPluses");
  2273. }
  2274. }
  2275.  
  2276. if (minusesDelta != 0)
  2277. {
  2278. let minusLi = entry_element.querySelector("section.rating-box > ul > li.minus");
  2279. if (minusLi) minusLi.textContent = entry_element.dataset.votesDown;
  2280.  
  2281.  
  2282. if (minusesDelta > 0)
  2283. {
  2284. entry_element.style.setProperty('--addedMinuses', JSON.stringify(plusesDelta.toString()));
  2285. entry_element.classList.add("addedMinuses");
  2286. }
  2287. else
  2288. {
  2289. entry_element.style.setProperty('--removedMinuses', JSON.stringify(plusesDelta.toString()));
  2290. entry_element.classList.add("removedMinuses");
  2291. }
  2292. }
  2293.  
  2294. // console.log("entryBlocksData:")
  2295. // console.log(entryBlocksData)
  2296.  
  2297. // console.log("entry_element.dataset:")
  2298. // console.log(entry_element.dataset)
  2299.  
  2300. // console.log("entry_fetched_data (fetched):")
  2301. // console.log(entry_fetched_data)
  2302.  
  2303. // entry_element.dataset.tags = entry_fetched_data.tags;
  2304. // entry_element.dataset.device = entry_fetched_data.device;
  2305. // entry_element.dataset.voted = entry_fetched_data.voted;
  2306. // entry_element.dataset.adult = entry_fetched_data.adult;
  2307. // entry_element.dataset.tags = entry_fetched_data.tags;
  2308. // entry_element.dataset.favourite = entry_fetched_data.favourite;
  2309. // entry_element.dataset.deletable = entry_fetched_data.deletable;
  2310. // entry_element.dataset.editable = entry_fetched_data.editable;
  2311. // entry_element.dataset.slug = entry_fetched_data.slug;
  2312. // entry_element.dataset.parent_id = entry_fetched_data.parent_id;
  2313. // entry_element.dataset.resource = entry_fetched_data.resource; // "entry"
  2314. // entry_element.dataset.deleted = entry_fetched_data.deleted;
  2315. });
  2316. }
  2317. }
  2318. }
  2319.  
  2320.  
  2321.  
  2322.  
  2323.  
  2324.  
  2325.  
  2326.  
  2327.  
  2328. // <section class="rating-box" data-pluses="269" data-minuses="0" data-pluses-minuses-total="269" data-pluses-below-limit="true">
  2329. function parseRatingBoxCurrentContentAndCreateDataValues(ratingBoxSection)
  2330. {
  2331. // dodanie data-pluses na podstawie aktualnych wartosci plusow w HTML
  2332. // console.log("parseRatingBoxCurrentContentAndCreateDataValues(ratingBoxSection)")
  2333.  
  2334. const minusLi = ratingBoxSection.querySelector('li.minus');
  2335. let plusLi = ratingBoxSection.querySelector('li.plus');
  2336. if (!plusLi) plusLi = ratingBoxSection.querySelector('li.zero')
  2337. let votesUp = plusLi ? plusLi.textContent : 0; // 5liczba plusów
  2338. let votesDown = minusLi ? -1 * minusLi.textContent : 0; // 15 liczba minusów (dodatnia)
  2339. let votesCount = votesUp - votesDown; // -10 suma plusów i minusów
  2340. let votesAll = votesUp + votesDown; // 20 liczba glosow
  2341.  
  2342.  
  2343. ratingBoxSection.dataset.votesUp = votesUp;
  2344. ratingBoxSection.dataset.votesDown = votesDown;
  2345. ratingBoxSection.dataset.votesCount = votesCount;
  2346. ratingBoxSection.dataset.votesAll = votesAll;
  2347.  
  2348. // limit ukrywania wpisow przypietych na glownej
  2349. const homepagePinnedEntriesPlusesLimit = settings.homepagePinnedEntriesHideBelowLimit;
  2350. if (homepagePinnedEntriesPlusesLimit > 0)
  2351. {
  2352. // czy wpis jest poniżej limitu ukrywania wpisow przypietych na glownej
  2353. let plusesBelowLimit = (votesCount < homepagePinnedEntriesPlusesLimit ? true : false);
  2354. ratingBoxSection.dataset.plusesBelowLimit = plusesBelowLimit;
  2355. }
  2356. }
  2357.  
  2358.  
  2359.  
  2360. // VOTING EXPLOSION
  2361. function votingExplosionEventListener(ratingBoxSection)
  2362. {
  2363. ratingBoxSection.addEventListener('click', function (event)
  2364. {
  2365. var clickedButton = event.target;
  2366.  
  2367. console.log(clickedButton);
  2368.  
  2369. let count = 0;
  2370. let vote = "voted"; // "voted", "unvoted"
  2371. let action = "plused"; // "plused", "minused"
  2372. let sign = "+";
  2373.  
  2374. let plusLi = ratingBoxSection.querySelector('li.plus');
  2375. if (!plusLi) plusLi = ratingBoxSection.querySelector('li.zero');
  2376. let minusLi = ratingBoxSection.querySelector('button.plus');
  2377.  
  2378. let votesUp = plusLi ? plusLi.textContent : 0;
  2379. let votesDown = minusLi ? -1 * minusLi.textContent : 0;
  2380.  
  2381. if (clickedButton.matches('button.plus.voted')) // dodano plusa
  2382. {
  2383. action = "plused";
  2384. vote = "voted";
  2385. count = votesUp;
  2386. }
  2387. else if (clickedButton.matches('button.plus:not(.voted)')) // usunieto plusa
  2388. {
  2389. action = "plused";
  2390. vote = "unvoted";
  2391. count = votesUp;
  2392. }
  2393. else if (clickedButton.matches('button.minus.voted')) // dodano minusa
  2394. {
  2395. action = "minused";
  2396. vote = "voted";
  2397. sign = "-";
  2398. count = votesDown;
  2399. }
  2400. else if (clickedButton.matches('button.minus:not(.voted)')) // usunięto minusa
  2401. {
  2402. action = "minused";
  2403. vote = "unvoted";
  2404. sign = "-";
  2405. count = votesDown;
  2406. }
  2407.  
  2408. if (vote == "voted")
  2409. {
  2410. let min_x = -60;
  2411. let max_x = 60;
  2412. let min_y = -60;
  2413. let max_y = -20;
  2414.  
  2415. if (count > 30) max_y = 60;
  2416. if (count > 300) { min_x = -90; max_x = 90; }
  2417.  
  2418. // let particlesCount = (count > 110 ? Math.ceil(count / 10) : count);
  2419. let particlesCount = count;
  2420. if (particlesCount > 2000) particlesCount = 200;
  2421. else if (particlesCount > 690) particlesCount = particlesCount / 10;
  2422. else if (particlesCount > 345) particlesCount = particlesCount / 5;
  2423. else if (particlesCount > 39) particlesCount = 39;
  2424.  
  2425.  
  2426. var newDivs = [];
  2427.  
  2428. for (var i = 0; i < particlesCount; i++)
  2429. {
  2430. var newDiv = document.createElement('div');
  2431. newDiv.textContent = sign;
  2432.  
  2433. newDiv.classList.add(`wykopxs_vote_animation`, `wykopxs_${vote}`, `wykopxs_${action}`); // class="wykopxs_vote_animation wykopxs_voted wykopxs_plused"
  2434.  
  2435. let color = (sign === "+" ? "green" : "red");
  2436. if (sign === "+")
  2437. {
  2438. if (count >= 666 && getRandomInt(1, 10) == 1) color = "golden";
  2439. if (count > 100 && count < 666 && getRandomInt(1, 80) == 1) newDiv.textContent = "💚";;
  2440. }
  2441. if (count > 100 && getRandomInt(1, 30) == 1)
  2442. {
  2443. min_x += getRandomInt(-30, 30); max_x += getRandomInt(-30, 30)
  2444. min_y -= getRandomInt(-30, 30); max_y -= getRandomInt(-30, 30);
  2445. }
  2446.  
  2447. newDiv.classList.add(`wykopxs_${color}`);
  2448.  
  2449. newDiv.style.setProperty('--position_x', getRandomInt(min_x, max_x, "px"));
  2450. newDiv.style.setProperty('--position_y', getRandomInt(min_y, max_y, "px"));
  2451. newDiv.style.setProperty('--position_z', 0);
  2452. if (count > 30)
  2453. {
  2454. newDiv.style.setProperty('--explosionTiming',
  2455. getRandomString("linear", "ease", "ease-in-out", "ease-in", "ease-out")); // "cubic-bezier(0.1, 0.7, 1, 0.1)"
  2456. newDiv.style.setProperty('--explosionDelay', getRandomInt(0, getRandomInt(0, Math.max(800, count)), "ms"));
  2457. newDiv.style.setProperty('--explosionDuration', getRandomInt(900, 1300), "ms");
  2458. }
  2459.  
  2460. clickedButton.after(newDiv);
  2461. newDivs.push(newDiv);
  2462. }
  2463.  
  2464. parseRatingBoxCurrentContentAndCreateDataValues(ratingBoxSection);
  2465.  
  2466. setTimeout(function ()
  2467. {
  2468. for (var i = 0; i < newDivs.length; i++)
  2469. {
  2470. newDivs[i].parentNode.removeChild(newDivs[i]);
  2471. }
  2472.  
  2473. }, 2500);
  2474. }
  2475. });
  2476. }
  2477.  
  2478. // waitForKeyElements(`body > section > div.main-content > main.main > section > div.content > section.entry-page > section.entry > section.stream > div.content > section.entry`, minusyTutaj, false);
  2479.  
  2480. // body > section > div.main-content > main.main > section > div.content > section.entry-page > section.entry > section.stream > div.content > section.entry > div#entry-comments > section.stream > div.content > section.reply`
  2481.  
  2482. function minusyTutaj(jNodeEntryBlock)
  2483. {
  2484. const entryBlock = jNodeEntryBlock[0]; // jNode => DOMElement
  2485.  
  2486. // alert(entryBlock)
  2487. // Select the section with class 'rating-box'
  2488. let section = document.querySelector('.rating-box');
  2489.  
  2490. // Clear the existing content
  2491. section.innerHTML = '';
  2492.  
  2493. // Create new elements
  2494. let ul = document.createElement('ul');
  2495. let liZero = document.createElement('li');
  2496. let liMinus = document.createElement('li');
  2497. let div = document.createElement('div');
  2498. let buttonPlus = document.createElement('button');
  2499. let buttonMinus = document.createElement('button');
  2500.  
  2501. // Set classes and text content for new elements
  2502. ul.className = '';
  2503. liZero.className = 'zero separated';
  2504. liZero.textContent = '0';
  2505. liMinus.className = 'minus';
  2506. liMinus.textContent = '-8';
  2507. div.className = 'buttons';
  2508. buttonPlus.className = 'plus';
  2509. buttonPlus.textContent = '+';
  2510. buttonMinus.className = 'minus';
  2511. buttonMinus.textContent = '-';
  2512.  
  2513. // Append new elements to the DOM
  2514. ul.appendChild(liZero);
  2515. ul.appendChild(liMinus);
  2516. div.appendChild(buttonPlus);
  2517. div.appendChild(buttonMinus);
  2518. section.appendChild(ul);
  2519. section.appendChild(div);
  2520.  
  2521. }
  2522.  
  2523.  
  2524.  
  2525.  
  2526.  
  2527.  
  2528. const apiGetLink = "https://wykop.pl/api/v3/links/";
  2529. /*
  2530. <section id="link-7288349" class="link-block"
  2531. data-votes-up="183" data-votes-down="5" data-votes-count="178" data-voted="0" data-comments-count="10" data-comments-hot="false" data-hot="false" data-adult="false" data-created-at="2023-11-27 21:12:49" data-published-at="2023-11-28 15:22:38" data-title="Dwie awarie..." data-slug="dwie-awarie-w-ec-bedzin-wznowienie-dostaw-ciepla-w-koncu-tygodnia-rmf-24" data-description="Dwie awarie w (...)" data-source-label="www.rmf24.pl" data-source-u-r-l="https://www.rmf24.pl/regiony/slaskie/news..." data-source-type="anchor" data-tags="slaskie,bedzin,awaria,wydarzenia">
  2532. */
  2533.  
  2534. function linkBlockDetected(jNodeLinkBlock)
  2535. {
  2536. const linkBlock = jNodeLinkBlock[0]; // jNode => DOMElement
  2537. const link_id = linkBlock.id.replace("link-", ""); // 78643212
  2538. const fetchURL = apiGetLink + link_id;
  2539.  
  2540. let link_data;
  2541.  
  2542. let sectionVoteBox = linkBlock.querySelector('section.vote-box');
  2543. if (sectionVoteBox)
  2544. {
  2545. fetch(fetchURL,
  2546. {
  2547. method: "GET", // or 'PUT'
  2548. headers: {
  2549. "Content-Type": "application/json",
  2550. Authorization: "Bearer " + window.localStorage.token,
  2551. },
  2552. })
  2553. .then(x => x.json())
  2554. .then(data =>
  2555. {
  2556. link_data = data.data;
  2557. // console.log(link_data);
  2558.  
  2559. linkBlock.dataset.votesUp = link_data.votes.up; // 10
  2560. linkBlock.dataset.votesDown = link_data.votes.down; // -20
  2561. linkBlock.dataset.votesCount = link_data.votes.count; // -10 (suma wykopów i zakopów)
  2562. linkBlock.dataset.votesAll = link_data.votes.up + link_data.votes.down; // 30 (łączna liczba głosów)
  2563.  
  2564. link_data.votes.votesDownPercent = 0;
  2565. link_data.votes.votesUpPercent = 0;
  2566.  
  2567. if (linkBlock.dataset.votesAll > 0)
  2568. {
  2569. link_data.votes.votesDownPercent = Math.ceil(link_data.votes.down * 100 / linkBlock.dataset.votesAll);
  2570. link_data.votes.votesUpPercent = Math.ceil(link_data.votes.up * 100 / linkBlock.dataset.votesAll);
  2571. }
  2572. linkBlock.dataset.voted = link_data.voted;
  2573. linkBlock.dataset.commentsCount = link_data.comments.count;
  2574. linkBlock.dataset.commentsHot = link_data.comments.hot;
  2575. linkBlock.dataset.hot = link_data.hot;
  2576. linkBlock.dataset.adult = link_data.adult;
  2577. linkBlock.dataset.createdAt = link_data.created_at;
  2578. linkBlock.dataset.publishedAt = link_data.published_at;
  2579. linkBlock.dataset.title = link_data.title;
  2580. linkBlock.dataset.slug = link_data.slug;
  2581. linkBlock.dataset.description = link_data.description;
  2582. linkBlock.dataset.sourceLabel = link_data.source.label;
  2583. linkBlock.dataset.sourceURL = link_data.source.url;
  2584. linkBlock.dataset.sourceType = link_data.source.type;
  2585. linkBlock.dataset.tags = link_data.tags;
  2586.  
  2587. // Znaleziska sortowane wg liczby wykopów
  2588. if (settings.linksAnalyzerSortByVotesCount)
  2589. {
  2590. linkBlock.style.order = -1 * link_data.votes.count; // style="order: -321"
  2591. }
  2592. const votesMeter = document.createElement('progress');
  2593. votesMeter.className = "wykopxs wykopx_votesMeter";
  2594. votesMeter.setAttribute('value', link_data.votes.up);
  2595. votesMeter.setAttribute('max', link_data.votes.up + link_data.votes.down);
  2596.  
  2597. const votesDownInfo = document.createElement('div');
  2598. votesDownInfo.className = "burry active wykopxVotesDownInfo";
  2599.  
  2600. const span = document.createElement('span');
  2601. span.className = "wykopxs wykopx_votesDown";
  2602. span.setAttribute('data-v-83d9f12a', ''); // VUE
  2603. span.setAttribute('data-dropdown', `buried-${link_id}`);
  2604. span.setAttribute('title', `Statystyki Wykop X:
  2605.  
  2606. Liczba wykopujących: ${link_data.votes.up}
  2607. Liczba zakopujących: ${link_data.votes.down} (${link_data.votes.votesDownPercent} %)`);
  2608.  
  2609. const spanVotesDownCount = document.createElement('span');
  2610. spanVotesDownCount.className = "wykopxs wykopx_votesDownCount";
  2611. spanVotesDownCount.textContent = `${link_data.votes.down}`;
  2612.  
  2613. const spanVotesDownPercent = document.createElement('span');
  2614. spanVotesDownPercent.className = "wykopxs wykopx_votesDownPercent";
  2615. spanVotesDownPercent.textContent = `(${link_data.votes.votesDownPercent} %)`;
  2616.  
  2617. span.appendChild(spanVotesDownCount);
  2618. span.appendChild(spanVotesDownPercent);
  2619. votesDownInfo.appendChild(span);
  2620.  
  2621.  
  2622. sectionVoteBox.appendChild(votesDownInfo);
  2623. if (linkBlock.dataset.votesAll > 0)
  2624. {
  2625. sectionVoteBox.appendChild(votesMeter);
  2626. }
  2627.  
  2628. });
  2629. }
  2630. }
  2631.  
  2632.  
  2633.  
  2634.  
  2635.  
  2636.  
  2637.  
  2638.  
  2639.  
  2640. /* ZNIESIENIE LIMITÓW W TEXTAREA I INPUT PODCZAS WKLEJANIA TEKSTU */
  2641. // <input data-v-6486857b="" data-v-99298700="" type="text" placeholder="Wpisz tytuł Znaleziska..." maxlength="80" class="">
  2642. // <textarea data-v-8f9e192e="" data-v-99298700="" placeholder="Wpisz opis Znaleziska..." maxlength="300" class=""></textarea>
  2643. // <input data-v-714efcd5="" id="title" type="text" placeholder="Wpisz tytuł..." maxlength="80" class="highlight">
  2644. if (settings.disableNewLinkEditorPastedTextLimit)
  2645. {
  2646. waitForKeyElements("[maxlength]", disableNewLinkEditorPastedTextLimit, false);
  2647. }
  2648.  
  2649. function disableNewLinkEditorPastedTextLimit(jNodeInput)
  2650. {
  2651. const input = jNodeInput[0];
  2652. const maxLength = input.getAttribute('maxlength');
  2653. input.removeAttribute('maxlength');
  2654.  
  2655. let divElement = document.createElement('div');
  2656.  
  2657. divElement.className = 'wykopxs_textinput_limit_info';
  2658. divElement.style.color = 'rgba(120, 120, 120, 1)';
  2659. divElement.style.fontSize = '14px';
  2660. divElement.style.margin = '10px 0px 10px 0px';
  2661.  
  2662. input.parentNode.appendChild(divElement, input);
  2663.  
  2664. function handleInputEvent()
  2665. {
  2666. let charCount = input.value.length;
  2667. divElement.innerHTML = `
  2668. Wykop X: wprowadzono:
  2669. <span class="${charCount > maxLength ? 'overLimit' : 'withinLimit'}" style="color: ${charCount > maxLength ? 'red' : 'inherit'}">
  2670. <strong>${charCount}</strong> /
  2671. <strong>${maxLength}</strong>
  2672. </span>
  2673. znaków`;
  2674. }
  2675.  
  2676. input.addEventListener('change', handleInputEvent);
  2677. input.addEventListener('focus', handleInputEvent);
  2678. input.addEventListener('paste', handleInputEvent);
  2679.  
  2680.  
  2681. let timeout = null;
  2682. input.addEventListener('keyup', function (e)
  2683. {
  2684. if (e.key === ' ' || e.key === '.')
  2685. {
  2686. handleInputEvent(e);
  2687. }
  2688. else
  2689. {
  2690. clearTimeout(timeout);
  2691. timeout = setTimeout(function ()
  2692. {
  2693. handleInputEvent(e);
  2694. }, 2000);
  2695. }
  2696. });
  2697.  
  2698. }
  2699.  
  2700.  
  2701.  
  2702.  
  2703.  
  2704.  
  2705.  
  2706.  
  2707.  
  2708.  
  2709.  
  2710.  
  2711.  
  2712.  
  2713.  
  2714.  
  2715.  
  2716. /* HELPER FUNCTIONS */
  2717.  
  2718.  
  2719.  
  2720. // consoleX("TEXT")
  2721. // consoleX("TEXT", 1)
  2722. // consoleX("TEXT", false)
  2723. function consoleX(text, dev_mode = false)
  2724. {
  2725. let tpl = `background-color:black; border:1px solid rgba(244, 244, 244, 0.4); font-weight: bolder; padding: 0px 9px; font-family: "Segoe UI", "Open Sans", sans-serif; margin-right: 10px;`;
  2726. if (dev_mode) tpl += `color:rgba(43, 255, 75, 1);`;
  2727. else tpl += `color:rgba(255, 255, 255, 0.8);`;
  2728.  
  2729. if (dev_mode == false || dev == true) console.log(`%cWykop X%c` + text, `${tpl}`, `font-family: "Segoe UI", "Open Sans"`);
  2730. }
  2731.  
  2732.  
  2733. // DEV RUN WITH DELAY
  2734. function runWithDelay(time, f)
  2735. {
  2736. // consoleX(`runWithDelay(f , ${time})`, 1);
  2737. setTimeout(function ()
  2738. {
  2739. f();
  2740. }, time);
  2741. }
  2742.  
  2743.  
  2744. // getRandomInt(-30, 20, "px")
  2745. function getRandomInt(min, max, unit)
  2746. {
  2747. min = Math.ceil(min);
  2748. max = Math.floor(max);
  2749. let randomValue = Math.floor(Math.random() * (max - min + 1)) + min;
  2750. if (unit != null) randomValue = randomValue + unit;
  2751. return randomValue;
  2752. }
  2753.  
  2754.  
  2755. // getRandomString("string1", "string2", "string3", "string4", "string5");
  2756. function getRandomString(...stringsArray)
  2757. {
  2758. let randomString = stringsArray[Math.floor(Math.random() * stringsArray.length)];
  2759. return randomString;
  2760. }
  2761.  
  2762.  
  2763. // if (wykopxSettings.getPropertyValue("--enableNotatkowator")) {
  2764. // waitForKeyElements("section.entry", addWykopXActionBoxToEntryAndComment, false);
  2765. // }
  2766.  
  2767.  
  2768.  
  2769.  
  2770.  
  2771.  
  2772.  
  2773.  
  2774.  
  2775.  
  2776.  
  2777. /* NEW WYKOP PAGE REDIRECTION */
  2778. navigation.addEventListener("navigate", (event) =>
  2779. {
  2780. console.log("navigation - navigate event - " + event.type)
  2781. originalTabTitle = document.title;
  2782.  
  2783. visiblePlusesObserver.disconnect();
  2784.  
  2785. // consoleX(`navigation.addEventListener("navigate", (event) =>`, 1);
  2786.  
  2787. //
  2788. runWithDelay(2000, function ()
  2789. {
  2790. hashAndPathNameLoad();
  2791. categoryRedirectToMicroblogButton();
  2792. countNumberOfNotificationsOnDesktop();
  2793. autoOpenMoreContentEverywhere();
  2794. addActionBoxesToAllEntriesAndComments();
  2795.  
  2796. if (settings.tagHeaderEditable && pathnameArray[1] == "tag") runWithDelay(5000, tagHeaderEditableLoad);
  2797. });
  2798.  
  2799. if (!settings.tabChangeOnlyOnHiddenState)
  2800. {
  2801. runWithDelay(7000, () =>
  2802. {
  2803. executeTabAndFaviconChanges();
  2804. })
  2805. }
  2806.  
  2807. // runWithDelay(1000, countNumberOfNotificationsOnDesktop);
  2808. // runWithDelay(2000, autoOpenMoreContentEverywhere);
  2809. // runWithDelay2000, addActionBoxesToAllEntriesAndComments);
  2810. });
  2811.  
  2812.  
  2813. /*
  2814. “popstate”: This event is fired when the active history entry changes, either by the user navigating to a different state, or by the code calling the history.pushState() or history.replaceState() methods. This event can be used to update the page content according to the new state.
  2815. “hashchange”: This event is fired when the fragment identifier of the URL (the part after the “#”) changes. This event can be used to implement single-page applications that use different hash values to load different views.
  2816. “pushstate”: This event is fired when the history.pushState() method is called, which adds a new state to the history stack. This event can be used to perform some actions when a new state is created.
  2817. “replacestate”: This event is fired when the history.replaceState() method is called, which modifies the current state in the history stack. This event can be used to perform some actions when the current state is changed.
  2818. */
  2819.  
  2820.  
  2821.  
  2822.  
  2823.  
  2824. let user = {
  2825. data: null,
  2826. username: null
  2827. };
  2828.  
  2829.  
  2830.  
  2831. // lOADED PAGE
  2832. window.onload = function (event)
  2833. {
  2834. const topHeaderProfileButton = document.querySelector("body header > div.right > nav > ul > li.account a.avatar");
  2835. if (topHeaderProfileButton) user.username = topHeaderProfileButton.getAttribute("href").split('/')[2];
  2836.  
  2837. if (user.username == null)
  2838. {
  2839. consoleX(`Cześć Anon. Nie jesteś zalogowany na Wykopie (⌐ ͡■ ͜ʖ ͡■)`);
  2840. }
  2841. else
  2842. {
  2843. consoleX(`Cześć ${user.username} (⌐ ͡■ ͜ʖ ͡■)`);
  2844. }
  2845. hashAndPathNameLoad();
  2846. focusOnAddingNewMicroblogEntry();
  2847.  
  2848. // 8s
  2849. runWithDelay(3000, function ()
  2850. {
  2851. if (settings.linksAnalyzerEnable)
  2852. {
  2853. waitForKeyElements(`section.link-block[id^="link-"]`, linkBlockDetected, false);
  2854. // GM_wrench.waitForKeyElements(`section.link-block[id^="link-"]`, linkBlockDetected, false);
  2855. }
  2856. addWykopXButtonsToNavBar();
  2857.  
  2858. });
  2859.  
  2860. // 8s
  2861. runWithDelay(8000, function ()
  2862. {
  2863. countNumberOfNotificationsOnDesktop();
  2864. addNotificationSummaryButtonToNavBar();
  2865. addNightModeButtonToNavBar();
  2866. unrollDropdowns();
  2867. addExtraButtons();
  2868. addWykopXPromoBanner();
  2869.  
  2870. hideWykopXSPromo();
  2871. // categoryRedirectToMicroblogButton();
  2872. mirkoukrywaczBuildListOfHiddenElements();
  2873. autoOpenMoreContentEverywhere();
  2874. refreshOrRedirectOnHomeButtonClick();
  2875. refreshOrRedirectOnMicroblogButtonClick();
  2876. tagHeaderEditableLoad();
  2877. addActionBoxesToAllEntriesAndComments();
  2878. addObservedTagsToRightSidebar();
  2879. });
  2880.  
  2881.  
  2882. // 20s
  2883. runWithDelay(12000, function ()
  2884. {
  2885.  
  2886.  
  2887. checkVersionForUpdates();
  2888.  
  2889. createNewProfileDropdownMenuItem(
  2890. {
  2891. text: `Wykop X - Informacje`,
  2892. title: "Otwórz stronę Wiki z informacjami o dodatku Wykop X",
  2893. className: `wykopx_wiki`,
  2894. id: undefined,
  2895. url: "http://wiki.wykopx.pl/",
  2896. target: "_self",
  2897. icon: null,
  2898. number: null
  2899. });
  2900.  
  2901. });
  2902.  
  2903. };
  2904.  
  2905.  
  2906.  
  2907.  
  2908.  
  2909.  
  2910. })();