nfmzkvmx
Junior Member | Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору В инициализацию. Можно в существующую кнопку. В контекстном меню ссылок, выделенных текстовых ссылок и текста, оканчивающихся на ".m3u", добавится пункт "Сохранить плейлист m3u...". По клику по которому, полученное по запросу по ссылке, сохранится на рабочий стол. Проверял только в 52-ой esr, с отключенной мультипроцессностью и с пофикшеным Custom Buttons. Не универсально, так что если на каких-то ссылках ошибку выдает - напишите. Попробую поправить. И если с включенным e10s не работает, тоже напишите, потыкаюсь потом. Код: ((listener, popup = document.getElementById("contentAreaContextMenu")) => { addEventListener("popupshowing", listener, false, popup); addDestructor(() => removeEventListener("popupshowing", listener, false, popup)) })({ deskFolder: OS.Constants.Path.desktopDir, tmpPath: OS.Path.join(OS.Constants.Path.tmpDir, 'm3u.tmp'), lbl: "Сохранить плейлист m3u...", alertS: Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService), slider(txt) { return this.alertS.showAlertNotification("", this.lbl, txt, false, "", null, "") }, saveToFile([str, name]) { const enc = new TextEncoder(), arr = enc.encode(str); let filePath, fileName = new Date().toLocaleFormat("%e.%m.%Y (%H-%M-%S) - ") + name.match(/[^/]+$/)[0]; fileName = fileName.endsWith(".m3u") ? fileName : fileName + ".m3u"; filePath = OS.Path.join(this.deskFolder, fileName); return OS.File.writeAtomic(filePath, arr, {tmpPath: this.tmpPath}) }, xhr(url) { return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(), error = err => reject(xhr.statusText + " [" + err.type + ": " + xhr.status + "]"); xhr.mozBackgroundRequest = true; xhr.open("GET", url); xhr.channel.loadFlags |= Ci.nsIRequest.LOAD_ANONYMOUS | Ci.nsIRequest.LOAD_BYPASS_CACHE | Ci.nsIRequest.INHIBIT_CACHING; xhr.timeout = 10000; xhr.onload = e => xhr.status == 200 && xhr.responseText && resolve([xhr.responseText, xhr.responseURL]) || error(e);; xhr.onerror = xhr.onabort = xhr.ontimeout = er => error(er); xhr.send(null); }) }, get node() { delete this.node; return this.node = this.createNode() }, createNode() { let mItem; if (!mItem) { let cMenu = document.getElementById("contentAreaContextMenu"); mItem = document.createElement("menuitem"); cMenu.insertBefore(mItem, document.getElementById("context-savelink")); mItem.setAttribute("label", this.lbl); mItem.onclick = () => this.xhr(this.link()).then( response => this.saveToFile(response).then( success => this.slider("Успешно сохранено!") , error => this.slider("Ошибка при сохранении на диск:\n\t" + error) ) , error => this.slider("Не удалось получить файл:\n\t" + error) ) addDestructor(() => cMenu.removeChild(mItem)) } return mItem; }, link() { return gContextMenu.linkURL || gContextMenu.textSelected.trim() }, shouldShow() { let link = this.link(); return !!((gContextMenu.onPlainTextLink || gContextMenu.onLink) && link.endsWith(".m3u") || gContextMenu.isTextSelected && /^http.+\.m3u$/.test(link)); }, handleEvent(e) { this.node.hidden = !this.shouldShow(); } }); | |