@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Conpherence - add dropdown menu

Summary: Fixes T3641. Probably needs some @chad love though on colors and what have you. Technique was to jam this into the existing notifications stuff as much as possible. I think its "okay" but if we were to add more stuff here (like a 3rd application) this could get a quality pass to consolidate even more code.

Test Plan: played with it in Chrome and Safari - looks reasonable

Reviewers: chad, epriestley

Reviewed By: epriestley

CC: aran, Korvin

Maniphest Tasks: T3641

Differential Revision: https://secure.phabricator.com/D6708

+269 -46
+49 -40
src/__celerity_resource_map__.php
··· 997 997 ), 998 998 'disk' => '/rsrc/css/application/conpherence/message-pane.css', 999 999 ), 1000 + 'conpherence-notification-css' => 1001 + array( 1002 + 'uri' => '/res/8804c853/rsrc/css/application/conpherence/notification.css', 1003 + 'type' => 'css', 1004 + 'requires' => 1005 + array( 1006 + ), 1007 + 'disk' => '/rsrc/css/application/conpherence/notification.css', 1008 + ), 1000 1009 'conpherence-update-css' => 1001 1010 array( 1002 1011 'uri' => '/res/92094ed7/rsrc/css/application/conpherence/update.css', ··· 1226 1235 ), 1227 1236 'javelin-behavior-aphlict-dropdown' => 1228 1237 array( 1229 - 'uri' => '/res/b3be58e8/rsrc/js/application/aphlict/behavior-aphlict-dropdown.js', 1238 + 'uri' => '/res/c8def75f/rsrc/js/application/aphlict/behavior-aphlict-dropdown.js', 1230 1239 'type' => 'js', 1231 1240 'requires' => 1232 1241 array( ··· 4212 4221 'uri' => '/res/pkg/e289f6ce/core.pkg.css', 4213 4222 'type' => 'css', 4214 4223 ), 4215 - '606f7152' => 4224 + '7cc3f99d' => 4216 4225 array( 4217 4226 'name' => 'core.pkg.js', 4218 4227 'symbols' => ··· 4255 4264 35 => 'phabricator-hovercard', 4256 4265 36 => 'javelin-behavior-phabricator-hovercards', 4257 4266 ), 4258 - 'uri' => '/res/pkg/606f7152/core.pkg.js', 4267 + 'uri' => '/res/pkg/7cc3f99d/core.pkg.js', 4259 4268 'type' => 'js', 4260 4269 ), 4261 4270 '4ccfeb47' => ··· 4425 4434 'diffusion-icons-css' => 'c8ce2d88', 4426 4435 'global-drag-and-drop-css' => 'e289f6ce', 4427 4436 'inline-comment-summary-css' => 'dd27a69b', 4428 - 'javelin-aphlict' => '606f7152', 4437 + 'javelin-aphlict' => '7cc3f99d', 4429 4438 'javelin-behavior' => '2dbbb7d1', 4430 - 'javelin-behavior-aphlict-dropdown' => '606f7152', 4431 - 'javelin-behavior-aphlict-listen' => '606f7152', 4432 - 'javelin-behavior-aphront-basic-tokenizer' => '606f7152', 4439 + 'javelin-behavior-aphlict-dropdown' => '7cc3f99d', 4440 + 'javelin-behavior-aphlict-listen' => '7cc3f99d', 4441 + 'javelin-behavior-aphront-basic-tokenizer' => '7cc3f99d', 4433 4442 'javelin-behavior-aphront-drag-and-drop-textarea' => '48040be9', 4434 - 'javelin-behavior-aphront-form-disable-on-submit' => '606f7152', 4443 + 'javelin-behavior-aphront-form-disable-on-submit' => '7cc3f99d', 4435 4444 'javelin-behavior-audit-preview' => '96909266', 4436 4445 'javelin-behavior-dark-console' => '4ccfeb47', 4437 - 'javelin-behavior-device' => '606f7152', 4446 + 'javelin-behavior-device' => '7cc3f99d', 4438 4447 'javelin-behavior-differential-accept-with-errors' => '48040be9', 4439 4448 'javelin-behavior-differential-add-reviewers-and-ccs' => '48040be9', 4440 4449 'javelin-behavior-differential-comment-jump' => '48040be9', ··· 4450 4459 'javelin-behavior-diffusion-commit-graph' => '96909266', 4451 4460 'javelin-behavior-diffusion-pull-lastmodified' => '96909266', 4452 4461 'javelin-behavior-error-log' => '4ccfeb47', 4453 - 'javelin-behavior-global-drag-and-drop' => '606f7152', 4454 - 'javelin-behavior-history-install' => '606f7152', 4455 - 'javelin-behavior-konami' => '606f7152', 4456 - 'javelin-behavior-lightbox-attachments' => '606f7152', 4462 + 'javelin-behavior-global-drag-and-drop' => '7cc3f99d', 4463 + 'javelin-behavior-history-install' => '7cc3f99d', 4464 + 'javelin-behavior-konami' => '7cc3f99d', 4465 + 'javelin-behavior-lightbox-attachments' => '7cc3f99d', 4457 4466 'javelin-behavior-load-blame' => '48040be9', 4458 4467 'javelin-behavior-maniphest-batch-selector' => '98f64f07', 4459 4468 'javelin-behavior-maniphest-subpriority-editor' => '98f64f07', 4460 4469 'javelin-behavior-maniphest-transaction-controls' => '98f64f07', 4461 4470 'javelin-behavior-maniphest-transaction-expand' => '98f64f07', 4462 4471 'javelin-behavior-maniphest-transaction-preview' => '98f64f07', 4463 - 'javelin-behavior-phabricator-active-nav' => '606f7152', 4464 - 'javelin-behavior-phabricator-autofocus' => '606f7152', 4465 - 'javelin-behavior-phabricator-gesture' => '606f7152', 4466 - 'javelin-behavior-phabricator-hovercards' => '606f7152', 4467 - 'javelin-behavior-phabricator-keyboard-shortcuts' => '606f7152', 4468 - 'javelin-behavior-phabricator-nav' => '606f7152', 4472 + 'javelin-behavior-phabricator-active-nav' => '7cc3f99d', 4473 + 'javelin-behavior-phabricator-autofocus' => '7cc3f99d', 4474 + 'javelin-behavior-phabricator-gesture' => '7cc3f99d', 4475 + 'javelin-behavior-phabricator-hovercards' => '7cc3f99d', 4476 + 'javelin-behavior-phabricator-keyboard-shortcuts' => '7cc3f99d', 4477 + 'javelin-behavior-phabricator-nav' => '7cc3f99d', 4469 4478 'javelin-behavior-phabricator-object-selector' => '48040be9', 4470 - 'javelin-behavior-phabricator-oncopy' => '606f7152', 4471 - 'javelin-behavior-phabricator-remarkup-assist' => '606f7152', 4472 - 'javelin-behavior-phabricator-reveal-content' => '606f7152', 4473 - 'javelin-behavior-phabricator-search-typeahead' => '606f7152', 4474 - 'javelin-behavior-phabricator-tooltips' => '606f7152', 4475 - 'javelin-behavior-phabricator-watch-anchor' => '606f7152', 4476 - 'javelin-behavior-refresh-csrf' => '606f7152', 4479 + 'javelin-behavior-phabricator-oncopy' => '7cc3f99d', 4480 + 'javelin-behavior-phabricator-remarkup-assist' => '7cc3f99d', 4481 + 'javelin-behavior-phabricator-reveal-content' => '7cc3f99d', 4482 + 'javelin-behavior-phabricator-search-typeahead' => '7cc3f99d', 4483 + 'javelin-behavior-phabricator-tooltips' => '7cc3f99d', 4484 + 'javelin-behavior-phabricator-watch-anchor' => '7cc3f99d', 4485 + 'javelin-behavior-refresh-csrf' => '7cc3f99d', 4477 4486 'javelin-behavior-repository-crossreference' => '48040be9', 4478 - 'javelin-behavior-toggle-class' => '606f7152', 4479 - 'javelin-behavior-workflow' => '606f7152', 4487 + 'javelin-behavior-toggle-class' => '7cc3f99d', 4488 + 'javelin-behavior-workflow' => '7cc3f99d', 4480 4489 'javelin-dom' => '2dbbb7d1', 4481 4490 'javelin-event' => '2dbbb7d1', 4482 4491 'javelin-history' => '2dbbb7d1', ··· 4501 4510 'maniphest-transaction-detail-css' => '06bacb9a', 4502 4511 'phabricator-action-list-view-css' => 'e289f6ce', 4503 4512 'phabricator-application-launch-view-css' => 'e289f6ce', 4504 - 'phabricator-busy' => '606f7152', 4513 + 'phabricator-busy' => '7cc3f99d', 4505 4514 'phabricator-content-source-view-css' => 'dd27a69b', 4506 4515 'phabricator-core-css' => 'e289f6ce', 4507 4516 'phabricator-crumbs-view-css' => 'e289f6ce', 4508 4517 'phabricator-drag-and-drop-file-upload' => '48040be9', 4509 - 'phabricator-dropdown-menu' => '606f7152', 4510 - 'phabricator-file-upload' => '606f7152', 4518 + 'phabricator-dropdown-menu' => '7cc3f99d', 4519 + 'phabricator-file-upload' => '7cc3f99d', 4511 4520 'phabricator-filetree-view-css' => 'e289f6ce', 4512 4521 'phabricator-flag-css' => 'e289f6ce', 4513 4522 'phabricator-form-view-css' => 'e289f6ce', 4514 4523 'phabricator-header-view-css' => 'e289f6ce', 4515 - 'phabricator-hovercard' => '606f7152', 4524 + 'phabricator-hovercard' => '7cc3f99d', 4516 4525 'phabricator-jump-nav' => 'e289f6ce', 4517 - 'phabricator-keyboard-shortcut' => '606f7152', 4518 - 'phabricator-keyboard-shortcut-manager' => '606f7152', 4526 + 'phabricator-keyboard-shortcut' => '7cc3f99d', 4527 + 'phabricator-keyboard-shortcut-manager' => '7cc3f99d', 4519 4528 'phabricator-main-menu-view' => 'e289f6ce', 4520 - 'phabricator-menu-item' => '606f7152', 4529 + 'phabricator-menu-item' => '7cc3f99d', 4521 4530 'phabricator-nav-view-css' => 'e289f6ce', 4522 - 'phabricator-notification' => '606f7152', 4531 + 'phabricator-notification' => '7cc3f99d', 4523 4532 'phabricator-notification-css' => 'e289f6ce', 4524 4533 'phabricator-notification-menu-css' => 'e289f6ce', 4525 4534 'phabricator-object-item-list-view-css' => 'e289f6ce', 4526 4535 'phabricator-object-selector-css' => 'dd27a69b', 4527 - 'phabricator-phtize' => '606f7152', 4528 - 'phabricator-prefab' => '606f7152', 4536 + 'phabricator-phtize' => '7cc3f99d', 4537 + 'phabricator-prefab' => '7cc3f99d', 4529 4538 'phabricator-project-tag-css' => '06bacb9a', 4530 4539 'phabricator-property-list-view-css' => 'e289f6ce', 4531 4540 'phabricator-remarkup-css' => 'e289f6ce', ··· 4533 4542 'phabricator-side-menu-view-css' => 'e289f6ce', 4534 4543 'phabricator-standard-page-view' => 'e289f6ce', 4535 4544 'phabricator-tag-view-css' => 'e289f6ce', 4536 - 'phabricator-textareautils' => '606f7152', 4537 - 'phabricator-tooltip' => '606f7152', 4545 + 'phabricator-textareautils' => '7cc3f99d', 4546 + 'phabricator-tooltip' => '7cc3f99d', 4538 4547 'phabricator-transaction-view-css' => 'e289f6ce', 4539 4548 'phabricator-zindex-css' => 'e289f6ce', 4540 4549 'phui-button-css' => 'e289f6ce',
+2
src/__phutil_library_map__.php
··· 256 256 'ConpherenceListController' => 'applications/conpherence/controller/ConpherenceListController.php', 257 257 'ConpherenceMenuItemView' => 'applications/conpherence/view/ConpherenceMenuItemView.php', 258 258 'ConpherenceNewController' => 'applications/conpherence/controller/ConpherenceNewController.php', 259 + 'ConpherenceNotificationPanelController' => 'applications/conpherence/controller/ConpherenceNotificationPanelController.php', 259 260 'ConpherenceParticipant' => 'applications/conpherence/storage/ConpherenceParticipant.php', 260 261 'ConpherenceParticipantCountQuery' => 'applications/conpherence/query/ConpherenceParticipantCountQuery.php', 261 262 'ConpherenceParticipantQuery' => 'applications/conpherence/query/ConpherenceParticipantQuery.php', ··· 2274 2275 'ConpherenceListController' => 'ConpherenceController', 2275 2276 'ConpherenceMenuItemView' => 'AphrontTagView', 2276 2277 'ConpherenceNewController' => 'ConpherenceController', 2278 + 'ConpherenceNotificationPanelController' => 'ConpherenceController', 2277 2279 'ConpherenceParticipant' => 'ConpherenceDAO', 2278 2280 'ConpherenceParticipantCountQuery' => 'PhabricatorOffsetPagedQuery', 2279 2281 'ConpherenceParticipantQuery' => 'PhabricatorOffsetPagedQuery',
+1
src/applications/conpherence/application/PhabricatorApplicationConpherence.php
··· 43 43 'thread/(?P<id>[1-9]\d*)/' => 'ConpherenceListController', 44 44 '(?P<id>[1-9]\d*)/' => 'ConpherenceViewController', 45 45 'new/' => 'ConpherenceNewController', 46 + 'panel/' => 'ConpherenceNotificationPanelController', 46 47 'widget/(?P<id>[1-9]\d*)/' => 'ConpherenceWidgetController', 47 48 'update/(?P<id>[1-9]\d*)/' => 'ConpherenceUpdateController', 48 49 ),
+103
src/applications/conpherence/controller/ConpherenceNotificationPanelController.php
··· 1 + <?php 2 + 3 + /** 4 + * @group conpherence 5 + */ 6 + final class ConpherenceNotificationPanelController 7 + extends ConpherenceController { 8 + 9 + public function processRequest() { 10 + 11 + $request = $this->getRequest(); 12 + $user = $request->getUser(); 13 + $conpherences = array(); 14 + $unread_status = ConpherenceParticipationStatus::BEHIND; 15 + 16 + $participant_data = id(new ConpherenceParticipantQuery()) 17 + ->withParticipantPHIDs(array($user->getPHID())) 18 + ->setLimit(5) 19 + ->execute(); 20 + 21 + if ($participant_data) { 22 + $conpherences = id(new ConpherenceThreadQuery()) 23 + ->setViewer($user) 24 + ->withPHIDs(array_keys($participant_data)) 25 + ->needParticipantCache(true) 26 + ->execute(); 27 + } 28 + 29 + if ($conpherences) { 30 + require_celerity_resource('conpherence-notification-css'); 31 + $view = new AphrontNullView(); 32 + foreach ($conpherences as $conpherence) { 33 + $p_data = $participant_data[$conpherence->getPHID()]; 34 + $d_data = $conpherence->getDisplayData($user); 35 + $classes = array( 36 + 'phabricator-notification', 37 + 'conpherence-notification', 38 + ); 39 + 40 + if ($p_data->getParticipationStatus() == $unread_status) { 41 + $classes[] = 'phabricator-notification-unread'; 42 + } 43 + $uri = $this->getApplicationURI($conpherence->getID().'/'); 44 + $title = $d_data['title']; 45 + $subtitle = $d_data['subtitle']; 46 + $unread_count = $d_data['unread_count']; 47 + $epoch = $d_data['epoch']; 48 + $image = $d_data['image']; 49 + 50 + $msg_view = id(new ConpherenceMenuItemView()) 51 + ->setUser($user) 52 + ->setTitle($title) 53 + ->setSubtitle($subtitle) 54 + ->setHref($uri) 55 + ->setEpoch($epoch) 56 + ->setImageURI($image) 57 + ->setUnreadCount($unread_count); 58 + 59 + $view->appendChild(javelin_tag( 60 + 'div', 61 + array( 62 + 'class' => implode(' ', $classes), 63 + 'sigil' => 'notification', 64 + 'meta' => array( 65 + 'href' => $uri, 66 + ), 67 + ), 68 + $msg_view)); 69 + } 70 + $content = $view->render(); 71 + } else { 72 + $content = hsprintf( 73 + '<div class="phabricator-notification no-notifications">%s</div>', 74 + pht('You have no messages.')); 75 + } 76 + 77 + $content = hsprintf( 78 + '<div class="phabricator-notification-header">%s</div>'. 79 + '%s'. 80 + '<div class="phabricator-notification-view-all">%s</div>', 81 + pht('Messages'), 82 + $content, 83 + phutil_tag( 84 + 'a', 85 + array( 86 + 'href' => '/conpherence/', 87 + ), 88 + 'View All Conpherences')); 89 + 90 + $unread = id(new ConpherenceParticipantCountQuery()) 91 + ->withParticipantPHIDs(array($user->getPHID())) 92 + ->withParticipationStatus($unread_status) 93 + ->execute(); 94 + $unread_count = idx($unread, $user->getPHID(), 0); 95 + 96 + $json = array( 97 + 'content' => $content, 98 + 'number' => (int)$unread_count, 99 + ); 100 + 101 + return id(new AphrontAjaxResponse())->setContent($json); 102 + } 103 + }
+1 -1
src/applications/conpherence/storage/ConpherenceThread.php
··· 133 133 return $this->widgetData; 134 134 } 135 135 136 - public function getDisplayData(PhabricatorUser $user, $size) { 136 + public function getDisplayData(PhabricatorUser $user) { 137 137 $recent_phids = $this->getRecentParticipantPHIDs(); 138 138 $handles = $this->getHandles(); 139 139
+1 -1
src/applications/conpherence/view/ConpherenceThreadListView.php
··· 78 78 $user = $this->getUser(); 79 79 80 80 $uri = $this->baseURI.$thread->getID().'/'; 81 - $data = $thread->getDisplayData($user, null); 81 + $data = $thread->getDisplayData($user); 82 82 $title = $data['title']; 83 83 $subtitle = $data['subtitle']; 84 84 $unread_count = $data['unread_count'];
+30 -3
src/view/page/menu/PhabricatorMainMenuView.php
··· 45 45 $app_button = ''; 46 46 47 47 if ($user->isLoggedIn()) { 48 - list($menu, $dropdown) = $this->renderNotificationMenu(); 48 + list($menu, $dropdowns) = $this->renderNotificationMenu(); 49 49 $alerts[] = $menu; 50 - $menus[] = $dropdown; 50 + $menus = array_merge($menus, $dropdowns); 51 51 $app_button = $this->renderApplicationMenuButton($header_id); 52 52 $search_button = $this->renderSearchMenuButton($header_id); 53 53 } ··· 248 248 ); 249 249 250 250 $message_tag = ''; 251 + $message_notification_dropdown = ''; 251 252 $conpherence = 'PhabricatorApplicationConpherence'; 252 253 if (PhabricatorApplication::isClassInstalled($conpherence)) { 253 254 $message_id = celerity_generate_unique_node_id(); 254 255 $message_count_id = celerity_generate_unique_node_id(); 256 + $message_dropdown_id = celerity_generate_unique_node_id(); 255 257 256 258 $unread_status = ConpherenceParticipationStatus::BEHIND; 257 259 $unread = id(new ConpherenceParticipantCountQuery()) ··· 293 295 $message_icon_tag, 294 296 $message_count_tag, 295 297 )); 298 + 299 + Javelin::initBehavior( 300 + 'aphlict-dropdown', 301 + array( 302 + 'bubbleID' => $message_id, 303 + 'countID' => $message_count_id, 304 + 'dropdownID' => $message_dropdown_id, 305 + 'loadingText' => pht('Loading...'), 306 + 'uri' => '/conpherence/panel/', 307 + )); 308 + 309 + $message_notification_dropdown = javelin_tag( 310 + 'div', 311 + array( 312 + 'id' => $message_dropdown_id, 313 + 'class' => 'phabricator-notification-menu', 314 + 'sigil' => 'phabricator-notification-menu', 315 + 'style' => 'display: none;', 316 + ), 317 + ''); 296 318 } 297 319 298 320 $count_id = celerity_generate_unique_node_id(); ··· 341 363 'countID' => $count_id, 342 364 'dropdownID' => $dropdown_id, 343 365 'loadingText' => pht('Loading...'), 366 + 'uri' => '/notification/panel/', 344 367 )); 345 368 346 369 $notification_dropdown = javelin_tag( ··· 353 376 ), 354 377 ''); 355 378 379 + $dropdowns = array( 380 + $notification_dropdown, 381 + $message_notification_dropdown); 382 + 356 383 return array( 357 384 hsprintf('%s%s', $bubble_tag, $message_tag), 358 - $notification_dropdown, 385 + $dropdowns 359 386 ); 360 387 } 361 388
+81
webroot/rsrc/css/application/conpherence/notification.css
··· 1 + /** 2 + * @provides conpherence-notification-css 3 + */ 4 + 5 + /* kill styles on phabricator-notification */ 6 + .conpherence-notification { 7 + padding: 0; 8 + } 9 + 10 + .phabricator-notification .conpherence-menu-item-view { 11 + display: block; 12 + height: 55px; 13 + width: 100%; 14 + overflow: hidden; 15 + position: relative; 16 + text-decoration: none; 17 + border-bottom: solid 1px #E9E9E9; 18 + border-right: 0; 19 + border-left: 2px solid transparent; 20 + } 21 + 22 + .phabricator-notification .conpherence-menu-item-view 23 + .conpherence-menu-item-image { 24 + top: 6px; 25 + left: 6px; 26 + display: block; 27 + position: absolute; 28 + width: 35px; 29 + height: 35px; 30 + background-size: 35px; 31 + border: 4px solid #DEDEDE; 32 + border-radius: 3px; 33 + } 34 + 35 + .phabricator-notification .conpherence-menu-item-view 36 + .conpherence-menu-item-title { 37 + display: block; 38 + margin-top: 12px; 39 + margin-left: 58px; 40 + text-align: left; 41 + font-weight: bold; 42 + font-size: 13px; 43 + color: #333; 44 + overflow: hidden; 45 + width: 220px; 46 + text-overflow: ellipsis; 47 + } 48 + 49 + .phabricator-notification .conpherence-menu-item-view 50 + .conpherence-menu-item-subtitle { 51 + display: block; 52 + color: #a1a5a9; 53 + font-size: 11px; 54 + margin-top: 2px; 55 + margin-left: 58px; 56 + font-style: italic; 57 + } 58 + 59 + .phabricator-notification .conpherence-menu-item-view 60 + .conpherence-menu-item-unread-count { 61 + position: absolute; 62 + left: 35px; 63 + top: 3px; 64 + background: #f00; 65 + border-radius: 10px; 66 + color: white; 67 + font-weight: bold; 68 + padding: 1px 6px 2px; 69 + border: 1px solid #a00; 70 + font-size: 12px; 71 + } 72 + 73 + .phabricator-notification .conpherence-menu-item-view 74 + .conpherence-menu-item-date { 75 + position: absolute; 76 + top: 15px; 77 + right: 16px; 78 + color: #a1a5a9; 79 + font-size: 11px; 80 + } 81 +
+1 -1
webroot/rsrc/js/application/aphlict/behavior-aphlict-dropdown.js
··· 28 28 if (request) { //already fetching 29 29 return; 30 30 } 31 - request = new JX.Request('/notification/panel/', function(response) { 31 + request = new JX.Request(config.uri, function(response) { 32 32 var display = (response.number > 999) ? "\u221E" : response.number; 33 33 34 34 JX.DOM.setContent(count, display);