import { Linking } from "react-native" ; import { URL , URLSearchParams } from "react-native-url-polyfill" ; import joinURL from "url-join" ; import { getEmitter as getDropboxEmitter } from "./dropbox" ; import { processCodeExchange as processGoogleDriveCodeExchange } from "./google" ; import { notifyError , notifySuccess } from "../library/notifications" ; import { addPendingOTP } from "./otpAll" ; const URI_PROTO_BUTTERCUP = "buttercup://" ; const URI_PROTO_OTPAUTH = "otpauth://" ; function extractHashProperties ( url ) { const hashProps = ( url . hash || "" ) . replace ( /^#/ , "" ) . split ( "&" ) ; return hashProps . reduce ( ( output , keyVal ) => { const [ key , value ] = keyVal . split ( "=" ) ; return { ... output , [ key ] : value } ; } , { } ) ; } function extractQueryProperties ( url ) { const params = url . searchParams ; const output = { } ; for ( const [ name , value ] of params ) { output [ name ] = value ; } return output ; } async function handleURLChange ( url ) { if ( ! url ) return ; const lowerURL = url . toLowerCase ( ) ; if ( lowerURL . indexOf ( URI_PROTO_BUTTERCUP ) === 0 ) { processButtercupURL ( new URL ( url ) ) ; } else if ( lowerURL . indexOf ( URI_PROTO_OTPAUTH ) === 0 ) { const stored = await addPendingOTP ( url ) ; if ( stored ) { notifySuccess ( "OTP Payload Received" , "Edit an entry to save it." ) ; } } else { notifyError ( "Unrecognised URI" , "Buttercup received an unrecognised URI request." ) ; } } export async function initialise ( ) { const initialURL = await Linking . getInitialURL ( ) ; if ( initialURL ) { await handleURLChange ( initialURL ) ; } const urlChangeHandler = async ( { url } ) => { await handleURLChange ( url ) ; } ; Linking . addEventListener ( "url" , urlChangeHandler ) ; } function normaliseButtercupPath ( url ) { return joinURL ( "/" , url . host , url . pathname ) . replace ( /\/+$/ , "" ) ; } function processButtercupURL ( url ) { switch ( normaliseButtercupPath ( url ) ) { case "/auth/dropbox" : { const { access_token : accessToken } = extractHashProperties ( url ) ; getDropboxEmitter ( ) . emit ( "token" , { token : accessToken } ) ; break ; } case "/auth/google" : { const { code : authCode } = extractQueryProperties ( url ) ; processGoogleDriveCodeExchange ( authCode ) ; break ; } default : console . warn ( "Unrecognised URL" , url . toString ( ) ) ; break ; } }