@uimaxbai/am-lyrics 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -32,6 +32,10 @@ export declare class AmLyrics extends LitElement {
32
32
  private mainWordProgress;
33
33
  private backgroundWordProgress;
34
34
  private lyricsSource;
35
+ private availableSources;
36
+ private currentSourceIndex;
37
+ private isFetchingAlternatives;
38
+ private hasFetchedAllProviders;
35
39
  private animationFrameId?;
36
40
  private mainWordAnimations;
37
41
  private backgroundWordAnimations;
@@ -58,6 +62,9 @@ export declare class AmLyrics extends LitElement {
58
62
  private fetchLyrics;
59
63
  private onLyricsLoaded;
60
64
  private autoProcessLyrics;
65
+ private static getRankForCollected;
66
+ private static mergeAndSortSources;
67
+ private switchSource;
61
68
  private resolveSongMetadata;
62
69
  private static parseQueryMetadata;
63
70
  private static searchLyricsPlusCatalog;
@@ -1 +1 @@
1
- {"version":3,"file":"AmLyrics.d.ts","sourceRoot":"","sources":["../../src/AmLyrics.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AmLyrics.d.ts","sourceRoot":"","sources":["../../src/AmLyrics.ts"],"names":[],"mappings":"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"}
@@ -45,7 +45,7 @@ const t$1=globalThis,e$4=t$1.ShadowRoot&&(void 0===t$1.ShadyCSS||t$1.ShadyCSS.na
45
45
  * Copyright 2017 Google LLC
46
46
  * SPDX-License-Identifier: BSD-3-Clause
47
47
  */
48
- const t=globalThis,i$1=t=>t,s$1=t.trustedTypes,e$2=s$1?s$1.createPolicy("lit-html",{createHTML:t=>t}):void 0,h="$lit$",o$2=`lit$${Math.random().toFixed(9).slice(2)}$`,n$1="?"+o$2,r$2=`<${n$1}>`,l=document,c=()=>l.createComment(""),a=t=>null===t||"object"!=typeof t&&"function"!=typeof t,u=Array.isArray,d=t=>u(t)||"function"==typeof t?.[Symbol.iterator],f="[ \t\n\f\r]",v=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,_=/-->/g,m=/>/g,p=RegExp(`>|${f}(?:([^\\s"'>=/]+)(${f}*=${f}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),g=/'/g,$=/"/g,y=/^(?:script|style|textarea|title)$/i,x=t=>(i,...s)=>({_$litType$:t,strings:i,values:s}),b=x(1),E=Symbol.for("lit-noChange"),A=Symbol.for("lit-nothing"),C=new WeakMap,P=l.createTreeWalker(l,129);function V(t,i){if(!u(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==e$2?e$2.createHTML(i):i}const N=(t,i)=>{const s=t.length-1,e=[];let n,l=2===i?"<svg>":3===i?"<math>":"",c=v;for(let i=0;i<s;i++){const s=t[i];let a,u,d=-1,f=0;for(;f<s.length&&(c.lastIndex=f,u=c.exec(s),null!==u);)f=c.lastIndex,c===v?"!--"===u[1]?c=_:void 0!==u[1]?c=m:void 0!==u[2]?(y.test(u[2])&&(n=RegExp("</"+u[2],"g")),c=p):void 0!==u[3]&&(c=p):c===p?">"===u[0]?(c=n??v,d=-1):void 0===u[1]?d=-2:(d=c.lastIndex-u[2].length,a=u[1],c=void 0===u[3]?p:'"'===u[3]?$:g):c===$||c===g?c=p:c===_||c===m?c=v:(c=p,n=void 0);const x=c===p&&t[i+1].startsWith("/>")?" ":"";l+=c===v?s+r$2:d>=0?(e.push(a),s.slice(0,d)+h+s.slice(d)+o$2+x):s+o$2+(-2===d?i:x);}return [V(t,l+(t[s]||"<?>")+(2===i?"</svg>":3===i?"</math>":"")),e]};class S{constructor({strings:t,_$litType$:i},e){let r;this.parts=[];let l=0,a=0;const u=t.length-1,d=this.parts,[f,v]=N(t,i);if(this.el=S.createElement(f,e),P.currentNode=this.el.content,2===i||3===i){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes);}for(;null!==(r=P.nextNode())&&d.length<u;){if(1===r.nodeType){if(r.hasAttributes())for(const t of r.getAttributeNames())if(t.endsWith(h)){const i=v[a++],s=r.getAttribute(t).split(o$2),e=/([.?@])?(.*)/.exec(i);d.push({type:1,index:l,name:e[2],strings:s,ctor:"."===e[1]?I:"?"===e[1]?L:"@"===e[1]?z:H}),r.removeAttribute(t);}else t.startsWith(o$2)&&(d.push({type:6,index:l}),r.removeAttribute(t));if(y.test(r.tagName)){const t=r.textContent.split(o$2),i=t.length-1;if(i>0){r.textContent=s$1?s$1.emptyScript:"";for(let s=0;s<i;s++)r.append(t[s],c()),P.nextNode(),d.push({type:2,index:++l});r.append(t[i],c());}}}else if(8===r.nodeType)if(r.data===n$1)d.push({type:2,index:l});else {let t=-1;for(;-1!==(t=r.data.indexOf(o$2,t+1));)d.push({type:7,index:l}),t+=o$2.length-1;}l++;}}static createElement(t,i){const s=l.createElement("template");return s.innerHTML=t,s}}function M(t,i,s=t,e){if(i===E)return i;let h=void 0!==e?s._$Co?.[e]:s._$Cl;const o=a(i)?void 0:i._$litDirective$;return h?.constructor!==o&&(h?._$AO?.(false),void 0===o?h=void 0:(h=new o(t),h._$AT(t,s,e)),void 0!==e?(s._$Co??=[])[e]=h:s._$Cl=h),void 0!==h&&(i=M(t,h._$AS(t,i.values),h,e)),i}class R{constructor(t,i){this._$AV=[],this._$AN=void 0,this._$AD=t,this._$AM=i;}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(t){const{el:{content:i},parts:s}=this._$AD,e=(t?.creationScope??l).importNode(i,true);P.currentNode=e;let h=P.nextNode(),o=0,n=0,r=s[0];for(;void 0!==r;){if(o===r.index){let i;2===r.type?i=new k(h,h.nextSibling,this,t):1===r.type?i=new r.ctor(h,r.name,r.strings,this,t):6===r.type&&(i=new Z(h,this,t)),this._$AV.push(i),r=s[++n];}o!==r?.index&&(h=P.nextNode(),o++);}return P.currentNode=l,e}p(t){let i=0;for(const s of this._$AV) void 0!==s&&(void 0!==s.strings?(s._$AI(t,s,i),i+=s.strings.length-2):s._$AI(t[i])),i++;}}class k{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(t,i,s,e){this.type=2,this._$AH=A,this._$AN=void 0,this._$AA=t,this._$AB=i,this._$AM=s,this.options=e,this._$Cv=e?.isConnected??true;}get parentNode(){let t=this._$AA.parentNode;const i=this._$AM;return void 0!==i&&11===t?.nodeType&&(t=i.parentNode),t}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(t,i=this){t=M(this,t,i),a(t)?t===A||null==t||""===t?(this._$AH!==A&&this._$AR(),this._$AH=A):t!==this._$AH&&t!==E&&this._(t):void 0!==t._$litType$?this.$(t):void 0!==t.nodeType?this.T(t):d(t)?this.k(t):this._(t);}O(t){return this._$AA.parentNode.insertBefore(t,this._$AB)}T(t){this._$AH!==t&&(this._$AR(),this._$AH=this.O(t));}_(t){this._$AH!==A&&a(this._$AH)?this._$AA.nextSibling.data=t:this.T(l.createTextNode(t)),this._$AH=t;}$(t){const{values:i,_$litType$:s}=t,e="number"==typeof s?this._$AC(t):(void 0===s.el&&(s.el=S.createElement(V(s.h,s.h[0]),this.options)),s);if(this._$AH?._$AD===e)this._$AH.p(i);else {const t=new R(e,this),s=t.u(this.options);t.p(i),this.T(s),this._$AH=t;}}_$AC(t){let i=C.get(t.strings);return void 0===i&&C.set(t.strings,i=new S(t)),i}k(t){u(this._$AH)||(this._$AH=[],this._$AR());const i=this._$AH;let s,e=0;for(const h of t)e===i.length?i.push(s=new k(this.O(c()),this.O(c()),this,this.options)):s=i[e],s._$AI(h),e++;e<i.length&&(this._$AR(s&&s._$AB.nextSibling,e),i.length=e);}_$AR(t=this._$AA.nextSibling,s){for(this._$AP?.(false,true,s);t!==this._$AB;){const s=i$1(t).nextSibling;i$1(t).remove(),t=s;}}setConnected(t){ void 0===this._$AM&&(this._$Cv=t,this._$AP?.(t));}}class H{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(t,i,s,e,h){this.type=1,this._$AH=A,this._$AN=void 0,this.element=t,this.name=i,this._$AM=e,this.options=h,s.length>2||""!==s[0]||""!==s[1]?(this._$AH=Array(s.length-1).fill(new String),this.strings=s):this._$AH=A;}_$AI(t,i=this,s,e){const h=this.strings;let o=false;if(void 0===h)t=M(this,t,i,0),o=!a(t)||t!==this._$AH&&t!==E,o&&(this._$AH=t);else {const e=t;let n,r;for(t=h[0],n=0;n<h.length-1;n++)r=M(this,e[s+n],i,n),r===E&&(r=this._$AH[n]),o||=!a(r)||r!==this._$AH[n],r===A?t=A:t!==A&&(t+=(r??"")+h[n+1]),this._$AH[n]=r;}o&&!e&&this.j(t);}j(t){t===A?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,t??"");}}class I extends H{constructor(){super(...arguments),this.type=3;}j(t){this.element[this.name]=t===A?void 0:t;}}class L extends H{constructor(){super(...arguments),this.type=4;}j(t){this.element.toggleAttribute(this.name,!!t&&t!==A);}}class z extends H{constructor(t,i,s,e,h){super(t,i,s,e,h),this.type=5;}_$AI(t,i=this){if((t=M(this,t,i,0)??A)===E)return;const s=this._$AH,e=t===A&&s!==A||t.capture!==s.capture||t.once!==s.once||t.passive!==s.passive,h=t!==A&&(s===A||e);e&&this.element.removeEventListener(this.name,this,s),h&&this.element.addEventListener(this.name,this,t),this._$AH=t;}handleEvent(t){"function"==typeof this._$AH?this._$AH.call(this.options?.host??this.element,t):this._$AH.handleEvent(t);}}class Z{constructor(t,i,s){this.element=t,this.type=6,this._$AN=void 0,this._$AM=i,this.options=s;}get _$AU(){return this._$AM._$AU}_$AI(t){M(this,t);}}const B=t.litHtmlPolyfillSupport;B?.(S,k),(t.litHtmlVersions??=[]).push("3.3.2");const D=(t,i,s)=>{const e=s?.renderBefore??i;let h=e._$litPart$;if(void 0===h){const t=s?.renderBefore??null;e._$litPart$=h=new k(i.insertBefore(c(),t),t,void 0,s??{});}return h._$AI(t),h};
48
+ const t=globalThis,i$1=t=>t,s$1=t.trustedTypes,e$2=s$1?s$1.createPolicy("lit-html",{createHTML:t=>t}):void 0,h="$lit$",o$2=`lit$${Math.random().toFixed(9).slice(2)}$`,n$1="?"+o$2,r$2=`<${n$1}>`,l=document,c=()=>l.createComment(""),a=t=>null===t||"object"!=typeof t&&"function"!=typeof t,u=Array.isArray,d=t=>u(t)||"function"==typeof t?.[Symbol.iterator],f="[ \t\n\f\r]",v=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,_=/-->/g,m=/>/g,p=RegExp(`>|${f}(?:([^\\s"'>=/]+)(${f}*=${f}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),g=/'/g,$=/"/g,y=/^(?:script|style|textarea|title)$/i,x=t=>(i,...s)=>({_$litType$:t,strings:i,values:s}),b=x(1),w=x(2),E=Symbol.for("lit-noChange"),A=Symbol.for("lit-nothing"),C=new WeakMap,P=l.createTreeWalker(l,129);function V(t,i){if(!u(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==e$2?e$2.createHTML(i):i}const N=(t,i)=>{const s=t.length-1,e=[];let n,l=2===i?"<svg>":3===i?"<math>":"",c=v;for(let i=0;i<s;i++){const s=t[i];let a,u,d=-1,f=0;for(;f<s.length&&(c.lastIndex=f,u=c.exec(s),null!==u);)f=c.lastIndex,c===v?"!--"===u[1]?c=_:void 0!==u[1]?c=m:void 0!==u[2]?(y.test(u[2])&&(n=RegExp("</"+u[2],"g")),c=p):void 0!==u[3]&&(c=p):c===p?">"===u[0]?(c=n??v,d=-1):void 0===u[1]?d=-2:(d=c.lastIndex-u[2].length,a=u[1],c=void 0===u[3]?p:'"'===u[3]?$:g):c===$||c===g?c=p:c===_||c===m?c=v:(c=p,n=void 0);const x=c===p&&t[i+1].startsWith("/>")?" ":"";l+=c===v?s+r$2:d>=0?(e.push(a),s.slice(0,d)+h+s.slice(d)+o$2+x):s+o$2+(-2===d?i:x);}return [V(t,l+(t[s]||"<?>")+(2===i?"</svg>":3===i?"</math>":"")),e]};class S{constructor({strings:t,_$litType$:i},e){let r;this.parts=[];let l=0,a=0;const u=t.length-1,d=this.parts,[f,v]=N(t,i);if(this.el=S.createElement(f,e),P.currentNode=this.el.content,2===i||3===i){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes);}for(;null!==(r=P.nextNode())&&d.length<u;){if(1===r.nodeType){if(r.hasAttributes())for(const t of r.getAttributeNames())if(t.endsWith(h)){const i=v[a++],s=r.getAttribute(t).split(o$2),e=/([.?@])?(.*)/.exec(i);d.push({type:1,index:l,name:e[2],strings:s,ctor:"."===e[1]?I:"?"===e[1]?L:"@"===e[1]?z:H}),r.removeAttribute(t);}else t.startsWith(o$2)&&(d.push({type:6,index:l}),r.removeAttribute(t));if(y.test(r.tagName)){const t=r.textContent.split(o$2),i=t.length-1;if(i>0){r.textContent=s$1?s$1.emptyScript:"";for(let s=0;s<i;s++)r.append(t[s],c()),P.nextNode(),d.push({type:2,index:++l});r.append(t[i],c());}}}else if(8===r.nodeType)if(r.data===n$1)d.push({type:2,index:l});else {let t=-1;for(;-1!==(t=r.data.indexOf(o$2,t+1));)d.push({type:7,index:l}),t+=o$2.length-1;}l++;}}static createElement(t,i){const s=l.createElement("template");return s.innerHTML=t,s}}function M(t,i,s=t,e){if(i===E)return i;let h=void 0!==e?s._$Co?.[e]:s._$Cl;const o=a(i)?void 0:i._$litDirective$;return h?.constructor!==o&&(h?._$AO?.(false),void 0===o?h=void 0:(h=new o(t),h._$AT(t,s,e)),void 0!==e?(s._$Co??=[])[e]=h:s._$Cl=h),void 0!==h&&(i=M(t,h._$AS(t,i.values),h,e)),i}class R{constructor(t,i){this._$AV=[],this._$AN=void 0,this._$AD=t,this._$AM=i;}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(t){const{el:{content:i},parts:s}=this._$AD,e=(t?.creationScope??l).importNode(i,true);P.currentNode=e;let h=P.nextNode(),o=0,n=0,r=s[0];for(;void 0!==r;){if(o===r.index){let i;2===r.type?i=new k(h,h.nextSibling,this,t):1===r.type?i=new r.ctor(h,r.name,r.strings,this,t):6===r.type&&(i=new Z(h,this,t)),this._$AV.push(i),r=s[++n];}o!==r?.index&&(h=P.nextNode(),o++);}return P.currentNode=l,e}p(t){let i=0;for(const s of this._$AV) void 0!==s&&(void 0!==s.strings?(s._$AI(t,s,i),i+=s.strings.length-2):s._$AI(t[i])),i++;}}class k{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(t,i,s,e){this.type=2,this._$AH=A,this._$AN=void 0,this._$AA=t,this._$AB=i,this._$AM=s,this.options=e,this._$Cv=e?.isConnected??true;}get parentNode(){let t=this._$AA.parentNode;const i=this._$AM;return void 0!==i&&11===t?.nodeType&&(t=i.parentNode),t}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(t,i=this){t=M(this,t,i),a(t)?t===A||null==t||""===t?(this._$AH!==A&&this._$AR(),this._$AH=A):t!==this._$AH&&t!==E&&this._(t):void 0!==t._$litType$?this.$(t):void 0!==t.nodeType?this.T(t):d(t)?this.k(t):this._(t);}O(t){return this._$AA.parentNode.insertBefore(t,this._$AB)}T(t){this._$AH!==t&&(this._$AR(),this._$AH=this.O(t));}_(t){this._$AH!==A&&a(this._$AH)?this._$AA.nextSibling.data=t:this.T(l.createTextNode(t)),this._$AH=t;}$(t){const{values:i,_$litType$:s}=t,e="number"==typeof s?this._$AC(t):(void 0===s.el&&(s.el=S.createElement(V(s.h,s.h[0]),this.options)),s);if(this._$AH?._$AD===e)this._$AH.p(i);else {const t=new R(e,this),s=t.u(this.options);t.p(i),this.T(s),this._$AH=t;}}_$AC(t){let i=C.get(t.strings);return void 0===i&&C.set(t.strings,i=new S(t)),i}k(t){u(this._$AH)||(this._$AH=[],this._$AR());const i=this._$AH;let s,e=0;for(const h of t)e===i.length?i.push(s=new k(this.O(c()),this.O(c()),this,this.options)):s=i[e],s._$AI(h),e++;e<i.length&&(this._$AR(s&&s._$AB.nextSibling,e),i.length=e);}_$AR(t=this._$AA.nextSibling,s){for(this._$AP?.(false,true,s);t!==this._$AB;){const s=i$1(t).nextSibling;i$1(t).remove(),t=s;}}setConnected(t){ void 0===this._$AM&&(this._$Cv=t,this._$AP?.(t));}}class H{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(t,i,s,e,h){this.type=1,this._$AH=A,this._$AN=void 0,this.element=t,this.name=i,this._$AM=e,this.options=h,s.length>2||""!==s[0]||""!==s[1]?(this._$AH=Array(s.length-1).fill(new String),this.strings=s):this._$AH=A;}_$AI(t,i=this,s,e){const h=this.strings;let o=false;if(void 0===h)t=M(this,t,i,0),o=!a(t)||t!==this._$AH&&t!==E,o&&(this._$AH=t);else {const e=t;let n,r;for(t=h[0],n=0;n<h.length-1;n++)r=M(this,e[s+n],i,n),r===E&&(r=this._$AH[n]),o||=!a(r)||r!==this._$AH[n],r===A?t=A:t!==A&&(t+=(r??"")+h[n+1]),this._$AH[n]=r;}o&&!e&&this.j(t);}j(t){t===A?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,t??"");}}class I extends H{constructor(){super(...arguments),this.type=3;}j(t){this.element[this.name]=t===A?void 0:t;}}class L extends H{constructor(){super(...arguments),this.type=4;}j(t){this.element.toggleAttribute(this.name,!!t&&t!==A);}}class z extends H{constructor(t,i,s,e,h){super(t,i,s,e,h),this.type=5;}_$AI(t,i=this){if((t=M(this,t,i,0)??A)===E)return;const s=this._$AH,e=t===A&&s!==A||t.capture!==s.capture||t.once!==s.once||t.passive!==s.passive,h=t!==A&&(s===A||e);e&&this.element.removeEventListener(this.name,this,s),h&&this.element.addEventListener(this.name,this,t),this._$AH=t;}handleEvent(t){"function"==typeof this._$AH?this._$AH.call(this.options?.host??this.element,t):this._$AH.handleEvent(t);}}class Z{constructor(t,i,s){this.element=t,this.type=6,this._$AN=void 0,this._$AM=i,this.options=s;}get _$AU(){return this._$AM._$AU}_$AI(t){M(this,t);}}const B=t.litHtmlPolyfillSupport;B?.(S,k),(t.litHtmlVersions??=[]).push("3.3.2");const D=(t,i,s)=>{const e=s?.renderBefore??i;let h=e._$litPart$;if(void 0===h){const t=s?.renderBefore??null;e._$litPart$=h=new k(i.insertBefore(c(),t),t,void 0,s??{});}return h._$AI(t),h};
49
49
 
50
50
  /**
51
51
  * @license
@@ -309,7 +309,7 @@ class GoogleService {
309
309
  }
310
310
  }
311
311
 
312
- const VERSION = '1.1.0';
312
+ const VERSION = '1.1.1';
313
313
  const INSTRUMENTAL_THRESHOLD_MS = 7000; // Show dots for gaps >= 7s
314
314
  const KPOE_SERVERS = [
315
315
  'https://lyricsplus.binimum.org',
@@ -350,6 +350,10 @@ class AmLyrics extends i {
350
350
  this.mainWordProgress = new Map();
351
351
  this.backgroundWordProgress = new Map();
352
352
  this.lyricsSource = null;
353
+ this.availableSources = [];
354
+ this.currentSourceIndex = 0;
355
+ this.isFetchingAlternatives = false;
356
+ this.hasFetchedAllProviders = false;
353
357
  this.mainWordAnimations = new Map();
354
358
  this.backgroundWordAnimations = new Map();
355
359
  this.lastInstrumentalIndex = null;
@@ -463,43 +467,55 @@ class AmLyrics extends i {
463
467
  this.isLoading = true;
464
468
  this.lyrics = undefined;
465
469
  this.lyricsSource = null;
470
+ this.availableSources = [];
471
+ this.currentSourceIndex = 0;
472
+ this.isFetchingAlternatives = false;
473
+ this.hasFetchedAllProviders = false;
466
474
  try {
467
475
  const resolvedMetadata = await this.resolveSongMetadata();
468
476
  const isMusicIdOnlyRequest = Boolean(this.musicId) &&
469
477
  !this.songTitle &&
470
478
  !this.songArtist &&
471
479
  !this.query;
480
+ const collectedSources = [];
472
481
  if (resolvedMetadata?.metadata && !isMusicIdOnlyRequest) {
473
482
  const title = resolvedMetadata.metadata.title?.trim() || '';
474
483
  const artist = resolvedMetadata.metadata.artist?.trim() || '';
475
- const youLyResult = await AmLyrics.fetchLyricsFromYouLyPlus(title, artist, resolvedMetadata.metadata);
476
- if (youLyResult && youLyResult.lines.length > 0) {
477
- this.lyrics = youLyResult.lines;
478
- this.lyricsSource = youLyResult.source ?? 'LyricsPlus (KPoe)';
479
- await this.onLyricsLoaded();
480
- return;
484
+ const youLyResults = await AmLyrics.fetchLyricsFromYouLyPlus(title, artist, resolvedMetadata.metadata);
485
+ if (youLyResults && youLyResults.length > 0) {
486
+ collectedSources.push(...youLyResults);
481
487
  }
482
488
  }
483
- // Fallback: Tidal
484
- if (resolvedMetadata?.metadata) {
489
+ if (collectedSources.length === 0 && resolvedMetadata?.metadata) {
485
490
  const tidalResult = await AmLyrics.fetchLyricsFromTidal(resolvedMetadata.metadata, resolvedMetadata.catalogIsrc);
486
491
  if (tidalResult && tidalResult.lines.length > 0) {
487
- this.lyrics = tidalResult.lines;
488
- this.lyricsSource = 'Tidal';
489
- await this.onLyricsLoaded();
490
- return;
492
+ collectedSources.push({
493
+ lines: tidalResult.lines,
494
+ source: 'Tidal',
495
+ });
491
496
  }
492
497
  }
493
498
  // Fallback: LRCLIB
494
- if (resolvedMetadata?.metadata) {
499
+ if (collectedSources.length === 0 && resolvedMetadata?.metadata) {
495
500
  const lrclibResult = await AmLyrics.fetchLyricsFromLrclib(resolvedMetadata.metadata);
496
501
  if (lrclibResult && lrclibResult.lines.length > 0) {
497
- this.lyrics = lrclibResult.lines;
498
- this.lyricsSource = 'LRCLIB';
499
- await this.onLyricsLoaded();
500
- return;
502
+ collectedSources.push({
503
+ lines: lrclibResult.lines,
504
+ source: 'LRCLIB',
505
+ });
501
506
  }
502
507
  }
508
+ this.hasFetchedAllProviders =
509
+ collectedSources.length === 0 ||
510
+ collectedSources.some(s => s.source === 'LRCLIB' || s.source === 'Tidal');
511
+ if (collectedSources.length > 0) {
512
+ this.availableSources = AmLyrics.mergeAndSortSources(collectedSources);
513
+ this.currentSourceIndex = 0;
514
+ this.lyrics = this.availableSources[0].lines;
515
+ this.lyricsSource = this.availableSources[0].source;
516
+ await this.onLyricsLoaded();
517
+ return;
518
+ }
503
519
  this.lyrics = undefined;
504
520
  this.lyricsSource = null;
505
521
  }
@@ -532,6 +548,110 @@ class AmLyrics extends i {
532
548
  await this.applyTranslation();
533
549
  }
534
550
  }
551
+ static getRankForCollected(sourceLabel, parsedLines) {
552
+ const lower = sourceLabel.toLowerCase();
553
+ const hasWordSync = parsedLines.some((line) => line.text && Array.isArray(line.text) && line.text.length > 1);
554
+ const isUnsynced = parsedLines.length > 0 &&
555
+ parsedLines.every((line) => line.timestamp === 0 && line.endtime === 0);
556
+ const isQQ = lower.includes('qq') || lower.includes('lyricsplus');
557
+ if (lower.includes('apple') && hasWordSync)
558
+ return 1;
559
+ if (isQQ && hasWordSync)
560
+ return 2;
561
+ if (lower.includes('musixmatch') && hasWordSync)
562
+ return 3;
563
+ if (lower.includes('tidal') && hasWordSync)
564
+ return 4;
565
+ if (lower.includes('lrclib') && hasWordSync)
566
+ return 5;
567
+ if (lower.includes('apple') && !hasWordSync && !isUnsynced)
568
+ return 6;
569
+ if (isQQ && !hasWordSync && !isUnsynced)
570
+ return 7;
571
+ if (lower.includes('musixmatch') && !hasWordSync && !isUnsynced)
572
+ return 8;
573
+ if (lower.includes('tidal') && !hasWordSync && !isUnsynced)
574
+ return 9;
575
+ if (lower.includes('lrclib') && !hasWordSync && !isUnsynced)
576
+ return 10;
577
+ if (lower.includes('apple') && isUnsynced)
578
+ return 11;
579
+ if (isQQ && isUnsynced)
580
+ return 12;
581
+ if (lower.includes('musixmatch') && isUnsynced)
582
+ return 13;
583
+ if (lower.includes('tidal') && isUnsynced)
584
+ return 14;
585
+ if (lower.includes('lrclib') && isUnsynced)
586
+ return 15;
587
+ return 20;
588
+ }
589
+ static mergeAndSortSources(collectedSources) {
590
+ const uniqueSourcesMap = new Map();
591
+ for (const source of collectedSources) {
592
+ const normalizedSource = source.source
593
+ .toLowerCase()
594
+ .includes('lyricsplus')
595
+ ? 'QQ'
596
+ : source.source;
597
+ if (!uniqueSourcesMap.has(normalizedSource)) {
598
+ uniqueSourcesMap.set(normalizedSource, {
599
+ ...source,
600
+ source: normalizedSource,
601
+ });
602
+ }
603
+ }
604
+ return Array.from(uniqueSourcesMap.values()).sort((a, b) => AmLyrics.getRankForCollected(a.source, a.lines) -
605
+ AmLyrics.getRankForCollected(b.source, b.lines));
606
+ }
607
+ async switchSource() {
608
+ if (this.isFetchingAlternatives)
609
+ return;
610
+ if (!this.hasFetchedAllProviders) {
611
+ this.isFetchingAlternatives = true;
612
+ try {
613
+ const resolvedMetadata = await this.resolveSongMetadata();
614
+ if (resolvedMetadata?.metadata) {
615
+ const newSources = [];
616
+ // Try Tidal if not fetched
617
+ if (!this.availableSources.some(s => s.source.toLowerCase().includes('tidal'))) {
618
+ const tidalResult = await AmLyrics.fetchLyricsFromTidal(resolvedMetadata.metadata, resolvedMetadata.catalogIsrc);
619
+ if (tidalResult && tidalResult.lines.length > 0) {
620
+ newSources.push({ lines: tidalResult.lines, source: 'Tidal' });
621
+ }
622
+ }
623
+ // Try LRCLIB if not fetched
624
+ if (!this.availableSources.some(s => s.source.toLowerCase().includes('lrclib'))) {
625
+ const lrclibResult = await AmLyrics.fetchLyricsFromLrclib(resolvedMetadata.metadata);
626
+ if (lrclibResult && lrclibResult.lines.length > 0) {
627
+ newSources.push({ lines: lrclibResult.lines, source: 'LRCLIB' });
628
+ }
629
+ }
630
+ if (newSources.length > 0) {
631
+ this.availableSources = AmLyrics.mergeAndSortSources([
632
+ ...this.availableSources,
633
+ ...newSources,
634
+ ]);
635
+ // Re-sync current index since sorting might shift elements
636
+ this.currentSourceIndex = this.availableSources.findIndex(s => s.source === this.lyricsSource);
637
+ if (this.currentSourceIndex === -1)
638
+ this.currentSourceIndex = 0;
639
+ }
640
+ }
641
+ }
642
+ finally {
643
+ this.hasFetchedAllProviders = true;
644
+ this.isFetchingAlternatives = false;
645
+ }
646
+ }
647
+ if (this.availableSources.length > 1) {
648
+ this.currentSourceIndex =
649
+ (this.currentSourceIndex + 1) % this.availableSources.length;
650
+ this.lyrics = this.availableSources[this.currentSourceIndex].lines;
651
+ this.lyricsSource = this.availableSources[this.currentSourceIndex].source;
652
+ await this.onLyricsLoaded();
653
+ }
654
+ }
535
655
  async resolveSongMetadata() {
536
656
  const metadata = {
537
657
  title: this.songTitle?.trim() ?? '',
@@ -675,7 +795,7 @@ class AmLyrics extends i {
675
795
  }
676
796
  static async fetchLyricsFromYouLyPlus(title, artist, metadata = {}) {
677
797
  if (!title || !artist)
678
- return null;
798
+ return [];
679
799
  const params = new URLSearchParams({ title, artist });
680
800
  if (metadata.album) {
681
801
  params.append('album', metadata.album);
@@ -687,6 +807,8 @@ class AmLyrics extends i {
687
807
  const getRank = (sourceLabel, parsedLines) => {
688
808
  const lower = sourceLabel.toLowerCase();
689
809
  const hasWordSync = parsedLines.some((line) => line.text && Array.isArray(line.text) && line.text.length > 1);
810
+ const isUnsynced = parsedLines.length > 0 &&
811
+ parsedLines.every((line) => line.timestamp === 0 && line.endtime === 0);
690
812
  const isQQ = lower.includes('qq') || lower.includes('lyricsplus');
691
813
  if (lower.includes('apple') && hasWordSync)
692
814
  return 1;
@@ -694,16 +816,21 @@ class AmLyrics extends i {
694
816
  return 2;
695
817
  if (lower.includes('musixmatch') && hasWordSync)
696
818
  return 3;
697
- if (lower.includes('apple') && !hasWordSync)
819
+ if (lower.includes('apple') && !hasWordSync && !isUnsynced)
698
820
  return 4;
699
- if (isQQ && !hasWordSync)
821
+ if (isQQ && !hasWordSync && !isUnsynced)
700
822
  return 5;
701
- if (lower.includes('musixmatch') && !hasWordSync)
823
+ if (lower.includes('musixmatch') && !hasWordSync && !isUnsynced)
702
824
  return 6;
825
+ if (lower.includes('apple') && isUnsynced)
826
+ return 7;
827
+ if (isQQ && isUnsynced)
828
+ return 8;
829
+ if (lower.includes('musixmatch') && isUnsynced)
830
+ return 9;
703
831
  return 10;
704
832
  };
705
- let bestFallbackResult = null;
706
- let bestFallbackRank = 100;
833
+ const allResults = [];
707
834
  // Shuffle servers so we pick a random one first, with all others as fallback
708
835
  // Limit to 2 servers to prevent unnecessary API spam when Apple lyrics are missing
709
836
  const shuffledServers = [...KPOE_SERVERS]
@@ -732,24 +859,18 @@ class AmLyrics extends i {
732
859
  'LyricsPlus (KPoe)';
733
860
  const rank = getRank(sourceLabel, lines);
734
861
  const result = { lines, source: sourceLabel };
735
- // If source is Apple, return immediately (best quality)
862
+ allResults.push(result);
863
+ // If source is Apple synced, we have the best so we can just immediately break the sweep
736
864
  if (rank === 1) {
737
- return result;
738
- }
739
- // Otherwise, store as fallback if we don't have one yet
740
- if (rank < bestFallbackRank) {
741
- bestFallbackResult = result;
742
- bestFallbackRank = rank;
865
+ break;
743
866
  }
744
- // Proxies are identical mirrors; if we got a valid response (even a fallback),
745
- // there's no reason to query the next proxy because it will return the exact same fallback.
746
- break;
747
867
  }
748
868
  }
749
869
  }
750
- // If we finished the 2-server check and STILL don't have Apple (1) or QQ (2),
870
+ // If we haven't found a completely synced Apple/QQ result (rank 1 or 2) among the servers,
751
871
  // force an explicit query against lyricsplus.binimum.org looking for QQ
752
- if (bestFallbackRank > 2) {
872
+ const hasHighRankResult = allResults.some(r => getRank(r.source, r.lines) <= 2);
873
+ if (!hasHighRankResult) {
753
874
  try {
754
875
  const qqParams = new URLSearchParams(params);
755
876
  qqParams.set('source', 'qq');
@@ -762,18 +883,17 @@ class AmLyrics extends i {
762
883
  const sourceLabel = payload?.metadata?.source ||
763
884
  payload?.metadata?.provider ||
764
885
  'LyricsPlus (KPoe)';
765
- const rank = getRank(sourceLabel, lines || []);
766
- if (lines && lines.length > 0 && rank < bestFallbackRank) {
767
- return { lines, source: sourceLabel };
886
+ if (lines && lines.length > 0) {
887
+ allResults.push({ lines, source: sourceLabel });
768
888
  }
769
889
  }
770
890
  }
771
891
  }
772
892
  catch (error) {
773
- // Explicit QQ fallback failed, ignore and proceed to return whatever we had
893
+ // Explicit QQ fallback failed, ignore
774
894
  }
775
895
  }
776
- return bestFallbackResult;
896
+ return allResults;
777
897
  }
778
898
  /**
779
899
  * Parse LRC subtitle format into LyricsLine[].
@@ -1017,8 +1137,8 @@ class AmLyrics extends i {
1017
1137
  });
1018
1138
  }
1019
1139
  for (const entry of sanitizedEntries) {
1020
- const start = Number(entry.time);
1021
- const duration = Number(entry.duration);
1140
+ const start = AmLyrics.toMilliseconds(entry.time);
1141
+ const duration = AmLyrics.toMilliseconds(entry.duration);
1022
1142
  // Determine alignment
1023
1143
  let alignment;
1024
1144
  const singerId = entry.element?.singer;
@@ -1039,7 +1159,11 @@ class AmLyrics extends i {
1039
1159
  for (const syl of syllabus) {
1040
1160
  const sylStart = AmLyrics.toMilliseconds(syl.time, lineStart);
1041
1161
  const sylDuration = AmLyrics.toMilliseconds(syl.duration);
1042
- const sylEnd = sylDuration > 0 ? sylStart + sylDuration : lineEnd;
1162
+ // If there's only 1 syllable and duration is 0, it's likely a line-synced fallback.
1163
+ // Otherwise, it's an instantaneous boundary (like a space or comma) and should not span the line.
1164
+ const sylEnd = sylDuration === 0 && syllabus.length === 1
1165
+ ? lineEnd
1166
+ : sylStart + sylDuration;
1043
1167
  const syllable = {
1044
1168
  text: typeof syl.text === 'string' ? syl.text : '',
1045
1169
  part: Boolean(syl.part),
@@ -1152,6 +1276,7 @@ class AmLyrics extends i {
1152
1276
  const lineElement = this.lyricsContainer.querySelector(`#lyrics-line-${lineIndex}`);
1153
1277
  if (lineElement) {
1154
1278
  lineElement.classList.add('active');
1279
+ lineElement.classList.remove('pre-active'); // Cleanup pre-active when fully active
1155
1280
  }
1156
1281
  }
1157
1282
  }
@@ -1260,16 +1385,23 @@ class AmLyrics extends i {
1260
1385
  for (let i = 0; i < this.lyrics.length; i += 1) {
1261
1386
  const line = this.lyrics[i];
1262
1387
  const timeUntilStart = line.timestamp - newTime;
1388
+ const nextLineEl = this.lyricsContainer.querySelector(`#lyrics-line-${i}`);
1263
1389
  if (timeUntilStart > 0 && timeUntilStart <= preScrollLeadMs) {
1264
- const nextLineEl = this.lyricsContainer.querySelector(`#lyrics-line-${i}`);
1265
- // Only trigger if we aren't already targeting this line
1266
- if (nextLineEl && nextLineEl !== this.currentPrimaryActiveLine) {
1267
- // We don't set currentPrimaryActiveLine here to avoid triggering
1268
- // styles, just the YouLy scroll.
1269
- this.scrollToActiveLineYouLy(nextLineEl);
1390
+ // Time to pre-scroll and pre-activate!
1391
+ if (nextLineEl) {
1392
+ // Apply unblur & zoom effect ahead of lyric start
1393
+ nextLineEl.classList.add('pre-active');
1394
+ // Only trigger scroll if we aren't already targeting this line
1395
+ if (nextLineEl !== this.currentPrimaryActiveLine) {
1396
+ this.scrollToActiveLineYouLy(nextLineEl);
1397
+ }
1270
1398
  }
1271
1399
  break;
1272
1400
  }
1401
+ else if (nextLineEl) {
1402
+ // Ensure lines outside the pre-scroll window don't stay pre-active
1403
+ nextLineEl.classList.remove('pre-active');
1404
+ }
1273
1405
  }
1274
1406
  }
1275
1407
  }
@@ -2474,6 +2606,9 @@ class AmLyrics extends i {
2474
2606
  this.style.setProperty('--hover-background-color', this.hoverBackgroundColor);
2475
2607
  this.style.setProperty('--highlight-color', this.highlightColor);
2476
2608
  const sourceLabel = this.lyricsSource ?? 'Unavailable';
2609
+ const isUnsynced = this.lyrics && this.lyrics.length > 0
2610
+ ? this.lyrics.every(l => l.timestamp === 0 && l.endtime === 0)
2611
+ : false;
2477
2612
  const renderContent = () => {
2478
2613
  if (this.isLoading) {
2479
2614
  // Render stylized skeleton lines
@@ -2944,7 +3079,9 @@ class AmLyrics extends i {
2944
3079
  };
2945
3080
  return b `
2946
3081
  <div
2947
- class="lyrics-container blur-inactive-enabled ${this.isUserScrolling
3082
+ class="lyrics-container ${isUnsynced
3083
+ ? 'is-unsynced'
3084
+ : 'blur-inactive-enabled'} ${this.isUserScrolling
2948
3085
  ? 'user-scrolling'
2949
3086
  : ''}"
2950
3087
  >
@@ -3051,7 +3188,54 @@ class AmLyrics extends i {
3051
3188
  ? b `
3052
3189
  <footer class="lyrics-footer">
3053
3190
  <div class="footer-content">
3054
- <span class="source-info">Source: ${sourceLabel}</span>
3191
+ <span
3192
+ class="source-info"
3193
+ style="display: flex; align-items: center; gap: 8px;"
3194
+ >
3195
+ Source: ${sourceLabel}
3196
+ ${(this.availableSources &&
3197
+ this.availableSources.length > 1) ||
3198
+ !this.hasFetchedAllProviders
3199
+ ? b `
3200
+ <button
3201
+ class="download-button"
3202
+ title="Switch Lyrics Source"
3203
+ style="font-family: inherit; font-size: 11px; padding: 2px 6px; border-radius: 4px; border: 1px solid rgba(255, 255, 255, 0.2); background: transparent; cursor: pointer; color: #aaa; display: inline-flex; align-items: center;"
3204
+ @click=${this.switchSource}
3205
+ ?disabled=${this.isFetchingAlternatives}
3206
+ >
3207
+ <svg
3208
+ style="margin-right: 4px; ${this
3209
+ .isFetchingAlternatives
3210
+ ? 'animation: spin 1s linear infinite;'
3211
+ : ''}"
3212
+ xmlns="http://www.w3.org/2000/svg"
3213
+ width="12"
3214
+ height="12"
3215
+ viewBox="0 0 24 24"
3216
+ fill="none"
3217
+ stroke="currentColor"
3218
+ stroke-width="2"
3219
+ stroke-linecap="round"
3220
+ stroke-linejoin="round"
3221
+ class="lucide lucide-arrow-down-up-icon lucide-arrow-down-up"
3222
+ >
3223
+ ${this.isFetchingAlternatives
3224
+ ? w `<path
3225
+ d="M21 12a9 9 0 1 1-6.219-8.56"
3226
+ ></path>`
3227
+ : w `<path d="m3 16 4 4 4-4"></path
3228
+ ><path d="M7 20V4"></path
3229
+ ><path d="m21 8-4-4-4 4"></path
3230
+ ><path d="M17 4v16"></path>`}
3231
+ </svg>
3232
+ ${this.isFetchingAlternatives
3233
+ ? 'Switching...'
3234
+ : 'Switch'}
3235
+ </button>
3236
+ `
3237
+ : ''}
3238
+ </span>
3055
3239
  <span class="version-info">
3056
3240
  v${VERSION} •
3057
3241
 
@@ -3201,7 +3385,8 @@ AmLyrics.styles = i$3 `
3201
3385
  color 0.7s;
3202
3386
  }
3203
3387
 
3204
- .lyrics-line.active .lyrics-line-container {
3388
+ .lyrics-line.active .lyrics-line-container,
3389
+ .lyrics-line.pre-active .lyrics-line-container {
3205
3390
  transform: scale3d(1.001, 1.001, 1);
3206
3391
  will-change: transform;
3207
3392
  transition:
@@ -3258,24 +3443,60 @@ AmLyrics.styles = i$3 `
3258
3443
  direction: rtl;
3259
3444
  }
3260
3445
 
3446
+ /* --- Unsynced (Plain Text) Lyrics Overrides --- */
3447
+ .lyrics-container.is-unsynced .lyrics-line {
3448
+ opacity: 1 !important;
3449
+ color: var(--lyplus-text-primary) !important;
3450
+ filter: none !important;
3451
+ transform: none !important;
3452
+ cursor: default;
3453
+ }
3454
+
3455
+ .lyrics-container.is-unsynced .lyrics-line-container {
3456
+ transform: none !important;
3457
+ background-color: transparent !important;
3458
+ }
3459
+
3460
+ .lyrics-container.is-unsynced .lyrics-syllable {
3461
+ color: var(--lyplus-text-primary) !important;
3462
+ background-color: transparent !important;
3463
+ -webkit-background-clip: unset !important;
3464
+ background-clip: unset !important;
3465
+ -webkit-text-fill-color: unset !important;
3466
+ text-fill-color: unset !important;
3467
+ text-shadow: none !important;
3468
+ filter: none !important;
3469
+ opacity: 1 !important;
3470
+ transform: none !important;
3471
+ }
3472
+
3261
3473
  @media (hover: hover) and (pointer: fine) {
3262
3474
  .lyrics-line:hover {
3263
3475
  background: var(--hover-background-color, rgba(255, 255, 255, 0.13));
3264
3476
  }
3477
+ .lyrics-container.is-unsynced .lyrics-line:hover {
3478
+ background: transparent !important;
3479
+ }
3265
3480
  }
3266
3481
 
3267
3482
  /* --- Blur Effect for Inactive Lines --- */
3268
3483
  .lyrics-container.blur-inactive-enabled:not(.not-focused)
3269
- .lyrics-line:not(.active):not(.lyrics-gap) {
3484
+ .lyrics-line:not(.active):not(.pre-active):not(.lyrics-gap) {
3270
3485
  filter: blur(var(--lyplus-blur-amount));
3271
3486
  }
3272
3487
 
3273
3488
  .lyrics-container.blur-inactive-enabled:not(.not-focused)
3274
- .lyrics-line.post-active-line:not(.lyrics-gap):not(.active),
3489
+ .lyrics-line.post-active-line:not(.lyrics-gap):not(.active):not(
3490
+ .pre-active
3491
+ ),
3275
3492
  .lyrics-container.blur-inactive-enabled:not(.not-focused)
3276
- .lyrics-line.next-active-line:not(.lyrics-gap):not(.active),
3493
+ .lyrics-line.next-active-line:not(.lyrics-gap):not(.active):not(
3494
+ .pre-active
3495
+ ),
3277
3496
  .lyrics-container.blur-inactive-enabled:not(.not-focused)
3278
- .lyrics-line.lyrics-activest:not(.active):not(.lyrics-gap) {
3497
+ .lyrics-line.lyrics-activest:not(.active):not(.lyrics-gap):not(
3498
+ .pre-active
3499
+ ) {
3279
3500
  filter: blur(var(--lyplus-blur-amount-near));
3280
3501
  }
3281
3502
 
@@ -3285,6 +3506,12 @@ AmLyrics.styles = i$3 `
3285
3506
  opacity: 0.8 !important;
3286
3507
  }
3287
3508
 
3509
+ /* Unblur early for pre-active lines */
3510
+ .lyrics-container.blur-inactive-enabled .lyrics-line.pre-active {
3511
+ filter: blur(0px) !important;
3512
+ opacity: var(--lyplus-primary-opacity);
3513
+ }
3514
+
3288
3515
  /* ==========================================================================
3289
3516
  WORD & SYLLABLE STYLES
3290
3517
  ========================================================================== */
@@ -3716,6 +3943,7 @@ AmLyrics.styles = i$3 `
3716
3943
  vertical-align: middle;
3717
3944
  display: inline-flex;
3718
3945
  align-items: center;
3946
+ font-family: inherit;
3719
3947
  }
3720
3948
 
3721
3949
  .lyrics-header .download-button:hover {
@@ -3766,6 +3994,7 @@ AmLyrics.styles = i$3 `
3766
3994
  padding: 2px 5px;
3767
3995
  cursor: pointer;
3768
3996
  font-weight: normal;
3997
+ font-family: inherit;
3769
3998
  }
3770
3999
 
3771
4000
  .format-select:hover {
@@ -4266,6 +4495,18 @@ __decorate([
4266
4495
  __decorate([
4267
4496
  r()
4268
4497
  ], AmLyrics.prototype, "lyricsSource", void 0);
4498
+ __decorate([
4499
+ r()
4500
+ ], AmLyrics.prototype, "availableSources", void 0);
4501
+ __decorate([
4502
+ r()
4503
+ ], AmLyrics.prototype, "currentSourceIndex", void 0);
4504
+ __decorate([
4505
+ r()
4506
+ ], AmLyrics.prototype, "isFetchingAlternatives", void 0);
4507
+ __decorate([
4508
+ r()
4509
+ ], AmLyrics.prototype, "hasFetchedAllProviders", void 0);
4269
4510
  __decorate([
4270
4511
  e('.lyrics-container')
4271
4512
  ], AmLyrics.prototype, "lyricsContainer", void 0);