Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions config/wpn_ucp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,7 @@ phpbb_webpushnotifications_ucp_push_subscribe_controller:
phpbb_webpushnotifications_ucp_push_unsubscribe_controller:
path: /push/unsubscribe
defaults: { _controller: phpbb.wpn.ucp.controller.webpush:unsubscribe }

phpbb_webpushnotifications_ucp_push_toggle_popup_controller:
path: /push/toggle-popup
defaults: { _controller: phpbb.wpn.ucp.controller.webpush:toggle_popup }
2 changes: 2 additions & 0 deletions language/en/webpushnotifications_module_ucp.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,6 @@
'NOTIFY_WEBPUSH_POPUP_MESSAGE' => 'We would like to send you browser notifications for replies, private messages, and relevant forum activity. Optional — you can manage these settings at any time.',
'NOTIFY_WEBPUSH_POPUP_ALLOW' => 'Allow',
'NOTIFY_WEBPUSH_POPUP_DENY' => 'Deny',
'NOTIFY_WEBPUSH_POPUP_DISABLE' => 'Disable web push notification prompts',
'NOTIFY_WEBPUSH_POPUP_DISABLE_EXPLAIN' => 'Turn this on to stop us from asking you to enable web push notifications on any of your devices. If you disable web push notification prompts, we won’t be able to alert you if you ever become unsubscribed.',
]);
2 changes: 2 additions & 0 deletions language/ru/webpushnotifications_module_ucp.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,6 @@
'NOTIFY_WEBPUSH_POPUP_MESSAGE' => 'Браузерные уведомления позволяют быстро получать информацию о новых ответах, личных сообщениях и других активностях на данной конференции. Функцию можно отключить или включить в любое время в настройках уведомлений в Личном разделе.',
'NOTIFY_WEBPUSH_POPUP_ALLOW' => 'Включить',
'NOTIFY_WEBPUSH_POPUP_DENY' => 'Отклонить',
'NOTIFY_WEBPUSH_POPUP_DISABLE' => 'Disable web push notification prompts',
'NOTIFY_WEBPUSH_POPUP_DISABLE_EXPLAIN' => 'Turn this on to stop us from asking you to enable web push notifications on any of your devices. If you disable web push notification prompts, we won’t be able to alert you if you ever become unsubscribed.',
]);
48 changes: 48 additions & 0 deletions migrations/add_user_popup_preference.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php
/**
*
* phpBB Browser Push Notifications. An extension for the phpBB Forum Software package.
*
* @copyright (c) 2025, phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
*/

namespace phpbb\webpushnotifications\migrations;

use phpbb\db\migration\migration;

class add_user_popup_preference extends migration
{
public function effectively_installed()
{
return $this->db_tools->sql_column_exists($this->table_prefix . 'users', 'user_wpn_popup_disabled');
}

public static function depends_on()
{
return ['\phpbb\webpushnotifications\migrations\add_popup_prompt'];
}

public function update_schema()
{
return [
'add_columns' => [
$this->table_prefix . 'users' => [
'user_wpn_popup_disabled' => ['BOOL', 0],
],
],
];
}

public function revert_schema()
{
return [
'drop_columns' => [
$this->table_prefix . 'users' => [
'user_wpn_popup_disabled',
],
],
];
}
}
4 changes: 3 additions & 1 deletion notification/method/webpush.php
Original file line number Diff line number Diff line change
Expand Up @@ -390,11 +390,13 @@ public function get_ucp_template_data(helper $controller_helper, form_helper $fo
'NOTIFICATIONS_WEBPUSH_ENABLE' => ($this->config['load_notifications'] && $this->config['allow_board_notifications'] && $this->config['wpn_webpush_dropdown_subscribe']) || stripos($this->user->page['page'], 'notification_options'),
'U_WEBPUSH_SUBSCRIBE' => $controller_helper->route('phpbb_webpushnotifications_ucp_push_subscribe_controller'),
'U_WEBPUSH_UNSUBSCRIBE' => $controller_helper->route('phpbb_webpushnotifications_ucp_push_unsubscribe_controller'),
'U_WEBPUSH_TOGGLE_POPUP' => $controller_helper->route('phpbb_webpushnotifications_ucp_push_toggle_popup_controller'),
'VAPID_PUBLIC_KEY' => $this->config['wpn_webpush_vapid_public'],
'U_WEBPUSH_WORKER_URL' => $controller_helper->route('phpbb_webpushnotifications_ucp_push_worker_controller'),
'SUBSCRIPTIONS' => $subscriptions,
'WEBPUSH_FORM_TOKENS' => $form_helper->get_form_tokens(\phpbb\webpushnotifications\ucp\controller\webpush::FORM_TOKEN_UCP),
'S_WEBPUSH_POPUP_PROMPT' => $this->config['wpn_webpush_popup_prompt'] && $this->user->id() != ANONYMOUS && $this->user->data['user_type'] != USER_IGNORE,
'S_WEBPUSH_POPUP_PROMPT' => $this->config['wpn_webpush_popup_prompt'] && $this->user->id() != ANONYMOUS && $this->user->data['user_type'] != USER_IGNORE && !($this->user->data['user_wpn_popup_disabled'] ?? 0),
'S_WEBPUSH_POPUP_DISABLED' => $this->user->data['user_wpn_popup_disabled'] ?? 0,
];
}

