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
210 lines
5.2 KiB
JavaScript
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 };
|