2019-11-03 19:13:06 +00:00
|
|
|
import "./meta"
|
|
|
|
|
|
|
|
import { ScorePlayerData } from "./types"
|
2019-12-01 05:16:07 +00:00
|
|
|
import { waitForDocumentLoaded } from "./utils"
|
2020-03-08 21:36:37 +00:00
|
|
|
import * as recaptcha from "./recaptcha"
|
2019-11-03 19:13:06 +00:00
|
|
|
|
2019-12-01 23:30:38 +00:00
|
|
|
import { PDFWorkerHelper } from "./worker-helper"
|
|
|
|
import FileSaver from "file-saver/dist/FileSaver.js"
|
|
|
|
|
|
|
|
const saveAs: typeof import("file-saver").saveAs = FileSaver.saveAs
|
2019-12-01 09:11:40 +00:00
|
|
|
|
|
|
|
let pdfBlob: Blob
|
2019-12-01 07:10:51 +00:00
|
|
|
|
2020-01-26 06:32:54 +00:00
|
|
|
const generatePDF = async (imgURLs: string[], imgType: "svg" | "png", name?: string) => {
|
2019-12-01 09:38:26 +00:00
|
|
|
if (pdfBlob) {
|
|
|
|
return saveAs(pdfBlob, `${name}.pdf`)
|
|
|
|
}
|
|
|
|
|
2020-02-27 11:52:43 +00:00
|
|
|
const cachedImg = document.querySelector("img[src*=score_]") as HTMLImageElement
|
2019-12-01 09:38:26 +00:00
|
|
|
const { naturalWidth: width, naturalHeight: height } = cachedImg
|
|
|
|
|
2019-12-01 23:30:38 +00:00
|
|
|
const worker = new PDFWorkerHelper()
|
2020-01-26 06:32:54 +00:00
|
|
|
const pdfArrayBuffer = await worker.generatePDF(imgURLs, imgType, width, height)
|
2019-12-01 23:30:38 +00:00
|
|
|
worker.terminate()
|
2019-12-01 07:10:51 +00:00
|
|
|
|
2019-12-01 23:30:38 +00:00
|
|
|
pdfBlob = new Blob([pdfArrayBuffer])
|
2019-12-01 09:11:40 +00:00
|
|
|
|
2019-12-01 23:30:38 +00:00
|
|
|
saveAs(pdfBlob, `${name}.pdf`)
|
2019-12-01 07:10:51 +00:00
|
|
|
}
|
|
|
|
|
2019-12-01 09:38:26 +00:00
|
|
|
const getPagesNumber = (scorePlayerData: ScorePlayerData) => {
|
|
|
|
try {
|
|
|
|
return scorePlayerData.json.metadata.pages
|
|
|
|
} catch (_) {
|
2020-02-27 11:52:43 +00:00
|
|
|
return document.querySelectorAll("img[src*=score_]").length
|
2019-12-01 09:38:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-01 23:30:38 +00:00
|
|
|
const getImgType = (): "svg" | "png" => {
|
|
|
|
try {
|
2020-02-27 11:52:43 +00:00
|
|
|
const imgE: HTMLImageElement = document.querySelector("img[src*=score_]")
|
2019-12-01 23:30:38 +00:00
|
|
|
const { pathname } = new URL(imgE.src)
|
|
|
|
const imgtype = pathname.match(/\.(\w+)$/)[1]
|
|
|
|
return imgtype as "svg" | "png"
|
|
|
|
} catch (_) {
|
|
|
|
return null
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-01 07:10:51 +00:00
|
|
|
const getTitle = (scorePlayerData: ScorePlayerData) => {
|
|
|
|
try {
|
|
|
|
return scorePlayerData.json.metadata.title
|
|
|
|
} catch (_) {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const getScoreFileName = (scorePlayerData: ScorePlayerData) => {
|
2020-01-26 06:32:54 +00:00
|
|
|
return getTitle(scorePlayerData).replace(/[\s<>:{}"/\\|?*~.\0\cA-\cZ]+/g, "_")
|
2019-12-01 07:10:51 +00:00
|
|
|
}
|
|
|
|
|
2019-11-29 23:07:43 +00:00
|
|
|
const main = () => {
|
2019-11-03 19:13:06 +00:00
|
|
|
|
2019-12-01 05:13:14 +00:00
|
|
|
// @ts-ignore
|
|
|
|
if (!window.UGAPP || !window.UGAPP.store || !window.UGAPP.store.jmuse_settings) { return }
|
|
|
|
|
2020-03-08 21:36:37 +00:00
|
|
|
// init recaptcha
|
|
|
|
recaptcha.init()
|
|
|
|
|
2019-11-29 23:07:43 +00:00
|
|
|
// @ts-ignore
|
|
|
|
const scorePlayer: ScorePlayerData = window.UGAPP.store.jmuse_settings.score_player
|
|
|
|
|
2019-12-01 05:16:07 +00:00
|
|
|
const { id } = scorePlayer.json
|
2019-11-29 23:07:43 +00:00
|
|
|
const baseURL = scorePlayer.urls.image_path
|
2019-11-03 19:13:06 +00:00
|
|
|
|
2019-12-01 05:16:07 +00:00
|
|
|
// const msczURL = `https://musescore.com/static/musescore/scoredata/score/${getIndexPath(id)}/${id}/score_${vid}_${scoreHexId}.mscz`
|
|
|
|
|
|
|
|
// https://github.com/Xmader/cloudflare-worker-musescore-mscz
|
2020-03-08 21:36:37 +00:00
|
|
|
const msczURL = `https://musescore.now.sh/api/mscz?id=${id}&token=`
|
2019-12-01 05:16:07 +00:00
|
|
|
|
2019-11-29 23:07:43 +00:00
|
|
|
const mxlURL = baseURL + "score.mxl"
|
|
|
|
const { midi: midiURL, mp3: mp3URL } = scorePlayer.urls
|
|
|
|
|
2020-02-15 21:30:10 +00:00
|
|
|
const btnsDiv = document.querySelector(".score-right .buttons-wrapper") || document.querySelectorAll("aside section > div")[4]
|
2019-11-29 23:07:43 +00:00
|
|
|
const downloadBtn = btnsDiv.querySelector("button, .button") as HTMLElement
|
|
|
|
downloadBtn.onclick = null
|
|
|
|
|
2020-03-29 21:31:33 +00:00
|
|
|
// fix the icon of the download btn
|
|
|
|
// if the `downloadBtn` seleted was a `Print` btn, replace the `print` icon with the `download` icon
|
|
|
|
const svgPath: SVGPathElement = downloadBtn.querySelector("svg > path")
|
|
|
|
if(svgPath) {
|
|
|
|
svgPath.setAttribute("d", "M9.6 2.4h4.8V12h2.784l-5.18 5.18L6.823 12H9.6V2.4zM19.2 19.2H4.8v2.4h14.4v-2.4z")
|
|
|
|
}
|
|
|
|
|
2019-12-01 23:30:38 +00:00
|
|
|
const imgType = getImgType() || "svg"
|
|
|
|
|
2020-01-26 06:32:54 +00:00
|
|
|
const sheetImgURLs = Array.from({ length: getPagesNumber(scorePlayer) }).fill(null).map((_, i) => {
|
2019-12-01 23:30:38 +00:00
|
|
|
return baseURL + `score_${i}.${imgType}`
|
2019-12-01 09:38:26 +00:00
|
|
|
})
|
|
|
|
|
2019-11-29 23:07:43 +00:00
|
|
|
const downloadURLs = {
|
2019-12-01 18:21:59 +00:00
|
|
|
"MSCZ": msczURL,
|
2019-12-01 07:10:51 +00:00
|
|
|
"PDF": null,
|
2019-11-29 23:07:43 +00:00
|
|
|
"MusicXML": mxlURL,
|
|
|
|
"MIDI": midiURL,
|
|
|
|
"MP3": mp3URL,
|
2019-11-03 20:21:59 +00:00
|
|
|
}
|
2019-11-03 20:12:15 +00:00
|
|
|
|
2019-12-01 07:10:51 +00:00
|
|
|
const createBtn = (name: string) => {
|
2019-11-29 23:07:43 +00:00
|
|
|
const btn = downloadBtn.cloneNode(true) as HTMLElement
|
|
|
|
|
|
|
|
if (btn.nodeName.toLowerCase() == "button") {
|
|
|
|
btn.setAttribute("style", "width: 205px !important")
|
|
|
|
} else {
|
|
|
|
btn.dataset.target = ""
|
|
|
|
}
|
|
|
|
|
2019-12-01 07:10:51 +00:00
|
|
|
const textNode = [...btn.childNodes].find((x) => {
|
2020-03-29 11:51:24 +00:00
|
|
|
return x.textContent.includes("Download") || x.textContent.includes("Print")
|
2019-11-29 23:07:43 +00:00
|
|
|
})
|
2019-12-01 07:10:51 +00:00
|
|
|
textNode.textContent = `Download ${name}`
|
|
|
|
|
|
|
|
return {
|
|
|
|
btn,
|
|
|
|
textNode,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const newDownloadBtns = Object.keys(downloadURLs).map((name) => {
|
|
|
|
const url = downloadURLs[name]
|
|
|
|
const { btn, textNode } = createBtn(name)
|
|
|
|
|
2020-03-08 21:36:37 +00:00
|
|
|
if (name == "PDF") {
|
2019-12-01 07:10:51 +00:00
|
|
|
btn.onclick = () => {
|
|
|
|
const text = textNode.textContent
|
2019-12-01 09:38:26 +00:00
|
|
|
const filename = getScoreFileName(scorePlayer)
|
|
|
|
|
2019-12-01 07:10:51 +00:00
|
|
|
textNode.textContent = "Processing…"
|
2019-12-01 09:38:26 +00:00
|
|
|
|
2020-01-26 06:32:54 +00:00
|
|
|
generatePDF(sheetImgURLs, imgType, filename).then(() => {
|
2019-12-01 07:10:51 +00:00
|
|
|
textNode.textContent = text
|
|
|
|
})
|
|
|
|
}
|
2020-03-08 21:36:37 +00:00
|
|
|
} else if (name == "MSCZ") {
|
|
|
|
btn.onclick = async () => {
|
2020-03-08 21:44:20 +00:00
|
|
|
const text = textNode.textContent
|
|
|
|
textNode.textContent = "Processing…"
|
|
|
|
|
2020-03-08 21:36:37 +00:00
|
|
|
const token = await recaptcha.execute()
|
2020-03-08 21:44:20 +00:00
|
|
|
const filename = getScoreFileName(scorePlayer)
|
|
|
|
|
|
|
|
const r = await fetch(url + token)
|
|
|
|
const data = await r.blob()
|
|
|
|
|
|
|
|
textNode.textContent = text
|
|
|
|
|
|
|
|
saveAs(data, `${filename}.mscz`)
|
2020-03-08 21:36:37 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
btn.onclick = () => {
|
|
|
|
window.open(url)
|
|
|
|
}
|
2019-12-01 07:10:51 +00:00
|
|
|
}
|
2019-11-29 23:07:43 +00:00
|
|
|
|
|
|
|
return btn
|
2019-11-03 20:21:59 +00:00
|
|
|
})
|
2019-11-03 20:01:29 +00:00
|
|
|
|
2019-11-29 23:07:43 +00:00
|
|
|
downloadBtn.replaceWith(...newDownloadBtns)
|
|
|
|
|
|
|
|
}
|
2019-11-03 19:13:06 +00:00
|
|
|
|
2019-11-29 23:07:43 +00:00
|
|
|
waitForDocumentLoaded().then(main)
|