import React, { useEffect, useRef, useState } from 'react'; import { __, sprintf } from '@wordpress/i18n'; import { api } from '../api/index.js'; import { canManagePluginNotifications, getPluginNotificationQuestion, } from '../lib/plugin-notifications.js'; import { Button } from './UI/index.jsx'; import PluginNotificationPreferences from './PluginNotificationPreferences.jsx'; export default function PluginNotificationsCard() { const [ settings, setSettings ] = useState( null ); const [ defaults, setDefaults ] = useState( null ); const [ loading, setLoading ] = useState( true ); const [ saving, setSaving ] = useState( false ); const [ editing, setEditing ] = useState( false ); const [ error, setError ] = useState( '' ); const [ saved, setSaved ] = useState( false ); const [ reload, setReload ] = useState( 0 ); const initialRef = useRef( null ); const savingRef = useRef( false ); const mountedRef = useRef( false ); const allowed = canManagePluginNotifications(); const dirty = settings && JSON.stringify( settings ) !== JSON.stringify( initialRef.current ); useEffect( () => { mountedRef.current = true; return () => { mountedRef.current = false; }; }, [] ); useEffect( () => { if ( ! allowed ) return; let active = true; setLoading( true ); setError( '' ); api.getPluginNotifications() .then( ( result ) => { if ( ! active ) return; if ( ! result?.settings ) throw new Error( __( 'Could not load notification preferences.', 'arrayfunnel' ) ); initialRef.current = result.settings; setSettings( result.settings ); setDefaults( result.defaults ); } ) .catch( ( err ) => { if ( active ) setError( err.message || __( 'Could not load notification preferences.', 'arrayfunnel' ) ); } ) .finally( () => { if ( active ) setLoading( false ); } ); return () => { active = false; }; }, [ allowed, reload ] ); const save = async ( event ) => { event.preventDefault(); if ( savingRef.current || editing || ! dirty ) return; const validationError = getPluginNotificationQuestion( defaults ).validate( settings ); if ( validationError ) { setError( validationError ); return; } savingRef.current = true; setSaving( true ); setError( '' ); setSaved( false ); try { const result = await api.savePluginNotifications( { settings, initial_settings: initialRef.current, } ); if ( ! result?.settings ) throw new Error( __( 'Could not save notification preferences.', 'arrayfunnel' ) ); if ( ! mountedRef.current ) return; initialRef.current = result.settings; setSettings( result.settings ); if ( result.defaults ) setDefaults( result.defaults ); setSaved( true ); } catch ( err ) { if ( mountedRef.current ) setError( err.message || __( 'Could not save notification preferences.', 'arrayfunnel' ) ); } finally { savingRef.current = false; if ( mountedRef.current ) setSaving( false ); } }; return (
{ ! allowed ? (

{ __( 'A site administrator can manage plugin notification preferences.', 'arrayfunnel' ) }

) : loading ? (

{ __( 'Loading notification preferences…', 'arrayfunnel' ) }

) : settings ? (
{ setSettings( next ); setSaved( false ); setError( '' ); } } disabled={ saving } onEditingChange={ setEditing } /> { error && (

{ error }

) }
{ editing ? __( 'Confirm the recipient with the checkmark, then save your preferences.', 'arrayfunnel' ) : dirty ? __( 'You have unsaved changes.', 'arrayfunnel' ) : saved ? __( 'Notification preferences saved.', 'arrayfunnel' ) : '' }
) : ( <>

{ error }

) }
); } function ContactSiteDeveloper( { name, email, disabled } ) { const [ message, setMessage ] = useState( '' ); const copyingRef = useRef( false ); const timeoutRef = useRef( null ); const mountedRef = useRef( false ); const unavailable = disabled || ! email; useEffect( () => { mountedRef.current = true; return () => { mountedRef.current = false; clearTimeout( timeoutRef.current ); }; }, [] ); const contact = async ( event ) => { event.preventDefault(); if ( unavailable || copyingRef.current ) return; const href = event.currentTarget.href; copyingRef.current = true; clearTimeout( timeoutRef.current ); try { await copyText( email ); if ( mountedRef.current ) setMessage( sprintf( /* translators: %s: site developer's email address. */ __( 'Email %s copied to clipboard', 'arrayfunnel' ), email ) ); } catch { if ( mountedRef.current ) setMessage( __( 'Could not copy the email address. Please copy it manually.', 'arrayfunnel' ) ); } finally { copyingRef.current = false; if ( mountedRef.current ) { timeoutRef.current = setTimeout( () => setMessage( '' ), 3000 ); window.location.href = href; } } }; return ( { name ? sprintf( /* translators: %s: site developer's name. */ __( 'Contact site developer — %s', 'arrayfunnel' ), name ) : __( 'Contact site developer', 'arrayfunnel' ) } { message && ( { message } ) } ); } async function copyText( value ) { try { if ( navigator.clipboard?.writeText ) { await navigator.clipboard.writeText( value ); return; } } catch { // Older browsers and insecure admin URLs can still use the selection fallback. } const previousFocus = document.activeElement; const field = document.createElement( 'textarea' ); field.value = value; field.setAttribute( 'readonly', '' ); field.style.position = 'fixed'; field.style.opacity = '0'; document.body.appendChild( field ); field.select(); try { if ( ! document.execCommand( 'copy' ) ) throw new Error( 'clipboard_unavailable' ); } finally { field.remove(); previousFocus?.focus( { preventScroll: true } ); } }