Differential D14011 Diff 33879 src/applications/webpush/settings/PhabricatorWebpushNotificationsSettingsPanel.php
Changeset View
Changeset View
Standalone View
Standalone View
src/applications/webpush/settings/PhabricatorWebpushNotificationsSettingsPanel.php
- This file was added.
| <?php | |||||
| final class PhabricatorWebpushNotificationsSettingsPanel | |||||
| extends PhabricatorSettingsPanel { | |||||
| public function getPanelKey() { | |||||
| return 'webpush'; | |||||
| } | |||||
| public function getPanelName() { | |||||
| return pht('Subscriptions'); | |||||
| } | |||||
| public function getPanelGroup() { | |||||
| return pht('Push Notifications'); | |||||
| } | |||||
| public function isEnabled() { | |||||
| $enabled = PhabricatorEnv::getEnvConfig('webpush.enabled') | |||||
| && PhabricatorEnv::getEnvConfig('webpush.gcm-sender-id') | |||||
| && PhabricatorEnv::getEnvConfig('webpush.gcm-api-key') | |||||
| && strncmp(PhabricatorEnv::getEnvConfig('phabricator.base-uri'), | |||||
| 'https://', 8) === 0; | |||||
| return $enabled; | |||||
| } | |||||
| public function isEditableByAdministrators() { | |||||
| if ($this->getUser()->getIsMailingList()) { | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| public function processRequest(AphrontRequest $request) { | |||||
| $user = $this->getUser(); | |||||
| $editable = PhabricatorEnv::getEnvConfig('account.editable'); | |||||
| $uri = $request->getRequestURI(); | |||||
| $uri->setQueryParams(array()); | |||||
| if ($editable) { | |||||
| $new = $request->getStr('new'); | |||||
| if ($new) { | |||||
| return $this->returnNewSubscriptionResponse($request, $uri, $new); | |||||
| } | |||||
| $delete = $request->getInt('delete'); | |||||
| if ($delete) { | |||||
| return $this->returnDeleteSubscriptionResponse($request, $uri, $delete); | |||||
| } | |||||
| } | |||||
| $subscriptions = id(new PhabricatorUserWebPushSubscriber())->loadAllWhere( | |||||
| 'userPHID = %s ORDER BY dateCreated DESC', | |||||
| $user->getPHID()); | |||||
| $rows = array(); | |||||
| foreach ($subscriptions as $subscription) { | |||||
| $button_remove = javelin_tag( | |||||
| 'a', | |||||
| array( | |||||
| 'class' => 'button small grey', | |||||
| 'href' => $uri->alter('delete', $subscription->getID()), | |||||
| 'sigil' => 'workflow', | |||||
| ), | |||||
| pht('Remove')); | |||||
| $remove = $button_remove; | |||||
| $rows[] = array( | |||||
| $subscription->getUserAgent(), | |||||
| $remove, | |||||
| ); | |||||
| } | |||||
| $table = new AphrontTableView($rows); | |||||
| $table->setHeaders( | |||||
| array( | |||||
| pht('Browser'), | |||||
| pht('Action'), | |||||
| )); | |||||
| $table->setColumnClasses( | |||||
| array( | |||||
| 'wide', | |||||
| 'action', | |||||
| )); | |||||
| $table->setColumnVisibility( | |||||
| array( | |||||
| true, | |||||
| $editable, | |||||
| )); | |||||
| $view = new PHUIObjectBoxView(); | |||||
| $header = new PHUIHeaderView(); | |||||
| $header->setHeader(pht('Push Notifications')); | |||||
| if ($editable) { | |||||
| $icon = id(new PHUIIconView()) | |||||
| ->setIconFont('fa-plus'); | |||||
| $button = new PHUIButtonView(); | |||||
| $button->setText(pht('Add Current Browser')); | |||||
| $button->setTag('a'); | |||||
| $button->setHref($uri->alter('new', 'true')); | |||||
| $button->setIcon($icon); | |||||
| $button->addSigil('workflow'); | |||||
| $header->addActionLink($button); | |||||
| } | |||||
| $view->appendChild(phutil_tag( | |||||
| 'link', | |||||
| array( | |||||
| 'rel' => 'manifest', | |||||
| 'href' => '/manifest.json', | |||||
| ))); | |||||
| $view->setHeader($header); | |||||
| $view->setTable($table); | |||||
| return $view; | |||||
| } | |||||
| private function returnNewSubscriptionResponse( | |||||
| AphrontRequest $request, | |||||
| PhutilURI $uri, | |||||
| $new) { | |||||
| $user = $this->getUser(); | |||||
| $viewer = $this->getViewer(); | |||||
| $subscription_id = null; | |||||
| $endpoint = null; | |||||
| $errors = array(); | |||||
| if ($request->isDialogFormPost()) { | |||||
| $endpoint = trim($request->getStr('endpoint')); | |||||
| if (!strlen($endpoint)) { | |||||
| $errors[] = pht('Browser data is missing.'); | |||||
| } | |||||
| $subscription_id = basename($endpoint); | |||||
| $endpoint = dirname($endpoint); | |||||
| if (!$errors) { | |||||
| $object = id(new PhabricatorUserWebPushSubscriber()) | |||||
| ->setEndpoint($endpoint) | |||||
| ->setSubscriptionId($subscription_id) | |||||
| ->setUserAgent(idx($_SERVER, 'HTTP_USER_AGENT')) | |||||
| ->setUserPHID($user->getPHID()); | |||||
| try { | |||||
| id(new PhabricatorUserEditor()) | |||||
| ->setActor($viewer) | |||||
| ->addSubscription($user, $object); | |||||
| return id(new AphrontReloadResponse())->setURI($uri); | |||||
| } catch (AphrontDuplicateKeyQueryException $ex) { | |||||
| $errors[] = pht('This browser is already subscribed ' | |||||
| .'to push notifications.'); | |||||
| } | |||||
| } | |||||
| } | |||||
| if ($errors) { | |||||
| $errors = id(new PHUIInfoView()) | |||||
| ->setErrors($errors); | |||||
| } | |||||
| $dialog = id(new AphrontDialogView()) | |||||
| ->setFormID('webpush-subscribe') | |||||
| ->setUser($viewer) | |||||
| ->addHiddenInput('new', 'true') | |||||
| ->addHiddenInput('endpoint', '') | |||||
| ->setTitle(pht('Subscribe this browser')) | |||||
| ->appendChild($errors) | |||||
| ->appendChild(phutil_tag('p', array(), pht( | |||||
| 'Your browser needs to support Service Workers and Push '. | |||||
| 'Notifications. Most recent versions of Chrome and Firefox do.'))) | |||||
| ->addCancelButton($uri); | |||||
| if (!$errors) { | |||||
| $dialog->addSubmitButton(pht('Subscribe')); | |||||
| } | |||||
| require_celerity_resource('javelin-behavior-webpush-subscriptions'); | |||||
| Javelin::initBehavior('webpush-subscriptions'); | |||||
| return id(new AphrontDialogResponse())->setDialog($dialog); | |||||
| } | |||||
| private function returnDeleteSubscriptionResponse( | |||||
| AphrontRequest $request, | |||||
| PhutilURI $uri, | |||||
| $subscription_id) { | |||||
| $user = $this->getUser(); | |||||
| $viewer = $this->getViewer(); | |||||
| $subscriber = id(new PhabricatorUserWebPushSubscriber())->loadOneWhere( | |||||
| 'id = %d AND userPHID = %s', | |||||
| $subscription_id, | |||||
| $user->getPHID()); | |||||
| if (!$subscriber) { | |||||
| return new Aphront404Response(); | |||||
| } | |||||
| if ($request->isFormPost()) { | |||||
| id(new PhabricatorUserEditor()) | |||||
| ->setActor($viewer) | |||||
| ->removeSubscription($user, $subscriber); | |||||
| return id(new AphrontRedirectResponse())->setURI($uri); | |||||
| } | |||||
| $dialog = id(new AphrontDialogView()) | |||||
| ->setUser($viewer) | |||||
| ->addHiddenInput('delete', $subscription_id) | |||||
| ->setTitle(pht('Really delete subscription?')) | |||||
| ->appendParagraph( | |||||
| pht( | |||||
| 'Are you sure you want to unsubscribe this browser?')) | |||||
| ->addSubmitButton(pht('Unsubscribe')) | |||||
| ->addCancelButton($uri); | |||||
| return id(new AphrontDialogResponse())->setDialog($dialog); | |||||
| } | |||||
| } |