Skip to content

Instantly share code, notes, and snippets.

@fotoflo
Created July 21, 2022 23:03
Show Gist options
  • Save fotoflo/a15b25e3721266827341723b1964ecc6 to your computer and use it in GitHub Desktop.
Save fotoflo/a15b25e3721266827341723b1964ecc6 to your computer and use it in GitHub Desktop.
import React, { useState, createContext, useEffect, useCallback } from "react";
export const GapiClientContext = createContext();
const GAPI_CONFIG = {
apiKey: process.env.NEXT_PUBLIC_FIREBASE_CONFIG_apiKey,
clientId: process.env.GOOGLE_ID,
scope: "https://www.googleapis.com/auth/gmail.send",
discoveryDocs: ["https://www.googleapis.com/discovery/v1/apis/gmail/v1/rest"],
fetch_basic_profile: true,
immediate: true,
plugin_name: "app name",
};
const GapiContextProvider = ({ session, ...props }) => {
const defaultButtonText = "Send Email";
const sendingButtonText = "Sending";
const [gmailSuccessMessage, setGmailSuccessMessage] = useState("");
const [gmailErrorMessage, setGmailErrorMessage] = useState("");
const [gmailButtonText, setGmailButtonText] = useState(defaultButtonText);
const [gmailIsSent, setGmailIsSent] = useState(false);
const [gmailIsSending, setGmailIsSending] = useState(false);
const [gmailIsError, setGmailIsError] = useState(false);
const [gmailIsDisabled, setGmailIsDisabled] = useState(true);
const [GapiClient, setGapiClient] = useState(); //{ gapi });
// to test initClient properly, remove access from third party access after each grant:
// https://myaccount.google.com/permissions?continue=https%3A%2F%2Fmyaccount.google.com%2Fsecurity%3Fpli%3D1
// then logout
// to ensure gapi only loads once: https://stackoverflow.com/questions/68985492/how-to-prevent-script-from-loading-multiple-times-with-react
const initClient = useCallback(async () => {
if (window.gapiIsInitialized) return;
console.log("intting gapi");
return gapi.client.init(GAPI_CONFIG).then(
() => {
const access_token =
session.externalAccounts.find((acct) => acct.provider === "gmail")
?.access_token ?? "";
if (access_token === "") return;
gapi.client.setToken({ access_token });
window.gapiIsInitialized = true;
setGmailIsDisabled(false);
return;
},
(e) => {
window.gapiIsLoading = false;
console.info("error init gapi client", e.details);
}
);
}, []);
const setupGapi = useCallback(async () => {
const gapi = await import("gapi-script").then((pack) => pack.gapi);
// https://stackoverflow.com/questions/71040050/why-am-i-getting-syntaxerror-cannot-use-import-statement-outside-a-module
setGapiClient({ gapi });
try {
await gapi.load("client:auth2", initClient);
} catch (e) {
window.gapiIsLoading = false;
console.log("couldnt sign in to gAPI!", e);
}
}, [initClient]);
useEffect(() => {
if (window.gapiIsInitialized || window.gapiIsLoading) return;
window.gapiIsLoading = true;
setupGapi();
}, [initClient, setupGapi]);
useEffect(() => {
// handle gmail sending state
if (gmailIsSending) {
setGmailIsDisabled(true);
setGmailButtonText(sendingButtonText);
}
if (gmailIsSent) {
setGmailSuccessMessage("Sent!");
setGmailButtonText(defaultButtonText);
}
if (gmailIsError) {
setGmailIsDisabled(true);
setGmailButtonText(defaultButtonText);
}
setTimeout(() => {
setGmailSuccessMessage([""]);
setGmailErrorMessage([""]);
setGmailIsSending(false);
setGmailIsError(false);
setGmailIsSent(false);
setGmailIsDisabled(false);
}, 10000);
}, [gmailIsSending, gmailIsSent, gmailIsError]);
return (
<GapiClientContext.Provider
value={{
GapiClient,
gmailButtonText,
gmailSuccessMessage,
gmailErrorMessage,
setGmailIsSending,
setGmailIsSent,
setGmailIsError,
setGmailErrorMessage,
gmailIsDisabled,
}}
>
{props.children}
</GapiClientContext.Provider>
);
};
export default GapiContextProvider;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment