pages235/src/googledrive.ts

110 lines
4.2 KiB
TypeScript

import { GoogleOAuthProvider, useGoogleLogin } from '@react-oauth/google'
import { proxy, ref, subscribe } from 'valtio'
import React from 'react'
import { loadScript } from 'prismarine-viewer/viewer/lib/utils'
import { loadGoogleDriveApi, loadInMemorySave } from './react/SingleplayerProvider'
import { setLoadingScreenStatus } from './utils'
import { mountGoogleDriveFolder } from './browserfs'
import { showOptionsModal } from './react/SelectOption'
const CLIENT_ID = '137156026346-igv2gkjsj2hlid92rs3q7cjjnc77s132.apps.googleusercontent.com'
// const CLIENT_ID = process.env.GOOGLE_CLIENT_ID
const SCOPES = 'https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.install'
export const APP_ID = CLIENT_ID.split('-')[0]
export const GoogleDriveProvider = ({ children }) => {
return React.createElement(GoogleOAuthProvider, { clientId: CLIENT_ID } as any, children)
// return <GoogleOAuthProvider clientId={CLIENT_ID}><Root /></GoogleOAuthProvider>
}
export const isGoogleDriveAvailable = () => {
return !!CLIENT_ID
}
export const useGoogleLogIn = () => {
const login = useGoogleLogin({
onSuccess (tokenResponse) {
localStorage.hasEverLoggedIn = true
googleProviderState.accessToken = tokenResponse.access_token
googleProviderState.expiresIn = ref(new Date(Date.now() + tokenResponse.expires_in * 1000))
googleProviderState.hasEverLoggedIn = true
},
// prompt: hasEverLoggedIn ? 'none' : 'consent',
scope: SCOPES,
flow: 'implicit',
onError (error) {
const accessDenied = error.error === 'access_denied' || error.error === 'invalid_scope' || (error as any).error_subtype === 'access_denied'
if (accessDenied) {
googleProviderState.hasEverLoggedIn = false
}
}
})
return () => login({
prompt: googleProviderState.hasEverLoggedIn ? 'none' : 'consent'
})
}
export const possiblyHandleStateVariable = async () => {
const stateParam = new URLSearchParams(window.location.search).get('state')
if (!stateParam) return
setLoadingScreenStatus('Opening world in read only mode, waiting for login...')
await loadGoogleDriveApi()
await loadScript('https://accounts.google.com/gsi/client')
const parsed = JSON.parse(stateParam) as {
ids: [string]
action: 'open'
userId: string
}
const tokenClient = window.google.accounts.oauth2.initTokenClient({
client_id: CLIENT_ID,
scope: SCOPES,
async callback (response) {
if (response.error) {
setLoadingScreenStatus('Error: ' + response.error, true)
googleProviderState.hasEverLoggedIn = false
return
}
setLoadingScreenStatus('Opening world in read only mode...')
googleProviderState.accessToken = response.access_token
await mountGoogleDriveFolder(true, parsed.ids[0])
await loadInMemorySave('/google')
}
})
const choice = await showOptionsModal('Select an action...', ['Login'])
if (choice === 'Login') {
tokenClient.requestAccessToken({
prompt: googleProviderState.hasEverLoggedIn ? '' : 'consent',
})
} else {
window.close()
}
}
export const googleProviderState = proxy({
accessToken: (localStorage.saveAccessToken ? localStorage.accessToken : null) as string | null,
hasEverLoggedIn: !!(localStorage.hasEverLoggedIn),
isReady: false,
expiresIn: localStorage.saveAccessToken ? ref(new Date(Date.now() + 1000 * 60 * 60)) : null,
readonlyMode: localStorage.googleReadonlyMode ? localStorage.googleReadonlyMode === 'true' : true,
lastSelectedFolder: (localStorage.lastSelectedFolder ? JSON.parse(localStorage.lastSelectedFolder) : null) as {
id: string
name: string
} | null
})
subscribe(googleProviderState, () => {
localStorage.googleReadonlyMode = googleProviderState.readonlyMode
localStorage.lastSelectedFolder = googleProviderState.lastSelectedFolder ? JSON.stringify(googleProviderState.lastSelectedFolder) : null
if (googleProviderState.hasEverLoggedIn) {
localStorage.hasEverLoggedIn = true
} else {
delete localStorage.hasEverLoggedIn
}
if (localStorage.saveAccessToken && googleProviderState) {
// For testing only
localStorage.accessToken = googleProviderState.accessToken || null
} else {
delete localStorage.accessToken
}
})