Add optional age confirmation modal
This commit is contained in:
parent
812de7aed7
commit
73c366ee0d
@ -1140,6 +1140,8 @@ define( 'CONSTANT_NAME', value );
|
||||
| FICTIONEER_FA_CDN | string | Font Awesome CDN URL.
|
||||
| FICTIONEER_FA_INTEGRITY | string | Font Awesome integrity SHA384 hash.
|
||||
| FICTIONEER_DISCORD_EMBED_COLOR | string | Color code for Discord notifications. Default `'9692513'`.
|
||||
| FICTIONEER_TRUNCATION_ELLIPSIS | string | Appended to truncated strings. Default `…`.
|
||||
| FICTIONEER_AGE_CONFIRMATION_REDIRECT | string | Redirect URL if a visitor reject the age confirmation. Default `https://search.brave.com/`.
|
||||
| FICTIONEER_COMMENTCODE_TTL | integer | How long guests can see their private/unapproved comments in _seconds_. Default `600`.
|
||||
| FICTIONEER_AJAX_TTL | integer | How long to cache certain AJAX requests locally in _milliseconds_. Default `60000`.
|
||||
| FICTIONEER_AJAX_LOGIN_TTL | integer | How long to cache AJAX authentications locally in _milliseconds_. Default `15000`.
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -185,6 +185,11 @@ if ( ! defined( 'FICTIONEER_TRUNCATION_ELLIPSIS' ) ) {
|
||||
define( 'FICTIONEER_TRUNCATION_ELLIPSIS', '…' );
|
||||
}
|
||||
|
||||
// String: Age confirmation redirect
|
||||
if ( ! defined( 'FICTIONEER_AGE_CONFIRMATION_REDIRECT' ) ) {
|
||||
define( 'FICTIONEER_AGE_CONFIRMATION_REDIRECT', 'https://search.brave.com/' );
|
||||
}
|
||||
|
||||
/*
|
||||
* Integers
|
||||
*/
|
||||
|
@ -188,6 +188,20 @@ function fictioneer_output_modals( $args ) {
|
||||
get_template_part( 'partials/_modal-chapter-changelog' );
|
||||
}
|
||||
|
||||
// Age confirmation modal
|
||||
if (
|
||||
get_option( 'fictioneer_enable_site_age_confirmation' ) ||
|
||||
(
|
||||
! $is_archive &&
|
||||
get_option( 'fictioneer_enable_post_age_confirmation' ) &&
|
||||
in_array( $args['post_type'], ['fcn_story', 'fcn_chapter'] )
|
||||
)
|
||||
) {
|
||||
if ( ! current_user_can( 'edit_fcn_stories' ) ) {
|
||||
get_template_part( 'partials/_modal-age', null, $args );
|
||||
}
|
||||
}
|
||||
|
||||
// Action to add modals
|
||||
do_action( 'fictioneer_modals' );
|
||||
}
|
||||
|
@ -649,6 +649,20 @@ define( 'FICTIONEER_OPTIONS', array(
|
||||
'sanitize_callback' => 'fictioneer_sanitize_checkbox',
|
||||
'label' => __( 'Disable Font Awesome integration', 'fictioneer' ),
|
||||
'default' => 0
|
||||
),
|
||||
'fictioneer_enable_site_age_confirmation' => array(
|
||||
'name' => 'fictioneer_enable_site_age_confirmation',
|
||||
'group' => 'fictioneer-settings-general-group',
|
||||
'sanitize_callback' => 'fictioneer_sanitize_checkbox',
|
||||
'label' => __( 'Enable age confirmation modal for site', 'fictioneer' ),
|
||||
'default' => 0
|
||||
),
|
||||
'fictioneer_enable_post_age_confirmation' => array(
|
||||
'name' => 'fictioneer_enable_post_age_confirmation',
|
||||
'group' => 'fictioneer-settings-general-group',
|
||||
'sanitize_callback' => 'fictioneer_sanitize_checkbox',
|
||||
'label' => __( 'Enable age confirmation modal for posts', 'fictioneer' ),
|
||||
'default' => 0
|
||||
)
|
||||
),
|
||||
'integers' => array(
|
||||
@ -936,6 +950,22 @@ define( 'FICTIONEER_OPTIONS', array(
|
||||
'label' => __( 'Comma-separated list of allowed <a href="%s" target="_blank" rel="noreferrer">mime types</a> for user roles with the "Upload Restriction". Must be among the allowed mime type and file extensions of WordPress.', 'fictioneer' ),
|
||||
'default' => FICTIONEER_DEFAULT_UPLOAD_MIME_TYPE_RESTRICTIONS,
|
||||
'placeholder' => FICTIONEER_DEFAULT_UPLOAD_MIME_TYPE_RESTRICTIONS
|
||||
),
|
||||
'fictioneer_phrase_site_age_confirmation' => array(
|
||||
'name' => 'fictioneer_phrase_site_age_confirmation',
|
||||
'group' => 'fictioneer-settings-phrases-group',
|
||||
'sanitize_callback' => 'wp_kses_post',
|
||||
'label' => __( 'Age confirmation modal content for the site.', 'fictioneer' ),
|
||||
'default' => __( 'This website is intended for an adult audience. Please confirm that you are of legal age (18+) or leave the website.', 'fictioneer' ),
|
||||
'placeholder' => __( 'This website is intended for an adult audience. Please confirm that you are of legal age (18+) or leave the website.', 'fictioneer' )
|
||||
),
|
||||
'fictioneer_phrase_post_age_confirmation' => array(
|
||||
'name' => 'fictioneer_phrase_post_age_confirmation',
|
||||
'group' => 'fictioneer-settings-phrases-group',
|
||||
'sanitize_callback' => 'wp_kses_post',
|
||||
'label' => __( 'Age confirmation modal content for posts.', 'fictioneer' ),
|
||||
'default' => __( 'This content is intended for an adult audience. Please confirm that you are of legal age (18+) or leave the website.', 'fictioneer' ),
|
||||
'placeholder' => __( 'This content is intended for an adult audience. Please confirm that you are of legal age (18+) or leave the website.', 'fictioneer' )
|
||||
)
|
||||
)
|
||||
));
|
||||
|
@ -80,6 +80,15 @@
|
||||
?>
|
||||
</div>
|
||||
|
||||
<div class="fictioneer-card__row">
|
||||
<?php
|
||||
fictioneer_settings_label_checkbox(
|
||||
'fictioneer_enable_site_age_confirmation',
|
||||
__( 'Require age confirmation for the whole site.', 'fictioneer' )
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
|
||||
<div class="fictioneer-card__row">
|
||||
<?php
|
||||
fictioneer_settings_label_checkbox(
|
||||
@ -141,6 +150,15 @@
|
||||
<p><?php _e( 'Updating these settings may require the theme caches to be purged. You can do that under Tools.', 'fictioneer' ); ?></p>
|
||||
</div>
|
||||
|
||||
<div class="fictioneer-card__row">
|
||||
<?php
|
||||
fictioneer_settings_label_checkbox(
|
||||
'fictioneer_enable_post_age_confirmation',
|
||||
__( 'Require age confirmation for <b>adult-rated</b> content.', 'fictioneer' )
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
|
||||
<div class="fictioneer-card__row">
|
||||
<?php
|
||||
fictioneer_settings_label_checkbox(
|
||||
|
@ -107,6 +107,50 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="fictioneer-card">
|
||||
<div class="fictioneer-card__wrapper">
|
||||
<h3 class="fictioneer-card__header"><?php _e( 'Age Confirmation Modal: Site', 'fictioneer' ); ?></h3>
|
||||
<div class="fictioneer-card__content">
|
||||
|
||||
<?php
|
||||
$default = esc_html( __( 'This website is intended for an adult audience. Please confirm that you are of legal age (18+) or leave the website.', 'fictioneer' ) );
|
||||
?>
|
||||
|
||||
<div class="fictioneer-card__row">
|
||||
<textarea class="fictioneer-textarea" name="fictioneer_phrase_site_age_confirmation" rows="4" placeholder="<?php echo $default; ?>"><?php echo esc_attr( get_option( 'fictioneer_phrase_site_age_confirmation' ) ); ?></textarea>
|
||||
<p class="fictioneer-sub-label"><?php _e( 'HTML allowed.', 'fictioneer' ); ?></p>
|
||||
</div>
|
||||
|
||||
<div class="fictioneer-card__row">
|
||||
<code><?php echo $default; ?></code>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="fictioneer-card">
|
||||
<div class="fictioneer-card__wrapper">
|
||||
<h3 class="fictioneer-card__header"><?php _e( 'Age Confirmation Modal: Posts', 'fictioneer' ); ?></h3>
|
||||
<div class="fictioneer-card__content">
|
||||
|
||||
<?php
|
||||
$default = esc_html( __( 'This content is intended for an adult audience. Please confirm that you are of legal age (18+) or leave the website.', 'fictioneer' ) );
|
||||
?>
|
||||
|
||||
<div class="fictioneer-card__row">
|
||||
<textarea class="fictioneer-textarea" name="fictioneer_phrase_post_age_confirmation" rows="4" placeholder="<?php echo $default; ?>"><?php echo esc_attr( get_option( 'fictioneer_phrase_post_age_confirmation' ) ); ?></textarea>
|
||||
<p class="fictioneer-sub-label"><?php _e( 'HTML allowed.', 'fictioneer' ); ?></p>
|
||||
</div>
|
||||
|
||||
<div class="fictioneer-card__row">
|
||||
<code><?php echo $default; ?></code>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php do_action( 'fictioneer_admin_settings_phrases' ); ?>
|
||||
|
||||
</div>
|
||||
|
2
js/laws.min.js
vendored
2
js/laws.min.js
vendored
@ -1 +1 @@
|
||||
const fcn_hasConsent=fcn_getCookie("fcn_cookie_consent")??"",fcn_consentBanner=_$$$("consent-banner");function fcn_loadConsentBanner(){fcn_consentBanner.classList.remove("hidden"),_$$$("consent-accept-button")?.addEventListener("click",(()=>{fcn_setCookie("fcn_cookie_consent","full"),fcn_consentBanner.classList.add("hidden")})),_$$$("consent-reject-button")?.addEventListener("click",(()=>{fcn_setCookie("fcn_cookie_consent","necessary"),fcn_consentBanner.classList.add("hidden")}))}fcn_consentBanner&&""===fcn_hasConsent?setTimeout((()=>{fcn_loadConsentBanner()}),2e3):fcn_consentBanner.remove();
|
||||
const fcn_hasConsent=fcn_getCookie("fcn_cookie_consent")??"",fcn_consentBanner=_$$$("consent-banner");function fcn_loadConsentBanner(){fcn_consentBanner.classList.remove("hidden"),_$$$("consent-accept-button")?.addEventListener("click",(()=>{fcn_setCookie("fcn_cookie_consent","full"),fcn_consentBanner.classList.add("hidden")})),_$$$("consent-reject-button")?.addEventListener("click",(()=>{fcn_setCookie("fcn_cookie_consent","necessary"),fcn_consentBanner.classList.add("hidden")}))}function fcn_showAgeConfirmationModal(){const n=_$(".story__article, .chapter__article")?.dataset.ageRating;if(n&&"adult"!==n)return void _$$$("age-confirmation-modal")?.remove();const e=_$$$("age-confirmation-leave");fcn_theRoot.classList.add("age-modal-open"),_$$$("age-confirmation-modal").classList.add("_open"),_$$$("age-confirmation-confirm")?.addEventListener("click",(n=>{fcn_theRoot.classList.remove("age-modal-open"),n.currentTarget.closest(".modal").remove(),localStorage.setItem("fcnAgeConfirmation","1")})),e?.addEventListener("click",(()=>{window.location.href=e.dataset.redirect??"https://search.brave.com/",localStorage.removeItem("fcnAgeConfirmation")}))}fcn_consentBanner&&""===fcn_hasConsent?setTimeout((()=>{fcn_loadConsentBanner()}),2e3):fcn_consentBanner.remove(),_$$$("age-confirmation-modal")&&"1"!==localStorage.getItem("fcnAgeConfirmation")?setTimeout((()=>{fcn_showAgeConfirmationModal()}),2e3):_$$$("age-confirmation-modal")?.remove();
|
47
partials/_modal-age.php
Normal file
47
partials/_modal-age.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/**
|
||||
* Partial: Age Confirmation Modal
|
||||
*
|
||||
* @package WordPress
|
||||
* @subpackage Fictioneer
|
||||
* @since 5.9.0
|
||||
*
|
||||
* @internal $args['post_id'] The current post ID.
|
||||
* @internal $args['post_type'] The current post type.
|
||||
*/
|
||||
?>
|
||||
|
||||
<?php
|
||||
|
||||
// No direct access!
|
||||
defined( 'ABSPATH' ) OR exit;
|
||||
|
||||
// Setup
|
||||
$site_modal = get_option( 'fictioneer_enable_site_age_confirmation' );
|
||||
|
||||
?>
|
||||
|
||||
<div id="age-confirmation-modal" class="modal age-confirmation">
|
||||
|
||||
<div class="modal__wrapper">
|
||||
|
||||
<h4 class="modal__header"><?php _e( 'Age Confirmation', 'fictioneer' ); ?></h4>
|
||||
|
||||
<?php if ( $site_modal ) : ?>
|
||||
<div class="modal__row modal__description _large"><?php
|
||||
echo get_option( 'fictioneer_phrase_site_age_confirmation' ) ?: __( 'This website is intended for an adult audience. Please confirm that you are of legal age (18+) or leave the website.', 'fictioneer' );
|
||||
?></div>
|
||||
<?php else : ?>
|
||||
<div class="modal__row modal__description _large"><?php
|
||||
echo get_option( 'fictioneer_phrase_post_age_confirmation' ) ?: __( 'This content is intended for an adult audience. Please confirm that you are of legal age (18+) or leave the website.', 'fictioneer' );
|
||||
?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="modal__actions _age-confirmation">
|
||||
<button type="reset" id="age-confirmation-leave" data-redirect="<?php esc_attr_e( FICTIONEER_AGE_CONFIRMATION_REDIRECT ); ?>" class="button"><?php _ex( 'Leave', 'Age confirmation modal button.', 'fictioneer' ); ?></button>
|
||||
<button type="submit" id="age-confirmation-confirm" class="button"><?php _ex( 'Confirm', 'Age confirmation modal button.', 'fictioneer' ); ?></button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
@ -44,6 +44,7 @@ get_header( null, $header_args );
|
||||
$chapter_ids = [];
|
||||
$password_class = ! empty( $post->post_password ) ? 'password' : '';
|
||||
$title = fictioneer_get_safe_title( $post->ID );
|
||||
$age_rating = get_post_meta( $post->ID, 'fictioneer_chapter_rating', true );
|
||||
$this_breadcrumb = [ $title, get_the_permalink() ];
|
||||
|
||||
$story_id = get_post_meta( $post->ID, 'fictioneer_chapter_story', true );
|
||||
@ -58,6 +59,10 @@ get_header( null, $header_args );
|
||||
if ( $story_post ) {
|
||||
$story_data = fictioneer_get_story_data( $story_id, false ); // Does not refresh comment count!
|
||||
$chapter_ids = $story_data['chapter_ids'];
|
||||
|
||||
if ( empty( $age_rating ) ) {
|
||||
$age_rating = $story_data['rating'];
|
||||
}
|
||||
}
|
||||
|
||||
// Chapter navigation
|
||||
@ -120,7 +125,7 @@ get_header( null, $header_args );
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<article id="ch-<?php the_ID(); ?>" data-author-id="<?php echo get_the_author_meta( 'ID' ); ?>" class="chapter__article padding-left padding-right <?php echo post_password_required() ? '_password' : ''; ?>">
|
||||
<article id="ch-<?php the_ID(); ?>" data-author-id="<?php echo get_the_author_meta( 'ID' ); ?>" class="chapter__article padding-left padding-right <?php echo post_password_required() ? '_password' : ''; ?>" data-age-rating="<?php echo strtolower( $age_rating ); ?>">
|
||||
|
||||
<div class="chapter__actions chapter__actions--top">
|
||||
<div class="chapter__actions-container chapter__actions-left"><?php
|
||||
|
@ -54,7 +54,7 @@ get_header( null, $header_args );
|
||||
);
|
||||
?>
|
||||
|
||||
<article id="<?php the_ID(); ?>" class="story__article <?php if ( ! $can_checkmarks ) echo '_no-checkmarks'; ?>">
|
||||
<article id="<?php the_ID(); ?>" class="story__article <?php if ( ! $can_checkmarks ) echo '_no-checkmarks'; ?>" data-age-rating="<?php echo strtolower( $story['rating'] ); ?>">
|
||||
|
||||
<?php
|
||||
// Render article header
|
||||
|
@ -36,3 +36,52 @@ function fcn_loadConsentBanner() {
|
||||
fcn_consentBanner.classList.add('hidden');
|
||||
});
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// AGE CONFIRMATION
|
||||
// =============================================================================
|
||||
|
||||
if (_$$$('age-confirmation-modal') && localStorage.getItem('fcnAgeConfirmation') !== '1') {
|
||||
// Delay to avoid impacting web vitals
|
||||
setTimeout(() => {
|
||||
fcn_showAgeConfirmationModal();
|
||||
}, 2000);
|
||||
} else {
|
||||
_$$$('age-confirmation-modal')?.remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show age confirmation modal if required.
|
||||
*
|
||||
* @since 5.9.0
|
||||
*/
|
||||
|
||||
function fcn_showAgeConfirmationModal() {
|
||||
// Adult story or chapter?
|
||||
const rating = _$('.story__article, .chapter__article')?.dataset.ageRating;
|
||||
|
||||
if (rating && rating !== 'adult') {
|
||||
_$$$('age-confirmation-modal')?.remove();
|
||||
return;
|
||||
}
|
||||
|
||||
// Setup
|
||||
const leave = _$$$('age-confirmation-leave');
|
||||
|
||||
// Disable site and show modal
|
||||
fcn_theRoot.classList.add('age-modal-open');
|
||||
_$$$('age-confirmation-modal').classList.add('_open');
|
||||
|
||||
// Confirm button
|
||||
_$$$('age-confirmation-confirm')?.addEventListener('click', event => {
|
||||
fcn_theRoot.classList.remove('age-modal-open');
|
||||
event.currentTarget.closest('.modal').remove();
|
||||
localStorage.setItem('fcnAgeConfirmation', '1');
|
||||
});
|
||||
|
||||
// Leave button
|
||||
leave?.addEventListener('click', () => {
|
||||
window.location.href = leave.dataset.redirect ?? 'https://search.brave.com/';
|
||||
localStorage.removeItem('fcnAgeConfirmation');
|
||||
});
|
||||
}
|
||||
|
@ -1,3 +1,16 @@
|
||||
:root.age-modal-open {
|
||||
overflow: hidden;
|
||||
|
||||
body {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
:is(.site, .mobile-menu, .consent-banner) {
|
||||
pointer-events: none;
|
||||
filter: blur(5px) brightness(0.5);
|
||||
}
|
||||
}
|
||||
|
||||
.site {
|
||||
position: relative;
|
||||
left: 0;
|
||||
|
@ -6,6 +6,10 @@
|
||||
line-height: 1.3;
|
||||
contain: content; // Improve performance
|
||||
|
||||
&.age-confirmation {
|
||||
--modal-width: 450px;
|
||||
}
|
||||
|
||||
&:not(._open) {
|
||||
display: none;
|
||||
content-visibility: hidden;
|
||||
@ -225,6 +229,10 @@
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&._large {
|
||||
font-size: var(--fs-xs);
|
||||
}
|
||||
}
|
||||
|
||||
&__textarea {
|
||||
@ -249,6 +257,15 @@
|
||||
justify-content: flex-end;
|
||||
padding: 0 12px 12px;
|
||||
|
||||
&._age-confirmation {
|
||||
gap: 9px; // 9px + 3px margin
|
||||
padding-top: 12px;
|
||||
|
||||
.button {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
}
|
||||
|
||||
.button {
|
||||
&:not(:first-child) {
|
||||
margin-left: 3px;
|
||||
|
Loading…
x
Reference in New Issue
Block a user