From 2eca89e6723c6540414e4ffbef0ac439fc0c9257 Mon Sep 17 00:00:00 2001 From: Xmader Date: Sun, 27 Dec 2020 23:51:37 -0500 Subject: [PATCH] feat: view score in LibreScore --- src/btn.ts | 15 ++++++++++++--- src/librescore-link.ts | 25 +++++++++++++++++++++++++ src/main.ts | 10 +++++++++- src/scoreinfo.ts | 5 +++++ 4 files changed, 51 insertions(+), 4 deletions(-) create mode 100644 src/librescore-link.ts diff --git a/src/btn.ts b/src/btn.ts index 1047f8f..2acfd56 100644 --- a/src/btn.ts +++ b/src/btn.ts @@ -9,6 +9,11 @@ import btnListCss from './btn.css' type BtnElement = HTMLButtonElement +export enum ICON { + DOWNLOAD = 'M9.6 2.4h4.8V12h2.784l-5.18 5.18L6.823 12H9.6V2.4zM19.2 19.2H4.8v2.4h14.4v-2.4z', + LIBRESCORE = 'm5.4837 4.4735v10.405c-1.25-0.89936-3.0285-0.40896-4.1658 0.45816-1.0052 0.76659-1.7881 2.3316-0.98365 3.4943 1 1.1346 2.7702 0.70402 3.8817-0.02809 1.0896-0.66323 1.9667-1.8569 1.8125-3.1814v-5.4822h8.3278v9.3865h9.6438v-2.6282h-6.4567v-12.417c-4.0064-0.015181-8.0424-0.0027-12.06-0.00676zm0.54477 2.2697h8.3278v1.1258h-8.3278v-1.1258z', +} + const getBtnContainer = (): HTMLDivElement => { const els = [...document.querySelectorAll('*')].reverse() const el = els.find(b => { @@ -20,7 +25,7 @@ const getBtnContainer = (): HTMLDivElement => { return btnParent } -const buildDownloadBtn = () => { +const buildDownloadBtn = (icon: ICON) => { const btn = document.createElement('button') btn.type = 'button' @@ -28,7 +33,7 @@ const buildDownloadBtn = () => { const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg') svg.setAttribute('viewBox', '0 0 24 24') const svgPath = document.createElementNS('http://www.w3.org/2000/svg', 'path') - 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') + svgPath.setAttribute('d', icon) svgPath.setAttribute('fill', '#fff') svg.append(svgPath) @@ -49,6 +54,7 @@ interface BtnOptions { readonly action: BtnAction; readonly disabled?: boolean; readonly tooltip?: string; + readonly icon?: ICON; } export enum BtnListMode { @@ -62,7 +68,7 @@ export class BtnList { constructor (private getBtnParent: () => HTMLDivElement = getBtnContainer) { } add (options: BtnOptions): BtnElement { - const btnTpl = buildDownloadBtn() + const btnTpl = buildDownloadBtn(options.icon ?? ICON.DOWNLOAD) const setText = (btn: BtnElement) => { const textNode = btn.querySelector('span') return (str: string): void => { @@ -186,10 +192,13 @@ export namespace BtnAction { const _url = await normalizeUrlInput(url) const a = document.createElement('a') a.href = _url + a.target = '_blank' a.dispatchEvent(new MouseEvent('click')) }, fallback, timeout) } + export const openUrl = download + export const mscoreWindow = (scoreinfo: ScoreInfo, fn: (w: Window, score: WebMscore, processingTextEl: ChildNode) => any): BtnAction => { return async (btnName, btn, setText) => { const _onclick = btn.onclick diff --git a/src/librescore-link.ts b/src/librescore-link.ts new file mode 100644 index 0000000..04d8044 --- /dev/null +++ b/src/librescore-link.ts @@ -0,0 +1,25 @@ +import { assertRes, getFetch } from './utils' +import { getMainCid } from './mscz' +import { ScoreInfo } from './scoreinfo' + +const _getLink = (scorepack: string) => { + return `https://librescore.org/score/${scorepack}` +} + +export const getLibreScoreLink = async (scoreinfo: ScoreInfo, _fetch = getFetch()): Promise => { + const mainCid = await getMainCid(scoreinfo, _fetch) + const ref = scoreinfo.getScorepackRef(mainCid) + const url = `https://ipfs.infura.io:5001/api/v0/dag/get?arg=${ref}` + + const r0 = await _fetch(url) + if (r0.status !== 500) { + assertRes(r0) + } + const res: { Message: string } | string = await r0.json() + if (typeof res !== 'string') { + // read further error msg + throw new Error(res.Message) + } + + return _getLink(res) +} diff --git a/src/main.ts b/src/main.ts index dc3459d..2b1037a 100644 --- a/src/main.ts +++ b/src/main.ts @@ -6,7 +6,8 @@ import { downloadPDF } from './pdf' import { downloadMscz } from './mscz' import { getFileUrl } from './file' import { INDV_DOWNLOADS } from './mscore' -import { BtnList, BtnAction, BtnListMode } from './btn' +import { getLibreScoreLink } from './librescore-link' +import { BtnList, BtnAction, BtnListMode, ICON } from './btn' import { ScoreInfoInPage, SheetInfoInPage, getActualId } from './scoreinfo' import i18n from './i18n' @@ -131,6 +132,13 @@ const main = (): void => { }), }) + btnList.add({ + name: 'View in LibreScore', + action: BtnAction.openUrl(() => getLibreScoreLink(scoreinfo)), + tooltip: 'BETA', + icon: ICON.LIBRESCORE, + }) + btnList.commit(BtnListMode.InPage) } diff --git a/src/scoreinfo.ts b/src/scoreinfo.ts index 4e67ee5..70059f4 100644 --- a/src/scoreinfo.ts +++ b/src/scoreinfo.ts @@ -4,6 +4,7 @@ import { getMainCid } from './mscz' export abstract class ScoreInfo { private readonly RADIX = 20; + private readonly INDEX_RADIX = 40; abstract id: number; abstract title: string; @@ -25,6 +26,10 @@ export abstract class ScoreInfo { public getMsczCidUrl (mainCid: string): string { return `https://ipfs.infura.io:5001/api/v0/block/stat?arg=${this.getMsczIpfsRef(mainCid)}` } + + public getScorepackRef (mainCid: string): string { + return `/ipfs/${mainCid}/index/${(+this.id) % this.INDEX_RADIX}/${this.id}/scorepack` + } } export class ScoreInfoObj extends ScoreInfo {