admin_url( 'admin-ajax.php' ),
'project' => 'site',
'src' => add_query_arg( 'ver', FINISHCOAT_VERSION, FINISHCOAT_URL . 'assets/finishcoat.js' ),
'lazy' => 'lazy' === $mode,
'site' => finishcoat_site_name(),
'label' => finishcoat_tab_label(),
'theme' => finishcoat_theme(),
'credit' => (bool) finishcoat_setting( 'credit' ),
'ver' => FINISHCOAT_VERSION,
// In link mode most visitors never load the page script, so its words come with its first request instead.
'i18n' => 'lazy' === $mode ? null : finishcoat_front_strings(),
);
}
/**
* The site name as plain text.
*
* @return string
*/
function finishcoat_site_name() {
return wp_specialchars_decode( (string) get_bloginfo( 'name' ), ENT_QUOTES );
}
/**
* Add the loader (and, unless it is left to the loader, the page script).
*
* @param bool $forced The [finishcoat] shortcode asked for it.
*/
function finishcoat_enqueue_front( $forced = false ) {
static $done = false;
if ( $done || ! finishcoat_loads_here( $forced ) ) {
return;
}
$done = true;
$mode = finishcoat_front_mode();
$boot = (string) file_get_contents( plugin_dir_path( FINISHCOAT_FILE ) . 'assets/finishcoat-boot.js' );
wp_register_script( 'finishcoat-boot', false, array(), FINISHCOAT_VERSION, array( 'in_footer' => true ) );
wp_enqueue_script( 'finishcoat-boot' );
wp_add_inline_script( 'finishcoat-boot', 'window.FinishcoatConfig = ' . wp_json_encode( finishcoat_front_config( $mode ) ) . ";\n" . $boot );
wp_register_script(
'finishcoat',
FINISHCOAT_URL . 'assets/finishcoat.js',
array( 'finishcoat-boot' ),
FINISHCOAT_VERSION,
array(
'in_footer' => true,
'strategy' => 'defer',
)
);
if ( 'now' === $mode ) {
wp_enqueue_script( 'finishcoat' );
}
do_action( 'finishcoat_front_scripts', $mode );
}
/**
* On a review link (?finishcoat=CODE), take the code out of the address bar first thing in
, before analytics
* or any other script on the page can read the address. This runs whatever the Show setting is, so the code also
* leaves the address on pages where the tab does not load. The script reads the address itself; the code is never
* printed into the page.
*/
function finishcoat_strip_review_code() {
if ( ! isset( $_GET['finishcoat'] ) || finishcoat_is_editor_view() ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- only checks whether the parameter is there; the value is not read here.
return;
}
$js = (string) file_get_contents( plugin_dir_path( FINISHCOAT_FILE ) . 'assets/finishcoat-strip.js' );
wp_print_inline_script_tag( $js, array( 'id' => 'finishcoat-strip-js' ) );
}
add_action( 'wp_head', 'finishcoat_strip_review_code', 1 );
/**
* Front-end hook.
*/
function finishcoat_front_scripts() {
finishcoat_enqueue_front( false );
}
add_action( 'wp_enqueue_scripts', 'finishcoat_front_scripts' );
/**
* [finishcoat] loads the tab on this page, even on a skipped page. [finishcoat board="yes"] also shows the board
* of every note in its place. Who sees the tab still follows the Show setting, and the board needs a review code.
*
* @param array|string $atts Shortcode attributes.
* @return string
*/
function finishcoat_shortcode( $atts ) {
$a = shortcode_atts( array( 'board' => 'no' ), $atts, 'finishcoat' );
finishcoat_enqueue_front( true );
if ( in_array( strtolower( (string) $a['board'] ), array( 'yes', '1', 'true' ), true ) ) {
return '';
}
return '';
}
add_shortcode( 'finishcoat', 'finishcoat_shortcode' );
/**
* Every string the page script shows, translated. The script looks them up by their English text.
*
* @return array
*/
function finishcoat_front_strings() {
return array(
'just now' => __( 'just now', 'finishcoat' ),
/* translators: %d: number of minutes. */
'%d min ago' => __( '%d min ago', 'finishcoat' ),
/* translators: %d: number of hours. */
'%d hr ago' => __( '%d hr ago', 'finishcoat' ),
'The notes service did not answer. Try again in a minute.' => __( 'The notes service did not answer. Try again in a minute.', 'finishcoat' ),
'No connection. Check your internet and try again.' => __( 'No connection. Check your internet and try again.', 'finishcoat' ),
'That code did not work. Check it and try again.' => __( 'That code did not work. Check it and try again.', 'finishcoat' ),
'Suggestions' => __( 'Suggestions', 'finishcoat' ),
'Continue' => __( 'Continue', 'finishcoat' ),
'Enter your review code' => __( 'Enter your review code', 'finishcoat' ),
'Your web designer sent you this code.' => __( 'Your web designer sent you this code.', 'finishcoat' ),
'Enter your review code.' => __( 'Enter your review code.', 'finishcoat' ),
'Checking...' => __( 'Checking...', 'finishcoat' ),
'Could not load notes.' => __( 'Could not load notes.', 'finishcoat' ),
/* translators: %s: label of the tab, such as Suggestions. */
'Close %s' => __( 'Close %s', 'finishcoat' ),
'New' => __( 'New', 'finishcoat' ),
'Noted' => __( 'Noted', 'finishcoat' ),
'In progress' => __( 'In progress', 'finishcoat' ),
'Done' => __( 'Done', 'finishcoat' ),
'Show' => __( 'Show', 'finishcoat' ),
'What would you change, keep or ask about on this page?' => __( 'What would you change, keep or ask about on this page?', 'finishcoat' ),
'Your name' => __( 'Your name', 'finishcoat' ),
'Pin it to a spot' => __( 'Pin it to a spot', 'finishcoat' ),
'Send' => __( 'Send', 'finishcoat' ),
'New notes are paused right now.' => __( 'New notes are paused right now.', 'finishcoat' ),
'Add photos' => __( 'Add photos', 'finishcoat' ),
'Try my photo here' => __( 'Try my photo here', 'finishcoat' ),
'Photos to send' => __( 'Photos to send', 'finishcoat' ),
'I own these photos or have permission to use them.' => __( 'I own these photos or have permission to use them.', 'finishcoat' ),
'Leave a suggestion' => __( 'Leave a suggestion', 'finishcoat' ),
'Want a different photo? Point at any photo on the page and click Try my photo here. Only you see it until you suggest it.' => __( 'Want a different photo? Point at any photo on the page and click Try my photo here. Only you see it until you suggest it.', 'finishcoat' ),
'Want a different photo? Tap Try my photo here, then tap a photo on the page. Only you see it until you suggest it.' => __( 'Want a different photo? Tap Try my photo here, then tap a photo on the page. Only you see it until you suggest it.', 'finishcoat' ),
'Forget this code' => __( 'Forget this code', 'finishcoat' ),
'Made with Finishcoat' => __( 'Made with Finishcoat', 'finishcoat' ),
/* translators: %s: site name. */
'Notes on this page go straight to %s.' => __( 'Notes on this page go straight to %s.', 'finishcoat' ),
'Notes on this page go straight to the site owner.' => __( 'Notes on this page go straight to the site owner.', 'finishcoat' ),
'Open' => __( 'Open', 'finishcoat' ),
'All' => __( 'All', 'finishcoat' ),
'Open full size' => __( 'Open full size', 'finishcoat' ),
/* translators: %s: name of the person who sent the photo. */
'Photo from %s, open full size' => __( 'Photo from %s, open full size', 'finishcoat' ),
'the client' => __( 'the client', 'finishcoat' ),
'The photo on the page now' => __( 'The photo on the page now', 'finishcoat' ),
'Before' => __( 'Before', 'finishcoat' ),
'After' => __( 'After', 'finishcoat' ),
/* translators: %s: name of the spot on the page, such as a heading. */
'Suggested for “%s”' => __( 'Suggested for “%s”', 'finishcoat' ),
'a photo' => __( 'a photo', 'finishcoat' ),
'Show the spot on the page' => __( 'Show the spot on the page', 'finishcoat' ),
/* translators: %d: note number on this page. */
'Note %d, show the spot on the page' => __( 'Note %d, show the spot on the page', 'finishcoat' ),
'Someone' => __( 'Someone', 'finishcoat' ),
'On' => __( 'On', 'finishcoat' ),
/* translators: %s: name of the spot on the page, such as a heading. */
'Pinned to “%s”' => __( 'Pinned to “%s”', 'finishcoat' ),
'Open on the page' => __( 'Open on the page', 'finishcoat' ),
'Reply' => __( 'Reply', 'finishcoat' ),
'Status' => __( 'Status', 'finishcoat' ),
'Delete' => __( 'Delete', 'finishcoat' ),
'Delete for good?' => __( 'Delete for good?', 'finishcoat' ),
'That did not work.' => __( 'That did not work.', 'finishcoat' ),
'Loading notes...' => __( 'Loading notes...', 'finishcoat' ),
'No notes on this page.' => __( 'No notes on this page.', 'finishcoat' ),
'No notes on this page yet. Write one below. Use Pin it to a spot if it is about one part of the page.' => __( 'No notes on this page yet. Write one below. Use Pin it to a spot if it is about one part of the page.', 'finishcoat' ),
'Everything on this page is marked done.' => __( 'Everything on this page is marked done.', 'finishcoat' ),
'Nothing here yet.' => __( 'Nothing here yet.', 'finishcoat' ),
/* translators: 1: label of the tab, 2: number of open notes. */
'%1$s, %2$d open on this page' => __( '%1$s, %2$d open on this page', 'finishcoat' ),
/* translators: 1: note number, 2: name of the person. */
'Note %1$d from %2$s' => __( 'Note %1$d from %2$s', 'finishcoat' ),
/* translators: %s: name of the person. */
'Replying to %s' => __( 'Replying to %s', 'finishcoat' ),
/* translators: %d: note number. */
'note %d' => __( 'note %d', 'finishcoat' ),
'Cancel' => __( 'Cancel', 'finishcoat' ),
'Write a reply' => __( 'Write a reply', 'finishcoat' ),
'this spot' => __( 'this spot', 'finishcoat' ),
'Click or tap a photo on the page to try your own photo there.' => __( 'Click or tap a photo on the page to try your own photo there.', 'finishcoat' ),
'Click the spot your note is about.' => __( 'Click the spot your note is about.', 'finishcoat' ),
'That spot has no photo. Click or tap a photo.' => __( 'That spot has no photo. Click or tap a photo.', 'finishcoat' ),
'Your new note goes here' => __( 'Your new note goes here', 'finishcoat' ),
/* translators: %s: name of the photo on the page. */
'Pinned to the photo “%s”' => __( 'Pinned to the photo “%s”', 'finishcoat' ),
'Do not suggest it' => __( 'Do not suggest it', 'finishcoat' ),
'Remove pin' => __( 'Remove pin', 'finishcoat' ),
'Move the pin' => __( 'Move the pin', 'finishcoat' ),
/* translators: %s: file name. */
'Only photos (JPEG, PNG, WebP) can be sent. %s was left out.' => __( 'Only photos (JPEG, PNG, WebP) can be sent. %s was left out.', 'finishcoat' ),
/* translators: 1: file name, 2: largest photo in MB. */
'%1$s is too big to send. The limit is %2$d MB a photo.' => __( '%1$s is too big to send. The limit is %2$d MB a photo.', 'finishcoat' ),
/* translators: %s: file name. */
'%s is empty. Try another photo.' => __( '%s is empty. Try another photo.', 'finishcoat' ),
/* translators: %d: most photos on one note. */
'You can send up to %d photos with a note.' => __( 'You can send up to %d photos with a note.', 'finishcoat' ),
/* translators: %s: name of the photo on the page. */
'Your photo for “%s”. Only you see it on the page. Send to suggest it.' => __( 'Your photo for “%s”. Only you see it on the page. Send to suggest it.', 'finishcoat' ),
'1 photo to send' => __( '1 photo to send', 'finishcoat' ),
/* translators: %d: number of photos. */
'%d photos to send' => __( '%d photos to send', 'finishcoat' ),
/* translators: %s: file name. */
'Remove %s' => __( 'Remove %s', 'finishcoat' ),
'Sending...' => __( 'Sending...', 'finishcoat' ),
'Write a note first.' => __( 'Write a note first.', 'finishcoat' ),
'Add your name so we know who it is from.' => __( 'Add your name so we know who it is from.', 'finishcoat' ),
'Tick the box to confirm you can share these photos.' => __( 'Tick the box to confirm you can share these photos.', 'finishcoat' ),
'Uploading...' => __( 'Uploading...', 'finishcoat' ),
'Saving...' => __( 'Saving...', 'finishcoat' ),
/* translators: %d: percent uploaded. %% is a percent sign. */
'Uploading... %d%%' => __( 'Uploading... %d%%', 'finishcoat' ),
'Those photos are too big to send at once. Try fewer.' => __( 'Those photos are too big to send at once. Try fewer.', 'finishcoat' ),
'Reply sent.' => __( 'Reply sent.', 'finishcoat' ),
'Thanks. Your photo suggestion is in, pinned to that spot.' => __( 'Thanks. Your photo suggestion is in, pinned to that spot.', 'finishcoat' ),
'Thanks. Your note is in and the site owner has been told.' => __( 'Thanks. Your note is in and the site owner has been told.', 'finishcoat' ),
'Background photo' => __( 'Background photo', 'finishcoat' ),
/* translators: %d: number of the photo on the page. */
'Photo %d' => __( 'Photo %d', 'finishcoat' ),
'Your photo on the page' => __( 'Your photo on the page', 'finishcoat' ),
'Only you can see this photo here. Nothing is sent until you suggest it.' => __( 'Only you can see this photo here. Nothing is sent until you suggest it.', 'finishcoat' ),
'Suggest this photo' => __( 'Suggest this photo', 'finishcoat' ),
'Try another' => __( 'Try another', 'finishcoat' ),
'Put the original back' => __( 'Put the original back', 'finishcoat' ),
'Add a note about this photo (optional)' => __( 'Add a note about this photo (optional)', 'finishcoat' ),
'Page' => __( 'Page', 'finishcoat' ),
/* translators: %s: label of the tab, such as Suggestions. */
'%s board' => __( '%s board', 'finishcoat' ),
/* translators: %s: label of the tab, such as Suggestions. */
'Every note left on this site, in one place. Use the %s tab on the right edge of any page to add one.' => __( 'Every note left on this site, in one place. Use the %s tab on the right edge of any page to add one.', 'finishcoat' ),
'All pages' => __( 'All pages', 'finishcoat' ),
'Everything' => __( 'Everything', 'finishcoat' ),
'Photos' => __( 'Photos', 'finishcoat' ),
'No suggestions yet.' => __( 'No suggestions yet.', 'finishcoat' ),
'Nothing matches those filters.' => __( 'Nothing matches those filters.', 'finishcoat' ),
/* translators: %d: number of notes. */
'Show %d more' => __( 'Show %d more', 'finishcoat' ),
/* translators: %s: name of the logged-in user. */
'Studio mode: replying as %s' => __( 'Studio mode: replying as %s', 'finishcoat' ),
'the site owner' => __( 'the site owner', 'finishcoat' ),
'Notes or photos? Leave them here.' => __( 'Notes or photos? Leave them here.', 'finishcoat' ),
);
}