chore: format
This commit is contained in:
@@ -13,29 +13,29 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { EMPTY, of } from 'rxjs';
|
||||
import { catchError, finalize, map, switchMap } from 'rxjs/operators';
|
||||
import { EMPTY, of } from "rxjs";
|
||||
import { catchError, finalize, map, switchMap } from "rxjs/operators";
|
||||
|
||||
import { animate, fetchRx } from './common';
|
||||
import { animate, fetchRx } from "./common";
|
||||
|
||||
const RE_CSS_URL = /url\s*\(['"]?(([^'"\\]|\\.)*)['"]?\)/u;
|
||||
|
||||
/** @param {Document} doc */
|
||||
const calcHash = (doc) => {
|
||||
const sidebar = doc.getElementById('_sidebar');
|
||||
const sidebarBg = sidebar?.querySelector('.sidebar-bg');
|
||||
const pageStyle = doc.getElementById('_pageStyle');
|
||||
const source = doc.getElementById('source');
|
||||
// const rule = Array.from(pageStyle?.sheet?.rules ?? []).find(r => r.selectorText === 'html');
|
||||
// const accentColor = rule?.style.getPropertyValue('--accent-color') ?? '';
|
||||
// const themeColor = rule?.style.getPropertyValue('--theme-color') ?? '';
|
||||
return [
|
||||
pageStyle?.innerText?.trim(),
|
||||
sidebar?.classList,
|
||||
sidebarBg?.classList,
|
||||
sidebarBg?.style.backgroundImage,
|
||||
source?.src
|
||||
].join('\n');
|
||||
const sidebar = doc.getElementById("_sidebar");
|
||||
const sidebarBg = sidebar?.querySelector(".sidebar-bg");
|
||||
const pageStyle = doc.getElementById("_pageStyle");
|
||||
const source = doc.getElementById("source");
|
||||
// const rule = Array.from(pageStyle?.sheet?.rules ?? []).find(r => r.selectorText === 'html');
|
||||
// const accentColor = rule?.style.getPropertyValue('--accent-color') ?? '';
|
||||
// const themeColor = rule?.style.getPropertyValue('--theme-color') ?? '';
|
||||
return [
|
||||
pageStyle?.innerText?.trim(),
|
||||
sidebar?.classList,
|
||||
sidebarBg?.classList,
|
||||
sidebarBg?.style.backgroundImage,
|
||||
source?.src,
|
||||
].join("\n");
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -44,120 +44,123 @@ const calcHash = (doc) => {
|
||||
* @param {Location=} location
|
||||
*/
|
||||
function isExternal({ protocol, host }, location = window.location) {
|
||||
return protocol !== location.protocol || host !== location.host;
|
||||
return protocol !== location.protocol || host !== location.host;
|
||||
}
|
||||
|
||||
const objectURLs = new WeakMap();
|
||||
|
||||
export class CrossFader {
|
||||
/** @param {number} fadeDuration */
|
||||
constructor(fadeDuration) {
|
||||
this.sidebar = document.getElementById('_sidebar');
|
||||
this.fadeDuration = fadeDuration;
|
||||
this.prevHash = calcHash(document);
|
||||
this.themeColorEl = document.querySelector('meta[name="theme-color"]');
|
||||
}
|
||||
/** @param {number} fadeDuration */
|
||||
constructor(fadeDuration) {
|
||||
this.sidebar = document.getElementById("_sidebar");
|
||||
this.fadeDuration = fadeDuration;
|
||||
this.prevHash = calcHash(document);
|
||||
this.themeColorEl = document.querySelector('meta[name="theme-color"]');
|
||||
}
|
||||
|
||||
/** @param {Document} newDocument */
|
||||
fetchImage2(newDocument) {
|
||||
const sidebarBg = newDocument.querySelector('.sidebar-bg');
|
||||
const video = sidebarBg?.querySelector('source');
|
||||
const { backgroundImage = '' } = sidebarBg?.style ?? {};
|
||||
const result = RE_CSS_URL.exec(backgroundImage);
|
||||
const videoUrl = video?.src;
|
||||
if (!result) {
|
||||
return of('');
|
||||
}
|
||||
/** @param {Document} newDocument */
|
||||
fetchImage2(newDocument) {
|
||||
const sidebarBg = newDocument.querySelector(".sidebar-bg");
|
||||
const video = sidebarBg?.querySelector("source");
|
||||
const { backgroundImage = "" } = sidebarBg?.style ?? {};
|
||||
const result = RE_CSS_URL.exec(backgroundImage);
|
||||
const videoUrl = video?.src;
|
||||
if (!result) {
|
||||
return of("");
|
||||
}
|
||||
|
||||
const url = new URL(result[1], window.location.origin);
|
||||
const url = new URL(result[1], window.location.origin);
|
||||
|
||||
return fetchRx(url.href, {
|
||||
method: 'GET',
|
||||
headers: { Accept: 'image/*' },
|
||||
...(isExternal(url) ? { mode: 'cors' } : {}),
|
||||
}).pipe(
|
||||
switchMap((r) => r.blob()),
|
||||
map((blob) => [URL.createObjectURL(blob), videoUrl]),
|
||||
catchError(() => of(url.href)),
|
||||
);
|
||||
}
|
||||
return fetchRx(url.href, {
|
||||
method: "GET",
|
||||
headers: { Accept: "image/*" },
|
||||
...(isExternal(url) ? { mode: "cors" } : {}),
|
||||
}).pipe(
|
||||
switchMap((r) => r.blob()),
|
||||
map((blob) => [URL.createObjectURL(blob), videoUrl]),
|
||||
catchError(() => of(url.href)),
|
||||
);
|
||||
}
|
||||
|
||||
/** @param {Document} newDocument */
|
||||
fetchImage(newDocument) {
|
||||
const hash = calcHash(newDocument);
|
||||
if (hash === this.prevHash) return EMPTY;
|
||||
/** @param {Document} newDocument */
|
||||
fetchImage(newDocument) {
|
||||
const hash = calcHash(newDocument);
|
||||
if (hash === this.prevHash) return EMPTY;
|
||||
|
||||
return this.fetchImage2(newDocument).pipe(
|
||||
map(([objectUrl, videoUrl]) => {
|
||||
return this.fetchImage2(newDocument).pipe(
|
||||
map(([objectUrl, videoUrl]) => {
|
||||
/** @type {HTMLDivElement} */
|
||||
const div =
|
||||
newDocument.querySelector(".sidebar-bg") ??
|
||||
document.createElement("div");
|
||||
|
||||
/** @type {HTMLDivElement} */
|
||||
const div = newDocument.querySelector('.sidebar-bg') ?? document.createElement('div');
|
||||
if (objectUrl) {
|
||||
div.style.backgroundImage = `url(${objectUrl})`;
|
||||
objectURLs.set(div, objectUrl);
|
||||
}
|
||||
|
||||
if (objectUrl) {
|
||||
div.style.backgroundImage = `url(${objectUrl})`;
|
||||
objectURLs.set(div, objectUrl);
|
||||
}
|
||||
const video = div.querySelector("video");
|
||||
|
||||
const video = div.querySelector('video');
|
||||
if (video && videoUrl) {
|
||||
video.querySelector("source").src = videoUrl;
|
||||
}
|
||||
|
||||
if (video && videoUrl) {
|
||||
video.querySelector('source').src = videoUrl;
|
||||
}
|
||||
return [div, hash, newDocument];
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
return [div, hash, newDocument];
|
||||
}),
|
||||
);
|
||||
/** @param {Document} newDocument */
|
||||
updateStyle(newDocument) {
|
||||
const classList = newDocument.getElementById("_sidebar")?.classList;
|
||||
if (classList) this.sidebar.setAttribute("class", classList);
|
||||
|
||||
}
|
||||
if (this.themeColorEl) {
|
||||
const themeColor = newDocument.head.querySelector(
|
||||
'meta[name="theme-color"]',
|
||||
)?.content;
|
||||
if (themeColor) {
|
||||
window.setTimeout(() => {
|
||||
if (this.themeColorEl) {
|
||||
this.themeColorEl.content = themeColor;
|
||||
}
|
||||
}, 250);
|
||||
}
|
||||
}
|
||||
|
||||
/** @param {Document} newDocument */
|
||||
updateStyle(newDocument) {
|
||||
const classList = newDocument.getElementById('_sidebar')?.classList;
|
||||
if (classList) this.sidebar.setAttribute('class', classList);
|
||||
try {
|
||||
const pageStyle = document.getElementById("_pageStyle");
|
||||
const newPageStyle = newDocument.getElementById("_pageStyle");
|
||||
if (!newPageStyle) return;
|
||||
pageStyle?.parentNode?.replaceChild(newPageStyle, pageStyle);
|
||||
} catch (e) {
|
||||
if (process.env.DEBUG) console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.themeColorEl) {
|
||||
const themeColor = newDocument.head.querySelector('meta[name="theme-color"]')?.content;
|
||||
if (themeColor) {
|
||||
window.setTimeout(() => {
|
||||
if (this.themeColorEl) {
|
||||
this.themeColorEl.content = themeColor;
|
||||
}
|
||||
}, 250);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param {[HTMLDivElement]} param0
|
||||
* @param {[HTMLDListElement, string, Document]} param1
|
||||
*/
|
||||
fade([prevDiv], [div, hash, newDocument]) {
|
||||
prevDiv?.parentNode?.insertBefore(div, prevDiv.nextElementSibling);
|
||||
|
||||
try {
|
||||
const pageStyle = document.getElementById('_pageStyle');
|
||||
const newPageStyle = newDocument.getElementById('_pageStyle');
|
||||
if (!newPageStyle) return;
|
||||
pageStyle?.parentNode?.replaceChild(newPageStyle, pageStyle);
|
||||
} catch (e) {
|
||||
if (process.env.DEBUG) console.error(e);
|
||||
}
|
||||
}
|
||||
this.updateStyle(newDocument);
|
||||
|
||||
/**
|
||||
* @param {[HTMLDivElement]} param0
|
||||
* @param {[HTMLDListElement, string, Document]} param1
|
||||
*/
|
||||
fade([prevDiv], [div, hash, newDocument]) {
|
||||
prevDiv?.parentNode?.insertBefore(div, prevDiv.nextElementSibling);
|
||||
// Only update the prev hash after we're actually in the fade stage
|
||||
this.prevHash = hash;
|
||||
|
||||
this.updateStyle(newDocument);
|
||||
return animate(div, [{ opacity: 0 }, { opacity: 1 }], {
|
||||
duration: this.fadeDuration,
|
||||
easing: "ease",
|
||||
}).pipe(
|
||||
finalize(() => {
|
||||
if (objectURLs.has(prevDiv))
|
||||
URL.revokeObjectURL(objectURLs.get(prevDiv));
|
||||
prevDiv?.parentNode?.removeChild(prevDiv);
|
||||
|
||||
// Only update the prev hash after we're actually in the fade stage
|
||||
this.prevHash = hash;
|
||||
|
||||
return animate(div, [{ opacity: 0 }, { opacity: 1 }], {
|
||||
duration: this.fadeDuration,
|
||||
easing: 'ease',
|
||||
}).pipe(
|
||||
finalize(() => {
|
||||
if (objectURLs.has(prevDiv)) URL.revokeObjectURL(objectURLs.get(prevDiv));
|
||||
prevDiv?.parentNode?.removeChild(prevDiv);
|
||||
|
||||
div.querySelector('video').play();
|
||||
}),
|
||||
);
|
||||
}
|
||||
div.querySelector("video").play();
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user