updated plugin ActivityPub version 8.3.0

This commit is contained in:
2026-06-03 21:28:46 +00:00
committed by Gitium
parent a4b78ec277
commit 6fe182458a
340 changed files with 43232 additions and 7568 deletions

View File

@ -17,5 +17,4 @@ jQuery( function( $ ) {
$( '.activate-now' ).removeClass( 'thickbox open-plugin-details-modal' );
}, 1200 );
} );
} );

View File

@ -0,0 +1,364 @@
/**
* ActivityPub Connected Applications JavaScript.
*
* Handles registering OAuth clients, deleting clients, and revoking
* OAuth tokens from the user profile, following the WordPress core
* Application Passwords UI pattern.
*/
/* global activitypubConnectedApps, jQuery, ClipboardJS */
( function( $ ) {
var $section = $( '#activitypub-connected-apps-section' ),
$newAppForm = $section.find( '.create-application-password' ),
$newAppFields = $newAppForm.find( '.input' ),
$newAppButton = $newAppForm.find( '.button' ),
$appsWrapper = $section.find( '#activitypub-registered-apps-wrapper' ),
$appsTbody = $section.find( '#activitypub-registered-apps-tbody' ),
$tokensWrapper = $section.find( '.activitypub-connected-apps-list-table-wrapper' ),
$tokensTbody = $section.find( '#activitypub-connected-apps-tbody' ),
$revokeAll = $section.find( '#activitypub-revoke-all-tokens' ),
$deleteAll = $section.find( '#activitypub-delete-all-clients' );
// Register a new application.
$newAppButton.on( 'click', function( e ) {
e.preventDefault();
if ( $newAppButton.prop( 'aria-disabled' ) ) {
return;
}
var $name = $( '#activitypub-new-app-name' );
var $redirectUri = $( '#activitypub-new-app-redirect-uri' );
if ( 0 === $name.val().trim().length ) {
$name.trigger( 'focus' );
return;
}
if ( 0 === $redirectUri.val().trim().length ) {
$redirectUri.trigger( 'focus' );
return;
}
clearNotices();
$newAppButton.prop( 'aria-disabled', true ).addClass( 'disabled' );
$.ajax( {
url: activitypubConnectedApps.ajaxUrl,
method: 'POST',
data: {
action: 'activitypub_register_oauth_client',
name: $name.val().trim(),
redirect_uri: $redirectUri.val().trim(),
_wpnonce: activitypubConnectedApps.nonce
}
} ).always( function() {
$newAppButton.removeProp( 'aria-disabled' ).removeClass( 'disabled' );
} ).done( function( response ) {
if ( ! response.success ) {
addNotice(
response.data && response.data.message ? response.data.message : activitypubConnectedApps.registerError,
'error'
);
return;
}
// Build credential notice (matches core's tmpl-new-application-password).
var $notice = $( '<div></div>' )
.attr( 'role', 'alert' )
.attr( 'tabindex', '-1' )
.addClass( 'notice notice-success is-dismissible new-application-password-notice' );
// Client ID row.
var $clientIdRow = $( '<p></p>' ).addClass( 'application-password-display' )
.append( $( '<label></label>' ).text( activitypubConnectedApps.clientIdLabel ) )
.append( $( '<input>' ).attr( { type: 'text', readonly: 'readonly' } ).addClass( 'code' ).val( response.data.client_id ) )
.append(
$( '<button>' ).attr( 'type', 'button' ).addClass( 'button copy-button' )
.attr( 'data-clipboard-text', response.data.client_id )
.text( activitypubConnectedApps.copy )
)
.append( $( '<span>' ).addClass( 'success hidden' ).attr( 'aria-hidden', 'true' ).text( activitypubConnectedApps.copied ) );
$notice.append( $clientIdRow );
// Client Secret row (if present).
if ( response.data.client_secret ) {
var $secretRow = $( '<p></p>' ).addClass( 'application-password-display' )
.append( $( '<label></label>' ).text( activitypubConnectedApps.clientSecretLabel ) )
.append( $( '<input>' ).attr( { type: 'text', readonly: 'readonly' } ).addClass( 'code' ).val( response.data.client_secret ) )
.append(
$( '<button>' ).attr( 'type', 'button' ).addClass( 'button copy-button' )
.attr( 'data-clipboard-text', response.data.client_secret )
.text( activitypubConnectedApps.copy )
)
.append( $( '<span>' ).addClass( 'success hidden' ).attr( 'aria-hidden', 'true' ).text( activitypubConnectedApps.copied ) );
$notice.append( $secretRow );
}
$notice.append( $( '<p></p>' ).text( activitypubConnectedApps.saveWarning ) );
// Dismiss button (matches core's tmpl-new-application-password).
$notice.append(
$( '<button>' ).attr( 'type', 'button' ).addClass( 'notice-dismiss' )
.append( $( '<span>' ).addClass( 'screen-reader-text' ).text( activitypubConnectedApps.dismiss ) )
);
// Insert after the form (not inside it), same as core.
$newAppForm.after( $notice );
$notice.trigger( 'focus' );
// Initialize ClipboardJS for the new notice.
if ( 'undefined' !== typeof ClipboardJS ) {
new ClipboardJS( '.new-application-password-notice .copy-button' )
.on( 'success', function( clipEvent ) {
var $btn = $( clipEvent.trigger );
$btn.siblings( '.success' ).removeClass( 'hidden' );
setTimeout( function() {
$btn.siblings( '.success' ).addClass( 'hidden' );
}, 3000 );
} );
}
// Add the new client to the registered apps table.
var $row = $( '<tr>' )
.attr( 'data-client-id', response.data.client_id )
.append( $( '<td>' ).text( $name.val().trim() ) )
.append( $( '<td>' ).text( $redirectUri.val().trim() ) )
.append( $( '<td>' ).text( response.data.created ) )
.append(
$( '<td>' ).append(
$( '<button>' )
.addClass( 'button delete' )
.text( activitypubConnectedApps.deleteLabel )
)
);
$appsTbody.prepend( $row );
$appsWrapper.show();
// Clear the form fields.
$name.val( '' );
$redirectUri.val( '' );
} ).fail( function( xhr, textStatus, errorThrown ) {
var errorMessage = errorThrown;
if ( xhr.responseJSON && xhr.responseJSON.message ) {
errorMessage = xhr.responseJSON.message;
}
addNotice( errorMessage || activitypubConnectedApps.registerError, 'error' );
} );
} );
// Delete a registered client.
$appsTbody.on( 'click', '.delete', function( e ) {
e.preventDefault();
if ( ! window.confirm( activitypubConnectedApps.confirmDelete ) ) {
return;
}
var $button = $( this ),
$tr = $button.closest( 'tr' ),
clientId = $tr.data( 'client-id' );
clearNotices();
$button.prop( 'disabled', true );
$.ajax( {
url: activitypubConnectedApps.ajaxUrl,
method: 'POST',
data: {
action: 'activitypub_delete_oauth_client',
client_id: clientId,
_wpnonce: activitypubConnectedApps.nonce
}
} ).always( function() {
$button.prop( 'disabled', false );
} ).done( function( response ) {
if ( response.success && response.data.deleted ) {
if ( 0 === $tr.siblings().length ) {
$appsWrapper.hide();
}
$tr.remove();
addNotice( activitypubConnectedApps.appDeleted, 'success' ).trigger( 'focus' );
}
} ).fail( handleErrorResponse );
} );
// Delete all registered clients.
$deleteAll.on( 'click', function( e ) {
e.preventDefault();
if ( ! window.confirm( activitypubConnectedApps.confirmDeleteAll ) ) {
return;
}
var $button = $( this );
clearNotices();
$button.prop( 'disabled', true );
$.ajax( {
url: activitypubConnectedApps.ajaxUrl,
method: 'POST',
data: {
action: 'activitypub_delete_all_oauth_clients',
_wpnonce: activitypubConnectedApps.nonce
}
} ).always( function() {
$button.prop( 'disabled', false );
} ).done( function( response ) {
if ( response.success && response.data.deleted ) {
$appsTbody.children().remove();
$appsWrapper.hide();
addNotice( activitypubConnectedApps.allAppsDeleted, 'success' ).trigger( 'focus' );
}
} ).fail( handleErrorResponse );
} );
// Revoke a single token.
$tokensTbody.on( 'click', '.delete', function( e ) {
e.preventDefault();
if ( ! window.confirm( activitypubConnectedApps.confirm ) ) {
return;
}
var $button = $( this ),
$tr = $button.closest( 'tr' ),
metaKey = $tr.data( 'meta-key' );
clearNotices();
$button.prop( 'disabled', true );
$.ajax( {
url: activitypubConnectedApps.ajaxUrl,
method: 'POST',
data: {
action: 'activitypub_revoke_oauth_token',
meta_key: metaKey,
_wpnonce: activitypubConnectedApps.nonce
}
} ).always( function() {
$button.prop( 'disabled', false );
} ).done( function( response ) {
if ( response.success && response.data.deleted ) {
if ( 0 === $tr.siblings().length ) {
$tokensWrapper.hide();
}
$tr.remove();
addNotice( activitypubConnectedApps.appRevoked, 'success' ).trigger( 'focus' );
}
} ).fail( handleErrorResponse );
} );
// Revoke all tokens.
$revokeAll.on( 'click', function( e ) {
e.preventDefault();
if ( ! window.confirm( activitypubConnectedApps.confirmAll ) ) {
return;
}
var $button = $( this );
clearNotices();
$button.prop( 'disabled', true );
$.ajax( {
url: activitypubConnectedApps.ajaxUrl,
method: 'POST',
data: {
action: 'activitypub_revoke_all_oauth_tokens',
_wpnonce: activitypubConnectedApps.nonce
}
} ).always( function() {
$button.prop( 'disabled', false );
} ).done( function( response ) {
if ( response.success && response.data.deleted ) {
$tokensTbody.children().remove();
$section.children( '.new-application-password-notice' ).remove();
$tokensWrapper.hide();
addNotice( activitypubConnectedApps.allAppsRevoked, 'success' ).trigger( 'focus' );
}
} ).fail( handleErrorResponse );
} );
// Dismiss notices via event delegation on the section (same as core).
$section.on( 'click', '.notice-dismiss', function( e ) {
e.preventDefault();
var $el = $( this ).parent();
$el.removeAttr( 'role' );
$el.fadeTo( 100, 0, function() {
$el.slideUp( 100, function() {
$el.remove();
$newAppFields.first().trigger( 'focus' );
} );
} );
} );
// Submit form on Enter key in input fields (same as core).
$newAppFields.on( 'keypress', function( e ) {
if ( 13 === e.which ) {
e.preventDefault();
$newAppButton.trigger( 'click' );
}
} );
/**
* Handles an error response from the AJAX call.
*
* @param {jqXHR} xhr The XHR object from the ajax call.
* @param {string} textStatus The string categorizing the ajax request's status.
* @param {string} errorThrown The HTTP status error text.
*/
function handleErrorResponse( xhr, textStatus, errorThrown ) {
var errorMessage = errorThrown;
if ( xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message ) {
errorMessage = xhr.responseJSON.data.message;
}
addNotice( errorMessage, 'error' );
}
/**
* Displays a notice message in the Connected Applications section.
*
* @param {string} message The message to display.
* @param {string} type The notice type. Either 'success' or 'error'.
* @returns {jQuery} The notice element.
*/
function addNotice( message, type ) {
var $notice = $( '<div></div>' )
.attr( 'role', 'alert' )
.attr( 'tabindex', '-1' )
.addClass( 'is-dismissible notice notice-' + type )
.append( $( '<p></p>' ).text( message ) )
.append(
$( '<button></button>' )
.attr( 'type', 'button' )
.addClass( 'notice-dismiss' )
.append( $( '<span></span>' ).addClass( 'screen-reader-text' ).text( activitypubConnectedApps.dismiss ) )
);
$newAppForm.after( $notice );
return $notice;
}
/**
* Clears notice messages from the Connected Applications section.
*/
function clearNotices() {
$( '.notice', $section ).remove();
}
}( jQuery ) );

