FA Embedded Image Viewer

Embeds the clicked Image on the Current Site, so you can view it without loading the submission Page

  1. // ==UserScript==
  2. // @name FA Embedded Image Viewer
  3. // @namespace Violentmonkey Scripts
  4. // @match *://*.furaffinity.net/*
  5. // @require https://update.gf.qytechs.cn/scripts/525666/1549449/Furaffinity-Prototype-Extensions.js
  6. // @require https://update.gf.qytechs.cn/scripts/483952/1549453/Furaffinity-Request-Helper.js
  7. // @require https://update.gf.qytechs.cn/scripts/492931/1549454/Furaffinity-Submission-Image-Viewer.js
  8. // @require https://update.gf.qytechs.cn/scripts/485827/1549457/Furaffinity-Match-List.js
  9. // @require https://update.gf.qytechs.cn/scripts/485153/1549461/Furaffinity-Loading-Animations.js
  10. // @require https://update.gf.qytechs.cn/scripts/476762/1549463/Furaffinity-Custom-Pages.js
  11. // @require https://update.gf.qytechs.cn/scripts/475041/1550020/Furaffinity-Custom-Settings.js
  12. // @grant GM_info
  13. // @version 2.4.4
  14. // @author Midori Dragon
  15. // @description Embeds the clicked Image on the Current Site, so you can view it without loading the submission Page
  16. // @icon https://www.furaffinity.net/themes/beta/img/banners/fa_logo.png
  17. // @license MIT
  18. // @homepageURL https://gf.qytechs.cn/scripts/458971-fa-embedded-image-viewer
  19. // @supportURL https://gf.qytechs.cn/scripts/458971-fa-embedded-image-viewer/feedback
  20. // ==/UserScript==
  21. // jshint esversion: 8
  22. (() => {
  23. "use strict";
  24. var __webpack_modules__ = {
  25. 789: (module, __webpack_exports__, __webpack_require__) => {
  26. __webpack_require__.d(__webpack_exports__, {
  27. A: () => __WEBPACK_DEFAULT_EXPORT__
  28. });
  29. var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(601), _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = __webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__), _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(314), ___CSS_LOADER_EXPORT___ = __webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__)()(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default());
  30. ___CSS_LOADER_EXPORT___.push([ module.id, "#eiv-main {\n position: fixed;\n width: 100vw;\n height: 100vh;\n max-width: 1850px;\n z-index: 999999;\n background: rgba(30, 33, 38, .65);\n}\n\n#eiv-background {\n position: fixed;\n display: flex;\n flex-direction: column;\n left: 50%;\n transform: translate(-50%, 0%);\n margin-top: 20px;\n padding: 20px;\n background: rgba(30, 33, 38, .90);\n border-radius: 10px;\n}\n\n#eiv-submission-container {\n -webkit-user-drag: none;\n}\n\n.eiv-submission-img {\n max-width: inherit;\n max-height: inherit;\n border-radius: 10px;\n user-select: none;\n}\n\n#eiv-button-container {\n position: relative;\n margin-top: 20px;\n margin-bottom: 20px;\n margin-left: 20px;\n}\n\n#eiv-button-wrapper {\n display: flex;\n justify-content: center;\n align-items: center;\n}\n\n#eiv-preview-spinner-container {\n position: absolute;\n top: 50%;\n right: 0;\n transform: translateY(-50%);\n}\n\n.eiv-button {\n margin-left: 4px;\n margin-right: 4px;\n user-select: none;\n}\n", "" ]);
  31. const __WEBPACK_DEFAULT_EXPORT__ = ___CSS_LOADER_EXPORT___;
  32. },
  33. 314: module => {
  34. module.exports = function(cssWithMappingToString) {
  35. var list = [];
  36. list.toString = function toString() {
  37. return this.map((function(item) {
  38. var content = "", needLayer = void 0 !== item[5];
  39. if (item[4]) content += "@supports (".concat(item[4], ") {");
  40. if (item[2]) content += "@media ".concat(item[2], " {");
  41. if (needLayer) content += "@layer".concat(item[5].length > 0 ? " ".concat(item[5]) : "", " {");
  42. content += cssWithMappingToString(item);
  43. if (needLayer) content += "}";
  44. if (item[2]) content += "}";
  45. if (item[4]) content += "}";
  46. return content;
  47. })).join("");
  48. };
  49. list.i = function i(modules, media, dedupe, supports, layer) {
  50. if ("string" == typeof modules) modules = [ [ null, modules, void 0 ] ];
  51. var alreadyImportedModules = {};
  52. if (dedupe) for (var k = 0; k < this.length; k++) {
  53. var id = this[k][0];
  54. if (null != id) alreadyImportedModules[id] = true;
  55. }
  56. for (var _k = 0; _k < modules.length; _k++) {
  57. var item = [].concat(modules[_k]);
  58. if (!dedupe || !alreadyImportedModules[item[0]]) {
  59. if (void 0 !== layer) if (void 0 === item[5]) item[5] = layer; else {
  60. item[1] = "@layer".concat(item[5].length > 0 ? " ".concat(item[5]) : "", " {").concat(item[1], "}");
  61. item[5] = layer;
  62. }
  63. if (media) if (!item[2]) item[2] = media; else {
  64. item[1] = "@media ".concat(item[2], " {").concat(item[1], "}");
  65. item[2] = media;
  66. }
  67. if (supports) if (!item[4]) item[4] = "".concat(supports); else {
  68. item[1] = "@supports (".concat(item[4], ") {").concat(item[1], "}");
  69. item[4] = supports;
  70. }
  71. list.push(item);
  72. }
  73. }
  74. };
  75. return list;
  76. };
  77. },
  78. 601: module => {
  79. module.exports = function(i) {
  80. return i[1];
  81. };
  82. },
  83. 72: module => {
  84. var stylesInDOM = [];
  85. function getIndexByIdentifier(identifier) {
  86. for (var result = -1, i = 0; i < stylesInDOM.length; i++) if (stylesInDOM[i].identifier === identifier) {
  87. result = i;
  88. break;
  89. }
  90. return result;
  91. }
  92. function modulesToDom(list, options) {
  93. for (var idCountMap = {}, identifiers = [], i = 0; i < list.length; i++) {
  94. var item = list[i], id = options.base ? item[0] + options.base : item[0], count = idCountMap[id] || 0, identifier = "".concat(id, " ").concat(count);
  95. idCountMap[id] = count + 1;
  96. var indexByIdentifier = getIndexByIdentifier(identifier), obj = {
  97. css: item[1],
  98. media: item[2],
  99. sourceMap: item[3],
  100. supports: item[4],
  101. layer: item[5]
  102. };
  103. if (-1 !== indexByIdentifier) {
  104. stylesInDOM[indexByIdentifier].references++;
  105. stylesInDOM[indexByIdentifier].updater(obj);
  106. } else {
  107. var updater = addElementStyle(obj, options);
  108. options.byIndex = i;
  109. stylesInDOM.splice(i, 0, {
  110. identifier,
  111. updater,
  112. references: 1
  113. });
  114. }
  115. identifiers.push(identifier);
  116. }
  117. return identifiers;
  118. }
  119. function addElementStyle(obj, options) {
  120. var api = options.domAPI(options);
  121. api.update(obj);
  122. return function updater(newObj) {
  123. if (newObj) {
  124. if (newObj.css === obj.css && newObj.media === obj.media && newObj.sourceMap === obj.sourceMap && newObj.supports === obj.supports && newObj.layer === obj.layer) return;
  125. api.update(obj = newObj);
  126. } else api.remove();
  127. };
  128. }
  129. module.exports = function(list, options) {
  130. var lastIdentifiers = modulesToDom(list = list || [], options = options || {});
  131. return function update(newList) {
  132. newList = newList || [];
  133. for (var i = 0; i < lastIdentifiers.length; i++) {
  134. var index = getIndexByIdentifier(lastIdentifiers[i]);
  135. stylesInDOM[index].references--;
  136. }
  137. for (var newLastIdentifiers = modulesToDom(newList, options), _i = 0; _i < lastIdentifiers.length; _i++) {
  138. var _index = getIndexByIdentifier(lastIdentifiers[_i]);
  139. if (0 === stylesInDOM[_index].references) {
  140. stylesInDOM[_index].updater();
  141. stylesInDOM.splice(_index, 1);
  142. }
  143. }
  144. lastIdentifiers = newLastIdentifiers;
  145. };
  146. };
  147. },
  148. 659: module => {
  149. var memo = {};
  150. module.exports = function insertBySelector(insert, style) {
  151. var target = function getTarget(target) {
  152. if (void 0 === memo[target]) {
  153. var styleTarget = document.querySelector(target);
  154. if (window.HTMLIFrameElement && styleTarget instanceof window.HTMLIFrameElement) try {
  155. styleTarget = styleTarget.contentDocument.head;
  156. } catch (e) {
  157. styleTarget = null;
  158. }
  159. memo[target] = styleTarget;
  160. }
  161. return memo[target];
  162. }(insert);
  163. if (!target) throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.");
  164. target.appendChild(style);
  165. };
  166. },
  167. 540: module => {
  168. module.exports = function insertStyleElement(options) {
  169. var element = document.createElement("style");
  170. options.setAttributes(element, options.attributes);
  171. options.insert(element, options.options);
  172. return element;
  173. };
  174. },
  175. 56: (module, __unused_webpack_exports, __webpack_require__) => {
  176. module.exports = function setAttributesWithoutAttributes(styleElement) {
  177. var nonce = true ? __webpack_require__.nc : 0;
  178. if (nonce) styleElement.setAttribute("nonce", nonce);
  179. };
  180. },
  181. 825: module => {
  182. module.exports = function domAPI(options) {
  183. if ("undefined" == typeof document) return {
  184. update: function update() {},
  185. remove: function remove() {}
  186. };
  187. var styleElement = options.insertStyleElement(options);
  188. return {
  189. update: function update(obj) {
  190. !function apply(styleElement, options, obj) {
  191. var css = "";
  192. if (obj.supports) css += "@supports (".concat(obj.supports, ") {");
  193. if (obj.media) css += "@media ".concat(obj.media, " {");
  194. var needLayer = void 0 !== obj.layer;
  195. if (needLayer) css += "@layer".concat(obj.layer.length > 0 ? " ".concat(obj.layer) : "", " {");
  196. css += obj.css;
  197. if (needLayer) css += "}";
  198. if (obj.media) css += "}";
  199. if (obj.supports) css += "}";
  200. var sourceMap = obj.sourceMap;
  201. if (sourceMap && "undefined" != typeof btoa) css += "\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))), " */");
  202. options.styleTagTransform(css, styleElement, options.options);
  203. }(styleElement, options, obj);
  204. },
  205. remove: function remove() {
  206. !function removeStyleElement(styleElement) {
  207. if (null === styleElement.parentNode) return false;
  208. styleElement.parentNode.removeChild(styleElement);
  209. }(styleElement);
  210. }
  211. };
  212. };
  213. },
  214. 113: module => {
  215. module.exports = function styleTagTransform(css, styleElement) {
  216. if (styleElement.styleSheet) styleElement.styleSheet.cssText = css; else {
  217. for (;styleElement.firstChild; ) styleElement.removeChild(styleElement.firstChild);
  218. styleElement.appendChild(document.createTextNode(css));
  219. }
  220. };
  221. }
  222. }, __webpack_module_cache__ = {};
  223. function __webpack_require__(moduleId) {
  224. var cachedModule = __webpack_module_cache__[moduleId];
  225. if (void 0 !== cachedModule) return cachedModule.exports;
  226. var module = __webpack_module_cache__[moduleId] = {
  227. id: moduleId,
  228. exports: {}
  229. };
  230. __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
  231. return module.exports;
  232. }
  233. __webpack_require__.n = module => {
  234. var getter = module && module.__esModule ? () => module.default : () => module;
  235. __webpack_require__.d(getter, {
  236. a: getter
  237. });
  238. return getter;
  239. };
  240. __webpack_require__.d = (exports, definition) => {
  241. for (var key in definition) if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) Object.defineProperty(exports, key, {
  242. enumerable: true,
  243. get: definition[key]
  244. });
  245. };
  246. __webpack_require__.o = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);
  247. __webpack_require__.nc = void 0;
  248. __webpack_require__.d({}, {
  249. yr: () => closeEmbedAfterOpenSetting,
  250. xe: () => loadingSpinSpeedFavSetting,
  251. _d: () => loadingSpinSpeedSetting,
  252. h_: () => openInNewTabSetting,
  253. e2: () => previewQualitySetting,
  254. uL: () => requestHelper
  255. });
  256. class EmbeddedHTML {
  257. static get html() {
  258. return '\n<div id="eiv-background">\n <a id="eiv-submission-container"></a>\n <div id="eiv-button-container">\n <div id="eiv-button-wrapper">\n <a id="eiv-fav-button" type="button" class="eiv-button button standard mobile-fix">⠀⠀</a>\n <a id="eiv-download-button" type="button" class="eiv-button button standard mobile-fix">Download</a>\n <a id="eiv-open-button" type="button" class="eiv-button button standard mobile-fix">Open</a>\n <a id="eiv-open-gallery-button" type="button" class="eiv-button button standard mobile-fix" style="display: none;">Open Gallery</a>\n <a id="eiv-remove-sub-button" type="button" class="eiv-button button standard mobile-fix" style="display: none;">Remove</a>\n <a id="eiv-close-button" type="button" class="eiv-button button standard mobile-fix">Close</a>\n </div>\n <div id="eiv-preview-spinner-container"></div>\n </div>\n</div>';
  259. }
  260. }
  261. var injectStylesIntoStyleTag = __webpack_require__(72), injectStylesIntoStyleTag_default = __webpack_require__.n(injectStylesIntoStyleTag), styleDomAPI = __webpack_require__(825), styleDomAPI_default = __webpack_require__.n(styleDomAPI), insertBySelector = __webpack_require__(659), insertBySelector_default = __webpack_require__.n(insertBySelector), setAttributesWithoutAttributes = __webpack_require__(56), setAttributesWithoutAttributes_default = __webpack_require__.n(setAttributesWithoutAttributes), insertStyleElement = __webpack_require__(540), insertStyleElement_default = __webpack_require__.n(insertStyleElement), styleTagTransform = __webpack_require__(113), styleTagTransform_default = __webpack_require__.n(styleTagTransform), Style = __webpack_require__(789), options = {};
  262. options.styleTagTransform = styleTagTransform_default();
  263. options.setAttributes = setAttributesWithoutAttributes_default();
  264. options.insert = insertBySelector_default().bind(null, "head");
  265. options.domAPI = styleDomAPI_default();
  266. options.insertStyleElement = insertStyleElement_default();
  267. injectStylesIntoStyleTag_default()(Style.A, options);
  268. Style.A && Style.A.locals && Style.A.locals;
  269. const string = class {
  270. static isNullOrWhitespace(str) {
  271. return null == str || "" === str.trim();
  272. }
  273. static isNullOrEmpty(str) {
  274. return null == str || "" === str;
  275. }
  276. };
  277. var LogLevel;
  278. !function(LogLevel) {
  279. LogLevel[LogLevel.Error = 1] = "Error";
  280. LogLevel[LogLevel.Warning = 2] = "Warning";
  281. LogLevel[LogLevel.Info = 3] = "Info";
  282. }(LogLevel || (LogLevel = {}));
  283. class Logger {
  284. static log(logLevel = LogLevel.Warning, ...args) {
  285. if (null == window.__FF_GLOBAL_LOG_LEVEL__) window.__FF_GLOBAL_LOG_LEVEL__ = LogLevel.Error;
  286. if (!(logLevel > window.__FF_GLOBAL_LOG_LEVEL__)) switch (logLevel) {
  287. case LogLevel.Error:
  288. console.error(...args);
  289. break;
  290.  
  291. case LogLevel.Warning:
  292. console.warn(...args);
  293. break;
  294.  
  295. case LogLevel.Info:
  296. console.log(...args);
  297. }
  298. }
  299. static setLogLevel(logLevel) {
  300. window.__FF_GLOBAL_LOG_LEVEL__ = logLevel;
  301. }
  302. static logError(...args) {
  303. Logger.log(LogLevel.Error, ...args);
  304. }
  305. static logWarning(...args) {
  306. Logger.log(LogLevel.Warning, ...args);
  307. }
  308. static logInfo(...args) {
  309. Logger.log(LogLevel.Info, ...args);
  310. }
  311. }
  312. var __awaiter = function(thisArg, _arguments, P, generator) {
  313. return new (P || (P = Promise))((function(resolve, reject) {
  314. function fulfilled(value) {
  315. try {
  316. step(generator.next(value));
  317. } catch (e) {
  318. reject(e);
  319. }
  320. }
  321. function rejected(value) {
  322. try {
  323. step(generator.throw(value));
  324. } catch (e) {
  325. reject(e);
  326. }
  327. }
  328. function step(result) {
  329. result.done ? resolve(result.value) : function adopt(value) {
  330. return value instanceof P ? value : new P((function(resolve) {
  331. resolve(value);
  332. }));
  333. }(result.value).then(fulfilled, rejected);
  334. }
  335. step((generator = generator.apply(thisArg, _arguments || [])).next());
  336. }));
  337. };
  338. const embeddedModes = {
  339. watchesFavoriteViewer: "wfv-favorites"
  340. };
  341. class EmbeddedImage extends EventTarget {
  342. constructor(figure) {
  343. super();
  344. this.favRequestRunning = false;
  345. this.downloadRequestRunning = false;
  346. this._imageLoaded = false;
  347. Object.setPrototypeOf(this, EmbeddedImage.prototype);
  348. this.embeddedElem = document.createElement("div");
  349. this.createElements(figure);
  350. const submissionContainer = document.getElementById("eiv-submission-container"), previewLoadingSpinnerContainer = document.getElementById("eiv-preview-spinner-container");
  351. this.loadingSpinner = new window.FALoadingSpinner(submissionContainer);
  352. this.loadingSpinner.delay = loadingSpinSpeedSetting.value;
  353. this.loadingSpinner.spinnerThickness = 6;
  354. this.loadingSpinner.visible = true;
  355. this.previewLoadingSpinner = new window.FALoadingSpinner(previewLoadingSpinnerContainer);
  356. this.previewLoadingSpinner.delay = loadingSpinSpeedSetting.value;
  357. this.previewLoadingSpinner.spinnerThickness = 4;
  358. this.previewLoadingSpinner.size = 40;
  359. document.addEventListener("click", this.onDocumentClick.bind(this));
  360. this.fillSubDocInfos(figure);
  361. }
  362. static get embeddedExists() {
  363. return null != document.getElementById("eiv-main");
  364. }
  365. get onRemove() {
  366. return this._onRemove;
  367. }
  368. set onRemove(handler) {
  369. this._onRemove = handler;
  370. }
  371. onDocumentClick(event) {
  372. if (event.target === document.documentElement) this.remove();
  373. }
  374. onOpenClick() {
  375. if (closeEmbedAfterOpenSetting.value) this.remove();
  376. }
  377. onRemoveSubClick(figure) {
  378. return __awaiter(this, void 0, void 0, (function*() {
  379. const sid = figure.id.trimStart("sid-");
  380. this.remove();
  381. figure.remove();
  382. yield requestHelper.PersonalUserRequests.MessageRequests.NewSubmissions.removeSubmissions([ sid ]);
  383. }));
  384. }
  385. invokeRemove() {
  386. var _a;
  387. null === (_a = this._onRemove) || void 0 === _a || _a.call(this);
  388. this.dispatchEvent(new Event("remove"));
  389. }
  390. remove() {
  391. var _a;
  392. null === (_a = this.embeddedElem.parentNode) || void 0 === _a || _a.removeChild(this.embeddedElem);
  393. document.removeEventListener("click", this.onDocumentClick);
  394. this.invokeRemove();
  395. }
  396. createElements(figure) {
  397. var _a;
  398. this.embeddedElem.id = "eiv-main";
  399. this.embeddedElem.setAttribute("eiv-sid", figure.id.trimStart("sid-"));
  400. this.embeddedElem.innerHTML = EmbeddedHTML.html;
  401. document.getElementById("ddmenu").appendChild(this.embeddedElem);
  402. this.embeddedElem.addEventListener("click", (event => {
  403. if (event.target === this.embeddedElem) this.remove();
  404. }));
  405. const submissionContainer = document.getElementById("eiv-submission-container");
  406. if (openInNewTabSetting.value) submissionContainer.setAttribute("target", "_blank");
  407. submissionContainer.addEventListener("click", this.onOpenClick.bind(this));
  408. const userLink = function getByLinkFromFigcaption(figcaption) {
  409. var _a, _b, _c;
  410. if (null != figcaption) {
  411. const infos = figcaption.querySelectorAll("i");
  412. let userLink = null;
  413. for (const info of Array.from(infos)) if (null !== (_b = null === (_a = info.textContent) || void 0 === _a ? void 0 : _a.toLowerCase().includes("by")) && void 0 !== _b ? _b : false) {
  414. const linkElem = null === (_c = info.parentNode) || void 0 === _c ? void 0 : _c.querySelector("a[href][title]");
  415. if (linkElem) userLink = linkElem.getAttribute("href");
  416. }
  417. return userLink;
  418. }
  419. return null;
  420. }(figure.querySelector("figcaption"));
  421. if (null != userLink) {
  422. const galleryLink = userLink.trimEnd("/").replace("user", "gallery"), scrapsLink = userLink.trimEnd("/").replace("user", "scraps");
  423. if (!window.location.toString().includes(userLink) && !window.location.toString().includes(galleryLink) && !window.location.toString().includes(scrapsLink)) {
  424. const openGalleryButton = document.getElementById("eiv-open-gallery-button");
  425. openGalleryButton.style.display = "block";
  426. openGalleryButton.setAttribute("href", galleryLink);
  427. if (openInNewTabSetting.value) openGalleryButton.setAttribute("target", "_blank");
  428. openGalleryButton.addEventListener("click", this.onOpenClick.bind(this));
  429. }
  430. }
  431. const link = null === (_a = figure.querySelector("a[href]")) || void 0 === _a ? void 0 : _a.getAttribute("href"), openButton = document.getElementById("eiv-open-button");
  432. openButton.setAttribute("href", null != link ? link : "");
  433. if (openInNewTabSetting.value) openButton.setAttribute("target", "_blank");
  434. openButton.addEventListener("click", this.onOpenClick.bind(this));
  435. document.getElementById("eiv-close-button").addEventListener("click", this.remove.bind(this));
  436. const embeddedModesValues = Object.values(embeddedModes);
  437. if (window.location.toString().toLowerCase().includes("msg/submissions") && embeddedModesValues.every((mode => !window.location.toString().toLocaleLowerCase().includes(mode)))) {
  438. const removeSubButton = document.getElementById("eiv-remove-sub-button");
  439. removeSubButton.style.display = "block";
  440. removeSubButton.addEventListener("click", (() => {
  441. this.onRemoveSubClick(figure);
  442. }));
  443. }
  444. document.getElementById("eiv-preview-spinner-container").addEventListener("click", (() => {
  445. this.previewLoadingSpinner.visible = false;
  446. }));
  447. }
  448. fillSubDocInfos(figure) {
  449. return __awaiter(this, void 0, void 0, (function*() {
  450. var _a, _b, _c;
  451. const sid = figure.id.split("-")[1], ddmenu = document.getElementById("ddmenu"), doc = yield requestHelper.SubmissionRequests.getSubmissionPage(sid);
  452. if (null != doc) {
  453. this.submissionImg = doc.getElementById("submissionImg");
  454. const imgSrc = this.submissionImg.src;
  455. let prevSrc = null !== (_a = this.submissionImg.getAttribute("data-preview-src")) && void 0 !== _a ? _a : void 0;
  456. if (!string.isNullOrWhitespace(prevSrc)) {
  457. Logger.logInfo("Preview quality @" + previewQualitySetting.value);
  458. prevSrc = null == prevSrc ? void 0 : prevSrc.replace("@600", "@" + previewQualitySetting.value);
  459. }
  460. const submissionContainer = document.getElementById("eiv-submission-container"), faImageViewer = new window.FAImageViewer(submissionContainer, imgSrc, prevSrc);
  461. faImageViewer.faImage.imgElem.id = "eiv-submission-img";
  462. faImageViewer.faImagePreview.imgElem.id = "eiv-preview-submission-img";
  463. faImageViewer.faImage.imgElem.classList.add("eiv-submission-img");
  464. faImageViewer.faImagePreview.imgElem.classList.add("eiv-submission-img");
  465. faImageViewer.faImage.imgElem.style.maxWidth = faImageViewer.faImagePreview.imgElem.style.maxWidth = window.innerWidth - 40 + "px";
  466. faImageViewer.faImage.imgElem.style.maxHeight = faImageViewer.faImagePreview.imgElem.style.maxHeight = window.innerHeight - ddmenu.clientHeight - 76 - 40 - 100 + "px";
  467. faImageViewer.addEventListener("image-load-start", (() => {
  468. this._imageLoaded = false;
  469. }));
  470. faImageViewer.addEventListener("image-load", (() => {
  471. this._imageLoaded = true;
  472. this.loadingSpinner.visible = false;
  473. this.previewLoadingSpinner.visible = false;
  474. }));
  475. faImageViewer.addEventListener("preview-image-load", (() => {
  476. this.loadingSpinner.visible = false;
  477. if (!this._imageLoaded) this.previewLoadingSpinner.visible = true;
  478. }));
  479. faImageViewer.load();
  480. const url = null === (_b = doc.querySelector('meta[property="og:url"]')) || void 0 === _b ? void 0 : _b.getAttribute("content");
  481. submissionContainer.setAttribute("href", null != url ? url : "");
  482. const result = function getFavKey(doc) {
  483. var _a, _b, _c, _d, _e, _f, _g;
  484. const columnPage = doc.getElementById("columnpage"), navbar = null == columnPage ? void 0 : columnPage.querySelector('div[class*="favorite-nav"]'), buttons = null !== (_a = null == navbar ? void 0 : navbar.querySelectorAll('a[class*="button"][href]')) && void 0 !== _a ? _a : [];
  485. let favButton;
  486. for (const button of Array.from(buttons)) if (null !== (_c = null === (_b = button.textContent) || void 0 === _b ? void 0 : _b.toLowerCase().includes("fav")) && void 0 !== _c ? _c : false) favButton = button;
  487. if (null != favButton) return {
  488. favKey: null !== (_e = null === (_d = favButton.getAttribute("href")) || void 0 === _d ? void 0 : _d.split("?key=")[1]) && void 0 !== _e ? _e : null,
  489. isFav: !(null !== (_g = null === (_f = favButton.getAttribute("href")) || void 0 === _f ? void 0 : _f.toLowerCase().includes("unfav")) && void 0 !== _g ? _g : true)
  490. };
  491. return null;
  492. }(doc), favButton = document.getElementById("eiv-fav-button");
  493. if (null == result) favButton.style.display = "none"; else {
  494. favButton.textContent = result.isFav ? "+Fav" : "-Fav";
  495. favButton.setAttribute("isFav", result.isFav.toString());
  496. favButton.setAttribute("key", null !== (_c = result.favKey) && void 0 !== _c ? _c : "");
  497. favButton.addEventListener("click", (() => {
  498. if (!this.favRequestRunning) this.doFavRequest(sid);
  499. }));
  500. }
  501. const downloadButton = document.getElementById("eiv-download-button");
  502. downloadButton.addEventListener("click", (() => {
  503. if (this.downloadRequestRunning) return;
  504. this.downloadRequestRunning = true;
  505. const loadingTextSpinner = new window.FALoadingTextSpinner(downloadButton);
  506. loadingTextSpinner.delay = loadingSpinSpeedFavSetting.value;
  507. loadingTextSpinner.visible = true;
  508. const iframe = document.createElement("iframe");
  509. iframe.style.display = "none";
  510. iframe.src = this.submissionImg.src + "?eiv-download";
  511. iframe.addEventListener("load", (() => {
  512. this.downloadRequestRunning = false;
  513. loadingTextSpinner.visible = false;
  514. setTimeout((() => {
  515. var _a;
  516. return null === (_a = iframe.parentNode) || void 0 === _a ? void 0 : _a.removeChild(iframe);
  517. }), 100);
  518. }));
  519. document.body.appendChild(iframe);
  520. }));
  521. }
  522. }));
  523. }
  524. doFavRequest(sid) {
  525. return __awaiter(this, void 0, void 0, (function*() {
  526. var _a, _b, _c;
  527. const favButton = document.getElementById("eiv-fav-button");
  528. this.favRequestRunning = true;
  529. const loadingTextSpinner = new window.FALoadingTextSpinner(favButton);
  530. loadingTextSpinner.delay = loadingSpinSpeedFavSetting.value;
  531. loadingTextSpinner.visible = true;
  532. let favKey = null !== (_a = favButton.getAttribute("key")) && void 0 !== _a ? _a : "", isFav = "true" === favButton.getAttribute("isFav");
  533. if (!string.isNullOrWhitespace(favKey)) {
  534. if (isFav) {
  535. favKey = null !== (_b = yield requestHelper.SubmissionRequests.favSubmission(sid, favKey)) && void 0 !== _b ? _b : "";
  536. loadingTextSpinner.visible = false;
  537. if (!string.isNullOrWhitespace(favKey)) {
  538. favButton.setAttribute("key", favKey);
  539. isFav = false;
  540. favButton.setAttribute("isFav", isFav.toString());
  541. favButton.textContent = "-Fav";
  542. } else {
  543. favButton.textContent = "x";
  544. setTimeout((() => favButton.textContent = "+Fav"), 1e3);
  545. }
  546. } else {
  547. favKey = null !== (_c = yield requestHelper.SubmissionRequests.unfavSubmission(sid, favKey)) && void 0 !== _c ? _c : "";
  548. loadingTextSpinner.visible = false;
  549. if (!string.isNullOrWhitespace(favKey)) {
  550. favButton.setAttribute("key", favKey);
  551. isFav = true;
  552. favButton.setAttribute("isFav", isFav.toString());
  553. favButton.textContent = "+Fav";
  554. } else {
  555. favButton.textContent = "x";
  556. setTimeout((() => favButton.textContent = "-Fav"), 1e3);
  557. }
  558. }
  559. this.favRequestRunning = false;
  560. } else favButton.textContent = "x";
  561. }));
  562. }
  563. static addEmbeddedEventForAllFigures() {
  564. return __awaiter(this, void 0, void 0, (function*() {
  565. var _a;
  566. const nonEmbeddedFigures = null !== (_a = document.querySelectorAll("figure:not([embedded])")) && void 0 !== _a ? _a : [];
  567. for (const figure of Array.from(nonEmbeddedFigures)) {
  568. figure.setAttribute("embedded", "true");
  569. figure.addEventListener("click", (event => {
  570. if (event instanceof MouseEvent && event.target instanceof HTMLElement) if (!event.ctrlKey && !event.target.id.includes("favbutton") && "checkbox" !== event.target.getAttribute("type")) {
  571. if (!string.isNullOrWhitespace(event.target.getAttribute("href"))) return;
  572. event.preventDefault();
  573. if (!EmbeddedImage.embeddedExists && figure instanceof HTMLElement) new EmbeddedImage(figure);
  574. }
  575. }));
  576. }
  577. }));
  578. }
  579. }
  580. const customSettings = new window.FACustomSettings("Midori's Script Settings", "FA Embedded Image Viewer Settings"), openInNewTabSetting = customSettings.newSetting(window.FASettingType.Boolean, "Open in new Tab");
  581. openInNewTabSetting.description = "Wether to open links in a new Tab or the current one.";
  582. openInNewTabSetting.defaultValue = true;
  583. const loadingSpinSpeedFavSetting = customSettings.newSetting(window.FASettingType.Number, "Fav Loading Animation");
  584. loadingSpinSpeedFavSetting.description = "The duration that the loading animation, for faving a submission, takes for a full rotation in milliseconds.";
  585. loadingSpinSpeedFavSetting.defaultValue = 600;
  586. const loadingSpinSpeedSetting = customSettings.newSetting(window.FASettingType.Number, "Embedded Loading Animation");
  587. loadingSpinSpeedSetting.description = "The duration that the loading animation of the Embedded element to load takes for a full rotation in milliseconds.";
  588. loadingSpinSpeedSetting.defaultValue = 1e3;
  589. const closeEmbedAfterOpenSetting = customSettings.newSetting(window.FASettingType.Boolean, "Close Embed after open");
  590. closeEmbedAfterOpenSetting.description = "Wether to close the current embedded Submission after it is opened in a new Tab (also for open Gallery).";
  591. closeEmbedAfterOpenSetting.defaultValue = true;
  592. const previewQualitySetting = customSettings.newSetting(window.FASettingType.Option, "Preview Quality");
  593. previewQualitySetting.description = "The quality of the preview image. Value range is 2-6. (Higher values can be slower)";
  594. previewQualitySetting.defaultValue = 400;
  595. previewQualitySetting.options = {
  596. 200: "Very Low",
  597. 300: "Low",
  598. 400: "Medium",
  599. 500: "High",
  600. 600: "Very High"
  601. };
  602. customSettings.loadSettings();
  603. const requestHelper = new window.FARequestHelper(2);
  604. if (customSettings.isFeatureEnabled) {
  605. const matchList = new window.FAMatchList(customSettings);
  606. matchList.matches = [ "net/browse", "net/user", "net/gallery", "net/search", "net/favorites", "net/scraps", "net/controls/favorites", "net/controls/submissions", "net/msg/submissions", "d.furaffinity.net" ];
  607. matchList.runInIFrame = true;
  608. if (matchList.hasMatch) {
  609. const page = new window.FACustomPage("d.furaffinity.net", "eiv-download");
  610. let pageDownload = false;
  611. page.addEventListener("onOpen", (() => {
  612. !function downloadImage() {
  613. let url = window.location.toString();
  614. if (url.includes("?")) {
  615. const parts = url.split("?");
  616. url = parts[0];
  617. }
  618. const download = document.createElement("a");
  619. download.href = url;
  620. download.download = url.substring(url.lastIndexOf("/") + 1);
  621. download.style.display = "none";
  622. document.body.appendChild(download);
  623. download.click();
  624. document.body.removeChild(download);
  625. window.close();
  626. }();
  627. pageDownload = true;
  628. }));
  629. page.checkPageOpened();
  630. if (!pageDownload && !matchList.isWindowIFrame) {
  631. EmbeddedImage.addEmbeddedEventForAllFigures();
  632. window.addEventListener("ei-update-embedded", (() => {
  633. EmbeddedImage.addEmbeddedEventForAllFigures();
  634. }));
  635. }
  636. }
  637. }
  638. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址