UNPKG

@gravatar-com/quick-editor

Version:

A lightweight library to provide seamless Gravatar profile management for third-party sites

142 lines (115 loc) 3.63 kB
const ScopeList = [ 'about', 'avatars', 'verified-accounts', 'links', 'interests', 'contact-info', 'wallet', 'photos', 'design', 'privacy', ] as const; const WINDOW_CHECK_INTERVAL = 500; export type Scope = ( typeof ScopeList )[ number ][]; export type ProfileUpdatedType = 'avatar_updated' | 'profile_updated'; export type Open = ( email?: string ) => boolean; export type Close = () => void; export type IsOpen = () => boolean; export type OnProfileUpdated = ( type: ProfileUpdatedType ) => void; export type OnOpened = () => void; export type OnClosed = () => void; export type QuickEditorCoreOptions = Partial< { email: string; scope: Scope; locale: string; onProfileUpdated: OnProfileUpdated; onOpened: OnOpened; onClosed: OnClosed; utm?: string; } >; export class GravatarQuickEditorCore { _name: string; _email: string; _scope: Scope; _locale: string; _onProfileUpdated: OnProfileUpdated; _onOpened: OnOpened; _onClosed: OnClosed; _utm: string; _window: Window | null = null; constructor( { email, scope = [], locale, onProfileUpdated, onOpened, onClosed, utm }: QuickEditorCoreOptions ) { this._name = this._getName(); this._email = email; this._scope = scope; this._locale = locale; this._onProfileUpdated = onProfileUpdated; this._onOpened = onOpened; this._onClosed = onClosed; this._utm = utm; if ( ! this._scope.every( ( s ) => ScopeList.includes( s ) ) ) { // eslint-disable-next-line console.error( 'Gravatar Quick Editor: Invalid scope definition. Available scope: ' + ScopeList.join( ', ' ) ); this._scope = this._scope.filter( ( s ) => ScopeList.includes( s ) ); } window.addEventListener( 'message', this._onMessage.bind( this ) ); } open: Open = ( email ) => { email = email || this._email; if ( ! email ) { // eslint-disable-next-line console.error( 'Gravatar Quick Editor: Email not provided' ); return false; } email = encodeURIComponent( email ); const scope = encodeURIComponent( this._scope.join( ',' ) ); const width = 400; const height = 720; const left = window.screenLeft + ( window.outerWidth - width ) / 2; const top = window.screenTop + ( window.outerHeight - height ) / 2; const options = `popup,width=${ width },height=${ height },top=${ top },left=${ left }`; const host = this._locale ? `https://${ this._locale }.gravatar.com` : 'https://gravatar.com'; const utm = this._utm ? `&utm=${ encodeURIComponent( this._utm ) }` : ''; const url = `${ host }/profile?email=${ email }&scope=${ scope }&is_quick_editor=true${ utm }`; this._window = window.open( url, this._name, options ); if ( this._window === null ) { // eslint-disable-next-line console.error( 'Gravatar Quick Editor: Could not open window' ); return false; } if ( this._onOpened ) { this._onOpened(); } if ( this._onClosed ) { const timer = setInterval( () => { if ( this._window.closed ) { clearInterval( timer ); this._onClosed(); } }, WINDOW_CHECK_INTERVAL ); } return true; }; close: Close = () => { if ( this._window ) { this._window.close(); } }; isOpen: IsOpen = () => { return this._window !== null && ! this._window.closed; }; _getName() { return `GravatarQuickEditor_${ new Date().getTime() }${ Math.floor( Math.random() * ( 9999 - 1000 ) + 1000 ) }`; } _onMessage( event: MessageEvent ) { if ( ! this._onProfileUpdated || ! event.origin.match( /https:\/\/([a-z\-]{2,5}\.)?gravatar.com/ ) ) { return; } if ( event.data?.name !== this._name ) { return; } this._onProfileUpdated( event.data.type ); } }