import { LitElement, html, css } from 'lit-element'; import { wrapCss, rwpLogo, IS_APP, clickOnSpacebarPress } from './misc'; import { registerSW } from './pageutils'; import fasHelp from '@fortawesome/fontawesome-free/svgs/solid/question-circle.svg'; import fasArrowLeft from '@fortawesome/fontawesome-free/svgs/solid/arrow-left.svg'; import fasArrowRight from '@fortawesome/fontawesome-free/svgs/solid/arrow-right.svg'; // =========================================================================== class ReplayWebApp extends LitElement { constructor() { super(); this.sourceUrl = null; this.collTitle = null; this.showAbout = false; this.pageParams = {}; this.inited = false; this.navMenuShown = false; this.collPageUrl = ""; this.pageTitle = ""; this.pageReplay = false; registerSW(__SW_NAME__); this.safariKeyframes(); } get appName() { return "ReplayWeb.page"; } get homeUrl() { return window.location.pathname; } static get properties() { return { inited: { type: Boolean }, pageParams: { type: Object }, sourceUrl: { type: String }, navMenuShown: { type: Boolean }, showAbout: { type: Boolean }, collTitle: { type: String }, loadInfo: { type: Object }, embed: { type: String }, collPageUrl: { type: String }, pageTitle: { type: String }, pageReplay: { type: Boolean }, source: { type: String } } } static get styles() { return wrapCss(ReplayWebApp.appStyles); } static get appStyles() { return css` #wrlogo { max-height: 1.0rem; } .navbar { height: 1.5rem; } .navbar-brand { height: 1.5rem; display: flex; align-items: center; } .wr-logo-item { padding: 0 8px 0 0; } .no-wrap { white-space: nowrap; overflow-x: hidden; text-overflow: ellipsis; } .has-allcaps { font-variant-caps: small-caps; } :host { position: fixed; left: 0px; top: 0px; bottom: 0px; right: 0px; display: flex; min-width: 0px; flex-direction: column; } wr-coll { height: 100%; } .navbar { padding: 0 0.5em; } div.navbar-menu fa-icon { vertical-align: sub; } .tagline { margin-top: 1.0rem; } @media screen and (min-width: 840px) { .menu-only { display: none; } a.arrow-button { padding-left: 4px; padding-right: 4px; } .info-menu { padding: 0 1.0em; } .logo-text { padding-left: 0px; margin-left: 6px; } a.navbar-item.logo-text:hover { background-color: initial; } } @media screen and (max-width: 840px) { .wide-only { display: none !important; } } `; } get mainLogo() { return rwpLogo; } renderNavBrand() { return html` replay web.page Home `; } renderNavBar() { return html`

Skipped