View File

@ -0,0 +1,129 @@
/**
* ActivityPub Following List Table Polling.
*
* Adds polling functionality to the Following list table to check for status updates
* of pending follow requests without requiring manual page refresh.
*
* @package Activitypub
*/
( function ( $ ) {
'use strict';
/**
* Following List Table Polling.
*/
var ActivityPubFollowing = {
/**
* Initialize the polling functionality.
*/
init: function () {
this.setupHeartbeatListeners();
// Check every 5 seconds. It'll automatically slow down after 2 mins 30 secs.
window.wp.heartbeat.interval( 'fast' );
},
/**
* Set up WordPress Heartbeat API listeners.
*/
setupHeartbeatListeners: function () {
// Add our data to the Heartbeat API request.
$( document ).on( 'heartbeat-send.activitypub_following', function ( e, data ) {
data.activitypub_following_check = {
user_id: ActivityPubFollowingSettings.user_id,
pending_ids: ActivityPubFollowing.getPendingIds(),
};
} );
// Process the Heartbeat API response.
$( document ).on( 'heartbeat-tick.activitypub_following', function ( e, data ) {
if ( data.activitypub_following ) {
ActivityPubFollowing.processUpdates( data.activitypub_following );
}
} );
},
/**
* Get IDs of all pending follow requests currently displayed in the table.
*
* @return {Array} Array of pending follow request IDs.
*/
getPendingIds: function () {
var pendingIds = [];
// Find all rows with pending status.
$( '.wp-list-table tr.status-pending' ).each( function () {
var id = $( this ).attr( 'id' );
if ( id ) {
// Extract the numeric ID from the row ID (e.g., "following-123" -> "123").
pendingIds.push( id.replace( /^following-(\d+)$/, '$1' ) );
}
} );
return pendingIds;
},
/**
* Process updates received from the server.
*
* @param {Object} response Response data from the server.
*/
processUpdates: function ( response ) {
if ( response.counts ) {
// Update the counts in the views navigation.
if ( Object.hasOwn( response.counts, 'all' ) ) {
$( '.subsubsub .all .count' ).text( '(' + response.counts.all + ')' );
}
if ( Object.hasOwn( response.counts, 'accepted' ) ) {
$( '.subsubsub .accepted .count' ).text( '(' + response.counts.accepted + ')' );
}
if ( Object.hasOwn( response.counts, 'pending' ) ) {
$( '.subsubsub .pending .count' ).text( '(' + response.counts.pending + ')' );
// Remove heartbeat listeners when there are no more pending follows.
if ( 0 === response.counts.pending ) {
$( document ).off( 'heartbeat-send.activitypub_following' );
$( document ).off( 'heartbeat-tick.activitypub_following' );
window.wp.heartbeat.interval( 60 );
}
}
}
if ( ! response.updated_items || ! response.updated_items.length ) {
return;
}
// Remove any existing notices.
$( 'div.notice' ).remove();
var $listTable = $( '#the-list' );
// Process each updated item.
$.each( response.updated_items, function ( index, item ) {
var $row = $( '#following-' + item.id );
if ( $row.length && item.status === 'accepted' ) {
// Remove the row when we're in the "Pending" view.
if ( 'pending' === new URLSearchParams( window.location.search ).get( 'status' ) ) {
$row.remove();
} else {
$row.find( 'strong.pending' ).remove();
}
if ( 0 === $listTable.children().length ) {
$listTable.append(
'<tr class="no-items"><td class="colspanchange" colspan="5">' + response.no_items + '</td></tr>'
);
}
}
} );
},
};
// Initialize on document ready.
$( document ).ready( function () {
ActivityPubFollowing.init();
} );
} )( jQuery );

