diff --git a/src/__celerity_resource_map__.php b/src/__celerity_resource_map__.php index 3a069635b0..19eac0ddb1 100644 --- a/src/__celerity_resource_map__.php +++ b/src/__celerity_resource_map__.php @@ -357,6 +357,13 @@ celerity_register_resource_map(array( 'disk' => '/rsrc/image/icon/unsubscribe.png', 'type' => 'png', ), + '/rsrc/image/notification_menu.png' => + array( + 'hash' => 'f3834ad08a16fc631cd46ceb5db4fb0e', + 'uri' => '/res/f3834ad0/rsrc/image/notification_menu.png', + 'disk' => '/rsrc/image/notification_menu.png', + 'type' => 'png', + ), '/rsrc/image/phabricator_logo.png' => array( 'hash' => '7e62ff4001914cb3c87893a228f400c4', @@ -758,15 +765,15 @@ celerity_register_resource_map(array( ), 'javelin-behavior-aphlict-dropdown' => array( - 'uri' => '/res/c0b06adb/rsrc/js/application/aphlict/behavior-aphlict-dropdown.js', + 'uri' => '/res/425c08fd/rsrc/js/application/aphlict/behavior-aphlict-dropdown.js', 'type' => 'js', 'requires' => array( 0 => 'javelin-behavior', - 1 => 'javelin-aphlict', - 2 => 'javelin-util', - 3 => 'javelin-request', - 4 => 'javelin-stratcom', + 1 => 'javelin-request', + 2 => 'javelin-stratcom', + 3 => 'javelin-vector', + 4 => 'javelin-dom', ), 'disk' => '/rsrc/js/application/aphlict/behavior-aphlict-dropdown.js', ), @@ -2304,7 +2311,7 @@ celerity_register_resource_map(array( ), 'phabricator-standard-page-view' => array( - 'uri' => '/res/abebf8a7/rsrc/css/application/base/standard-page-view.css', + 'uri' => '/res/fe757493/rsrc/css/application/base/standard-page-view.css', 'type' => 'css', 'requires' => array( @@ -2559,7 +2566,7 @@ celerity_register_resource_map(array( ), array( 'packages' => array( - '040e796f' => + '59b02d20' => array( 'name' => 'core.pkg.css', 'symbols' => @@ -2588,7 +2595,7 @@ celerity_register_resource_map(array( 21 => 'phabricator-flag-css', 22 => 'aphront-error-view-css', ), - 'uri' => '/res/pkg/040e796f/core.pkg.css', + 'uri' => '/res/pkg/59b02d20/core.pkg.css', 'type' => 'css', ), '0c96375e' => @@ -2755,20 +2762,20 @@ celerity_register_resource_map(array( 'reverse' => array( 'aphront-attached-file-view-css' => '7839ae2d', - 'aphront-crumbs-view-css' => '040e796f', - 'aphront-dialog-view-css' => '040e796f', - 'aphront-error-view-css' => '040e796f', - 'aphront-form-view-css' => '040e796f', + 'aphront-crumbs-view-css' => '59b02d20', + 'aphront-dialog-view-css' => '59b02d20', + 'aphront-error-view-css' => '59b02d20', + 'aphront-form-view-css' => '59b02d20', 'aphront-headsup-action-list-view-css' => '32f461a4', - 'aphront-headsup-view-css' => '040e796f', - 'aphront-list-filter-view-css' => '040e796f', - 'aphront-pager-view-css' => '040e796f', - 'aphront-panel-view-css' => '040e796f', - 'aphront-side-nav-view-css' => '040e796f', - 'aphront-table-view-css' => '040e796f', - 'aphront-tokenizer-control-css' => '040e796f', - 'aphront-tooltip-css' => '040e796f', - 'aphront-typeahead-control-css' => '040e796f', + 'aphront-headsup-view-css' => '59b02d20', + 'aphront-list-filter-view-css' => '59b02d20', + 'aphront-pager-view-css' => '59b02d20', + 'aphront-panel-view-css' => '59b02d20', + 'aphront-side-nav-view-css' => '59b02d20', + 'aphront-table-view-css' => '59b02d20', + 'aphront-tokenizer-control-css' => '59b02d20', + 'aphront-tooltip-css' => '59b02d20', + 'aphront-typeahead-control-css' => '59b02d20', 'differential-changeset-view-css' => '32f461a4', 'differential-core-view-css' => '32f461a4', 'differential-inline-comment-editor' => '1662d764', @@ -2834,15 +2841,15 @@ celerity_register_resource_map(array( 'javelin-workflow' => '0c96375e', 'maniphest-task-summary-css' => '7839ae2d', 'maniphest-transaction-detail-css' => '7839ae2d', - 'phabricator-app-buttons-css' => '040e796f', + 'phabricator-app-buttons-css' => '59b02d20', 'phabricator-content-source-view-css' => '32f461a4', - 'phabricator-core-buttons-css' => '040e796f', - 'phabricator-core-css' => '040e796f', - 'phabricator-directory-css' => '040e796f', + 'phabricator-core-buttons-css' => '59b02d20', + 'phabricator-core-css' => '59b02d20', + 'phabricator-directory-css' => '59b02d20', 'phabricator-drag-and-drop-file-upload' => '1662d764', 'phabricator-dropdown-menu' => '0c96375e', - 'phabricator-flag-css' => '040e796f', - 'phabricator-jump-nav' => '040e796f', + 'phabricator-flag-css' => '59b02d20', + 'phabricator-jump-nav' => '59b02d20', 'phabricator-keyboard-shortcut' => '0c96375e', 'phabricator-keyboard-shortcut-manager' => '0c96375e', 'phabricator-menu-item' => '0c96375e', @@ -2850,11 +2857,11 @@ celerity_register_resource_map(array( 'phabricator-paste-file-upload' => '0c96375e', 'phabricator-prefab' => '0c96375e', 'phabricator-project-tag-css' => '7839ae2d', - 'phabricator-remarkup-css' => '040e796f', + 'phabricator-remarkup-css' => '59b02d20', 'phabricator-shaped-request' => '1662d764', - 'phabricator-standard-page-view' => '040e796f', + 'phabricator-standard-page-view' => '59b02d20', 'phabricator-tooltip' => '0c96375e', - 'phabricator-transaction-view-css' => '040e796f', - 'syntax-highlighting-css' => '040e796f', + 'phabricator-transaction-view-css' => '59b02d20', + 'syntax-highlighting-css' => '59b02d20', ), )); diff --git a/src/applications/notification/builder/PhabricatorNotificationBuilder.php b/src/applications/notification/builder/PhabricatorNotificationBuilder.php index 8204dfa9de..22c8c2462c 100644 --- a/src/applications/notification/builder/PhabricatorNotificationBuilder.php +++ b/src/applications/notification/builder/PhabricatorNotificationBuilder.php @@ -46,10 +46,6 @@ final class PhabricatorNotificationBuilder { $null_view->appendChild($view); } - return id(new AphrontNullView())->appendChild( - '
'. - $null_view->render(). - '
'); - + return $null_view; } } diff --git a/src/applications/notification/view/PhabricatorNotificationStoryView.php b/src/applications/notification/view/PhabricatorNotificationStoryView.php index 51a29c870c..90d01ef8e5 100644 --- a/src/applications/notification/view/PhabricatorNotificationStoryView.php +++ b/src/applications/notification/view/PhabricatorNotificationStoryView.php @@ -40,26 +40,20 @@ extends PhabricatorNotificationView { public function render() { - $title = $this->title; + $classes = array( + 'phabricator-notification', + ); + if (!$this->viewed) { - $title = ''.$title.''; + $classes[] = 'phabricator-notification-unread'; } - $head = phutil_render_tag( - 'div', - array( - 'class' => 'phabricator-notification-story-head', - ), - nonempty($title, 'Untitled Story')); - - return phutil_render_tag( 'div', array( - 'class' => - 'phabricator-notification '. - 'phabricator-notification-story-one-line'), - $head); + 'class' => implode(' ', $classes), + ), + $this->title); } } diff --git a/src/view/page/PhabricatorStandardPageView.php b/src/view/page/PhabricatorStandardPageView.php index c0815f350c..6d654ed74e 100644 --- a/src/view/page/PhabricatorStandardPageView.php +++ b/src/view/page/PhabricatorStandardPageView.php @@ -381,8 +381,9 @@ final class PhabricatorStandardPageView extends AphrontPageView { ' '); } - $notification_header = ''; + $notification_indicator = ''; $notification_dropdown = ''; + $notification_container = ''; if (PhabricatorEnv::getEnvConfig('notification.enabled') && $user->isLoggedIn()) { @@ -404,22 +405,43 @@ final class PhabricatorStandardPageView extends AphrontPageView { Javelin::initBehavior('aphlict-dropdown', array()); - $notification_indicator = - javelin_render_tag( - 'td', - array( - 'sigil' => 'aphlict-indicator', - 'id' => 'phabricator-notification-indicator', - ), - id(new PhabricatorFeedStoryNotification) - ->countUnread($user)); + $notification_count = id(new PhabricatorFeedStoryNotification()) + ->countUnread($user); - $notification_header = - $notification_indicator. - ''. - '
'. - '
'. - ''; + $indicator_classes = array( + 'phabricator-notification-indicator', + ); + if ($notification_count) { + $indicator_classes[] = 'phabricator-notification-indicator-unread'; + } + + $notification_indicator = javelin_render_tag( + 'div', + array( + 'id' => 'phabricator-notification-indicator', + 'class' => implode(' ', $indicator_classes), + ), + $notification_count); + + $notification_indicator = javelin_render_tag( + 'div', + array( + 'id' => 'phabricator-notification-menu', + 'class' => 'phabricator-icon-menu icon-menu-notifications', + 'sigil' => 'aphlict-indicator', + ), + $notification_indicator); + + $notification_indicator = javelin_render_tag( + 'td', + array( + 'class' => 'phabricator-icon-menu-cell', + ), + $notification_indicator); + + $notification_container = + '
'. + '
'; $notification_dropdown = javelin_render_tag( 'div', @@ -441,6 +463,7 @@ final class PhabricatorStandardPageView extends AphrontPageView { $custom_logo. ' '. ''. + $notification_indicator. ''. ''. ''. @@ -460,10 +483,10 @@ final class PhabricatorStandardPageView extends AphrontPageView { ''. - $notification_header. ''. '
'. - $notification_dropdown; + $notification_dropdown. + $notification_container; $footer_chrome = '
'. $foot_links. diff --git a/webroot/rsrc/css/application/base/standard-page-view.css b/webroot/rsrc/css/application/base/standard-page-view.css index 21e9d7a89c..7ff237ed4c 100644 --- a/webroot/rsrc/css/application/base/standard-page-view.css +++ b/webroot/rsrc/css/application/base/standard-page-view.css @@ -239,57 +239,70 @@ a.handle-disabled { } -#phabricator-notification-indicator { - background-color: #0069a6; - text-align: center; - font-size: 20px; - vertical-align: middle; +.phabricator-icon-menu { height: 40px; - width: 40px; - - -moz-user-select: -moz-none; - -khtml-user-select: none; - -webkit-user-select: none; - -o-user-select: none; + width: 60px; + left: -22px; + position: relative; + cursor: pointer; } -#phabricator-notification-indicator:hover { - cursor: pointer; - background-color: #0089d9; +.phabricator-icon-menu-cell { + width: 60px; +} + +.icon-menu-notifications { + background: url(/rsrc/image/notification_menu.png); +} + +.phabricator-icon-menu:hover { + background-position: 0 -40px; +} + +.phabricator-notification-indicator { + display: none; } .phabricator-notification-indicator-unread { - font-weight: bold; + display: block; + + position: absolute; + right: 8px; + top: 2px; + padding: 1px 3px; + + background: #dd3333; + + border: 1px solid #aa0000; + font-size: 11px; + + box-shadow: 0px 0px 4px rgba(255, 255, 255, 0.75); } + #phabricator-notification-dropdown { - - word-wrap: break-word; - - overflow-y: auto; position: absolute; - width: 600px; - height: 300px; - right: 0px; + top: 40px; + border: 1px solid #99c4d7; + border-top-width: 0; + background: #fdfdff; - background-color: #f0f0f0; - border: 1px solid darkgrey; - box-shadow: 3px 3px #ccc; - -webkit-box-shadow: 3px 3px #ccc; - -moz-box-shadow: 3px 3px #ccc; + width: 360px; + box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); + + font-size: 11px; z-index: 3; + + word-wrap: break-word; + overflow-y: auto; } -.phabricator-notification-story-head { - border-bottom: 1px solid darkgray; - padding-top: 2px; - padding-bottom: 2px; +.phabricator-notification { + padding: 6px 6px; } - -.phabricator-notification-frame { - padding-left: 5px; - padding-right: 10px; +.phabricator-notification-unread { + background: #aacfef; } diff --git a/webroot/rsrc/image/notification_menu.png b/webroot/rsrc/image/notification_menu.png new file mode 100644 index 0000000000..408e9d6e6d Binary files /dev/null and b/webroot/rsrc/image/notification_menu.png differ diff --git a/webroot/rsrc/js/application/aphlict/behavior-aphlict-dropdown.js b/webroot/rsrc/js/application/aphlict/behavior-aphlict-dropdown.js index b3569934e6..8cd33d4384 100644 --- a/webroot/rsrc/js/application/aphlict/behavior-aphlict-dropdown.js +++ b/webroot/rsrc/js/application/aphlict/behavior-aphlict-dropdown.js @@ -1,15 +1,16 @@ /** * @provides javelin-behavior-aphlict-dropdown * @requires javelin-behavior - * javelin-aphlict - * javelin-util * javelin-request * javelin-stratcom + * javelin-vector + * javelin-dom */ JX.behavior('aphlict-dropdown', function(config) { var dropdown = JX.$('phabricator-notification-dropdown'); var indicator = JX.$('phabricator-notification-indicator'); + var menu = JX.$('phabricator-notification-menu'); var visible = false; var request = null; @@ -52,16 +53,22 @@ JX.behavior('aphlict-dropdown', function(config) { JX.DOM.listen( - indicator, + menu, 'click', null, function(e) { - if(visible) { + if (visible) { JX.DOM.hide(dropdown); } else { + var p = JX.$V(menu); + p.y = null; + p.x -= 6; + p.setPos(dropdown); + JX.DOM.show(dropdown); } visible = !visible; + e.kill(); } )