Files
replayweb.page/src/gdrive.js
T
sua yoo 1893550274 Format src files with Prettier (#215)
Formats files in `src` with [prettier for consistent code style](https://prettier.io/docs/en/why-prettier) and adds npm script

Related to https://github.com/webrecorder/replayweb.page/issues/201
2023-08-16 18:21:18 -07:00

210 lines
5.2 KiB
JavaScript

import { LitElement, html, css } from "lit";
import { wrapCss } from "./misc";
import fabGoogleDrive from "@fortawesome/fontawesome-free/svgs/brands/google-drive.svg";
// ===========================================================================
class GDrive extends LitElement {
constructor() {
super();
this.state = "trypublic";
this.sourceUrl = "";
this.scriptLoaded = false;
this.error = false;
}
static get properties() {
return {
state: { type: String },
sourceUrl: { type: String },
error: { type: Boolean },
reauth: { type: Boolean },
};
}
updated(changedProperties) {
if (changedProperties.has("sourceUrl")) {
this.error = false;
this.state = "trypublic";
this.tryPublicAccess().then((result) => {
if (!result) {
this.state = "tryauto";
this.requestUpdate();
}
});
}
}
async tryPublicAccess() {
try {
const sourceUrl = this.sourceUrl;
const fileId = sourceUrl.slice("googledrive://".length);
// eslint-disable-next-line no-undef
const publicCheckUrl = `${__HELPER_PROXY__}/g/${fileId}`;
let resp = null;
try {
resp = await fetch(publicCheckUrl);
} catch (e) {
return false;
}
const json = await resp.json();
if (!json.url || !json.name || !json.size) {
return false;
}
// only allow for small downloads that will not result in partial download
if (json.size > 15000000) {
return false;
}
const publicUrl = json.url;
try {
const abort = new AbortController();
const signal = abort.signal;
resp = await fetch(publicUrl, { signal });
abort.abort();
if (resp.status != 200) {
return false;
}
} catch (e) {
return false;
}
const name = json.name;
const extra = { publicUrl };
const size = Number(json.size);
this.dispatchEvent(
new CustomEvent("load-ready", {
detail: { name, extra, size, sourceUrl },
}),
);
return true;
} catch (e) {
return false;
}
}
onLoad() {
this.scriptLoaded = true;
this.gauth("none", (response) => {
if (response.error) {
if (this.state !== "implicitonly") {
this.state = "trymanual";
}
} else {
this.authed(response);
}
});
}
onClickAuth() {
this.gauth("select_account", (response) => {
if (!response.error) {
this.authed(response);
}
});
}
async authed(response) {
const sourceUrl = this.sourceUrl;
const fileId = sourceUrl.slice("googledrive://".length);
const metadataUrl = `https://www.googleapis.com/drive/v3/files/${fileId}`;
const authToken = response.access_token;
const headers = { Authorization: `Bearer ${authToken}` };
const resp = await fetch(
metadataUrl + "?fields=name,size&supportsAllDrives=true",
{ headers },
);
if (resp.status === 404 || resp.status == 403) {
if (this.state !== "implicitonly") {
this.state = "trymanual";
}
this.error = true;
return;
}
this.error = false;
const metadata = await resp.json();
const name = metadata.name;
const size = Number(metadata.size);
this.dispatchEvent(
new CustomEvent("load-ready", {
detail: { sourceUrl, headers, size, name },
}),
);
}
static get styles() {
return wrapCss(css``);
}
render() {
return html` ${this.script()}
${this.state !== "trymanual"
? html` <p>Connecting to Google Drive...</p> `
: html`
${this.error
? html`
<div class="error has-text-danger">
<p>
${this.reauth
? "Some resources are loaded on demand from Google Drive, which requires reauthorization."
: "Could not access this file with the current Google Drive account."}
</p>
<p>
If you have multiple Google Drive accounts, be sure to
select the correct one.
</p>
</div>
<br />
`
: ""}
<button
class="button is-warning is-rounded"
@click="${this.onClickAuth}"
>
<span class="icon"
><fa-icon .svg="${fabGoogleDrive}"></fa-icon
></span>
<span>Authorize Google Drive</span>
</button>
`}`;
}
script() {
if (this.state === "trypublic" || this.scriptLoaded) {
return html``;
}
const script = document.createElement("script");
script.onload = () => this.onLoad();
script.src = "https://apis.google.com/js/platform.js";
return script;
}
gauth(prompt, callback) {
self.gapi.load("auth2", () => {
self.gapi.auth2.authorize(
{
// eslint-disable-next-line no-undef
client_id: __GDRIVE_CLIENT_ID__,
scope: "https://www.googleapis.com/auth/drive.file",
response_type: "token",
prompt,
},
callback,
);
});
}
}
customElements.define("wr-gdrive", GDrive);
export { GDrive };