@uppy/provider-views
Version:
View library for Uppy remote provider plugins.
160 lines (159 loc) • 6.4 kB
JavaScript
import { jsxs as _jsxs, jsx as _jsx } from "preact/jsx-runtime";
import { useCallback, useEffect, useRef, useState } from 'preact/hooks';
import AuthView from '../ProviderView/AuthView.js';
import { authorize, ensureScriptsInjected, InvalidTokenError, logout, pollPickingSession, showDrivePicker, showPhotosPicker, } from './googlePicker.js';
import { GoogleDriveIcon, GooglePhotosIcon } from './icons.js';
function useStore(store, key) {
const [value, setValueState] = useState();
useEffect(() => {
;
(async () => {
setValueState(await store.getItem(key));
})();
}, [key, store]);
const setValue = useCallback(async (v) => {
setValueState(v);
if (v == null) {
return store.removeItem(key);
}
return store.setItem(key, v);
}, [key, store]);
return [value, setValue];
}
export default function GooglePickerView({ uppy, i18n, clientId, onFilesPicked, pickerType, apiKey, appId, storage, }) {
const [loading, setLoading] = useState(false);
const [accessToken, setAccessTokenStored] = useStore(storage, `uppy:google-${pickerType}-picker:accessToken`);
const pickingSessionRef = useRef();
const accessTokenRef = useRef(accessToken);
const shownPickerRef = useRef(false);
const setAccessToken = useCallback((t) => {
uppy.log('Access token updated');
setAccessTokenStored(t);
accessTokenRef.current = t;
}, [setAccessTokenStored, uppy]);
// keep access token in sync with the ref
useEffect(() => {
accessTokenRef.current = accessToken;
}, [accessToken]);
const showPicker = useCallback(async (signal) => {
let newAccessToken = accessToken;
const doShowPicker = async (token) => {
if (pickerType === 'drive') {
await showDrivePicker({
token,
apiKey,
appId,
onFilesPicked,
signal,
});
}
else {
// photos
const onPickingSessionChange = (newPickingSession) => {
pickingSessionRef.current = newPickingSession;
};
await showPhotosPicker({
token,
pickingSession: pickingSessionRef.current,
onPickingSessionChange,
signal,
});
}
};
setLoading(true);
try {
try {
await ensureScriptsInjected(pickerType);
if (newAccessToken == null) {
newAccessToken = await authorize({ clientId, pickerType });
}
if (newAccessToken == null)
throw new Error();
await doShowPicker(newAccessToken);
shownPickerRef.current = true;
setAccessToken(newAccessToken);
}
catch (err) {
if (err instanceof InvalidTokenError) {
uppy.log('Token is invalid or expired, reauthenticating');
newAccessToken = await authorize({
pickerType,
accessToken: newAccessToken,
clientId,
});
// now try again:
await doShowPicker(newAccessToken);
shownPickerRef.current = true;
setAccessToken(newAccessToken);
}
else {
throw err;
}
}
}
catch (err) {
if (err instanceof Error &&
'type' in err &&
err.type === 'popup_closed') {
// user closed the auth popup, ignore
}
else {
setAccessToken(null);
uppy.log(err);
}
}
finally {
setLoading(false);
}
}, [
accessToken,
apiKey,
appId,
clientId,
onFilesPicked,
pickerType,
setAccessToken,
uppy,
]);
useEffect(() => {
const abortController = new AbortController();
pollPickingSession({
pickingSessionRef,
accessTokenRef,
signal: abortController.signal,
onFilesPicked,
onError: (err) => uppy.log(err),
});
return () => abortController.abort();
}, [onFilesPicked, uppy]);
useEffect(() => {
// when mounting, once we have a token, be nice to the user and automatically show the picker
// accessToken === undefined means not yet loaded from storage, so wait for that first
if (accessToken === undefined || shownPickerRef.current) {
return undefined;
}
const abortController = new AbortController();
showPicker(abortController.signal);
return () => {
// only abort the picker if it's not yet shown
if (!shownPickerRef.current)
abortController.abort();
};
}, [accessToken, showPicker]);
const handleLogoutClick = useCallback(async () => {
if (accessToken) {
await logout(accessToken);
setAccessToken(null);
pickingSessionRef.current = undefined;
}
}, [accessToken, setAccessToken]);
if (loading) {
return _jsxs("div", { children: [i18n('pleaseWait'), "..."] });
}
if (accessToken == null) {
return (_jsx(AuthView, { pluginName: pickerType === 'drive'
? i18n('pluginNameGoogleDrivePicker')
: i18n('pluginNameGooglePhotosPicker'), pluginIcon: pickerType === 'drive' ? GoogleDriveIcon : GooglePhotosIcon, handleAuth: showPicker, i18n: i18n, loading: loading }));
}
return (_jsxs("div", { style: { textAlign: 'center' }, children: [_jsx("button", { type: "button", className: "uppy-u-reset uppy-c-btn uppy-c-btn-primary", style: { display: 'block', marginBottom: '1em' }, disabled: loading, onClick: () => showPicker(), children: pickerType === 'drive' ? i18n('pickFiles') : i18n('pickPhotos') }), _jsx("button", { type: "button", className: "uppy-u-reset uppy-c-btn", disabled: loading, onClick: handleLogoutClick, children: i18n('logOut') })] }));
}