`; } renderNavEnd() { return html`  User Docs About ` } renderColl() { return html` this.showAbout = true}>`; } renderHomeIndex() { return html` ${!IS_APP ? html`

Explore and Replay Interactive Archived Webpages Directly in your Browser. (See Examples)

` : ``}
`; } render() { if (!this.inited) { return html``; } return html` ${!this.embed || this.embed === "full" ? this.renderNavBar() : ''} ${this.sourceUrl ? this.renderColl() : this.renderHomeIndex()} ${this.showAbout ? this.renderAbout() : ``} `; } firstUpdated() { this.initRoute(); window.addEventListener("popstate", (event) => { this.initRoute(); }); } updated(changedProperties) { if (changedProperties.has("sourceUrl")) { this.collTitle = null; } } onFavIcons(event) { const head = document.querySelector('head'); const oldLinks = document.querySelectorAll("link[rel*='icon']"); for (const link of oldLinks) { head.removeChild(link); } for (const icon of event.detail.icons) { const link = document.createElement('link'); link.rel = icon.rel; link.href = icon.href; head.appendChild(link); } } skipMenu(event){ // This is a workaround, since this app's routing doesn't permit normal // following of in-page anchors. event.preventDefault(); this.renderRoot.querySelector("#skip-main-target").focus() } onNavMenu(event) { event.preventDefault(); event.stopPropagation(); this.navMenuShown = !this.navMenuShown; if (this.navMenuShown) { // Since this menu can be large and obscure significant page content, // dismiss like a modal, returning keyboard focus to the // menu button on dismissal. document.addEventListener("click", (event) => { event.preventDefault(); this.navMenuShown = false; this.renderRoot.querySelector("#menu-button").focus(); }, {once: true}); document.addEventListener("keypress", (event) => { if (event.key == "Escape") { event.preventDefault(); this.navMenuShown = false; this.renderRoot.querySelector("#menu-button").focus(); } }, {once: true}); } } initRoute() { this.inited = true; this.pageParams = new URLSearchParams(window.location.search); // Google Drive let state = this.pageParams.get("state"); if (state) { try { state = JSON.parse(state); if ((state.ids instanceof Array) && state.userId && state.action === "open") { this.pageParams.set("source", "googledrive://" + state.ids[0]); this.pageParams.delete("state"); window.location.search = this.pageParams.toString(); return; } } catch (e) { console.log(e); } } if (this.source) { this.pageParams.set("source", this.source); const url = new URL(window.location.href); url.search = this.pageParams.toString(); window.history.replaceState({}, document.title, url.href); } this.sourceUrl = this.pageParams.get("source") || ""; this.embed = this.pageParams.get("embed") || ""; if (this.pageParams.has("terms")) { this.showAbout = true; } if (this.pageParams.get("config")) { if (!this.loadInfo) { this.loadInfo = {} } try { this.loadInfo.extraConfig = JSON.parse(this.pageParams.get("config")); } catch (e) { console.log("invalid config: " + e); } } if (this.pageParams.get("basePageUrl")) { if (!this.loadInfo) { this.loadInfo = {extraConfig: {}} } if (!this.loadInfo.extraConfig) { this.loadInfo.extraConfig = {}; } this.loadInfo.extraConfig.baseUrl = this.pageParams.get("basePageUrl"); } if (this.pageParams.get("customColl")) { if (!this.loadInfo) { this.loadInfo = {} } this.loadInfo.customColl = this.pageParams.get("customColl"); } if (IS_APP && this.sourceUrl.startsWith("file://")) { const url = new URL(__APP_FILE_SERVE_PREFIX__); url.searchParams.set("filename", this.sourceUrl.slice("file://".length)); this.loadInfo = { sourceUrl: this.sourceUrl, loadUrl: url.href, } } } onStartLoad(event) { // just redirect right away? this.pageParams.set("source", event.detail.sourceUrl); const url = new URL(window.location.href); url.search = this.pageParams.toString(); this.collPageUrl = url.toString(); if (!event.detail.isFile) { window.location.search = this.pageParams.toString(); return; } else { window.history.pushState({}, "", this.collPageUrl); } this.sourceUrl = event.detail.sourceUrl; this.loadInfo = event.detail; } onCollLoaded(event) { this.loadInfo = null; if (event.detail.collInfo) { this.collTitle = event.detail.collInfo.title; } if (event.detail.alreadyLoaded) { //this.sourceLoaded = true; return; } //this.initRoute(); if (event.detail.sourceUrl !== this.sourceUrl) { this.pageParams.set("source", event.detail.sourceUrl); window.location.search = this.pageParams.toString(); } } onTitle(event) { if (event.detail.title) { this.pageTitle = event.detail.title; this.pageReplay = event.detail.replayTitle; document.title = (event.detail.replayTitle ? "Archive of " : "") + this.pageTitle + " | ReplayWeb.page"; } } safariKeyframes() { // Safari requires keyframes at the document level, add spinner keyframes here const css = ` @keyframes spinAround { from { transform: rotate(0deg); } to { transform: rotate(359deg); } } `; const style = document.createElement("style"); document.head.appendChild(style); style.appendChild(document.createTextNode(css)); } renderAbout() { return html` `; } onAboutClose() { this.showAbout = false; } } customElements.define("replay-app-main", ReplayWebApp); export { ReplayWebApp };