Expand Down
1 change: 1 addition & 0 deletions styles/all/template/ucp_notifications_webpush.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
serviceWorkerUrl: '{{ U_WEBPUSH_WORKER_URL }}',
subscribeUrl: '{{ U_WEBPUSH_SUBSCRIBE }}',
unsubscribeUrl: '{{ U_WEBPUSH_UNSUBSCRIBE }}',
togglePopupUrl: '{{ U_WEBPUSH_TOGGLE_POPUP }}',
ajaxErrorTitle: '{{ lang_js('AJAX_ERROR_TITLE') }}',
vapidPublicKey: '{{ VAPID_PUBLIC_KEY }}',
formTokens: {
Expand Down
102 changes: 91 additions & 11 deletions styles/all/template/webpush.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ function PhpbbWebpush() {
/** @type {HTMLElement} Unsubscribe button */
let unsubscribeButton;

/** @type {HTMLElement} Toggle popup button */
let togglePopupButton;

/** @type {string} URL to toggle popup prompt preference */
let togglePopupUrl = '';

/** @type {function} Escape key handler for popup */
let popupEscapeHandler;

/**
* Init function for phpBB Web Push
* @type {array} options
Expand All @@ -41,13 +50,20 @@ function PhpbbWebpush() {
serviceWorkerUrl = options.serviceWorkerUrl;
subscribeUrl = options.subscribeUrl;
unsubscribeUrl = options.unsubscribeUrl;
togglePopupUrl = options.togglePopupUrl;
this.formTokens = options.formTokens;
subscriptions = options.subscriptions;
ajaxErrorTitle = options.ajaxErrorTitle;
vapidPublicKey = options.vapidPublicKey;

subscribeButton = document.querySelector('#subscribe_webpush');
unsubscribeButton = document.querySelector('#unsubscribe_webpush');
togglePopupButton = document.querySelector('#toggle_popup_prompt');

// Set up toggle popup button handler if it exists (on UCP settings page)
if (togglePopupButton) {
togglePopupButton.addEventListener('click', togglePopupHandler);
}

// Service workers are only supported in secure context
if (window.isSecureContext !== true) {
Expand Down Expand Up @@ -163,7 +179,7 @@ function PhpbbWebpush() {
if (allowBtn) {
allowBtn.addEventListener('click', (event) => {
event.stopPropagation();
popup.style.display = 'none';
hidePopup(popup);
subscribeButtonHandler(event).catch(error => {
console.error('Subscription handler error:', error);
});
Expand All @@ -173,19 +189,40 @@ function PhpbbWebpush() {
if (denyBtn) {
denyBtn.addEventListener('click', (event) => {
event.stopPropagation();
popup.style.display = 'none';
hidePopup(popup);
promptDenied.set();
});
}

if (overlay) {
overlay.addEventListener('click', (event) => {
if (event.target === overlay) {
popup.style.display = 'none';
hidePopup(popup);
promptDenied.set();
}
});

popupEscapeHandler = (event) => {
if (event.key === 'Escape') {
hidePopup(popup);
promptDenied.set();
}
};

document.addEventListener('keydown', popupEscapeHandler);
}
}

/**
* Hide popup
* @param popup
*/
function hidePopup(popup) {
if (popup) {
popup.style.display = 'none';
}
document.removeEventListener('keydown', popupEscapeHandler);
popupEscapeHandler = null;
}

/**
Expand Down Expand Up @@ -282,10 +319,7 @@ function PhpbbWebpush() {
});
} catch (error) {
promptDenied.set(); // deny the prompt on error to prevent repeated prompting
const popup = document.getElementById('wpn_popup_prompt');
if (popup) {
popup.style.display = 'none';
}
hidePopup(document.getElementById('wpn_popup_prompt'));
console.error('Push subscription error:', error);
phpbb.alert(subscribeButton.getAttribute('data-l-err'), error.message || subscribeButton.getAttribute('data-l-unsupported'));
} finally {
Expand Down Expand Up @@ -331,6 +365,55 @@ function PhpbbWebpush() {
});
}

/**
* Handler for toggle popup prompt button
*
* @param {Object} event Toggle button push event
*/
function togglePopupHandler(event) {
event.preventDefault();

const loadingIndicator = phpbb.loadingIndicator();
const formData = new FormData();
formData.append('form_token', phpbb.webpush.formTokens.formToken);
formData.append('creation_time', phpbb.webpush.formTokens.creationTime.toString());

fetch(togglePopupUrl, {
method: 'POST',
headers: {
'X-Requested-With': 'XMLHttpRequest',
},
body: formData,
})
.then(response => response.json())
.then(data => {
loadingIndicator.fadeOut(phpbb.alertTime);
if (data.success) {
// Update toggle icon based on new state
const button = document.getElementById('toggle_popup_prompt');
if (button) {
const icon = button.querySelector('i');
if (icon) {
if (data.disabled) {
icon.classList.remove('fa-toggle-off');
icon.classList.add('fa-toggle-on');
} else {
icon.classList.remove('fa-toggle-on');
icon.classList.add('fa-toggle-off');
}
}
}
if ('form_tokens' in data) {
updateFormTokens(data.form_tokens);
}
}
})
.catch(error => {
loadingIndicator.fadeOut(phpbb.alertTime);
phpbb.alert(ajaxErrorTitle, error);
});
}

/**
* Handle subscribe response
*
Expand All @@ -343,10 +426,7 @@ function PhpbbWebpush() {
updateFormTokens(response.form_tokens);
}
promptDenied.remove();
const popup = document.getElementById('wpn_popup_prompt');
if (popup) {
popup.style.display = 'none';
}
hidePopup(document.getElementById('wpn_popup_prompt'));
}
}

Expand Down
8 changes: 4 additions & 4 deletions styles/all/template/webpush_popup.html
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
{% if S_WEBPUSH_POPUP_PROMPT %}
<div id="wpn_popup_prompt" class="wpn-popup-overlay" style="display:none;">
<div id="wpn_popup_prompt" class="wpn-popup-overlay" style="display:none;" role="dialog" aria-modal="true" aria-labelledby="wpn_popup_title" aria-describedby="wpn_popup_message">
<div class="wpn-popup-container">
<div class="wpn-popup-content">
<h3 class="wpn-popup-title">
<h3 id="wpn_popup_title" class="wpn-popup-title">
<span>{{ lang('NOTIFY_WEBPUSH_POPUP_TITLE') }}</span>
<span class="fa-stack fa-lg">
<span class="fa-stack fa-lg" aria-hidden="true">
<i class="fa fa-circle fa-stack-2x"></i>
<i class="fa fa-bell fa-stack-1x fa-inverse"></i>
</span>
</h3>
<p class="wpn-popup-message">{{ lang('NOTIFY_WEBPUSH_POPUP_MESSAGE') }}</p>
<p id="wpn_popup_message" class="wpn-popup-message">{{ lang('NOTIFY_WEBPUSH_POPUP_MESSAGE') }}</p>
<div class="wpn-popup-buttons">
<button id="wpn_popup_allow" class="wpn-popup-btn wpn-popup-btn-allow">{{ lang('NOTIFY_WEBPUSH_POPUP_ALLOW') }}</button>
<button id="wpn_popup_deny" class="wpn-popup-btn wpn-popup-btn-deny">{{ lang('NOTIFY_WEBPUSH_POPUP_DENY') }}</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@
<br><span>{{ lang('NOTIFY_WEBPUSH_ENABLE_EXPLAIN') }}</span>
</dd>
</dl>
<dl>
<dt><label for="toggle_popup_prompt">{{ lang('NOTIFY_WEBPUSH_POPUP_DISABLE') ~ lang('COLON') }}</label></dt>
<dd>
<button id="toggle_popup_prompt" type="button" name="toggle_popup_prompt" class="wpn-toggle-button" aria-label="{{ lang('NOTIFY_WEBPUSH_POPUP_DISABLE') }}">
<i class="icon icon-lg fa-fw fa-toggle-{% if S_WEBPUSH_POPUP_DISABLED %}on{% else %}off{% endif %}" aria-hidden="true"></i>
</button>
<br><span>{{ lang('NOTIFY_WEBPUSH_POPUP_DISABLE_EXPLAIN') }}</span>
</dd>
</dl>
</fieldset>
</div>
</div>
Expand Down
Loading