View File

@ -0,0 +1,440 @@
/**
* ActivityPub Moderation Admin JavaScript
*/
/* global activitypubModerationL10n, jQuery */
/**
* @param {Object} $ - jQuery
* @param {Object} wp - WordPress global object
* @param {Object} wp.i18n - Internationalization functions
* @param {Object} wp.a11y - Accessibility functions
* @param {Object} wp.ajax - AJAX functions
*/
(function( $, wp ) {
'use strict';
var __ = wp.i18n.__;
var _n = wp.i18n._n;
var sprintf = wp.i18n.sprintf;
/**
* Helper function to show a message using wp.a11y and alert
*
* @param {string} message - The message to display
*/
function showMessage( message ) {
if ( wp.a11y && wp.a11y.speak ) {
wp.a11y.speak( message, 'assertive' );
}
alert( message );
}
/**
* Helper function to validate domain format
*
* @param {string} domain - The domain to validate
* @return {boolean} Whether the domain is valid
*/
function isValidDomain( domain ) {
// Basic domain validation - must contain at least one dot and valid characters
var domainRegex = /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
return domainRegex.test( domain ) && domain.includes( '.' ) && domain.length > 3;
}
/**
* Helper function to check if a term already exists in the UI
*
* @param {string} type - The type of block (domain or keyword)
* @param {string} value - The value to check
* @param {string} context - The context (user or site)
* @param {number|null} userId - The user ID (for user context)
* @return {boolean} Whether the term is already blocked
*/
function isTermAlreadyBlocked( type, value, context, userId ) {
var selector;
if ( context === 'user' ) {
selector = '.activitypub-user-block-list[data-user-id="' + userId + '"] .remove-user-block-btn[data-type="' + type + '"][data-value="' + value + '"]';
} else if ( context === 'site' ) {
selector = '.remove-site-block-btn[data-type="' + type + '"][data-value="' + value + '"]';
}
return $( selector ).length > 0;
}
/**
* Validate a blocked term value
*
* @param {string} type - The type of block (domain or keyword)
* @param {string} value - The value to validate
* @param {string} context - The context (user or site)
* @param {number|null} userId - The user ID (for user context)
* @return {boolean} Whether the value is valid
*/
function validateBlockedTerm( type, value, context, userId ) {
if ( ! value ) {
showMessage( __( 'Please enter a value to block.', 'activitypub' ) );
return false;
}
if ( type === 'domain' && ! isValidDomain( value ) ) {
showMessage( __( 'Please enter a valid domain (e.g., example.com).', 'activitypub' ) );
return false;
}
if ( isTermAlreadyBlocked( type, value, context, userId ) ) {
showMessage( __( 'This term is already blocked.', 'activitypub' ) );
return false;
}
return true;
}
/**
* Create a table row for a blocked term.
*
* @param {string} type - The type of block (domain or keyword)
* @param {string} value - The blocked value
* @param {string} context - The context (user or site)
* @return {jQuery} The constructed table row
*/
function createBlockedTermRow( type, value, context ) {
var $button = $( '<button>', {
type: 'button',
'class': 'button button-small remove-' + context + '-block-btn',
'data-type': type,
'data-value': value,
text: __( 'Remove', 'activitypub' )
} );
return $( '<tr>' ).append( $( '<td>' ).text( value ), $( '<td>' ).append( $button ) );
}
/**
* Helper function to add a blocked term to the UI
*/
function addBlockedTermToUI( type, value, context, userId ) {
var table;
if ( context === 'user' ) {
// For user moderation, add to the appropriate table
var container = $( '.activitypub-user-block-list[data-user-id="' + userId + '"]' );
table = container.find( '.activitypub-blocked-' + type );
if ( table.length === 0 ) {
table = $( '<table class="widefat striped activitypub-blocked-' + type + '" role="presentation" style="max-width: 500px; margin: 15px 0;"><tbody></tbody></table>' );
container.find( '#new_user_' + type ).closest( '.add-user-block-form' ).before( table );
}
table.find( 'tbody' ).append( createBlockedTermRow( type, value, context ) );
} else if ( context === 'site' ) {
// For site moderation, add to the table inside the details element
var details = $( '.activitypub-site-block-details[data-type="' + type + '"]' );
table = details.find( '.activitypub-site-blocked-' + type );
if ( table.length === 0 ) {
// Create table inside the details element (after summary)
table = $( '<table class="widefat striped activitypub-site-blocked-' + type + '" role="presentation"><tbody></tbody></table>' );
details.find( 'summary' ).after( table );
}
table.find( 'tbody' ).append( createBlockedTermRow( type, value, context ) );
updateSiteBlockSummary( type );
}
}
/**
* Helper function to update the site block summary count
*/
function updateSiteBlockSummary( type ) {
var details = $( '.activitypub-site-block-details[data-type="' + type + '"]' );
var table = details.find( '.activitypub-site-blocked-' + type );
var count = table.find( 'tbody tr' ).length || table.find( 'tr' ).length;
var summary = details.find( 'summary' );
if ( count === 0 ) {
// Empty state
var emptyText = type === 'domain'
? __( 'No blocked domains', 'activitypub' )
: __( 'No blocked keywords', 'activitypub' );
summary.text( emptyText );
details.attr( 'open', '' );
table.remove();
} else {
// Has items - use _n for proper pluralization
var text = type === 'domain'
? _n( '%s blocked domain', '%s blocked domains', count, 'activitypub' )
: _n( '%s blocked keyword', '%s blocked keywords', count, 'activitypub' );
summary.text( sprintf( text, count ) );
}
}
/**
* Helper function to remove a blocked term from the UI
*/
function removeBlockedTermFromUI( type, value, context ) {
// Find and remove the specific blocked term element
var selector = '.remove-' + context + '-block-btn[data-type="' + type + '"][data-value="' + value + '"]';
var button = $( selector );
if ( button.length > 0 ) {
// Remove the parent table row
button.closest( 'tr' ).remove();
// Update the summary count for site blocks
if ( context === 'site' ) {
updateSiteBlockSummary( type );
}
}
}
/**
* Initialize moderation functionality
*/
function init() {
// User moderation management.
initUserModeration();
// Site moderation management.
initSiteModeration();
// Blocklist subscriptions management.
initBlocklistSubscriptions();
}
/**
* Initialize user moderation management
*/
function initUserModeration() {
// Function to add user blocked term.
function addUserBlockedTerm( type, userId ) {
var input = $( '#new_user_' + type );
var value = input.val().trim();
if ( ! validateBlockedTerm( type, value, 'user', userId ) ) {
return;
}
wp.ajax.post( 'activitypub_moderation_settings', {
context: 'user',
operation: 'add',
user_id: userId,
type: type,
value: value,
_wpnonce: activitypubModerationL10n.nonce
}).done( function() {
// Clear input and add item to the UI.
input.val( '' );
addBlockedTermToUI( type, value, 'user', userId );
}).fail( function( response ) {
var message = response && response.message ? response.message : __( 'Failed to add block.', 'activitypub' );
showMessage( message );
});
}
// Function to remove user blocked term.
function removeUserBlockedTerm( type, value, userId ) {
wp.ajax.post( 'activitypub_moderation_settings', {
context: 'user',
operation: 'remove',
user_id: userId,
type: type,
value: value,
_wpnonce: activitypubModerationL10n.nonce
}).done( function() {
removeBlockedTermFromUI( type, value, 'user' );
}).fail( function( response ) {
var message = response && response.message ? response.message : __( 'Failed to remove block.', 'activitypub' );
showMessage( message );
});
}
// Add user block functionality (button click).
$( document ).on( 'click', '.add-user-block-btn', function( e ) {
e.preventDefault();
var type = $( this ).data( 'type' );
var userId = $( this ).closest( '.activitypub-user-block-list' ).data( 'user-id' );
addUserBlockedTerm( type, userId );
});
// Add user block functionality (Enter key).
$( document ).on( 'keypress', '#new_user_domain, #new_user_keyword', function( e ) {
if ( e.which === 13 ) { // Enter key.
e.preventDefault();
var inputId = $( this ).attr( 'id' );
var type = inputId.replace( 'new_user_', '' );
var userId = $( this ).closest( '.activitypub-user-block-list' ).data( 'user-id' );
addUserBlockedTerm( type, userId );
}
});
// Remove user block functionality.
$( document ).on( 'click', '.remove-user-block-btn', function( e ) {
e.preventDefault();
var type = $( this ).data( 'type' );
var value = $( this ).data( 'value' );
var userId = $( this ).closest( '.activitypub-user-block-list' ).data( 'user-id' );
removeUserBlockedTerm( type, value, userId );
});
}
/**
* Initialize site moderation management
*/
function initSiteModeration() {
// Function to add site blocked term.
function addSiteBlockedTerm( type ) {
var input = $( '#new_site_' + type );
var value = input.val().trim();
if ( ! validateBlockedTerm( type, value, 'site', null ) ) {
return;
}
wp.ajax.post( 'activitypub_moderation_settings', {
context: 'site',
operation: 'add',
type: type,
value: value,
_wpnonce: activitypubModerationL10n.nonce
}).done( function() {
// Clear input and add item to the UI.
input.val( '' );
addBlockedTermToUI( type, value, 'site' );
}).fail( function( response ) {
var message = response && response.message ? response.message : __( 'Failed to add block.', 'activitypub' );
showMessage( message );
});
}
// Function to remove site blocked term.
function removeSiteBlockedTerm( type, value ) {
wp.ajax.post( 'activitypub_moderation_settings', {
context: 'site',
operation: 'remove',
type: type,
value: value,
_wpnonce: activitypubModerationL10n.nonce
}).done( function() {
removeBlockedTermFromUI( type, value, 'site' );
}).fail( function( response ) {
var message = response && response.message ? response.message : __( 'Failed to remove block.', 'activitypub' );
showMessage( message );
});
}
// Add site block functionality (button click).
$( document ).on( 'click', '.add-site-block-btn', function( e ) {
e.preventDefault();
var type = $( this ).data( 'type' );
addSiteBlockedTerm( type );
});
// Add site block functionality (Enter key).
$( document ).on( 'keypress', '#new_site_domain, #new_site_keyword', function( e ) {
if ( e.which === 13 ) { // Enter key.
e.preventDefault();
var inputId = $( this ).attr( 'id' );
var type = inputId.replace( 'new_site_', '' );
addSiteBlockedTerm( type );
}
});
// Remove site block functionality.
$( document ).on( 'click', '.remove-site-block-btn', function( e ) {
e.preventDefault();
var type = $( this ).data( 'type' );
var value = $( this ).data( 'value' );
removeSiteBlockedTerm( type, value );
});
}
/**
* Initialize blocklist subscriptions management
*/
function initBlocklistSubscriptions() {
// Function to add a blocklist subscription.
function addBlocklistSubscription( url ) {
if ( ! url ) {
var message = activitypubModerationL10n.enterUrl || 'Please enter a URL.';
if ( wp.a11y && wp.a11y.speak ) {
wp.a11y.speak( message, 'assertive' );
}
alert( message );
return;
}
// Disable the button while processing.
var button = $( '.add-blocklist-subscription-btn' );
button.prop( 'disabled', true );
wp.ajax.post( 'activitypub_blocklist_subscription', {
operation: 'add',
url: url,
_wpnonce: activitypubModerationL10n.nonce
}).done( function() {
// Reload the page to show the updated list.
window.location.reload();
}).fail( function( response ) {
var message = response && response.message ? response.message : activitypubModerationL10n.subscriptionFailed || 'Failed to add subscription.';
if ( wp.a11y && wp.a11y.speak ) {
wp.a11y.speak( message, 'assertive' );
}
alert( message );
button.prop( 'disabled', false );
});
}
// Function to remove a blocklist subscription.
function removeBlocklistSubscription( url ) {
wp.ajax.post( 'activitypub_blocklist_subscription', {
operation: 'remove',
url: url,
_wpnonce: activitypubModerationL10n.nonce
}).done( function() {
// Remove the row from the UI.
$( '.remove-blocklist-subscription-btn' ).filter( function() {
return $( this ).data( 'url' ) === url;
}).closest( 'tr' ).remove();
// If no more subscriptions, remove the table.
var table = $( '.activitypub-blocklist-subscriptions table' );
if ( table.find( 'tbody tr' ).length === 0 ) {
table.remove();
}
}).fail( function( response ) {
var message = response && response.message ? response.message : activitypubModerationL10n.removeSubscriptionFailed || 'Failed to remove subscription.';
if ( wp.a11y && wp.a11y.speak ) {
wp.a11y.speak( message, 'assertive' );
}
alert( message );
});
}
// Add subscription functionality (button click).
$( document ).on( 'click', '.add-blocklist-subscription-btn', function( e ) {
e.preventDefault();
var url = $( this ).data( 'url' ) || $( '#new_blocklist_subscription_url' ).val().trim();
addBlocklistSubscription( url );
});
// Add subscription functionality (Enter key).
$( document ).on( 'keypress', '#new_blocklist_subscription_url', function( e ) {
if ( e.which === 13 ) { // Enter key.
e.preventDefault();
var url = $( this ).val().trim();
addBlocklistSubscription( url );
}
});
// Remove subscription functionality.
$( document ).on( 'click', '.remove-blocklist-subscription-btn', function( e ) {
e.preventDefault();
var url = $( this ).data( 'url' );
removeBlocklistSubscription( url );
});
}
// Initialize when document is ready.
$( document ).ready( init );
})( jQuery, wp );